Andrew Wallo 10 月之前
父節點
當前提交
ccffc4e786

+ 112
- 0
app/Concerns/ManagesLineItems.php 查看文件

1
+<?php
2
+
3
+namespace App\Concerns;
4
+
5
+use App\Enums\Accounting\AdjustmentComputation;
6
+use App\Models\Accounting\DocumentLineItem;
7
+use App\Models\Accounting\Invoice;
8
+use App\Utilities\Currency\CurrencyConverter;
9
+use Illuminate\Support\Collection;
10
+
11
+trait ManagesLineItems
12
+{
13
+    protected function handleLineItems(Invoice $record, Collection $lineItems): void
14
+    {
15
+        foreach ($lineItems as $itemData) {
16
+            $lineItem = isset($itemData['id'])
17
+                ? $record->lineItems->find($itemData['id'])
18
+                : $record->lineItems()->make();
19
+
20
+            $lineItem->fill([
21
+                'offering_id' => $itemData['offering_id'],
22
+                'description' => $itemData['description'],
23
+                'quantity' => $itemData['quantity'],
24
+                'unit_price' => $itemData['unit_price'],
25
+            ]);
26
+
27
+            if (! $lineItem->exists) {
28
+                $lineItem->documentable()->associate($record);
29
+            }
30
+
31
+            $lineItem->save();
32
+
33
+            $this->handleLineItemAdjustments($lineItem, $itemData, $record->discount_method);
34
+            $this->updateLineItemTotals($lineItem, $record->discount_method);
35
+        }
36
+    }
37
+
38
+    protected function deleteRemovedLineItems(Invoice $record, Collection $lineItems): void
39
+    {
40
+        $existingLineItemIds = $record->lineItems->pluck('id');
41
+        $updatedLineItemIds = $lineItems->pluck('id')->filter();
42
+        $lineItemsToDelete = $existingLineItemIds->diff($updatedLineItemIds);
43
+
44
+        if ($lineItemsToDelete->isNotEmpty()) {
45
+            $record
46
+                ->lineItems()
47
+                ->whereIn('id', $lineItemsToDelete)
48
+                ->each(fn (DocumentLineItem $lineItem) => $lineItem->delete());
49
+        }
50
+    }
51
+
52
+    protected function handleLineItemAdjustments(DocumentLineItem $lineItem, array $itemData, string $discountMethod): void
53
+    {
54
+        $adjustmentIds = collect($itemData['salesTaxes'] ?? [])
55
+            ->merge($discountMethod === 'line_items' ? ($itemData['salesDiscounts'] ?? []) : [])
56
+            ->filter()
57
+            ->unique();
58
+
59
+        $lineItem->adjustments()->sync($adjustmentIds);
60
+        $lineItem->refresh();
61
+    }
62
+
63
+    protected function updateLineItemTotals(DocumentLineItem $lineItem, string $discountMethod): void
64
+    {
65
+        $lineItem->updateQuietly([
66
+            'tax_total' => $lineItem->calculateTaxTotal()->getAmount(),
67
+            'discount_total' => $discountMethod === 'line_items'
68
+                ? $lineItem->calculateDiscountTotal()->getAmount()
69
+                : 0,
70
+        ]);
71
+    }
72
+
73
+    protected function updateInvoiceTotals(Invoice $record, array $data): array
74
+    {
75
+        $subtotalCents = $record->lineItems()->sum('subtotal');
76
+        $taxTotalCents = $record->lineItems()->sum('tax_total');
77
+        $discountTotalCents = $this->calculateDiscountTotal(
78
+            $data['discount_method'],
79
+            AdjustmentComputation::parse($data['discount_computation']),
80
+            $data['discount_rate'] ?? null,
81
+            $subtotalCents,
82
+            $record
83
+        );
84
+
85
+        $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
86
+
87
+        return [
88
+            'subtotal' => CurrencyConverter::convertCentsToFormatSimple($subtotalCents),
89
+            'tax_total' => CurrencyConverter::convertCentsToFormatSimple($taxTotalCents),
90
+            'discount_total' => CurrencyConverter::convertCentsToFormatSimple($discountTotalCents),
91
+            'total' => CurrencyConverter::convertCentsToFormatSimple($grandTotalCents),
92
+        ];
93
+    }
94
+
95
+    protected function calculateDiscountTotal(
96
+        string $discountMethod,
97
+        ?AdjustmentComputation $discountComputation,
98
+        ?string $discountRate,
99
+        int $subtotalCents,
100
+        Invoice $record
101
+    ): int {
102
+        if ($discountMethod === 'line_items') {
103
+            return $record->lineItems()->sum('discount_total');
104
+        }
105
+
106
+        if ($discountComputation === AdjustmentComputation::Percentage) {
107
+            return (int) ($subtotalCents * ((float) $discountRate / 100));
108
+        }
109
+
110
+        return CurrencyConverter::convertToCents($discountRate);
111
+    }
112
+}

