# Inventory Analytics 工程说明 ## 项目概览 当前工程包含两条独立业务链路: - 委外批次库存上传:通过本地网页上传 Excel/CSV 文件,保存原始文件,并逐行写入 Raw PostgreSQL 表。 - 飞书库存同步:从 Analytics PostgreSQL 查询库存、挂单量、销售和商品信息,并同步到飞书多维表格。 ## 目录结构 ```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 batch_inventory_data/ ``` 该目录保存上传的委外批次库存原始文件,不纳入业务代码结构。 ## 环境变量 ### 委外批次库存上传 上传页使用 `.env` 中的 Raw 数据库配置: ```text RAW_DB_HOST RAW_DB_PORT RAW_DB_USER RAW_DB_PASSWORD RAW_DB_NAME ``` 写入目标: ```text raw_data.wangdian_batch_inventory ``` 表结构由 `upload_inventory_page.py` 内的 `get_create_table_sql()` 创建: ```sql payload JSONB NOT NULL, start_time TIMESTAMP WITH TIME ZONE, end_time TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), reserved_1 TEXT, reserved_2 TEXT ``` ### 飞书库存同步 飞书同步使用 `.env` 中的飞书和 Analytics 数据库配置: ```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 ``` `FEISHU_APP_TOKEN` 可选;当 `FEISHU_BASE_URL` 已包含 `/base/` 或 `/wiki/` 时,可以不单独配置。 ## 委外批次库存上传 启动上传页: ```bash python3 upload_inventory_page.py ``` 打开页面: ```text http://127.0.0.1:8080 ``` 支持文件: - `.xlsx` - `.xlsm` - `.xls` - `.csv` 单文件大小限制: ```text 200 MB ``` 上传成功后会执行: 1. 保存文件到 `batch_inventory_data/`。 2. 解析 Excel/CSV 为行数据。 3. 创建 Raw schema/table 和 `created_at` 索引。 4. 每一行插入一条 JSONB payload。 payload 示例: ```json { "source_file": "委外批次库存.xlsx", "stored_file": "20260423_172410_委外批次库存.xlsx", "uploaded_at": "2026-04-23T18:20:00", "total_count": 120, "inventory_data": { "货品编码": "SKU001", "批次": "BATCH001", "数量": 10 } } ``` ## 飞书库存同步 查看飞书 Base 表: ```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 ``` 同步目标配置在 `inventory_sync/specs.py`: ```python BRAND_SYNC_TARGETS = [ BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂", warehouse_keys=(2, 3, 7, 13)), ] ``` 字段映射也集中维护在 `inventory_sync/specs.py` 的 `FIELD_SPECS`。 ## 日志说明 项目使用结构化事件日志,格式: ```text YYYY-MM-DD HH:MM:SS LEVEL logger_name 事件=中文事件描述 中文字段=字段值 ... ``` 上传页日志输出到 stdout,典型事件包括: ```text 事件=上传服务启动中 事件=收到上传请求 事件=已解析上传文件 事件=上传文件已保存 事件=开始解析库存文件 事件=已解析Excel工作表 事件=已加载Raw数据库配置 事件=Raw数据表确认完成 事件=Raw数据写入完成 事件=上传请求处理完成 ``` 飞书同步日志输出到 stderr,JSON 结果仍输出到 stdout,便于命令行管道消费。典型事件包括: ```text 事件=飞书同步入口启动 事件=飞书同步动作开始 事件=已加载环境变量文件 事件=开始读取飞书Base信息 事件=开始查询PostgreSQL 事件=开始同步品牌数据 事件=开始同步目标飞书表 事件=目标飞书表同步完成 事件=飞书同步入口完成 ``` ## 查看和关闭上传服务 查看 8080 端口: ```bash lsof -nP -iTCP:8080 -sTCP:LISTEN ``` 关闭服务: ```bash kill ``` 如果普通关闭失败: ```bash kill -9 ``` ## 验证命令 语法检查: ```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 python3 upload_inventory_page.py ``` ## 维护原则 - 上传 Raw 数据保持原始粒度,每行一条 payload,不在上传阶段做复杂业务清洗。 - 飞书同步使用 `inventory_sync/specs.py` 管理品牌目标和字段映射。 - SQL 调整优先修改 `inventory_sync/sql.py`。 - 入口脚本保持稳定,便于人工执行和后续定时任务接入。 - 日志新增时优先使用 `事件=<中文描述>`,并输出足够定位问题的关键字段。