Ver código fonte

refactor

3.x
Andrew Wallo 11 meses atrás
pai
commit
102fc13820
45 arquivos alterados com 451 adições e 480 exclusões
  1. 16
    0
      app/Enums/Accounting/AdjustmentCategory.php
  2. 2
    4
      app/Enums/Accounting/AdjustmentComputation.php
  3. 2
    4
      app/Enums/Accounting/AdjustmentScope.php
  4. 2
    7
      app/Enums/Accounting/AdjustmentType.php
  5. 0
    16
      app/Enums/Setting/DiscountScope.php
  6. 0
    39
      app/Enums/Setting/DiscountType.php
  7. 0
    19
      app/Enums/Setting/TaxComputation.php
  8. 1
    1
      app/Filament/Company/Clusters/Settings/Pages/CompanyDefault.php
  9. 0
    4
      app/Listeners/SyncAssociatedModels.php
  10. 0
    29
      app/Listeners/SyncWithCompanyDefaults.php
  11. 5
    0
      app/Models/Accounting/Account.php
  12. 69
    0
      app/Models/Accounting/Adjustment.php
  13. 2
    2
      app/Models/Accounting/Document.php
  14. 2
    2
      app/Models/Accounting/DocumentLineItem.php
  15. 2
    2
      app/Models/Banking/Payment.php
  16. 2
    2
      app/Models/Common/Client.php
  17. 1
    1
      app/Models/Common/Offering.php
  18. 2
    2
      app/Models/Common/Vendor.php
  19. 5
    12
      app/Models/Company.php
  20. 0
    30
      app/Models/Setting/CompanyDefault.php
  21. 8
    2
      app/Models/Setting/Discount.php
  22. 8
    2
      app/Models/Setting/Tax.php
  23. 35
    0
      app/Services/ChartOfAccountsService.php
  24. 6
    6
      composer.lock
  25. 47
    6
      config/chart-of-accounts.php
  26. 57
    0
      database/factories/Accounting/AccountFactory.php
  27. 120
    0
      database/factories/Accounting/AdjustmentFactory.php
  28. 2
    2
      database/factories/Accounting/DocumentFactory.php
  29. 2
    2
      database/factories/Accounting/DocumentLineItemFactory.php
  30. 6
    0
      database/factories/Accounting/TransactionFactory.php
  31. 2
    2
      database/factories/Banking/PaymentFactory.php
  32. 2
    2
      database/factories/Common/ClientFactory.php
  33. 2
    2
      database/factories/Common/OfferingFactory.php
  34. 2
    2
      database/factories/Common/VendorFactory.php
  35. 0
    50
      database/factories/Setting/CompanyDefaultFactory.php
  36. 0
    68
      database/factories/Setting/DiscountFactory.php
  37. 0
    62
      database/factories/Setting/TaxFactory.php
  38. 4
    3
      database/migrations/2023_09_03_100000_create_accounting_tables.php
  39. 0
    41
      database/migrations/2023_09_08_011045_create_taxes_table.php
  40. 0
    4
      database/migrations/2023_09_08_040159_create_company_defaults_table.php
  41. 4
    8
      database/migrations/2023_09_12_014413_create_appearances_table.php
  42. 3
    6
      database/migrations/2023_09_12_032057_create_document_defaults_table.php
  43. 4
    8
      database/migrations/2023_10_11_210415_create_localizations_table.php
  44. 7
    9
      database/migrations/2024_11_14_230753_create_adjustments_table.php
  45. 17
    17
      package-lock.json

+ 16
- 0
app/Enums/Accounting/AdjustmentCategory.php Ver arquivo

@@ -0,0 +1,16 @@
1
+<?php
2
+
3
+namespace App\Enums\Accounting;
4
+
5
+use Filament\Support\Contracts\HasLabel;
6
+
7
+enum AdjustmentCategory: string implements HasLabel
8
+{
9
+    case Tax = 'tax';
10
+    case Discount = 'discount';
11
+
12
+    public function getLabel(): ?string
13
+    {
14
+        return $this->name;
15
+    }
16
+}

app/Enums/Setting/DiscountComputation.php → app/Enums/Accounting/AdjustmentComputation.php Ver arquivo

@@ -1,16 +1,14 @@
1 1
 <?php
2 2
 
3
-namespace App\Enums\Setting;
3
+namespace App\Enums\Accounting;
4 4
 
5 5
 use Filament\Support\Contracts\HasLabel;
6 6
 
