Kaynağa Gözat

feat: almost done with release

3.x
wallo 1 yıl önce
ebeveyn
işleme
05976e1a90
32 değiştirilmiş dosya ile 675 ekleme ve 457 silme
  1. 7
    7
      app/Actions/OptionAction/CreateCurrency.php
  2. 39
    0
      app/Casts/JournalEntryCast.php
  3. 2
    2
      app/Casts/MoneyCast.php
  4. 18
    2
      app/Casts/TransactionAmountCast.php
  5. 47
    0
      app/Collections/Accounting/JournalEntryCollection.php
  6. 114
    42
      app/Concerns/HasJournalEntryActions.php
  7. 7
    7
      app/Contracts/AccountHandler.php
  8. 3
    0
      app/Enums/Banking/BankAccountType.php
  9. 7
    7
      app/Facades/Accounting.php
  10. 0
    10
      app/Filament/Company/Clusters/Settings/Resources/CurrencyResource.php
  11. 47
    36
      app/Filament/Company/Pages/Accounting/Transactions.php
  12. 1
    1
      app/Filament/Company/Pages/Reports/AccountBalances.php
  13. 13
    74
      app/Filament/Company/Resources/Banking/AccountResource.php
  14. 0
    11
      app/Filament/Company/Resources/Banking/AccountResource/Pages/CreateAccount.php
  15. 70
    0
      app/Filament/Forms/Components/CreateCurrencySelect.php
  16. 1
    1
      app/Filament/Forms/Components/DateRangeSelect.php
  17. 2
    2
      app/Filament/Forms/Components/JournalEntryRepeater.php
  18. 1
    1
      app/Listeners/UpdateAccountBalances.php
  19. 7
    12
      app/Models/Accounting/JournalEntry.php
  20. 8
    0
      app/Models/Accounting/Transaction.php
  21. 6
    14
      app/Observers/JournalEntryObserver.php
  22. 8
    3
      app/Observers/TransactionObserver.php
  23. 14
    0
      app/Providers/MacroServiceProvider.php
  24. 21
    21
      app/Services/AccountService.php
  25. 2
    1
      app/Utilities/Currency/ConfigureCurrencies.php
  26. 17
    0
      app/Utilities/Currency/CurrencyConverter.php
  27. 0
    69
      app/ValueObjects/BalanceValue.php
  28. 79
    0
      app/ValueObjects/Money.php
  29. 54
    49
      composer.lock
  30. 7
    12
      database/migrations/2023_09_08_040159_create_company_defaults_table.php
  31. 73
    73
      package-lock.json
  32. 0
    0
      resources/views/filament/forms/components/journal-entry-repeater.blade.php

+ 7
- 7
app/Actions/OptionAction/CreateCurrency.php Dosyayı Görüntüle

@@ -7,22 +7,22 @@ use App\Utilities\Currency\CurrencyAccessor;
7 7
 
8 8
 class CreateCurrency
