开发机迁移

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

@@ -0,0 +1,74 @@
-- 迁移:为 dws_member_winback_index 和 dws_member_newconv_index 添加 visits_30d 字段
-- Fix-3recall 维度需要 30 天到店次数,原先用 visits_14d 近似
-- 日期2026-04-07
-- 重要:加列后必须重建所有引用这两张表的视图,否则视图看不到新列
-- 1. 加列
ALTER TABLE dws.dws_member_winback_index
ADD COLUMN IF NOT EXISTS visits_30d integer DEFAULT 0 NOT NULL;
ALTER TABLE dws.dws_member_newconv_index
ADD COLUMN IF NOT EXISTS visits_30d integer DEFAULT 0 NOT NULL;
-- 2. 重建 app schema RLS 视图DROP + CREATE因为列顺序变化导致 CREATE OR REPLACE 报错)
DROP VIEW IF EXISTS app.v_dws_member_winback_index;
CREATE VIEW app.v_dws_member_winback_index AS
SELECT winback_id, site_id, tenant_id, member_id, status, segment,
member_create_time, first_visit_time, last_visit_time, last_recharge_time,
t_v, t_r, t_a,
visits_14d, visits_30d, visits_60d, visits_total,
spend_30d, spend_180d, sv_balance, recharge_60d_amt, interval_count,
overdue_old, drop_old, recharge_old, value_old,
raw_score, display_score, last_wechat_touch_time,
calc_time, calc_version, created_at, updated_at,
overdue_cdf_p, ideal_interval_days, ideal_next_visit_date
FROM dws.dws_member_winback_index
WHERE site_id = current_setting('app.current_site_id')::bigint;
DROP VIEW IF EXISTS app.v_dws_member_newconv_index;
CREATE VIEW app.v_dws_member_newconv_index AS
SELECT newconv_id, site_id, tenant_id, member_id, status, segment,
member_create_time, first_visit_time, last_visit_time, last_recharge_time,
t_v, t_r, t_a,
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, welcome_new,
raw_score_welcome, raw_score_convert, raw_score,
display_score_welcome, display_score_convert, display_score,
last_wechat_touch_time, calc_time, calc_version, created_at, updated_at
FROM dws.dws_member_newconv_index
WHERE site_id = current_setting('app.current_site_id')::bigint;
-- 3. 重建 dws.v_member_recall_priority (UNION ALL 视图)
DROP VIEW IF EXISTS dws.v_member_recall_priority;
CREATE VIEW dws.v_member_recall_priority AS
SELECT site_id, tenant_id, member_id, 'WBI'::varchar(10) AS index_type,
status, segment, member_create_time, first_visit_time, last_visit_time, last_recharge_time,
t_v, t_r, t_a, visits_14d, visits_30d, visits_60d, visits_total,
spend_30d, spend_180d, sv_balance, recharge_60d_amt,
NULL::numeric(10,4) AS need_new, NULL::numeric(10,4) AS salvage_new,
NULL::numeric(10,4) AS recharge_new, NULL::numeric(10,4) AS value_new,
NULL::numeric(10,4) AS welcome_new,
NULL::numeric(14,6) AS raw_score_welcome, NULL::numeric(14,6) AS raw_score_convert,
raw_score,
NULL::numeric(4,2) AS display_score_welcome, NULL::numeric(4,2) AS display_score_convert,
display_score, last_wechat_touch_time, calc_time
FROM dws.dws_member_winback_index
UNION ALL
SELECT site_id, tenant_id, member_id, 'NCI'::varchar(10) AS index_type,
status, segment, member_create_time, first_visit_time, last_visit_time, last_recharge_time,
t_v, t_r, t_a, visits_14d, visits_30d, visits_60d, visits_total,
spend_30d, spend_180d, sv_balance, recharge_60d_amt,
need_new, salvage_new, recharge_new, value_new, welcome_new,
raw_score_welcome, raw_score_convert, raw_score,
display_score_welcome, display_score_convert, display_score,
last_wechat_touch_time, calc_time
FROM dws.dws_member_newconv_index;
-- 4. 回滚脚本(如需回滚,按逆序执行):
-- DROP VIEW IF EXISTS dws.v_member_recall_priority;
-- DROP VIEW IF EXISTS app.v_dws_member_newconv_index;
-- DROP VIEW IF EXISTS app.v_dws_member_winback_index;
-- ALTER TABLE dws.dws_member_winback_index DROP COLUMN IF EXISTS visits_30d;
-- ALTER TABLE dws.dws_member_newconv_index DROP COLUMN IF EXISTS visits_30d;
-- 然后重建原始视图(不含 visits_30d

View File

@@ -0,0 +1,58 @@
-- 迁移:修复 app schema 快照视图多行膨胀
-- 背景consumption_summary 和 assistant_customer_stats 按 stat_date 存储每日快照,
-- 原视图返回全部行导致 JOIN 行膨胀和前端卡片重复。
-- 修复DISTINCT ON 只取每个唯一键的最新 stat_date 行。
-- 日期2026-04-08
-- 1. v_dws_member_consumption_summary每个 member_id 只取最新快照
CREATE OR REPLACE VIEW app.v_dws_member_consumption_summary AS
SELECT DISTINCT ON (member_id)
id, site_id, tenant_id, member_id, stat_date,
member_nickname, member_mobile, card_grade_name,
register_date, first_consume_date, last_consume_date,
total_visit_count, total_consume_amount, total_recharge_amount,
total_table_fee, total_goods_amount, total_assistant_amount,
visit_count_7d, visit_count_10d, visit_count_15d,
visit_count_30d, visit_count_60d, visit_count_90d,
consume_amount_7d, consume_amount_10d, consume_amount_15d,
consume_amount_30d, consume_amount_60d, consume_amount_90d,
cash_card_balance, gift_card_balance, total_card_balance,
days_since_last, is_active_7d, is_active_30d, is_active_90d,
customer_tier, created_at, updated_at,
recharge_count_30d, recharge_count_60d, recharge_count_90d,
recharge_amount_30d, recharge_amount_60d, recharge_amount_90d,
avg_ticket_amount
FROM dws.dws_member_consumption_summary
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
ORDER BY member_id, stat_date DESC;
-- 2. v_dws_assistant_customer_stats每对 (assistant_id, member_id) 只取最新快照
CREATE OR REPLACE VIEW app.v_dws_assistant_customer_stats AS
SELECT DISTINCT ON (assistant_id, member_id)
id, site_id, tenant_id, assistant_id, assistant_nickname,
member_id, member_nickname, member_mobile, stat_date,
first_service_date, last_service_date,
total_service_count, total_service_hours, total_service_amount,
service_count_7d, service_count_10d, service_count_15d,
service_count_30d, service_count_60d, service_count_90d,
service_hours_7d, service_hours_10d, service_hours_15d,
service_hours_30d, service_hours_60d, service_hours_90d,
service_amount_7d, service_amount_10d, service_amount_15d,
service_amount_30d, service_amount_60d, service_amount_90d,
days_since_last, is_active_7d, is_active_30d,
created_at, updated_at
FROM dws.dws_assistant_customer_stats
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
ORDER BY assistant_id, member_id, stat_date DESC;
-- 验证 SQL执行后检查:
-- SET app.current_site_id = '<site_id>';
-- 1) SELECT COUNT(*), COUNT(DISTINCT member_id) FROM app.v_dws_member_consumption_summary; -- 两个值应该相等
-- 2) SELECT COUNT(*), COUNT(DISTINCT (assistant_id, member_id)) FROM app.v_dws_assistant_customer_stats; -- 两个值应该相等
-- 3) SELECT member_id, COUNT(*) FROM app.v_dws_member_consumption_summary GROUP BY member_id HAVING COUNT(*) > 1; -- 应返回 0 行
-- 回滚:
-- CREATE OR REPLACE VIEW app.v_dws_member_consumption_summary AS
-- SELECT ... FROM dws.dws_member_consumption_summary WHERE (site_id = ...); -- 去掉 DISTINCT ON 和 ORDER BY
-- CREATE OR REPLACE VIEW app.v_dws_assistant_customer_stats AS
-- SELECT ... FROM dws.dws_assistant_customer_stats WHERE (site_id = ...); -- 同上

