diff --git a/app/Http/Controllers/Admin/PlatformOrderController.php b/app/Http/Controllers/Admin/PlatformOrderController.php index 66fbdd2..0563ff6 100644 --- a/app/Http/Controllers/Admin/PlatformOrderController.php +++ b/app/Http/Controllers/Admin/PlatformOrderController.php @@ -155,6 +155,8 @@ class PlatformOrderController extends Controller 'receipt_status' => trim((string) $request->query('receipt_status', '')), // 退款轨迹筛选:has(有退款)/none(无退款) 'refund_status' => trim((string) $request->query('refund_status', '')), + // 退款数据不一致(可治理):基于 refund_summary.total_amount 与 paid_amount 对比 + 'refund_inconsistent' => (string) $request->query('refund_inconsistent', ''), ]; @@ -328,6 +330,13 @@ class PlatformOrderController extends Controller return $this->applyFilters(PlatformOrder::query(), $mismatchFilters)->count(); })(), + // 退款数据不一致订单数(在当前筛选范围基础上叠加 inconsistent 口径) + 'refund_inconsistent_orders' => (function () use ($filters) { + $f = $filters; + $f['refund_inconsistent'] = '1'; + + return $this->applyFilters(PlatformOrder::query(), $f)->count(); + })(), ], 'failedReasonStats' => $failedReasonStats, ]); @@ -634,6 +643,8 @@ class PlatformOrderController extends Controller 'receipt_status' => trim((string) $request->query('receipt_status', '')), // 退款轨迹筛选:has(有退款)/none(无退款) 'refund_status' => trim((string) $request->query('refund_status', '')), + // 退款数据不一致(可治理):基于 refund_summary.total_amount 与 paid_amount 对比 + 'refund_inconsistent' => (string) $request->query('refund_inconsistent', ''), ]; @@ -823,6 +834,7 @@ class PlatformOrderController extends Controller 'reconcile_mismatch' => (string) $request->input('reconcile_mismatch', ''), 'receipt_status' => trim((string) $request->input('receipt_status', '')), 'refund_status' => trim((string) $request->input('refund_status', '')), + 'refund_inconsistent' => (string) $request->input('refund_inconsistent', ''), ]; // 防误操作:批量同步默认要求先勾选“只看可同步”,避免无意识扩大处理范围 @@ -967,6 +979,7 @@ class PlatformOrderController extends Controller 'reconcile_mismatch' => (string) $request->input('reconcile_mismatch', ''), 'receipt_status' => trim((string) $request->input('receipt_status', '')), 'refund_status' => trim((string) $request->input('refund_status', '')), + 'refund_inconsistent' => (string) $request->input('refund_inconsistent', ''), ]; // 防误操作:批量“仅标记为已生效”默认要求当前筛选口径为「已支付 + 待处理(pending)」 @@ -1088,6 +1101,7 @@ class PlatformOrderController extends Controller 'reconcile_mismatch' => (string) $request->input('reconcile_mismatch', ''), 'receipt_status' => trim((string) $request->input('receipt_status', '')), 'refund_status' => trim((string) $request->input('refund_status', '')), + 'refund_inconsistent' => (string) $request->input('refund_inconsistent', ''), ]; $query = PlatformOrder::query() @@ -1277,6 +1291,46 @@ class PlatformOrderController extends Controller $builder->whereRaw("JSON_EXTRACT(meta, '$.refund_summary.total_amount') IS NULL") ->whereRaw("JSON_EXTRACT(meta, '$.refund_receipts[0].amount') IS NULL"); } + }) + ->when(($filters['refund_inconsistent'] ?? '') !== '', function (Builder $builder) { + // 退款数据不一致(可治理): + // - 状态=refunded 但 退款总额 < 已付金额(允许 0.01 容差) + // - 状态!=refunded 且 已付金额>0 且 退款总额 >= 已付金额 + // 退款总额口径:优先 refund_summary.total_amount;缺省回退汇总 refund_receipts[].amount + $driver = $builder->getQuery()->getConnection()->getDriverName(); + + if ($driver === 'sqlite') { + $refundTotalExpr = "(CASE WHEN JSON_EXTRACT(meta, '$.refund_summary.total_amount') IS NOT NULL THEN CAST(JSON_EXTRACT(meta, '$.refund_summary.total_amount') AS REAL) ELSE (SELECT IFNULL(SUM(CAST(JSON_EXTRACT(value, '$.amount') AS REAL)), 0) FROM json_each(COALESCE(JSON_EXTRACT(meta, '$.refund_receipts'), '[]'))) END)"; + + $builder->where(function (Builder $q) use ($refundTotalExpr) { + // refunded 但退款不够 + $q->where(function (Builder $q2) use ($refundTotalExpr) { + $q2->where('payment_status', 'refunded') + ->whereRaw("paid_amount > 0") + ->whereRaw("(ROUND($refundTotalExpr * 100) + 1) < ROUND(paid_amount * 100)"); + }) + // 非 refunded 但退款已达到/超过已付 + ->orWhere(function (Builder $q2) use ($refundTotalExpr) { + $q2->where('payment_status', '!=', 'refunded') + ->whereRaw("paid_amount > 0") + ->whereRaw("ROUND($refundTotalExpr * 100) >= ROUND(paid_amount * 100)"); + }); + }); + } else { + $refundTotalExpr = "(CASE WHEN JSON_EXTRACT(meta, '$.refund_summary.total_amount') IS NOT NULL THEN CAST(JSON_UNQUOTE(JSON_EXTRACT(meta, '$.refund_summary.total_amount')) AS DECIMAL(12,2)) ELSE (SELECT IFNULL(SUM(j.amount), 0) FROM JSON_TABLE(meta, '$.refund_receipts[*]' COLUMNS(amount DECIMAL(12,2) PATH '$.amount')) j) END)"; + + $builder->where(function (Builder $q) use ($refundTotalExpr) { + $q->where(function (Builder $q2) use ($refundTotalExpr) { + $q2->where('payment_status', 'refunded') + ->whereRaw("paid_amount > 0") + ->whereRaw("(ROUND($refundTotalExpr * 100) + 1) < ROUND(paid_amount * 100)"); + })->orWhere(function (Builder $q2) use ($refundTotalExpr) { + $q2->where('payment_status', '!=', 'refunded') + ->whereRaw("paid_amount > 0") + ->whereRaw("ROUND($refundTotalExpr * 100) >= ROUND(paid_amount * 100)"); + }); + }); + } }); } diff --git a/resources/views/admin/platform_orders/index.blade.php b/resources/views/admin/platform_orders/index.blade.php index a3f8353..125ebb1 100644 --- a/resources/views/admin/platform_orders/index.blade.php +++ b/resources/views/admin/platform_orders/index.blade.php @@ -34,6 +34,8 @@ 无退款 | 对账不一致 + | + 退款不一致 @@ -106,6 +108,10 @@ 只看对账不一致(回执总额≠已付金额) +