Merge branch 'dev1023' into dev
解决 9 个冲突文件,并修复合并后遗留问题: - 大厅候选集:采用 FIFO 窗口 + 全部置顶单 UNION(列表与抢单/拼单复核同源) - 拼单份额:采用多次参与模型(每次参与 INSERT 新份额、requestId 幂等), 取消后可重新参与;移除 HEAD 已废弃的单行 rejoin 逻辑与对应测试 - 工单迁移与成本中心 103–108 编号撞车:合并重写为 109_work_order_share_participation / 110_work_order_hall_and_shop_indexes; 临时库全量执行与重跑幂等验证通过(10 列、唯一键已删、7 个索引) - 实时补丁:保留个性化字段、置顶重排、分页总数同步;补回 orderTimelineVisible 类型 - 打手大厅:保留 memo 组件化,移植「再拼一次」多份额按钮逻辑 - 全项目表格统一 PercentTable:WorkerOrderShareTable 改造 验证:backend typecheck/lint/check:sql/test(833 pass)、 frontend typecheck/lint/test(172 pass)/build 全绿。
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
-- 109_work_order_share_participation.sql
|
||||
-- 工单拼单份额模型:多次参与 + 份额级问题标记 + 撤单原因/份数。
|
||||
-- (由原 110/111/113/114 四个增量迁移合并重写,纯新增列/索引,不改历史结构。)
|
||||
--
|
||||
-- 目标:
|
||||
-- 1. 同一打手可对同一拼单工单多次参与,每次参与一条 work_order_shares;
|
||||
-- 每份在参与时固化截止时间与超时策略,超时 / 验收 / 撤单按份额独立。
|
||||
-- 2. 后台可对单个份额标记问题单:只影响该份额持有人,母单状态与其他参与者不变。
|
||||
-- 3. 撤单 / 撤份额的原因与份数落库,列表可直接展示「撤 N 份 · 原因」。
|
||||
--
|
||||
-- 兼容性:
|
||||
-- - 只加列 + 回填 + 删「一人一条」唯一键 + 建索引,不拆分历史行、不改历史资金;
|
||||
-- - 历史合并份额(quantity > 1)保持原样,结算公式 quantity × unit_reward 完全兼容;
|
||||
-- - DDL 全部幂等(IF NOT EXISTS / 受控 DROP),可安全重跑。
|
||||
|
||||
ALTER TABLE work_order_shares
|
||||
-- 参与瞬间固化的时限(母单后续改配置不影响这一份)
|
||||
ADD COLUMN IF NOT EXISTS deadline_at TIMESTAMPTZ,
|
||||
ADD COLUMN IF NOT EXISTS timeout_minutes INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS timeout_policy TEXT NOT NULL DEFAULT '',
|
||||
-- 取消来源枚举:timeout / worker_request / admin / problem / settlement
|
||||
ADD COLUMN IF NOT EXISTS cancelled_reason TEXT NOT NULL DEFAULT '',
|
||||
-- 客户端幂等键(一次点击一个);唯一索引只约束非空值
|
||||
ADD COLUMN IF NOT EXISTS request_id TEXT NOT NULL DEFAULT '',
|
||||
-- 份额级问题标记(与份额状态正交;problem_marked_at 为 NULL = 正常)
|
||||
ADD COLUMN IF NOT EXISTS problem_note TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS problem_marked_at TIMESTAMPTZ,
|
||||
ADD COLUMN IF NOT EXISTS problem_marked_by TEXT NOT NULL DEFAULT '',
|
||||
-- 后台撤单 / 撤份额:原因只做展示;份数 0 = 从未撤过
|
||||
ADD COLUMN IF NOT EXISTS cancel_note TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS cancel_quantity INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
COMMENT ON COLUMN work_order_shares.deadline_at IS
|
||||
'本份额截止时间:参与时 = created_at + 母单当时 timeout_minutes;0 分钟为 NULL';
|
||||
COMMENT ON COLUMN work_order_shares.timeout_minutes IS
|
||||
'参与时固化的时限(分钟),母单后续改配置不影响';
|
||||
COMMENT ON COLUMN work_order_shares.timeout_policy IS
|
||||
'参与时固化的超时策略 reopen/cancel_release/cancel_deduct';
|
||||
COMMENT ON COLUMN work_order_shares.cancelled_reason IS
|
||||
'取消来源:timeout/worker_request/admin/problem/settlement';
|
||||
COMMENT ON COLUMN work_order_shares.request_id IS
|
||||
'客户端幂等键(一次点击一个),重复请求返回原份额';
|
||||
COMMENT ON COLUMN work_order_shares.problem_note IS
|
||||
'份额级问题备注(后台标记问题时填写,选填)';
|
||||
COMMENT ON COLUMN work_order_shares.problem_marked_at IS
|
||||
'份额级问题标记时间;NULL = 正常。仅影响该份额持有人展示';
|
||||
COMMENT ON COLUMN work_order_shares.problem_marked_by IS
|
||||
'标记操作人(后台账号显示名)';
|
||||
COMMENT ON COLUMN work_order_shares.cancel_note IS
|
||||
'后台撤单/撤份额时填写的原因(自由文本,选填),仅用于展示';
|
||||
COMMENT ON COLUMN work_order_shares.cancel_quantity IS
|
||||
'被撤掉的份数(撤份额累计 / 单人撤单为整份份数;0 = 未撤过),仅用于展示';
|
||||
|
||||
-- 回填历史份额:按当时母单配置一次性固化(只碰尚未固化的历史行)。
|
||||
UPDATE work_order_shares s
|
||||
SET timeout_minutes = COALESCE(w.timeout_minutes, 0),
|
||||
timeout_policy = COALESCE(NULLIF(w.timeout_policy, ''), 'reopen'),
|
||||
deadline_at = CASE
|
||||
WHEN COALESCE(w.timeout_minutes, 0) > 0
|
||||
THEN s.created_at + (w.timeout_minutes || ' minutes')::interval
|
||||
ELSE NULL
|
||||
END
|
||||
FROM work_orders w
|
||||
WHERE w.id = s.work_order_id
|
||||
AND s.timeout_minutes = 0;
|
||||
|
||||
-- 删除「同一工单同一打手只能一条」约束(否则第二次参与报 23505)。
|
||||
-- 取消的历史份额保留用于追溯,重新参与直接新增一条。
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM pg_constraint
|
||||
WHERE conname = 'work_order_shares_work_order_id_worker_id_key'
|
||||
) THEN
|
||||
ALTER TABLE work_order_shares
|
||||
DROP CONSTRAINT work_order_shares_work_order_id_worker_id_key;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 到期扫描:只覆盖 joined 份额,走部分索引。
|
||||
CREATE INDEX IF NOT EXISTS idx_work_order_shares_due
|
||||
ON work_order_shares (deadline_at)
|
||||
WHERE status = 'joined';
|
||||
|
||||
-- 打手在某工单的份额列表(我的订单展开、押金累计求和)。
|
||||
CREATE INDEX IF NOT EXISTS idx_work_order_shares_worker_order
|
||||
ON work_order_shares (worker_id, work_order_id, created_at DESC);
|
||||
|
||||
-- 母单份额集合推导(recompute 母单状态、剩余份数)。
|
||||
CREATE INDEX IF NOT EXISTS idx_work_order_shares_order_status
|
||||
ON work_order_shares (work_order_id, status, created_at ASC);
|
||||
|
||||
-- 幂等键:同一打手同一个 request_id 只能产生一条份额。
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_work_order_shares_worker_request
|
||||
ON work_order_shares (worker_id, request_id)
|
||||
WHERE request_id <> '';
|
||||
|
||||
-- 打手「问题单」页签筛选与概览统计:按 (worker_id, work_order_id) 探测被标记的份额。
|
||||
CREATE INDEX IF NOT EXISTS idx_work_order_shares_problem_worker
|
||||
ON work_order_shares (worker_id, work_order_id)
|
||||
WHERE problem_marked_at IS NOT NULL;
|
||||
@@ -0,0 +1,25 @@
|
||||
-- 110_work_order_hall_and_shop_indexes.sql
|
||||
-- 工单相关热查询的部分索引(由原 103/106 两个索引迁移合并重写)。
|
||||
--
|
||||
-- 两处查询都已经有明确的 SQL 口径,这里只补与口径完全一致的索引:
|
||||
-- 1. 后台接单工单「按店铺筛选」:BTRIM(o.shop_name) = ANY($n::text[]),
|
||||
-- 普通 btree 无法命中表达式,必须建同表达式索引;
|
||||
-- 2. 抢单大厅候选集:FIFO 窗口之外还要无条件并入全部置顶单,
|
||||
-- 置顶单通常只有个位数,用「open 且 pinned_at 非空」的部分索引即可。
|
||||
-- 全部 IF NOT EXISTS,可安全重跑。
|
||||
|
||||
-- 后台「接单工单 → 店铺」筛选(可多选):表达式索引 + 部分索引省掉空店铺条目。
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_shop_name_trimmed
|
||||
ON orders (BTRIM(shop_name))
|
||||
WHERE BTRIM(shop_name) <> '';
|
||||
|
||||
COMMENT ON INDEX idx_orders_shop_name_trimmed IS
|
||||
'支持后台接单工单按订单店铺(orders.shop_name)精确多选筛选';
|
||||
|
||||
-- 抢单大厅置顶候选集:只索引处于 open 且已置顶的工单 id,避免扫全表。
|
||||
CREATE INDEX IF NOT EXISTS idx_work_orders_hall_pinned
|
||||
ON work_orders (id)
|
||||
WHERE status = 'open' AND pinned_at IS NOT NULL;
|
||||
|
||||
COMMENT ON INDEX idx_work_orders_hall_pinned IS
|
||||
'抢单大厅置顶候选集:open 且 pinned_at 非空的工单 id';
|
||||
Reference in New Issue
Block a user