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.

JournalEntryObserver.php 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace App\Observers;
  3. use App\Enums\Accounting\AccountCategory;
  4. use App\Models\Accounting\Account;
  5. use App\Models\Accounting\JournalEntry;
  6. class JournalEntryObserver
  7. {
  8. /**
  9. * Handle the JournalEntry "created" event.
  10. */
  11. public function created(JournalEntry $journalEntry): void
  12. {
  13. $account = $journalEntry->account;
  14. $amount = $this->cleanAmount($journalEntry->amount);
  15. if ($account) {
  16. $this->adjustBalance($account, $journalEntry->type, $amount);
  17. }
  18. }
  19. private function cleanAmount($amount): string
  20. {
  21. return str_replace(',', '', $amount);
  22. }
  23. private function adjustBalance(Account $account, $type, $amount): void
  24. {
  25. $debitBalance = $this->cleanAmount($account->debit_balance);
  26. $creditBalance = $this->cleanAmount($account->credit_balance);
  27. if ($type === 'debit') {
  28. $account->debit_balance = bcadd($debitBalance, $amount, 2);
  29. } elseif ($type === 'credit') {
  30. $account->credit_balance = bcadd($creditBalance, $amount, 2);
  31. }
  32. $this->updateNetMovement($account);
  33. $this->updateEndingBalance($account);
  34. }
  35. private function updateNetMovement(Account $account): void
  36. {
  37. $debitBalance = $this->cleanAmount($account->debit_balance);
  38. $creditBalance = $this->cleanAmount($account->credit_balance);
  39. $netMovementStrategy = match ($account->category) {
  40. AccountCategory::Asset, AccountCategory::Expense => bcsub($debitBalance, $creditBalance, 2),
  41. AccountCategory::Liability, AccountCategory::Equity, AccountCategory::Revenue => bcsub($creditBalance, $debitBalance, 2),
  42. };
  43. $account->net_movement = $netMovementStrategy;
  44. $account->save();
  45. }
  46. private function updateEndingBalance(Account $account): void
  47. {
  48. $startingBalance = $this->cleanAmount($account->starting_balance);
  49. $netMovement = $this->cleanAmount($account->net_movement);
  50. if (in_array($account->category, [AccountCategory::Asset, AccountCategory::Liability, AccountCategory::Equity], true)) {
  51. $account->ending_balance = bcadd($startingBalance, $netMovement, 2);
  52. }
  53. $account->save();
  54. }
  55. /**
  56. * Handle the JournalEntry "deleting" event.
  57. */
  58. public function deleting(JournalEntry $journalEntry): void
  59. {
  60. $account = $journalEntry->account;
  61. if ($account) {
  62. $amount = $this->cleanAmount($journalEntry->amount);
  63. $this->adjustBalance($account, $journalEntry->type, -$amount);
  64. }
  65. }
  66. /**
  67. * Handle the JournalEntry "deleted" event.
  68. */
  69. public function deleted(JournalEntry $journalEntry): void
  70. {
  71. //
  72. }
  73. /**
  74. * Handle the JournalEntry "restored" event.
  75. */
  76. public function restored(JournalEntry $journalEntry): void
  77. {
  78. //
  79. }
  80. /**
  81. * Handle the JournalEntry "force deleted" event.
  82. */
  83. public function forceDeleted(JournalEntry $journalEntry): void
  84. {
  85. //
  86. }
  87. }