9 9
 {
10
-    public function create(string $code, string $name, string $rate): Currency
10
+    public static function create(string $code, string $name, string $rate): Currency
11 11
     {
12 12
         $defaultCurrency = CurrencyAccessor::getDefaultCurrency();
13 13
 
14 14
         $hasDefaultCurrency = $defaultCurrency !== null;
15
-        $currency_code = currency($code);
15
+        $currency = currency($code);
16 16
 
17 17
         return Currency::create([
18 18
             'name' => $name,
19 19
             'code' => $code,
20 20
             'rate' => $rate,
21
-            'precision' => $currency_code->getPrecision(),
22
-            'symbol' => $currency_code->getSymbol(),
23
-            'symbol_first' => $currency_code->isSymbolFirst(),
24
-            'decimal_mark' => $currency_code->getDecimalMark(),
25
-            'thousands_separator' => $currency_code->getThousandsSeparator(),
21
+            'precision' => $currency->getPrecision(),
22
+            'symbol' => $currency->getSymbol(),
23
+            'symbol_first' => $currency->isSymbolFirst(),
24
+            'decimal_mark' => $currency->getDecimalMark(),
25
+            'thousands_separator' => $currency->getThousandsSeparator(),
26 26
             'enabled' => ! $hasDefaultCurrency,
27 27
         ]);
28 28
     }

+ 39
- 0
app/Casts/JournalEntryCast.php Dosyayı Görüntüle

@@ -0,0 +1,39 @@
1
+<?php
2
+
3
+namespace App\Casts;
4
+
5
+use App\Utilities\Currency\CurrencyAccessor;
6
+use App\Utilities\Currency\CurrencyConverter;
7
+use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
8
+use Illuminate\Database\Eloquent\Model;
9
+use UnexpectedValueException;
10
+
11
+class JournalEntryCast implements CastsAttributes
12
+{
13
+    public function get(Model $model, string $key, mixed $value, array $attributes): string
14
+    {
15
+        $currency_code = CurrencyAccessor::getDefaultCurrency();
16
+
17
+        if ($value !== null) {
18
+            return CurrencyConverter::prepareForMutator($value, $currency_code);
19
+        }
20
+
21
+        return '';
22
+    }
23
+
24
+    /**
25
+     * @throws UnexpectedValueException
26
+     */
27
+    public function set(Model $model, string $key, mixed $value, array $attributes): int
28
+    {
29
+        $currency_code = CurrencyAccessor::getDefaultCurrency();
30
+
31
+        if (is_numeric($value)) {
32
+            $value = (string) $value;
33
+        } elseif (! is_string($value)) {
34
+            throw new UnexpectedValueException('Expected string or numeric value for money cast');
35
+        }
36
+
37
+        return CurrencyConverter::prepareForAccessor($value, $currency_code);
38
+    }
39
+}

+ 2
- 2
app/Casts/MoneyCast.php Dosyayı Görüntüle

@@ -12,7 +12,7 @@ class MoneyCast implements CastsAttributes
12 12
 {
13 13
     public function get(Model $model, string $key, mixed $value, array $attributes): string
14 14
     {
15
-        $currency_code = $model->getAttribute('currency_code') ?? CurrencyAccessor::getDefaultCurrency();
15
+        $currency_code = $attributes['currency_code'] ?? CurrencyAccessor::getDefaultCurrency();
16 16
 
17 17
         if ($value !== null) {
18 18
             return CurrencyConverter::prepareForMutator($value, $currency_code);
@@ -26,7 +26,7 @@ class MoneyCast implements CastsAttributes
26 26
      */
27 27
     public function set(Model $model, string $key, mixed $value, array $attributes): int
28 28
     {
29
-        $currency_code = $model->getAttribute('currency_code') ?? CurrencyAccessor::getDefaultCurrency();
29
+        $currency_code = $attributes['currency_code'] ?? CurrencyAccessor::getDefaultCurrency();
30 30
 
31 31
         if (is_numeric($value)) {
32 32
             $value = (string) $value;

+ 18
- 2
app/Casts/TransactionAmountCast.php Dosyayı Görüntüle

@@ -2,6 +2,7 @@
2 2
 
3 3
 namespace App\Casts;
4 4
 
5
+use App\Models\Banking\BankAccount;
5 6
 use App\Utilities\Currency\CurrencyAccessor;
6 7
 use App\Utilities\Currency\CurrencyConverter;
7 8
 use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
@@ -13,7 +14,7 @@ class TransactionAmountCast implements CastsAttributes
13 14
     public function get(Model $model, string $key, mixed $value, array $attributes): string
14 15
     {
15 16
         // Attempt to retrieve the currency code from the related bankAccount->account model
16
-        $currency_code = $model->bankAccount?->account?->currency_code ?? CurrencyAccessor::getDefaultCurrency();
17
+        $currency_code = $this->getCurrencyCodeFromBankAccountId($attributes['bank_account_id'] ?? null);
17 18
 
18 19
         if ($value !== null) {
19 20
             return CurrencyConverter::prepareForMutator($value, $currency_code);
@@ -27,7 +28,7 @@ class TransactionAmountCast implements CastsAttributes
27 28
      */
28 29
     public function set(Model $model, string $key, mixed $value, array $attributes): int
29 30
     {
30
-        $currency_code = $model->bankAccount?->account?->currency_code ?? CurrencyAccessor::getDefaultCurrency();
31
+        $currency_code = $this->getCurrencyCodeFromBankAccountId($attributes['bank_account_id'] ?? null);
31 32
 
32 33
         if (is_numeric($value)) {
33 34
             $value = (string) $value;
@@ -37,4 +38,19 @@ class TransactionAmountCast implements CastsAttributes
37 38
 
38 39
         return CurrencyConverter::prepareForAccessor($value, $currency_code);
39 40
     }
41
+
42
+    /**
43
+     * Using this is necessary because the relationship is not always loaded into memory when the cast is called
44
+     * Instead of using: $model->bankAccount->account->currency_code directly, find the bank account and get the currency code
45
+     */
46
+    private function getCurrencyCodeFromBankAccountId(?int $bankAccountId): string
47
+    {
48
+        if ($bankAccountId === null) {
49
+            return CurrencyAccessor::getDefaultCurrency();
50
+        }
51
+
52
+        $bankAccount = BankAccount::find($bankAccountId);
53
+
54
+        return $bankAccount?->account?->currency_code ?? CurrencyAccessor::getDefaultCurrency();
55
+    }
40 56
 }

+ 47
- 0
app/Collections/Accounting/JournalEntryCollection.php Dosyayı Görüntüle

@@ -0,0 +1,47 @@
1
+<?php
2
+
3
+namespace App\Collections\Accounting;
4
+
5
+use App\Models\Accounting\JournalEntry;
6
+use App\Utilities\Currency\CurrencyAccessor;
7
+use App\Utilities\Currency\CurrencyConverter;
8
+use App\ValueObjects\Money;
9
+use Illuminate\Database\Eloquent\Collection;
10
+
11
+class JournalEntryCollection extends Collection
12
+{
13
+    public function sumDebits(): Money
14
+    {
15
+        $total = $this->reduce(static function ($carry, JournalEntry $item) {
16
+            if ($item->type->isDebit()) {
17
+                $amountAsInteger = CurrencyConverter::prepareForAccessor($item->amount, CurrencyAccessor::getDefaultCurrency());
18
+
19
+                return bcadd($carry, $amountAsInteger, 0);
20
+            }
21
+
22
+            return $carry;
23
+        }, 0);
24
+
25
+        return new Money($total, CurrencyAccessor::getDefaultCurrency());
26
+    }
27
+
28
+    public function sumCredits(): Money
29
+    {
30
+        $total = $this->reduce(static function ($carry, JournalEntry $item) {
31
+            if ($item->type->isCredit()) {
32
+                $amountAsInteger = CurrencyConverter::prepareForAccessor($item->amount, CurrencyAccessor::getDefaultCurrency());
33
+
34
+                return bcadd($carry, $amountAsInteger, 0);
35
+            }
36
+
37
+            return $carry;
38
+        }, 0);
39
+
40
+        return new Money($total, CurrencyAccessor::getDefaultCurrency());
41
+    }
42
+
43
+    public function areBalanced(): bool
44
+    {
45
+        return $this->sumDebits()->getAmount() === $this->sumCredits()->getAmount();
46
+    }
47
+}

+ 114
- 42
app/Concerns/HasJournalEntryActions.php Dosyayı Görüntüle

@@ -3,61 +3,105 @@
3 3
 namespace App\Concerns;
4 4
 
5 5
 use App\Enums\Accounting\JournalEntryType;
6
+use App\Utilities\Currency\CurrencyAccessor;
6 7
 
7 8
 trait HasJournalEntryActions
8 9
 {
9
-    public string $debitAmount = '0.00';
10
+    public int $debitAmount = 0;
10 11
 
11
-    public string $creditAmount = '0.00';
12
+    public int $creditAmount = 0;
12 13
 
13
-    public function setDebitAmount(string $amount): void
14
+    private function formatMoney(int $amount): string
14 15
     {
15
-        $this->debitAmount = $amount;
16
+        return money($amount, CurrencyAccessor::getDefaultCurrency())->format();
16 17
     }
17 18
 
18
-    public function getDebitAmount(): string
19
+    /**
20
+     * Expects formatted simple amount: e.g. 1,000.00 or 1.000,00
21
+     *
22
+     * Sets debit amount in cents as integer: e.g. 100000
23
+     */
24
+    public function setDebitAmount(int $amount): void
19 25
     {
20
-        return $this->debitAmount;
26
+        $this->debitAmount = $amount;
21 27
     }
22 28
 
23
-    public function getFormattedDebitAmount(): string
29
+    /**
30
+     * Expects formatted simple amount: e.g. 1,000.00 or 1.000,00
31
+     *
32
+     * Sets credit amount in cents as integer: e.g. 100000
33
+     */
34
+    public function setCreditAmount(int $amount): void
24 35
     {
25
-        return money($this->getDebitAmount(), 'USD', true)->format();
36
+        $this->creditAmount = $amount;
26 37
     }
27 38
 
28
-    public function setCreditAmount(string $amount): void
39
+    /**
40
+     * Returns debit amount in cents as integer: e.g. 100000
41
+     */
42
+    public function getDebitAmount(): int
29 43
     {
30
-        $this->creditAmount = $amount;
44
+        return $this->debitAmount;
31 45
     }
32 46
 
33
-    public function getCreditAmount(): string
47
+    /**
48
+     * Returns credit amount in cents as integer: e.g. 100000
49
+     */
50
+    public function getCreditAmount(): int
34 51
     {
35 52
         return $this->creditAmount;
36 53
     }
37 54
 
55
+    /**
56
+     * Expects debit amount in cents as string integer: e.g. 100000
57
+     *
58
+     * Returns formatted amount: e.g. $1,000.00 or €1.000,00
59
+     */
60
+    public function getFormattedDebitAmount(): string
61
+    {
62
+        return $this->formatMoney($this->getDebitAmount());
63
+    }
64
+
65
+    /**
66
+     * Expects credit amount in cents as integer: e.g. 100000
67
+     *
68
+     * Returns formatted amount: e.g. $1,000.00 or €1.000,00
69
+     */
38 70
     public function getFormattedCreditAmount(): string
39 71
     {
40
-        return money($this->getCreditAmount(), 'USD', true)->format();
72
+        return $this->formatMoney($this->getCreditAmount());
41 73
     }
42 74
 
43
-    public function getBalanceDifference(): string
75
+    /**
76
+     * Returns balance difference in cents as integer: e.g. 100000
77
+     */
78
+    public function getBalanceDifference(): int
44 79
     {
45
-        return bcsub($this->getDebitAmount(), $this->getCreditAmount(), 2);
80
+        return $this->getDebitAmount() - $this->getCreditAmount();
46 81
     }
47 82
 
83
+    /**
84
+     * Returns formatted balance difference: e.g. $1,000.00 or €1.000,00
85
+     */
48 86
     public function getFormattedBalanceDifference(): string
49 87
     {
50
-        $difference = $this->getBalanceDifference();
51
-        $absoluteDifference = abs((float) $difference);
88
+        $absoluteDifference = abs($this->getBalanceDifference());
52 89
 
53
-        return money($absoluteDifference, 'USD', true)->format();
90
+        return $this->formatMoney($absoluteDifference);
54 91
     }
55 92
 
93
+    /**
94
+     * Returns boolean indicating whether the journal entry is balanced
95
+     * using the debit and credit integer amounts
96
+     */
56 97
     public function isJournalEntryBalanced(): bool
57 98
     {
58
-        return bccomp($this->getDebitAmount(), $this->getCreditAmount(), 2) === 0;
99
+        return $this->getDebitAmount() === $this->getCreditAmount();
59 100
     }
60 101
 
102
+    /**
103
+     * Resets debit and credit amounts to '0.00'
104
+     */
61 105
     public function resetJournalEntryAmounts(): void
62 106
     {
63 107
         $this->reset(['debitAmount', 'creditAmount']);
@@ -65,47 +109,75 @@ trait HasJournalEntryActions
65 109
 
66 110
     public function adjustJournalEntryAmountsForTypeChange(JournalEntryType $newType, JournalEntryType $oldType, ?string $amount): void
67 111
     {
68
-        if ($newType !== $oldType) {
69
-            $normalizedAmount = $amount === null ? '0.00' : rtrim($amount, '.');
70
-            $normalizedAmount = $this->sanitizeAndFormatAmount($normalizedAmount);
71
-
72
-            if (bccomp($normalizedAmount, '0.00', 2) === 0) {
73
-                return;
74
-            }
75
-
76
-            if ($oldType->isDebit() && $newType->isCredit()) {
77
-                $this->setDebitAmount(bcsub($this->getDebitAmount(), $normalizedAmount, 2));
78
-                $this->setCreditAmount(bcadd($this->getCreditAmount(), $normalizedAmount, 2));
79
-            } elseif ($oldType->isCredit() && $newType->isDebit()) {
80
-                $this->setDebitAmount(bcadd($this->getDebitAmount(), $normalizedAmount, 2));
81
-                $this->setCreditAmount(bcsub($this->getCreditAmount(), $normalizedAmount, 2));
82
-            }
112
+        if ($newType === $oldType) {
113
+            return;
114
+        }
115
+
116
+        $amountComplete = $this->ensureCompleteDecimal($amount);
117
+        $normalizedAmount = $this->convertAmountToCents($amountComplete);
118
+
119
+        if ($normalizedAmount === 0) {
120
+            return;
121
+        }
122
+
123
+        if ($oldType->isDebit() && $newType->isCredit()) {
124
+            $this->debitAmount -= $normalizedAmount;
125
+            $this->creditAmount += $normalizedAmount;
126
+        } elseif ($oldType->isCredit() && $newType->isDebit()) {
127
+            $this->debitAmount += $normalizedAmount;
128
+            $this->creditAmount -= $normalizedAmount;
83 129
         }
84 130
     }
85 131
 
132
+    /**
133
+     * Expects the journal entry type,
134
+     * the new amount and the old amount as formatted simple amounts: e.g. 1,000.00 or 1.000,00
135
+     * It can expect the amounts as partial amounts: e.g. 1,000. or 1.000, (this needs to be handled by this method)
136
+     */
86 137
     public function updateJournalEntryAmount(JournalEntryType $journalEntryType, ?string $newAmount, ?string $oldAmount): void
87 138
     {
88 139
         if ($newAmount === $oldAmount) {
89 140
             return;
90 141
         }
91 142
 
92
-        $normalizedNewAmount = $newAmount === null ? '0.00' : rtrim($newAmount, '.');
93
-        $normalizedOldAmount = $oldAmount === null ? '0.00' : rtrim($oldAmount, '.');
143
+        $newAmountComplete = $this->ensureCompleteDecimal($newAmount);
144
+        $oldAmountComplete = $this->ensureCompleteDecimal($oldAmount);
94 145
 
95
-        $formattedNewAmount = $this->sanitizeAndFormatAmount($normalizedNewAmount);
96
-        $formattedOldAmount = $this->sanitizeAndFormatAmount($normalizedOldAmount);
146
+        $formattedNewAmount = $this->convertAmountToCents($newAmountComplete);
147
+        $formattedOldAmount = $this->convertAmountToCents($oldAmountComplete);
97 148
 
98
-        $difference = bcsub($formattedNewAmount, $formattedOldAmount, 2);
149
+        $difference = $formattedNewAmount - $formattedOldAmount;
99 150
 
100 151
         if ($journalEntryType->isDebit()) {
101
-            $this->setDebitAmount(bcadd($this->getDebitAmount(), $difference, 2));
152
+            $this->debitAmount += $difference;
102 153
         } else {
103
-            $this->setCreditAmount(bcadd($this->getCreditAmount(), $difference, 2));
154
+            $this->creditAmount += $difference;
104 155
         }
105 156
     }
106 157
 
107
-    protected function sanitizeAndFormatAmount(string $amount): string
158
+    private function ensureCompleteDecimal(?string $amount): string
159
+    {
160
+        if ($amount === null) {
161
+            return '0';
162
+        }
163
+
164
+        $currency = currency(CurrencyAccessor::getDefaultCurrency());
165
+        $decimal = $currency->getDecimalMark();
166
+
167
+        if (substr($amount, -1) === $decimal) {
168
+            return '0';
169
+        }
170
+
171
+        return $amount;
172
+    }
173
+
174
+    /**
175
+     * Expects formatted simple amount: e.g. 1,000.00 or 1.000,00
176
+     *
177
+     * Returns sanitized amount in cents as integer: e.g. 100000
178
+     */
179
+    protected function convertAmountToCents(string $amount): int
108 180
     {
109
-        return (string) money($amount, 'USD')->getAmount();
181
+        return money($amount, CurrencyAccessor::getDefaultCurrency(), true)->getAmount();
110 182
     }
111 183
 }

+ 7
- 7
app/Contracts/AccountHandler.php Dosyayı Görüntüle

@@ -6,19 +6,19 @@ use App\DTO\AccountBalanceDTO;
6 6
 use App\DTO\AccountBalanceReportDTO;
7 7
 use App\Enums\Accounting\AccountCategory;
8 8
 use App\Models\Accounting\Account;
9
-use App\ValueObjects\BalanceValue;
9
+use App\ValueObjects\Money;
10 10
 
11 11
 interface AccountHandler
12 12
 {
13
-    public function getDebitBalance(Account $account, string $startDate, string $endDate): BalanceValue;
13
+    public function getDebitBalance(Account $account, string $startDate, string $endDate): Money;
14 14
 
15
-    public function getCreditBalance(Account $account, string $startDate, string $endDate): BalanceValue;
15
+    public function getCreditBalance(Account $account, string $startDate, string $endDate): Money;
16 16
 
17
-    public function getNetMovement(Account $account, string $startDate, string $endDate): BalanceValue;
17
+    public function getNetMovement(Account $account, string $startDate, string $endDate): Money;
18 18
 
19
-    public function getStartingBalance(Account $account, string $startDate): ?BalanceValue;
19
+    public function getStartingBalance(Account $account, string $startDate): ?Money;
20 20
 
21
-    public function getEndingBalance(Account $account, string $startDate, string $endDate): ?BalanceValue;
21
+    public function getEndingBalance(Account $account, string $startDate, string $endDate): ?Money;
22 22
 
23 23
     public function calculateNetMovementByCategory(AccountCategory $category, int $debitBalance, int $creditBalance): int;
24 24
 
@@ -28,7 +28,7 @@ interface AccountHandler
28 28
 
29 29
     public function buildAccountBalanceReport(string $startDate, string $endDate): AccountBalanceReportDTO;
30 30
 
31
-    public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): BalanceValue;
31
+    public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): Money;
32 32
 
33 33
     public function getAccountCategoryOrder(): array;
34 34
 

+ 3
- 0
app/Enums/Banking/BankAccountType.php Dosyayı Görüntüle

@@ -2,10 +2,13 @@
2 2
 
3 3
 namespace App\Enums\Banking;
4 4
 
5
+use App\Enums\Concerns\ParsesEnum;
5 6
 use Filament\Support\Contracts\HasLabel;
6 7
 
7 8
 enum BankAccountType: string implements HasLabel
8 9
 {
10
+    use ParsesEnum;
11
+
9 12
     case Investment = 'investment';
10 13
     case Credit = 'credit';
11 14
     case Depository = 'depository';

+ 7
- 7
app/Facades/Accounting.php Dosyayı Görüntüle

@@ -7,20 +7,20 @@ use App\DTO\AccountBalanceDTO;
7 7
 use App\DTO\AccountBalanceReportDTO;
8 8
 use App\Enums\Accounting\AccountCategory;
9 9
 use App\Models\Accounting\Account;
10
-use App\ValueObjects\BalanceValue;
10
+use App\ValueObjects\Money;
11 11
 use Illuminate\Support\Facades\Facade;
12 12
 
13 13
 /**
14
- * @method static BalanceValue getDebitBalance(Account $account, string $startDate, string $endDate)
15
- * @method static BalanceValue getCreditBalance(Account $account, string $startDate, string $endDate)
16
- * @method static BalanceValue getNetMovement(Account $account, string $startDate, string $endDate)
17
- * @method static BalanceValue|null getStartingBalance(Account $account, string $startDate)
18
- * @method static BalanceValue|null getEndingBalance(Account $account, string $startDate, string $endDate)
14
+ * @method static Money getDebitBalance(Account $account, string $startDate, string $endDate)
15
+ * @method static Money getCreditBalance(Account $account, string $startDate, string $endDate)
16
+ * @method static Money getNetMovement(Account $account, string $startDate, string $endDate)
17
+ * @method static Money|null getStartingBalance(Account $account, string $startDate)
18
+ * @method static Money|null getEndingBalance(Account $account, string $startDate, string $endDate)
19 19
  * @method static int calculateNetMovementByCategory(AccountCategory $category, int $debitBalance, int $creditBalance)
20 20
  * @method static array getBalances(Account $account, string $startDate, string $endDate)
21 21
  * @method static AccountBalanceDTO formatBalances(array $balances)
22 22
  * @method static AccountBalanceReportDTO buildAccountBalanceReport(string $startDate, string $endDate)
23
- * @method static BalanceValue getTotalBalanceForAllBankAccounts(string $startDate, string $endDate)
23
+ * @method static Money getTotalBalanceForAllBankAccounts(string $startDate, string $endDate)
24 24
  * @method static array getAccountCategoryOrder()
25 25
  * @method static string getEarliestTransactionDate()
26 26
  *

+ 0
- 10
app/Filament/Company/Clusters/Settings/Resources/CurrencyResource.php Dosyayı Görüntüle

@@ -12,7 +12,6 @@ use App\Models\Setting\Currency;
12 12
 use App\Models\Setting\Currency as CurrencyModel;
13 13
 use App\Utilities\Currency\CurrencyAccessor;
14 14
 use Closure;
15
-use Filament\Facades\Filament;
16 15
 use Filament\Forms;
17 16
 use Filament\Forms\Form;
18 17
 use Filament\Resources\Resource;
@@ -40,15 +39,6 @@ class CurrencyResource extends Resource
40 39
         return translate($modelLabel);
41 40
     }
42 41
 
43
-    public static function getNavigationParentItem(): ?string
44
-    {
45
-        if (Filament::hasTopNavigation()) {
46
-            return translate('Finance');
47
-        }
48
-
49
-        return null;
50
-    }
51
-
52 42
     public static function form(Form $form): Form
53 43
     {
54 44
         return $form

+ 47
- 36
app/Filament/Company/Pages/Accounting/Transactions.php Dosyayı Görüntüle

@@ -6,16 +6,14 @@ use App\Concerns\HasJournalEntryActions;
6 6
 use App\Enums\Accounting\AccountCategory;
7 7
 use App\Enums\Accounting\JournalEntryType;
8 8
 use App\Enums\Accounting\TransactionType;
9
-use App\Enums\Setting\DateFormat;
10 9
 use App\Facades\Accounting;
11 10
 use App\Filament\Company\Pages\Service\ConnectedAccount;
12
-use App\Forms\Components\DateRangeSelect;
13
-use App\Forms\Components\JournalEntryRepeater;
11
+use App\Filament\Forms\Components\DateRangeSelect;
12
+use App\Filament\Forms\Components\JournalEntryRepeater;
14 13
 use App\Models\Accounting\Account;
15 14
 use App\Models\Accounting\Transaction;
16 15
 use App\Models\Banking\BankAccount;
17 16
 use App\Models\Company;
18
-use App\Models\Setting\Localization;
19 17
 use App\Utilities\Currency\CurrencyAccessor;
20 18
 use App\Utilities\Currency\CurrencyConverter;
21 19
 use Awcodes\TableRepeater\Header;
@@ -41,7 +39,6 @@ use Filament\Support\Enums\FontWeight;
41 39
 use Filament\Support\Enums\IconPosition;
42 40
 use Filament\Support\Enums\IconSize;
43 41
 use Filament\Support\Enums\MaxWidth;
44
-use Filament\Support\RawJs;
45 42
 use Filament\Tables;
46 43
 use Filament\Tables\Concerns\InteractsWithTable;
47 44
 use Filament\Tables\Contracts\HasTable;
@@ -108,7 +105,8 @@ class Transactions extends Page implements HasTable
108 105
                     ->groupedIcon(null)
109 106
                     ->modalHeading('Journal Entry')
110 107
                     ->mutateFormDataUsing(static fn (array $data) => array_merge($data, ['type' => TransactionType::Journal]))
111
-                    ->afterFormFilled(fn () => $this->resetJournalEntryAmounts()),
108
+                    ->afterFormFilled(fn () => $this->resetJournalEntryAmounts())
109
+                    ->after(fn (Transaction $transaction) => $transaction->updateAmountIfBalanced()),
112 110
                 Actions\Action::make('connectBank')
113 111
                     ->label('Connect Your Bank')
114 112
                     ->url(ConnectedAccount::getUrl()),
@@ -146,8 +144,7 @@ class Transactions extends Page implements HasTable
146 144
             ->schema([
147 145
                 Forms\Components\DatePicker::make('posted_at')
148 146
                     ->label('Date')
149
-                    ->required()
150
-                    ->displayFormat('Y-m-d'),
147
+                    ->required(),
151 148
                 Forms\Components\TextInput::make('description')
152 149
                     ->label('Description'),
153 150
                 Forms\Components\Select::make('bank_account_id')
@@ -225,11 +222,7 @@ class Transactions extends Page implements HasTable
225 222
                 Tables\Columns\TextColumn::make('posted_at')
226 223
                     ->label('Date')
227 224
                     ->sortable()
228
-                    ->formatStateUsing(static function ($state) {
229
-                        $dateFormat = Localization::firstOrFail()->date_format->value ?? DateFormat::DEFAULT;
230
-
231
-                        return Carbon::parse($state)->translatedFormat($dateFormat);
232
-                    }),
225
+                    ->localizeDate(),
233 226
                 Tables\Columns\TextColumn::make('description')
234 227
                     ->limit(30)
235 228
                     ->label('Description'),
@@ -237,21 +230,20 @@ class Transactions extends Page implements HasTable
237 230
                     ->label('Account'),
238 231
                 Tables\Columns\TextColumn::make('account.name')
239 232
                     ->label('Category')
240
-                    ->state(static fn (Transaction $record) => $record->account->name ?? 'Journal Entry'),
233
+                    ->state(static fn (Transaction $transaction) => $transaction->account->name ?? 'Journal Entry'),
241 234
                 Tables\Columns\TextColumn::make('amount')
242 235
                     ->label('Amount')
243
-                    ->weight(static fn (Transaction $record) => $record->reviewed ? null : FontWeight::SemiBold)
236
+                    ->weight(static fn (Transaction $transaction) => $transaction->reviewed ? null : FontWeight::SemiBold)
244 237
                     ->color(
245
-                        static fn (Transaction $record) => match ($record->type) {
238
+                        static fn (Transaction $transaction) => match ($transaction->type) {
246 239
                             TransactionType::Deposit => Color::rgb('rgb(' . Color::Green[700] . ')'),
247 240
                             TransactionType::Journal => 'primary',
248 241
                             default => null,
249 242
                         }
250 243
                     )
251
-                    ->currency(static fn (Transaction $record) => $record->bankAccount->account->currency_code ?? 'USD', true)
252
-                    ->state(fn (Transaction $record) => $record->type->isJournal() ? $record->journalEntries->first()->amount : $record->amount),
244
+                    ->currency(static fn (Transaction $transaction) => $transaction->bankAccount->account->currency_code ?? CurrencyAccessor::getDefaultCurrency(), true),
253 245
             ])
254
-            ->recordClasses(static fn (Transaction $record) => $record->reviewed ? 'bg-primary-300/10' : null)
246
+            ->recordClasses(static fn (Transaction $transaction) => $transaction->reviewed ? 'bg-primary-300/10' : null)
255 247
             ->defaultSort('posted_at', 'desc')
256 248
             ->filters([
257 249
                 Tables\Filters\Filter::make('filters')
@@ -336,45 +328,47 @@ class Transactions extends Page implements HasTable
336 328
                 Tables\Actions\Action::make('markAsReviewed')
337 329
                     ->label('Mark as Reviewed')
338 330
                     ->view('filament.company.components.tables.actions.mark-as-reviewed')
339
-                    ->icon(static fn (Transaction $record) => $record->reviewed ? 'heroicon-s-check-circle' : 'heroicon-o-check-circle')
340
-                    ->color(static fn (Transaction $record, Tables\Actions\Action $action) => match (static::determineTransactionState($record, $action)) {
331
+                    ->icon(static fn (Transaction $transaction) => $transaction->reviewed ? 'heroicon-s-check-circle' : 'heroicon-o-check-circle')
332
+                    ->color(static fn (Transaction $transaction, Tables\Actions\Action $action) => match (static::determineTransactionState($transaction, $action)) {
341 333
                         'reviewed' => 'primary',
342 334
                         'unreviewed' => Color::rgb('rgb(' . Color::Gray[600] . ')'),
343 335
                         'uncategorized' => 'gray',
344 336
                     })
345
-                    ->tooltip(static fn (Transaction $record, Tables\Actions\Action $action) => match (static::determineTransactionState($record, $action)) {
337
+                    ->tooltip(static fn (Transaction $transaction, Tables\Actions\Action $action) => match (static::determineTransactionState($transaction, $action)) {
346 338
                         'reviewed' => 'Reviewed',
347 339
                         'unreviewed' => 'Mark as Reviewed',
348 340
                         'uncategorized' => 'Categorize first to mark as reviewed',
349 341
                     })
350
-                    ->disabled(fn (Transaction $record): bool => $record->isUncategorized())
351
-                    ->action(fn (Transaction $record) => $record->update(['reviewed' => ! $record->reviewed])),
342
+                    ->disabled(fn (Transaction $transaction): bool => $transaction->isUncategorized())
343
+                    ->action(fn (Transaction $transaction) => $transaction->update(['reviewed' => ! $transaction->reviewed])),
352 344
                 Tables\Actions\ActionGroup::make([
353 345
                     Tables\Actions\EditAction::make('updateTransaction')
354 346
                         ->label('Edit Transaction')
355 347
                         ->modalHeading('Edit Transaction')
356 348
                         ->modalWidth(MaxWidth::ThreeExtraLarge)
357 349
                         ->form(fn (Form $form) => $this->transactionForm($form))
358
-                        ->hidden(static fn (Transaction $record) => $record->type->isJournal()),
350
+                        ->hidden(static fn (Transaction $transaction) => $transaction->type->isJournal()),
359 351
                     Tables\Actions\EditAction::make('updateJournalTransaction')
360 352
                         ->label('Edit Journal Transaction')
361 353
                         ->modalHeading('Journal Entry')
362 354
                         ->modalWidth(MaxWidth::Screen)
363 355
                         ->form(fn (Form $form) => $this->journalTransactionForm($form))
364
-                        ->afterFormFilled(function (Transaction $record) {
365
-                            $debitAmounts = $record->journalEntries->where('type', JournalEntryType::Debit)->sum('amount');
366
-                            $creditAmounts = $record->journalEntries->where('type', JournalEntryType::Credit)->sum('amount');
356
+                        ->afterFormFilled(function (Transaction $transaction) {
357
+                            $debitAmounts = $transaction->journalEntries->sumDebits()->getAmount();
358
+                            $creditAmounts = $transaction->journalEntries->sumCredits()->getAmount();
367 359
 
368 360
                             $this->setDebitAmount($debitAmounts);
369 361
                             $this->setCreditAmount($creditAmounts);
370 362
                         })
371
-                        ->visible(static fn (Transaction $record) => $record->type->isJournal()),
363
+                        ->modalSubmitAction(fn (Actions\StaticAction $action) => $action->disabled(! $this->isJournalEntryBalanced()))
364
+                        ->after(fn (Transaction $transaction) => $transaction->updateAmountIfBalanced())
365
+                        ->visible(static fn (Transaction $transaction) => $transaction->type->isJournal()),
372 366
                     Tables\Actions\DeleteAction::make(),
373 367
                     Tables\Actions\ReplicateAction::make()
374 368
                         ->excludeAttributes(['created_by', 'updated_by', 'created_at', 'updated_at'])
375 369
                         ->modal(false)
376
-                        ->beforeReplicaSaved(static function (Transaction $replica) {
377
-                            $replica->description = '(Copy of) ' . $replica->description;
370
+                        ->beforeReplicaSaved(static function (Transaction $transaction) {
371
+                            $transaction->description = '(Copy of) ' . $transaction->description;
378 372
                         }),
379 373
                 ])
380 374
                     ->dropdownPlacement('bottom-start')
@@ -503,6 +497,23 @@ class Transactions extends Page implements HasTable
503 497
             ->schema($this->getJournalEntriesTableRepeaterSchema())
504 498
             ->streamlined()
505 499
             ->deletable(fn (JournalEntryRepeater $repeater) => $repeater->getItemsCount() > 2)
500
+            ->deleteAction(function (Forms\Components\Actions\Action $action) {
501
+                return $action
502
+                    ->action(function (array $arguments, JournalEntryRepeater $component): void {
503
+                        $items = $component->getState();
504
+
505
+                        $amount = $items[$arguments['item']]['amount'];
506
+                        $type = $items[$arguments['item']]['type'];
507
+
508
+                        $this->updateJournalEntryAmount(JournalEntryType::parse($type), '0.00', $amount);
509
+
510
+                        unset($items[$arguments['item']]);
511
+
512
+                        $component->state($items);
513
+
514
+                        $component->callAfterStateUpdated();
515
+                    });
516
+            })
506 517
             ->minItems(2)
507 518
             ->defaultItems(2)
508 519
             ->addable(false)
@@ -553,7 +564,7 @@ class Transactions extends Page implements HasTable
553 564
             TextInput::make('amount')
554 565
                 ->label('Amount')
555 566
                 ->live()
556
-                ->mask(RawJs::make('$money($input)'))
567
+                ->mask(moneyMask(CurrencyAccessor::getDefaultCurrency()))
557 568
                 ->afterStateUpdated(function (Get $get, Set $set, ?string $state, ?string $old) {
558 569
                     $this->updateJournalEntryAmount(JournalEntryType::parse($get('type')), $state, $old);
559 570
                 })
@@ -683,13 +694,13 @@ class Transactions extends Page implements HasTable
683 694
         }
684 695
     }
685 696
 
686
-    protected static function determineTransactionState(Transaction $record, Tables\Actions\Action $action): string
697
+    protected static function determineTransactionState(Transaction $transaction, Tables\Actions\Action $action): string
687 698
     {
688
-        if ($record->reviewed) {
699
+        if ($transaction->reviewed) {
689 700
             return 'reviewed';
690 701
         }
691 702
 
692
-        if ($record->reviewed === false && $action->isEnabled()) {
703
+        if ($transaction->reviewed === false && $action->isEnabled()) {
693 704
             return 'unreviewed';
694 705
         }
695 706
 
@@ -743,6 +754,6 @@ class Transactions extends Page implements HasTable
743 754
 
744 755
     protected function getBalanceForAllAccounts(): string
745 756
     {
746
-        return Accounting::getTotalBalanceForAllBankAccounts($this->fiscalYearStartDate, $this->fiscalYearEndDate)->formatted();
757
+        return Accounting::getTotalBalanceForAllBankAccounts($this->fiscalYearStartDate, $this->fiscalYearEndDate)->format();
747 758
     }
748 759
 }

+ 1
- 1
app/Filament/Company/Pages/Reports/AccountBalances.php Dosyayı Görüntüle

@@ -3,7 +3,7 @@
3 3
 namespace App\Filament\Company\Pages\Reports;
4 4
 
5 5
 use App\DTO\AccountBalanceReportDTO;
6
-use App\Forms\Components\DateRangeSelect;
6
+use App\Filament\Forms\Components\DateRangeSelect;
7 7
 use App\Models\Company;
8 8
 use App\Services\AccountBalancesExportService;
9 9
 use App\Services\AccountService;

+ 13
- 74
app/Filament/Company/Resources/Banking/AccountResource.php Dosyayı Görüntüle

@@ -2,15 +2,12 @@
2 2
 
3 3
 namespace App\Filament\Company\Resources\Banking;
4 4
 
5
-use App\Actions\OptionAction\CreateCurrency;
6 5
 use App\Enums\Accounting\AccountCategory;
7 6
 use App\Enums\Banking\BankAccountType;
8
-use App\Facades\Forex;
9 7
 use App\Filament\Company\Resources\Banking\AccountResource\Pages;
8
+use App\Filament\Forms\Components\CreateCurrencySelect;
10 9
 use App\Models\Accounting\AccountSubtype;
11 10
 use App\Models\Banking\BankAccount;
12
-use App\Utilities\Currency\CurrencyAccessor;
13
-use BackedEnum;
14 11
 use Filament\Forms;
15 12
 use Filament\Forms\Form;
16 13
 use Filament\Resources\Resource;
@@ -19,7 +16,6 @@ use Filament\Tables;
19 16
 use Filament\Tables\Table;
20 17
 use Illuminate\Support\Collection;
21 18
 use Illuminate\Support\Facades\Auth;
22
-use Illuminate\Support\Facades\DB;
23 19
 use Illuminate\Validation\Rules\Unique;
24 20
 use Wallo\FilamentSelectify\Components\ToggleButton;
25 21
 
@@ -49,14 +45,14 @@ class AccountResource extends Resource
49 45
                             ->columnSpan(1)
50 46
                             ->default(BankAccountType::DEFAULT)
51 47
                             ->live()
52
-                            ->afterStateUpdated(static function (Forms\Set $set, $state, ?BankAccount $record, string $operation) {
48
+                            ->afterStateUpdated(static function (Forms\Set $set, $state, ?BankAccount $bankAccount, string $operation) {
53 49
                                 if ($operation === 'create') {
54 50
                                     $set('account.subtype_id', null);
55
-                                } elseif ($operation === 'edit' && $record !== null) {
56
-                                    if ($state !== $record->type->value) {
51
+                                } elseif ($operation === 'edit' && $bankAccount !== null) {
52
+                                    if ($state !== $bankAccount->type->value) {
57 53
                                         $set('account.subtype_id', null);
58 54
                                     } else {
59
-                                        $set('account.subtype_id', $record->account->subtype_id);
55
+                                        $set('account.subtype_id', $bankAccount->account->subtype_id);
60 56
                                     }
61 57
                                 }
62 58
                             })
@@ -66,12 +62,7 @@ class AccountResource extends Resource
66 62
                             ->relationship('account')
67 63
                             ->schema([
68 64
                                 Forms\Components\Select::make('subtype_id')
69
-                                    ->options(static function (Forms\Get $get) {
70
-                                        $typeValue = $get('data.type', true); // Bug: $get('type') returns string on edit, but returns Enum type on create
71
-                                        $typeString = $typeValue instanceof BackedEnum ? $typeValue->value : $typeValue;
72
-
73
-                                        return static::groupSubtypesBySubtypeType($typeString);
74
-                                    })
65
+                                    ->options(static fn (Forms\Get $get) => static::groupSubtypesBySubtypeType(BankAccountType::parse($get('data.type', true))))
75 66
                                     ->localizeLabel()
76 67
                                     ->searchable()
77 68
                                     ->live()
@@ -79,67 +70,15 @@ class AccountResource extends Resource
79 70
                             ]),
80 71
                         Forms\Components\Group::make()
81 72
                             ->relationship('account')
82
-                            ->columns(2)
73
+                            ->columns()
83 74
                             ->columnSpanFull()
84 75
                             ->schema([
85 76
                                 Forms\Components\TextInput::make('name')
86 77
                                     ->maxLength(100)
87 78
                                     ->localizeLabel()
88 79
                                     ->required(),
89
-                                Forms\Components\Select::make('currency_code')
90
-                                    ->localizeLabel('Currency')
91
-                                    ->relationship('currency', 'name')
92
-                                    ->default(CurrencyAccessor::getDefaultCurrency())
93
-                                    ->preload()
94
-                                    ->searchable()
95
-                                    ->live()
96
-                                    ->required()
97
-                                    ->createOptionForm([
98
-                                        Forms\Components\Select::make('code')
99
-                                            ->localizeLabel()
100
-                                            ->searchable()
101
-                                            ->options(CurrencyAccessor::getAvailableCurrencies())
102
-                                            ->live()
103
-                                            ->afterStateUpdated(static function (callable $set, $state) {
104
-                                                if ($state === null) {
105
-                                                    return;
106
-                                                }
107
-
108
-                                                $currency_code = currency($state);
109
-                                                $defaultCurrencyCode = currency()->getCurrency();
110
-                                                $forexEnabled = Forex::isEnabled();
111
-                                                $exchangeRate = $forexEnabled ? Forex::getCachedExchangeRate($defaultCurrencyCode, $state) : null;
112
-
113
-                                                $set('name', $currency_code->getName() ?? '');
114
-
115
-                                                if ($forexEnabled && $exchangeRate !== null) {
116
-                                                    $set('rate', $exchangeRate);
117
-                                                }
118
-                                            })
119
-                                            ->required(),
120
-                                        Forms\Components\TextInput::make('name')
121
-                                            ->localizeLabel()
122
-                                            ->maxLength(100)
123
-                                            ->required(),
124
-                                        Forms\Components\TextInput::make('rate')
125
-                                            ->localizeLabel()
126
-                                            ->numeric()
127
-                                            ->required(),
128
-                                    ])->createOptionAction(static function (Forms\Components\Actions\Action $action) {
129
-                                        return $action
130
-                                            ->label('Add Currency')
131
-                                            ->slideOver()
132
-                                            ->modalWidth('md')
133
-                                            ->action(static function (array $data) {
134
-                                                return DB::transaction(static function () use ($data) {
135
-                                                    $code = $data['code'];
136
-                                                    $name = $data['name'];
137
-                                                    $rate = $data['rate'];
138
-
139
-                                                    return (new CreateCurrency())->create($code, $name, $rate);
140
-                                                });
141
-                                            });
142
-                                    }),
80
+                                CreateCurrencySelect::make('currency_code')
81
+                                    ->relationship('currency', 'name'),
143 82
                             ]),
144 83
                         Forms\Components\Group::make()
145 84
                             ->columns()
@@ -209,11 +148,11 @@ class AccountResource extends Resource
209 148
         ];
210 149
     }
211 150
 
212
-    public static function groupSubtypesBySubtypeType($typeString): array
151
+    public static function groupSubtypesBySubtypeType(BankAccountType $bankAccountType): array
213 152
     {
214
-        $category = match ($typeString) {
215
-            BankAccountType::Depository->value, BankAccountType::Investment->value => AccountCategory::Asset,
216
-            BankAccountType::Credit->value, BankAccountType::Loan->value => AccountCategory::Liability,
153
+        $category = match ($bankAccountType) {
154
+            BankAccountType::Depository, BankAccountType::Investment => AccountCategory::Asset,
155
+            BankAccountType::Credit, BankAccountType::Loan => AccountCategory::Liability,
217 156
             default => null,
218 157
         };
219 158
 

+ 0
- 11
app/Filament/Company/Resources/Banking/AccountResource/Pages/CreateAccount.php Dosyayı Görüntüle

@@ -4,8 +4,6 @@ namespace App\Filament\Company\Resources\Banking\AccountResource\Pages;
4 4
 
5 5
 use App\Filament\Company\Resources\Banking\AccountResource;
6 6
 use Filament\Resources\Pages\CreateRecord;
7
-use Illuminate\Database\Eloquent\Model;
8
-use Illuminate\Support\Facades\Log;
9 7
 
10 8
 class CreateAccount extends CreateRecord
11 9
 {
@@ -20,15 +18,6 @@ class CreateAccount extends CreateRecord
20 18
     {
21 19
         $data['enabled'] = (bool) ($data['enabled'] ?? false);
22 20
 
23
-        Log::info('CreateAccount::mutateFormDataBeforeCreate', $data);
24
-
25 21
         return $data;
26 22
     }
27
-
28
-    protected function handleRecordCreation(array $data): Model
29
-    {
30
-        Log::info('CreateAccount::handleRecordCreation', $data);
31
-
32
-        return parent::handleRecordCreation($data);
33
-    }
34 23
 }

+ 70
- 0
app/Filament/Forms/Components/CreateCurrencySelect.php Dosyayı Görüntüle

@@ -0,0 +1,70 @@
1
+<?php
2
+
3
+namespace App\Filament\Forms\Components;
4
+
5
+use App\Actions\OptionAction\CreateCurrency;
6
+use App\Utilities\Currency\CurrencyAccessor;
7
+use App\Utilities\Currency\CurrencyConverter;
8
+use Filament\Forms\Components\Actions\Action;
9
+use Filament\Forms\Components\Select;
10
+use Filament\Forms\Components\TextInput;
11
+use Filament\Forms\Set;
12
+use Filament\Support\Enums\MaxWidth;
13
+use Illuminate\Support\Facades\DB;
14
+
15
+class CreateCurrencySelect extends Select
16
+{
17
+    protected function setUp(): void
18
+    {
19
+        parent::setUp();
20
+
21
+        $this->localizeLabel('Currency')
22
+            ->default(CurrencyAccessor::getDefaultCurrency())
23
+            ->preload()
24
+            ->searchable()
25
+            ->live()
26
+            ->required()
27
+            ->createOptionForm($this->createCurrencyForm())
28
+            ->createOptionAction(fn (Action $action) => $this->createCurrencyAction($action));
29
+    }
30
+
31
+    protected function createCurrencyForm(): array
32
+    {
33
+        return [
34
+            Select::make('code')
35
+                ->localizeLabel()
36
+                ->searchable()
37
+                ->options(CurrencyAccessor::getAvailableCurrencies())
38
+                ->live()
39
+                ->afterStateUpdated(static function (Set $set, $state) {
40
+                    CurrencyConverter::handleCurrencyChange($set, $state);
41
+                })
42
+                ->required(),
43
+            TextInput::make('name')
44
+                ->localizeLabel()
45
+                ->maxLength(100)
46
+                ->required(),
47
+            TextInput::make('rate')
48
+                ->localizeLabel()
49
+                ->numeric()
50
+                ->required(),
51
+        ];
52
+    }
53
+
54
+    protected function createCurrencyAction(Action $action): Action
55
+    {
56
+        return $action
57
+            ->label('Add Currency')
58
+            ->slideOver()
59
+            ->modalWidth(MaxWidth::Medium)
60
+            ->action(static function (array $data) {
61
+                return DB::transaction(static function () use ($data) {
62
+                    $code = $data['code'];
63
+                    $name = $data['name'];
64
+                    $rate = $data['rate'];
65
+
66
+                    return CreateCurrency::create($code, $name, $rate);
67
+                });
68
+            });
69
+    }
70
+}

app/Forms/Components/DateRangeSelect.php → app/Filament/Forms/Components/DateRangeSelect.php Dosyayı Görüntüle

@@ -1,6 +1,6 @@
1 1
 <?php
2 2
 
3
-namespace App\Forms\Components;
3
+namespace App\Filament\Forms\Components;
4 4
 
5 5
 use App\Facades\Accounting;
6 6
 use App\Models\Company;

app/Forms/Components/JournalEntryRepeater.php → app/Filament/Forms/Components/JournalEntryRepeater.php Dosyayı Görüntüle

@@ -1,6 +1,6 @@
1 1
 <?php
2 2
 
3
-namespace App\Forms\Components;
3
+namespace App\Filament\Forms\Components;
4 4
 
5 5
 use Awcodes\TableRepeater\Components\TableRepeater;
6 6
 use Closure;
@@ -30,6 +30,6 @@ class JournalEntryRepeater extends TableRepeater
30 30
 
31 31
     public function getView(): string
32 32
     {
33
-        return 'forms.components.journal-entry-repeater';
33
+        return 'filament.forms.components.journal-entry-repeater';
34 34
     }
35 35
 }

+ 1
- 1
app/Listeners/UpdateAccountBalances.php Dosyayı Görüntüle

@@ -36,7 +36,7 @@ class UpdateAccountBalances
36 36
                 /** @var BankAccount $bankAccount */
37 37
                 $account = $bankAccount->account;
38 38
 
39
-                $oldConvertedBalanceInCents = $account->ending_balance->convert()->getConvertedValue();
39
+                $oldConvertedBalanceInCents = $account->ending_balance->convert()->getConvertedAmount();
40 40
                 $ratio = $event->newRate / $event->oldRate;
41 41
                 $newConvertedBalance = bcmul($oldConvertedBalanceInCents, $ratio, 2);
42 42
                 $newConvertedBalanceInCents = (int) round($newConvertedBalance);

+ 7
- 12
app/Models/Accounting/JournalEntry.php Dosyayı Görüntüle

@@ -2,7 +2,8 @@
2 2
 
3 3
 namespace App\Models\Accounting;
4 4
 
5
-use App\Casts\MoneyCast;
5
+use App\Casts\JournalEntryCast;
6
+use App\Collections\Accounting\JournalEntryCollection;
6 7
 use App\Concerns\Blamable;
7 8
 use App\Concerns\CompanyOwned;
8 9
 use App\Enums\Accounting\JournalEntryType;
@@ -10,7 +11,6 @@ use App\Models\Banking\BankAccount;
10 11
 use App\Observers\JournalEntryObserver;
11 12
 use Database\Factories\Accounting\JournalEntryFactory;
12 13
 use Illuminate\Database\Eloquent\Attributes\ObservedBy;
13
-use Illuminate\Database\Eloquent\Builder;
14 14
 use Illuminate\Database\Eloquent\Factories\Factory;
15 15
 use Illuminate\Database\Eloquent\Factories\HasFactory;
16 16
 use Illuminate\Database\Eloquent\Model;
@@ -36,7 +36,7 @@ class JournalEntry extends Model
36 36
 
37 37
     protected $casts = [
38 38
         'type' => JournalEntryType::class,
39
-        'amount' => MoneyCast::class,
39
+        'amount' => JournalEntryCast::class,
40 40
     ];
41 41
 
42 42
     public function account(): BelongsTo
@@ -59,18 +59,13 @@ class JournalEntry extends Model
59 59
         return $this->account->isUncategorized();
60 60
     }
61 61
 
62
-    public function scopeDebit(Builder $query): Builder
63
-    {
64
-        return $query->where('type', JournalEntryType::Debit);
65
-    }
66
-
67
-    public function scopeCredit(Builder $query): Builder
62
+    protected static function newFactory(): Factory
68 63
     {
69
-        return $query->where('type', JournalEntryType::Credit);
64
+        return JournalEntryFactory::new();
70 65
     }
71 66
 
72
-    protected static function newFactory(): Factory
67
+    public function newCollection(array $models = []): JournalEntryCollection
73 68
     {
74
-        return JournalEntryFactory::new();
69
+        return new JournalEntryCollection($models);
75 70
     }
76 71
 }

+ 8
- 0
app/Models/Accounting/Transaction.php Dosyayı Görüntüle

@@ -76,6 +76,14 @@ class Transaction extends Model
76 76
         return $this->journalEntries->contains(fn (JournalEntry $entry) => $entry->account->isUncategorized());
77 77
     }
78 78
 
79
+    public function updateAmountIfBalanced(): void
80
+    {
81
+        if ($this->journalEntries->areBalanced() && $this->journalEntries->sumDebits()->formatSimple() !== $this->getAttributeValue('amount')) {
82
+            $this->setAttribute('amount', $this->journalEntries->sumDebits()->formatSimple());
83
+            $this->save();
84
+        }
85
+    }
86
+
79 87
     protected static function newFactory(): Factory
80 88
     {
81 89
         return TransactionFactory::new();

+ 6
- 14
app/Observers/JournalEntryObserver.php Dosyayı Görüntüle

@@ -15,33 +15,25 @@ class JournalEntryObserver
15 15
     }
16 16
 
17 17
     /**
18
-     * Handle the JournalEntry "deleting" event.
19
-     */
20
-    public function deleting(JournalEntry $journalEntry): void
21
-    {
22
-        //
23
-    }
24
-
25
-    /**
26
-     * Handle the JournalEntry "deleted" event.
18
+     * Handle the JournalEntry "updated" event.
27 19
      */
28
-    public function deleted(JournalEntry $journalEntry): void
20
+    public function updated(JournalEntry $journalEntry): void
29 21
     {
30 22
         //
31 23
     }
32 24
 
33 25
     /**
34
-     * Handle the JournalEntry "restored" event.
26
+     * Handle the JournalEntry "deleting" event.
35 27
      */
36
-    public function restored(JournalEntry $journalEntry): void
28
+    public function deleting(JournalEntry $journalEntry): void
37 29
     {
38 30
         //
39 31
     }
40 32
 
41 33
     /**
42
-     * Handle the JournalEntry "force deleted" event.
34
+     * Handle the JournalEntry "deleted" event.
43 35
      */
44
-    public function forceDeleted(JournalEntry $journalEntry): void
36
+    public function deleted(JournalEntry $journalEntry): void
45 37
     {
46 38
         //
47 39
     }

+ 8
- 3
app/Observers/TransactionObserver.php Dosyayı Görüntüle

@@ -35,6 +35,8 @@ class TransactionObserver
35 35
      */
36 36
     public function updated(Transaction $transaction): void
37 37
     {
38
+        $transaction->refresh(); // DO NOT REMOVE
39
+
38 40
         if ($transaction->type->isJournal() || $this->hasRelevantChanges($transaction) === false) {
39 41
             return;
40 42
         }
@@ -105,10 +107,13 @@ class TransactionObserver
105 107
     private function getConvertedTransactionAmount(Transaction $transaction): string
106 108
     {
107 109
         $defaultCurrency = CurrencyAccessor::getDefaultCurrency();
108
-        $transactionCurrency = $transaction->bankAccount->account->currency_code; // only account which would have a different currency compared to the default currency
110
+        $bankAccountCurrency = $transaction->bankAccount->account->currency_code;
111
+        $chartAccountCurrency = $transaction->account->currency_code;
109 112
 
110
-        if ($transactionCurrency !== $defaultCurrency) {
111
-            return $this->convertToDefaultCurrency($transaction->amount, $transactionCurrency, $defaultCurrency);
113
+        if ($bankAccountCurrency !== $defaultCurrency) {
114
+            return $this->convertToDefaultCurrency($transaction->amount, $bankAccountCurrency, $defaultCurrency);
115
+        } elseif ($chartAccountCurrency !== $defaultCurrency) {
116
+            return $this->convertToDefaultCurrency($transaction->amount, $chartAccountCurrency, $defaultCurrency);
112 117
         }
113 118
 
114 119
         return $transaction->amount;

+ 14
- 0
app/Providers/MacroServiceProvider.php Dosyayı Görüntüle

@@ -4,7 +4,9 @@ namespace App\Providers;
4 4
 
5 5
 use Akaunting\Money\Currency;
6 6
 use Akaunting\Money\Money;
7
+use App\Enums\Setting\DateFormat;
7 8
 use App\Models\Accounting\AccountSubtype;
9
+use App\Models\Setting\Localization;
8 10
 use App\Utilities\Accounting\AccountCode;
9 11
 use App\Utilities\Currency\CurrencyAccessor;
10 12
 use BackedEnum;
@@ -12,6 +14,7 @@ use Closure;
12 14
 use Filament\Forms\Components\Field;
13 15
 use Filament\Forms\Components\TextInput;
14 16
 use Filament\Tables\Columns\TextColumn;
17
+use Illuminate\Support\Carbon;
15 18
 use Illuminate\Support\ServiceProvider;
16 19
 use Illuminate\Support\Str;
17 20
 
@@ -51,6 +54,17 @@ class MacroServiceProvider extends ServiceProvider
51 54
             return $this;
52 55
         });
53 56
 
57
+        TextColumn::macro('localizeDate', function (): static {
58
+            $localization = Localization::firstOrFail();
59
+
60
+            $dateFormat = $localization->date_format->value ?? DateFormat::DEFAULT;
61
+            $timezone = $localization->timezone ?? Carbon::now()->timezoneName;
62
+
63
+            $this->date($dateFormat, $timezone);
64
+
65
+            return $this;
66
+        });
67
+
54 68
         TextColumn::macro('currency', function (string | Closure | null $currency = null, ?bool $convert = null): static {
55 69
             $this->formatStateUsing(static function (TextColumn $column, $state) use ($currency, $convert): ?string {
56 70
                 if (blank($state)) {

+ 21
- 21
app/Services/AccountService.php Dosyayı Görüntüle

@@ -13,7 +13,7 @@ use App\Models\Accounting\Transaction;
13 13
 use App\Models\Banking\BankAccount;
14 14
 use App\Repositories\Accounting\JournalEntryRepository;
15 15
 use App\Utilities\Currency\CurrencyAccessor;
16
-use App\ValueObjects\BalanceValue;
16
+use App\ValueObjects\Money;
17 17
 use Illuminate\Database\Eloquent\Collection;
18 18
 
19 19
 class AccountService implements AccountHandler
@@ -25,30 +25,30 @@ class AccountService implements AccountHandler
25 25
         $this->journalEntryRepository = $journalEntryRepository;
26 26
     }
27 27
 
28
-    public function getDebitBalance(Account $account, string $startDate, string $endDate): BalanceValue
28
+    public function getDebitBalance(Account $account, string $startDate, string $endDate): Money
29 29
     {
30 30
         $amount = $this->journalEntryRepository->sumDebitAmounts($account, $startDate, $endDate);
31 31
 
32
-        return new BalanceValue($amount, $account->currency_code);
32
+        return new Money($amount, $account->currency_code);
33 33
     }
34 34
 
35
-    public function getCreditBalance(Account $account, string $startDate, string $endDate): BalanceValue
35
+    public function getCreditBalance(Account $account, string $startDate, string $endDate): Money
36 36
     {
37 37
         $amount = $this->journalEntryRepository->sumCreditAmounts($account, $startDate, $endDate);
38 38
 
39
-        return new BalanceValue($amount, $account->currency_code);
39
+        return new Money($amount, $account->currency_code);
40 40
     }
41 41
 
42
-    public function getNetMovement(Account $account, string $startDate, string $endDate): BalanceValue
42
+    public function getNetMovement(Account $account, string $startDate, string $endDate): Money
43 43
     {
44 44
         $debitBalance = $this->journalEntryRepository->sumDebitAmounts($account, $startDate, $endDate);
45 45
         $creditBalance = $this->journalEntryRepository->sumCreditAmounts($account, $startDate, $endDate);
46 46
         $netMovement = $this->calculateNetMovementByCategory($account->category, $debitBalance, $creditBalance);
47 47
 
48
-        return new BalanceValue($netMovement, $account->currency_code);
48
+        return new Money($netMovement, $account->currency_code);
49 49
     }
50 50
 
51
-    public function getStartingBalance(Account $account, string $startDate): ?BalanceValue
51
+    public function getStartingBalance(Account $account, string $startDate): ?Money
52 52
     {
53 53
         if (in_array($account->category, [AccountCategory::Expense, AccountCategory::Revenue], true)) {
54 54
             return null;
@@ -58,20 +58,20 @@ class AccountService implements AccountHandler
58 58
         $creditBalanceBefore = $this->journalEntryRepository->sumCreditAmounts($account, $startDate);
59 59
         $startingBalance = $this->calculateNetMovementByCategory($account->category, $debitBalanceBefore, $creditBalanceBefore);
60 60
 
61
-        return new BalanceValue($startingBalance, $account->currency_code);
61
+        return new Money($startingBalance, $account->currency_code);
62 62
     }
63 63
 
64
-    public function getEndingBalance(Account $account, string $startDate, string $endDate): ?BalanceValue
64
+    public function getEndingBalance(Account $account, string $startDate, string $endDate): ?Money
65 65
     {
66 66
         if (in_array($account->category, [AccountCategory::Expense, AccountCategory::Revenue], true)) {
67 67
             return null;
68 68
         }
69 69
 
70
-        $startingBalance = $this->getStartingBalance($account, $startDate)?->getValue();
71
-        $netMovement = $this->getNetMovement($account, $startDate, $endDate)->getValue();
70
+        $startingBalance = $this->getStartingBalance($account, $startDate)?->getAmount();
71
+        $netMovement = $this->getNetMovement($account, $startDate, $endDate)->getAmount();
72 72
         $endingBalance = $startingBalance + $netMovement;
73 73
 
74
-        return new BalanceValue($endingBalance, $account->currency_code);
74
+        return new Money($endingBalance, $account->currency_code);
75 75
     }
76 76
 
77 77
     public function calculateNetMovementByCategory(AccountCategory $category, int $debitBalance, int $creditBalance): int
@@ -84,9 +84,9 @@ class AccountService implements AccountHandler
84 84
 
85 85
     public function getBalances(Account $account, string $startDate, string $endDate): array
86 86
     {
87
-        $debitBalance = $this->getDebitBalance($account, $startDate, $endDate)->getValue();
88
-        $creditBalance = $this->getCreditBalance($account, $startDate, $endDate)->getValue();
89
-        $netMovement = $this->getNetMovement($account, $startDate, $endDate)->getValue();
87
+        $debitBalance = $this->getDebitBalance($account, $startDate, $endDate)->getAmount();
88
+        $creditBalance = $this->getCreditBalance($account, $startDate, $endDate)->getAmount();
89
+        $netMovement = $this->getNetMovement($account, $startDate, $endDate)->getAmount();
90 90
 
91 91
         $balances = [
92 92
             'debit_balance' => $debitBalance,
@@ -95,8 +95,8 @@ class AccountService implements AccountHandler
95 95
         ];
96 96
 
97 97
         if (! in_array($account->category, [AccountCategory::Expense, AccountCategory::Revenue], true)) {
98
-            $balances['starting_balance'] = $this->getStartingBalance($account, $startDate)?->getValue();
99
-            $balances['ending_balance'] = $this->getEndingBalance($account, $startDate, $endDate)?->getValue();
98
+            $balances['starting_balance'] = $this->getStartingBalance($account, $startDate)?->getAmount();
99
+            $balances['ending_balance'] = $this->getEndingBalance($account, $startDate, $endDate)?->getAmount();
100 100
         }
101 101
 
102 102
         return $balances;
@@ -187,7 +187,7 @@ class AccountService implements AccountHandler
187 187
         return new AccountBalanceReportDTO($accountCategories, $formattedReportTotalBalances);
188 188
     }
189 189
 
190
-    public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): BalanceValue
190
+    public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): Money
191 191
     {
192 192
         $bankAccountsAccounts = Account::where('accountable_type', BankAccount::class)
193 193
             ->get();
@@ -196,11 +196,11 @@ class AccountService implements AccountHandler
196 196
 
197 197
         // Get ending balance for each bank account
198 198
         foreach ($bankAccountsAccounts as $account) {
199
-            $endingBalance = $this->getEndingBalance($account, $startDate, $endDate)?->getValue() ?? 0;
199
+            $endingBalance = $this->getEndingBalance($account, $startDate, $endDate)?->getAmount() ?? 0;
200 200
             $totalBalance += $endingBalance;
201 201
         }
202 202
 
203
-        return new BalanceValue($totalBalance, CurrencyAccessor::getDefaultCurrency());
203
+        return new Money($totalBalance, CurrencyAccessor::getDefaultCurrency());
204 204
     }
205 205
 
206 206
     public function getAccountCategoryOrder(): array

+ 2
- 1
app/Utilities/Currency/ConfigureCurrencies.php Dosyayı Görüntüle

@@ -38,6 +38,7 @@ class ConfigureCurrencies
38 38
         $customCurrencies = [];
39 39
 
40 40
         foreach ($currencies as $currency) {
41
+            /** @var CurrencyModel $currency */
41 42
             $customCurrencies[$currency->code] = [
42 43
                 'name' => $currency->name,
43 44
                 'rate' => $currency->rate,
@@ -60,7 +61,7 @@ class ConfigureCurrencies
60 61
             try {
61 62
                 $name = Currencies::getName($code, app()->getLocale());
62 63
                 $existingCurrencies[$code]['name'] = ucwords($name);
63
-            } catch (MissingResourceException $e) {
64
+            } catch (MissingResourceException) {
64 65
                 $existingCurrencies[$code]['name'] = $currency['name'];
65 66
             }
66 67
         }

+ 17
- 0
app/Utilities/Currency/CurrencyConverter.php Dosyayı Görüntüle

@@ -2,6 +2,9 @@
2 2
 
3 3
 namespace App\Utilities\Currency;
4 4
 
5
+use App\Facades\Forex;
6
+use Filament\Forms\Set;
7
+
5 8
 class CurrencyConverter
6 9
 {
7 10
     public static function convertAndSet($newCurrency, $oldCurrency, $amount): ?string
@@ -31,4 +34,18 @@ class CurrencyConverter
31 34
     {
32 35
         return money($balance, $currency, true)->getAmount();
33 36
     }
37
+
38
+    public static function handleCurrencyChange(Set $set, $state): void
39
+    {
40
+        $currency = currency($state);
41
+        $defaultCurrencyCode = CurrencyAccessor::getDefaultCurrency();
42
+        $forexEnabled = Forex::isEnabled();
43
+        $exchangeRate = $forexEnabled ? Forex::getCachedExchangeRate($defaultCurrencyCode, $state) : null;
44
+
45
+        $set('name', $currency->getName() ?? '');
46
+
47
+        if ($forexEnabled && $exchangeRate !== null) {
48
+            $set('rate', $exchangeRate);
49
+        }
50
+    }
34 51
 }

+ 0
- 69
app/ValueObjects/BalanceValue.php Dosyayı Görüntüle

@@ -1,69 +0,0 @@
1
-<?php
2
-
3
-namespace App\ValueObjects;
4
-
5
-use App\Utilities\Currency\CurrencyAccessor;
6
-use App\Utilities\Currency\CurrencyConverter;
7
-
8
-class BalanceValue
9
-{
10
-    private int $value;
11
-
12
-    private string $currency;
13
-
14
-    private ?int $convertedValue = null;
15
-
16
-    public function __construct(int $value, string $currency)
17
-    {
18
-        $this->value = $value;
19
-        $this->currency = $currency;
20
-    }
21
-
22
-    public function getValue(): int
23
-    {
24
-        return $this->value;
25
-    }
26
-
27
-    public function getEffectiveValue(): int
28
-    {
29
-        return $this->convertedValue ?? $this->value;
30
-    }
31
-
32
-    public function getConvertedValue(): ?int
33
-    {
34
-        return $this->convertedValue;
35
-    }
36
-
37
-    public function getCurrency(): string
38
-    {
39
-        return $this->currency;
40
-    }
41
-
42
-    public function formatted(): string
43
-    {
44
-        return money($this->getEffectiveValue(), $this->getCurrency())->format();
45
-    }
46
-
47
-    public function formattedSimple(): string
48
-    {
49
-        return money($this->getEffectiveValue(), $this->getCurrency())->formatSimple();
50
-    }
51
-
52
-    public function formatWithCode(bool $codeBefore = false): string
53
-    {
54
-        return money($this->getEffectiveValue(), $this->getCurrency())->formatWithCode($codeBefore);
55
-    }
56
-
57
-    public function convert(): self
58
-    {
59
-        // The journal entry sums are stored in the default currency not the account currency (transaction amounts are stored in the account currency)
60
-        $fromCurrency = CurrencyAccessor::getDefaultCurrency();
61
-        $toCurrency = $this->currency;
62
-
63
-        if ($fromCurrency !== $toCurrency) {
64
-            $this->convertedValue = CurrencyConverter::convertBalance($this->value, $fromCurrency, $toCurrency);
65
-        }
66
-
67
-        return $this;
68
-    }
69
-}

+ 79
- 0
app/ValueObjects/Money.php Dosyayı Görüntüle

@@ -0,0 +1,79 @@
1
+<?php
2
+
3
+namespace App\ValueObjects;
4
+
5
+use App\Utilities\Currency\CurrencyAccessor;
6
+use App\Utilities\Currency\CurrencyConverter;
7
+
8
+class Money
9
+{
10
+    private int $amount;
11
+
12
+    private string $currencyCode;
13
+
14
+    private ?int $convertedAmount = null;
15
+
16
+    public function __construct(int $amount, string $currencyCode)
17
+    {
18
+        $this->amount = $amount;
19
+        $this->currencyCode = $currencyCode;
20
+    }
21
+
22
+    public function getAmount(): int
23
+    {
24
+        return $this->amount;
25
+    }
26
+
27
+    public function getCurrencyCode(): string
28
+    {
29
+        return $this->currencyCode;
30
+    }
31
+
32
+    public function getEffectiveAmount(): int
33
+    {
34
+        return $this->convertedAmount ?? $this->amount;
35
+    }
36
+
37
+    public function getConvertedAmount(): ?int
38
+    {
39
+        return $this->convertedAmount;
40
+    }
41
+
42
+    public function getValue(): float
43
+    {
44
+        return money($this->amount, $this->currencyCode)->getValue();
45
+    }
46
+
47
+    public function format(): string
48
+    {
49
+        return money($this->getEffectiveAmount(), $this->getCurrencyCode())->format();
50
+    }
51
+
52
+    public function formatSimple(): string
53
+    {
54
+        return money($this->getEffectiveAmount(), $this->getCurrencyCode())->formatSimple();
55
+    }
56
+
57
+    public function formatWithCode(bool $codeBefore = false): string
58
+    {
59
+        return money($this->getEffectiveAmount(), $this->getCurrencyCode())->formatWithCode($codeBefore);
60
+    }
61
+
62
+    public function convert(): self
63
+    {
64
+        // The journal entry sums are stored in the default currency not the account currency (transaction amounts are stored in the account currency)
65
+        $fromCurrency = CurrencyAccessor::getDefaultCurrency();
66
+        $toCurrency = $this->currencyCode;
67
+
68
+        if ($fromCurrency !== $toCurrency) {
69
+            $this->convertedAmount = CurrencyConverter::convertBalance($this->amount, $fromCurrency, $toCurrency);
70
+        }
71
+
72
+        return $this;
73
+    }
74
+
75
+    public function __toString(): string
76
+    {
77
+        return $this->formatSimple();
78
+    }
79
+}

+ 54
- 49
composer.lock Dosyayı Görüntüle

@@ -974,25 +974,25 @@
974 974
         },
975 975
         {
976 976
             "name": "brick/math",
977
-            "version": "0.11.0",
977
+            "version": "0.12.1",
978 978
             "source": {
979 979
                 "type": "git",
980 980
                 "url": "https://github.com/brick/math.git",
981
-                "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
981
+                "reference": "f510c0a40911935b77b86859eb5223d58d660df1"
982 982
             },
983 983
             "dist": {
984 984
                 "type": "zip",
985
-                "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
986
-                "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
985
+                "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1",
986
+                "reference": "f510c0a40911935b77b86859eb5223d58d660df1",
987 987
                 "shasum": ""
988 988
             },
989 989
             "require": {
990
-                "php": "^8.0"
990
+                "php": "^8.1"
991 991
             },
992 992
             "require-dev": {
993 993
                 "php-coveralls/php-coveralls": "^2.2",
994
-                "phpunit/phpunit": "^9.0",
995
-                "vimeo/psalm": "5.0.0"
994
+                "phpunit/phpunit": "^10.1",
995
+                "vimeo/psalm": "5.16.0"
996 996
             },
997 997
             "type": "library",
998 998
             "autoload": {
@@ -1012,12 +1012,17 @@
1012 1012
                 "arithmetic",
1013 1013
                 "bigdecimal",
1014 1014
                 "bignum",
1015
+                "bignumber",
1015 1016
                 "brick",
1016
-                "math"
1017
+                "decimal",
1018
+                "integer",
1019
+                "math",
1020
+                "mathematics",
1021
+                "rational"
1017 1022
             ],
1018 1023
             "support": {
1019 1024
                 "issues": "https://github.com/brick/math/issues",
1020
-                "source": "https://github.com/brick/math/tree/0.11.0"
1025
+                "source": "https://github.com/brick/math/tree/0.12.1"
1021 1026
             },
1022 1027
             "funding": [
1023 1028
                 {
@@ -1025,7 +1030,7 @@
1025 1030
                     "type": "github"
1026 1031
                 }
1027 1032
             ],
1028
-            "time": "2023-01-15T23:15:59+00:00"
1033
+            "time": "2023-11-29T23:19:16+00:00"
1029 1034
         },
1030 1035
         {
1031 1036
             "name": "carbonphp/carbon-doctrine-types",
@@ -1980,7 +1985,7 @@
1980 1985
         },
1981 1986
         {
1982 1987
             "name": "filament/actions",
1983
-            "version": "v3.2.71",
1988
+            "version": "v3.2.72",
1984 1989
             "source": {
1985 1990
                 "type": "git",
1986 1991
                 "url": "https://github.com/filamentphp/actions.git",
@@ -2033,16 +2038,16 @@
2033 2038
         },
2034 2039
         {
2035 2040
             "name": "filament/filament",
2036
-            "version": "v3.2.71",
2041
+            "version": "v3.2.72",
2037 2042
             "source": {
2038 2043
                 "type": "git",
2039 2044
                 "url": "https://github.com/filamentphp/panels.git",
2040
-                "reference": "e00510fb4edc73b027f784317381f791b47c22de"
2045
+                "reference": "28dc99ec5865982a1859a34e48ee88fb59f58313"
2041 2046
             },
2042 2047
             "dist": {
2043 2048
                 "type": "zip",
2044
-                "url": "https://api.github.com/repos/filamentphp/panels/zipball/e00510fb4edc73b027f784317381f791b47c22de",
2045
-                "reference": "e00510fb4edc73b027f784317381f791b47c22de",
2049
+                "url": "https://api.github.com/repos/filamentphp/panels/zipball/28dc99ec5865982a1859a34e48ee88fb59f58313",
2050
+                "reference": "28dc99ec5865982a1859a34e48ee88fb59f58313",
2046 2051
                 "shasum": ""
2047 2052
             },
2048 2053
             "require": {
@@ -2094,20 +2099,20 @@
2094 2099
                 "issues": "https://github.com/filamentphp/filament/issues",
2095 2100
                 "source": "https://github.com/filamentphp/filament"
2096 2101
             },
2097
-            "time": "2024-04-21T22:24:02+00:00"
2102
+            "time": "2024-04-28T08:39:16+00:00"
2098 2103
         },
2099 2104
         {
2100 2105
             "name": "filament/forms",
2101
-            "version": "v3.2.71",
2106
+            "version": "v3.2.72",
2102 2107
             "source": {
2103 2108
                 "type": "git",
2104 2109
                 "url": "https://github.com/filamentphp/forms.git",
2105
-                "reference": "eea1a3ec87bbe62d470dd0a26d9f4b8ef9cb5d39"
2110
+                "reference": "40988aa2cb540b17b86dc6684b9c3f57b9be3109"
2106 2111
             },
2107 2112
             "dist": {
2108 2113
                 "type": "zip",
2109
-                "url": "https://api.github.com/repos/filamentphp/forms/zipball/eea1a3ec87bbe62d470dd0a26d9f4b8ef9cb5d39",
2110
-                "reference": "eea1a3ec87bbe62d470dd0a26d9f4b8ef9cb5d39",
2114
+                "url": "https://api.github.com/repos/filamentphp/forms/zipball/40988aa2cb540b17b86dc6684b9c3f57b9be3109",
2115
+                "reference": "40988aa2cb540b17b86dc6684b9c3f57b9be3109",
2111 2116
                 "shasum": ""
2112 2117
             },
2113 2118
             "require": {
@@ -2150,20 +2155,20 @@
2150 2155
                 "issues": "https://github.com/filamentphp/filament/issues",
2151 2156
                 "source": "https://github.com/filamentphp/filament"
2152 2157
             },
2153
-            "time": "2024-04-21T22:23:42+00:00"
2158
+            "time": "2024-04-28T08:39:12+00:00"
2154 2159
         },
2155 2160
         {
2156 2161
             "name": "filament/infolists",
2157
-            "version": "v3.2.71",
2162
+            "version": "v3.2.72",
2158 2163
             "source": {
2159 2164
                 "type": "git",
2160 2165
                 "url": "https://github.com/filamentphp/infolists.git",
2161
-                "reference": "d205fbeacc7faf4430abb05c49334a64fb4d84ae"
2166
+                "reference": "612497be1c0e5b8b1e0ef9eeefe4754baab54271"
2162 2167
             },
2163 2168
             "dist": {
2164 2169
                 "type": "zip",
2165
-                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/d205fbeacc7faf4430abb05c49334a64fb4d84ae",
2166
-                "reference": "d205fbeacc7faf4430abb05c49334a64fb4d84ae",
2170
+                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/612497be1c0e5b8b1e0ef9eeefe4754baab54271",
2171
+                "reference": "612497be1c0e5b8b1e0ef9eeefe4754baab54271",
2167 2172
                 "shasum": ""
2168 2173
             },
2169 2174
             "require": {
@@ -2201,20 +2206,20 @@
2201 2206
                 "issues": "https://github.com/filamentphp/filament/issues",
2202 2207
                 "source": "https://github.com/filamentphp/filament"
2203 2208
             },
2204
-            "time": "2024-04-18T11:26:13+00:00"
2209
+            "time": "2024-04-28T08:39:09+00:00"
2205 2210
         },
2206 2211
         {
2207 2212
             "name": "filament/notifications",
2208
-            "version": "v3.2.71",
2213
+            "version": "v3.2.72",
2209 2214
             "source": {
2210 2215
                 "type": "git",
2211 2216
                 "url": "https://github.com/filamentphp/notifications.git",
2212
-                "reference": "dcc47b498c2a5a89296c2f46da651a8aa5e0bf55"
2217
+                "reference": "a37c926d2edbcb07e6fd8a354ce2f5daa59ad92e"
2213 2218
             },
2214 2219
             "dist": {
2215 2220
                 "type": "zip",
2216
-                "url": "https://api.github.com/repos/filamentphp/notifications/zipball/dcc47b498c2a5a89296c2f46da651a8aa5e0bf55",
2217
-                "reference": "dcc47b498c2a5a89296c2f46da651a8aa5e0bf55",
2221
+                "url": "https://api.github.com/repos/filamentphp/notifications/zipball/a37c926d2edbcb07e6fd8a354ce2f5daa59ad92e",
2222
+                "reference": "a37c926d2edbcb07e6fd8a354ce2f5daa59ad92e",
2218 2223
                 "shasum": ""
2219 2224
             },
2220 2225
             "require": {
@@ -2253,20 +2258,20 @@
2253 2258
                 "issues": "https://github.com/filamentphp/filament/issues",
2254 2259
                 "source": "https://github.com/filamentphp/filament"
2255 2260
             },
2256
-            "time": "2024-04-18T11:26:15+00:00"
2261
+            "time": "2024-04-28T08:39:09+00:00"
2257 2262
         },
2258 2263
         {
2259 2264
             "name": "filament/support",
2260
-            "version": "v3.2.71",
2265
+            "version": "v3.2.72",
2261 2266
             "source": {
2262 2267
                 "type": "git",
2263 2268
                 "url": "https://github.com/filamentphp/support.git",
2264
-                "reference": "594f8d38e365578b6d91455c5beade6c54def5a4"
2269
+                "reference": "169fa6303337ad1f5d0203b9d34baa76bc938384"
2265 2270
             },
2266 2271
             "dist": {
2267 2272
                 "type": "zip",
2268
-                "url": "https://api.github.com/repos/filamentphp/support/zipball/594f8d38e365578b6d91455c5beade6c54def5a4",
2269
-                "reference": "594f8d38e365578b6d91455c5beade6c54def5a4",
2273
+                "url": "https://api.github.com/repos/filamentphp/support/zipball/169fa6303337ad1f5d0203b9d34baa76bc938384",
2274
+                "reference": "169fa6303337ad1f5d0203b9d34baa76bc938384",
2270 2275
                 "shasum": ""
2271 2276
             },
2272 2277
             "require": {
@@ -2311,20 +2316,20 @@
2311 2316
                 "issues": "https://github.com/filamentphp/filament/issues",
2312 2317
                 "source": "https://github.com/filamentphp/filament"
2313 2318
             },
2314
-            "time": "2024-04-21T22:24:20+00:00"
2319
+            "time": "2024-04-28T08:39:28+00:00"
2315 2320
         },
2316 2321
         {
2317 2322
             "name": "filament/tables",
2318
-            "version": "v3.2.71",
2323
+            "version": "v3.2.72",
2319 2324
             "source": {
2320 2325
                 "type": "git",
2321 2326
                 "url": "https://github.com/filamentphp/tables.git",
2322
-                "reference": "b3bc1d2b5947562eb64748e6d3f59ed1073effe7"
2327
+                "reference": "c3fce6d9e3b9a41d48cbccdacef3508f0cf73f56"
2323 2328
             },
2324 2329
             "dist": {
2325 2330
                 "type": "zip",
2326
-                "url": "https://api.github.com/repos/filamentphp/tables/zipball/b3bc1d2b5947562eb64748e6d3f59ed1073effe7",
2327
-                "reference": "b3bc1d2b5947562eb64748e6d3f59ed1073effe7",
2331
+                "url": "https://api.github.com/repos/filamentphp/tables/zipball/c3fce6d9e3b9a41d48cbccdacef3508f0cf73f56",
2332
+                "reference": "c3fce6d9e3b9a41d48cbccdacef3508f0cf73f56",
2328 2333
                 "shasum": ""
2329 2334
             },
2330 2335
             "require": {
@@ -2364,11 +2369,11 @@
2364 2369
                 "issues": "https://github.com/filamentphp/filament/issues",
2365 2370
                 "source": "https://github.com/filamentphp/filament"
2366 2371
             },
2367
-            "time": "2024-04-21T22:24:20+00:00"
2372
+            "time": "2024-04-28T08:39:27+00:00"
2368 2373
         },
2369 2374
         {
2370 2375
             "name": "filament/widgets",
2371
-            "version": "v3.2.71",
2376
+            "version": "v3.2.72",
2372 2377
             "source": {
2373 2378
                 "type": "git",
2374 2379
                 "url": "https://github.com/filamentphp/widgets.git",
@@ -6403,20 +6408,20 @@
6403 6408
         },
6404 6409
         {
6405 6410
             "name": "ramsey/uuid",
6406
-            "version": "4.7.5",
6411
+            "version": "4.7.6",
6407 6412
             "source": {
6408 6413
                 "type": "git",
6409 6414
                 "url": "https://github.com/ramsey/uuid.git",
6410
-                "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
6415
+                "reference": "91039bc1faa45ba123c4328958e620d382ec7088"
6411 6416
             },
6412 6417
             "dist": {
6413 6418
                 "type": "zip",
6414
-                "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
6415
-                "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
6419
+                "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
6420
+                "reference": "91039bc1faa45ba123c4328958e620d382ec7088",
6416 6421
                 "shasum": ""
6417 6422
             },
6418 6423
             "require": {
6419
-                "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
6424
+                "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
6420 6425
                 "ext-json": "*",
6421 6426
                 "php": "^8.0",
6422 6427
                 "ramsey/collection": "^1.2 || ^2.0"
@@ -6479,7 +6484,7 @@
6479 6484
             ],
6480 6485
             "support": {
6481 6486
                 "issues": "https://github.com/ramsey/uuid/issues",
6482
-                "source": "https://github.com/ramsey/uuid/tree/4.7.5"
6487
+                "source": "https://github.com/ramsey/uuid/tree/4.7.6"
6483 6488
             },
6484 6489
             "funding": [
6485 6490
                 {
@@ -6491,7 +6496,7 @@
6491 6496
                     "type": "tidelift"
6492 6497
                 }
6493 6498
             ],
6494
-            "time": "2023-11-08T05:53:05+00:00"
6499
+            "time": "2024-04-27T21:32:50+00:00"
6495 6500
         },
6496 6501
         {
6497 6502
             "name": "ryangjchandler/blade-capture-directive",

+ 7
- 12
database/migrations/2023_09_08_040159_create_company_defaults_table.php Dosyayı Görüntüle

@@ -14,20 +14,15 @@ return new class extends Migration
14 14
         Schema::create('company_defaults', function (Blueprint $table) {
15 15
             $table->id();
16 16
             $table->foreignId('company_id')->constrained()->cascadeOnDelete();
17
-            $table->foreignId('bank_account_id')->nullable()->constrained('bank_accounts')->restrictOnDelete();
17
+            $table->foreignId('bank_account_id')->nullable()->constrained('bank_accounts')->nullOnDelete();
18 18
             $table->string('currency_code')->nullable();
19
-            $table->foreignId('sales_tax_id')->nullable()->constrained('taxes')->cascadeOnDelete();
20
-            $table->foreignId('purchase_tax_id')->nullable()->constrained('taxes')->cascadeOnDelete();
21
-            $table->foreignId('sales_discount_id')->nullable()->constrained('discounts')->cascadeOnDelete();
22
-            $table->foreignId('purchase_discount_id')->nullable()->constrained('discounts')->cascadeOnDelete();
23
-            $table->foreignId('created_by')->nullable()->constrained('users')->restrictOnDelete();
24
-            $table->foreignId('updated_by')->nullable()->constrained('users')->restrictOnDelete();
19
+            $table->foreignId('sales_tax_id')->nullable()->constrained('taxes')->nullOnDelete();
20
+            $table->foreignId('purchase_tax_id')->nullable()->constrained('taxes')->nullOnDelete();
21
+            $table->foreignId('sales_discount_id')->nullable()->constrained('discounts')->nullOnDelete();
22
+            $table->foreignId('purchase_discount_id')->nullable()->constrained('discounts')->nullOnDelete();
23
+            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
24
+            $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
25 25
             $table->timestamps();
26
-
27
-            $table->foreign(['company_id', 'currency_code'])
28
-                ->references(['company_id', 'code'])
29
-                ->on('currencies')
30
-                ->restrictOnDelete();
31 26
         });
32 27
     }
33 28
 

+ 73
- 73
package-lock.json Dosyayı Görüntüle

@@ -507,9 +507,9 @@
507 507
             }
508 508
         },
509 509
         "node_modules/@rollup/rollup-android-arm-eabi": {
510
-            "version": "4.16.4",
511
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.4.tgz",
512
-            "integrity": "sha512-GkhjAaQ8oUTOKE4g4gsZ0u8K/IHU1+2WQSgS1TwTcYvL+sjbaQjNHFXbOJ6kgqGHIO1DfUhI/Sphi9GkRT9K+Q==",
510
+            "version": "4.17.0",
511
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.0.tgz",
512
+            "integrity": "sha512-nNvLvC2fjC+3+bHYN9uaGF3gcyy7RHGZhtl8TB/kINj9hiOQza8kWJGZh47GRPMrqeseO8U+Z8ElDMCZlWBdHA==",
513 513
             "cpu": [
514 514
                 "arm"
515 515
             ],
@@ -520,9 +520,9 @@
520 520
             ]
521 521
         },
522 522
         "node_modules/@rollup/rollup-android-arm64": {
523
-            "version": "4.16.4",
524
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.4.tgz",
525
-            "integrity": "sha512-Bvm6D+NPbGMQOcxvS1zUl8H7DWlywSXsphAeOnVeiZLQ+0J6Is8T7SrjGTH29KtYkiY9vld8ZnpV3G2EPbom+w==",
523
+            "version": "4.17.0",
524
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.0.tgz",
525
+            "integrity": "sha512-+kjt6dvxnyTIAo7oHeYseYhDyZ7xRKTNl/FoQI96PHkJVxoChldJnne/LzYqpqidoK1/0kX0/q+5rrYqjpth6w==",
526 526
             "cpu": [
527 527
                 "arm64"
528 528
             ],
@@ -533,9 +533,9 @@
533 533
             ]
534 534
         },
535 535
         "node_modules/@rollup/rollup-darwin-arm64": {
536
-            "version": "4.16.4",
537
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.4.tgz",
538
-            "integrity": "sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==",
536
+            "version": "4.17.0",
537
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.0.tgz",
538
+            "integrity": "sha512-Oj6Tp0unMpGTBjvNwbSRv3DopMNLu+mjBzhKTt2zLbDJ/45fB1pltr/rqrO4bE95LzuYwhYn127pop+x/pzf5w==",
539 539
             "cpu": [
540 540
                 "arm64"
541 541
             ],
@@ -546,9 +546,9 @@
546 546
             ]
547 547
         },
548 548
         "node_modules/@rollup/rollup-darwin-x64": {
549
-            "version": "4.16.4",
550
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.4.tgz",
551
-            "integrity": "sha512-WZupV1+CdUYehaZqjaFTClJI72fjJEgTXdf4NbW69I9XyvdmztUExBtcI2yIIU6hJtYvtwS6pkTkHJz+k08mAQ==",
549
+            "version": "4.17.0",
550
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.0.tgz",
551
+            "integrity": "sha512-3nJx0T+yptxMd+v93rBRxSPTAVCv8szu/fGZDJiKX7kvRe9sENj2ggXjCH/KK1xZEmJOhaNo0c9sGMgGdfkvEw==",
552 552
             "cpu": [
553 553
                 "x64"
554 554
             ],
@@ -559,9 +559,9 @@
559 559
             ]
560 560
         },
561 561
         "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
562
-            "version": "4.16.4",
563
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.4.tgz",
564
-            "integrity": "sha512-ADm/xt86JUnmAfA9mBqFcRp//RVRt1ohGOYF6yL+IFCYqOBNwy5lbEK05xTsEoJq+/tJzg8ICUtS82WinJRuIw==",
562
+            "version": "4.17.0",
563
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.0.tgz",
564
+            "integrity": "sha512-Vb2e8p9b2lxxgqyOlBHmp6hJMu/HSU6g//6Tbr7x5V1DlPCHWLOm37nSIVK314f+IHzORyAQSqL7+9tELxX3zQ==",
565 565
             "cpu": [
566 566
                 "arm"
567 567
             ],
@@ -572,9 +572,9 @@
572 572
             ]
573 573
         },
574 574
         "node_modules/@rollup/rollup-linux-arm-musleabihf": {
575
-            "version": "4.16.4",
576
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.4.tgz",
577
-            "integrity": "sha512-tJfJaXPiFAG+Jn3cutp7mCs1ePltuAgRqdDZrzb1aeE3TktWWJ+g7xK9SNlaSUFw6IU4QgOxAY4rA+wZUT5Wfg==",
575
+            "version": "4.17.0",
576
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.0.tgz",
577
+            "integrity": "sha512-Md60KsmC5ZIaRq/bYYDloklgU+XLEZwS2EXXVcSpiUw+13/ZASvSWQ/P92rQ9YDCL6EIoXxuQ829JkReqdYbGg==",
578 578
             "cpu": [
579 579
                 "arm"
580 580
             ],
@@ -585,9 +585,9 @@
585 585
             ]
586 586
         },
587 587
         "node_modules/@rollup/rollup-linux-arm64-gnu": {
588
-            "version": "4.16.4",
589
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.4.tgz",
590
-            "integrity": "sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==",
588
+            "version": "4.17.0",
589
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.0.tgz",
590
+            "integrity": "sha512-zL5rBFtJ+2EGnMRm2TqKjdjgFqlotSU+ZJEN37nV+fiD3I6Gy0dUh3jBWN0wSlcXVDEJYW7YBe+/2j0N9unb2w==",
591 591
             "cpu": [
592 592
                 "arm64"
593 593
             ],
@@ -598,9 +598,9 @@
598 598
             ]
599 599
         },
600 600
         "node_modules/@rollup/rollup-linux-arm64-musl": {
601
-            "version": "4.16.4",
602
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.4.tgz",
603
-            "integrity": "sha512-zsFwdUw5XLD1gQe0aoU2HVceI6NEW7q7m05wA46eUAyrkeNYExObfRFQcvA6zw8lfRc5BHtan3tBpo+kqEOxmg==",
601
+            "version": "4.17.0",
602
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.0.tgz",
603
+            "integrity": "sha512-s2xAyNkJqUdtRVgNK4NK4P9QttS538JuX/kfVQOdZDI5FIKVAUVdLW7qhGfmaySJ1EvN/Bnj9oPm5go9u8navg==",
604 604
             "cpu": [
605 605
                 "arm64"
606 606
             ],
@@ -611,9 +611,9 @@
611 611
             ]
612 612
         },
613 613
         "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
614
-            "version": "4.16.4",
615
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.4.tgz",
616
-            "integrity": "sha512-p8C3NnxXooRdNrdv6dBmRTddEapfESEUflpICDNKXpHvTjRRq1J82CbU5G3XfebIZyI3B0s074JHMWD36qOW6w==",
614
+            "version": "4.17.0",
615
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.0.tgz",
616
+            "integrity": "sha512-7F99yzVT67B7IUNMjLD9QCFDCyHkyCJMS1dywZrGgVFJao4VJ9szrIEgH67cR+bXQgEaY01ur/WSL6B0jtcLyA==",
617 617
             "cpu": [
618 618
                 "ppc64"
619 619
             ],
@@ -624,9 +624,9 @@
624 624
             ]
625 625
         },
