Andrew Wallo vor 10 Monaten
Ursprung
Commit
1034a171d1

+ 52
- 10
app/Filament/Company/Resources/Sales/InvoiceResource.php Datei anzeigen

@@ -3,6 +3,7 @@
3 3
 namespace App\Filament\Company\Resources\Sales;
4 4
 
5 5
 use App\Collections\Accounting\InvoiceCollection;
6
+use App\Enums\Accounting\AdjustmentComputation;
6 7
 use App\Enums\Accounting\InvoiceStatus;
7 8
 use App\Enums\Accounting\PaymentMethod;
8 9
 use App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
@@ -128,6 +129,28 @@ class InvoiceResource extends Resource
128 129
                                     ->minDate(static function (Forms\Get $get) {
129 130
                                         return $get('date') ?? now();
130 131
                                     }),
132
+                                Forms\Components\Select::make('discount_method')
133
+                                    ->label('Discount Method')
134
+                                    ->options([
135
+                                        'line_items' => 'Per Line Item Discounts',
136
+                                        'invoice' => 'Invoice Level Discount',
137
+                                    ])
138
+                                    ->selectablePlaceholder(false)
139
+                                    ->default('line_items')
140
+                                    ->live(),
141
+                                Forms\Components\Grid::make(2)
142
+                                    ->schema([
143
+                                        Forms\Components\Select::make('discount_computation')
144
+                                            ->label('Discount Computation')
145
+                                            ->options(AdjustmentComputation::class)
146
+                                            ->default(AdjustmentComputation::Percentage)
147
+                                            ->selectablePlaceholder(false)
148
+                                            ->live(),
149
+                                        Forms\Components\TextInput::make('discount_rate')
150
+                                            ->label('Discount Rate')
151
+                                            ->live()
152
+                                            ->rate(static fn (Forms\Get $get) => $get('discount_computation')),
153
+                                    ])->visible(fn (Forms\Get $get) => $get('discount_method') === 'invoice'),
131 154
                             ])->grow(true),
132 155
                         ])->from('md'),
133 156
                         TableRepeater::make('lineItems')
@@ -238,15 +261,25 @@ class InvoiceResource extends Resource
238 261
                                     $invoice->updateApprovalTransaction();
239 262
                                 }
240 263
                             })
241
-                            ->headers([
242
-                                Header::make('Items')->width('15%'),
243
-                                Header::make('Description')->width('25%'),
244
-                                Header::make('Quantity')->width('10%'),
245
-                                Header::make('Price')->width('10%'),
246
-                                Header::make('Taxes')->width('15%'),
247
-                                Header::make('Discounts')->width('15%'),
248
-                                Header::make('Amount')->width('10%')->align('right'),
249
-                            ])
264
+                            ->headers(function (Forms\Get $get) {
265
+                                $hasDiscounts = $get('discount_method') === 'line_items';
266
+
267
+                                $headers = [
268
+                                    Header::make('Items')->width($hasDiscounts ? '15%' : '20%'),
269
+                                    Header::make('Description')->width($hasDiscounts ? '25%' : '30%'),  // Increase when no discounts
270
+                                    Header::make('Quantity')->width('10%'),
271
+                                    Header::make('Price')->width('10%'),
272
+                                    Header::make('Taxes')->width($hasDiscounts ? '15%' : '20%'),       // Increase when no discounts
273
+                                ];
274
+
275
+                                if ($hasDiscounts) {
276
+                                    $headers[] = Header::make('Discounts')->width('15%');
277
+                                }
278
+
279
+                                $headers[] = Header::make('Amount')->width('10%')->align('right');
280
+
281
+                                return $headers;
282
+                            })
250 283
                             ->schema([
251 284
                                 Forms\Components\Select::make('offering_id')
252 285
                                     ->relationship('sellableOffering', 'name')
@@ -262,7 +295,11 @@ class InvoiceResource extends Resource
262 295
                                             $set('description', $offeringRecord->description);
263 296
                                             $set('unit_price', $offeringRecord->price);
264 297
                                             $set('salesTaxes', $offeringRecord->salesTaxes->pluck('id')->toArray());
265
-                                            $set('salesDiscounts', $offeringRecord->salesDiscounts->pluck('id')->toArray());
298
+
299
+                                            $discountMethod = $get('../../discount_method');
300
+                                            if ($discountMethod === 'line_items') {
301
+                                                $set('salesDiscounts', $offeringRecord->salesDiscounts->pluck('id')->toArray());
302
+                                            }
266 303
                                         }
267 304
                                     }),
