'date', 'due_date' => 'date', 'status' => InvoiceStatus::class, 'subtotal' => MoneyCast::class, 'tax_total' => MoneyCast::class, 'discount_total' => MoneyCast::class, 'total' => MoneyCast::class, 'amount_paid' => MoneyCast::class, 'amount_due' => MoneyCast::class, ]; public function client(): BelongsTo { return $this->belongsTo(Client::class); } public function lineItems(): MorphMany { return $this->morphMany(DocumentLineItem::class, 'documentable'); } public function payments(): MorphMany { return $this->morphMany(Payment::class, 'payable'); } public function isDraft(): bool { return $this->status === InvoiceStatus::Draft; } public function canRecordPayment(): bool { return ! in_array($this->status, [ InvoiceStatus::Draft, InvoiceStatus::Paid, InvoiceStatus::Overpaid, InvoiceStatus::Void, ]); } public static function getNextDocumentNumber(): string { $company = auth()->user()->currentCompany; if (! $company) { throw new \RuntimeException('No current company is set for the user.'); } $defaultInvoiceSettings = $company->defaultInvoice; $numberPrefix = $defaultInvoiceSettings->number_prefix; $numberDigits = $defaultInvoiceSettings->number_digits; $latestDocument = static::query() ->whereNotNull('invoice_number') ->latest('invoice_number') ->first(); $lastNumberNumericPart = $latestDocument ? (int) substr($latestDocument->invoice_number, strlen($numberPrefix)) : 0; $numberNext = $lastNumberNumericPart + 1; return $defaultInvoiceSettings->getNumberNext( padded: true, format: true, prefix: $numberPrefix, digits: $numberDigits, next: $numberNext ); } }