7
-enum DiscountComputation: string implements HasLabel
7
+enum AdjustmentComputation: string implements HasLabel
8 8
 {
9 9
     case Percentage = 'percentage';
10 10
     case Fixed = 'fixed';
11 11
 
12
-    public const DEFAULT = self::Percentage->value;
13
-
14 12
     public function getLabel(): ?string
15 13
     {
16 14
         return translate($this->name);

app/Enums/Setting/TaxScope.php → app/Enums/Accounting/AdjustmentScope.php Ver arquivo

@@ -1,10 +1,8 @@
1 1
 <?php
2 2
 
3
-namespace App\Enums\Setting;
3
+namespace App\Enums\Accounting;
4 4
 
5
-use Filament\Support\Contracts\HasLabel;
6
-
7
-enum TaxScope: string implements HasLabel
5
+enum AdjustmentScope: string
8 6
 {
9 7
     case Product = 'product';
10 8
     case Service = 'service';

app/Enums/Setting/TaxType.php → app/Enums/Accounting/AdjustmentType.php Ver arquivo

@@ -1,18 +1,15 @@
1 1
 <?php
2 2
 
3
-namespace App\Enums\Setting;
3
+namespace App\Enums\Accounting;
4 4
 
5 5
 use Filament\Support\Contracts\HasColor;
6 6
 use Filament\Support\Contracts\HasIcon;
7 7
 use Filament\Support\Contracts\HasLabel;
8 8
 
9
-enum TaxType: string implements HasColor, HasIcon, HasLabel
9
+enum AdjustmentType: string implements HasColor, HasIcon, HasLabel
10 10
 {
11 11
     case Sales = 'sales';
12 12
     case Purchase = 'purchase';
13
-    case None = 'none';
14
-
15
-    public const DEFAULT = self::Sales->value;
16 13
 
17 14
     public function getLabel(): ?string
18 15
     {
@@ -24,7 +21,6 @@ enum TaxType: string implements HasColor, HasIcon, HasLabel
24 21
         return match ($this) {
25 22
             self::Sales => 'success',
26 23
             self::Purchase => 'warning',
27
-            self::None => 'gray',
28 24
         };
29 25
     }
30 26
 
@@ -33,7 +29,6 @@ enum TaxType: string implements HasColor, HasIcon, HasLabel
33 29
         return match ($this) {
34 30
             self::Sales => 'heroicon-o-currency-dollar',
35 31
             self::Purchase => 'heroicon-o-shopping-bag',
36
-            self::None => 'heroicon-o-x-circle',
37 32
         };
38 33
     }
39 34
 }

+ 0
- 16
app/Enums/Setting/DiscountScope.php Ver arquivo

@@ -1,16 +0,0 @@
1
-<?php
2
-
3
-namespace App\Enums\Setting;
4
-
5
-use Filament\Support\Contracts\HasLabel;
6
-
7
-enum DiscountScope: string implements HasLabel
8
-{
9
-    case Product = 'product';
10
-    case Service = 'service';
11
-
12
-    public function getLabel(): ?string
13
-    {
14
-        return translate($this->name);
15
-    }
16
-}

+ 0
- 39
app/Enums/Setting/DiscountType.php Ver arquivo

@@ -1,39 +0,0 @@
1
-<?php
2
-
3
-namespace App\Enums\Setting;
4
-
5
-use Filament\Support\Contracts\HasColor;
6
-use Filament\Support\Contracts\HasIcon;
7
-use Filament\Support\Contracts\HasLabel;
8
-
9
-enum DiscountType: string implements HasColor, HasIcon, HasLabel
10
-{
11
-    case Sales = 'sales';
12
-    case Purchase = 'purchase';
13
-    case None = 'none';
14
-
15
-    public const DEFAULT = self::Sales->value;
16
-
17
-    public function getLabel(): ?string
18
-    {
19
-        return translate($this->name);
20
-    }
21
-
22
-    public function getColor(): string | array | null
23
-    {
24
-        return match ($this) {
25
-            self::Sales => 'success',
26
-            self::Purchase => 'warning',
27
-            self::None => 'gray',
28
-        };
29
-    }
30
-
31
-    public function getIcon(): ?string
32
-    {
33
-        return match ($this) {
34
-            self::Sales => 'heroicon-o-currency-dollar',
35
-            self::Purchase => 'heroicon-o-shopping-bag',
36
-            self::None => 'heroicon-o-x-circle',
37
-        };
38
-    }
39
-}

+ 0
- 19
app/Enums/Setting/TaxComputation.php Ver arquivo

@@ -1,19 +0,0 @@
1
-<?php
2
-
3
-namespace App\Enums\Setting;
4
-
5
-use Filament\Support\Contracts\HasLabel;
6
-
7
-enum TaxComputation: string implements HasLabel
8
-{
9
-    case Fixed = 'fixed';
10
-    case Percentage = 'percentage';
11
-    case Compound = 'compound';
12
-
13
-    public const DEFAULT = self::Percentage->value;
14
-
15
-    public function getLabel(): ?string
16
-    {
17
-        return translate($this->name);
18
-    }
19
-}

+ 1
- 1
app/Filament/Company/Clusters/Settings/Pages/CompanyDefault.php Ver arquivo

@@ -108,7 +108,7 @@ class CompanyDefault extends Page
108 108
         return $form
109 109
             ->schema([
110 110
                 $this->getGeneralSection(),
111
-                $this->getModifiersSection(),
111
+                // $this->getModifiersSection(),
112 112
             ])
113 113
             ->model($this->record)
114 114
             ->statePath('data')

+ 0
- 4
app/Listeners/SyncAssociatedModels.php Ver arquivo

@@ -40,10 +40,6 @@ class SyncAssociatedModels
40 40
 
41 41
         $keyToMethodMap = [
42 42
             'bank_account_id' => 'bankAccount',
43
-            'sales_tax_id' => 'salesTax',
44
-            'purchase_tax_id' => 'purchaseTax',
45
-            'sales_discount_id' => 'salesDiscount',
46
-            'purchase_discount_id' => 'purchaseDiscount',
47 43
         ];
48 44
 
49 45
         foreach ($diff as $key => $value) {

+ 0
- 29
app/Listeners/SyncWithCompanyDefaults.php Ver arquivo

@@ -2,8 +2,6 @@
2 2
 
3 3
 namespace App\Listeners;
4 4
 
5
-use App\Enums\Setting\DiscountType;
6
-use App\Enums\Setting\TaxType;
7 5
 use App\Events\CompanyDefaultEvent;
8 6
 use App\Models\Setting\CompanyDefault;
9 7
 use Illuminate\Support\Facades\DB;
@@ -48,15 +46,12 @@ class SyncWithCompanyDefaults
48 46
     private function updateCompanyDefaults($model, $companyId): void
49 47
     {
50 48
         $modelName = class_basename($model);
51
-        $type = $model->getAttribute('type');
52 49
 
53 50
         $default = CompanyDefault::firstOrNew([
54 51
             'company_id' => $companyId,
55 52
         ]);
56 53
 
57 54
         match ($modelName) {
58
-            'Discount' => $this->handleDiscount($default, $type, $model->getKey()),
59
-            'Tax' => $this->handleTax($default, $type, $model->getKey()),
60 55
             'Currency' => $default->currency_code = $model->getAttribute('code'),
61 56
             'BankAccount' => $default->bank_account_id = $model->getKey(),
62 57
             default => null,
@@ -64,28 +59,4 @@ class SyncWithCompanyDefaults
64 59
 
65 60
         $default->save();
66 61
     }
67
-
68
-    private function handleDiscount($default, $type, $key): void
69
-    {
70
-        if (! in_array($type, [DiscountType::Sales, DiscountType::Purchase], true)) {
71
-            return;
72
-        }
73
-
74
-        match (true) {
75
-            $type === DiscountType::Sales => $default->sales_discount_id = $key,
76
-            $type === DiscountType::Purchase => $default->purchase_discount_id = $key,
77
-        };
78
-    }
79
-
80
-    private function handleTax($default, $type, $key): void
81
-    {
82
-        if (! in_array($type, [TaxType::Sales, TaxType::Purchase], true)) {
83
-            return;
84
-        }
85
-
86
-        match (true) {
87
-            $type === TaxType::Sales => $default->sales_tax_id = $key,
88
-            $type === TaxType::Purchase => $default->purchase_tax_id = $key,
89
-        };
90
-    }
91 62
 }

+ 5
- 0
app/Models/Accounting/Account.php Ver arquivo

@@ -79,6 +79,11 @@ class Account extends Model
79 79
         return $this->hasOne(BankAccount::class, 'account_id');
80 80
     }
81 81
 
82
+    public function adjustment(): HasOne
83
+    {
84
+        return $this->hasOne(Adjustment::class, 'account_id');
85
+    }
86
+
82 87
     public function getLastTransactionDate(): ?string
83 88
     {
84 89
         $lastJournalEntryTransaction = $this->journalEntries()

+ 69
- 0
app/Models/Accounting/Adjustment.php Ver arquivo

@@ -0,0 +1,69 @@
1
+<?php
2
+
3
+namespace App\Models\Accounting;
4
+
5
+use App\Casts\RateCast;
6
+use App\Concerns\Blamable;
7
+use App\Concerns\CompanyOwned;
8
+use App\Concerns\HasDefault;
9
+use App\Enums\Accounting\AdjustmentCategory;
10
+use App\Enums\Accounting\AdjustmentComputation;
11
+use App\Enums\Accounting\AdjustmentScope;
12
+use App\Enums\Accounting\AdjustmentType;
13
+use Database\Factories\Accounting\AdjustmentFactory;
14
+use Illuminate\Database\Eloquent\Factories\Factory;
15
+use Illuminate\Database\Eloquent\Factories\HasFactory;
16
+use Illuminate\Database\Eloquent\Model;
17
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
18
+use Illuminate\Database\Eloquent\Relations\MorphTo;
19
+
20
+class Adjustment extends Model
21
+{
22
+    use Blamable;
23
+    use CompanyOwned;
24
+    use HasDefault;
25
+    use HasFactory;
26
+
27
+    protected $table = 'adjustments';
28
+
29
+    protected $fillable = [
30
+        'company_id',
31
+        'account_id',
32
+        'category',
33
+        'type',
34
+        'rate',
35
+        'computation',
36
+        'scope',
37
+        'start_date',
38
+        'end_date',
39
+        'enabled',
40
+        'created_by',
41
+        'updated_by',
42
+    ];
43
+
44
+    protected $casts = [
45
+        'category' => AdjustmentCategory::class,
46
+        'type' => AdjustmentType::class,
47
+        'rate' => RateCast::class,
48
+        'computation' => AdjustmentComputation::class,
49
+        'scope' => AdjustmentScope::class,
50
+        'start_date' => 'datetime',
51
+        'end_date' => 'datetime',
52
+        'enabled' => 'boolean',
53
+    ];
54
+
55
+    public function account(): BelongsTo
56
+    {
57
+        return $this->belongsTo(Account::class, 'account_id');
58
+    }
59
+
60
+    public function adjustmentables(): MorphTo
61
+    {
62
+        return $this->morphTo();
63
+    }
64
+
65
+    protected static function newFactory(): Factory
66
+    {
67
+        return AdjustmentFactory::new();
68
+    }
69
+}

app/Models/Document.php → app/Models/Accounting/Document.php Ver arquivo

@@ -1,12 +1,12 @@
1 1
 <?php
2 2
 
3
-namespace App\Models;
3
+namespace App\Models\Accounting;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 6
 use Illuminate\Database\Eloquent\Model;
7 7
 
8 8
 class Document extends Model
9 9
 {
10
-    /** @use HasFactory<\Database\Factories\DocumentFactory> */
10
+    /** @use HasFactory<\Database\Factories\Accounting\DocumentFactory> */
11 11
     use HasFactory;
12 12
 }

app/Models/DocumentLineItem.php → app/Models/Accounting/DocumentLineItem.php Ver arquivo

@@ -1,12 +1,12 @@
1 1
 <?php
2 2
 
3
-namespace App\Models;
3
+namespace App\Models\Accounting;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 6
 use Illuminate\Database\Eloquent\Model;
7 7
 
8 8
 class DocumentLineItem extends Model
9 9
 {
10
-    /** @use HasFactory<\Database\Factories\DocumentLineItemFactory> */
10
+    /** @use HasFactory<\Database\Factories\Accounting\DocumentLineItemFactory> */
11 11
     use HasFactory;
12 12
 }

app/Models/Payment.php → app/Models/Banking/Payment.php Ver arquivo

@@ -1,12 +1,12 @@
1 1
 <?php
2 2
 
3
-namespace App\Models;
3
+namespace App\Models\Banking;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 6
 use Illuminate\Database\Eloquent\Model;
7 7
 
8 8
 class Payment extends Model
9 9
 {
10
-    /** @use HasFactory<\Database\Factories\PaymentFactory> */
10
+    /** @use HasFactory<\Database\Factories\Banking\PaymentFactory> */
11 11
     use HasFactory;
12 12
 }

app/Models/Client.php → app/Models/Common/Client.php Ver arquivo

@@ -1,12 +1,12 @@
1 1
 <?php
2 2
 
3
-namespace App\Models;
3
+namespace App\Models\Common;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 6
 use Illuminate\Database\Eloquent\Model;
7 7
 
8 8
 class Client extends Model
9 9
 {
10
-    /** @use HasFactory<\Database\Factories\ClientFactory> */
10
+    /** @use HasFactory<\Database\Factories\Common\ClientFactory> */
11 11
     use HasFactory;
12 12
 }

app/Models/Offering.php → app/Models/Common/Offering.php Ver arquivo

@@ -1,6 +1,6 @@
1 1
 <?php
2 2
 
3
-namespace App\Models;
3
+namespace App\Models\Common;
4 4
 
5 5
 use App\Concerns\CompanyOwned;
6 6
 use App\Models\Accounting\Account;

app/Models/Vendor.php → app/Models/Common/Vendor.php Ver arquivo

@@ -1,12 +1,12 @@
1 1
 <?php
2 2
 
3
-namespace App\Models;
3
+namespace App\Models\Common;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 6
 use Illuminate\Database\Eloquent\Model;
7 7
 
8 8
 class Vendor extends Model
9 9
 {
10
-    /** @use HasFactory<\Database\Factories\VendorFactory> */
10
+    /** @use HasFactory<\Database\Factories\Common\VendorFactory> */
11 11
     use HasFactory;
12 12
 }

+ 5
- 12
app/Models/Company.php Ver arquivo

@@ -12,10 +12,8 @@ use App\Models\Setting\Appearance;
12 12
 use App\Models\Setting\CompanyDefault;
13 13
 use App\Models\Setting\CompanyProfile;
14 14
 use App\Models\Setting\Currency;
15
-use App\Models\Setting\Discount;
16 15
 use App\Models\Setting\DocumentDefault;
17 16
 use App\Models\Setting\Localization;
18
-use App\Models\Setting\Tax;
19 17
 use Filament\Models\Contracts\HasAvatar;
20 18
 use Illuminate\Database\Eloquent\Factories\HasFactory;
21 19
 use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -74,6 +72,11 @@ class Company extends FilamentCompaniesCompany implements HasAvatar
74 72
         return $this->hasMany(Accounting\Account::class, 'company_id');
75 73
     }
76 74
 
75
+    public function adjustments(): HasMany
76
+    {
77
+        return $this->hasMany(Accounting\Adjustment::class, 'company_id');
78
+    }
79
+
77 80
     public function bankAccounts(): HasMany
78 81
     {
79 82
         return $this->hasMany(BankAccount::class, 'company_id');
@@ -122,11 +125,6 @@ class Company extends FilamentCompaniesCompany implements HasAvatar
122 125
         return $this->hasMany(Department::class, 'company_id');
123 126
     }
124 127
 
125
-    public function discounts(): HasMany
126
-    {
127
-        return $this->hasMany(Discount::class, 'company_id');
128
-    }
129
-
130 128
     public function locale(): HasOne
131 129
     {
132 130
         return $this->hasOne(Localization::class, 'company_id');
@@ -137,11 +135,6 @@ class Company extends FilamentCompaniesCompany implements HasAvatar
137 135
         return $this->hasOne(CompanyProfile::class, 'company_id');
138 136
     }
139 137
 
140
-    public function taxes(): HasMany
141
-    {
142
-        return $this->hasMany(Tax::class, 'company_id');
143
-    }
144
-
145 138
     public function transactions(): HasMany
146 139
     {
147 140
         return $this->hasMany(Accounting\Transaction::class, 'company_id');

+ 0
- 30
app/Models/Setting/CompanyDefault.php Ver arquivo

@@ -4,8 +4,6 @@ namespace App\Models\Setting;
4 4
 
5 5
 use App\Concerns\Blamable;
6 6
 use App\Concerns\CompanyOwned;
7
-use App\Enums\Setting\DiscountType;
8
-use App\Enums\Setting\TaxType;
9 7
 use App\Models\Banking\BankAccount;
10 8
 use Database\Factories\Setting\CompanyDefaultFactory;
11 9
 use Illuminate\Database\Eloquent\Factories\Factory;
@@ -25,10 +23,6 @@ class CompanyDefault extends Model
25 23
         'company_id',
26 24
         'bank_account_id',
27 25
         'currency_code',
28
-        'sales_tax_id',
29
-        'purchase_tax_id',
30
-        'sales_discount_id',
31
-        'purchase_discount_id',
32 26
         'created_by',
33 27
         'updated_by',
34 28
     ];
@@ -43,30 +37,6 @@ class CompanyDefault extends Model
43 37
         return $this->belongsTo(Currency::class, 'currency_code', 'code');
44 38
     }
45 39
 
46
-    public function salesTax(): BelongsTo
47
-    {
48
-        return $this->belongsTo(Tax::class, 'sales_tax_id', 'id')
49
-            ->where('type', TaxType::Sales);
50
-    }
51
-
52
-    public function purchaseTax(): BelongsTo
53
-    {
54
-        return $this->belongsTo(Tax::class, 'purchase_tax_id', 'id')
55
-            ->where('type', TaxType::Purchase);
56
-    }
57
-
58
-    public function salesDiscount(): BelongsTo
59
-    {
60
-        return $this->belongsTo(Discount::class, 'sales_discount_id', 'id')
61
-            ->where('type', DiscountType::Sales);
62
-    }
63
-
64
-    public function purchaseDiscount(): BelongsTo
65
-    {
66
-        return $this->belongsTo(Discount::class, 'purchase_discount_id', 'id')
67
-            ->where('type', DiscountType::Purchase);
68
-    }
69
-
70 40
     protected static function newFactory(): Factory
71 41
     {
72 42
         return CompanyDefaultFactory::new();

+ 8
- 2
app/Models/Setting/Discount.php Ver arquivo

@@ -10,10 +10,12 @@ use App\Concerns\SyncsWithCompanyDefaults;
10 10
 use App\Enums\Setting\DiscountComputation;
11 11
 use App\Enums\Setting\DiscountScope;
12 12
 use App\Enums\Setting\DiscountType;
13
+use App\Models\Accounting\Account;
13 14
 use Database\Factories\Setting\DiscountFactory;
14 15
 use Illuminate\Database\Eloquent\Factories\Factory;
15 16
 use Illuminate\Database\Eloquent\Factories\HasFactory;
16 17
 use Illuminate\Database\Eloquent\Model;
18
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
17 19
 use Illuminate\Database\Eloquent\Relations\HasOne;
18 20
 use Illuminate\Database\Eloquent\Relations\MorphTo;
19 21
 
@@ -29,8 +31,7 @@ class Discount extends Model
29 31
 
30 32
     protected $fillable = [
31 33
         'company_id',
32
-        'name',
33
-        'description',
34
+        'account_id',
34 35
         'rate',
35 36
         'computation',
36 37
         'type',
@@ -54,6 +55,11 @@ class Discount extends Model
54 55
 
55 56
     protected ?string $evaluatedDefault = 'type';
56 57
 
58
+    public function account(): BelongsTo
59
+    {
60
+        return $this->belongsTo(Account::class, 'account_id');
61
+    }
62
+
57 63
     public function defaultSalesDiscount(): HasOne
58 64
     {
59 65
         return $this->hasOne(CompanyDefault::class, 'sales_discount_id');

+ 8
- 2
app/Models/Setting/Tax.php Ver arquivo

@@ -10,10 +10,12 @@ use App\Concerns\SyncsWithCompanyDefaults;
10 10
 use App\Enums\Setting\TaxComputation;
11 11
 use App\Enums\Setting\TaxScope;
12 12
 use App\Enums\Setting\TaxType;
13
+use App\Models\Accounting\Account;
13 14
 use Database\Factories\Setting\TaxFactory;
14 15
 use Illuminate\Database\Eloquent\Factories\Factory;
15 16
 use Illuminate\Database\Eloquent\Factories\HasFactory;
16 17
 use Illuminate\Database\Eloquent\Model;
18
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
17 19
 use Illuminate\Database\Eloquent\Relations\HasOne;
18 20
 use Illuminate\Database\Eloquent\Relations\MorphTo;
19 21
 
@@ -29,8 +31,7 @@ class Tax extends Model
29 31
 
30 32
     protected $fillable = [
31 33
         'company_id',
32
-        'name',
33
-        'description',
34
+        'account_id',
34 35
         'rate',
35 36
         'computation',
36 37
         'type',
@@ -50,6 +51,11 @@ class Tax extends Model
50 51
 
51 52
     protected ?string $evaluatedDefault = 'type';
52 53
 
54
+    public function account(): BelongsTo
55
+    {
56
+        return $this->belongsTo(Account::class, 'account_id');
57
+    }
58
+
53 59
     public function defaultSalesTax(): HasOne
54 60
     {
55 61
         return $this->hasOne(CompanyDefault::class, 'sales_tax_id');

+ 35
- 0
app/Services/ChartOfAccountsService.php Ver arquivo

@@ -5,6 +5,7 @@ namespace App\Services;
5 5
 use App\Enums\Accounting\AccountType;
6 6
 use App\Enums\Banking\BankAccountType;
7 7
 use App\Models\Accounting\AccountSubtype;
8
+use App\Models\Accounting\Adjustment;
8 9
 use App\Models\Banking\BankAccount;
9 10
 use App\Models\Company;
10 11
 use App\Utilities\Currency\CurrencyAccessor;
@@ -77,6 +78,14 @@ class ChartOfAccountsService
77 78
                     $bankAccount->account()->associate($account);
78 79
                     $bankAccount->saveQuietly();
79 80
                 }
81
+
82
+                if (isset($subtypeConfig['adjustment_category'], $subtypeConfig['adjustment_type'])) {
83
+                    $adjustment = $this->createAdjustmentForAccount($company, $subtypeConfig['adjustment_category'], $subtypeConfig['adjustment_type']);
84
+
85
+                    // Associate the Adjustment with the Account
86
+                    $adjustment->account()->associate($account);
87
+                    $adjustment->saveQuietly();
88
+                }
80 89
             }
81 90
         }
82 91
     }
@@ -92,4 +101,30 @@ class ChartOfAccountsService
92 101
             'updated_by' => $company->owner->id,
93 102
         ]);
