FranchisorReceivableService.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace App\Services;
  3. use App\Enums\NotificationType;
  4. use App\Jobs\SyncFranchiseeChargeJob;
  5. use App\Models\CompanyPaymentAccount;
  6. use App\Models\FranchiseeAccountReceive;
  7. use App\Models\UnitAccountPayable;
  8. use Carbon\Carbon;
  9. use Exception;
  10. use Illuminate\Support\Facades\DB;
  11. use Illuminate\Validation\ValidationException;
  12. class FranchisorReceivableService
  13. {
  14. public function __construct(
  15. protected NotificationService $notifications,
  16. ) {}
  17. public function createManual(array $data): FranchiseeAccountReceive
  18. {
  19. return DB::transaction(function () use ($data) {
  20. $unitId = $data['account_type'] === 'unit' ? (int) $data['unit_id'] : null;
  21. $receivable = FranchiseeAccountReceive::create([
  22. 'unit_id' => $unitId,
  23. 'tbr_calculation_id' => null,
  24. 'financial_plan_account_id' => $data['financial_plan_account_id'] ?? null,
  25. 'origin' => $unitId ? 'manual_unit' : 'manual_internal',
  26. 'history' => $data['history'],
  27. 'value' => $data['value'],
  28. 'paid_value' => 0,
  29. 'due_date' => $data['due_date'],
  30. 'discount' => 0,
  31. 'fees' => 0,
  32. 'obs' => $data['obs'] ?? null,
  33. 'status' => 'pending',
  34. ]);
  35. if ($unitId) {
  36. UnitAccountPayable::create([
  37. 'unit_id' => $unitId,
  38. 'franchisee_account_receive_id' => $receivable->id,
  39. 'origin' => UnitAccountPayable::ORIGIN_MANUAL,
  40. 'history' => $receivable->history,
  41. 'value' => $receivable->value,
  42. 'paid_value' => 0,
  43. 'discount' => 0,
  44. 'fine' => 0,
  45. 'due_date' => $receivable->due_date,
  46. 'status' => 'pending',
  47. 'obs' => $receivable->obs,
  48. ]);
  49. $this->notifications->dispatch([
  50. 'origin_table' => 'franchisee_account_receives',
  51. 'origin_id' => $receivable->id,
  52. 'unit_id' => $unitId,
  53. 'type' => NotificationType::ACCOUNT_PAYABLE_CREATED->value,
  54. 'title' => 'Nova conta a pagar',
  55. 'message' => "Uma nova conta a pagar foi criada: {$receivable->history}.",
  56. 'url' => '/financial/accounts-payable',
  57. 'action_text' => 'Ver Contas a Pagar',
  58. 'priority' => 'normal',
  59. 'recipient_user_ids' => $this->notifications->unitUserIds($unitId),
  60. ]);
  61. }
  62. return $receivable->load(['unit', 'details', 'planAccount']);
  63. });
  64. }
  65. public function settle(FranchiseeAccountReceive $receivable, array $data): FranchiseeAccountReceive
  66. {
  67. if ($receivable->status->value === 'paid') {
  68. throw ValidationException::withMessages(['status' => 'Esta conta já está paga.']);
  69. }
  70. return DB::transaction(function () use ($receivable, $data) {
  71. $receivable->update([
  72. 'status' => 'paid',
  73. 'paid_value' => $receivable->value,
  74. 'payment_date' => $data['payment_date'] ?? Carbon::today()->format('Y-m-d'),
  75. ]);
  76. UnitAccountPayable::where('franchisee_account_receive_id', $receivable->id)
  77. ->update([
  78. 'status' => 'paid',
  79. 'paid_value' => $receivable->value,
  80. 'payment_date' => $data['payment_date'] ?? Carbon::today()->format('Y-m-d'),
  81. ]);
  82. if ($receivable->unit_id) {
  83. $this->notifications->dispatch([
  84. 'origin_table' => 'franchisee_account_receives',
  85. 'origin_id' => $receivable->id,
  86. 'unit_id' => $receivable->unit_id,
  87. 'type' => NotificationType::PAYMENT_CREDITED->value,
  88. 'title' => 'Pagamento confirmado',
  89. 'message' => "Sua cobrança {$receivable->history} foi devidamente creditada e consta como paga.",
  90. 'url' => '/financial/accounts-payable',
  91. 'action_text' => 'Ver Contas a Pagar',
  92. 'priority' => 'normal',
  93. 'recipient_user_ids' => $this->notifications->unitUserIds($receivable->unit_id),
  94. ]);
  95. }
  96. return $receivable->fresh(['unit', 'details', 'planAccount']);
  97. });
  98. }
  99. public function generateCharge(FranchiseeAccountReceive $receivable): FranchiseeAccountReceive
  100. {
  101. if (! $receivable->unit_id) {
  102. throw ValidationException::withMessages([
  103. 'unit' => 'Cobranças Asaas só podem ser geradas para contas vinculadas a uma unidade.',
  104. ]);
  105. }
  106. if (in_array($receivable->status->value, ['paid', 'cancelled'], true)) {
  107. throw ValidationException::withMessages([
  108. 'status' => 'Contas pagas ou canceladas não podem gerar cobrança.',
  109. ]);
  110. }
  111. if ($receivable->asaas_id) {
  112. throw ValidationException::withMessages([
  113. 'asaas' => 'Esta conta já possui cobrança gerada.',
  114. ]);
  115. }
  116. if (empty(CompanyPaymentAccount::resolveApiKey())) {
  117. throw ValidationException::withMessages([
  118. 'asaas' => 'A franqueadora não possui chave Asaas configurada.',
  119. ]);
  120. }
  121. try {
  122. SyncFranchiseeChargeJob::dispatchSync($receivable);
  123. } catch (Exception) {
  124. throw ValidationException::withMessages([
  125. 'asaas' => 'Não foi possível gerar a cobrança na Asaas. Tente novamente.',
  126. ]);
  127. }
  128. return $receivable->fresh(['unit', 'details', 'planAccount']);
  129. }
  130. public function reopen(FranchiseeAccountReceive $receivable): FranchiseeAccountReceive
  131. {
  132. throw ValidationException::withMessages([
  133. 'status' => 'Uma conta paga não pode voltar para um status anterior.',
  134. ]);
  135. }
  136. }