107 lines
3.3 KiB
PHP
107 lines
3.3 KiB
PHP
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||
|
||
class PlatformOrder extends Model
|
||
{
|
||
use HasFactory;
|
||
|
||
public function receiptTotal(): float
|
||
{
|
||
// 优先读扁平字段 payment_summary.total_amount(更稳定、避免遍历 receipts)
|
||
$total = (float) (data_get($this->meta, 'payment_summary.total_amount') ?? 0);
|
||
if ($total > 0) {
|
||
return $total;
|
||
}
|
||
|
||
// 回退:遍历 payment_receipts[].amount
|
||
$receipts = (array) (data_get($this->meta, 'payment_receipts', []) ?? []);
|
||
$sum = 0.0;
|
||
foreach ($receipts as $r) {
|
||
$sum += (float) (data_get($r, 'amount') ?? 0);
|
||
}
|
||
|
||
return $sum;
|
||
}
|
||
|
||
public function refundTotal(): float
|
||
{
|
||
// 优先读扁平字段 refund_summary.total_amount
|
||
$total = data_get($this->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');
|
||
}
|
||
}
|