Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
6.25% covered (danger)
6.25%
1 / 16
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
PurchasePayment
6.25% covered (danger)
6.25%
1 / 16
20.00% covered (danger)
20.00%
1 / 5
47.37
0.00% covered (danger)
0.00%
0 / 1
 payment_types
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 account
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 purchase_details
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 purchase
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 storePurchasePayment
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace App\Models\admin;
4
5use App\Models\Account;
6use App\Models\PaymentType;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9use Illuminate\Database\Eloquent\Relations\BelongsTo;
10
11class PurchasePayment extends Model
12{
13    use HasFactory;
14
15    protected $table = 'purchase_payments';
16
17    protected $fillable = [
18        'purchase_id',
19        'payment_type_id',
20        'account_id',
21        'total',
22        'paid',
23        'due',
24        'status',
25        'note',
26    ];
27
28    public function payment_types()
29    {
30        return $this->belongsTo(PaymentType::class);
31    }
32
33    public function account()
34    {
35        return $this->belongsTo(Account::class);
36    }
37
38    public function purchase_details()
39    {
40        return $this->belongsTo(PurchaseDetails::class);
41    }
42
43    // BUG FIX: this relation was missing entirely — nothing on PurchasePayment
44    // pointed back to its parent Purchase (only Purchase::purchase_payment()
45    // existed, one-way). The dashboard's whereHas('purchase', ...) queries
46    // need it to filter purchase payments by their purchase's created_at/date.
47    public function purchase(): BelongsTo
48    {
49        return $this->belongsTo(Purchase::class, 'purchase_id');
50    }
51
52    /**
53     * ###########################################
54     * #        Repository Methods Start         #
55     * ###########################################
56     * */
57    public static function storePurchasePayment($purchase, $payment)
58    {
59        $cardTotal = (float) PurchaseDetails::query()->where('purchase_id', $purchase->id)->sum('total');
60        $paid = max(0, (float) $payment['paid']);
61        // `due` is an unsigned column — an overpayment (paid > total) must not
62        // push it negative. Clamp at 0; the extra paid just sits as a supplier
63        // credit (rare, but a plausible fat-finger, and better than a crash).
64        $due = max(0, $cardTotal - $paid);
65
66        return self::query()->create([
67            'purchase_id' => $purchase->id,
68            'payment_type_id' => $payment['payment_type_id'],
69            'total' => $cardTotal,
70            'paid' => $paid,
71            'due' => $due,
72            'status' => $due <= 0 ? 'paid' : ($paid > 0 ? 'partial' : 'unpaid'),
73            'note' => $payment['note'] ?? null,
74        ]);
75    }
76    /**
77     * ###########################################
78     * #        Repository Methods END         #
79     * ###########################################
80     * */
81}