调整 格式+推送时间
This commit is contained in:
+5
-5
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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)),
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
"渠道库存同步任务完成",
|
"渠道库存同步任务完成",
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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"],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user