UnitAccountPayableService.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. namespace App\Services;
  3. use App\Models\UnitAccountPayable;
  4. use Carbon\Carbon;
  5. use Illuminate\Database\Eloquent\Collection;
  6. use Illuminate\Validation\ValidationException;
  7. /**
  8. * Contas a Pagar da unidade.
  9. *
  10. * Registros com origin='tbr' são criados automaticamente quando a matriz gera a
  11. * cobrança do TBR (espelho da dívida). Registros avulsos usam origin='manual'.
  12. * A baixa é manual (Asaas não cobra a unidade de si mesma).
  13. */
  14. class UnitAccountPayableService
  15. {
  16. public function list(int $unitId, array $filters = []): Collection
  17. {
  18. return UnitAccountPayable::where('unit_id', $unitId)
  19. ->when(
  20. isset($filters['status']),
  21. fn ($q) => $q->where('status', $filters['status']),
  22. )
  23. ->when(
  24. isset($filters['origin']),
  25. fn ($q) => $q->where('origin', $filters['origin']),
  26. )
  27. ->orderBy('due_date')
  28. ->get();
  29. }
  30. public function findForUnit(int $id, int $unitId): ?UnitAccountPayable
  31. {
  32. return UnitAccountPayable::where('id', $id)
  33. ->where('unit_id', $unitId)
  34. ->first();
  35. }
  36. public function createManual(int $unitId, array $data): UnitAccountPayable
  37. {
  38. return UnitAccountPayable::create([
  39. 'unit_id' => $unitId,
  40. 'origin' => UnitAccountPayable::ORIGIN_MANUAL,
  41. 'history' => $data['history'],
  42. 'value' => $data['value'],
  43. 'due_date' => $data['due_date'],
  44. 'obs' => $data['obs'] ?? null,
  45. 'paid_value' => 0,
  46. 'discount' => 0,
  47. 'fine' => 0,
  48. 'status' => 'pending',
  49. ]);
  50. }
  51. /**
  52. * Baixa manual: marca a conta como paga.
  53. */
  54. public function settle(UnitAccountPayable $payable, array $data): UnitAccountPayable
  55. {
  56. if ($payable->status === 'paid') {
  57. throw ValidationException::withMessages([
  58. 'status' => 'Esta conta já está paga.',
  59. ]);
  60. }
  61. if ($payable->status === 'cancelled') {
  62. throw ValidationException::withMessages([
  63. 'status' => 'Esta conta está cancelada e não pode receber baixa.',
  64. ]);
  65. }
  66. $discount = isset($data['discount']) ? (float) $data['discount'] : (float) $payable->discount;
  67. $fine = isset($data['fine']) ? (float) $data['fine'] : (float) $payable->fine;
  68. $paidValue = isset($data['paid_value'])
  69. ? (float) $data['paid_value']
  70. : round((float) $payable->value - $discount + $fine, 2);
  71. $payable->update([
  72. 'status' => 'paid',
  73. 'discount' => $discount,
  74. 'fine' => $fine,
  75. 'paid_value' => $paidValue,
  76. 'payment_date' => $data['payment_date'] ?? Carbon::today()->format('Y-m-d'),
  77. ]);
  78. return $payable->fresh();
  79. }
  80. /**
  81. * Reabre uma conta paga (estorno da baixa manual).
  82. */
  83. public function reopen(UnitAccountPayable $payable): UnitAccountPayable
  84. {
  85. if ($payable->status !== 'paid') {
  86. throw ValidationException::withMessages([
  87. 'status' => 'Só é possível reabrir contas que estão pagas.',
  88. ]);
  89. }
  90. $payable->update([
  91. 'status' => 'pending',
  92. 'paid_value' => 0,
  93. 'payment_date' => null,
  94. ]);
  95. return $payable->fresh();
  96. }
  97. }