94 103
     }
104
+
105
+    private function createAdjustmentForAccount(Company $company, string $category, string $type): Adjustment
106
+    {
107
+        $noDefaultAdjustmentType = $company->adjustments()->where('category', $category)
108
+            ->where('type', $type)
109
+            ->where('enabled', true)
110
+            ->doesntExist();
111
+
112
+        $defaultRate = match ([$category, $type]) {
113
+            ['tax', 'sales'] => 8,          // Default 8% for Sales Tax
114
+            ['tax', 'purchase'] => 8,       // Default 8% for Purchase Tax
115
+            ['discount', 'sales'] => 5,     // Default 5% for Sales Discount
116
+            ['discount', 'purchase'] => 5,  // Default 5% for Purchase Discount
117
+            default => 0,                   // Default to 0 if unspecified
118
+        };
119
+
120
+        return $company->adjustments()->createQuietly([
121
+            'category' => $category,
122
+            'type' => $type,
123
+            'rate' => $defaultRate,
124
+            'computation' => 'percentage',
125
+            'enabled' => $noDefaultAdjustmentType,
126
+            'created_by' => $company->owner->id,
127
+            'updated_by' => $company->owner->id,
128
+        ]);
129
+    }
95 130
 }

+ 6
- 6
composer.lock Ver arquivo

