f35e1a3ba5
含现场提货入账、零应付仍出账、核对补生成,以及线上历史账单修复 SQL。
196 lines
6.9 KiB
SQL
196 lines
6.9 KiB
SQL
-- =============================================================================
|
|
-- 酒厂账单一次性修复(v4.0.6)
|
|
-- 库:生产 dukang_prod(也可在已同步的本地 dukang_haoke 先演练)
|
|
--
|
|
-- 规则(与代码一致):
|
|
-- 起点 WINERY_BILL_EPOCH_YMD = 2026-08-01
|
|
-- 周期 WINERY_SETTLEMENT_PERIOD_DAYS = 3
|
|
-- 出账日 8/4、8/7、8/10 … ;纳入窗口 [出账日-3, 出账日)
|
|
-- 订单:status=COMPLETED AND pay_status=PAID
|
|
-- delivery_type IN ('LOCAL','CROSS_CITY','ON_SITE_PICKUP')
|
|
-- 账期归属:completed_at(缺则 paid_at)的北京日历日
|
|
-- 应付 = ROUND(实付合计 × 0.3, 2);出账日无单仍留账单(无需打款)
|
|
-- 已打款账单不改明细
|
|
-- 起点之前已入账的订单(如 7/28 同城挂在 7/31)保持原账单,不迁到 8/4
|
|
--
|
|
-- 本脚本会:
|
|
-- 1) 补现场提货等缺 completed_at 的已完成单
|
|
-- 2) 按周期补齐出账日账单(含中间应付为 0 的空账)
|
|
-- 3) 把未入账 / 挂错期(如 8/29)的同城、跨城、现场提货订单迁入对应出账日
|
|
-- 4) 按明细重算未打款表头
|
|
-- 5) 删除未打款、无明细、且非周期日的空账单(7/29、8/1、8/29 等)
|
|
--
|
|
-- 建议:先部署含「每 3 天出一期」的 API,再跑本脚本。
|
|
-- 若必须先修数据:跑完后尽快发版,避免旧「每日只收 D-3 当天」任务回刷 8/28。
|
|
--
|
|
-- 用法(生产):
|
|
-- mysql -u... -p dukang_prod < fix-winery-bills-v406.sql
|
|
-- =============================================================================
|
|
|
|
START TRANSACTION;
|
|
|
|
-- 1) 现场提货等:支付即完成但未写 completed_at
|
|
UPDATE user_order
|
|
SET completed_at = paid_at
|
|
WHERE status = 'COMPLETED'
|
|
AND pay_status = 'PAID'
|
|
AND completed_at IS NULL
|
|
AND paid_at IS NOT NULL;
|
|
|
|
-- 2) 补齐周期出账日(8/4 起至「今天北京日」能落到的最后一张)
|
|
INSERT INTO winery_bill (
|
|
bill_no, bill_date, order_count, order_amount, winery_rate, winery_amount, status, created_at
|
|
)
|
|
WITH RECURSIVE issue_days AS (
|
|
SELECT DATE('2026-08-04') AS issue_ymd
|
|
UNION ALL
|
|
SELECT DATE_ADD(issue_ymd, INTERVAL 3 DAY)
|
|
FROM issue_days
|
|
WHERE DATE_ADD(issue_ymd, INTERVAL 3 DAY) <= DATE(DATE_ADD(UTC_TIMESTAMP(), INTERVAL 8 HOUR))
|
|
)
|
|
SELECT
|
|
CONCAT('WBFIX', DATE_FORMAT(d.issue_ymd, '%Y%m%d')) AS bill_no,
|
|
TIMESTAMP(DATE_ADD(d.issue_ymd, INTERVAL -8 HOUR)) AS bill_date,
|
|
0,
|
|
0.00,
|
|
0.3000,
|
|
0.00,
|
|
'UNPAID',
|
|
TIMESTAMP(DATE_ADD(d.issue_ymd, INTERVAL -8 HOUR))
|
|
FROM issue_days d
|
|
WHERE NOT EXISTS (
|
|
SELECT 1
|
|
FROM winery_bill b
|
|
WHERE b.bill_date = TIMESTAMP(DATE_ADD(d.issue_ymd, INTERVAL -8 HOUR))
|
|
);
|
|
|
|
-- 3) 起点日及之后:从未打款账单上拿掉挂错期的明细(已打款账单因 status 过滤不会动)
|
|
DELETE i
|
|
FROM winery_bill_item i
|
|
INNER JOIN winery_bill b ON b.id = i.winery_bill_id
|
|
INNER JOIN user_order o ON o.id = i.order_id
|
|
INNER JOIN winery_bill target
|
|
ON target.bill_date = TIMESTAMP(DATE_ADD(
|
|
DATE_ADD(
|
|
DATE('2026-08-01'),
|
|
INTERVAL (FLOOR(DATEDIFF(
|
|
DATE(CONVERT_TZ(COALESCE(o.completed_at, o.paid_at), '+00:00', '+08:00')),
|
|
DATE('2026-08-01')
|
|
) / 3) + 1) * 3 DAY
|
|
),
|
|
INTERVAL -8 HOUR
|
|
))
|
|
WHERE b.status = 'UNPAID'
|
|
AND b.id <> target.id
|
|
AND o.status = 'COMPLETED'
|
|
AND o.pay_status = 'PAID'
|
|
AND o.delivery_type IN ('LOCAL', 'CROSS_CITY', 'ON_SITE_PICKUP')
|
|
AND COALESCE(o.completed_at, o.paid_at) IS NOT NULL
|
|
AND DATE(CONVERT_TZ(COALESCE(o.completed_at, o.paid_at), '+00:00', '+08:00')) >= '2026-08-01';
|
|
|
|
-- 4) 把未入账的同城/跨城/现场提货订单写入对应周期账单
|
|
INSERT INTO winery_bill_item (
|
|
winery_bill_id, order_id, order_no, delivery_type, pay_amount, winery_amount, paid_at, created_at
|
|
)
|
|
SELECT
|
|
target.id,
|
|
o.id,
|
|
o.order_no,
|
|
o.delivery_type,
|
|
o.pay_amount,
|
|
ROUND(o.pay_amount * 0.3, 2),
|
|
COALESCE(o.paid_at, o.completed_at),
|
|
UTC_TIMESTAMP(3)
|
|
FROM user_order o
|
|
INNER JOIN winery_bill target
|
|
ON target.bill_date = TIMESTAMP(DATE_ADD(
|
|
DATE_ADD(
|
|
DATE('2026-08-01'),
|
|
INTERVAL (FLOOR(DATEDIFF(
|
|
DATE(CONVERT_TZ(COALESCE(o.completed_at, o.paid_at), '+00:00', '+08:00')),
|
|
DATE('2026-08-01')
|
|
) / 3) + 1) * 3 DAY
|
|
),
|
|
INTERVAL -8 HOUR
|
|
))
|
|
LEFT JOIN winery_bill_item existing ON existing.order_id = o.id
|
|
WHERE o.status = 'COMPLETED'
|
|
AND o.pay_status = 'PAID'
|
|
AND o.delivery_type IN ('LOCAL', 'CROSS_CITY', 'ON_SITE_PICKUP')
|
|
AND COALESCE(o.completed_at, o.paid_at) IS NOT NULL
|
|
AND DATE(CONVERT_TZ(COALESCE(o.completed_at, o.paid_at), '+00:00', '+08:00')) >= '2026-08-01'
|
|
AND existing.id IS NULL;
|
|
|
|
-- 5) 按明细重算所有未打款表头(应付为 0 的周期账单也保留)
|
|
UPDATE winery_bill b
|
|
LEFT JOIN (
|
|
SELECT
|
|
winery_bill_id,
|
|
COUNT(*) AS order_count,
|
|
ROUND(SUM(pay_amount), 2) AS order_amount
|
|
FROM winery_bill_item
|
|
GROUP BY winery_bill_id
|
|
) x ON x.winery_bill_id = b.id
|
|
SET
|
|
b.order_count = IFNULL(x.order_count, 0),
|
|
b.order_amount = IFNULL(x.order_amount, 0.00),
|
|
b.winery_rate = 0.3000,
|
|
b.winery_amount = ROUND(IFNULL(x.order_amount, 0) * 0.3, 2)
|
|
WHERE b.status = 'UNPAID';
|
|
|
|
-- 6) 清掉误生成的非周期日空账单(有明细的如 7/31 保留;8/1 虽 MOD=0 但未满 3 天,仍删)
|
|
DELETE b
|
|
FROM winery_bill b
|
|
LEFT JOIN winery_bill_item i ON i.winery_bill_id = b.id
|
|
WHERE b.status = 'UNPAID'
|
|
AND i.id IS NULL
|
|
AND NOT (
|
|
DATEDIFF(DATE(CONVERT_TZ(b.bill_date, '+00:00', '+08:00')), DATE('2026-08-01')) >= 3
|
|
AND MOD(DATEDIFF(DATE(CONVERT_TZ(b.bill_date, '+00:00', '+08:00')), DATE('2026-08-01')), 3) = 0
|
|
);
|
|
|
|
COMMIT;
|
|
|
|
-- -----------------------------------------------------------------------------
|
|
-- 核对(不改数据)
|
|
-- -----------------------------------------------------------------------------
|
|
SELECT '=== 账单列表 ===' AS s;
|
|
SELECT
|
|
DATE(CONVERT_TZ(bill_date, '+00:00', '+08:00')) AS bill_ymd,
|
|
bill_no,
|
|
order_count,
|
|
order_amount,
|
|
winery_amount,
|
|
status
|
|
FROM winery_bill
|
|
ORDER BY bill_date;
|
|
|
|
SELECT '=== 明细按配送类型 ===' AS s;
|
|
SELECT delivery_type, COUNT(*) AS cnt, ROUND(SUM(pay_amount), 2) AS pay_sum
|
|
FROM winery_bill_item
|
|
GROUP BY delivery_type;
|
|
|
|
SELECT '=== 应入账但未入账(应为 0 行)===' AS s;
|
|
SELECT o.id, o.order_no, o.delivery_type, o.pay_amount,
|
|
DATE(CONVERT_TZ(COALESCE(o.completed_at, o.paid_at), '+00:00', '+08:00')) AS attr_ymd
|
|
FROM user_order o
|
|
LEFT JOIN winery_bill_item i ON i.order_id = o.id
|
|
WHERE o.status = 'COMPLETED'
|
|
AND o.pay_status = 'PAID'
|
|
AND o.delivery_type IN ('LOCAL', 'CROSS_CITY', 'ON_SITE_PICKUP')
|
|
AND i.id IS NULL;
|
|
|
|
SELECT '=== 非周期日仍在的账单(仅允许起点前已入账的,如 7/31)===' AS s;
|
|
SELECT
|
|
DATE(CONVERT_TZ(bill_date, '+00:00', '+08:00')) AS bill_ymd,
|
|
bill_no,
|
|
order_count,
|
|
order_amount,
|
|
status
|
|
FROM winery_bill
|
|
WHERE NOT (
|
|
DATEDIFF(DATE(CONVERT_TZ(bill_date, '+00:00', '+08:00')), DATE('2026-08-01')) >= 3
|
|
AND MOD(DATEDIFF(DATE(CONVERT_TZ(bill_date, '+00:00', '+08:00')), DATE('2026-08-01')), 3) = 0
|
|
)
|
|
ORDER BY bill_date;
|