TreasuryAccountService.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. namespace App\Services;
  3. use App\Models\TreasuryAccount;
  4. use App\Models\TreasuryLaunch;
  5. use Illuminate\Database\Eloquent\Collection;
  6. use Illuminate\Support\Carbon;
  7. class TreasuryAccountService
  8. {
  9. /**
  10. * Lista as contas de tesouraria por escopo:
  11. * - franqueador (rede/conta-mãe): sem unit_id => contas com unit_id null;
  12. * - franchisee: unit_id da unidade ativa => contas daquela unidade.
  13. * Cada conta recebe o saldo (entradas - saídas dos lançamentos).
  14. */
  15. public function getAll(?int $unitId = null): Collection
  16. {
  17. $accounts = TreasuryAccount::query()
  18. ->when(
  19. $unitId !== null,
  20. fn ($query) => $query->where('unit_id', $unitId),
  21. fn ($query) => $query->whereNull('unit_id'),
  22. )
  23. ->orderBy('created_at', 'desc')
  24. ->get();
  25. $this->attachBalances($accounts);
  26. return $accounts;
  27. }
  28. /**
  29. * Calcula o saldo de cada conta:
  30. * saldo = soma das entradas (to_account) - soma das saídas (from_account).
  31. *
  32. * Também expõe `balance_previous` = saldo no fim do mês anterior (saldo atual
  33. * menos o fluxo líquido do mês corrente), permitindo ao frontend exibir a
  34. * variação percentual "vs o mês anterior" em cada card.
  35. */
  36. private function attachBalances(Collection $accounts): void
  37. {
  38. $ids = $accounts->pluck('id');
  39. if ($ids->isEmpty()) {
  40. return;
  41. }
  42. $incoming = TreasuryLaunch::whereIn('to_account_id', $ids)
  43. ->groupBy('to_account_id')
  44. ->selectRaw('to_account_id, SUM(amount) as total')
  45. ->pluck('total', 'to_account_id');
  46. $outgoing = TreasuryLaunch::whereIn('from_account_id', $ids)
  47. ->groupBy('from_account_id')
  48. ->selectRaw('from_account_id, SUM(amount) as total')
  49. ->pluck('total', 'from_account_id');
  50. $monthStart = Carbon::now()->startOfMonth();
  51. $incomingMonth = TreasuryLaunch::whereIn('to_account_id', $ids)
  52. ->where('launch_date', '>=', $monthStart)
  53. ->groupBy('to_account_id')
  54. ->selectRaw('to_account_id, SUM(amount) as total')
  55. ->pluck('total', 'to_account_id');
  56. $outgoingMonth = TreasuryLaunch::whereIn('from_account_id', $ids)
  57. ->where('launch_date', '>=', $monthStart)
  58. ->groupBy('from_account_id')
  59. ->selectRaw('from_account_id, SUM(amount) as total')
  60. ->pluck('total', 'from_account_id');
  61. foreach ($accounts as $account) {
  62. $balance = (float) ($incoming[$account->id] ?? 0) - (float) ($outgoing[$account->id] ?? 0);
  63. $monthNet = (float) ($incomingMonth[$account->id] ?? 0) - (float) ($outgoingMonth[$account->id] ?? 0);
  64. $account->setAttribute('balance', $balance);
  65. $account->setAttribute('balance_previous', $balance - $monthNet);
  66. }
  67. }
  68. public function findById(int $id): ?TreasuryAccount
  69. {
  70. return TreasuryAccount::find($id);
  71. }
  72. public function findByIdForUnit(int $id, int $unitId): ?TreasuryAccount
  73. {
  74. return TreasuryAccount::where('id', $id)->where('unit_id', $unitId)->first();
  75. }
  76. public function create(array $data): TreasuryAccount
  77. {
  78. // Sem unit_id => conta da rede (franqueador). Com unit_id => conta da unidade (franchisee).
  79. $data['unit_id'] = $data['unit_id'] ?? null;
  80. return TreasuryAccount::create($data);
  81. }
  82. public function update(int $id, array $data): ?TreasuryAccount
  83. {
  84. $model = $this->findById($id);
  85. if (!$model) {
  86. return null;
  87. }
  88. $model->update($data);
  89. return $model->fresh();
  90. }
  91. public function delete(int $id): bool
  92. {
  93. $model = $this->findById($id);
  94. if (!$model) {
  95. return false;
  96. }
  97. return $model->delete();
  98. }
  99. // Add custom business logic methods here
  100. }