@@ -497,16 +497,16 @@
497 497
         },
498 498
         {
499 499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.326.0",
500
+            "version": "3.327.0",
501 501
             "source": {
502 502
                 "type": "git",
503 503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "5420284de9aad84e375fa8012cefd834bebfd623"
504
+                "reference": "ba4a7ac2544de61b33f693c461f8b09c0353298f"
505 505
             },
506 506
             "dist": {
507 507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5420284de9aad84e375fa8012cefd834bebfd623",
509
-                "reference": "5420284de9aad84e375fa8012cefd834bebfd623",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ba4a7ac2544de61b33f693c461f8b09c0353298f",
509
+                "reference": "ba4a7ac2544de61b33f693c461f8b09c0353298f",
510 510
                 "shasum": ""
511 511
             },
512 512
             "require": {
@@ -589,9 +589,9 @@
589 589
             "support": {
590 590
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
591 591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
592
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.326.0"
592
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.327.0"
593 593
             },
594
-            "time": "2024-11-13T19:07:44+00:00"
594
+            "time": "2024-11-14T19:06:19+00:00"
595 595
         },
596 596
         {
597 597
             "name": "aws/aws-sdk-php-laravel",

+ 47
- 6
config/chart-of-accounts.php Ver arquivo

@@ -118,9 +118,17 @@ return [
118 118
                 'multi_currency' => false,
119 119
                 'base_code' => '2100',
120 120
                 'inverse_cash_flow' => false,
121
+            ],
122
+            'Sales Taxes' => [
123
+                'description' => 'The amount of money owed to the government for sales tax collected from customers.',
124
+                'multi_currency' => false,
125
+                'base_code' => '2150',
126
+                'inverse_cash_flow' => false,
127
+                'adjustment_category' => 'tax',
128
+                'adjustment_type' => 'sales',
121 129
                 'accounts' => [
122
-                    'Sales Tax Payable' => [
123
-                        'description' => 'The amount of money owed to the government for sales tax collected from customers.',
130
+                    'Sales Tax' => [
131
+                        'description' => null,
124 132
                     ],
125 133
                 ],
126 134
             ],
@@ -271,8 +279,18 @@ return [
271 279
                     'Sales Returns and Allowances' => [
272 280
                         'description' => 'The amount of money returned to customers or deducted from sales due to returned goods or allowances granted.',
273 281
                     ],
274
-                    'Sales Discounts' => [
275
-                        'description' => 'The amount of money deducted from sales due to discounts offered to customers for early payment or other reasons.',
282
+                ],
283
+            ],
284
+            'Sales Discounts' => [
285
+                'description' => 'The amount of money deducted from sales due to discounts offered to customers for early payment or other reasons.',
286
+                'multi_currency' => false,
287
+                'base_code' => '4925',
288
+                'inverse_cash_flow' => false,
289
+                'adjustment_category' => 'discount',
290
+                'adjustment_type' => 'sales',
291
+                'accounts' => [
292
+                    'Sales Discount' => [
293
+                        'description' => null,
276 294
                     ],
277 295
                 ],
278 296
             ],
@@ -412,6 +430,19 @@ return [
412 430
                 'base_code' => '5600',
413 431
                 'inverse_cash_flow' => true,
414 432
             ],
433
+            'Purchase Taxes' => [
434
+                'description' => 'Taxes paid on purchases of goods or services, such as value-added tax (VAT), goods and services tax (GST), or customs duties.',
435
+                'multi_currency' => false,
436
+                'base_code' => '5650',
437
+                'inverse_cash_flow' => true,
438
+                'adjustment_category' => 'tax',
439
+                'adjustment_type' => 'purchase',
440
+                'accounts' => [
441
+                    'Purchase Tax' => [
442
+                        'description' => null,
443
+                    ],
444
+                ],
445
+            ],
415 446
             'Other Non-Operating Expense' => [
416 447
                 'description' => 'Expenses not related to primary business activities, like losses from asset disposals, legal settlements, restructuring costs, or foreign exchange losses.',
417 448
                 'multi_currency' => false,
@@ -434,8 +465,18 @@ return [
434 465
                     'Purchase Returns and Allowances' => [
435 466
                         'description' => 'The amount of money returned to suppliers or deducted from purchases due to returned goods or allowances granted.',
436 467
                     ],
437
-                    'Purchase Discounts' => [
438
-                        'description' => 'The amount of money deducted from purchases due to discounts offered by suppliers for early payment or other reasons.',
468
+                ],
469
+            ],
470
+            'Purchase Discounts' => [
471
+                'description' => 'The amount of money deducted from purchases due to discounts offered by suppliers for early payment or other reasons.',
472
+                'multi_currency' => false,
473
+                'base_code' => '5925',
474
+                'inverse_cash_flow' => true,
475
+                'adjustment_category' => 'discount',
476
+                'adjustment_type' => 'purchase',
477
+                'accounts' => [
478
+                    'Purchase Discount' => [
479
+                        'description' => null,
439 480
                     ],
440 481
                 ],
441 482
             ],

+ 57
- 0
database/factories/Accounting/AccountFactory.php Ver arquivo

@@ -6,6 +6,7 @@ use App\Models\Accounting\Account;
6 6
 use App\Models\Accounting\AccountSubtype;
7 7
 use App\Models\Banking\BankAccount;
8 8
 use App\Models\Setting\Currency;
9
+use App\Utilities\Accounting\AccountCode;
9 10
 use App\Utilities\Currency\CurrencyAccessor;
10 11
 use Illuminate\Database\Eloquent\Factories\Factory;
11 12
 
@@ -74,4 +75,60 @@ class AccountFactory extends Factory
74 75
             ]);
75 76
         });