626 626
         "node_modules/@rollup/rollup-linux-riscv64-gnu": {
627
-            "version": "4.16.4",
628
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.4.tgz",
629
-            "integrity": "sha512-Lh/8ckoar4s4Id2foY7jNgitTOUQczwMWNYi+Mjt0eQ9LKhr6sK477REqQkmy8YHY3Ca3A2JJVdXnfb3Rrwkng==",
627
+            "version": "4.17.0",
628
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.0.tgz",
629
+            "integrity": "sha512-leFtyiXisfa3Sg9pgZJwRKITWnrQfhtqDjCamnZhkZuIsk1FXmYwKoTkp6lsCgimIcneFFkHKp/yGLxDesga4g==",
630 630
             "cpu": [
631 631
                 "riscv64"
632 632
             ],
@@ -637,9 +637,9 @@
637 637
             ]
638 638
         },
639 639
         "node_modules/@rollup/rollup-linux-s390x-gnu": {
640
-            "version": "4.16.4",
641
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.4.tgz",
642
-            "integrity": "sha512-1xwwn9ZCQYuqGmulGsTZoKrrn0z2fAur2ujE60QgyDpHmBbXbxLaQiEvzJWDrscRq43c8DnuHx3QorhMTZgisQ==",
640
+            "version": "4.17.0",
641
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.0.tgz",
642
+            "integrity": "sha512-FtOgui6qMJ4jbSXTxElsy/60LEe/3U0rXkkz2G5CJ9rbHPAvjMvI+3qF0A0fwLQ5hW+/ZC6PbnS2KfRW9JkgDQ==",
643 643
             "cpu": [
644 644
                 "s390x"
645 645
             ],
@@ -650,9 +650,9 @@
650 650
             ]
