Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
84.62% covered (warning)
84.62%
11 / 13
81.82% covered (warning)
81.82%
9 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Order
84.62% covered (warning)
84.62%
11 / 13
81.82% covered (warning)
81.82%
9 / 11
11.44
0.00% covered (danger)
0.00%
0 / 1
 auditName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 auditExcept
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 auditLabel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 customer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 details
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 branch
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 warehouse
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 payment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 statusEnum
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 invoiceNumber
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 grandTotal
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Models;
4
5use App\Enums\OrderStatus;
6use App\Support\Auditable;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9
10class Order extends Model
11{
12    use Auditable, HasFactory;
13
14    protected function auditName(): string
15    {
16        return 'order';
17    }
18
19    protected function auditExcept(): array
20    {
21        return ['qr_code', 'bar_code'];
22    }
23
24    protected function auditLabel(): ?string
25    {
26        return $this->invoice_no ?? $this->order_number ?? ('#' . $this->getKey());
27    }
28
29    protected $table = 'orders';
30
31    protected $fillable = [
32        'customer_id',
33        'branch_id',
34        'warehouse_id',
35        'qr_code',
36        'bar_code',
37        'total',
38        'discount',
39        'tax',
40        'coupon_code',
41        'shipping_cost',
42        'due',
43        'status',
44        'payment_status',
45        'note',
46        'deliver_date',
47        'courier_name',
48        'tracking_number',
49    ];
50
51    public function customer()
52    {
53        return $this->belongsTo(Customer::class, 'customer_id', 'id');
54    }
55
56    public function details()
57    {
58        return $this->hasMany(OrderDetails::class, 'order_id');
59    }
60
61    public function branch()
62    {
63        return $this->belongsTo(Branch::class);
64    }
65
66    public function warehouse()
67    {
68        return $this->belongsTo(Warehouse::class);
69    }
70
71    public function payment()
72    {
73        return $this->hasMany(Payment::class, 'order_id', 'id');
74    }
75
76    /**
77     * `status` stays a plain string column (see App\Enums\OrderStatus) —
78     * this is a convenience lookup for views/services that want the
79     * label/color/icon, defaulting to Pending for anything unrecognised.
80     */
81    public function statusEnum(): OrderStatus
82    {
83        return OrderStatus::fromStored($this->status);
84    }
85
86    /**
87     * The invoice number is deliberately not stored — it's derived from the
88     * order id plus the two Settings → Checkout & Delivery fields
89     * (prefix/digit count), so numbering stays sequential in creation order
90     * with zero risk of a race condition from a separate counter, and
91     * changing the prefix/padding later doesn't require a migration.
92     */
93    public function invoiceNumber(): string
94    {
95        $prefix = settings('checkout.invoice_number_prefix', 'INV-');
96        $padding = (int) settings('checkout.invoice_number_padding', 5);
97
98        return $prefix . str_pad((string) $this->id, $padding, '0', STR_PAD_LEFT);
99    }
100
101    /** Grand total including the Phase 7 discount/tax columns — the one place this math should live. */
102    public function grandTotal(): float
103    {
104        return round(((float) $this->total) - ((float) $this->discount) + ((float) $this->tax) + ((float) $this->shipping_cost), 2);
105    }
106}