268 305
                                 Forms\Components\TextInput::make('description'),
@@ -287,6 +324,11 @@ class InvoiceResource extends Resource
287 324
                                     ->preload()
288 325
                                     ->multiple()
289 326
                                     ->live()
327
+                                    ->hidden(function (Forms\Get $get) {
328
+                                        $discountMethod = $get('../../discount_method');
329
+
330
+                                        return $discountMethod === 'invoice';
331
+                                    })
290 332
                                     ->searchable(),
291 333
                                 Forms\Components\Placeholder::make('total')
292 334
                                     ->hiddenLabel()

+ 6
- 0
app/Models/Accounting/Invoice.php Datei anzeigen

@@ -3,9 +3,11 @@
3 3
 namespace App\Models\Accounting;
4 4
 
5 5
 use App\Casts\MoneyCast;
6
+use App\Casts\RateCast;
6 7
 use App\Collections\Accounting\InvoiceCollection;
7 8
 use App\Concerns\Blamable;
8 9
 use App\Concerns\CompanyOwned;
10
+use App\Enums\Accounting\AdjustmentComputation;
9 11
 use App\Enums\Accounting\InvoiceStatus;
10 12
 use App\Enums\Accounting\JournalEntryType;
11 13
 use App\Enums\Accounting\TransactionType;
@@ -51,6 +53,8 @@ class Invoice extends Model
51 53
         'last_sent',
52 54
         'status',
53 55
         'currency_code',
56
+        'discount_computation',
57
+        'discount_rate',
54 58
         'subtotal',
55 59
         'tax_total',
56 60
         'discount_total',
@@ -69,6 +73,8 @@ class Invoice extends Model
69 73
         'paid_at' => 'datetime',
70 74
         'last_sent' => 'datetime',
71 75
         'status' => InvoiceStatus::class,
76
+        'discount_computation' => AdjustmentComputation::class,
77
+        'discount_rate' => RateCast::class,
72 78
         'subtotal' => MoneyCast::class,
73 79
         'tax_total' => MoneyCast::class,
74 80
         'discount_total' => MoneyCast::class,

+ 1
- 2
app/Providers/MacroServiceProvider.php Datei anzeigen

@@ -19,7 +19,6 @@ use Filament\Infolists\Components\TextEntry;
19 19
 use Filament\Tables\Columns\TextColumn;
20 20
 use Illuminate\Support\Carbon;
21 21
 use Illuminate\Support\ServiceProvider;
22
-use Illuminate\Support\Str;
23 22
 
24 23
 class MacroServiceProvider extends ServiceProvider
25 24
 {
@@ -104,7 +103,7 @@ class MacroServiceProvider extends ServiceProvider
104 103
         });
105 104
 
