meta, 'refund_summary.total_amount'); if ($total !== null) { return (float) $total; } // 回退:遍历 refund_receipts[].amount $refunds = (array) (data_get($this->meta, 'refund_receipts', []) ?? []); $sum = 0.0; foreach ($refunds as $r) { $sum += (float) (data_get($r, 'amount') ?? 0); } return $sum; } public function isRefundInconsistent(): bool { // 口径与平台订单列表 refund_inconsistent 保持一致:按分取整 + 0.01 容差 $refundTotal = (float) $this->refundTotal(); $paidAmount = (float) ($this->paid_amount ?? 0); $refundCents = (int) round($refundTotal * 100); $paidCents = (int) round($paidAmount * 100); if ((string) $this->payment_status === 'refunded') { // 允许 0.01 容差:refund_total + 0.01 < paid return ($refundCents + 1) < $paidCents; } return $paidCents > 0 && $refundCents >= $paidCents; } 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', 'discount_amount', 'payable_amount', 'paid_amount', 'placed_at', 'paid_at', 'activated_at', 'cancelled_at', 'refunded_at', 'plan_snapshot', 'meta', 'remark', ]; protected $casts = [ 'list_amount' => 'decimal:2', 'discount_amount' => 'decimal:2', 'payable_amount' => 'decimal:2', 'paid_amount' => 'decimal:2', 'placed_at' => 'datetime', 'paid_at' => 'datetime', 'activated_at' => 'datetime', 'cancelled_at' => 'datetime', 'refunded_at' => 'datetime', 'plan_snapshot' => 'array', 'meta' => 'array', ]; public function merchant(): BelongsTo { return $this->belongsTo(Merchant::class, 'merchant_id'); } public function plan(): BelongsTo { return $this->belongsTo(Plan::class); } public function siteSubscription(): BelongsTo { return $this->belongsTo(SiteSubscription::class); } public function creator(): BelongsTo { return $this->belongsTo(Admin::class, 'created_by_admin_id'); } }