+ 0
- 73
app/Filament/Company/Clusters/Settings/Pages/CompanyDefault.php 查看文件

6
 use App\Filament\Company\Clusters\Settings;
6
 use App\Filament\Company\Clusters\Settings;
7
 use App\Models\Banking\BankAccount;
7
 use App\Models\Banking\BankAccount;
8
 use App\Models\Setting\CompanyDefault as CompanyDefaultModel;
8
 use App\Models\Setting\CompanyDefault as CompanyDefaultModel;
9
-use App\Models\Setting\Discount;
10
-use App\Models\Setting\Tax;
11
 use Filament\Actions\Action;
9
 use Filament\Actions\Action;
12
 use Filament\Actions\ActionGroup;
10
 use Filament\Actions\ActionGroup;
13
 use Filament\Forms\Components\Component;
11
 use Filament\Forms\Components\Component;
108
         return $form
106
         return $form
109
             ->schema([
107
             ->schema([
110
                 $this->getGeneralSection(),
108
                 $this->getGeneralSection(),
111
-                // $this->getModifiersSection(),
112
             ])
109
             ])
113
             ->model($this->record)
110
             ->model($this->record)
114
             ->statePath('data')
111
             ->statePath('data')
140
             ])->columns();
137
             ])->columns();
141
     }
138
     }
142
 
139
 
143
-    protected function getModifiersSection(): Component
144
-    {
145
-        return Section::make('Taxes & Discounts')
146
-            ->schema([
147
-                Select::make('sales_tax_id')
148
-                    ->softRequired()
149
-                    ->localizeLabel()
150
-                    ->relationship('salesTax', 'name')
151
-                    ->getOptionLabelFromRecordUsing(function (Tax $record) {
152
-                        $currencyCode = $this->record->currency_code;
153
-
154
-                        $rate = rateFormat($record->rate, $record->computation->value, $currencyCode);
155
-
156
-                        $rateBadge = $this->renderBadgeOptionLabel($rate);
157
-
158
-                        return "{$record->name} ⁓ {$rateBadge}";
159
-                    })
160
-                    ->allowHtml()
161
-                    ->saveRelationshipsUsing(null)
162
-                    ->searchable(),
163
-                Select::make('purchase_tax_id')
164
-                    ->softRequired()
165
-                    ->localizeLabel()
166
-                    ->relationship('purchaseTax', 'name')
167
-                    ->getOptionLabelFromRecordUsing(function (Tax $record) {
168
-                        $currencyCode = $this->record->currency_code;
169
-
170
-                        $rate = rateFormat($record->rate, $record->computation->value, $currencyCode);
171
-
172
-                        $rateBadge = $this->renderBadgeOptionLabel($rate);
173
-
174
-                        return "{$record->name} ⁓ {$rateBadge}";
175
-                    })
176
-                    ->allowHtml()
177
-                    ->saveRelationshipsUsing(null)
178
-                    ->searchable(),
179
-                Select::make('sales_discount_id')
180
-                    ->softRequired()
181
-                    ->localizeLabel()
182
-                    ->relationship('salesDiscount', 'name')
183
-                    ->getOptionLabelFromRecordUsing(function (Discount $record) {
184
-                        $currencyCode = $this->record->currency_code;
185
-
186
-                        $rate = rateFormat($record->rate, $record->computation->value, $currencyCode);
187
-
188
-                        $rateBadge = $this->renderBadgeOptionLabel($rate);
189
-
190
-                        return "{$record->name} ⁓ {$rateBadge}";
191
-                    })
192
-                    ->saveRelationshipsUsing(null)
193
-                    ->allowHtml()
194
-                    ->searchable(),
195
-                Select::make('purchase_discount_id')
196
-                    ->softRequired()
197
-                    ->localizeLabel()
198
-                    ->relationship('purchaseDiscount', 'name')
199
-                    ->getOptionLabelFromRecordUsing(function (Discount $record) {
200
-                        $currencyCode = $this->record->currency_code;
201
-                        $rate = rateFormat($record->rate, $record->computation->value, $currencyCode);
202
-
203
-                        $rateBadge = $this->renderBadgeOptionLabel($rate);
204
-
205
-                        return "{$record->name} ⁓ {$rateBadge}";
206
-                    })
207
-                    ->allowHtml()
208
-                    ->saveRelationshipsUsing(null)
209
-                    ->searchable(),
210
-            ])->columns();
211
-    }
212
-
213
     public function renderBadgeOptionLabel(string $label): string
