开发机迁移

This commit is contained in:
Neo
2026-04-10 06:24:13 +08:00
parent f65c1d038b
commit 79d3c2e97e
50 changed files with 1565 additions and 318 deletions

View File

@@ -373,6 +373,8 @@ def transform_area_daily(
)
# 收集所有涉及的日期
all_dates: set[date] = set()
# 未知区域名称计数(汇总后一次性输出,避免逐行 warning 产生大量日志噪音)
_unknown_area_counts: Dict[str, int] = defaultdict(int)
for row in settlement_rows:
sd = row.get("stat_date")
@@ -389,11 +391,7 @@ def transform_area_daily(
area_code = resolve_area_code(area_name)
if area_code is None:
# 未知区域:记录警告,不计入具体区域行,但仍计入 all 行
logger.warning(
"DWS_FINANCE_AREA_DAILY: 未知区域名称 '%s',不计入具体区域",
area_name,
)
_unknown_area_counts[str(area_name)] += 1
# 提取金额
table_fee = safe_decimal_fn(row.get("table_fee_amount", 0))
@@ -464,6 +462,15 @@ def transform_area_daily(
for k, v in fields.items():
bucket[k] = bucket[k] + v
# 汇总输出未知区域名称(避免逐行 warning 刷屏)
if _unknown_area_counts:
summary = ", ".join(f"'{k}': {v}" for k, v in _unknown_area_counts.items())
logger.warning(
"DWS_FINANCE_AREA_DAILY: 共 %d 条结算单区域未匹配(不计入具体区域,仅计入 all: %s",
sum(_unknown_area_counts.values()),
summary,
)
# 也收集 global_summary 中的日期
for sd in global_index:
all_dates.add(sd)

View File

@@ -104,10 +104,10 @@ class FinanceBaseTask(BaseDwsTask):
SUM(CASE WHEN is_first = 1 THEN pay_amount + point_amount ELSE 0 END) AS first_recharge_total,
SUM(CASE WHEN is_first = 1 THEN pay_amount ELSE 0 END) AS first_recharge_cash,
SUM(CASE WHEN is_first = 1 THEN point_amount ELSE 0 END) AS first_recharge_gift,
COUNT(CASE WHEN is_first = 0 OR is_first IS NULL THEN 1 END) AS renewal_count,
SUM(CASE WHEN is_first = 0 OR is_first IS NULL THEN pay_amount + point_amount ELSE 0 END) AS renewal_total,
SUM(CASE WHEN is_first = 0 OR is_first IS NULL THEN pay_amount ELSE 0 END) AS renewal_cash,
SUM(CASE WHEN is_first = 0 OR is_first IS NULL THEN point_amount ELSE 0 END) AS renewal_gift,
COUNT(CASE WHEN is_first = 2 THEN 1 END) AS renewal_count,
SUM(CASE WHEN is_first = 2 THEN pay_amount + point_amount ELSE 0 END) AS renewal_total,
SUM(CASE WHEN is_first = 2 THEN pay_amount ELSE 0 END) AS renewal_cash,
SUM(CASE WHEN is_first = 2 THEN point_amount ELSE 0 END) AS renewal_gift,
COUNT(DISTINCT member_id) AS recharge_member_count
FROM dwd.dwd_recharge_order
WHERE site_id = %s

View File

@@ -139,10 +139,10 @@ class FinanceRechargeTask(FinanceBaseTask):
SUM(CASE WHEN is_first = 1 THEN pay_amount ELSE 0 END) AS first_recharge_cash,
SUM(CASE WHEN is_first = 1 THEN point_amount ELSE 0 END) AS first_recharge_gift,
SUM(CASE WHEN is_first = 1 THEN pay_amount + point_amount ELSE 0 END) AS first_recharge_total,
COUNT(CASE WHEN is_first != 1 OR is_first IS NULL THEN 1 END) AS renewal_count,
SUM(CASE WHEN is_first != 1 OR is_first IS NULL THEN pay_amount ELSE 0 END) AS renewal_cash,
SUM(CASE WHEN is_first != 1 OR is_first IS NULL THEN point_amount ELSE 0 END) AS renewal_gift,
SUM(CASE WHEN is_first != 1 OR is_first IS NULL THEN pay_amount + point_amount ELSE 0 END) AS renewal_total,
COUNT(CASE WHEN is_first = 2 THEN 1 END) AS renewal_count,
SUM(CASE WHEN is_first = 2 THEN pay_amount ELSE 0 END) AS renewal_cash,
SUM(CASE WHEN is_first = 2 THEN point_amount ELSE 0 END) AS renewal_gift,
SUM(CASE WHEN is_first = 2 THEN pay_amount + point_amount ELSE 0 END) AS renewal_total,
COUNT(DISTINCT member_id) AS recharge_member_count,
COUNT(DISTINCT CASE WHEN is_first = 1 THEN member_id END) AS new_member_count
FROM dwd.dwd_recharge_order
@@ -198,20 +198,19 @@ class FinanceRechargeTask(FinanceBaseTask):
CASH_CARD_TYPE_ID = 2793249295533893
GIFT_CARD_TYPE_IDS = [2791990152417157, 2793266846533445, 2794699703437125]
# CHANGE 2026-02-21 | dim_member_card_account 无 site_id 字段,改用 register_site_id
# CHANGE 2026-02-22 | 需求 B通过事实表反查支持跨店消费会员
# CHANGE 2026-04-08 | 修复卡余额快照失真:改为门店全量会员
# 原逻辑通过 dwd_recharge_order 反查,遗漏"有卡无充值"会员(赠卡、活动等)
# 余额代表门店预收负债,应覆盖所有持卡会员
sql = """
SELECT card_type_id, SUM(balance) AS total_balance
FROM dwd.dim_member_card_account
WHERE tenant_member_id IN (
SELECT DISTINCT member_id
FROM dwd.dwd_recharge_order
WHERE site_id = %s
AND member_id IS NOT NULL
AND member_id != 0
) AND scd2_is_current = 1
AND COALESCE(is_delete, 0) = 0
GROUP BY card_type_id
SELECT dca.card_type_id, SUM(dca.balance) AS total_balance
FROM dwd.dim_member_card_account dca
JOIN dwd.dim_member m
ON dca.tenant_member_id = m.member_id
AND m.scd2_is_current = 1
WHERE m.register_site_id = %s
AND dca.scd2_is_current = 1
AND COALESCE(dca.is_delete, 0) = 0
GROUP BY dca.card_type_id
"""
rows = self.db.query(sql, (site_id,))

View File

@@ -36,6 +36,7 @@ class MemberActivityData:
days_since_last_recharge: Optional[int] = None
visits_14d: int = 0
visits_30d: int = 0
visits_60d: int = 0
visits_total: int = 0
@@ -451,8 +452,9 @@ class MemberIndexBaseTask(BaseIndexTask):
last_visit_time = max(r.get('last_visit_time') for r in day_rows_sorted)
data.last_visit_time = last_visit_time
# 近14/60天到店次数
# 近14/30/60天到店次数
days_14_ago = base_date - timedelta(days=14)
days_30_ago_visit = base_date - timedelta(days=30)
days_60_ago = base_date - timedelta(days=60)
for r in day_rows_sorted:
visit_date = r.get('visit_date')
@@ -460,6 +462,8 @@ class MemberIndexBaseTask(BaseIndexTask):
continue
if visit_date >= days_14_ago:
data.visits_14d += 1
if visit_date >= days_30_ago_visit:
data.visits_30d += 1
if visit_date >= days_60_ago:
data.visits_60d += 1

View File

@@ -317,7 +317,7 @@ class NewconvIndexTask(MemberIndexBaseTask):
status, segment,
member_create_time, first_visit_time, last_visit_time, last_recharge_time,
t_v, t_r, t_a,
visits_14d, visits_60d, visits_total,
visits_14d, visits_30d, visits_60d, visits_total,
spend_30d, spend_180d, sv_balance, recharge_60d_amt,
interval_count,
need_new, salvage_new, recharge_new, value_new,
@@ -331,7 +331,7 @@ class NewconvIndexTask(MemberIndexBaseTask):
%s, %s,
%s, %s, %s, %s,
%s, %s, %s,
%s, %s, %s,
%s, %s, %s, %s,
%s, %s, %s, %s,
%s,
%s, %s, %s, %s,
@@ -352,7 +352,7 @@ class NewconvIndexTask(MemberIndexBaseTask):
data.status, data.segment,
activity.member_create_time, activity.first_visit_time, activity.last_visit_time, activity.last_recharge_time,
activity.t_v, activity.t_r, activity.t_a,
activity.visits_14d, activity.visits_60d, activity.visits_total,
activity.visits_14d, activity.visits_30d, activity.visits_60d, activity.visits_total,
activity.spend_30d, activity.spend_180d, activity.sv_balance, activity.recharge_60d_amt,
activity.interval_count,
data.need_new, data.salvage_new, data.recharge_new, data.value_new,

View File

@@ -353,7 +353,12 @@ class SpendingPowerIndexTask(BaseIndexTask):
COALESCE(NULLIF(s.member_id, 0), mca.tenant_member_id)
AS canonical_member_id,
s.pay_time,
COALESCE(s.pay_amount, 0) AS pay_amount
-- DWD 规则 #1禁止 consume_money/pay_amount使用 items_sum
(COALESCE(s.table_charge_money, 0)
+ COALESCE(s.goods_money, 0)
+ COALESCE(s.assistant_pd_money, 0)
+ COALESCE(s.assistant_cx_money, 0)
+ COALESCE(s.electricity_money, 0)) AS items_sum
FROM dwd.dwd_settlement_head s
LEFT JOIN dwd.dim_member_card_account mca
ON s.member_card_account_id = mca.member_card_id
@@ -368,14 +373,14 @@ class SpendingPowerIndexTask(BaseIndexTask):
SELECT
canonical_member_id AS member_id,
-- 90 天窗口
SUM(pay_amount) AS spend_90,
SUM(items_sum) AS spend_90,
COUNT(*) AS orders_90,
COUNT(DISTINCT {biz_expr}) AS visit_days_90,
COUNT(DISTINCT EXTRACT(ISOYEAR FROM pay_time)::int * 100
+ EXTRACT(WEEK FROM pay_time)::int) AS active_weeks_90,
-- 30 天窗口(子集过滤)
SUM(CASE WHEN pay_time >= %s - INTERVAL '{short_days} days'
THEN pay_amount ELSE 0 END) AS spend_30,
THEN items_sum ELSE 0 END) AS spend_30,
SUM(CASE WHEN pay_time >= %s - INTERVAL '{short_days} days'
THEN 1 ELSE 0 END) AS orders_30,
COUNT(DISTINCT CASE WHEN pay_time >= %s - INTERVAL '{short_days} days'
@@ -491,7 +496,12 @@ class SpendingPowerIndexTask(BaseIndexTask):
COALESCE(NULLIF(s.member_id, 0), mca.tenant_member_id)
AS canonical_member_id,
{biz_expr_s} AS pay_date,
COALESCE(s.pay_amount, 0) AS pay_amount
-- DWD 规则 #1使用 items_sum
(COALESCE(s.table_charge_money, 0)
+ COALESCE(s.goods_money, 0)
+ COALESCE(s.assistant_pd_money, 0)
+ COALESCE(s.assistant_cx_money, 0)
+ COALESCE(s.electricity_money, 0)) AS items_sum
FROM dwd.dwd_settlement_head s
LEFT JOIN dwd.dim_member_card_account mca
ON s.member_card_account_id = mca.member_card_id
@@ -502,7 +512,7 @@ class SpendingPowerIndexTask(BaseIndexTask):
AND s.settle_type IN (1, 3)
AND s.pay_time >= NOW() - INTERVAL '{long_days} days'
)
SELECT pay_date, SUM(pay_amount) AS daily_spend
SELECT pay_date, SUM(items_sum) AS daily_spend
FROM consume_source
WHERE canonical_member_id = %s
GROUP BY pay_date
@@ -544,7 +554,12 @@ class SpendingPowerIndexTask(BaseIndexTask):
COALESCE(NULLIF(s.member_id, 0), mca.tenant_member_id)
AS canonical_member_id,
{biz_expr_s} AS pay_date,
COALESCE(s.pay_amount, 0) AS pay_amount
-- DWD 规则 #1使用 items_sum
(COALESCE(s.table_charge_money, 0)
+ COALESCE(s.goods_money, 0)
+ COALESCE(s.assistant_pd_money, 0)
+ COALESCE(s.assistant_cx_money, 0)
+ COALESCE(s.electricity_money, 0)) AS items_sum
FROM dwd.dwd_settlement_head s
LEFT JOIN dwd.dim_member_card_account mca
ON s.member_card_account_id = mca.member_card_id
@@ -558,7 +573,7 @@ class SpendingPowerIndexTask(BaseIndexTask):
)
SELECT canonical_member_id AS member_id,
pay_date,
SUM(pay_amount) AS daily_spend
SUM(items_sum) AS daily_spend
FROM consume_source
WHERE canonical_member_id > 0
GROUP BY canonical_member_id, pay_date