View File

@@ -439,8 +439,10 @@ SELECT table_fee_log_id,
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
;
-- CHANGE 2026-04-08 | DISTINCT ON 只取每对 (assistant, member) 最新快照
CREATE OR REPLACE VIEW app.v_dws_assistant_customer_stats AS
SELECT id,
SELECT DISTINCT ON (assistant_id, member_id)
id,
site_id,
tenant_id,
assistant_id,
@@ -478,7 +480,8 @@ SELECT id,
created_at,
updated_at
FROM dws.dws_assistant_customer_stats
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
ORDER BY assistant_id, member_id, stat_date DESC;
;
CREATE OR REPLACE VIEW app.v_dws_assistant_daily_detail AS
@@ -976,8 +979,10 @@ SELECT relation_id,
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
;
-- CHANGE 2026-04-08 | DISTINCT ON 只取每个会员最新快照,避免多 stat_date 行膨胀
CREATE OR REPLACE VIEW app.v_dws_member_consumption_summary AS
SELECT id,
SELECT DISTINCT ON (member_id)
id,
site_id,
tenant_id,
member_id,
@@ -1024,7 +1029,8 @@ SELECT id,
recharge_amount_90d,
avg_ticket_amount
FROM dws.dws_member_consumption_summary
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint);
WHERE (site_id = (current_setting('app.current_site_id'::text))::bigint)
ORDER BY member_id, stat_date DESC;
;
CREATE OR REPLACE VIEW app.v_dws_member_newconv_index AS
@@ -1042,6 +1048,7 @@ SELECT newconv_id,
t_r,
t_a,
visits_14d,
visits_30d,
visits_60d,
visits_total,
spend_30d,
@@ -1167,6 +1174,7 @@ SELECT winback_id,
t_r,
t_a,
visits_14d,
visits_30d,
visits_60d,
visits_total,
spend_30d,