140
     public function renderBadgeOptionLabel(string $label): string
214
     {
141
     {
215
         return Blade::render('filament::components.badge', [
142
         return Blade::render('filament::components.badge', [

+ 11
- 122
app/Filament/Company/Resources/Sales/InvoiceResource.php 查看文件

3
 namespace App\Filament\Company\Resources\Sales;
3
 namespace App\Filament\Company\Resources\Sales;
4
 
4
 
5
 use App\Collections\Accounting\InvoiceCollection;
5
 use App\Collections\Accounting\InvoiceCollection;
6
-use App\Enums\Accounting\AdjustmentComputation;
7
 use App\Enums\Accounting\InvoiceStatus;
6
 use App\Enums\Accounting\InvoiceStatus;
8
 use App\Enums\Accounting\PaymentMethod;
7
 use App\Enums\Accounting\PaymentMethod;
9
 use App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
8
 use App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
13
 use App\Filament\Tables\Actions\ReplicateBulkAction;
12
 use App\Filament\Tables\Actions\ReplicateBulkAction;
14
 use App\Filament\Tables\Filters\DateRangeFilter;
13
 use App\Filament\Tables\Filters\DateRangeFilter;
15
 use App\Models\Accounting\Adjustment;
14
 use App\Models\Accounting\Adjustment;
16
-use App\Models\Accounting\DocumentLineItem;
17
 use App\Models\Accounting\Invoice;
15
 use App\Models\Accounting\Invoice;
18
 use App\Models\Banking\BankAccount;
16
 use App\Models\Banking\BankAccount;
19
 use App\Models\Common\Offering;
17
 use App\Models\Common\Offering;
32
 use Filament\Tables\Table;
30
 use Filament\Tables\Table;
33
 use Illuminate\Database\Eloquent\Builder;
31
 use Illuminate\Database\Eloquent\Builder;
34
 use Illuminate\Database\Eloquent\Collection;
32
 use Illuminate\Database\Eloquent\Collection;
35
-use Illuminate\Database\Eloquent\Model;
36
 use Illuminate\Support\Facades\Auth;
33
 use Illuminate\Support\Facades\Auth;
37
 use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
34
 use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
38
 
35
 
150
                         ])->from('md'),
147
                         ])->from('md'),
151
                         TableRepeater::make('lineItems')
148
                         TableRepeater::make('lineItems')
152
                             ->relationship()
149
                             ->relationship()
153
-                            ->saveRelationshipsUsing(function (TableRepeater $component, Forms\Contracts\HasForms $livewire, ?array $state) {
154
-                                if (! is_array($state)) {
155
-                                    $state = [];
156
-                                }
157
-
158
-                                $relationship = $component->getRelationship();
159
-
160
-                                $existingRecords = $component->getCachedExistingRecords();
161
-
162
-                                $recordsToDelete = [];
163
-
164
-                                foreach ($existingRecords->pluck($relationship->getRelated()->getKeyName()) as $keyToCheckForDeletion) {
165
-                                    if (array_key_exists("record-{$keyToCheckForDeletion}", $state)) {
166
-                                        continue;
167
-                                    }
168
-
169
-                                    $recordsToDelete[] = $keyToCheckForDeletion;
170
-                                    $existingRecords->forget("record-{$keyToCheckForDeletion}");
171
-                                }
172
-
173
-                                $relationship
174
-                                    ->whereKey($recordsToDelete)
175
-                                    ->get()
176
-                                    ->each(static fn (Model $record) => $record->delete());
177
-
178
-                                $childComponentContainers = $component->getChildComponentContainers(
179
-                                    withHidden: $component->shouldSaveRelationshipsWhenHidden(),
180
-                                );
181
-
182
-                                $itemOrder = 1;
183
-                                $orderColumn = $component->getOrderColumn();
184
-
185
-                                $translatableContentDriver = $livewire->makeFilamentTranslatableContentDriver();
186
-
187
-                                foreach ($childComponentContainers as $itemKey => $item) {
188
-                                    $itemData = $item->getState(shouldCallHooksBefore: false);
189
-
190
-                                    if ($orderColumn) {
191
-                                        $itemData[$orderColumn] = $itemOrder;
192
-
193
-                                        $itemOrder++;
194
-                                    }
195
-
196
-                                    if ($record = ($existingRecords[$itemKey] ?? null)) {
197
-                                        $itemData = $component->mutateRelationshipDataBeforeSave($itemData, record: $record);
198
-
199
-                                        if ($itemData === null) {
200
-                                            continue;
201
-                                        }
202
-
203
-                                        $translatableContentDriver ?
204
-                                            $translatableContentDriver->updateRecord($record, $itemData) :
205
-                                            $record->fill($itemData)->save();
206
-
207
-                                        continue;
208
-                                    }
209
-
210
-                                    $relatedModel = $component->getRelatedModel();
211
-
212
-                                    $itemData = $component->mutateRelationshipDataBeforeCreate($itemData);
213
-
214
-                                    if ($itemData === null) {
215
-                                        continue;
216
-                                    }
217
-
218
-                                    if ($translatableContentDriver) {
219
-                                        $record = $translatableContentDriver->makeRecord($relatedModel, $itemData);
220
-                                    } else {
221
-                                        $record = new $relatedModel;
222
-                                        $record->fill($itemData);
223
-                                    }
224
-
225
-                                    $record = $relationship->save($record);
226
-                                    $item->model($record)->saveRelationships();
227
-                                    $existingRecords->push($record);
228
-                                }
229
-
230
-                                $component->getRecord()->setRelation($component->getRelationshipName(), $existingRecords);
231
-
232
-                                /** @var Invoice $invoice */
233
-                                $invoice = $component->getRecord();
234
-
235
-                                // Recalculate totals for line items
236
-                                // Recalculate totals for line items
237
-                                $invoice->lineItems()->each(function (DocumentLineItem $lineItem) use ($invoice) {
238
-                                    $lineItem->updateQuietly([
239
-                                        'tax_total' => $lineItem->calculateTaxTotal()->getAmount(),
240
-                                        'discount_total' => $invoice->discount_method === 'line_items'
241
-                                            ? $lineItem->calculateDiscountTotal()->getAmount()
242
-                                            : 0,
243
-                                    ]);
244
-                                });
245
-
246
-                                $subtotal = $invoice->lineItems()->sum('subtotal') / 100;
247
-                                $taxTotal = $invoice->lineItems()->sum('tax_total') / 100;
248
-                                if ($invoice->discount_method === 'line_items') {
249
-                                    $discountTotal = $invoice->lineItems()->sum('discount_total') / 100;
250
-                                } else {
251
-                                    // Calculate invoice-level discount
252
-                                    if ($invoice->discount_computation === AdjustmentComputation::Percentage) {
253
-                                        $discountTotal = $subtotal * ($invoice->discount_rate / 100);
254
-                                    } else {
255
-                                        $discountTotal = $invoice->discount_rate;
256
-                                    }
257
-                                }
258
-
259
-                                $grandTotal = $subtotal + $taxTotal - $discountTotal;
260
-
261
-                                $invoice->updateQuietly([
262
-                                    'subtotal' => $subtotal,
263
-                                    'tax_total' => $taxTotal,
264
-                                    'discount_total' => $discountTotal,
265
-                                    'total' => $grandTotal,
266
-                                ]);
267
-
268
-                                if ($invoice->approved_at && $invoice->approvalTransaction) {
269
-                                    $invoice->updateApprovalTransaction();
270
-                                }
271
-                            })
150
+                            ->saveRelationshipsUsing(null)
151
+                            ->dehydrated(true)
272
                             ->headers(function (Forms\Get $get) {
152
                             ->headers(function (Forms\Get $get) {
273
                                 $hasDiscounts = $get('discount_method') === 'line_items';
153
                                 $hasDiscounts = $get('discount_method') === 'line_items';
274
 
154
 
323
                                     ->default(0),
203
                                     ->default(0),
324
                                 Forms\Components\Select::make('salesTaxes')
204
                                 Forms\Components\Select::make('salesTaxes')
325
                                     ->relationship('salesTaxes', 'name')
205
                                     ->relationship('salesTaxes', 'name')
206
+                                    ->saveRelationshipsUsing(null)
207
+                                    ->dehydrated(true)
326
                                     ->preload()
208
                                     ->preload()
327
                                     ->multiple()
209
                                     ->multiple()
328
                                     ->live()
210
                                     ->live()
329
                                     ->searchable(),
211
                                     ->searchable(),
330
                                 Forms\Components\Select::make('salesDiscounts')
212
                                 Forms\Components\Select::make('salesDiscounts')
331
                                     ->relationship('salesDiscounts', 'name')
213
                                     ->relationship('salesDiscounts', 'name')
214
+                                    ->saveRelationshipsUsing(null)
215
+                                    ->dehydrated(true)
332
                                     ->preload()
216
                                     ->preload()
333
                                     ->multiple()
217
                                     ->multiple()
334
                                     ->live()
218
                                     ->live()
386
         return $table
270
         return $table
387
             ->defaultSort('due_date')
271
             ->defaultSort('due_date')
388
             ->columns([
272
             ->columns([
273
+                Tables\Columns\TextColumn::make('id')
274
+                    ->label('ID')
275
+                    ->sortable()
276
+                    ->toggleable(isToggledHiddenByDefault: true)
277
+                    ->searchable(),
389
                 Tables\Columns\TextColumn::make('status')
278
                 Tables\Columns\TextColumn::make('status')
390
                     ->badge()
279
                     ->badge()
391
                     ->searchable(),
280
                     ->searchable(),

+ 18
- 0
app/Filament/Company/Resources/Sales/InvoiceResource/Pages/CreateInvoice.php 查看文件

2
 
2
 
3
 namespace App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
3
 namespace App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
4
 
4
 
5
+use App\Concerns\ManagesLineItems;
5
 use App\Concerns\RedirectToListPage;
6
 use App\Concerns\RedirectToListPage;
6
 use App\Filament\Company\Resources\Sales\InvoiceResource;
7
 use App\Filament\Company\Resources\Sales\InvoiceResource;
8
+use App\Models\Accounting\Invoice;
7
 use Filament\Resources\Pages\CreateRecord;
9
 use Filament\Resources\Pages\CreateRecord;
8
 use Filament\Support\Enums\MaxWidth;
10
 use Filament\Support\Enums\MaxWidth;
11
+use Illuminate\Database\Eloquent\Model;
9
 
12
 
10
 class CreateInvoice extends CreateRecord
13
 class CreateInvoice extends CreateRecord
11
 {
14
 {
15
+    use ManagesLineItems;
12
     use RedirectToListPage;
16
     use RedirectToListPage;
13
 
17
 
14
     protected static string $resource = InvoiceResource::class;
18
     protected static string $resource = InvoiceResource::class;
17
     {
21
     {
18
         return MaxWidth::Full;
22
         return MaxWidth::Full;
19
     }
23
     }
24
+
25
+    protected function handleRecordCreation(array $data): Model
26
+    {
27
+        /** @var Invoice $record */
28
+        $record = parent::handleRecordCreation($data);
29
+
30
+        $this->handleLineItems($record, collect($data['lineItems'] ?? []));
31
+
32
+        $totals = $this->updateInvoiceTotals($record, $data);
33
+
34
+        $record->updateQuietly($totals);
35
+
36
+        return $record;
37
+    }
20
 }
38
 }

+ 26
- 0
app/Filament/Company/Resources/Sales/InvoiceResource/Pages/EditInvoice.php 查看文件

2
 
2
 
3
 namespace App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
3
 namespace App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
4
 
4
 
5
+use App\Concerns\ManagesLineItems;
5
 use App\Concerns\RedirectToListPage;
6
 use App\Concerns\RedirectToListPage;
6
 use App\Filament\Company\Resources\Sales\InvoiceResource;
7
 use App\Filament\Company\Resources\Sales\InvoiceResource;
8
+use App\Models\Accounting\Invoice;
7
 use Filament\Actions;
9
 use Filament\Actions;
8
 use Filament\Resources\Pages\EditRecord;
10
 use Filament\Resources\Pages\EditRecord;
9
 use Filament\Support\Enums\MaxWidth;
11
 use Filament\Support\Enums\MaxWidth;
12
+use Illuminate\Database\Eloquent\Model;
10
 
13
 
11
 class EditInvoice extends EditRecord
14
 class EditInvoice extends EditRecord
12
 {
15
 {
16
+    use ManagesLineItems;
13
     use RedirectToListPage;
17
     use RedirectToListPage;
14
 
18
 
15
     protected static string $resource = InvoiceResource::class;
19
     protected static string $resource = InvoiceResource::class;
25
     {
29
     {
26
         return MaxWidth::Full;
30
         return MaxWidth::Full;
27
     }
31
     }
32
+
33
+    protected function handleRecordUpdate(Model $record, array $data): Model
34
+    {
35
+        /** @var Invoice $record */
36
+        $lineItems = collect($data['lineItems'] ?? []);
37
+
38
+        $this->deleteRemovedLineItems($record, $lineItems);
39
+
40
+        $this->handleLineItems($record, $lineItems);
41
+
42
+        $totals = $this->updateInvoiceTotals($record, $data);
43
+
44
+        $data = array_merge($data, $totals);
45
+
46
+        $record = parent::handleRecordUpdate($record, $data);
47
+
48
+        if ($record->approved_at && $record->approvalTransaction) {
49
+            $record->updateApprovalTransaction();
50
+        }
51
+
52
+        return $record;
53
+    }
28
 }
54
 }

+ 0
- 82
app/Models/Setting/Discount.php 查看文件

1
-<?php
2
-
3
-namespace App\Models\Setting;
4
-
5
-use App\Casts\RateCast;
6
-use App\Concerns\Blamable;
7
-use App\Concerns\CompanyOwned;
8
-use App\Concerns\HasDefault;
9
-use App\Concerns\SyncsWithCompanyDefaults;
10
-use App\Enums\Setting\DiscountComputation;
11
-use App\Enums\Setting\DiscountScope;
12
-use App\Enums\Setting\DiscountType;
13
-use App\Models\Accounting\Account;
14
-use Database\Factories\Setting\DiscountFactory;
15
-use Illuminate\Database\Eloquent\Factories\Factory;
16
-use Illuminate\Database\Eloquent\Factories\HasFactory;
17
-use Illuminate\Database\Eloquent\Model;
18
-use Illuminate\Database\Eloquent\Relations\BelongsTo;
19
-use Illuminate\Database\Eloquent\Relations\HasOne;
20
-use Illuminate\Database\Eloquent\Relations\MorphTo;
21
-
22
-class Discount extends Model
23
-{
24
-    use Blamable;
25
-    use CompanyOwned;
26
-    use HasDefault;
27
-    use HasFactory;
28
-    use SyncsWithCompanyDefaults;
29
-
30
-    protected $table = 'discounts';
31
-
32
-    protected $fillable = [
33
-        'company_id',
34
-        'account_id',
35
-        'rate',
36
-        'computation',
37
-        'type',
38
-        'scope',
39
-        'start_date',
40
-        'end_date',
41
-        'enabled',
42
-        'created_by',
43
-        'updated_by',
44
-    ];
45
-
46
-    protected $casts = [
47
-        'rate' => RateCast::class,
48
-        'computation' => DiscountComputation::class,
49
-        'type' => DiscountType::class,
50
-        'scope' => DiscountScope::class,
51
-        'start_date' => 'datetime',
52
-        'end_date' => 'datetime',
53
-        'enabled' => 'boolean',
54
-    ];
55
-
56
-    protected ?string $evaluatedDefault = 'type';
57
-
58
-    public function account(): BelongsTo
59
-    {
60
-        return $this->belongsTo(Account::class, 'account_id');
61
-    }
62
-
63
-    public function defaultSalesDiscount(): HasOne
64
-    {
65
-        return $this->hasOne(CompanyDefault::class, 'sales_discount_id');
66
-    }
67
-
68
-    public function defaultPurchaseDiscount(): HasOne
69
-    {
70
-        return $this->hasOne(CompanyDefault::class, 'purchase_discount_id');
71
-    }
72
-
73
-    public function adjustmentables(): MorphTo
74
-    {
75
-        return $this->morphTo();
76
-    }
77
-
78
-    protected static function newFactory(): Factory
79
-    {
80
-        return DiscountFactory::new();
81
-    }
82
-}

+ 0
- 78
app/Models/Setting/Tax.php 查看文件

1
-<?php
2
-
3
-namespace App\Models\Setting;
4
-
5
-use App\Casts\RateCast;
6
-use App\Concerns\Blamable;
7
-use App\Concerns\CompanyOwned;
8
-use App\Concerns\HasDefault;
9
-use App\Concerns\SyncsWithCompanyDefaults;
10
-use App\Enums\Setting\TaxComputation;
11
-use App\Enums\Setting\TaxScope;
12
-use App\Enums\Setting\TaxType;
13
-use App\Models\Accounting\Account;
14
-use Database\Factories\Setting\TaxFactory;
15
-use Illuminate\Database\Eloquent\Factories\Factory;
16
-use Illuminate\Database\Eloquent\Factories\HasFactory;
17
-use Illuminate\Database\Eloquent\Model;
18
-use Illuminate\Database\Eloquent\Relations\BelongsTo;
19
-use Illuminate\Database\Eloquent\Relations\HasOne;
20
-use Illuminate\Database\Eloquent\Relations\MorphTo;
21
-
22
-class Tax extends Model
23
-{
24
-    use Blamable;
25
-    use CompanyOwned;
26
-    use HasDefault;
27
-    use HasFactory;
28
-    use SyncsWithCompanyDefaults;
29
-
30
-    protected $table = 'taxes';
31
-
32
-    protected $fillable = [
33
-        'company_id',
34
-        'account_id',
35
-        'rate',
36
-        'computation',
37
-        'type',
38
-        'scope',
39
-        'enabled',
40
-        'created_by',
41
-        'updated_by',
42
-    ];
43
-
44
-    protected $casts = [
45
-        'rate' => RateCast::class,
46
-        'computation' => TaxComputation::class,
47
-        'type' => TaxType::class,
48
-        'scope' => TaxScope::class,
49
-        'enabled' => 'boolean',
50
-    ];
51
-
52
-    protected ?string $evaluatedDefault = 'type';
53
-
54
-    public function account(): BelongsTo
55
-    {
56
-        return $this->belongsTo(Account::class, 'account_id');
57
-    }
58
-
59
-    public function defaultSalesTax(): HasOne
60
-    {
61
-        return $this->hasOne(CompanyDefault::class, 'sales_tax_id');
62
-    }
63
-
64
-    public function defaultPurchaseTax(): HasOne
65
-    {
66
-        return $this->hasOne(CompanyDefault::class, 'purchase_tax_id');
67
-    }
68
-
69
-    public function adjustmentables(): MorphTo
70
-    {
71
-        return $this->morphTo();
72
-    }
73
-
74
-    protected static function newFactory(): Factory
75
-    {
76
-        return TaxFactory::new();
77
-    }
78
-}

+ 0
- 2
app/Providers/AuthServiceProvider.php 查看文件

36
     {
36
     {
37
         $models = [
37
         $models = [
38
             Setting\Currency::class,
38
             Setting\Currency::class,
39
-            Setting\Discount::class,
40
-            Setting\Tax::class,
41
             Banking\BankAccount::class,
39
             Banking\BankAccount::class,
42
         ];
40
         ];
43
 
41
 

Loading…
取消
儲存