106 105
         TextInput::macro('rate', function (string | Closure | null $computation = null): static {
107
-            $this->extraAttributes(['wire:key' => Str::random()])
106
+            $this
108 107
                 ->prefix(static function (TextInput $component) use ($computation) {
109 108
                     $computation = $component->evaluate($computation);
110 109
 

+ 25
- 10
app/View/Models/InvoiceTotalViewModel.php Datei anzeigen

@@ -2,6 +2,7 @@
2 2
 
3 3
 namespace App\View\Models;
4 4
 
5
+use App\Enums\Accounting\AdjustmentComputation;
5 6
 use App\Models\Accounting\Adjustment;
6 7
 use App\Models\Accounting\Invoice;
7 8
 use App\Utilities\Currency\CurrencyConverter;
@@ -37,18 +38,32 @@ class InvoiceTotalViewModel
37 38
             return $carry + $taxAmount;
38 39
         }, 0);
39 40
 
40
-        $discountTotal = $lineItems->reduce(function ($carry, $item) {
41
-            $quantity = max((float) ($item['quantity'] ?? 0), 0);
42
-            $unitPrice = max((float) ($item['unit_price'] ?? 0), 0);
43
-            $salesDiscounts = $item['salesDiscounts'] ?? [];
44
-            $lineTotal = $quantity * $unitPrice;
41
+        // Calculate discount based on method
42
+        $discountMethod = $this->data['discount_method'] ?? 'line_items';
45 43
 
46
-            $discountAmount = Adjustment::whereIn('id', $salesDiscounts)
47
-                ->pluck('rate')
48
-                ->sum(fn ($rate) => $lineTotal * ($rate / 100));
44
+        if ($discountMethod === 'line_items') {
45
+            $discountTotal = $lineItems->reduce(function ($carry, $item) {
46
+                $quantity = max((float) ($item['quantity'] ?? 0), 0);
47
+                $unitPrice = max((float) ($item['unit_price'] ?? 0), 0);
48
+                $salesDiscounts = $item['salesDiscounts'] ?? [];
49
+                $lineTotal = $quantity * $unitPrice;
49 50
 
50
-            return $carry + $discountAmount;
51
-        }, 0);
51
+                $discountAmount = Adjustment::whereIn('id', $salesDiscounts)
52
+                    ->pluck('rate')
53
+                    ->sum(fn ($rate) => $lineTotal * ($rate / 100));
54
+
55
+                return $carry + $discountAmount;
56
+            }, 0);
57
+        } else {
58
+            $discountComputation = $this->data['discount_computation'] ?? AdjustmentComputation::Percentage;
59
+            $discountRate = (float) ($this->data['discount_rate'] ?? 0);
60
+
61
+            if ($discountComputation === AdjustmentComputation::Percentage) {
62
+                $discountTotal = $subtotal * ($discountRate / 100);
63
+            } else {
64
+                $discountTotal = $discountRate;
65
+            }
66
+        }
52 67
 
53 68
         $grandTotal = $subtotal + ($taxTotal - $discountTotal);
54 69
 

+ 47
- 47
composer.lock Datei anzeigen

@@ -497,16 +497,16 @@
497 497
         },
498 498
         {
499 499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.334.1",
500
+            "version": "3.334.2",
501 501
             "source": {
502 502
                 "type": "git",
503 503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "3938b3467f64a30fed7ee1762a6785f808a5ae4d"
504
+                "reference": "b19afc076bb1cc2617bdef76efd41587596109e7"
505 505
             },
506 506
             "dist": {
507 507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3938b3467f64a30fed7ee1762a6785f808a5ae4d",
509
-                "reference": "3938b3467f64a30fed7ee1762a6785f808a5ae4d",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b19afc076bb1cc2617bdef76efd41587596109e7",
509
+                "reference": "b19afc076bb1cc2617bdef76efd41587596109e7",
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.334.1"
592
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.334.2"
593 593
             },
594
-            "time": "2024-12-05T01:17:41+00:00"
594
+            "time": "2024-12-09T19:30:23+00:00"
595 595
         },
596 596
         {
597 597
             "name": "aws/aws-sdk-php-laravel",
@@ -695,17 +695,17 @@
695 695
             },
696 696
             "type": "library",
697 697
             "extra": {
698
-                "branch-alias": {
699
-                    "dev-master": "1.0-dev"
700
-                },
701 698
                 "laravel": {
702
-                    "providers": [
703
-                        "Barryvdh\\Snappy\\ServiceProvider"
704
-                    ],
705 699
                     "aliases": {
706 700
                         "PDF": "Barryvdh\\Snappy\\Facades\\SnappyPdf",
707 701
                         "SnappyImage": "Barryvdh\\Snappy\\Facades\\SnappyImage"
708
-                    }
702
+                    },
703
+                    "providers": [
704
+                        "Barryvdh\\Snappy\\ServiceProvider"
705
+                    ]
706
+                },
707
+                "branch-alias": {
708
+                    "dev-master": "1.0-dev"
709 709
                 }
710 710
             },
