Drop the Excel (.xlsm) production-execution-card pipeline now that the project only synchronizes Access databases to SQL Server. - Delete excel_sync_to_sql.py, migration.py, config/field_mappings.py - Remove Excel-only config symbols (EXCEL_CONFIGS, MIGRATION_TASKS, EXECUTION_CARD_FIELDS, CONTRACT_DATA_*, CACHE_DIR, TEMP_DIR, EXCEL_SYNC_* settings) from the config package - Drop now-unused deps from requirements.txt: pandas, sqlalchemy, openpyxl - Update .env.example, CLAUDE.md, and the uptime_kuma_utils docstring - Fix the tube-bending workshop Access table mapping in SYNC_MAPPING (source table renamed; old name no longer exists) The three Excel-sourced tables in warehouseOutbound (executionCardData, contractData, customerProductType) and their data are left untouched. Co-Authored-By: Claude <noreply@anthropic.com>
180 lines
8.3 KiB
Markdown
180 lines
8.3 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
This is a data synchronization system (BLD_sync) that extracts data from:
|
|
- **Microsoft Access databases** (.accdb) located on network shares
|
|
|
|
And synchronizes it to:
|
|
- **Microsoft SQL Server** (CompanyDB) with multiple schemas organized by data type
|
|
|
|
The system supports both full initialization sync and incremental sync driven by a change log table.
|
|
|
|
## Architecture
|
|
|
|
### Data Flow
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ Network File Sources │
|
|
│ Access DBs (\\192.168.110.114\生产进度表\) │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ Sync Scripts │
|
|
│ • run_incremental_sync.py - Change log driven incremental sync │
|
|
│ • init_full_sync.py - Full table truncation/reload │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ SQL Server (CompanyDB) │
|
|
│ Schemas: productionContractData, productWarehousing, │
|
|
│ workshopOne/Two/Three, machining, contractPlanning, │
|
|
│ inspectionRecords, partsWarehouse, etc. │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
> Note: The system previously also synced Excel `.xlsm` production-execution-card files into
|
|
> the `warehouseOutbound` schema (`executionCardData`, `contractData`, `customerProductType`).
|
|
> That Excel pipeline has been removed; the existing tables and their data remain in CompanyDB
|
|
> but are no longer updated.
|
|
|
|
### Key Components
|
|
|
|
**run_incremental_sync.py** - Log-driven incremental sync
|
|
- Polls `TableChangeLog` table for unsynced records (`Synced=0`)
|
|
- Queries by `TableAddress` to match configured Access file paths
|
|
- Connects to the source Access DB, reads latest rows by primary key, then DELETE + INSERT
|
|
- Per-batch verification (delete/insert checks by primary key) before marking `Synced=1`
|
|
- Long-running service with configurable polling interval
|
|
|
|
**init_full_sync.py** - Full table reload
|
|
- Truncates target tables and reloads all data from Access
|
|
- Handles IDENTITY_INSERT ON/OFF for tables with identity columns
|
|
- Progress logging with row counts and throughput metrics
|
|
|
|
**config/** - Configuration package
|
|
- `database.py`: SQL Server / Access driver settings (read from env via `python-dotenv`)
|
|
- `file_sources.py`: `SYNC_MAPPING` — nested dict mapping Access files → tables → SQL targets
|
|
- `app_settings.py`: `LOG_TABLE_CONFIG`, `NTFY_CONFIG`, `UPTIME_KUMA_CONFIG`, `POLL_INTERVAL`, `BATCH_SIZE`
|
|
- Symbols are re-exported from `config/__init__.py` (e.g. `from config import SYNC_MAPPING`)
|
|
|
|
**db_utils.py** - Database connection utilities
|
|
- `get_sql_conn()`: SQL Server connection via pyodbc
|
|
- `get_access_conn()`: Access database connection
|
|
- `fmt_table()`: Safe table name formatting `[schema].[table]`
|
|
- `generate_insert_sql()`: Dynamic INSERT statement generation
|
|
- `create_table_from_access()`: Auto-create SQL Server table from Access `cursor.description`
|
|
|
|
**ntfy_utils.py** - Push notifications
|
|
- Sends alerts to ntfy server on errors/completion
|
|
- Uses Bearer token authentication
|
|
|
|
**uptime_kuma_utils.py** - Heartbeat monitoring
|
|
- `UptimeKumaMonitor` pushes heartbeats to Uptime Kuma; used by the incremental sync service
|
|
|
|
**log_utils.py** - Unified logging
|
|
- `LoggerManager` creates a timestamped log file under `log/` and archives old logs by year-month
|
|
|
|
**vbareplace.py** / **vba.txt** - Access VBA helper tool
|
|
- Standalone drag-and-drop tool that injects the change-log VBA macro into Access forms and
|
|
refreshes linked tables (packaged via PyInstaller; unrelated to the Python sync scripts)
|
|
|
|
## Common Development Tasks
|
|
|
|
### Install Dependencies
|
|
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### Run Full Initial Sync (Reload All Data)
|
|
|
|
```bash
|
|
python init_full_sync.py
|
|
```
|
|
|
|
### Run Incremental Sync Service (Change Log Driven)
|
|
|
|
```bash
|
|
python run_incremental_sync.py
|
|
```
|
|
|
|
## Configuration Management
|
|
|
|
Configuration lives in the **`config/` package** (re-exported via `config/__init__.py`):
|
|
- Database credentials and driver strings come from environment variables (see `.env.example`),
|
|
loaded by `python-dotenv`.
|
|
- Modify `SYNC_MAPPING` in `config/file_sources.py` to add new Access files/tables.
|
|
|
|
## Important Implementation Details
|
|
|
|
### SQL Server Connection
|
|
- Uses ODBC Driver 18 for SQL Server
|
|
- Requires `TrustServerCertificate=yes` due to self-signed cert
|
|
- Direct pyodbc connections (no SQLAlchemy); `fast_executemany=True` for bulk inserts
|
|
|
|
### Access Database Connection
|
|
- Driver: `{Microsoft Access Driver (*.mdb, *.accdb)}`
|
|
- Direct file path connection via pyodbc
|
|
|
|
### Type Mapping / Auto Table Creation
|
|
- When a SQL Server target table does not exist, it is created from the Access `cursor.description`.
|
|
- Access types map to SQL Server types: `int`→`INT` (PK → `IDENTITY(1,1) PRIMARY KEY`),
|
|
`float`→`FLOAT`, `bool`→`BIT`, `datetime`→`DATETIME`, `Decimal`→`DECIMAL(p,s)`,
|
|
`str`→`NVARCHAR(size)` (size > 4000 → `NVARCHAR(MAX)`).
|
|
|
|
### Identity Column Handling
|
|
Tables with identity columns require:
|
|
```sql
|
|
SET IDENTITY_INSERT [schema].[table] ON
|
|
-- perform inserts
|
|
SET IDENTITY_INSERT [schema].[table] OFF
|
|
```
|
|
|
|
See `has_identity_column()` in `init_full_sync.py` / `run_incremental_sync.py` for detection logic.
|
|
|
|
### File Path Matching in Incremental Sync
|
|
The change log table stores paths in VBA format:
|
|
- Network: `;DATABASE=\\server\share\file.accdb`
|
|
- Local: `LOCAL:\path\to\file.accdb` or `LOCAL=\path\to\file.accdb`
|
|
|
|
The code constructs multiple match patterns for robust matching.
|
|
|
|
## Database Schema Organization
|
|
|
|
SQL Server schemas by function:
|
|
- `productionContractData` - Contract data by year (25年/26年压力表/温度计)
|
|
- `productWarehousing` - Finished product inspection/warehousing records
|
|
- `workshopOne/Two/Three` - Workshop production records
|
|
- `machining` - Machining process records (膜片焊接, 喷涂寄出, etc.)
|
|
- `contractPlanning` - Work order assignment records
|
|
- `inspectionRecords` - Quality inspection records
|
|
- `partsWarehouse` - Component inventory records
|
|
- `thermometerRecord` - Thermometer calibration/testing records
|
|
- `solderingData` - Soldering operation records
|
|
- `TIGWelding` - TIG welding records
|
|
- `executionCardIssuanceRecord` - Execution card issuance records
|
|
- `tubeBending` - Tube bending records
|
|
- `warehouseOutbound` - (Legacy) Excel-sourced tables: `executionCardData`, `contractData`,
|
|
`customerProductType` — no longer updated
|
|
|
|
## Notifications
|
|
|
|
The system uses [ntfy](https://ntfy.sh/) for push notifications:
|
|
- Configured in `NTFY_CONFIG` within `config/app_settings.py`
|
|
- Sends on: errors, critical failures, task completion
|
|
- Authenticated via Bearer token
|
|
|
|
## Logging
|
|
|
|
- File logs: `log/` directory, one timestamped file per run (`<prefix>_<YYYYMMDD>_<HHMMSS>.log`)
|
|
- Console output: With emoji prefixes for status (✅ ❌ ⚠️ 🔄)
|
|
- Old logs are archived into `log/Archive/YYYY-MM/` automatically
|
|
(see `LoggerManager.archive_old_logs` in `log_utils.py`; `archive_existing_logs.py` is a
|
|
one-time helper for historical logs)
|