View File

@@ -369,7 +369,7 @@ class WinbackIndexTask(MemberIndexBaseTask):
status, segment,
member_create_time, first_visit_time, last_visit_time, last_recharge_time,
t_v, t_r, t_a,
visits_14d, visits_60d, visits_total,
visits_14d, visits_30d, visits_60d, visits_total,
spend_30d, spend_180d, sv_balance, recharge_60d_amt,
interval_count,
overdue_old, overdue_cdf_p, drop_old, recharge_old, value_old,
@@ -382,7 +382,7 @@ class WinbackIndexTask(MemberIndexBaseTask):
%s, %s,
%s, %s, %s, %s,
%s, %s, %s,
%s, %s, %s,
%s, %s, %s, %s,
%s, %s, %s, %s,
%s,
%s, %s, %s, %s, %s,
@@ -402,7 +402,7 @@ class WinbackIndexTask(MemberIndexBaseTask):
data.status, data.segment,
activity.member_create_time, activity.first_visit_time, activity.last_visit_time, activity.last_recharge_time,
activity.t_v, activity.t_r, activity.t_a,
activity.visits_14d, activity.visits_60d, activity.visits_total,
activity.visits_14d, activity.visits_30d, activity.visits_60d, activity.visits_total,
activity.spend_30d, activity.spend_180d, activity.sv_balance, activity.recharge_60d_amt,
activity.interval_count,
data.overdue_old, data.overdue_cdf_p, data.drop_old, data.recharge_old, data.value_old,