TreasuryAccountService.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 create(array $data): TreasuryAccount
  73. {
  74. // Sem unit_id => conta da rede (franqueador). Com unit_id => conta da unidade (franchisee).
  75. $data['unit_id'] = $data['unit_id'] ?? null;
  76. return TreasuryAccount::create($data);
  77. }
  78. public function update(int $id, array $data): ?TreasuryAccount
  79. {
  80. $model = $this->findById($id);
  81. if (!$model) {
  82. return null;
  83. }
  84. $model->update($data);
  85. return $model->fresh();
  86. }
  87. public function delete(int $id): bool
  88. {
  89. $model = $this->findById($id);
  90. if (!$model) {
  91. return false;
  92. }
  93. return $model->delete();
  94. }
  95. // Add custom business logic methods here
  96. }