# Inventory Analytics 重构记录与后续计划 ## 1. 当前目标 本次整理后的工程目标是将项目收束为两条清晰链路: - 委外批次库存上传:本地页面上传文件,归档原始文件,并写入 Raw PostgreSQL。 - 飞书库存同步:从 Analytics PostgreSQL 查询库存数据,并同步到飞书多维表格。 重构重点: - 删除与当前工程目标无关的旧脚本。 - 将上传页入库逻辑整理为清晰的函数边界。 - 添加工程化日志,保证关键执行信息可追踪。 - 保留飞书同步原入口,并补齐入口、CLI、业务同步阶段日志。 ## 2. 当前目录结构 ```text inventory_analytics/ ├── .env ├── PROJECT_GUIDE.md ├── REFACTOR_PLAN.md ├── upload_inventory_page.py ├── list_feishu_base_tables.py └── inventory_sync/ ├── __init__.py ├── cli.py ├── feishu.py ├── postgres.py ├── service.py ├── settings.py ├── specs.py └── sql.py ``` 已删除旧脚本: ```text crud.py base_xlsx_to_db.py save_orders.py session.py tmall_orders_flow.py ``` ## 3. 上传页重构结果 文件:`upload_inventory_page.py` 职责: - 启动本地上传页面。 - 接收拖拽上传的 Excel/CSV 文件。 - 保存原始文件到 `batch_inventory_data/`。 - 读取 `.env` 中的 Raw 数据库配置。 - 创建 `raw_data.wangdian_batch_inventory`。 - 按文件行粒度写入 JSONB payload。 - 输出结构化日志。 关键常量: ```python HOST = "127.0.0.1" PORT = 8080 UPLOAD_DIR = PROJECT_ROOT / "batch_inventory_data" MAX_UPLOAD_BYTES = 200 * 1024 * 1024 DB_SCHEMA = "raw_data" DB_TABLE = "wangdian_batch_inventory" DATA_FIELD = "inventory_data" ``` payload 结构: ```json { "source_file": "原始文件名.xlsx", "stored_file": "带时间戳的归档文件名.xlsx", "uploaded_at": "上传时间", "total_count": 100, "inventory_data": { "每一行的字段": "每一行的值" } } ``` 说明: - `total_count` 表示本批上传文件解析出的总行数。 - `inventory_data` 保存当前行的完整数据。 - Excel 多 sheet 文件会在行数据中补充 `_sheet_name`。 - 空值会写入 JSON `null`。 - 日期类单元格会转成 ISO 字符串。 ## 4. 飞书同步重构结果 入口文件:`list_feishu_base_tables.py` 模块职责: | 文件 | 职责 | | --- | --- | | `list_feishu_base_tables.py` | 兼容入口、配置日志、记录启动和退出 | | `inventory_sync/cli.py` | 解析 action、编排顶层执行、输出 JSON 结果 | | `inventory_sync/settings.py` | 加载 `.env`,构建配置对象 | | `inventory_sync/postgres.py` | 执行 Analytics PostgreSQL 查询 | | `inventory_sync/sql.py` | 维护库存同步 SQL | | `inventory_sync/feishu.py` | 封装飞书 API | | `inventory_sync/service.py` | 编排品牌同步业务流程 | | `inventory_sync/specs.py` | 维护品牌目标和字段映射 | 当前 action: ```text feishu 查看飞书 Base 表信息 postgres 查询 Analytics PostgreSQL sync-brand 按配置同步品牌数据到飞书 all 执行完整流程 ``` ## 5. 日志方案 日志统一采用事件式结构: ```text YYYY-MM-DD HH:MM:SS LEVEL logger_name 事件=中文事件描述 中文字段=字段值 ... ``` 上传页 logger: ```text inventory_upload ``` 飞书同步 logger: ```text inventory_sync_entrypoint inventory_sync.cli inventory_sync.service ``` 上传页关键事件: ```text 上传服务启动中 上传服务已启动 收到GET请求 开始处理POST请求 收到上传请求 已解析上传文件 已分配上传归档路径 上传文件已保存 开始解析库存文件 已解析Excel工作表 已解析CSV文件 已加载Raw数据库配置 开始连接Raw数据库 开始确认Raw数据表 Raw数据表确认完成 开始写入Raw数据 Raw数据写入完成 上传请求处理完成 上传文件写入Raw数据库失败 上传服务已停止 ``` 飞书同步关键事件: ```text 飞书同步入口启动 飞书同步动作开始 已加载环境变量文件 开始读取飞书Base信息 飞书Base信息读取完成 开始查询PostgreSQL PostgreSQL查询完成 开始准备品牌同步 开始同步目标飞书表 目标飞书表已有记录读取完成 目标飞书表同步完成 飞书同步动作完成 飞书同步入口完成 ``` ## 6. 执行方式 启动上传页: ```bash python3 upload_inventory_page.py ``` 查看飞书表: ```bash python3 list_feishu_base_tables.py --action feishu ``` 查询 PostgreSQL: ```bash python3 list_feishu_base_tables.py --action postgres ``` 同步品牌数据: ```bash python3 list_feishu_base_tables.py --action sync-brand ``` 执行完整飞书同步: ```bash python3 list_feishu_base_tables.py --action all ``` ## 7. 配置维护 ### 7.1 上传页 Raw 数据库配置 ```text RAW_DB_HOST RAW_DB_PORT RAW_DB_USER RAW_DB_PASSWORD RAW_DB_NAME ``` ### 7.2 飞书同步配置 ```text FEISHU_APP_ID FEISHU_APP_SECRET FEISHU_BASE_URL FEISHU_APP_TOKEN ANALYTICS_DB_HOST ANALYTICS_DB_PORT ANALYTICS_DB_USER ANALYTICS_DB_PASSWORD ANALYTICS_DB_NAME ``` ### 7.3 品牌和字段配置 品牌同步目标维护在 `inventory_sync/specs.py`: ```python BRAND_SYNC_TARGETS = [ BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂渠道库存-9:30和20:00", warehouse_keys=(2, 3, 7, 13)), ] ``` 字段映射维护在 `FIELD_SPECS`: ```python FieldSpec("飞书字段名", "SQL 输出字段名", field_type, formatter, scale) ``` ## 8. 验证命令 语法检查: ```bash python3 -m py_compile upload_inventory_page.py list_feishu_base_tables.py inventory_sync/*.py ``` 帮助信息: ```bash python3 list_feishu_base_tables.py --help ``` 端口检查: ```bash lsof -nP -iTCP:8080 -sTCP:LISTEN ``` ## 9. 后续计划 - 为上传页增加 dry-run 或预览模式,只解析文件不写库。 - 为上传页增加重复文件或重复批次检测。 - 为 Raw 表增加按 `stored_file` 或 `uploaded_at` 的查询辅助索引。 - 为飞书同步增加 dry-run,预览删除和新增数量。 - 为飞书同步增加 upsert 模式,降低全量删除带来的风险。 - 增加单元测试,覆盖文件解析、payload 构造、字段映射、数字转换。 - 将日志接入文件轮转或统一日志采集系统。 - 将运行命令接入 Makefile 或任务脚本,减少人工输入成本。