651 651
         },
652 652
         "node_modules/@rollup/rollup-linux-x64-gnu": {
653
-            "version": "4.16.4",
654
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.4.tgz",
655
-            "integrity": "sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==",
653
+            "version": "4.17.0",
654
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.0.tgz",
655
+            "integrity": "sha512-v6eiam/1w3HUfU/ZjzIDodencqgrSqzlNuNtiwH7PFJHYSo1ezL0/UIzmS2lpSJF1ORNaplXeKHYmmdt81vV2g==",
656 656
             "cpu": [
657 657
                 "x64"
658 658
             ],
@@ -663,9 +663,9 @@
663 663
             ]
664 664
         },
665 665
         "node_modules/@rollup/rollup-linux-x64-musl": {
666
-            "version": "4.16.4",
667
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.4.tgz",
668
-            "integrity": "sha512-ch86i7KkJKkLybDP2AtySFTRi5fM3KXp0PnHocHuJMdZwu7BuyIKi35BE9guMlmTpwwBTB3ljHj9IQXnTCD0vA==",
666
+            "version": "4.17.0",
667
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.0.tgz",
668
+            "integrity": "sha512-OUhkSdpM5ofVlVU2k4CwVubYwiwu1a4jYWPpubzN7Vzao73GoPBowHcCfaRSFRz1SszJ3HIsk3dZYk4kzbqjgw==",
669 669
             "cpu": [
670 670
                 "x64"
671 671
             ],
@@ -676,9 +676,9 @@
676 676
             ]
