|
@@ -22,6 +22,8 @@ use App\Utilities\Currency\CurrencyConverter;
|
22
|
22
|
use Filament\Actions\Action;
|
23
|
23
|
use Filament\Actions\MountableAction;
|
24
|
24
|
use Filament\Actions\ReplicateAction;
|
|
25
|
+use Filament\Actions\StaticAction;
|
|
26
|
+use Filament\Support\Enums\Alignment;
|
25
|
27
|
use Illuminate\Database\Eloquent\Attributes\CollectedBy;
|
26
|
28
|
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
27
|
29
|
use Illuminate\Database\Eloquent\Builder;
|
|
@@ -31,6 +33,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
31
|
33
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
32
|
34
|
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
33
|
35
|
use Illuminate\Support\Carbon;
|
|
36
|
+use Illuminate\Support\HtmlString;
|
34
|
37
|
|
35
|
38
|
#[CollectedBy(DocumentCollection::class)]
|
36
|
39
|
#[ObservedBy(InvoiceObserver::class)]
|
|
@@ -458,14 +461,63 @@ class Invoice extends Document
|
458
|
461
|
return CurrencyConverter::convertCentsToFormatSimple($convertedCents);
|
459
|
462
|
}
|
460
|
463
|
|
|
464
|
+ public function hasInactiveAdjustments(): bool
|
|
465
|
+ {
|
|
466
|
+ return $this->lineItems->contains(function (DocumentLineItem $lineItem) {
|
|
467
|
+ return $lineItem->adjustments->contains(function (Adjustment $adjustment) {
|
|
468
|
+ return $adjustment->isInactive();
|
|
469
|
+ });
|
|
470
|
+ });
|
|
471
|
+ }
|
|
472
|
+
|
|
473
|
+ // TODO: Potentially handle this another way
|
|
474
|
+ public static function getBlockedApproveAction(string $action = Action::class): MountableAction
|
|
475
|
+ {
|
|
476
|
+ return $action::make('blockedApprove')
|
|
477
|
+ ->label('Approve')
|
|
478
|
+ ->icon('heroicon-m-check-circle')
|
|
479
|
+ ->visible(fn (self $record) => $record->canBeApproved() && $record->hasInactiveAdjustments())
|
|
480
|
+ ->requiresConfirmation()
|
|
481
|
+ ->modalAlignment(Alignment::Start)
|
|
482
|
+ ->modalIconColor('danger')
|
|
483
|
+ ->modalDescription(function (self $record) {
|
|
484
|
+ $inactiveAdjustments = collect();
|
|
485
|
+
|
|
486
|
+ foreach ($record->lineItems as $lineItem) {
|
|
487
|
+ foreach ($lineItem->adjustments as $adjustment) {
|
|
488
|
+ if ($adjustment->isInactive() && $inactiveAdjustments->doesntContain($adjustment->name)) {
|
|
489
|
+ $inactiveAdjustments->push($adjustment->name);
|
|
490
|
+ }
|
|
491
|
+ }
|
|
492
|
+ }
|
|
493
|
+
|
|
494
|
+ $output = "<p class='text-sm mb-4'>This invoice contains inactive adjustments that need to be addressed before approval:</p>";
|
|
495
|
+ $output .= "<ul role='list' class='list-disc list-inside space-y-1 text-sm'>";
|
|
496
|
+
|
|
497
|
+ foreach ($inactiveAdjustments as $name) {
|
|
498
|
+ $output .= "<li class='py-1'><span class='font-medium'>{$name}</span></li>";
|
|
499
|
+ }
|
|
500
|
+
|
|
501
|
+ $output .= '</ul>';
|
|
502
|
+ $output .= "<p class='text-sm mt-4'>Please update these adjustments before approving the invoice.</p>";
|
|
503
|
+
|
|
504
|
+ return new HtmlString($output);
|
|
505
|
+ })
|
|
506
|
+ ->modalSubmitAction(function (StaticAction $action, self $record) {
|
|
507
|
+ $action->label('Edit Invoice')
|
|
508
|
+ ->url(InvoiceResource\Pages\EditInvoice::getUrl(['record' => $record->id]));
|
|
509
|
+ });
|
|
510
|
+ }
|
|
511
|
+
|
461
|
512
|
public static function getApproveDraftAction(string $action = Action::class): MountableAction
|
462
|
513
|
{
|
463
|
514
|
return $action::make('approveDraft')
|
464
|
515
|
->label('Approve')
|
465
|
516
|
->icon('heroicon-m-check-circle')
|
466
|
517
|
->visible(function (self $record) {
|
467
|
|
- return $record->canBeApproved();
|
|
518
|
+ return $record->canBeApproved() && ! $record->hasInactiveAdjustments();
|
468
|
519
|
})
|
|
520
|
+ ->requiresConfirmation()
|
469
|
521
|
->databaseTransaction()
|
470
|
522
|
->successNotificationTitle('Invoice approved')
|
471
|
523
|
->action(function (self $record, MountableAction $action) {
|