76 77
     }
78
+
79
+    public function forSalesTax(?string $name = null, ?string $description = null): static
80
+    {
81
+        $accountSubtype = AccountSubtype::where('name', 'Sales Taxes')->first();
82
+
83
+        return $this->state([
84
+            'name' => $name,
85
+            'description' => $description,
86
+            'category' => $accountSubtype->category,
87
+            'type' => $accountSubtype->type,
88
+            'subtype_id' => $accountSubtype->id,
89
+            'code' => AccountCode::generate($accountSubtype),
90
+        ]);
91
+    }
92
+
93
+    public function forPurchaseTax(?string $name = null, ?string $description = null): static
94
+    {
95
+        $accountSubtype = AccountSubtype::where('name', 'Purchase Taxes')->first();
96
+
97
+        return $this->state([
98
+            'name' => $name,
99
+            'description' => $description,
100
+            'category' => $accountSubtype->category,
101
+            'type' => $accountSubtype->type,
102
+            'subtype_id' => $accountSubtype->id,
103
+            'code' => AccountCode::generate($accountSubtype),
104
+        ]);
105
+    }
106
+
107
+    public function forSalesDiscount(?string $name = null, ?string $description = null): static
108
+    {
109
+        $accountSubtype = AccountSubtype::where('name', 'Sales Discounts')->first();
110
+
111
+        return $this->state([
112
+            'name' => $name,
113
+            'description' => $description,
114
+            'category' => $accountSubtype->category,
115
+            'type' => $accountSubtype->type,
116
+            'subtype_id' => $accountSubtype->id,
117
+            'code' => AccountCode::generate($accountSubtype),
118
+        ]);
119
+    }
120
+
121
+    public function forPurchaseDiscount(?string $name = null, ?string $description = null): static
122
+    {
123
+        $accountSubtype = AccountSubtype::where('name', 'Purchase Discounts')->first();
124
+
125
+        return $this->state([
126
+            'name' => $name,
127
+            'description' => $description,
128
+            'category' => $accountSubtype->category,
129
+            'type' => $accountSubtype->type,
130
+            'subtype_id' => $accountSubtype->id,
131
+            'code' => AccountCode::generate($accountSubtype),
132
+        ]);
133
+    }
77 134
 }

+ 120
- 0
database/factories/Accounting/AdjustmentFactory.php Ver arquivo

@@ -0,0 +1,120 @@
1
+<?php
2
+
3
+namespace Database\Factories\Accounting;
4
+
5
+use App\Enums\Accounting\AdjustmentCategory;
6
+use App\Enums\Accounting\AdjustmentComputation;
7
+use App\Enums\Accounting\AdjustmentScope;
8
+use App\Enums\Accounting\AdjustmentType;
9
+use App\Models\Accounting\Account;
10
+use App\Models\Accounting\Adjustment;
11
+use Illuminate\Database\Eloquent\Factories\Factory;
12
+use Illuminate\Support\Carbon;
13
+
14
+/**
15
+ * @extends Factory<Adjustment>
16
+ */
17
+class AdjustmentFactory extends Factory
18
+{
19
+    /**
20
+     * The name of the factory's corresponding model.
21
+     */
22
+    protected $model = Adjustment::class;
23
+
24
+    /**
25
+     * Define the model's default state.
26
+     *
27
+     * @return array<string, mixed>
28
+     */
29
+    public function definition(): array
30
+    {
31
+        $startDate = $this->faker->dateTimeBetween('now', '+1 year');
32
+        $endDate = $this->faker->dateTimeBetween($startDate, Carbon::parse($startDate)->addYear());
33
+        $computation = $this->faker->randomElement(AdjustmentComputation::class);
34
+
35
+        $rate = $computation === AdjustmentComputation::Fixed
36
+            ? $this->faker->numberBetween(5, 100) * 100 // $5 - $100 for fixed amounts
37
+            : $this->faker->numberBetween(3, 25) * 10000; // 3% - 25% for percentages
38
+
39
+        return [
40
+            'rate' => $rate,
41
+            'computation' => $computation,
42
+            'category' => $this->faker->randomElement(AdjustmentCategory::class),
43
+            'type' => $this->faker->randomElement(AdjustmentType::class),
44
+            'scope' => $this->faker->randomElement(AdjustmentScope::class),
45
+            'start_date' => $startDate,
46
+            'end_date' => $endDate,
47
+            'enabled' => false,
48
+        ];
49
+    }
50
+
51
+    public function configure(): static
52
+    {
53
+        return $this->afterCreating(function (Adjustment $adjustment) {
54
+            if ($adjustment->account_id === null) {
55
+                $account = Account::factory()->create();
56
+                $adjustment->account()->associate($account);
57
+            }
58
+        });
59
+    }
60
+
61
+    /**
62
+     * Define a sales tax adjustment.
63
+     */
64
+    public function salesTax(?string $name = null, ?string $description = null): self
65
+    {
66
+        $name = $name ?? 'Sales Tax';
67
+        $account = Account::factory()->forSalesTax($name, $description)->create();
68
+
69
+        return $this->state([
70
+            'category' => AdjustmentCategory::Tax,
71
+            'type' => AdjustmentType::Sales,
72
+            'account_id' => $account->id,
73
+        ]);
74
+    }
75
+
76
+    /**
77
+     * Define a purchase tax adjustment.
78
+     */
79
+    public function purchaseTax(?string $name = null, ?string $description = null): self
80
+    {
81
+        $name = $name ?? 'Purchase Tax';
82
+        $account = Account::factory()->forPurchaseTax($name, $description)->create();
83
+
84
+        return $this->state([
85
+            'category' => AdjustmentCategory::Tax,
86
+            'type' => AdjustmentType::Purchase,
87
+            'account_id' => $account->id,
88
+        ]);
89
+    }
90
+
91
+    /**
92
+     * Define a sales discount adjustment.
93
+     */
94
+    public function salesDiscount(?string $name = null, ?string $description = null): self
95
+    {
96
+        $name = $name ?? 'Sales Discount';
97
+        $account = Account::factory()->forSalesDiscount($name, $description)->create();
98
+
99
+        return $this->state([
100
+            'category' => AdjustmentCategory::Discount,
101
+            'type' => AdjustmentType::Sales,
102
+            'account_id' => $account->id,
103
+        ]);
104
+    }
105
+
106
+    /**
107
+     * Define a purchase discount adjustment.
108
+     */
109
+    public function purchaseDiscount(?string $name = null, ?string $description = null): self
110
+    {
111
+        $name = $name ?? 'Purchase Discount';
112
+        $account = Account::factory()->forPurchaseDiscount($name, $description)->create();
113
+
114
+        return $this->state([
115
+            'category' => AdjustmentCategory::Discount,
116
+            'type' => AdjustmentType::Purchase,
117
+            'account_id' => $account->id,
118
+        ]);
119
+    }
120
+}

database/factories/DocumentFactory.php → database/factories/Accounting/DocumentFactory.php Ver arquivo

@@ -1,11 +1,11 @@
1 1
 <?php
2 2
 
3
-namespace Database\Factories;
3
+namespace Database\Factories\Accounting;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\Factory;
6 6
 
7 7
 /**
8
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Document>
8
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Accounting\Document>
9 9
  */
10 10
 class DocumentFactory extends Factory
