From a1ae7caf888c9a8b8d30623c50711e9067b5a3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Wed, 11 Mar 2026 06:57:25 +0000 Subject: [PATCH] feat: add PlatformOrder isReconcileMismatch and reuse in subscription summary --- .../Admin/SiteSubscriptionController.php | 5 +- app/Models/PlatformOrder.php | 9 ++ .../PlatformOrderReconcileMismatchTest.php | 100 ++++++++++++++++++ 3 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 tests/Unit/PlatformOrderReconcileMismatchTest.php diff --git a/app/Http/Controllers/Admin/SiteSubscriptionController.php b/app/Http/Controllers/Admin/SiteSubscriptionController.php index cbf4075..e10ade3 100644 --- a/app/Http/Controllers/Admin/SiteSubscriptionController.php +++ b/app/Http/Controllers/Admin/SiteSubscriptionController.php @@ -74,10 +74,7 @@ class SiteSubscriptionController extends Controller $noReceiptOrders++; } - // reconcile_mismatch 口径:支付回执总额 与订单 paid_amount 不一致(按分取整,差额>=0.01) - $receiptCents = (int) round($receiptTotal * 100); - $paidCents = (int) round(((float) ($o->paid_amount ?? 0)) * 100); - if (abs($receiptCents - $paidCents) >= 1) { + if ($o->isReconcileMismatch()) { $reconcileMismatchOrders++; } diff --git a/app/Models/PlatformOrder.php b/app/Models/PlatformOrder.php index e0a5cbe..fedd461 100644 --- a/app/Models/PlatformOrder.php +++ b/app/Models/PlatformOrder.php @@ -63,6 +63,15 @@ class PlatformOrder extends Model return $paidCents > 0 && $refundCents >= $paidCents; } + public function isReconcileMismatch(): bool + { + // 口径与平台订单列表 reconcile_mismatch 保持一致:支付回执总额 与订单 paid_amount 不一致(按分取整,差额>=0.01) + $receiptCents = (int) round(((float) $this->receiptTotal()) * 100); + $paidCents = (int) round(((float) ($this->paid_amount ?? 0)) * 100); + + return abs($receiptCents - $paidCents) >= 1; + } + protected $fillable = [ 'merchant_id', 'plan_id', 'site_subscription_id', 'created_by_admin_id', 'order_no', 'order_type', 'status', 'payment_status', 'payment_channel', 'plan_name', 'billing_cycle', 'period_months', 'quantity', 'list_amount', diff --git a/tests/Unit/PlatformOrderReconcileMismatchTest.php b/tests/Unit/PlatformOrderReconcileMismatchTest.php new file mode 100644 index 0000000..618cd96 --- /dev/null +++ b/tests/Unit/PlatformOrderReconcileMismatchTest.php @@ -0,0 +1,100 @@ +create([ + 'name' => '单测站点_reconcile', + 'slug' => 'unit-test-merchant-reconcile', + 'status' => 'active', + ]); + + $plan = Plan::query()->create([ + 'code' => 'unit_test_plan_reconcile_mismatch', + 'name' => '单测套餐_reconcile', + 'billing_cycle' => 'monthly', + 'price' => 10, + 'list_price' => 10, + 'status' => 'active', + 'sort' => 10, + 'published_at' => now(), + ]); + + $order = PlatformOrder::query()->create([ + 'merchant_id' => $merchant->id, + 'plan_id' => $plan->id, + 'order_no' => 'PO_UNIT_RECONCILE_MISMATCH_0001', + 'order_type' => 'subscription', + 'status' => 'activated', + 'payment_status' => 'paid', + 'plan_name' => 'Unit Test Plan', + 'billing_cycle' => 'monthly', + 'period_months' => 1, + 'quantity' => 1, + 'payable_amount' => 10, + 'paid_amount' => 10, + 'placed_at' => now(), + 'meta' => [ + 'payment_summary' => [ + 'total_amount' => 9.99, + ], + ], + ]); + + $this->assertTrue($order->isReconcileMismatch()); + } + + public function test_is_reconcile_mismatch_returns_false_when_receipt_total_equals_paid_amount(): void + { + $merchant = Merchant::query()->create([ + 'name' => '单测站点_reconcile_2', + 'slug' => 'unit-test-merchant-reconcile-2', + 'status' => 'active', + ]); + + $plan = Plan::query()->create([ + 'code' => 'unit_test_plan_reconcile_match', + 'name' => '单测套餐_reconcile_2', + 'billing_cycle' => 'monthly', + 'price' => 10, + 'list_price' => 10, + 'status' => 'active', + 'sort' => 10, + 'published_at' => now(), + ]); + + $order = PlatformOrder::query()->create([ + 'merchant_id' => $merchant->id, + 'plan_id' => $plan->id, + 'order_no' => 'PO_UNIT_RECONCILE_MATCH_0001', + 'order_type' => 'subscription', + 'status' => 'activated', + 'payment_status' => 'paid', + 'plan_name' => 'Unit Test Plan', + 'billing_cycle' => 'monthly', + 'period_months' => 1, + 'quantity' => 1, + 'payable_amount' => 10, + 'paid_amount' => 10, + 'placed_at' => now(), + 'meta' => [ + 'payment_summary' => [ + 'total_amount' => 10.00, + ], + ], + ]); + + $this->assertFalse($order->isReconcileMismatch()); + } +}