业绩明细汇总拆开复杂差额规则

月度汇总先按默认差额聚合,只有实收/应付兜底行再计算完整差额原因。7月验证结果一致,汇总耗时由约3.49秒降到0.71秒。
This commit is contained in:
yueyang 2026-10-19 18:15:27 +08:00
parent e4d82dab2a
commit d9535cf9b8

View File

@ -136,6 +136,12 @@ class Pages extends Controller
'未匹配',
];
/** 差额按实收/应付口径兜底时使用的备注;这部分行才需要判断复杂差额原因。 */
private const RECEIPT_BASIS_FALLBACK_REMARKS = [
'订单实付按卖家实收核对',
'订单实付按应付/已付核对',
];
/** 业绩明细「异常标注」筛选项,取值与同步命令写入的标注一致。 */
private const RECEIPT_REMARK_OPTIONS = [
'账单无单号',
@ -502,9 +508,41 @@ class Pages extends Controller
$rules
)) . ')';
return "CASE WHEN remark IN ('订单实付按卖家实收核对','订单实付按应付/已付核对')"
return "CASE WHEN remark IN (" . self::receiptBasisFallbackSqlList() . ')'
. " AND NOT COALESCE({$ruleUnion}, 0) THEN 0"
. ' ELSE COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0)) END';
. ' ELSE ' . self::receiptDefaultDifferenceSql() . ' END';
}
/** 未命中复杂原因时,差额的默认口径。 */
private static function receiptDefaultDifferenceSql(): string
{
return 'COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))';
}
/**
* 口径兜底行的差额修正量:只对「实收/应付核对」行计算复杂规则,
* 避免把京东、京喜、得物、淘系退款等关联子查询放进整月汇总的每一行。
*/
private static function receiptFallbackDifferenceAdjustmentSql(): string
{
$rules = self::receiptDifferenceRemarkConditions();
unset($rules['差额待核实']);
$ruleUnion = '(' . implode(' OR ', array_map(
static fn (string $condition): string => '(' . $condition . ')',
$rules
)) . ')';
return 'CASE WHEN NOT COALESCE(' . $ruleUnion . ', 0) THEN -('
. self::receiptDefaultDifferenceSql() . ') ELSE 0 END';
}
/** @return string SQL 的字符串字面量列表 */
private static function receiptBasisFallbackSqlList(): string
{
return implode(', ', array_map(
static fn (string $remark): string => "'" . str_replace("'", "''", $remark) . "'",
self::RECEIPT_BASIS_FALLBACK_REMARKS
));
}
private static function receiptDifferenceRemark(object $row): ?string
@ -1219,7 +1257,8 @@ class Pages extends Controller
$aggQuery = $base();
$applyFilters($aggQuery);
// 口径兜底行(备注为空、口径对上)的差额按 0 计——与页面行展示、差额筛选同一套判定。
$differenceExpr = self::receiptEffectiveDifferenceSql();
$differenceBaseExpr = self::receiptDefaultDifferenceSql();
$fallbackSql = self::receiptBasisFallbackSqlList();
$agg = $aggQuery->selectRaw("
COUNT(*) as total,
SUM(payment_count) as payments,
@ -1230,13 +1269,24 @@ class Pages extends Controller
SUM(planting_amount) as planting_total,
SUM(product_amount) as goods_total,
SUM(paid_amount) as paid_total,
SUM({$differenceExpr}) as difference_total,
SUM({$differenceBaseExpr}) as difference_base,
SUM(CASE WHEN remark IN ({$fallbackSql}) THEN 1 ELSE 0 END) as basis_fallback_rows,
SUM(CASE WHEN payment_count > 1 THEN 1 ELSE 0 END) as multi_pay,
SUM(CASE WHEN income_amount = 0 THEN 1 ELSE 0 END) as zero_income,
SUM(CASE WHEN match_status = '已匹配' THEN 1 ELSE 0 END) as matched,
SUM(CASE WHEN match_status = '未匹配' THEN 1 ELSE 0 END) as unmatched
")->first();
$total = (int) ($agg->total ?? 0);
$differenceTotal = (float) ($agg->difference_base ?? 0);
if ((int) ($agg->basis_fallback_rows ?? 0) > 0) {
$adjustmentQuery = $base();
$applyFilters($adjustmentQuery);
$adjustment = $adjustmentQuery
->whereIn('remark', self::RECEIPT_BASIS_FALLBACK_REMARKS)
->selectRaw('SUM(' . self::receiptFallbackDifferenceAdjustmentSql() . ') as adjustment')
->first();
$differenceTotal += (float) ($adjustment->adjustment ?? 0);
}
$stats = [
'month' => $month,
@ -1255,7 +1305,7 @@ class Pages extends Controller
'planting_total' => round((float) ($agg->planting_total ?? 0), 2),
'goods_total' => round((float) ($agg->goods_total ?? 0), 2),
'paid_total' => round((float) ($agg->paid_total ?? 0), 2),
'difference_total' => round((float) ($agg->difference_total ?? 0), 2),
'difference_total' => round($differenceTotal, 2),
'per_page' => $limit,
];