711 711
             "autoload": {
@@ -6301,16 +6301,16 @@
6301 6301
         },
6302 6302
         {
6303 6303
             "name": "spatie/color",
6304
-            "version": "1.6.1",
6304
+            "version": "1.6.2",
6305 6305
             "source": {
6306 6306
                 "type": "git",
6307 6307
                 "url": "https://github.com/spatie/color.git",
6308
-                "reference": "4c540ffbef68a3df3d209718ae06deaab081e708"
6308
+                "reference": "b4fac074a9e5999dcca12cbfab0f7c73e2684d6d"
6309 6309
             },
6310 6310
             "dist": {
6311 6311
                 "type": "zip",
6312
-                "url": "https://api.github.com/repos/spatie/color/zipball/4c540ffbef68a3df3d209718ae06deaab081e708",
6313
-                "reference": "4c540ffbef68a3df3d209718ae06deaab081e708",
6312
+                "url": "https://api.github.com/repos/spatie/color/zipball/b4fac074a9e5999dcca12cbfab0f7c73e2684d6d",
6313
+                "reference": "b4fac074a9e5999dcca12cbfab0f7c73e2684d6d",
6314 6314
                 "shasum": ""
6315 6315
             },
6316 6316
             "require": {
@@ -6348,7 +6348,7 @@
6348 6348
             ],
6349 6349
             "support": {
6350 6350
                 "issues": "https://github.com/spatie/color/issues",
6351
-                "source": "https://github.com/spatie/color/tree/1.6.1"
6351
+                "source": "https://github.com/spatie/color/tree/1.6.2"
6352 6352
             },
6353 6353
             "funding": [
6354 6354
                 {
@@ -6356,7 +6356,7 @@
6356 6356
                     "type": "github"
6357 6357
                 }
6358 6358
             ],
6359
-            "time": "2024-11-18T15:00:47+00:00"
6359
+            "time": "2024-12-09T16:20:38+00:00"
6360 6360
         },
6361 6361
         {
6362 6362
             "name": "spatie/invade",
@@ -6419,16 +6419,16 @@
6419 6419
         },
