- Removido README.md padrão do Laravel (backend) - Removidos scripts de deploy (não mais necessários) - Atualizado copilot-instructions.md para novo fluxo - Adicionada documentação de auditoria do servidor - Sincronizado código de produção com repositório Novo workflow: - Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney) - Mudanças PHP são instantâneas - Mudanças React requerem 'npm run build' - Commit após validação funcional
148 lines
3.8 KiB
PHP
Executable File
148 lines
3.8 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
class LiabilityInstallment extends Model
|
|
{
|
|
use HasFactory, SoftDeletes;
|
|
|
|
/**
|
|
* Status da parcela
|
|
*/
|
|
public const STATUS_PENDING = 'pending';
|
|
public const STATUS_PAID = 'paid';
|
|
public const STATUS_PARTIAL = 'partial';
|
|
public const STATUS_OVERDUE = 'overdue';
|
|
public const STATUS_CANCELLED = 'cancelled';
|
|
|
|
public const STATUSES = [
|
|
self::STATUS_PENDING => '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());
|
|
});
|
|
}
|
|
}
|