View File

@@ -789,6 +789,7 @@ CREATE TABLE dws.dws_member_newconv_index (
t_r numeric(6,2),
t_a numeric(6,2),
visits_14d integer DEFAULT 0 NOT NULL,
visits_30d integer DEFAULT 0 NOT NULL,
visits_60d integer DEFAULT 0 NOT NULL,
visits_total integer DEFAULT 0 NOT NULL,
spend_30d numeric(14,2) DEFAULT 0 NOT NULL,
@@ -907,6 +908,7 @@ CREATE TABLE dws.dws_member_winback_index (
t_r numeric(6,2),
t_a numeric(6,2),
visits_14d integer DEFAULT 0 NOT NULL,
visits_30d integer DEFAULT 0 NOT NULL,
visits_60d integer DEFAULT 0 NOT NULL,
visits_total integer DEFAULT 0 NOT NULL,
spend_30d numeric(14,2) DEFAULT 0 NOT NULL,
@@ -1297,6 +1299,7 @@ SELECT dws_member_winback_index.site_id,
dws_member_winback_index.t_r,
dws_member_winback_index.t_a,
dws_member_winback_index.visits_14d,
dws_member_winback_index.visits_30d,
dws_member_winback_index.visits_60d,
dws_member_winback_index.visits_total,
dws_member_winback_index.spend_30d,
@@ -1332,6 +1335,7 @@ UNION ALL
dws_member_newconv_index.t_r,
dws_member_newconv_index.t_a,
dws_member_newconv_index.visits_14d,
dws_member_newconv_index.visits_30d,
dws_member_newconv_index.visits_60d,
dws_member_newconv_index.visits_total,
dws_member_newconv_index.spend_30d,

View File

@@ -0,0 +1,11 @@
-- 迁移coach_tasks 添加 completion_type 字段
-- Fix-13区分自动完成auto和手动完成manual
-- 日期2026-04-07
ALTER TABLE biz.coach_tasks
ADD COLUMN IF NOT EXISTS completion_type character varying(10);
COMMENT ON COLUMN biz.coach_tasks.completion_type IS '完成类型auto=系统自动检测到店, manual=助教手动标记';
-- 回滚:
-- ALTER TABLE biz.coach_tasks DROP COLUMN IF EXISTS completion_type;

View File

@@ -16,6 +16,7 @@ CREATE SEQUENCE IF NOT EXISTS biz.cfg_task_generator_params_id_seq AS bigint;
CREATE SEQUENCE IF NOT EXISTS biz.coach_task_history_id_seq AS bigint;
CREATE SEQUENCE IF NOT EXISTS biz.coach_task_transfer_log_id_seq AS bigint;
CREATE SEQUENCE IF NOT EXISTS biz.coach_tasks_id_seq AS bigint;
CREATE SEQUENCE IF NOT EXISTS biz.recall_events_id_seq AS bigint;
CREATE SEQUENCE IF NOT EXISTS biz.connectors_id_seq AS integer;
CREATE SEQUENCE IF NOT EXISTS biz.dws_assistant_task_monthly_id_seq AS bigint;
CREATE SEQUENCE IF NOT EXISTS biz.excel_upload_log_id_seq AS bigint;
@@ -153,6 +154,7 @@ CREATE TABLE biz.coach_tasks (
abandon_reason text,
completed_at timestamp with time zone,
completed_task_type character varying(50),
completion_type character varying(10),
parent_task_id bigint,
created_at timestamp with time zone DEFAULT now(),
updated_at timestamp with time zone DEFAULT now(),
@@ -161,6 +163,17 @@ CREATE TABLE biz.coach_tasks (
transferred_at timestamp with time zone
);
CREATE TABLE biz.recall_events (
id bigint DEFAULT nextval('biz.recall_events_id_seq'::regclass) NOT NULL,
site_id bigint NOT NULL,
assistant_id bigint NOT NULL,
member_id bigint NOT NULL,
pay_time timestamp with time zone NOT NULL,
task_id bigint,
task_type character varying(50),
created_at timestamp with time zone DEFAULT now()
);
CREATE TABLE biz.connectors (
id integer DEFAULT nextval('biz.connectors_id_seq'::regclass) NOT NULL,
connector_key character varying(50) NOT NULL,
@@ -341,6 +354,8 @@ ALTER TABLE biz.dws_assistant_task_monthly ADD CONSTRAINT dws_assistant_task_mon
ALTER TABLE biz.excel_upload_log ADD CONSTRAINT excel_upload_log_pkey PRIMARY KEY (id);
ALTER TABLE biz.notes ADD CONSTRAINT notes_task_id_fkey FOREIGN KEY (task_id) REFERENCES biz.coach_tasks(id);
ALTER TABLE biz.notes ADD CONSTRAINT notes_pkey PRIMARY KEY (id);
ALTER TABLE biz.recall_events ADD CONSTRAINT recall_events_pkey PRIMARY KEY (id);
ALTER TABLE biz.recall_events ADD CONSTRAINT recall_events_task_id_fkey FOREIGN KEY (task_id) REFERENCES biz.coach_tasks(id);
ALTER TABLE biz.salary_adjustments ADD CONSTRAINT salary_adjustments_upload_batch_id_fkey FOREIGN KEY (upload_batch_id) REFERENCES biz.excel_upload_log(id);
ALTER TABLE biz.salary_adjustments ADD CONSTRAINT salary_adjustments_pkey PRIMARY KEY (id);
ALTER TABLE biz.site_code_history ADD CONSTRAINT site_code_history_pkey PRIMARY KEY (id);
@@ -386,5 +401,7 @@ CREATE INDEX idx_task_monthly_site_month ON biz.dws_assistant_task_monthly USING
CREATE INDEX idx_excel_log_site ON biz.excel_upload_log USING btree (site_id, created_at DESC);
CREATE INDEX idx_notes_target ON biz.notes USING btree (site_id, target_type, target_id);
CREATE INDEX idx_salary_adj_assistant_month ON biz.salary_adjustments USING btree (assistant_id, salary_month);
CREATE UNIQUE INDEX idx_recall_events_site_assistant_member_day ON biz.recall_events USING btree (site_id, assistant_id, member_id, (date_trunc('day', pay_time AT TIME ZONE 'Asia/Shanghai')));
CREATE INDEX idx_recall_events_assistant_pay ON biz.recall_events USING btree (site_id, assistant_id, pay_time);
CREATE INDEX idx_salary_adj_site_month ON biz.salary_adjustments USING btree (site_id, salary_month);