6420 6420
         {
6421 6421
             "name": "spatie/laravel-package-tools",
6422
-            "version": "1.16.6",
6422
+            "version": "1.17.0",
6423 6423
             "source": {
6424 6424
                 "type": "git",
6425 6425
                 "url": "https://github.com/spatie/laravel-package-tools.git",
6426
-                "reference": "1f26942dc1e5c49eacfced34fdbc29ed234bd7b3"
6426
+                "reference": "9ab30fd24f677e5aa370ea4cf6b41c517d16cf85"
6427 6427
             },
6428 6428
             "dist": {
6429 6429
                 "type": "zip",
6430
-                "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/1f26942dc1e5c49eacfced34fdbc29ed234bd7b3",
6431
-                "reference": "1f26942dc1e5c49eacfced34fdbc29ed234bd7b3",
6430
+                "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/9ab30fd24f677e5aa370ea4cf6b41c517d16cf85",
6431
+                "reference": "9ab30fd24f677e5aa370ea4cf6b41c517d16cf85",
6432 6432
                 "shasum": ""
6433 6433
             },
6434 6434
             "require": {
@@ -6437,10 +6437,10 @@
6437 6437
             },
6438 6438
             "require-dev": {
6439 6439
                 "mockery/mockery": "^1.5",
6440
-                "orchestra/testbench": "^7.7|^8.0",
6441
-                "pestphp/pest": "^1.22",
6442
-                "phpunit/phpunit": "^9.5.24",
6443
-                "spatie/pest-plugin-test-time": "^1.1"
6440
+                "orchestra/testbench": "^7.7|^8.0|^9.0",
6441
+                "pestphp/pest": "^1.22|^2",
6442
+                "phpunit/phpunit": "^9.5.24|^10.5",
6443
+                "spatie/pest-plugin-test-time": "^1.1|^2.2"
6444 6444
             },
6445 6445
             "type": "library",
6446 6446
             "autoload": {
@@ -6467,7 +6467,7 @@
6467 6467
             ],
6468 6468
             "support": {
6469 6469
                 "issues": "https://github.com/spatie/laravel-package-tools/issues",
6470
-                "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.6"
6470
+                "source": "https://github.com/spatie/laravel-package-tools/tree/1.17.0"
6471 6471
             },
6472 6472
             "funding": [
6473 6473
                 {
@@ -6475,7 +6475,7 @@
6475 6475
                     "type": "github"
6476 6476
                 }
6477 6477
             ],
6478
-            "time": "2024-11-18T15:02:02+00:00"
6478
+            "time": "2024-12-09T16:29:14+00:00"
6479 6479
         },
