e4d62df7e3
- 智能供应商识别(蓉城易购/烟草/杨碧月/通用) - 百度 OCR 表格识别集成 - 规则引擎(列映射/数据清洗/单位转换/规格推断) - 条码映射管理与云端同步(Gitea REST API) - 云端同步支持:条码映射、供应商配置、商品资料、采购模板 - 拖拽一键处理(图片→OCR→Excel→合并) - 191 个单元测试 - 移除无用的模板管理功能 - 清理 IDE 产物目录 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.8 KiB
6.8 KiB
CLAUDE.md - 益选 OCR 订单处理系统
项目概述
益选 OCR 订单处理系统 (orc-order-v2) 是一个面向零售与分销场景的采购单处理工具。
核心流程: 图片 OCR → Excel 规范化 → 模板填充 → 合并导出
目标系统: 银豹 (PosPal) POS 系统
技术栈: Python 3.9+, Tkinter, Pandas, Baidu OCR API, xlrd/xlwt/openpyxl
项目结构
orc-order-v2/
├── 启动器.py # 入口桩 (~13行, 仅导入 main)
├── headless_api.py # CLI 自动化接口 (OpenClaw 对接)
├── build_exe.py # PyInstaller 打包脚本
├── config.ini # 全局配置 (API密钥、路径)
├── config/
│ ├── config.ini # 配置副本
│ ├── barcode_mappings.json # 条码映射规则
│ └── suppliers_config.json # 供应商配置 (列映射/清洗规则/计算规则)
├── app/
│ ├── config/
│ │ ├── settings.py # ConfigManager 单例
│ │ └── defaults.py # 默认配置
│ ├── core/
│ │ ├── excel/
│ │ │ ├── processor.py # ExcelProcessor - 标准化转换核心
│ │ │ ├── converter.py # UnitConverter - 单位转换与规格推断
│ │ │ ├── merger.py # PurchaseOrderMerger - 采购单合并
│ │ │ ├── validators.py # ProductValidator
│ │ │ └── handlers/ # 条码映射、单位转换处理器
│ │ ├── handlers/
│ │ │ ├── rule_engine.py # 通用规则引擎 (split/extract/normalize/mark)
│ │ │ ├── column_mapper.py # 列映射器
│ │ │ ├── data_cleaner.py # 数据清洗器
│ │ │ └── calculator.py # 计算器
│ │ ├── ocr/
│ │ │ ├── table_ocr.py # OCRProcessor
│ │ │ └── baidu_ocr.py # BaiduOCRClient
│ │ ├── processors/
│ │ │ ├── base.py # BaseProcessor 抽象基类
│ │ │ ├── tobacco_processor.py
│ │ │ ├── ocr_processor.py
│ │ │ └── supplier_processors/
│ │ │ └── generic_supplier_processor.py
│ │ └── utils/
│ │ ├── file_utils.py # 文件操作工具
│ │ ├── log_utils.py # 日志工具
│ │ ├── string_utils.py # 字符串工具
│ │ └── dialog_utils.py # Tkinter 对话框工具
│ ├── services/
│ │ ├── order_service.py # 订单服务 (智能路由分发)
│ │ ├── ocr_service.py # OCR 服务
│ │ ├── processor_service.py # 处理器调度服务
│ │ ├── tobacco_service.py # 烟草公司专用服务
│ │ └── special_suppliers_service.py # 特殊供应商服务 (蓉城/杨碧月)
│ └── ui/ # GUI 模块 (从启动器.py拆分)
│ ├── error_utils.py # L0 错误对话框
│ ├── theme.py # L0 主题管理 (THEMES, create_modern_button)
│ ├── logging_ui.py # L0 日志队列与GUI日志处理器
│ ├── ui_widgets.py # L0 StatusBar, ProgressReporter, center_window
│ ├── user_settings.py # L1 用户设置与最近文件管理
│ ├── result_previews.py # L1 处理结果预览对话框
│ ├── command_runner.py # L1 命令执行器 (subprocess + 日志重定向)
│ ├── file_operations.py # L2 文件选择/清理/目录操作
│ ├── action_handlers.py # L2 业务操作 (OCR/Excel/合并/拖拽)
│ ├── barcode_editor.py # L2 条码映射编辑
│ ├── config_dialog.py # L3 系统设置对话框
│ ├── shortcuts.py # L3 键盘快捷键绑定
│ └── main_window.py # L4 main() 主窗口构建
├── templates/
│ ├── 银豹-采购单模板.xls # 输出模板
│ └── 商品资料.xlsx # 单价校验参考数据
├── data/
│ ├── input/ # 输入文件
│ ├── output/ # OCR 输出
│ ├── result/ # 最终采购单
│ └── user_settings.json # 用户设置
└── docs/
└── SYSTEM_ARCHITECTURE.md # 系统架构文档
命令与运行
# GUI 模式
python 启动器.py
# CLI 模式 (OpenClaw 对接)
python headless_api.py [input] [--excel|--tobacco|--rongcheng] [--barcode X --target Y]
# 打包 EXE
python build_exe.py
# 条码映射更新
python headless_api.py --update-mapping --barcode 6920584471055 --target 6920584471017
供应商智能识别逻辑
系统通过扫描 Excel 前 50 行内容特征自动路由:
| 供应商 | 识别特征 | 预处理逻辑 |
|---|---|---|
| 烟草公司 | "专卖证号" 或 "510109104938" | B/E/G/H 列映射, 数量*10, 单价/10 |
| 蓉城易购 | "RCDH" | E/N/Q/S 列映射, 多条码分裂均分数量 |
| 杨碧月 | "经手人" + "杨碧月" | 列对齐, 单位转换 (件→瓶) |
| 通用供应商 | suppliers_config.json 配置 | 列映射 + 规则引擎 |
配置系统
- ConfigManager (
app/config/settings.py): 单例模式, 基于 configparser 读取config.ini - 供应商配置 (
config/suppliers_config.json): JSON 格式, 定义列映射/清洗规则/计算规则 - 条码映射 (
config/barcode_mappings.json): 运行时可更新的条码转换规则
关键约定
输出格式
- 银豹采购单模板: 4 列 — 条码(B), 采购量(C), 赠送量(D), 采购单价(E)
- 单价保留 4 位小数, 使用 xlwt.XFStyle
- 采购单文件名:
采购单_{原文件名}.xls
单位转换规则
- "件"/"箱"/"提"/"盒" → 数量*包装数量, 单价/包装数量, 单位→"瓶"
- 赠品: 价格为 0 或金额为 0 的行标记为赠品
- 条码映射优先于单位转换
规格推断
- 从商品名称推断: "24入纸箱" → 124, "450g15" → 1*15
- 支持三级规格: 1512
- OCR 修正: "IL" → "1L", "6oo" → "600"
已知技术债务
启动器.py 过大(已拆分为 13 个app/ui/模块, 入口桩仅 13 行)- 代码重复: 表头识别、列映射、金额解析在多处重复实现
- 配置不统一: config.ini + suppliers_config.json + 硬编码路径混用
- 无测试: 测试目录为空, 无自动化测试
- 旧格式依赖: xlrd/xlwt 仅支持 .xls, 不支持 .xlsx 写入
- API 密钥明文: config.ini 中百度 OCR API 密钥未加密
- 路径硬编码: config.ini 中
template_folder = E:\2025Code\python\orc-order-v2\templates - 日志不统一: 混用
get_logger()和logging.getLogger()