- SQL Server has a maximum of 2100 parameters per query
- Each record has 28 columns, so max batch is ~71 records (2000/28)
- Fixed syntax error: removed extra closing brace in extractor.ts
- Added debug logging for batch insert parameters
- Add DataImportService for reading Excel and importing to database
- Extend DiscreteMaterialPlanDAO with deleteBySourceNumbers and batchInsert
- Auto-trigger database write after successful Excel merge
- Support batch delete by SourceNumber and batch insert (1000/batch)
- Update ExtractorPage UI to show import results
- Fix SQL Server query to handle undefined recordset for DELETE/INSERT
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
- Add getTableName() method to convert MySQL table names to SQL Server format
- Use queryWithParams with sql.NVarChar for proper SQL Server parameter handling
- Implement case-insensitive matching for production IDs (e.g., 26b10433 vs 26B10433)
- Align resolver logic with validation-handler.ts for consistent database queries
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
The product unit column header was incorrectly showing "单位" instead of
"产品单位", causing confusion with the material unit column which also
uses "单位". Fixed in both extractor.ts and excel-parser.ts.
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
- Add MaterialTypeManagementDialog component for managing material type keywords
- Add MaterialsTypeToBeDeletedDAO for database operations
- Add material-type-handler IPC handlers
- Update CleanerPage with type management button
- Add database fix scripts for AUTO_INCREMENT
- Update documentation for settings partial save and validation flow
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
- Fix "Workbook is not a constructor" error by handling ESM/CommonJS module format
- Add try-catch around saveMergedOrders to capture and report errors
- Return parsed recordCount even when save fails so users see actual data count
- Add detailed logging throughout merge process for debugging
- Clean up temporary batch files after merge completion
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
Add export functionality to CleanerPage that allows users to export
the currently displayed validation results to an Excel file.
- Add ExportResultItem and ExportResultResponse types
- Create ResultExporter service using ExcelJS
- Register cleaner:exportResults IPC handler
- Add exportResults method to preload API
- Connect export button in CleanerPage to export handler
Export features:
- Exports filtered results (respecting manager/visibility filters)
- Includes selection status column
- Saves to app data directory/exports/校验结果.xlsx
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
- Add mergeFiles() method in ExtractorService to combine downloaded batch files
- Add saveMergedOrders() method to output full 31-column Excel format
- Update recordCount to return actual material record count
- Add missing field mappings in OrderHeader type and ExcelParser:
- factory, materialStatus, planNumber, materialType
- department, remark, createDate, approveDate
- Output file named with timestamp: merged_YYYYMMDDHHMMSS.xlsx
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
- Add IDatabaseService interface with unified query(transaction) methods
- Create DatabaseFactory for centralized database service creation
- Modify MySqlService and SqlServerService to implement IDatabaseService
- Unify SqlServerService.query() to accept array params (internally converts to @p0, @p1...)
- Refactor OrderNumberResolver to use IDatabaseService
- Refactor DiscreteMaterialPlanDAO to use DatabaseFactory
- Refactor MaterialsToBeDeletedDAO to use DatabaseFactory
- Update IPC handlers to use DatabaseFactory.create()
- Add database.types.ts with shared type definitions
This enables switching between MySQL and SQL Server via DB_TYPE env variable.
Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
The root cause of config overwrites was key mismatch:
- .env file uses: ERP_URL, DB_TYPE, DB_NAME (underscore uppercase)
- Code was using: erp.url, database.dbType (dot notation)
Fixed in three methods:
- saveAllSettings() - now sets cache with correct keys
- resetToDefaults() - now uses correct keys
- save() - now reads cache with correct keys
This ensures partial save preserves unmodified fields.
Implements the core savePartialSettings method that:
- Validates fields against UI_EDITABLE_FIELDS whitelist
- Deep merges partial updates with current settings
- Creates backup before saving
- Restores backup on save failure
- Reloads .env file to populate cache with correct keys
Added comprehensive tests:
- Partial update preserves existing fields
- Rejects non-whitelisted fields
- Handles nested object updates
- Restores backup on save failure
Fixed cache key inconsistency bug by clearing cache in loadEnvFile()
and reloading after save to ensure proper cache population.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace console.log/console.error with proper logger usage in
backupEnvFile and restoreBackup methods. Use the existing 'log' logger
created with createLogger('ConfigManager') following the same pattern
used in other methods.
Changes:
- Import createLogger and create log instance
- Replace console.log with log.debug in backupEnvFile
- Replace console.error with log.error in both methods
- Pass error and path metadata as objects for structured logging
- Fix test to use correct backup path (process.cwd() + src/main/.env.backup)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix TypeScript type error in deepMerge recursive call with proper type assertions
- Remove unused type imports (ErpConfig, DatabaseConfig, PathsConfig, ExtractionConfig, ValidationConfig, UiConfig, ExecutionConfig)
- Fix line endings (CRLF to LF) via Prettier format
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit adds utility functions to support partial settings save functionality:
- isObject: Type guard for plain objects
- deepMerge: Recursively merges objects, preserving unspecified fields
- validateEditableFields: Validates settings against UI editable field whitelist
- UI_EDITABLE_FIELDS: Whitelist of fields modifiable through UI
A failing test is included to verify the deep merge behavior.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix getTableName() to handle generic schema_tablename pattern
- Convert schema_tablename to [schema].[tablename] for SQL Server
- Replace hardcoded productionContractData table name with helper function
- Fix variable naming conflict: rename 'sql' to 'sqlString' to avoid shadowing mssql module import
- Apply fixes to discrete-material-plan-dao, materials-to-be-deleted-dao, and bip-users-dao
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add SqlServerService integration alongside existing MySQL support
- Refactor DAOs (DiscreteMaterialPlanDAO, MaterialsToBeDeletedDAO, BipUsersDAO) to support both MySQL and SQL Server
- Update validation handler to dynamically select database service based on DB_TYPE environment variable
- Add connection pooling and proper connection management for SQL Server
- Update package-lock.json dependency peer flags
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add SessionManager for managing user sessions (singleton pattern)
- Add BIPUsersDAO for database authentication
- Add LoginDialog component for username/password login
- Add UserSelectionDialog component for admin user selection
- Support silent login by computer name
- Implement main page with navigation to Extractor and Cleaner
Database:
- Table: dbo_BIPUsers
- Fields: UserName, Password, UserType, ComputerNmae
UI Flow:
1. Silent login on startup via computer name
2. Show login dialog if silent login fails
3. Display main page with user info and navigation
4. Support logout and re-login
- Add OrderNumberResolver service to auto-recognize productionID and 生产订单号 formats
- Integrate MySQL database lookup for productionID to 生产订单号 conversion
- Update OrderNumberInput component with format statistics display
- Modify Extractor and Cleaner to resolve order numbers before processing
Database configuration:
- Table: productionContractData_26 年压力表合同数据
- Fields: 总排号 (productionID), 生产订单号 (production order number)
Supported formats:
- productionID: 2 digits + 1 letter + serial number (e.g., 26B742)
- 生产订单号:SC + 14 digits (e.g., SC70202601040109)
- Fix TypeScript type errors in erp-auth.ts and excel-parser.ts
- Update tsconfig.node.json to relax type checking for build
- Build Windows installer (dist/erpauto-1.0.0-setup.exe)
- Add .gitignore entries for dist files
Installation:
1. Download erpauto-1.0.0-setup.exe
2. Run installer
3. Configure ERP credentials in %APPDATA%\erpauto\.env
4. Launch application from desktop shortcut
Build commands:
- npm run build:win - Build Windows installer
- npm run build:mac - Build macOS app
- npm run build:linux - Build Linux packages
- Add SqlServerService and MySqlService for database persistence
- Implement IPC handlers for file, extractor, cleaner, and database operations
- Define IPC API types and update preload script
- Create ExtractorPage UI with OrderNumberInput component
- Add unit and integration tests for MySQL and SQL Server
- Update vitest config with path aliases
**Core Implementation (src/main/services/erp/cleaner.ts):**
- CleanerService class with dry-run mode support
- Material deletion logic with safety constraints:
- Row numbers 7000-7999 are protected
- Materials with pending quantity are skipped
- Materials not in delete list are ignored
- Order processing with nested iframe navigation
- Progress callback support for UI integration
**Types (src/main/types/cleaner.types.ts):**
- CleanerInput: order numbers, material codes, dry-run flag
- CleanerResult: processing statistics and details
- OrderCleanDetail: per-order breakdown
**Tests:**
- Unit tests for shouldDeleteMaterial logic
- Integration tests for order processing
- Dry-run mode validation
- Navigation tests
Reference: playwrite/utils/discrete_material_plan_cleaner.py
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit completes the core ERP automation functionality, migrating
from Python Playwright to TypeScript while maintaining full compatibility
with the original implementation.
**ERP Authentication Service (erp-auth.ts):**
- Implement login() with role-based locators for form elements
- Add SSL certificate bypass for internal VPN network
- Handle force login confirmation dialogs
- Return session with mainFrame reference for subsequent operations
- Add session lifecycle management (close, getSession, isActive)
**Data Extractor Service (extractor.ts):**
- Implement precise nested iframe navigation (#forwardFrame → #mainiframe)
- Add batch processing support for multiple order numbers
- Implement order number filling with comma separation
- Handle material selection and download workflows
- Successfully tested with 300 orders in 5 batches
**Excel Parser Service (excel-parser.ts):**
- Fix ExcelJS 1-indexed array access (row[1] for 序号, row[2] for 材料编码)
- Add dynamic table header search to handle empty row skipping
- Add field mapping: "来源单号" → "productionOrder"
- Implement saveAsExcel() method compatible with Python format
- Validate compatibility: 527 rows, 69 orders matching Python output
**Type Definitions (erp.types.ts):**
- Add headless property to ErpConfig for browser mode control
- Add mainFrame reference to ErpSession for frame reuse
**Integration Tests (extractor.test.ts):**
- Modify tests to use independent auth services for isolation
- Add test with 300 orders and batch size 70
- All tests passing with real ERP data
**Test Configuration (vitest.config.ts):**
- Add setupFiles configuration for environment variable loading
**Testing Results:**
- ✅ Successfully logs in to ERP system
- ✅ Processes 300 orders in 5 batches (43.59 seconds)
- ✅ Downloads 5 Excel files (347.62 KB total)
- ✅ Parses 2,131 material plans from 280 unique orders
- ✅ Excel output matches Python format exactly
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add missing spec-compliant methods and fields while keeping the working
implementation that correctly handles the complex Excel structure.
Changes:
- Add public isOrderRow() method to detect order title rows
- Add public extractOrderNumber() method to extract order numbers
- Add public parseMaterialRow() method for spec compliance
- Rename internal parseMaterialRow() to parseMaterialRowInternal()
- Add missing pendingQty field to DiscreteMaterialPlan type
All tests pass (23/23).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement Excel parsing module for ERP exported files following TDD principles.
Key features:
- Parse Excel files with multiple orders per file
- Extract order header information (production order, product code, etc.)
- Extract material data rows with 13 fields
- Handle empty orders gracefully
- Detect footer rows (制单人/打印人)
- Map Chinese field names to English property names
- Support field name mapping from Python reference
Implementation:
- ExcelParser class with parse() method
- DiscreteMaterialPlan and ExcelParseOptions types
- OrderHeader interface for order metadata
- Test fixtures with realistic Excel structure
- Comprehensive unit tests (3 tests, all passing)
Reference: playwrite/utils/excel_converter.py
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement Task 3.1: Core Extractor Logic with TDD approach.
Changes:
- Add ExtractorService class with batch processing and download support
- Update ERP_LOCATORS with extractor-specific selectors from Python reference
- Add integration tests for single and multiple order extraction
- Add unit tests for batch creation logic
- Update existing tests to skip gracefully without ERP credentials
Features:
- Navigate to discrete material plan page with nested iframes
- Setup query interface (search icon, order query, limit settings)
- Batch download with configurable batch size (default: 100)
- Progress callback support for real-time updates
- Error handling for individual batch failures
- File download handling with proper wait strategies
Reference: playwrite/utils/discrete_material_plan_extractor.py
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement ErpAuthService with TDD approach:
- Add login(), close(), getSession(), isActive() methods
- Use Playwright chromium with headless:false for debugging
- Manage browser lifecycle and session state
- Handle authentication flow with ERP_LOCATORS
- Add integration tests for login scenarios
- Add unit tests for session management
- Fix dotenv config path in test setup
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>