6480 6480
         {
6481 6481
             "name": "squirephp/model",
@@ -7714,8 +7714,8 @@
7714 7714
             "type": "library",
7715 7715
             "extra": {
7716 7716
                 "thanks": {
7717
-                    "name": "symfony/polyfill",
7718
-                    "url": "https://github.com/symfony/polyfill"
7717
+                    "url": "https://github.com/symfony/polyfill",
7718
+                    "name": "symfony/polyfill"
7719 7719
                 }
7720 7720
             },
7721 7721
             "autoload": {
@@ -7790,8 +7790,8 @@
7790 7790
             "type": "library",
7791 7791
             "extra": {
7792 7792
                 "thanks": {
7793
-                    "name": "symfony/polyfill",
7794
-                    "url": "https://github.com/symfony/polyfill"
7793
+                    "url": "https://github.com/symfony/polyfill",
7794
+                    "name": "symfony/polyfill"
7795 7795
                 }
7796 7796
             },
7797 7797
             "autoload": {
@@ -7951,8 +7951,8 @@
7951 7951
             "type": "library",
7952 7952
             "extra": {
7953 7953
                 "thanks": {
7954
-                    "name": "symfony/polyfill",
7955
-                    "url": "https://github.com/symfony/polyfill"
7954
+                    "url": "https://github.com/symfony/polyfill",
7955
+                    "name": "symfony/polyfill"
7956 7956
                 }
7957 7957
             },
7958 7958
             "autoload": {
@@ -8109,8 +8109,8 @@
8109 8109
             "type": "library",
8110 8110
             "extra": {
8111 8111
                 "thanks": {
8112
-                    "name": "symfony/polyfill",
8113
-                    "url": "https://github.com/symfony/polyfill"
8112
+                    "url": "https://github.com/symfony/polyfill",
8113
+                    "name": "symfony/polyfill"
8114 8114
                 }
8115 8115
             },
8116 8116
             "autoload": {
@@ -8189,8 +8189,8 @@
8189 8189
             "type": "library",
8190 8190
             "extra": {
8191 8191
                 "thanks": {
8192
-                    "name": "symfony/polyfill",
8193
-                    "url": "https://github.com/symfony/polyfill"
8192
+                    "url": "https://github.com/symfony/polyfill",
8193
+                    "name": "symfony/polyfill"
8194 8194
                 }
8195 8195
             },
8196 8196
             "autoload": {
@@ -8271,8 +8271,8 @@
8271 8271
             "type": "library",
8272 8272
             "extra": {
8273 8273
                 "thanks": {
8274
-                    "name": "symfony/polyfill",
8275
-                    "url": "https://github.com/symfony/polyfill"
8274
+                    "url": "https://github.com/symfony/polyfill",
8275
+                    "name": "symfony/polyfill"
8276 8276
                 }
8277 8277
             },
8278 8278
             "autoload": {
@@ -12769,16 +12769,16 @@
12769 12769
         },
12770 12770
         {
12771 12771
             "name": "spatie/ray",
12772
-            "version": "1.41.3",
12772
+            "version": "1.41.4",
12773 12773
             "source": {
12774 12774
                 "type": "git",
12775 12775
                 "url": "https://github.com/spatie/ray.git",
12776
-                "reference": "e2ecbc17a493dab635f3cf026858b46f0ccbb053"
12776
+                "reference": "c5dbda0548c1881b30549ccc0b6d485f7471aaa5"
12777 12777
             },
12778 12778
             "dist": {
12779 12779
                 "type": "zip",
12780
-                "url": "https://api.github.com/repos/spatie/ray/zipball/e2ecbc17a493dab635f3cf026858b46f0ccbb053",
12781
-                "reference": "e2ecbc17a493dab635f3cf026858b46f0ccbb053",
12780
+                "url": "https://api.github.com/repos/spatie/ray/zipball/c5dbda0548c1881b30549ccc0b6d485f7471aaa5",
12781
+                "reference": "c5dbda0548c1881b30549ccc0b6d485f7471aaa5",
12782 12782
                 "shasum": ""
12783 12783
             },
12784 12784
             "require": {
@@ -12838,7 +12838,7 @@
12838 12838
             ],
12839 12839
             "support": {
12840 12840
                 "issues": "https://github.com/spatie/ray/issues",
12841
-                "source": "https://github.com/spatie/ray/tree/1.41.3"
12841
+                "source": "https://github.com/spatie/ray/tree/1.41.4"
12842 12842
             },
12843 12843
             "funding": [
12844 12844
                 {
@@ -12850,7 +12850,7 @@
12850 12850
                     "type": "other"
12851 12851
                 }
12852 12852
             ],
12853
-            "time": "2024-12-02T12:33:18+00:00"
12853
+            "time": "2024-12-09T11:32:15+00:00"
12854 12854
         },
12855 12855
         {
12856 12856
             "name": "symfony/polyfill-iconv",

+ 2
- 0
database/migrations/2024_11_27_223015_create_invoices_table.php Datei anzeigen

@@ -27,6 +27,8 @@ return new class extends Migration
27 27
             $table->timestamp('last_sent')->nullable();
28 28
             $table->string('status')->default('draft');
29 29
             $table->string('currency_code')->nullable();
30
+            $table->string('discount_computation')->nullable();
31
+            $table->integer('discount_rate')->default(0);
30 32
             $table->integer('subtotal')->default(0);
31 33
             $table->integer('tax_total')->default(0);
32 34
             $table->integer('discount_total')->default(0);

+ 3
- 3
package-lock.json Datei anzeigen

@@ -1218,9 +1218,9 @@
1218 1218
             "license": "MIT"
1219 1219
         },
1220 1220
         "node_modules/electron-to-chromium": {
1221
-            "version": "1.5.71",
1222
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.71.tgz",
1223
-            "integrity": "sha512-dB68l59BI75W1BUGVTAEJy45CEVuEGy9qPVVQ8pnHyHMn36PLPPoE1mjLH+lo9rKulO3HC2OhbACI/8tCqJBcA==",
1221
+            "version": "1.5.72",
1222
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz",
1223
+            "integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==",
1224 1224
             "dev": true,
1225 1225
             "license": "ISC"
1226 1226
         },

Laden…
Abbrechen
Speichern