- src: config_loader / source_watcher / excel_parser / sync_writer / runner - 169 Excel 全量同步至 114 SQL Server + Access 生产库 - 新增 .gitignore(忽略 venv、日志、数据、含凭据的 config.yaml 等) - 新增 README.md(用途、安装、配置、运行模式、部署说明)
124 lines
4.4 KiB
Markdown
124 lines
4.4 KiB
Markdown
# ProcurementVisibilityHub_DataSync
|
||
|
||
采购执行情况即时数据同步服务。将 169 共享盘上的 Excel(`采购执行情况即时数据.xlsx`)同步写入两个目标库:
|
||
|
||
- **SQL Server**(114 / `CompanyDB`,schema `procurementVisibilityHub`,表 `请购执行`)
|
||
- **Access 生产库**(`ProcurementVisibilityHub.accdb`,表 `procurementVisibilityHub_请购执行`)
|
||
|
||
采用**全量覆盖**策略:SQL Server 端 `TRUNCATE + INSERT`,Access 端 `DELETE + INSERT`,并写入统一的「导入时间」。
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
| 路径 | 说明 |
|
||
|---|---|
|
||
| `config/config.yaml` | 运行配置(含 DB 凭据,**已被 .gitignore 忽略**) |
|
||
| `src/config_loader.py` | 读取 YAML 配置、构造 ODBC 连接串 |
|
||
| `src/source_watcher.py` | 源文件变化检测(mtime/size)+ 下载到 `data/` |
|
||
| `src/excel_parser.py` | 解析 xlsx → 行字典,含字段映射与类型转换 |
|
||
| `src/sync_writer.py` | 全量写入 SQL Server + Access |
|
||
| `src/runner.py` | 主入口:服务循环 / 单次 / 本地联调 / dry-run |
|
||
| `data/` | 源文件历史副本(运行时生成,已忽略) |
|
||
| `logs/sync.log` | 运行日志(运行时生成,已忽略) |
|
||
|
||
---
|
||
|
||
## 环境要求
|
||
|
||
- Python **3.10+**
|
||
- 目标主机需安装 ODBC 驱动:
|
||
- **ODBC Driver 17 for SQL Server**(连 114 SQL Server)
|
||
- **Microsoft Access Driver (*.mdb, *.accdb)**(连 Access 生产库)
|
||
- 依赖见 `requirements.txt`:`PyYAML`、`openpyxl`、`pyodbc`
|
||
|
||
---
|
||
|
||
## 安装
|
||
|
||
```bash
|
||
# 1. 创建并激活虚拟环境(项目内)
|
||
python -m venv .venv
|
||
.\.venv\Scripts\activate # Windows
|
||
# source .venv/bin/activate # Linux/macOS
|
||
|
||
# 2. 安装依赖
|
||
pip install -r requirements.txt
|
||
|
||
# 3. 准备配置(从模板复制后填入真实凭据)
|
||
cp config/config.yaml.example config/config.yaml # 若无模板,直接新建 config/config.yaml
|
||
```
|
||
|
||
> ⚠️ `config/config.yaml` 含数据库账号密码,**不纳入版本管理**。如需团队共享,请提交一份 `config/config.yaml.example`(占位凭据),真实配置留本地。
|
||
|
||
---
|
||
|
||
## 配置说明(config/config.yaml 关键字段)
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| `source.unc_path` | 源 Excel 的 UNC 路径(169 共享盘) |
|
||
| `source.local_cache_dir` | 本地历史副本目录(默认 `data`) |
|
||
| `scan.interval_seconds` | 服务循环扫描间隔(秒) |
|
||
| `sql_server.*` | SQL Server 连接信息(server/port/database/user/password…) |
|
||
| `access.*` | Access 库路径与表名(DBQ/table) |
|
||
| `field_map` | Excel 列名 → 数据库字段名(仅列名不同者) |
|
||
| `auto_fields` | 数据库自动生成字段:`id_field`(自增不写)、`import_time_field`(=同步时刻) |
|
||
| `sync.strategy` | 同步策略,当前固定 `full` |
|
||
| `sync.batch_size` | 批量插入大小(默认 1000) |
|
||
| `logging` | 日志级别与目录 |
|
||
|
||
---
|
||
|
||
## 使用方式
|
||
|
||
```bash
|
||
# 服务循环模式(默认,配合 NSSM 部署为 Windows 服务)
|
||
python -m src.runner
|
||
|
||
# 单次运行后退出
|
||
python -m src.runner --once
|
||
|
||
# 用本地文件作源(跳过 169 下载,便于联调)
|
||
python -m src.runner --local X.xlsx
|
||
|
||
# 仅解析并打印,不写库
|
||
python -m src.runner --local X.xlsx --dry-run
|
||
|
||
# 指定配置文件
|
||
python -m src.runner --config config/config.yaml
|
||
```
|
||
|
||
运行逻辑:检测源 Excel 是否变化(mtime/size),无变化则跳过;有变化则下载副本 → 解析 → 全量写入两个目标库。
|
||
|
||
---
|
||
|
||
## 运行流程
|
||
|
||
```
|
||
169 共享 Excel
|
||
│ source_watcher 检测变化 + 下载到 data/
|
||
▼
|
||
excel_parser 解析(字段映射 + 类型转换:float/datetime/int/text)
|
||
▼
|
||
sync_writer 全量写入
|
||
├─ SQL Server:TRUNCATE + 分批 INSERT(fast_executemany,事务提交)
|
||
└─ Access: DELETE + 分批 INSERT(autocommit)
|
||
▼
|
||
logs/sync.log 记录全过程
|
||
```
|
||
|
||
---
|
||
|
||
## 部署(NSSM 服务)
|
||
|
||
以 Windows 服务常驻运行(主机 114),由 NSSM 拉起 `python -m src.runner` 进入循环模式。日志统一写入 `logs/sync.log`。
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
- **连不上 SQL Server**:确认 ODBC Driver 17 已装、114:1433 可达、账号密码正确(`Encrypt`/`TrustServerCertificate` 与服务器端匹配)。
|
||
- **Access 写入失败**:确认目标主机装了 Microsoft Access Driver,且 `access.dbq` 路径存在、有写权限。
|
||
- **源无变化不执行**:属正常行为(基于 mtime/size 的增量跳过);想强制全量可用 `--local` 指定当前文件或删除 `data/.source_meta.json` 基准。
|