11 11
 {

database/factories/DocumentLineItemFactory.php → database/factories/Accounting/DocumentLineItemFactory.php Ver arquivo

@@ -1,11 +1,11 @@
1 1
 <?php
2 2
 
3
-namespace Database\Factories;
3
+namespace Database\Factories\Accounting;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\Factory;
6 6
 
7 7
 /**
8
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\DocumentLineItem>
8
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Accounting\DocumentLineItem>
9 9
  */
10 10
 class DocumentLineItemFactory extends Factory
11 11
 {

+ 6
- 0
database/factories/Accounting/TransactionFactory.php Ver arquivo

@@ -5,6 +5,7 @@ namespace Database\Factories\Accounting;
5 5
 use App\Enums\Accounting\AccountType;
6 6
 use App\Enums\Accounting\TransactionType;
7 7
 use App\Models\Accounting\Account;
8
+use App\Models\Accounting\AccountSubtype;
8 9
 use App\Models\Accounting\Transaction;
9 10
 use App\Models\Banking\BankAccount;
10 11
 use App\Models\Company;
@@ -69,8 +70,13 @@ class TransactionFactory extends Factory
69 70
 
70 71
             $accountIdForBankAccount = $bankAccount->account->id;
71 72
 
73
+            $excludedSubtypes = AccountSubtype::where('company_id', $company->id)
74
+                ->whereIn('name', ['Sales Taxes', 'Purchase Taxes', 'Sales Discounts', 'Purchase Discounts'])
75
+                ->pluck('id');
76
+
72 77
             $account = Account::whereIn('type', $associatedAccountTypes)
73 78
                 ->where('company_id', $company->id)
79
+                ->whereNotIn('subtype_id', $excludedSubtypes)
74 80
                 ->whereKeyNot($accountIdForBankAccount)
75 81
                 ->inRandomOrder()
76 82
                 ->first();

database/factories/PaymentFactory.php → database/factories/Banking/PaymentFactory.php Ver arquivo

@@ -1,11 +1,11 @@
1 1
 <?php
2 2
 
3
-namespace Database\Factories;
3
+namespace Database\Factories\Banking;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\Factory;
6 6
 
7 7
 /**
8
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Payment>
8
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Banking\Payment>
9 9
  */
10 10
 class PaymentFactory extends Factory
11 11
 {

database/factories/ClientFactory.php → database/factories/Common/ClientFactory.php Ver arquivo

@@ -1,11 +1,11 @@
1 1
 <?php
2 2
 
3
-namespace Database\Factories;
3
+namespace Database\Factories\Common;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\Factory;
6 6
 
7 7
 /**
8
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Client>
8
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Common\Client>
9 9
  */
10 10
 class ClientFactory extends Factory
11 11
 {

database/factories/OfferingFactory.php → database/factories/Common/OfferingFactory.php Ver arquivo

@@ -1,11 +1,11 @@
1 1
 <?php
2 2
 
3
-namespace Database\Factories;
3
+namespace Database\Factories\Common;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\Factory;
6 6
 
7 7
 /**
8
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Offering>
8
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Common\Offering>
9 9
  */
10 10
 class OfferingFactory extends Factory
11 11
 {

database/factories/VendorFactory.php → database/factories/Common/VendorFactory.php Ver arquivo

@@ -1,11 +1,11 @@
1 1
 <?php
2 2
 
3
-namespace Database\Factories;
3
+namespace Database\Factories\Common;
4 4
 
5 5
 use Illuminate\Database\Eloquent\Factories\Factory;
6 6
 
7 7
 /**
8
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Vendor>
8
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Common\Vendor>
9 9
  */
10 10
 class VendorFactory extends Factory
11 11
 {

+ 0
- 50
database/factories/Setting/CompanyDefaultFactory.php Ver arquivo

@@ -7,10 +7,8 @@ use App\Models\Company;
7 7
 use App\Models\Setting\Appearance;
8 8
 use App\Models\Setting\CompanyDefault;
9 9
 use App\Models\Setting\Currency;
10
-use App\Models\Setting\Discount;
11 10
 use App\Models\Setting\DocumentDefault;
12 11
 use App\Models\Setting\Localization;
13
-use App\Models\Setting\Tax;
14 12
 use App\Models\User;
15 13
 use Illuminate\Database\Eloquent\Factories\Factory;
16 14
 
@@ -46,10 +44,6 @@ class CompanyDefaultFactory extends Factory
46 44
         }
47 45
 
48 46
         $currency = $this->createCurrency($company, $user, $currencyCode);
49
-        $salesTax = $this->createSalesTax($company, $user);
50
-        $purchaseTax = $this->createPurchaseTax($company, $user);
51
-        $salesDiscount = $this->createSalesDiscount($company, $user);
52
-        $purchaseDiscount = $this->createPurchaseDiscount($company, $user);
53 47
         $this->createAppearance($company, $user);
54 48
         $this->createDocumentDefaults($company, $user);
55 49
         $this->createLocalization($company, $user, $countryCode, $language);
@@ -57,10 +51,6 @@ class CompanyDefaultFactory extends Factory
57 51
         $companyDefaults = [
58 52
             'company_id' => $company->id,
59 53
             'currency_code' => $currency->code,
60
-            'sales_tax_id' => $salesTax->id,
61
-            'purchase_tax_id' => $purchaseTax->id,
62
-            'sales_discount_id' => $salesDiscount->id,
63
-            'purchase_discount_id' => $purchaseDiscount->id,
64 54
             'created_by' => $user->id,
65 55
             'updated_by' => $user->id,
66 56
         ];
@@ -78,46 +68,6 @@ class CompanyDefaultFactory extends Factory
78 68
         ]);
79 69
     }
80 70
 
81
-    private function createSalesTax(Company $company, User $user): Tax
82
-    {
83
-        return Tax::factory()->salesTax()->createQuietly([
84
-            'company_id' => $company->id,
85
-            'enabled' => true,
86
-            'created_by' => $user->id,
87
-            'updated_by' => $user->id,
88
-        ]);
89
-    }
90
-
91
-    private function createPurchaseTax(Company $company, User $user): Tax
92
-    {
93
-        return Tax::factory()->purchaseTax()->createQuietly([
94
-            'company_id' => $company->id,
95
-            'enabled' => true,
96
-            'created_by' => $user->id,
97
-            'updated_by' => $user->id,
98
-        ]);
99
-    }
100
-
101
-    private function createSalesDiscount(Company $company, User $user): Discount
102
-    {
103
-        return Discount::factory()->salesDiscount()->createQuietly([
104
-            'company_id' => $company->id,
105
-            'enabled' => true,
106
-            'created_by' => $user->id,
107
-            'updated_by' => $user->id,
108
-        ]);
109
-    }
110
-
111
-    private function createPurchaseDiscount(Company $company, User $user): Discount
112
-    {
113
-        return Discount::factory()->purchaseDiscount()->createQuietly([
114
-            'company_id' => $company->id,
115
-            'enabled' => true,
116
-            'created_by' => $user->id,
117
-            'updated_by' => $user->id,
118
-        ]);
119
-    }
120
-
121 71
     private function createAppearance(Company $company, User $user): void
122 72
     {
123 73
         Appearance::factory()->createQuietly([

+ 0
- 68
database/factories/Setting/DiscountFactory.php Ver arquivo

@@ -1,68 +0,0 @@
1
-<?php
2
-
3
-namespace Database\Factories\Setting;
4
-
5
-use App\Enums\Setting\DiscountComputation;
6
-use App\Enums\Setting\DiscountScope;
7
-use App\Enums\Setting\DiscountType;
8
-use App\Models\Setting\Discount;
9
-use Illuminate\Database\Eloquent\Factories\Factory;
10
-use Illuminate\Support\Carbon;
11
-
12
-/**
13
- * @extends Factory<Discount>
14
- */
15
-class DiscountFactory extends Factory
16
-{
17
-    /**
18
-     * The name of the factory's corresponding model.
19
-     */
20
-    protected $model = Discount::class;
21
-
22
-    /**
23
-     * Define the model's default state.
24
-     *
25
-     * @return array<string, mixed>
26
-     */
27
-    public function definition(): array
28
-    {
29
-        $startDate = $this->faker->dateTimeBetween('now', '+1 year');
30
-        $endDate = $this->faker->dateTimeBetween($startDate, Carbon::parse($startDate)->addYear());
31
-
32
-        $computation = $this->faker->randomElement(DiscountComputation::class);
33
-
34
-        if ($computation === DiscountComputation::Fixed) {
35
-            $rate = $this->faker->numberBetween(5, 100) * 100; // $5 - $100
36
-        } else {
37
-            $rate = $this->faker->numberBetween(3, 50) * 10000; // 3% - 50%
38
-        }
39
-
40
-        return [
41
-            'name' => $this->faker->unique()->word,
42
-            'description' => $this->faker->sentence,
43
-            'rate' => $rate,
44
-            'computation' => $computation,
45
-            'type' => $this->faker->randomElement(DiscountType::class),
46
-            'scope' => $this->faker->randomElement(DiscountScope::class),
47
-            'start_date' => $startDate,
48
-            'end_date' => $endDate,
49
-            'enabled' => false,
50
-        ];
51
-    }
52
-
53
-    public function salesDiscount(): self
54
-    {
55
-        return $this->state([
56
-            'name' => 'Summer Sale',
57
-            'type' => DiscountType::Sales,
58
-        ]);
59
-    }
60
-
61
-    public function purchaseDiscount(): self
62
-    {
63
-        return $this->state([
64
-            'name' => 'Bulk Purchase',
65
-            'type' => DiscountType::Purchase,
66
-        ]);
67
-    }
68
-}

+ 0
- 62
database/factories/Setting/TaxFactory.php Ver arquivo

@@ -1,62 +0,0 @@
1
-<?php
2
-
3
-namespace Database\Factories\Setting;
4
-
5
-use App\Enums\Setting\TaxComputation;
6
-use App\Enums\Setting\TaxScope;
7
-use App\Enums\Setting\TaxType;
8
-use App\Models\Setting\Tax;
9
-use Illuminate\Database\Eloquent\Factories\Factory;
10
-
11
-/**
12
- * @extends Factory<Tax>
13
- */
14
-class TaxFactory extends Factory
15
-{
16
-    /**
17
-     * The name of the factory's corresponding model.
18
-     */
19
-    protected $model = Tax::class;
20
-
21
-    /**
22
-     * Define the model's default state.
23
-     *
24
-     * @return array<string, mixed>
25
-     */
26
-    public function definition(): array
27
-    {
28
-        $computation = $this->faker->randomElement(TaxComputation::class);
29
-
30
-        if ($computation === TaxComputation::Fixed) {
31
-            $rate = $this->faker->biasedNumberBetween(1, 10) * 100; // $1 - $10
32
-        } else {
33
-            $rate = $this->faker->biasedNumberBetween(3, 25) * 10000; // 3% - 25%
34
-        }
35
-
36
-        return [
37
-            'name' => $this->faker->unique()->word,
38
-            'description' => $this->faker->sentence,
39
-            'rate' => $rate,
40
-            'computation' => $computation,
41
-            'type' => $this->faker->randomElement(TaxType::class),
42
-            'scope' => $this->faker->randomElement(TaxScope::class),
43
-            'enabled' => false,
44
-        ];
45
-    }
46
-
47
-    public function salesTax(): self
48
-    {
49
-        return $this->state([
50
-            'name' => 'State Sales Tax',
51
-            'type' => TaxType::Sales,
52
-        ]);
53
-    }
54
-
55
-    public function purchaseTax(): self
56
-    {
57
-        return $this->state([
58
-            'name' => 'State Purchase Tax',
59
-            'type' => TaxType::Purchase,
60
-        ]);
61
-    }
62
-}

+ 4
- 3
database/migrations/2023_09_03_100000_create_accounting_tables.php Ver arquivo

@@ -1,6 +1,5 @@
1 1
 <?php
2 2
 
3
-use App\Enums\Banking\BankAccountType;
4 3
 use Illuminate\Database\Migrations\Migration;
5 4
 use Illuminate\Database\Schema\Blueprint;
6 5
 use Illuminate\Support\Facades\Schema;
@@ -61,12 +60,14 @@ return new class extends Migration
61 60
             $table->foreignId('company_id')->constrained()->cascadeOnDelete();
62 61
             $table->foreignId('account_id')->nullable()->constrained('accounts')->nullOnDelete();
63 62
             $table->foreignId('institution_id')->nullable()->constrained('institutions')->nullOnDelete();
64
-            $table->string('type')->default(BankAccountType::DEFAULT);
63
+            $table->string('type')->default('depository');
65 64
             $table->string('number', 20)->nullable();
66 65
             $table->boolean('enabled')->default(true);
67 66
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
68 67
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
69 68
             $table->timestamps();
69
+
70
+            $table->unique(['company_id', 'account_id']);
70 71
         });
71 72
 
72 73
         Schema::create('connected_bank_accounts', function (Blueprint $table) {
@@ -82,7 +83,7 @@ return new class extends Migration
82 83
             $table->double('current_balance')->default(0);
83 84
             $table->string('name');
84 85
             $table->string('mask');
85
-            $table->string('type')->default(BankAccountType::DEFAULT);
86
+            $table->string('type')->default('depository');
86 87
             $table->string('subtype')->nullable();
87 88
             $table->boolean('import_transactions')->default(false);
88 89
             $table->timestamp('last_imported_at')->nullable();

+ 0
- 41
database/migrations/2023_09_08_011045_create_taxes_table.php Ver arquivo

@@ -1,41 +0,0 @@
1
-<?php
2
-
3
-use App\Enums\Setting\TaxComputation;
4
-use App\Enums\Setting\TaxType;
5
-use Illuminate\Database\Migrations\Migration;
6
-use Illuminate\Database\Schema\Blueprint;
7
-use Illuminate\Support\Facades\Schema;
8
-
9
-return new class extends Migration
10
-{
11
-    /**
12
-     * Run the migrations.
13
-     */
14
-    public function up(): void
15
-    {
16
-        Schema::create('taxes', function (Blueprint $table) {
17
-            $table->id();
18
-            $table->foreignId('company_id')->constrained()->cascadeOnDelete();
19
-            $table->string('name')->index();
20
-            $table->string('description')->nullable();
21
-            $table->integer('rate')->default(0);
22
-            $table->string('computation')->default(TaxComputation::DEFAULT);
23
-            $table->string('type')->default(TaxType::DEFAULT);
24
-            $table->string('scope')->nullable();
25
-            $table->boolean('enabled')->default(true);
26
-            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
27
-            $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
28
-            $table->timestamps();
29
-
30
-            $table->unique(['company_id', 'name', 'type']);
31
-        });
32
-    }
33
-
34
-    /**
35
-     * Reverse the migrations.
36
-     */
37
-    public function down(): void
38
-    {
39
-        Schema::dropIfExists('taxes');
40
-    }
41
-};

+ 0
- 4
database/migrations/2023_09_08_040159_create_company_defaults_table.php Ver arquivo

@@ -16,10 +16,6 @@ return new class extends Migration
16 16
             $table->foreignId('company_id')->constrained()->cascadeOnDelete();
17 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')->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 19
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
24 20
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
25 21
             $table->timestamps();

+ 4
- 8
database/migrations/2023_09_12_014413_create_appearances_table.php Ver arquivo

@@ -1,9 +1,5 @@
1 1
 <?php
2 2
 
3
-use App\Enums\Setting\Font;
4
-use App\Enums\Setting\PrimaryColor;
5
-use App\Enums\Setting\RecordsPerPage;
6
-use App\Enums\Setting\TableSortDirection;
7 3
 use Illuminate\Database\Migrations\Migration;
8 4
 use Illuminate\Database\Schema\Blueprint;
9 5
 use Illuminate\Support\Facades\Schema;
@@ -18,10 +14,10 @@ return new class extends Migration
18 14
         Schema::create('appearances', function (Blueprint $table) {
19 15
             $table->id();
20 16
             $table->foreignId('company_id')->constrained()->onDelete('cascade');
21
-            $table->string('primary_color')->default(PrimaryColor::DEFAULT);
22
-            $table->string('font')->default(Font::DEFAULT);
23
-            $table->string('table_sort_direction')->default(TableSortDirection::DEFAULT);
24
-            $table->unsignedTinyInteger('records_per_page')->default(RecordsPerPage::DEFAULT);
17
+            $table->string('primary_color')->default('indigo');
18
+            $table->string('font')->default('inter');
19
+            $table->string('table_sort_direction')->default('asc');
20
+            $table->unsignedTinyInteger('records_per_page')->default(10);
25 21
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
26 22
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
27 23
             $table->timestamps();

+ 3
- 6
database/migrations/2023_09_12_032057_create_document_defaults_table.php Ver arquivo

@@ -1,8 +1,5 @@
1 1
 <?php
2 2
 
3
-use App\Enums\Setting\Font;
4
-use App\Enums\Setting\PaymentTerms;
5
-use App\Enums\Setting\Template;
6 3
 use Illuminate\Database\Migrations\Migration;
7 4
 use Illuminate\Database\Schema\Blueprint;
8 5
 use Illuminate\Support\Facades\Schema;
@@ -23,14 +20,14 @@ return new class extends Migration
23 20
             $table->string('number_prefix')->nullable();
24 21
             $table->unsignedTinyInteger('number_digits')->default(5);
25 22
             $table->unsignedBigInteger('number_next')->default(1);
26
-            $table->string('payment_terms')->default(PaymentTerms::DEFAULT);
23
+            $table->string('payment_terms')->default('due_upon_receipt');
27 24
             $table->string('header')->nullable();
28 25
             $table->string('subheader')->nullable();
29 26
             $table->text('terms')->nullable();
30 27
             $table->text('footer')->nullable();
31 28
             $table->string('accent_color')->default('#4F46E5');
32
-            $table->string('font')->default(Font::DEFAULT);
33
-            $table->string('template')->default(Template::DEFAULT);
29
+            $table->string('font')->default('inter');
30
+            $table->string('template')->default('default');
34 31
             $table->json('item_name')->nullable();
35 32
             $table->json('unit_name')->nullable();
36 33
             $table->json('price_name')->nullable();

+ 4
- 8
database/migrations/2023_10_11_210415_create_localizations_table.php Ver arquivo

@@ -1,9 +1,5 @@
1 1
 <?php
2 2
 
3
-use App\Enums\Setting\DateFormat;
4
-use App\Enums\Setting\NumberFormat;
5
-use App\Enums\Setting\TimeFormat;
6
-use App\Enums\Setting\WeekStart;
7 3
 use Illuminate\Database\Migrations\Migration;
8 4
 use Illuminate\Database\Schema\Blueprint;
9 5
 use Illuminate\Support\Facades\Schema;
@@ -20,12 +16,12 @@ return new class extends Migration
20 16
             $table->foreignId('company_id')->constrained()->cascadeOnDelete();
21 17
             $table->string('language')->default('en');
22 18
             $table->string('timezone')->nullable();
23
-            $table->string('date_format')->default(DateFormat::DEFAULT);
24
-            $table->string('time_format')->default(TimeFormat::DEFAULT);
19
+            $table->string('date_format')->default('M j, Y');
20
+            $table->string('time_format')->default('g:i A');
25 21
             $table->unsignedTinyInteger('fiscal_year_end_month')->default(12);
26 22
             $table->unsignedTinyInteger('fiscal_year_end_day')->default(31);
27
-            $table->unsignedTinyInteger('week_start')->default(WeekStart::DEFAULT);
28
-            $table->string('number_format')->default(NumberFormat::DEFAULT);
23
+            $table->unsignedTinyInteger('week_start')->default(1);
24
+            $table->string('number_format')->default('comma_dot');
29 25
             $table->boolean('percent_first')->default(false);
30 26
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
31 27
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();

database/migrations/2023_09_08_024259_create_discounts_table.php → database/migrations/2024_11_14_230753_create_adjustments_table.php Ver arquivo

@@ -1,7 +1,5 @@
1 1
 <?php
2 2
 
3
-use App\Enums\Setting\DiscountComputation;
4
-use App\Enums\Setting\DiscountType;
5 3
 use Illuminate\Database\Migrations\Migration;
6 4
 use Illuminate\Database\Schema\Blueprint;
7 5
 use Illuminate\Support\Facades\Schema;
@@ -13,14 +11,14 @@ return new class extends Migration
13 11
      */
14 12
     public function up(): void
15 13
     {
16
-        Schema::create('discounts', function (Blueprint $table) {
14
+        Schema::create('adjustments', function (Blueprint $table) {
17 15
             $table->id();
18 16
             $table->foreignId('company_id')->constrained()->cascadeOnDelete();
19
-            $table->string('name')->index();
20
-            $table->string('description')->nullable();
17
+            $table->foreignId('account_id')->nullable()->constrained('accounts')->nullOnDelete();
18
+            $table->string('category')->default('tax');
19
+            $table->string('type')->default('sales');
21 20
             $table->integer('rate')->default(0);
22
-            $table->string('computation')->default(DiscountComputation::DEFAULT);
23
-            $table->string('type')->default(DiscountType::DEFAULT);
21
+            $table->string('computation')->default('percentage');
24 22
             $table->string('scope')->nullable();
25 23
             $table->dateTime('start_date')->nullable();
26 24
             $table->dateTime('end_date')->nullable();
@@ -29,7 +27,7 @@ return new class extends Migration
29 27
             $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
30 28
             $table->timestamps();
31 29
 
32
-            $table->unique(['company_id', 'name', 'type']);
30
+            $table->unique(['company_id', 'account_id']);
33 31
         });
34 32
     }
35 33
 
@@ -38,6 +36,6 @@ return new class extends Migration
38 36
      */
39 37
     public function down(): void
40 38
     {
41
-        Schema::dropIfExists('discounts');
39
+        Schema::dropIfExists('adjustments');
42 40
     }
43 41
 };

+ 17
- 17
package-lock.json Ver arquivo

@@ -1187,9 +1187,9 @@
1187 1187
             "license": "MIT"
1188 1188
         },
1189 1189
         "node_modules/electron-to-chromium": {
1190
-            "version": "1.5.57",
1191
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.57.tgz",
1192
-            "integrity": "sha512-xS65H/tqgOwUBa5UmOuNSLuslDo7zho0y/lgQw35pnrqiZh7UOWHCeL/Bt6noJATbA6tpQJGCifsFsIRZj1Fqg==",
1190
+            "version": "1.5.59",
1191
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.59.tgz",
1192
+            "integrity": "sha512-faAXB6+gEbC8FsiRdpOXgOe4snP49YwjiXynEB8Mp7sUx80W5eN+BnnBHJ/F7eIeLzs+QBfDD40bJMm97oEFcw==",
1193 1193
             "dev": true,
1194 1194
             "license": "ISC"
1195 1195
         },
@@ -2447,34 +2447,34 @@
2447 2447
             }
2448 2448
         },
2449 2449
         "node_modules/tailwindcss": {
2450
-            "version": "3.4.14",
2451
-            "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
2452
-            "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
2450
+            "version": "3.4.15",
2451
+            "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
2452
+            "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==",
2453 2453
             "dev": true,
2454 2454
             "license": "MIT",
2455 2455
             "dependencies": {
2456 2456
                 "@alloc/quick-lru": "^5.2.0",
2457 2457
                 "arg": "^5.0.2",
2458
-                "chokidar": "^3.5.3",
2458
+                "chokidar": "^3.6.0",
2459 2459
                 "didyoumean": "^1.2.2",
2460 2460
                 "dlv": "^1.1.3",
2461
-                "fast-glob": "^3.3.0",
2461
+                "fast-glob": "^3.3.2",
2462 2462
                 "glob-parent": "^6.0.2",
2463 2463
                 "is-glob": "^4.0.3",
2464
-                "jiti": "^1.21.0",
2464
+                "jiti": "^1.21.6",
2465 2465
                 "lilconfig": "^2.1.0",
2466
-                "micromatch": "^4.0.5",
2466
+                "micromatch": "^4.0.8",
2467 2467
                 "normalize-path": "^3.0.0",
2468 2468
                 "object-hash": "^3.0.0",
2469
-                "picocolors": "^1.0.0",
2470
-                "postcss": "^8.4.23",
2469
+                "picocolors": "^1.1.1",
2470
+                "postcss": "^8.4.47",
2471 2471
                 "postcss-import": "^15.1.0",
2472 2472
                 "postcss-js": "^4.0.1",
2473
-                "postcss-load-config": "^4.0.1",
2474
-                "postcss-nested": "^6.0.1",
2475
-                "postcss-selector-parser": "^6.0.11",
2476
-                "resolve": "^1.22.2",
2477
-                "sucrase": "^3.32.0"
2473
+                "postcss-load-config": "^4.0.2",
2474
+                "postcss-nested": "^6.2.0",
2475
+                "postcss-selector-parser": "^6.1.2",
2476
+                "resolve": "^1.22.8",
2477
+                "sucrase": "^3.35.0"
2478 2478
             },
2479 2479
             "bin": {
2480 2480
                 "tailwind": "lib/cli.js",

Carregando…
Cancelar
Salvar