feat: 完成Excel导入入库
实现 app/excel.py 多文件导入,解析账号名、别名、商品id,记录 source_file_abs/source_sheet/source_row/row_key。 导入时支持缺必需列整文件拒绝、脏行逐行跳过统计,并写入 batches/tasks;补充 match_summary 与回写占位。 新增 tests/test_excel.py 覆盖入库、缺列拒绝、多文件容错和别名匹配;同步任务看板、API 合约、当前状态和 progress。
This commit is contained in:
+24
-8
@@ -88,24 +88,40 @@ SQLite 连接规则:
|
||||
- `connect()` 必须设置 `PRAGMA foreign_keys=ON`、`journal_mode=WAL`、`busy_timeout=5000`、`synchronous=NORMAL`。
|
||||
- DB 写入短事务、单条提交;Excel 回写失败不回滚 DB。
|
||||
|
||||
## excel 模块(`app/excel.py`,待建,依赖 openpyxl)
|
||||
## excel 模块(`app/excel.py`,导入已建;回写待 T-204/T-403,依赖 openpyxl)
|
||||
|
||||
```python
|
||||
import_tasks(file_paths: list[str]) -> dict
|
||||
# 只解析【输入列】:账号名、别名、商品id;并记录 source_file/source_file_abs/source_sheet/source_row/row_key
|
||||
# -> {"rows": [...], "stats": {"files": int, "total": int, "valid": int, "invalid": int, "file_errors": [...]}}
|
||||
# 必需列缺失(别名/商品id)= 整个文件拒绝并记录到 file_errors,不导入该文件任何行
|
||||
# invalid = 单行缺别名/商品id 或商品id格式错误等脏数据;逐行跳过,不阻塞同文件其他有效行
|
||||
class ExcelError(RuntimeError): ...
|
||||
OPENPYXL_IMPORT_ERROR: Exception | None
|
||||
|
||||
import_tasks(file_paths, path=None, note=None, write_db=True) -> dict
|
||||
# file_paths 可传单个路径或多个路径。
|
||||
# 只解析【输入列】:账号名(可选)、别名、商品id;并记录
|
||||
# source_file/source_file_abs/source_sheet/source_row/row_key。
|
||||
# 默认 write_db=True:有有效行时创建 batch 并写入 tasks。
|
||||
# -> {
|
||||
# "batch_id": str|None,
|
||||
# "rows": [...],
|
||||
# "stats": {
|
||||
# "files": int, "total": int, "valid": int, "invalid": int,
|
||||
# "inserted": int, "file_errors": [...], "row_errors": [...]
|
||||
# }
|
||||
# }
|
||||
# 必需列缺失(别名/商品id)= 整个文件拒绝并记录到 file_errors,不导入该文件任何行。
|
||||
# invalid = 单行缺别名/商品id 或商品id 格式错误等脏数据;逐行跳过,不阻塞同文件其他有效行。
|
||||
# openpyxl 缺失时模块仍可导入,调用 import_tasks 时抛 ExcelError。
|
||||
|
||||
match_summary(rows: list[dict], accounts: list) -> dict
|
||||
# 用 accounts 的别名对 rows 做匹配统计(导入汇总栏用)
|
||||
# -> {"matched": int, "unmatched": int, "by_account": {别名: 行数}, "unmatched_aliases": [..]}
|
||||
|
||||
write_back(batch_id, excel_path=None) -> dict
|
||||
write_back(batch_id, excel_path=None, path=None) -> dict
|
||||
# 把【旧标题/旧封面/新标题/新封面/更新状态】批量回写到【原 Excel】
|
||||
# excel_path 为空则按 source_file_abs 分组回写本批次涉及的所有原文件
|
||||
# 原文件被占用(锁) → 抛错,调用方提示“请关闭后重试”,或改用 export_copy
|
||||
export_copy(batch_id, out_dir_or_path) -> dict # 退路:另存新结果文件,不动原文件
|
||||
export_copy(batch_id, out_dir_or_path, path=None) -> dict
|
||||
# 退路:另存新结果文件,不动原文件
|
||||
# T-201 仅保证函数存在;实际回写/另存实现留给 T-204/T-403。
|
||||
```
|
||||
|
||||
列模板见 [架构 5.3](04-architecture.md);别名以“别名”列为权威。
|
||||
|
||||
Reference in New Issue
Block a user