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.

AccountService.php 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. <?php
  2. namespace App\Services;
  3. use App\Models\Accounting\Account;
  4. use App\Models\Banking\BankAccount;
  5. use App\Models\Banking\ConnectedBankAccount;
  6. use App\Models\Company;
  7. use App\Models\Setting\Currency;
  8. use Illuminate\Database\Eloquent\ModelNotFoundException;
  9. class AccountService
  10. {
  11. public function getOrProcessAccount(BankAccount $bankAccount, Company $company, ConnectedBankAccount $connectedBankAccount): Account
  12. {
  13. if ($bankAccount->account()->doesntExist()) {
  14. return $this->processNewAccount($bankAccount, $company, $connectedBankAccount);
  15. }
  16. return $bankAccount->account;
  17. }
  18. public function processNewAccount(BankAccount $bankAccount, Company $company, ConnectedBankAccount $connectedBankAccount): Account
  19. {
  20. $currencyCode = $connectedBankAccount->currency_code ?? 'USD';
  21. $currency = $this->ensureCurrencyExists($company, $currencyCode);
  22. $accountSubtype = $this->getAccountSubtype($bankAccount->type->value);
  23. $accountSubtypeId = $this->resolveAccountSubtypeId($company, $accountSubtype);
  24. return $bankAccount->account()->create([
  25. 'company_id' => $company->id,
  26. 'name' => $connectedBankAccount->name,
  27. 'currency_code' => $currency->code,
  28. 'description' => $connectedBankAccount->name,
  29. 'subtype_id' => $accountSubtypeId,
  30. 'active' => true,
  31. ]);
  32. }
  33. protected function ensureCurrencyExists(Company $company, string $currencyCode): Currency
  34. {
  35. $currencyRelationship = $company->currencies();
  36. $defaultCurrency = $currencyRelationship->firstWhere('enabled', true);
  37. $hasDefaultCurrency = $defaultCurrency !== null;
  38. $currency_code = currency($currencyCode);
  39. return $currencyRelationship->firstOrCreate([
  40. 'code' => $currencyCode,
  41. ], [
  42. 'name' => $currency_code->getName(),
  43. 'rate' => $currency_code->getRate(),
  44. 'precision' => $currency_code->getPrecision(),
  45. 'symbol' => $currency_code->getSymbol(),
  46. 'symbol_first' => $currency_code->isSymbolFirst(),
  47. 'decimal_mark' => $currency_code->getDecimalMark(),
  48. 'thousands_separator' => $currency_code->getThousandsSeparator(),
  49. 'enabled' => ! $hasDefaultCurrency,
  50. ]);
  51. }
  52. protected function getAccountSubtype(string $plaidType): string
  53. {
  54. return match ($plaidType) {
  55. 'depository' => 'Cash and Cash Equivalents',
  56. 'credit' => 'Short-Term Borrowings',
  57. 'loan' => 'Long-Term Borrowings',
  58. 'investment' => 'Long-Term Investments',
  59. 'other' => 'Other Current Assets',
  60. };
  61. }
  62. protected function resolveAccountSubtypeId(Company $company, string $accountSubtype): int
  63. {
  64. $accountSubtypeId = $company->accountSubtypes()
  65. ->where('name', $accountSubtype)
  66. ->value('id');
  67. if ($accountSubtypeId === null) {
  68. throw new ModelNotFoundException("Account subtype '{$accountSubtype}' not found for company '{$company->name}'");
  69. }
  70. return $accountSubtypeId;
  71. }
  72. }