'Pendente', self::STATUS_PAID => 'Pago', self::STATUS_PARTIAL => 'Parcial', self::STATUS_OVERDUE => 'Atrasado', self::STATUS_CANCELLED => 'Cancelado', ]; protected $fillable = [ 'liability_account_id', 'installment_number', 'due_date', 'installment_amount', 'principal_amount', 'interest_amount', 'fee_amount', 'paid_amount', 'paid_date', 'status', 'reconciled_transaction_id', 'payment_account_id', 'notes', ]; protected $casts = [ 'due_date' => 'date', 'paid_date' => 'date', 'installment_amount' => 'decimal:2', 'principal_amount' => 'decimal:2', 'interest_amount' => 'decimal:2', 'fee_amount' => 'decimal:2', 'paid_amount' => 'decimal:2', ]; protected $appends = ['is_overdue', 'days_until_due']; /** * Relação com o contrato passivo */ public function liabilityAccount(): BelongsTo { return $this->belongsTo(LiabilityAccount::class); } /** * Relação com a conta usada para pagamento */ public function paymentAccount(): BelongsTo { return $this->belongsTo(Account::class, 'payment_account_id'); } /** * Verificar se está atrasado */ public function getIsOverdueAttribute(): bool { if ($this->status === self::STATUS_PAID) { return false; } return $this->due_date->isPast(); } /** * Dias até o vencimento (negativo se atrasado) */ public function getDaysUntilDueAttribute(): int { return now()->startOfDay()->diffInDays($this->due_date, false); } /** * Marcar como pago */ public function markAsPaid(?float $amount = null, ?\DateTime $paidDate = null, ?int $paymentAccountId = null): void { $this->paid_amount = $amount ?? $this->installment_amount; $this->paid_date = $paidDate ?? now(); $this->payment_account_id = $paymentAccountId; $this->status = self::STATUS_PAID; $this->save(); // Recalcular totais do contrato $this->liabilityAccount->recalculateTotals(); } /** * Atualizar status baseado na data de vencimento */ public function updateOverdueStatus(): void { if ($this->status === self::STATUS_PENDING && $this->is_overdue) { $this->status = self::STATUS_OVERDUE; $this->save(); } } /** * Scope para parcelas pendentes */ public function scopePending($query) { return $query->where('status', self::STATUS_PENDING); } /** * Scope para parcelas pagas */ public function scopePaid($query) { return $query->where('status', self::STATUS_PAID); } /** * Scope para parcelas atrasadas */ public function scopeOverdue($query) { return $query->where('status', self::STATUS_OVERDUE) ->orWhere(function ($q) { $q->where('status', self::STATUS_PENDING) ->where('due_date', '<', now()->startOfDay()); }); } }