# Datie ERP 数据自动化项目 - 上下文与进度总结 ## 1. 项目概况与架构 - **业务目标**:从 ERP 系统(云MES)自动抓取收货明细与 BOM 成本数据,进行本地清洗、持久化与二次计算,最后通过 Web UI(成本雷达图、期间对比分析表)提供极高数据密度的商业智能看板。 - **技术栈**: - **爬虫端**:Python + DrissionPage (无头浏览器/监听API拦截)。 - **后端**:Flask + SQLite (单文件存储,`erp_data.db`)。 - **前端**:Vue 2 + ElementUI + Axios + ECharts,通过 `v-text` 避免与 Jinja2 语法冲突。 - **部署计划**:最终打包为 Windows `.exe` 单文件应用(PyInstaller),利用 `webbrowser` 开机自启,并引入 `APScheduler` 实现后台每半小时自动增量同步。 ## 2. 核心业务逻辑与计算公式 (非常重要!) ### 2.1 数量字段定义(解决“件数”与“重量”冲突) 在 ERP 原始数据中,部分物料(如 `1PZJ` 开头的床身毛胚)同时存在件数和转换后的重量。为了保证所有公式正确: - **进货数量 (purchase_qty)**:固定读取 `plannedPurchaseQuantity`(例如:8件)。**只代表件数**。 - **收货数量 (receive_qty)**:优先读取带有转换单位的 `convertGoodsQuantity`(例如:6520 KG),如果没有转换单位则回退到 `goodsQuantity`。**代表实际计价的重量/体积**。 ### 2.2 核心派生字段计算逻辑 基于上述字段定义,后端在 [app.py](file:///Users/jm/workplace/Datie/web_ui/app.py) 中动态计算以下指标: - **物料单价 (receive_price)**: - **公式**:`ROUND(COALESCE(total_amount / NULLIF(receive_qty, 0), receive_price, 0), 2)` - **说明**:收货总金额 ÷ 收货数量(重量)。例如:44988元 ÷ 6520 KG = 6.9 元/KG。 - **铸件重量 (casting_weight)**: - **公式**:`receive_qty / purchase_qty` - **说明**:收货数量(重量) ÷ 进货数量(件数)。例如:6520 KG ÷ 8 件 = 815 KG/件。该逻辑仅针对物料代码以 `1PZJ` 开头的数据生效。 - **BOM 用量合并展示**:前端将 `usage_qty` 与 `unit_name` 拼接展示(如 "2PCS")。 ## 3. UI/UX 设计规范 - **极端空间压缩**:表格行高极度压缩,去除 padding,字体使用 15px/16px,数据完美居中(Flexbox `justify-content: center`)。 - **斑马纹设计**:表格行采用白/浅蓝交替背景色,增强可读性。 - **状态指示器精简**: - 移除原先的橙色点(🟠)。 - **红点 (🔴)**:仅表示该物料在选定期间内无采购数据,当前显示的价格是**追溯至期间以前的最新历史基准价**。 - **横杠 (-)**:表示该节点(无论是父件还是底层子件)彻底没有历史采购价格,或者成本加总为 0。 ## 4. 最新进度与修复记录 (2026-04) 1. **数据抓取逻辑重构**: - 修复了爬虫脚本 [fetch_receipt_details_full.py](file:///Users/jm/workplace/Datie/browser_login/fetch_receipt_details_full.py) 和增量脚本的字段映射,确保精准提取 `convert` 系列字段。 - 优化了入库脚本 [import_to_sqlite.py](file:///Users/jm/workplace/Datie/browser_login/import_to_sqlite.py),加入了 `UPSERT` (存在即更新) 的防重复逻辑。 2. **后端查询重构**: - 修正了 `app.py` 中所有的 SQL 查询,将 `NULLIF(purchase_qty, 0)` 替换为 `NULLIF(receive_qty, 0)`,彻底解决了 8件 vs 6520公斤的计算冲突。 3. **异步调度集成**: - 实现了 [home.html](file:///Users/jm/workplace/Datie/web_ui/templates/home.html) 控制台,通过 `/api/sync_receipts` 等接口利用 `subprocess.run` 异步执行爬虫脚本,前端展示 Loading 状态。 ## 5. 下一步开发计划 (Next Steps) 1. **本地测试与验证**:在前端完成所有 BOM 树、期间对比的价格和铸件重量的视觉核对。 2. **Windows 部署准备**: - 配置 `PyInstaller` 的 `.spec` 文件,解决静态资源(templates, static)和数据库外部挂载路径(`sys._MEIPASS`)问题。 - 在 Flask 启动生命周期中集成 `APScheduler` 以替代目前手动点击按钮触发的增量更新。