677 677
         },
678 678
         "node_modules/@rollup/rollup-win32-arm64-msvc": {
679
-            "version": "4.16.4",
680
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.4.tgz",
681
-            "integrity": "sha512-Ma4PwyLfOWZWayfEsNQzTDBVW8PZ6TUUN1uFTBQbF2Chv/+sjenE86lpiEwj2FiviSmSZ4Ap4MaAfl1ciF4aSA==",
679
+            "version": "4.17.0",
680
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.0.tgz",
681
+            "integrity": "sha512-uL7UYO/MNJPGL/yflybI+HI+n6+4vlfZmQZOCb4I+z/zy1wisHT3exh7oNQsnL6Eso0EUTEfgQ/PaGzzXf6XyQ==",
682 682
             "cpu": [
683 683
                 "arm64"
684 684
             ],
@@ -689,9 +689,9 @@
689 689
             ]
690 690
         },
691 691
         "node_modules/@rollup/rollup-win32-ia32-msvc": {
692
-            "version": "4.16.4",
693
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.4.tgz",
694
-            "integrity": "sha512-9m/ZDrQsdo/c06uOlP3W9G2ENRVzgzbSXmXHT4hwVaDQhYcRpi9bgBT0FTG9OhESxwK0WjQxYOSfv40cU+T69w==",
692
+            "version": "4.17.0",
693
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.0.tgz",
694
+            "integrity": "sha512-4WnSgaUiUmXILwFqREdOcqvSj6GD/7FrvSjhaDjmwakX9w4Z2F8JwiSP1AZZbuRkPqzi444UI5FPv33VKOWYFQ==",
695 695
             "cpu": [
696 696
                 "ia32"
697 697
             ],
@@ -702,9 +702,9 @@
702 702
             ]
