You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TransactionObserver.php 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <?php
  2. namespace App\Observers;
  3. use App\Enums\Accounting\TransactionType;
  4. use App\Models\Accounting\Account;
  5. use App\Models\Accounting\JournalEntry;
  6. use App\Models\Accounting\Transaction;
  7. use Illuminate\Support\Facades\DB;
  8. class TransactionObserver
  9. {
  10. /**
  11. * Handle the Transaction "created" event.
  12. */
  13. public function created(Transaction $transaction): void
  14. {
  15. if ($transaction->type === TransactionType::Journal) {
  16. return;
  17. }
  18. $chartAccount = $transaction->account;
  19. $bankAccount = $transaction->bankAccount->account;
  20. $debitAccount = $transaction->type === TransactionType::Withdrawal ? $chartAccount : $bankAccount;
  21. $creditAccount = $transaction->type === TransactionType::Withdrawal ? $bankAccount : $chartAccount;
  22. $this->createJournalEntries($transaction, $debitAccount, $creditAccount);
  23. }
  24. private function createJournalEntries(Transaction $transaction, Account $debitAccount, Account $creditAccount): void
  25. {
  26. $debitAccount->journalEntries()->create([
  27. 'company_id' => $transaction->company_id,
  28. 'transaction_id' => $transaction->id,
  29. 'type' => 'debit',
  30. 'amount' => $transaction->amount,
  31. 'description' => $transaction->description,
  32. ]);
  33. $creditAccount->journalEntries()->create([
  34. 'company_id' => $transaction->company_id,
  35. 'transaction_id' => $transaction->id,
  36. 'type' => 'credit',
  37. 'amount' => $transaction->amount,
  38. 'description' => $transaction->description,
  39. ]);
  40. }
  41. /**
  42. * Handle the Transaction "updated" event.
  43. */
  44. public function updated(Transaction $transaction): void
  45. {
  46. if ($transaction->type === TransactionType::Journal || $this->hasRelevantChanges($transaction) === false) {
  47. return;
  48. }
  49. $chartAccount = $transaction->account;
  50. $bankAccount = $transaction->bankAccount?->account;
  51. if (! $chartAccount || ! $bankAccount) {
  52. return;
  53. }
  54. $journalEntries = $transaction->journalEntries;
  55. $debitEntry = $journalEntries->where('type', 'debit')->first();
  56. $creditEntry = $journalEntries->where('type', 'credit')->first();
  57. if (! $debitEntry || ! $creditEntry) {
  58. return;
  59. }
  60. $debitAccount = $transaction->type === TransactionType::Withdrawal ? $chartAccount : $bankAccount;
  61. $creditAccount = $transaction->type === TransactionType::Withdrawal ? $bankAccount : $chartAccount;
  62. $this->updateJournalEntriesForTransaction($debitEntry, $debitAccount, $transaction);
  63. $this->updateJournalEntriesForTransaction($creditEntry, $creditAccount, $transaction);
  64. }
  65. protected function hasRelevantChanges(Transaction $transaction): bool
  66. {
  67. return $transaction->wasChanged(['amount', 'account_id', 'bank_account_id', 'type']);
  68. }
  69. protected function updateJournalEntriesForTransaction(JournalEntry $journalEntry, Account $account, Transaction $transaction): void
  70. {
  71. DB::transaction(static function () use ($journalEntry, $account, $transaction) {
  72. $journalEntry->update([
  73. 'account_id' => $account->id,
  74. 'amount' => $transaction->amount,
  75. ]);
  76. });
  77. }
  78. /**
  79. * Handle the Transaction "deleting" event.
  80. */
  81. public function deleting(Transaction $transaction): void
  82. {
  83. DB::transaction(static function () use ($transaction) {
  84. $transaction->journalEntries()->each(fn (JournalEntry $entry) => $entry->delete());
  85. });
  86. }
  87. /**
  88. * Handle the Transaction "deleted" event.
  89. */
  90. public function deleted(Transaction $transaction): void
  91. {
  92. //
  93. }
  94. /**
  95. * Handle the Transaction "restored" event.
  96. */
  97. public function restored(Transaction $transaction): void
  98. {
  99. //
  100. }
  101. /**
  102. * Handle the Transaction "force deleted" event.
  103. */
  104. public function forceDeleted(Transaction $transaction): void
  105. {
  106. //
  107. }
  108. }