'datetime', 'ended_at' => 'datetime', 'start_date' => 'date', 'end_date' => 'date', 'next_date' => 'date', 'last_date' => 'date', 'auto_send' => 'boolean', 'send_time' => 'datetime:H:i', 'payment_terms' => PaymentTerms::class, 'frequency' => Frequency::class, 'interval_type' => IntervalType::class, 'month' => Month::class, 'day_of_month' => DayOfMonth::class, 'day_of_week' => DayOfWeek::class, 'end_type' => EndType::class, 'status' => RecurringInvoiceStatus::class, 'discount_method' => DocumentDiscountMethod::class, 'discount_computation' => AdjustmentComputation::class, 'discount_rate' => RateCast::class, 'subtotal' => MoneyCast::class, 'tax_total' => MoneyCast::class, 'discount_total' => MoneyCast::class, 'total' => MoneyCast::class, ]; public function client(): BelongsTo { return $this->belongsTo(Client::class); } public function currency(): BelongsTo { return $this->belongsTo(Currency::class, 'currency_code', 'code'); } public function invoices(): HasMany { return $this->hasMany(Invoice::class, 'recurring_invoice_id'); } public function lineItems(): MorphMany { return $this->morphMany(DocumentLineItem::class, 'documentable'); } public function isDraft(): bool { return $this->status === RecurringInvoiceStatus::Draft; } public function isActive(): bool { return $this->status === RecurringInvoiceStatus::Active; } public function wasApproved(): bool { return $this->approved_at !== null; } public function wasEnded(): bool { return $this->ended_at !== null; } public function isNeverEnding(): bool { return $this->end_type === EndType::Never; } public function canBeApproved(): bool { return $this->isDraft() && ! $this->wasApproved(); } public function canBeEnded(): bool { return $this->isActive() && ! $this->wasEnded(); } public function hasLineItems(): bool { return $this->lineItems()->exists(); } }