'date', 'due_date' => 'date', 'subtotal' => 'decimal:2', 'tax_amount' => 'decimal:2', 'discount_amount' => 'decimal:2', 'total_amount' => 'decimal:2', 'paid_amount' => 'decimal:2', 'balance_amount' => 'decimal:2' ]; protected $appends = ['display_status']; public function items(): HasMany { return $this->hasMany(SalesInvoiceItem::class, 'invoice_id'); } public function customer(): BelongsTo { return $this->belongsTo(User::class, 'customer_id'); } public function warehouse(): BelongsTo { return $this->belongsTo(Warehouse::class, 'warehouse_id'); } public function customerDetails(): BelongsTo { return $this->belongsTo(\Workdo\Account\Models\Customer::class, 'customer_id', 'user_id'); } public function paymentAllocations(): HasMany { return $this->hasMany(\Workdo\Account\Models\CustomerPaymentAllocation::class, 'invoice_id'); } public function salesReturns(): HasMany { return $this->hasMany(SalesInvoiceReturn::class, 'original_invoice_id'); } public function isOverdue(): bool { return $this->due_date < now() && $this->status !== 'paid'; } public function getDisplayStatusAttribute(): string { if ($this->isOverdue()) { return 'overdue'; } return $this->status; } protected static function boot() { parent::boot(); static::creating(function ($invoice) { if (empty($invoice->invoice_number)) { $invoice->invoice_number = static::generateInvoiceNumber(); } }); } public static function generateInvoiceNumber(): string { $year = date('Y'); $month = date('m'); $lastInvoice = static::where('invoice_number', 'like', "SI-{$year}-{$month}-%") ->where('created_by', creatorId()) ->orderBy('invoice_number', 'desc') ->first(); if ($lastInvoice) { $lastNumber = (int) substr($lastInvoice->invoice_number, -3); $nextNumber = $lastNumber + 1; } else { $nextNumber = 1; } return "SI-{$year}-{$month}-" . str_pad($nextNumber, 3, '0', STR_PAD_LEFT); } }