Commit Graph

350 Commits

Author SHA1 Message Date
Misaka_Company
116539ff42 feat(cleaner): record all material operations in database, including successful deletions
Previously only skipped and failed materials were persisted. Now every
material (deleted, uncertain, skipped, failed) is recorded in
CleanerMaterialDetail for full audit traceability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 14:24:18 +08:00
Misaka_Company
0286df94dd fix(cleaner): cast BIT to INT for MAX() in getBatches query
SQL Server does not support MAX() on BIT columns, causing the
getBatches query to fail silently and return empty results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 14:17:26 +08:00
Misaka_Company
32931cecad style: format changed files with prettier
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:35:31 +08:00
Misaka_Company
b95f12fca1 chore(cleaner): clean up legacy report viewer references
Remove ReportViewerDialog and ReportAnalysisDialog lazy imports, state
variables, Suspense wrappers, and the "查看报告" toolbar button. These
components were for the old Markdown file-based report viewer which has
been replaced by database-backed operation history.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:30:10 +08:00
Misaka_Company
4c40457c71 feat(cleaner): add operation history modal with database-backed records
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:23:57 +08:00
Misaka_Company
bd68444a74 feat(cleaner): add renderer types for cleaner operation history
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:09:47 +08:00
Misaka_Company
7dfa88c2a3 refactor(cleaner): remove Markdown report generator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:06:19 +08:00
Misaka_Company
998edb4b84 refactor(cleaner): replace report generation with database persistence
Remove generateExecutionId(), generateAndUploadReport(), and all
executionId references from CleanerApplicationService. The service
now accepts batchId, historyDao, and appVersion from the IPC handler
and writes execution/order/material records to the database via
CleanerOperationHistoryDAO instead of generating Markdown reports.

All execution paths (success, failure, outer retry, retry-login-failure)
persist their results to the database with appropriate status tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:02:43 +08:00
Misaka_Company
74096fbfa0 feat(cleaner): add preload API for cleaner operation history
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:52:14 +08:00
Misaka_Company
73656dada8 feat(cleaner): add IPC handlers for cleaner operation history
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:38:54 +08:00
Misaka_Company
9a91658121 feat(cleaner): add IPC channels for cleaner operation history
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:33:16 +08:00
Misaka_Company
a924e8a4e8 feat(cleaner): add CleanerOperationHistoryDAO for three-table persistence
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:29:54 +08:00
Misaka_Company
b363a53d8a feat(cleaner): add type definitions for cleaner operation history
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:18:56 +08:00
Misaka_Company
e1d55b8b39 feat(cleaner): add outer-level retry on fatal crash with execution ID
When CleanerService hits a fatal error (browser crash, timeout), the
outer catch now sets result.crashed=true. CleanerApplicationService
detects this, closes the dead browser session, re-logs into ERP, and
re-runs all orders once. An execution ID (CLN-yyyyMMddHHmmss-XXXX)
generated at startup ensures report files are deduplicated across
retries. Reports now display execution ID and app version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 10:07:29 +08:00
Misaka
8b173890fa feat(cleaner): add multi-signal deletion verification with material-level retry
Replace fragile single-signal (row change only) deletion verification
with a robust multi-signal approach using row change + material count +
ERP message detection. Add material-level retry (up to 3 attempts) for
transient failures, with detailed tracking of failed/uncertain deletions.

- Add DeletionOutcome/DeletionErrorCategory enums and FailedMaterial type
- Add deleteWithVerification() core method with retry logic
- Add evaluateDeletionSignals() pure logic (unit tested, 9 cases)
- Add helper methods: readMaterialCount, checkErpMessages, handleConfirmDialog
- Extend CleanerResult/OrderCleanDetail with failed/uncertain tracking
- Update report generator with failed materials detail section
- Update ExecutionReportDialog to display failed/uncertain stats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 21:55:47 +08:00
Misaka_Company
b065e23306 1.11.1 v1.11.1 2026-04-07 08:53:22 +08:00
Misaka_Company
1c0a000a67 fix(preload): add missing selectedManagers param to getCleanerData type declaration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 08:52:58 +08:00
Misaka
6b3c62268a 1.11.0 2026-04-06 19:22:32 +08:00
Misaka
bb86208d32 docs: add release notes for version 1.11.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 19:22:20 +08:00
Misaka
3be7959067 feat(cleaner): support selectedManagers filtering for admin cleaner execution
Admin can now pass selectedManagers to getCleanerData so material codes
are queried from MaterialsToBeDeleted by ManagerName IN (selectedManagers).
When no managers are selected, fallback to DiscreteMaterialPlanData by
orderNumbers. User behavior is unchanged. Includes updated tests and
role-based flow documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 19:20:22 +08:00
Misaka
91f29a1167 refactor(audit): unify computerName source to cached os.hostname()
Export cachedHostname from audit-logger and use it in process-guards,
replacing process.env.COMPUTERNAME so all audit entries use the same value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 17:41:36 +08:00
Misaka
abad61758c refactor(audit): type-safe enums, expanded coverage, and crash-safe logging
Replace magic strings with AuditAction/AuditStatus enums across all consumers,
add logAuditWithCurrentUser() convenience wrapper, extend audit coverage to
data import, result export, app update, and ERP credentials operations, and
harden crash handlers with try/catch to prevent audit failures from cascading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 17:40:30 +08:00
Misaka
d0c745e243 refactor(test): migrate e2e to Playwright and remove duplicate unit tests
Switch extractor-workflow e2e test from vitest to Playwright test runner
for consistency with playwright.config.ts. Remove redundant unit tests
(cleaner, erp-auth, extractor) that have been superseded by more thorough
replacements under tests/unit/services/erp/. Enable test isolation
unconditionally to prevent cross-file state pollution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 11:55:58 +08:00
Misaka
fe6cdbf076 fix(test): add mock-driver tests for database services
- Add connected-path tests for mysql, sql-server, and postgresql using
  mocked drivers (mysql2/promise, mssql, pg) covering
  connect, query, transaction, and disconnect scenarios