703 703
         },
704 704
         "node_modules/@rollup/rollup-win32-x64-msvc": {
705
-            "version": "4.16.4",
706
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.4.tgz",
707
-            "integrity": "sha512-YunpoOAyGLDseanENHmbFvQSfVL5BxW3k7hhy0eN4rb3gS/ct75dVD0EXOWIqFT/nE8XYW6LP6vz6ctKRi0k9A==",
705
+            "version": "4.17.0",
706
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.0.tgz",
707
+            "integrity": "sha512-ve+D8t1prRSRnF2S3pyDtTXDlvW1Pngbz76tjgYFQW1jxVSysmQCZfPoDAo4WP+Ano8zeYp85LsArZBI12HfwQ==",
708 708
             "cpu": [
709 709
                 "x64"
710 710
             ],
@@ -931,9 +931,9 @@
931 931
             }
932 932
         },
933 933
         "node_modules/caniuse-lite": {
934
-            "version": "1.0.30001612",
935
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz",
936
-            "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==",
934
+            "version": "1.0.30001613",
935
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001613.tgz",
936
+            "integrity": "sha512-BNjJULJfOONQERivfxte7alLfeLW4QnwHvNW4wEcLEbXfV6VSCYvr+REbf2Sojv8tC1THpjPXBxWgDbq4NtLWg==",
937 937
             "dev": true,
938 938
             "funding": [
939 939
                 {
@@ -2010,9 +2010,9 @@
2010 2010
             }
2011 2011
         },
2012 2012
         "node_modules/rollup": {
2013
-            "version": "4.16.4",
2014
-            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.4.tgz",
2015
-            "integrity": "sha512-kuaTJSUbz+Wsb2ATGvEknkI12XV40vIiHmLuFlejoo7HtDok/O5eDDD0UpCVY5bBX5U5RYo8wWP83H7ZsqVEnA==",
2013
+            "version": "4.17.0",
2014
+            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.0.tgz",
2015
+            "integrity": "sha512-wZJSn0WMtWrxhYKQRt5Z6GIXlziOoMDFmbHmRfL3v+sBTAshx2DBq1AfMArB7eIjF63r4ocn2ZTAyUptg/7kmQ==",
2016 2016
             "dev": true,
2017 2017
             "dependencies": {
2018 2018
                 "@types/estree": "1.0.5"
@@ -2025,22 +2025,22 @@
2025 2025
                 "npm": ">=8.0.0"
2026 2026
             },
2027 2027
             "optionalDependencies": {
2028
-                "@rollup/rollup-android-arm-eabi": "4.16.4",
2029
-                "@rollup/rollup-android-arm64": "4.16.4",
2030
-                "@rollup/rollup-darwin-arm64": "4.16.4",
2031
-                "@rollup/rollup-darwin-x64": "4.16.4",
2032
-                "@rollup/rollup-linux-arm-gnueabihf": "4.16.4",
2033
-                "@rollup/rollup-linux-arm-musleabihf": "4.16.4",
2034
-                "@rollup/rollup-linux-arm64-gnu": "4.16.4",
2035
-                "@rollup/rollup-linux-arm64-musl": "4.16.4",
2036
-                "@rollup/rollup-linux-powerpc64le-gnu": "4.16.4",
2037
-                "@rollup/rollup-linux-riscv64-gnu": "4.16.4",
2038
-                "@rollup/rollup-linux-s390x-gnu": "4.16.4",
2039
-                "@rollup/rollup-linux-x64-gnu": "4.16.4",
2040
-                "@rollup/rollup-linux-x64-musl": "4.16.4",
2041
-                "@rollup/rollup-win32-arm64-msvc": "4.16.4",
2042
-                "@rollup/rollup-win32-ia32-msvc": "4.16.4",
2043
-                "@rollup/rollup-win32-x64-msvc": "4.16.4",
2028
+                "@rollup/rollup-android-arm-eabi": "4.17.0",
2029
+                "@rollup/rollup-android-arm64": "4.17.0",
2030
+                "@rollup/rollup-darwin-arm64": "4.17.0",
2031
+                "@rollup/rollup-darwin-x64": "4.17.0",
2032
+                "@rollup/rollup-linux-arm-gnueabihf": "4.17.0",
2033
+                "@rollup/rollup-linux-arm-musleabihf": "4.17.0",
2034
+                "@rollup/rollup-linux-arm64-gnu": "4.17.0",
2035
+                "@rollup/rollup-linux-arm64-musl": "4.17.0",
2036
+                "@rollup/rollup-linux-powerpc64le-gnu": "4.17.0",
2037
+                "@rollup/rollup-linux-riscv64-gnu": "4.17.0",
2038
+                "@rollup/rollup-linux-s390x-gnu": "4.17.0",
2039
+                "@rollup/rollup-linux-x64-gnu": "4.17.0",
2040
+                "@rollup/rollup-linux-x64-musl": "4.17.0",
2041
+                "@rollup/rollup-win32-arm64-msvc": "4.17.0",
2042
+                "@rollup/rollup-win32-ia32-msvc": "4.17.0",
2043
+                "@rollup/rollup-win32-x64-msvc": "4.17.0",
2044 2044
                 "fsevents": "~2.3.2"
2045 2045
             }
2046 2046
         },
@@ -2536,9 +2536,9 @@
2536 2536
             }
2537 2537
         },
2538 2538
         "node_modules/yaml": {
2539
-            "version": "2.4.1",
2540
-            "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
2541
-            "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
2539
+            "version": "2.4.2",
2540
+            "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
2541
+            "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
2542 2542
             "dev": true,
2543 2543
             "bin": {
2544 2544
                 "yaml": "bin.mjs"

resources/views/forms/components/journal-entry-repeater.blade.php → resources/views/filament/forms/components/journal-entry-repeater.blade.php Dosyayı Görüntüle


Loading…
İptal
Kaydet