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>
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>
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>
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>
- 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>
6-task TDD plan covering SqlDialect abstraction, PostgreSqlService,
DAO refactoring, and config/factory integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design for integrating PostgreSQL as a third database option using
a SqlDialect abstraction layer to unify SQL dialect differences
across MySQL, SQL Server, and PostgreSQL.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix logger-performance test mock path to use bare module specifier
- Replace meaningless "should be defined" assertions in repositories test
with behavior-based tests covering upsert, batch operations, queries,
deletes, and error handling for both MaterialsToBeDeletedRepository
and DiscreteMaterialPlanRepository
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The shouldDeleteMaterial tests had a mockCleaner that reimplemented the
production logic inline, meaning bugs in the real code would never be caught.
Now uses an actual CleanerService instance instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Refactor logger.test.ts to mock logger module directly instead of winston
- Move vi.resetModules() to beforeEach to avoid module cache pollution
- Simplify mock structure to avoid conflicts with logger-performance.test.ts
- All 335 tests now pass (44 files)
Replace toBeDefined()/typeof checks with assertions that verify actual
behavior and output content. Key changes:
- locators: assert actual CSS selector values instead of existence
- logger-integration: test run()/getContext()/withRequestContext() behavior
- logger: verify winstonCalls content (level, message, metadata)
- config-manager: test default values, singleton, and getConfig() throws
- erp-auth: remove empty Class Structure block (covered by behavior tests)
- audit-logger: spy on auditLogger.info to verify JSONL entry content
- extractor: remove Math.ceil tests, verify error result structure
Net: -209 lines of hollow/redundant test code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The vi.mock('fs') factory returned { default: { ... } } causing fs.mkdirSync
to be undefined at runtime. Add top-level exports alongside default for ESM/CJS interop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
eliminate any usage across TypeORM/Database mock types
Replaced 23 any in types.ts and 5 any in index.ts with
typed alternatives:
- MockDataSource/MockRepository: generics + Record<string, unknown>
- MockQueryBuilder: Record<string, unknown>
- MockDatabaseService: unknown[]
- createMockAxios: removed as any cast
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace 4x expect(true).toBe(true) in audit-logger.test.ts with
applyAuditConfig() + app.getVersion call count assertions
- Replace if(!hasCredentials){return} pattern with it.skipIf() in
3 integration test files (cleaner, erp-auth, extractor) so Vitest
correctly reports 12 tests as "skipped" instead of "passed"
- Remove placeholder assertion from skipped update-service test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add detailed step-by-step logging in navigation phase with elapsed time tracking
- Enhance query interface setup with individual step logging and timing
- Improve order query and result collection with validation logging
- Add comprehensive processDetailPage logging with 8 tracked steps
- Detail material processing loop with decision tracking (delete/skip reasons)
- Enhance retry mechanism with per-attempt logging and success rate tracking
- Add performance monitoring with slow operation detection (isSlow flags)
- All logs use consistent Chinese labeling with [Phase] prefix format
Total: +437 lines of logging instrumentation across cleaner.ts
Add getLocalIpAddress() that reliably resolves the primary LAN IPv4
address by collecting all non-loopback, non-APIPA addresses and
prioritizing RFC 1918 private ranges (192.168.x.x, 10.x.x.x,
172.16-31.x.x) over public IPs. Falls back to any non-internal
address or 'N/A'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Winston's default npm levels assign debug=5 and verbose=4, so setting
level to 'verbose' (threshold 4) filtered out debug (5 > 4). Register
PROJECT_LEVELS { error:0, warn:1, info:2, debug:3, verbose:4 } so
Winston's <= threshold filter aligns with the project's intended
semantics where verbose is the most detailed level.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add React ErrorBoundary component that captures rendering errors with
full component stack and logs them to main process via IPC. Wrap all
three App branches (PlaywrightDownload, UnauthenticatedApp,
AuthenticatedApp) with scoped boundaries.
Replace 13 console.* calls across renderer with structured logger:
- useDialogFocus: 10 calls (focus management diagnostics)
- PlaywrightDownloadDialog: 1 call (download cancellation error)
- useReportData: 1 call (report fetch failure)
- parser: 1 call (execution time extraction warning)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Seq centralized logging transport with async ESM import
- Add appVersion and computerName to logger defaultMeta (all app logs)
- Add appVersion to audit log entries for version-level traceability
- Improve unhandledRejection to capture full stack traces for Error instances
- Add Seq config schema and template configuration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enhance ERP automation error diagnostics by capturing PNG screenshots
on every error and forwarding browser console warnings/errors to the
structured logger. Includes automatic cleanup of old screenshots
aligned with the configured log retention period.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ~45 structured log calls across extractor-core, cleaner, and erp-auth
to cover all automation steps (navigation, query, download, material processing).
Enhance capturePageContext with a step parameter for precise failure localization,
and fix missing capturePageContext calls in error handlers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace console.error with structured useLogger calls in 5 key renderer
files (Cleaner, LoginDialog, Extractor, OperationHistory, MaterialType)
to enable persistent log capture for frontend error diagnosis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Eliminate console.* remnants in bootstrap, session-manager, migrations, and app entry
so startup and login failures are captured in log files. Add log.error before all 14
throw sites in ERP services (auth, extractor, cleaner, browser manager) to ensure
critical automation failures are traceable. Introduce capturePageContext utility for
defensive Playwright page state capture during error logging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add createLogger/trackDuration logging to mysql.ts, sql-server.ts, and
data-source.ts — the only database layer files without observability.
Connect/disconnect, query execution (with duration tracking), and
transaction lifecycle events are now logged. Passwords and parameter
values are excluded; SQL statements are capped at 100 chars.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously getLogDir() only checked app.isReady(), which caused
development builds to write logs to the user data directory instead
of the local project logs/ folder. Now uses app.isPackaged to
correctly distinguish production from development environments.
Also adds comprehensive logging system documentation and a debug
utility for verifying Electron environment detection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add headless field to extraction config schema (default: true).
Extractor handler now reads globalConfig.extraction.headless instead
of hardcoding true. Users can set headless: false in config.yaml
to show the browser window during extraction for debugging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove misleading await from audit-logger tests (functions are sync)
- Add cleanup() to LoggerAPI type definition in index.d.ts
- Fix circular reference fallback to preserve null values
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make logAudit and closeAuditLogger synchronous (were async for no reason)
- Set audit-logger silent:true initially, enable on applyAuditConfig()
- Add try-catch for circular references in consoleFormat meta JSON
- Update all callers to remove unnecessary await/.catch() on sync functions
- Add comment to shared.ts explaining acceptable sync FS usage
- Fix audit-logger test for sync closeAuditLogger
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add LOGGER_LEVEL_CHANGED IPC channel for broadcasting level changes
- setLogLevel() now notifies all BrowserWindows when level changes
- Add verbose case in IPC forwardToWinston (was falling through to info)
- Renderer logger API listens for level changes and updates cached level
- Add cleanup() method to remove level change listener
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cache isProduction() result at module load to avoid repeated property
lookups. Add isSerializedError() check in format functions to skip
re-serialization when error objects have already been processed by
logError/formatErrorForLogging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move logger close from before-quit to will-quit to keep the logger available
for uncaughtException handlers that may fire during shutdown. Remove 4
redundant console.error calls that duplicate Winston logger output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Extract shared module: consolidate getLogDir() and isProduction()
into shared.ts, eliminate duplication across logger modules
2. Make retention config effective: delay file transport creation
until config is loaded, apply appRetention/auditRetention from config.yaml
3. Add before-quit log flush: close logger and audit logger on
app exit to prevent log loss
4. Unify logError entry point: remove duplicate logError from index.ts,
re-export from error-utils.ts with richer error context
5. Renderer log level filtering: add client-side level check in preload
to skip IPC for filtered-out messages
6. Child logger cache + audit cleanup: cache child loggers in IPC
handler for performance, remove redundant timestamp format in audit logger
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>