- Fix tautological assertion in auth-flow.test.ts (hasError >= 0 was always true)
- Add tests/integration to vitest exclude list to prevent
  module cache pollution under isolate:false
- Set isolate to true for CI, false for local dev (was: isolate false)
2026-04-06 11:11:04 +08:00
Misaka
188117e5ce refactor(test): replace module-level mutable state with vi.fn() mocks
Replace fragile module-level let variables and SQL string parsing
with vi.hoisted() mock functions that are reset and configured
per-test in beforeEach via mockResolvedValue/mockResolvedValueOnce.

- Remove 8 module-level mutable state variables
- Remove matchQuery() SQL parser
- Use vi.hoisted() for shared mock functions across vi.mock() factories
- Each test explicitly controls mock return values with mockResolvedValueOnce
- Fix getCleanerData error test to use direct mock instead of dynamic import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 09:21:04 +08:00
Misaka
0560b3c84a style: apply prettier formatting to test files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 09:03:16 +08:00
Misaka
fb3bdbc493 test: fix mock configuration and lint errors in unit tests
- Fix logger mock missing default export in extractor.test.ts
- Fix performance-monitor mock configuration
- Fix prefer-const in validation-database.test.ts
- Fix no-unsafe-function-type in cleaner-handler.test.ts
- Fix no-empty-function in cleaner-application-service.test.ts
- Run prettier format on test files

All 622 tests now passing (59 files, 3 skipped)
2026-04-05 22:04:32 +08:00
Misaka
c6f67e49a4 1.10.0 2026-04-05 21:41:08 +08:00
Misaka
d16f2d1af0 docs: add release notes for version 1.10.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 21:40:55 +08:00
Misaka
4150a13175 fix(test): improve test isolation and reduce noise in unit tests
- Add logger/error-utils mocks to cleaner-handler test to suppress IPC error log noise
- Move setupServiceMocks into beforeEach for consistent default mocking in cleaner tests
- Replace vi.waitFor (2s timeout) with setImmediate microtask flush in extractor test
- Remove dead activeType assignments in validation-database test
- Align TestUser.id type with UserInfo.id (string → number) and use deterministic counter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 21:38:20 +08:00
Misaka
d0f8ad0fef test(erp): add unit tests for ERP services and test coverage docs
Add unit tests for core ERP service modules including ErpBrowserManager,
cleaner, erp-auth, extractor-core, extractor, and order-resolver. Also
includes test coverage improvement plan and quality review report.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 17:23:00 +08:00
Misaka
4a7c220baa fix(extractor): resolve SQL syntax error from double-quoted table names 2026-04-05 13:51:18 +08:00
Misaka
f51cae0f6f fix(db): complete PostgreSQL integration in validation and cleaner services
OrderNumberResolver, validation, and cleaner services had incomplete
PostgreSQL support - they only handled SQL Server and MySQL, causing
PostgreSQL to fall through to MySQL code paths with invalid syntax
(backticks, ? placeholders) and missing schema.table name splitting.

Changes:
- Add PostgreSQL SQL generation ($N params, double-quoted identifiers)
  in OrderNumberResolver, validation-application-service,
  production-input-service, and validation-database
- Add PostgreSQL to database factory functions in validation-database
  and cleaner-application-service
- Add UPPER, LOWER, and 40+ common SQL functions to SQL_KEYWORDS to
  prevent prepareSql() from quoting them as identifiers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 13:46:37 +08:00
Misaka
7601b5f176 fix(db): PostgreSQL P0 fixes - SQL_KEYWORDS expansion, timeout config, and tests
- Expand SQL_KEYWORDS from ~120 to 226+ words covering:
  - Window functions (ROW_NUMBER, RANK, LAG, LEAD, etc.)
  - CTEs (WITH, RECURSIVE, MATERIALIZED, etc.)
  - Advanced grouping (ROLLUP, CUBE, GROUPING SETS)
  - JSON operations, types, table sampling
  - Transaction control and other PostgreSQL-specific keywords
- Add connection pool timeout configuration:
  - connectionTimeoutMillis: 10s
  - statement_timeout: 30s (PostgreSQL level)
  - idleTimeoutMillis: 30s (connection cleanup)
  - query_timeout: 60s (driver-level fallback)
