Andrew Wallo 5 місяці тому
джерело
коміт
88ad988e42

+ 5
- 3
app/Services/ChartOfAccountsService.php Переглянути файл

@@ -9,13 +9,15 @@ use App\Models\Accounting\AccountSubtype;
9 9
 use App\Models\Accounting\Adjustment;
10 10
 use App\Models\Banking\BankAccount;
11 11
 use App\Models\Company;
12
-use App\Utilities\Currency\CurrencyAccessor;
13 12
 use Exception;
14 13
 
15 14
 class ChartOfAccountsService
16 15
 {
17
-    public function createChartOfAccounts(Company $company): void
16
+    private string $currencyCode;
17
+
18
+    public function createChartOfAccounts(Company $company, string $currencyCode = 'USD'): void
18 19
     {
20
+        $this->currencyCode = $currencyCode;
19 21
         $chartOfAccounts = config('chart-of-accounts.default');
20 22
 
21 23
         // Always create a non-recoverable "Purchase Tax" adjustment, even without an account
@@ -53,7 +55,7 @@ class ChartOfAccountsService
53 55
     {
54 56
         if (isset($subtypeConfig['accounts']) && is_array($subtypeConfig['accounts'])) {
55 57
             $baseCode = $subtypeConfig['base_code'];
56
-            $defaultCurrencyCode = CurrencyAccessor::getDefaultCurrency();
58
+            $defaultCurrencyCode = $this->currencyCode;
57 59
 
58 60
             if (empty($defaultCurrencyCode)) {
59 61
                 throw new Exception('No default currency available for creating accounts.');

+ 1
- 1
app/Services/CompanyDefaultService.php Переглянути файл

@@ -17,7 +17,7 @@ class CompanyDefaultService
17 17
 
18 18
             // Create Chart of Accounts
19 19
             $chartOfAccountsService = app(ChartOfAccountsService::class);
20
-            $chartOfAccountsService->createChartOfAccounts($company);
20
+            $chartOfAccountsService->createChartOfAccounts($company, $currencyCode);
21 21
 
22 22
             // Get the default bank account and update the company default record
23 23
             $defaultBankAccount = $company->bankAccounts()->where('enabled', true)->firstOrFail();

+ 27
- 36
database/factories/Accounting/DocumentLineItemFactory.php Переглянути файл

@@ -43,23 +43,20 @@ class DocumentLineItemFactory extends Factory
43 43
         return $this
44 44
             ->for($invoice, 'documentable')
45 45
             ->for($invoice->company, 'company')
46
-            ->state(function (array $attributes) {
47
-                $offering = Offering::where('sellable', true)
46
+            ->afterCreating(function (DocumentLineItem $lineItem) {
47
+                $offering = Offering::query()
48
+                    ->where('company_id', $lineItem->company_id)
49
+                    ->where('sellable', true)
48 50
                     ->inRandomOrder()
49
-                    ->first();
51
+                    ->firstOrFail();
50 52
 
51
-                return [
53
+                $lineItem->updateQuietly([
52 54
                     'offering_id' => $offering->id,
53 55
                     'unit_price' => $offering->price,
54
-                ];
55
-            })
56
-            ->afterCreating(function (DocumentLineItem $lineItem) {
57
-                $offering = $lineItem->offering;
56
+                ]);
58 57
 
59
-                if ($offering) {
60
-                    $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
61
-                    $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
62
-                }
58
+                $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
59
+                $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
63 60
 
64 61
                 $lineItem->refresh();
65 62
 
@@ -78,23 +75,20 @@ class DocumentLineItemFactory extends Factory
78 75
         return $this
79 76
             ->for($estimate, 'documentable')
80 77
             ->for($estimate->company, 'company')
81
-            ->state(function (array $attributes) {
82
-                $offering = Offering::where('sellable', true)
78
+            ->afterCreating(function (DocumentLineItem $lineItem) {
79
+                $offering = Offering::query()
80
+                    ->where('company_id', $lineItem->company_id)
81
+                    ->where('sellable', true)
83 82
                     ->inRandomOrder()
84
-                    ->first();
83
+                    ->firstOrFail();
85 84
 
86
-                return [
85
+                $lineItem->updateQuietly([
87 86
                     'offering_id' => $offering->id,
88 87
                     'unit_price' => $offering->price,
89
-                ];
90
-            })
91
-            ->afterCreating(function (DocumentLineItem $lineItem) {
92
-                $offering = $lineItem->offering;
88
+                ]);
93 89
 
94
-                if ($offering) {
95
-                    $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
96
-                    $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
97
-                }
90
+                $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
91
+                $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
98 92
 
99 93
                 $lineItem->refresh();
100 94
 
@@ -113,23 +107,20 @@ class DocumentLineItemFactory extends Factory
113 107
         return $this
114 108
             ->for($bill, 'documentable')
115 109
             ->for($bill->company, 'company')
116
-            ->state(function (array $attributes) {
117
-                $offering = Offering::where('purchasable', true)
110
+            ->afterCreating(function (DocumentLineItem $lineItem) {
111
+                $offering = Offering::query()
112
+                    ->where('company_id', $lineItem->company_id)
113
+                    ->where('purchasable', true)
118 114
                     ->inRandomOrder()
119
-                    ->first();
115
+                    ->firstOrFail();
120 116
 
121
-                return [
117
+                $lineItem->updateQuietly([
122 118
                     'offering_id' => $offering->id,
123 119
                     'unit_price' => $offering->price,
124
-                ];
125
-            })
126
-            ->afterCreating(function (DocumentLineItem $lineItem) {
127
-                $offering = $lineItem->offering;
120
+                ]);
128 121
 
129
-                if ($offering) {
130
-                    $lineItem->purchaseTaxes()->syncWithoutDetaching($offering->purchaseTaxes->pluck('id')->toArray());
131
-                    $lineItem->purchaseDiscounts()->syncWithoutDetaching($offering->purchaseDiscounts->pluck('id')->toArray());
132
-                }
122
+                $lineItem->purchaseTaxes()->syncWithoutDetaching($offering->purchaseTaxes->pluck('id')->toArray());
123
+                $lineItem->purchaseDiscounts()->syncWithoutDetaching($offering->purchaseDiscounts->pluck('id')->toArray());
133 124
 
134 125
                 $lineItem->refresh();
135 126
 

+ 41
- 57
database/factories/Common/OfferingFactory.php Переглянути файл

@@ -34,82 +34,66 @@ class OfferingFactory extends Factory
34 34
             'description' => $this->faker->sentence,
35 35
             'type' => $this->faker->randomElement(OfferingType::cases()),
36 36
             'price' => $this->faker->numberBetween(5, 1000),
37
-            'sellable' => $this->faker->boolean(80),
38
-            'purchasable' => $this->faker->boolean(80),
39
-            'income_account_id' => function (array $attributes) {
40
-                return $attributes['sellable'] ? 10 : null;
41
-            },
42
-            'expense_account_id' => function (array $attributes) {
43
-                return $attributes['purchasable'] ? $this->faker->numberBetween(17, 35) : null;
44
-            },
37
+            'sellable' => false,
38
+            'purchasable' => false,
39
+            'income_account_id' => null,
40
+            'expense_account_id' => null,
45 41
             'created_by' => 1,
46 42
             'updated_by' => 1,
47 43
         ];
48 44
     }
49 45
 
50
-    public function sellable(): self
46
+    public function withSalesAdjustments(): self
51 47
     {
52
-        $incomeAccount = Account::query()
53
-            ->where('category', AccountCategory::Revenue)
54
-            ->where('type', AccountType::OperatingRevenue)
55
-            ->inRandomOrder()
56
-            ->first();
48
+        return $this->afterCreating(function (Offering $offering) {
49
+            $incomeAccount = Account::query()
50
+                ->where('company_id', $offering->company_id)
51
+                ->where('category', AccountCategory::Revenue)
52
+                ->where('type', AccountType::OperatingRevenue)
53
+                ->inRandomOrder()
54
+                ->firstOrFail();
57 55
 
58
-        return $this->state(function (array $attributes) use ($incomeAccount) {
59
-            return [
56
+            $offering->updateQuietly([
60 57
                 'sellable' => true,
61
-                'income_account_id' => $incomeAccount?->id ?? 10,
62
-            ];
63
-        });
64
-    }
65
-
66
-    public function purchasable(): self
67
-    {
68
-        $expenseAccount = Account::query()
69
-            ->where('category', AccountCategory::Expense)
70
-            ->where('type', AccountType::OperatingExpense)
71
-            ->inRandomOrder()
72
-            ->first();
73
-
74
-        return $this->state(function (array $attributes) use ($expenseAccount) {
75
-            return [
76
-                'purchasable' => true,
77
-                'expense_account_id' => $expenseAccount?->id ?? $this->faker->numberBetween(17, 35),
78
-            ];
79
-        });
80
-    }
58
+                'income_account_id' => $incomeAccount->id,
59
+            ]);
81 60
 
82
-    public function withSalesAdjustments(): self
83
-    {
84
-        return $this->afterCreating(function (Offering $offering) {
85
-            if ($offering->sellable) {
86
-                $adjustments = $offering->company?->adjustments()
87
-                    ->where('type', AdjustmentType::Sales)
88
-                    ->pluck('id');
61
+            $adjustments = $offering->company?->adjustments()
62
+                ->where('type', AdjustmentType::Sales)
63
+                ->pluck('id');
89 64
 
90
-                $adjustmentsToAttach = $adjustments->isNotEmpty()
91
-                    ? $adjustments->random(min(2, $adjustments->count()))
92
-                    : Adjustment::factory()->salesTax()->count(2)->create()->pluck('id');
65
+            $adjustmentsToAttach = $adjustments->isNotEmpty()
66
+                ? $adjustments->random(min(2, $adjustments->count()))
67
+                : Adjustment::factory()->salesTax()->count(2)->create()->pluck('id');
93 68
 
94
-                $offering->salesAdjustments()->attach($adjustmentsToAttach);
95
-            }
69
+            $offering->salesAdjustments()->attach($adjustmentsToAttach);
96 70
         });
97 71
     }
98 72
 
99 73
     public function withPurchaseAdjustments(): self
100 74
     {
101 75
         return $this->afterCreating(function (Offering $offering) {
102
-            if ($offering->purchasable) {
103
-                $adjustments = $offering->company?->adjustments()
104
-                    ->where('type', AdjustmentType::Purchase)
105
-                    ->pluck('id');
76
+            $expenseAccount = Account::query()
77
+                ->where('company_id', $offering->company_id)
78
+                ->where('category', AccountCategory::Expense)
79
+                ->where('type', AccountType::OperatingExpense)
80
+                ->inRandomOrder()
81
+                ->firstOrFail();
82
+
83
+            $offering->updateQuietly([
84
+                'purchasable' => true,
85
+                'expense_account_id' => $expenseAccount->id,
86
+            ]);
87
+
88
+            $adjustments = $offering->company?->adjustments()
89
+                ->where('type', AdjustmentType::Purchase)
90
+                ->pluck('id');
106 91
 
107
-                $adjustmentsToAttach = $adjustments->isNotEmpty()
108
-                    ? $adjustments->random(min(2, $adjustments->count()))
109
-                    : Adjustment::factory()->purchaseTax()->count(2)->create()->pluck('id');
92
+            $adjustmentsToAttach = $adjustments->isNotEmpty()
93
+                ? $adjustments->random(min(2, $adjustments->count()))
94
+                : Adjustment::factory()->purchaseTax()->count(2)->create()->pluck('id');
110 95
 
111
-                $offering->purchaseAdjustments()->attach($adjustmentsToAttach);
112
-            }
96
+            $offering->purchaseAdjustments()->attach($adjustmentsToAttach);
113 97
         });
114 98
     }
115 99
 }

+ 0
- 2
database/factories/CompanyFactory.php Переглянути файл

@@ -111,9 +111,7 @@ class CompanyFactory extends Factory
111 111
         return $this->afterCreating(function (Company $company) use ($count) {
112 112
             Offering::factory()
113 113
                 ->count($count)
114
-                ->sellable()
115 114
                 ->withSalesAdjustments()
116
-                ->purchasable()
117 115
                 ->withPurchaseAdjustments()
118 116
                 ->create([
119 117
                     'company_id' => $company->id,

Завантаження…
Відмінити
Зберегти