Portal::class, 'amount_cents' => 'integer', 'tax_cents' => 'integer', 'total_cents' => 'integer', 'invoice_date' => 'date', 'due_date' => 'date', 'paid_at' => 'datetime', 'raw_snapshot' => 'array', 'pdf_payload' => 'array', 'pdf_generated_at' => 'datetime', 'imported_at' => 'datetime', ]; } /** * @return BelongsTo */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Neueste Rechnung zuerst: nach Rechnungsdatum, dann ID als Tiebreaker. * Single Source of Truth für die „latest legacy invoice"-Ordnung. */ public function scopeLatestFirst(Builder $query): Builder { return $query->orderByDesc('invoice_date')->orderByDesc('id'); } /** * Ohne die erledigten `hold`-Rechnungen (Default in allen Ansichten). */ public function scopeWithoutHold(Builder $query): Builder { return $query->where(function (Builder $query): void { $query->whereNull('status')->orWhere('status', '!=', self::STATUS_HOLD); }); } /** * Noch offene Alt-Vorgänge, die im neuen System abgearbeitet werden. */ public function scopeOpenLegacy(Builder $query): Builder { return $query->whereIn('status', [self::STATUS_PENDING, self::STATUS_REMINDER]); } public function isHold(): bool { return $this->status === self::STATUS_HOLD; } }