Files
inventory_analytics/REFACTOR_PLAN.md
T
2026-05-11 16:56:27 +08:00

6.3 KiB
Raw Blame History

Inventory Analytics 重构记录与后续计划

1. 当前目标

本次整理后的工程目标是将项目收束为两条清晰链路:

  • 委外批次库存上传:本地页面上传文件,归档原始文件,并写入 Raw PostgreSQL。
  • 飞书库存同步:从 Analytics PostgreSQL 查询库存数据,并同步到飞书多维表格。

重构重点:

  • 删除与当前工程目标无关的旧脚本。
  • 将上传页入库逻辑整理为清晰的函数边界。
  • 添加工程化日志,保证关键执行信息可追踪。
  • 保留飞书同步原入口,并补齐入口、CLI、业务同步阶段日志。

2. 当前目录结构

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

已删除旧脚本:

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。
  • 输出结构化日志。

关键常量:

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 结构:

{
  "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:

feishu      查看飞书 Base 表信息
postgres    查询 Analytics PostgreSQL
sync-brand  按配置同步品牌数据到飞书
all         执行完整流程

5. 日志方案

日志统一采用事件式结构:

YYYY-MM-DD HH:MM:SS LEVEL logger_name 事件=中文事件描述 中文字段=字段值 ...

上传页 logger:

inventory_upload

飞书同步 logger:

inventory_sync_entrypoint
inventory_sync.cli
inventory_sync.service

上传页关键事件:

上传服务启动中
上传服务已启动
收到GET请求
开始处理POST请求
收到上传请求
已解析上传文件
已分配上传归档路径
上传文件已保存
开始解析库存文件
已解析Excel工作表
已解析CSV文件
已加载Raw数据库配置
开始连接Raw数据库
开始确认Raw数据表
Raw数据表确认完成
开始写入Raw数据
Raw数据写入完成
上传请求处理完成
上传文件写入Raw数据库失败
上传服务已停止

飞书同步关键事件:

飞书同步入口启动
飞书同步动作开始
已加载环境变量文件
开始读取飞书Base信息
飞书Base信息读取完成
开始查询PostgreSQL
PostgreSQL查询完成
开始准备品牌同步
开始同步目标飞书表
目标飞书表已有记录读取完成
目标飞书表同步完成
飞书同步动作完成
飞书同步入口完成

6. 执行方式

启动上传页:

python3 upload_inventory_page.py

查看飞书表:

python3 list_feishu_base_tables.py --action feishu

查询 PostgreSQL:

python3 list_feishu_base_tables.py --action postgres

同步品牌数据:

python3 list_feishu_base_tables.py --action sync-brand

执行完整飞书同步:

python3 list_feishu_base_tables.py --action all

7. 配置维护

7.1 上传页 Raw 数据库配置

RAW_DB_HOST
RAW_DB_PORT
RAW_DB_USER
RAW_DB_PASSWORD
RAW_DB_NAME

7.2 飞书同步配置

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:

BRAND_SYNC_TARGETS = [
    BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂渠道库存-9:00和19:00", warehouse_keys=(2, 3, 7, 13)),
]

字段映射维护在 FIELD_SPECS:

FieldSpec("飞书字段名", "SQL 输出字段名", field_type, formatter, scale)

8. 验证命令

语法检查:

python3 -m py_compile upload_inventory_page.py list_feishu_base_tables.py inventory_sync/*.py

帮助信息:

python3 list_feishu_base_tables.py --help

端口检查:

lsof -nP -iTCP:8080 -sTCP:LISTEN

9. 后续计划

  • 为上传页增加 dry-run 或预览模式,只解析文件不写库。
  • 为上传页增加重复文件或重复批次检测。
  • 为 Raw 表增加按 stored_file 或 uploaded_at 的查询辅助索引。
  • 为飞书同步增加 dry-run,预览删除和新增数量。
  • 为飞书同步增加 upsert 模式,降低全量删除带来的风险。
  • 增加单元测试,覆盖文件解析、payload 构造、字段映射、数字转换。
  • 将日志接入文件轮转或统一日志采集系统。
  • 将运行命令接入 Makefile 或任务脚本,减少人工输入成本。