- Add 12 comprehensive edge case tests covering:
  - Window functions, CTEs, advanced grouping
  - CASE expressions, set operations, JSON operators
- All 38 tests pass

Production-ready: prevents hung queries and supports complex SQL.
2026-04-05 13:09:01 +08:00
Misaka
e2669af870 fix: remove unused imports and fix logger test isolation
- Remove unused imports (run, trackDuration, PerformanceTracker,
  ConfigManager, disconnectDb) flagged by ESLint
- Remove unused isSlow variable in performance-monitor catch block
- Add eslint-disable for require() in Playwright JS script
- Fix logger-performance test flakiness by using vi.resetModules()
  with dynamic imports to prevent cached logger references across
  test files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 12:15:18 +08:00
Misaka
e54d94fce2 style: apply formatter to docs, types, and test files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 11:56:22 +08:00
Misaka
9791a84047 fix(db): auto-quote SQL identifiers for PostgreSQL case-sensitivity
Add prepareSql() to PostgreSqlService that quotes unquoted column names
before execution. PostgreSQL lowercases unquoted identifiers, but
SSMA-migrated tables have uppercase column names requiring double-quoting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 11:54:30 +08:00
Misaka
b5ba18b595 refactor(db): migrate BIPUsersDAO to use DatabaseFactory and SqlDialect
Replace hardcoded MySqlService/SqlServerService with DatabaseFactory,
enabling PostgreSQL support for user authentication and management.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 11:20:17 +08:00
Misaka
13fb7bcf46 style: fix lint errors in dialect files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:37:32 +08:00
Misaka
0ca17a1807 fix(db): correct dialect import paths and extend bip-users-dao type
- Fix dialect files to use relative paths instead of @types alias
- Add 'postgresql' to BIPUsersDAO dbType union

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:34:03 +08:00
Misaka
54a3ac680a feat(db): integrate PostgreSQL into factory, config, and TypeORM data source
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:29:57 +08:00
Misaka
16b2882729 style: fix extra blank line after formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:26:29 +08:00
Misaka
e97ec63433 refactor(db): use SqlDialect in ExtractorOperationHistoryDAO
Replace all isSqlServer checks, buildPlaceholders, and hardcoded table names
with the SqlDialect abstraction. The dialect now handles parameter placeholders,
table name quoting, current timestamp functions, and pagination across all
supported database types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:25:38 +08:00
Misaka
9556891dea refactor(db): use SqlDialect in MaterialsTypeToBeDeletedDAO
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:20:04 +08:00
Misaka
fa57f9e564 refactor(db): use SqlDialect in MaterialsToBeDeletedDAO
Replace all isSqlServer/if-else branches with SqlDialect calls:
- Table name via dialect.quoteTableName()
- Placeholders via dialect.param() and dialect.params()
- UPSERT via dialect.upsert() in upsertMaterial(), upsertBatch(), updateManager()
- Remove buildPlaceholders(), TABLE_NAME_SQLSERVER, TABLE_NAME_MYSQL
- Re-export SqlDialect type from dialects barrel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:17:21 +08:00
Misaka
9300f3455f refactor(db): use SqlDialect in DiscreteMaterialPlanDAO
Replace all manual isSqlServer checks and inline SQL dialect logic with the
SqlDialect abstraction. Removes buildPlaceholders(), TABLE_NAME_SQLSERVER,
and TABLE_NAME_MYSQL in favor of dialect.params(), dialect.param(), and
dialect.quoteTableName(). Batch size logic now uses dialect.maxBatchRows().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:10:54 +08:00
Misaka
7e521da3f1 feat(db): add PostgreSqlService with pg driver
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:04:48 +08:00
Misaka
130e0602d1 feat(db): implement SqlDialect with MySQL, SQL Server, PostgreSQL dialects
Add three SqlDialect implementations with a factory function:
- MySqlDialect: positional ?, ON DUPLICATE KEY UPDATE, LIMIT/OFFSET
- SqlServerDialect: @pN params, MERGE USING, OFFSET/FETCH
- PostgreSqlDialect: $N (1-based), ON CONFLICT DO UPDATE, LIMIT/OFFSET

TDD approach: 43 tests written first, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 10:01:24 +08:00
Misaka
0956bf907f feat(db): add SqlDialect interface and PostgreSQL type definitions
- Add 'postgresql' to DatabaseType union in database.types.ts
- Add PostgreSqlConfig interface extending DatabaseConfig
- Add postgresqlConfigSchema Zod schema with host, port, database,
  username, password, and maxPoolSize fields
- Add 'postgresql' to databaseConfigSchema and type exports
- Create SqlDialect interface with methods for quoteTableName,
  param, params, currentTimestamp, upsert, paginate, maxBatchRows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 09:19:49 +08:00
Misaka
6c730616b8 docs: add PostgreSQL integration implementation plan
6-task TDD plan covering SqlDialect abstraction, PostgreSqlService,
DAO refactoring, and config/factory integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 09:14:33 +08:00