2026-04-23 16:40:45 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from collections.abc import Sequence
|
|
|
|
|
|
|
|
|
|
from .specs import BRAND_SYNC_TARGETS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEFAULT_SYNC_TARGET = BRAND_SYNC_TARGETS[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _quote_sql_literal(value: str) -> str:
|
|
|
|
|
return "'" + value.replace("'", "''") + "'"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _format_warehouse_keys(warehouse_keys: Sequence[int | str]) -> str:
|
|
|
|
|
cleaned_keys = tuple(int(key) for key in warehouse_keys)
|
|
|
|
|
if not cleaned_keys:
|
|
|
|
|
raise ValueError("warehouse_keys 不能为空")
|
|
|
|
|
return ", ".join(str(key) for key in cleaned_keys)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_postgres_query(
|
|
|
|
|
brand_name: str = DEFAULT_SYNC_TARGET.brand_name,
|
|
|
|
|
warehouse_keys: Sequence[int | str] = DEFAULT_SYNC_TARGET.warehouse_keys,
|
|
|
|
|
) -> str:
|
|
|
|
|
brand_filter = _quote_sql_literal(brand_name)
|
|
|
|
|
warehouse_key_filter = _format_warehouse_keys(warehouse_keys)
|
|
|
|
|
return f"""
|
2026-04-20 15:02:17 +08:00
|
|
|
WITH inventory_latest AS (
|
|
|
|
|
SELECT
|
|
|
|
|
t."统一规格编码",
|
|
|
|
|
t."仓库主键",
|
|
|
|
|
t."物理总库存"
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT
|
|
|
|
|
f."统一规格编码",
|
|
|
|
|
f."仓库主键",
|
|
|
|
|
f."快照时间",
|
|
|
|
|
f."物理总库存",
|
|
|
|
|
ROW_NUMBER() OVER (
|
|
|
|
|
PARTITION BY f."统一规格编码", f."仓库主键"
|
|
|
|
|
ORDER BY f."快照时间" DESC
|
|
|
|
|
) AS rn
|
|
|
|
|
FROM analytics_layer.fact_inventory_snapshot f
|
|
|
|
|
WHERE f."数据来源系统" = '旺店通'
|
|
|
|
|
AND NULLIF(TRIM(f."统一规格编码"), '') IS NOT NULL
|
|
|
|
|
) t
|
|
|
|
|
WHERE t.rn = 1
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
inventory_summary AS (
|
|
|
|
|
SELECT
|
|
|
|
|
"统一规格编码",
|
|
|
|
|
SUM("物理总库存") AS "总库存"
|
|
|
|
|
FROM inventory_latest
|
2026-04-23 16:40:45 +08:00
|
|
|
WHERE "仓库主键" IN ({warehouse_key_filter})
|
2026-04-20 15:02:17 +08:00
|
|
|
GROUP BY "统一规格编码"
|
|
|
|
|
),
|
|
|
|
|
|
2026-04-23 16:40:45 +08:00
|
|
|
shop_stock_latest AS (
|
2026-04-20 15:02:17 +08:00
|
|
|
SELECT
|
|
|
|
|
t."统一规格编码",
|
|
|
|
|
t."店铺主键",
|
2026-04-24 19:00:07 +08:00
|
|
|
SUM(t."可发库存") AS "可发库存"
|
2026-04-20 15:02:17 +08:00
|
|
|
FROM (
|
|
|
|
|
SELECT
|
|
|
|
|
f."统一规格编码",
|
|
|
|
|
f."店铺主键",
|
2026-04-24 19:00:07 +08:00
|
|
|
f."仓库主键",
|
2026-04-20 15:02:17 +08:00
|
|
|
f."快照时间",
|
2026-04-23 16:40:45 +08:00
|
|
|
f."可发库存",
|
|
|
|
|
f."状态",
|
2026-04-20 15:02:17 +08:00
|
|
|
ROW_NUMBER() OVER (
|
2026-04-24 19:00:07 +08:00
|
|
|
PARTITION BY
|
|
|
|
|
f."统一规格编码",
|
|
|
|
|
f."店铺主键",
|
|
|
|
|
f."仓库主键"
|
2026-04-20 15:02:17 +08:00
|
|
|
ORDER BY f."快照时间" DESC
|
|
|
|
|
) AS rn
|
2026-04-23 16:40:45 +08:00
|
|
|
FROM analytics_layer.fact_shop_stock_snapshot f
|
2026-04-20 15:02:17 +08:00
|
|
|
WHERE f."数据来源系统" = '旺店通店铺'
|
|
|
|
|
AND NULLIF(TRIM(f."统一规格编码"), '') IS NOT NULL
|
|
|
|
|
) t
|
|
|
|
|
WHERE t.rn = 1
|
2026-04-23 16:40:45 +08:00
|
|
|
AND t."状态" <> '已失效'
|
2026-05-07 18:29:45 +08:00
|
|
|
AND t."可发库存" <> 0
|
2026-04-24 19:00:07 +08:00
|
|
|
GROUP BY
|
|
|
|
|
t."统一规格编码",
|
|
|
|
|
t."店铺主键"
|
2026-04-20 15:02:17 +08:00
|
|
|
),
|
|
|
|
|
|
|
|
|
|
sales_summary AS (
|
|
|
|
|
SELECT
|
|
|
|
|
fs."统一规格编码",
|
2026-04-22 17:12:37 +08:00
|
|
|
fs."店铺主键",
|
2026-04-20 15:02:17 +08:00
|
|
|
SUM(
|
|
|
|
|
CASE
|
|
|
|
|
WHEN fs."发货时间" >= date_trunc('month', now())
|
|
|
|
|
AND fs."发货时间" < date_trunc('month', now()) + INTERVAL '1 month'
|
|
|
|
|
THEN fs."销售数量"
|
|
|
|
|
ELSE 0
|
|
|
|
|
END
|
|
|
|
|
) AS "本月销售数量",
|
|
|
|
|
SUM(
|
|
|
|
|
CASE
|
|
|
|
|
WHEN fs."发货时间" >= date_trunc('month', now()) - INTERVAL '1 month'
|
|
|
|
|
AND fs."发货时间" < date_trunc('month', now())
|
|
|
|
|
THEN fs."销售数量"
|
|
|
|
|
ELSE 0
|
|
|
|
|
END
|
|
|
|
|
) AS "上月销售数量",
|
|
|
|
|
SUM(
|
|
|
|
|
CASE
|
|
|
|
|
WHEN fs."发货时间" >= date_trunc('month', now()) - INTERVAL '2 month'
|
|
|
|
|
AND fs."发货时间" < date_trunc('month', now()) - INTERVAL '1 month'
|
|
|
|
|
THEN fs."销售数量"
|
|
|
|
|
ELSE 0
|
|
|
|
|
END
|
|
|
|
|
) AS "上上月销售数量"
|
|
|
|
|
FROM analytics_layer.fact_sales fs
|
|
|
|
|
WHERE NULLIF(TRIM(fs."统一规格编码"), '') IS NOT NULL
|
|
|
|
|
AND fs."发货时间" >= date_trunc('month', now()) - INTERVAL '2 month'
|
|
|
|
|
AND fs."发货时间" < date_trunc('month', now()) + INTERVAL '1 month'
|
2026-04-22 17:12:37 +08:00
|
|
|
GROUP BY fs."统一规格编码", fs."店铺主键"
|
2026-04-20 15:02:17 +08:00
|
|
|
),
|
|
|
|
|
|
|
|
|
|
product_dim AS (
|
|
|
|
|
SELECT DISTINCT ON ("统一规格编码")
|
|
|
|
|
"统一规格编码",
|
|
|
|
|
"品牌名称",
|
|
|
|
|
"货品简称",
|
|
|
|
|
"一级分类",
|
|
|
|
|
"商品名称",
|
|
|
|
|
"条形码",
|
|
|
|
|
"零售价"
|
|
|
|
|
FROM analytics_layer.dim_product
|
|
|
|
|
WHERE NULLIF(TRIM("统一规格编码"), '') IS NOT NULL
|
|
|
|
|
ORDER BY "统一规格编码"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
SELECT
|
|
|
|
|
sl."统一规格编码",
|
|
|
|
|
pd."品牌名称",
|
|
|
|
|
pd."货品简称",
|
|
|
|
|
pd."一级分类",
|
|
|
|
|
pd."商品名称",
|
|
|
|
|
pd."条形码",
|
|
|
|
|
pd."零售价",
|
|
|
|
|
ds."店铺名称",
|
2026-04-23 16:40:45 +08:00
|
|
|
COALESCE(sl."可发库存", 0) AS "店铺挂单量",
|
2026-04-20 15:02:17 +08:00
|
|
|
COALESCE(inv."总库存", 0) AS "总库存",
|
|
|
|
|
COALESCE(ss."本月销售数量", 0) AS "本月销售数量",
|
|
|
|
|
COALESCE(ss."上月销售数量", 0) AS "上月销售数量",
|
|
|
|
|
COALESCE(ss."上上月销售数量", 0) AS "上上月销售数量"
|
2026-04-23 16:40:45 +08:00
|
|
|
FROM shop_stock_latest sl
|
2026-04-20 15:02:17 +08:00
|
|
|
LEFT JOIN inventory_summary inv
|
|
|
|
|
ON sl."统一规格编码" = inv."统一规格编码"
|
|
|
|
|
LEFT JOIN analytics_layer.dim_shop ds
|
|
|
|
|
ON sl."店铺主键" = ds."店铺主键"
|
|
|
|
|
LEFT JOIN sales_summary ss
|
|
|
|
|
ON sl."统一规格编码" = ss."统一规格编码"
|
2026-05-07 18:29:45 +08:00
|
|
|
AND sl."店铺主键" = ss."店铺主键"
|
2026-04-20 15:02:17 +08:00
|
|
|
LEFT JOIN product_dim pd
|
|
|
|
|
ON sl."统一规格编码" = pd."统一规格编码"
|
2026-04-23 16:40:45 +08:00
|
|
|
WHERE pd."品牌名称" = {brand_filter}
|
2026-04-20 15:02:17 +08:00
|
|
|
ORDER BY sl."统一规格编码", sl."店铺主键"
|
|
|
|
|
"""
|
2026-04-23 16:40:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
POSTGRES_QUERY = build_postgres_query()
|