调整 格式+推送时间

This commit is contained in:
2026-05-11 16:56:27 +08:00
parent 7ea35eaa9c
commit ab7d2f9b7a
9 changed files with 41 additions and 39 deletions
+5 -5
View File
@@ -10,7 +10,7 @@
命名说明: 命名说明:
- “渠道库存统计”是框架层命名,当前默认业务目标仍是羽心堂渠道库存。 - “渠道库存统计”是框架层命名,当前默认业务目标仍是羽心堂渠道库存-9:00和19:00。
- “批次库存统计”是框架层命名,当前默认业务目标仍是羽心堂批次库存。 - “批次库存统计”是框架层命名,当前默认业务目标仍是羽心堂批次库存。
- 后续扩展到其他品牌时,优先复用这两条通用链路,而不是继续新增带品牌名的脚本和包名。 - 后续扩展到其他品牌时,优先复用这两条通用链路,而不是继续新增带品牌名的脚本和包名。
@@ -278,7 +278,7 @@ all
说明: 说明:
- 当前脚本名已经泛化为“渠道库存统计”,但内部动作参数 `sync-brand` 仍来自历史实现,后续可再统一。 - 当前脚本名已经泛化为“渠道库存统计”,但内部动作参数 `sync-brand` 仍来自历史实现,后续可再统一。
- 当前默认同步目标仍是羽心堂渠道库存。 - 当前默认同步目标仍是羽心堂渠道库存-9:00和19:00。
渠道库存统计目标和字段映射当前仍维护在: 渠道库存统计目标和字段映射当前仍维护在:
@@ -379,7 +379,7 @@ prefect_inventory_scheduler.py
### 10.1 调度目标 ### 10.1 调度目标
当前通过 Prefect 定义了 2 个 deployment,都会在每天 `09:15`(`Asia/Shanghai`)执行: 当前通过 Prefect 定义了 2 个 deployment,都会在每天 `09:15` 和 `19:15`(`Asia/Shanghai`)执行:
- 渠道库存统计并写入飞书 - 渠道库存统计并写入飞书
- 批次库存统计报表并写入飞书 - 批次库存统计报表并写入飞书
@@ -407,8 +407,8 @@ sh scripts/register_prefect_deployments.sh
脚本会进入 Docker 容器内,按 deployment 名称分别注册: 脚本会进入 Docker 容器内,按 deployment 名称分别注册:
```bash ```bash
docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name channel-inventory-sync-0915 docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name channel-inventory-sync-0915-1915
docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name batch-inventory-repor-0915 docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name batch-inventory-report-0915-1915
``` ```
### 10.4 启动 Docker worker ### 10.4 启动 Docker worker
+4 -4
View File
@@ -171,8 +171,8 @@ PREFECT_API_URL
项目定义了两个 Prefect deployment: 项目定义了两个 Prefect deployment:
- `channel-inventory-sync-0915`:每天 09:15 执行渠道库存统计并写入飞书。 - `channel-inventory-sync-0915-1915`:每天 09:15 和 19:15 执行渠道库存统计并写入飞书。
- `batch-inventory-repor-0915`:每天 09:15 执行批次库存统计并写入飞书。 - `batch-inventory-report-0915-1915`:每天 09:15 和 19:15 执行批次库存统计并写入飞书。
注册 deployment: 注册 deployment:
@@ -183,8 +183,8 @@ sh scripts/register_prefect_deployments.sh
该脚本会进入 Docker 容器内,按 deployment 名称分别注册: 该脚本会进入 Docker 容器内,按 deployment 名称分别注册:
```bash ```bash
docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name channel-inventory-sync-0915 docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name channel-inventory-sync-0915-1915
docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name batch-inventory-repor-0915 docker compose exec -T prefect-inventory-worker prefect --no-prompt deploy --name batch-inventory-report-0915-1915
``` ```
启动 Docker worker: 启动 Docker worker:
+1 -1
View File
@@ -247,7 +247,7 @@ ANALYTICS_DB_NAME
```python ```python
BRAND_SYNC_TARGETS = [ BRAND_SYNC_TARGETS = [
BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂", warehouse_keys=(2, 3, 7, 13)), BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂渠道库存-9:00和19:00", warehouse_keys=(2, 3, 7, 13)),
] ]
``` ```
+5 -9
View File
@@ -9,7 +9,6 @@ from typing import Any
from inventory_analytics.logging_utils import exception_fields from inventory_analytics.logging_utils import exception_fields
from inventory_analytics.logging_utils import log_event as emit_log_event from inventory_analytics.logging_utils import log_event as emit_log_event
from inventory_analytics.logging_utils import sanitize_value
from .feishu import FeishuClient from .feishu import FeishuClient
from .postgres import query_postgres from .postgres import query_postgres
@@ -62,14 +61,14 @@ def safe_result_summary(result: dict[str, object]) -> dict[str, object]:
summary["sync_brand"] = { summary["sync_brand"] = {
"target_count": sync_result.get("target_count"), "target_count": sync_result.get("target_count"),
"source_row_count": sync_result.get("source_row_count"), "source_row_count": sync_result.get("source_row_count"),
"filtered_row_count": sync_result.get("filtered_row_count"),
"deleted_record_count": sync_result.get("deleted_record_count"),
"created_record_count": sync_result.get("created_record_count"),
"shop_count": sync_result.get("shop_count"),
} }
return summary return summary
def public_result(result: dict[str, object]) -> dict[str, object]:
return sanitize_value(result)
def main() -> int: def main() -> int:
started_at = time.monotonic() started_at = time.monotonic()
try: try:
@@ -115,10 +114,7 @@ def main() -> int:
source_row_count=result["sync_brand"].get("source_row_count") if isinstance(result["sync_brand"], dict) else None, source_row_count=result["sync_brand"].get("source_row_count") if isinstance(result["sync_brand"], dict) else None,
) )
if safe_logs: print(json.dumps(safe_result_summary(result), ensure_ascii=False, indent=2))
print(json.dumps(safe_result_summary(result), ensure_ascii=False, indent=2))
else:
print(json.dumps(public_result(result), ensure_ascii=False, indent=2))
log_event( log_event(
logging.INFO, logging.INFO,
"渠道库存同步任务完成", "渠道库存同步任务完成",
+6 -6
View File
@@ -189,15 +189,12 @@ def sync_brand_target(
) )
return { return {
"brand_name": target.brand_name,
"warehouse_keys": target.warehouse_keys,
"target_table_name": target.table_name,
"target_table_id": table_id,
"available_fields": available_fields,
"source_row_count": len(source_rows), "source_row_count": len(source_rows),
"filtered_row_count": len(target_rows), "filtered_row_count": len(target_rows),
"deleted_record_count": deleted_count, "deleted_record_count": deleted_count,
"created_record_count": created_count, "created_record_count": created_count,
"available_field_count": len(available_fields),
"shop_count": len(shop_names),
} }
@@ -232,5 +229,8 @@ def run_sync_brand(config: AppConfig, client: FeishuClient, postgres_result: dic
return { return {
"target_count": len(BRAND_SYNC_TARGETS), "target_count": len(BRAND_SYNC_TARGETS),
"source_row_count": source_row_count, "source_row_count": source_row_count,
"targets": results, "filtered_row_count": sum(int(result.get("filtered_row_count") or 0) for result in results),
"deleted_record_count": sum(int(result.get("deleted_record_count") or 0) for result in results),
"created_record_count": sum(int(result.get("created_record_count") or 0) for result in results),
"shop_count": sum(int(result.get("shop_count") or 0) for result in results),
} }
+3 -2
View File
@@ -25,7 +25,7 @@ class FieldSpec:
BRAND_SYNC_TARGETS = [ BRAND_SYNC_TARGETS = [
BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂", warehouse_keys=(2, 3, 7, 13)), BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂渠道库存-9:00和19:00", warehouse_keys=(2, 3, 7, 13)),
] ]
@@ -42,7 +42,7 @@ FIELD_SPECS = [
FieldSpec("分类", "一级分类", 1), FieldSpec("分类", "一级分类", 1),
FieldSpec("条形码", "条形码", 1), FieldSpec("条形码", "条形码", 1),
FieldSpec("零售价", "零售价", 2, "0.00", 2), FieldSpec("零售价", "零售价", 2, "0.00", 2),
FieldSpec("可用总库存", "可用总库存", 2, "0", 0), FieldSpec("渠道锁库库存", "可用总库存", 2, "0", 0),
FieldSpec("全渠道总库存", "总库存", 2, "0", 0), FieldSpec("全渠道总库存", "总库存", 2, "0", 0),
FieldSpec("品牌", "品牌名称", 1), FieldSpec("品牌", "品牌名称", 1),
FieldSpec("产品类别", "货品简称", 1), FieldSpec("产品类别", "货品简称", 1),
@@ -55,6 +55,7 @@ LEGACY_NAME_MAP = {
"商品名称": "货品名称", "商品名称": "货品名称",
"店铺名称": "店铺名称", "店铺名称": "店铺名称",
"店铺挂单量": "店铺可用库存", "店铺挂单量": "店铺可用库存",
"可用总库存": "渠道锁库库存",
"本月销售数量": month_sales_field_name(0), "本月销售数量": month_sales_field_name(0),
"上月销售数量": month_sales_field_name(1), "上月销售数量": month_sales_field_name(1),
"上上月销售数量": month_sales_field_name(2), "上上月销售数量": month_sales_field_name(2),
+10 -4
View File
@@ -6,9 +6,9 @@ push: []
pull: [] pull: []
deployments: deployments:
- name: channel-inventory-sync-0915 - name: channel-inventory-sync-0915-1915
version: "1.0.0" version: "1.0.0"
description: "每天 09:15 执行渠道库存统计并写入飞书多维表格。" description: "每天 09:15 和 19:15 执行渠道库存统计并写入飞书多维表格。"
entrypoint: prefect_inventory_scheduler.py:inventory_channel_inventory_sync_flow entrypoint: prefect_inventory_scheduler.py:inventory_channel_inventory_sync_flow
parameters: {} parameters: {}
tags: tags:
@@ -19,12 +19,15 @@ deployments:
- cron: "15 9 * * *" - cron: "15 9 * * *"
timezone: "Asia/Shanghai" timezone: "Asia/Shanghai"
active: true active: true
- cron: "15 19 * * *"
timezone: "Asia/Shanghai"
active: true
work_pool: work_pool:
name: inventory-analytics-pool name: inventory-analytics-pool
- name: batch-inventory-repor-0915 - name: batch-inventory-report-0915-1915
version: "1.0.0" version: "1.0.0"
description: "每天 09:15 生成批次库存统计数据并写入飞书多维表格,不输出本地报表文件。" description: "每天 09:15 和 19:15 生成批次库存统计数据并写入飞书多维表格,不输出本地报表文件。"
entrypoint: prefect_inventory_scheduler.py:inventory_batch_inventory_report_flow entrypoint: prefect_inventory_scheduler.py:inventory_batch_inventory_report_flow
parameters: parameters:
output: "" output: ""
@@ -39,5 +42,8 @@ deployments:
- cron: "15 9 * * *" - cron: "15 9 * * *"
timezone: "Asia/Shanghai" timezone: "Asia/Shanghai"
active: true active: true
- cron: "15 19 * * *"
timezone: "Asia/Shanghai"
active: true
work_pool: work_pool:
name: inventory-analytics-pool name: inventory-analytics-pool
+5 -5
View File
@@ -132,7 +132,7 @@ def inventory_batch_inventory_report_flow(
def parse_args() -> argparse.Namespace: def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Prefect 调度:每天 09:15 执行渠道库存统计和批次库存统计写飞书。") parser = argparse.ArgumentParser(description="Prefect 调度:每天 09:15 和 19:15 执行渠道库存统计和批次库存统计写飞书。")
parser.add_argument("--serve-channel-inventory-sync", action="store_true", help="启动渠道库存统计 flow 的本地 serve 调度") parser.add_argument("--serve-channel-inventory-sync", action="store_true", help="启动渠道库存统计 flow 的本地 serve 调度")
parser.add_argument("--serve-batch-inventory-report", action="store_true", help="启动批次库存统计 flow 的本地 serve 调度") parser.add_argument("--serve-batch-inventory-report", action="store_true", help="启动批次库存统计 flow 的本地 serve 调度")
parser.add_argument("--run-channel-inventory-sync", action="store_true", help="立即执行一次渠道库存统计 flow") parser.add_argument("--run-channel-inventory-sync", action="store_true", help="立即执行一次渠道库存统计 flow")
@@ -154,15 +154,15 @@ def main() -> None:
} }
if args.serve_channel_inventory_sync: if args.serve_channel_inventory_sync:
inventory_channel_inventory_sync_flow.serve( inventory_channel_inventory_sync_flow.serve(
name="channel-inventory-sync-0915", name="channel-inventory-sync-0915-1915",
cron="15 9 * * *", cron=("15 9 * * *", "15 19 * * *"),
tags=["inventory", "feishu", "channel-inventory-sync"], tags=["inventory", "feishu", "channel-inventory-sync"],
) )
return return
if args.serve_batch_inventory_report: if args.serve_batch_inventory_report:
inventory_batch_inventory_report_flow.serve( inventory_batch_inventory_report_flow.serve(
name="batch-inventory-repor-0915", name="batch-inventory-report-0915-1915",
cron="15 9 * * *", cron=("15 9 * * *", "15 19 * * *"),
parameters=flow_kwargs, parameters=flow_kwargs,
tags=["inventory", "feishu", "batch-inventory-report"], tags=["inventory", "feishu", "batch-inventory-report"],
) )
+2 -3
View File
@@ -10,6 +10,5 @@ deploy_by_name() {
prefect --no-prompt deploy --name "${deployment_name}" prefect --no-prompt deploy --name "${deployment_name}"
} }
deploy_by_name "channel-inventory-sync-0915" deploy_by_name "channel-inventory-sync-0915-1915"
deploy_by_name "batch-inventory-repor-0915" deploy_by_name "batch-inventory-report-0915-1915"