Andrew Wallo 6 月之前
父節點
當前提交
502ffe7de4

+ 27
- 0
app/Filament/Company/Resources/Sales/EstimateResource/Pages/ViewEstimate.php 查看文件

5
 use App\Enums\Accounting\DocumentType;
5
 use App\Enums\Accounting\DocumentType;
6
 use App\Filament\Company\Resources\Sales\ClientResource;
6
 use App\Filament\Company\Resources\Sales\ClientResource;
7
 use App\Filament\Company\Resources\Sales\EstimateResource;
7
 use App\Filament\Company\Resources\Sales\EstimateResource;
8
+use App\Filament\Infolists\Components\BannerEntry;
8
 use App\Filament\Infolists\Components\DocumentPreview;
9
 use App\Filament\Infolists\Components\DocumentPreview;
9
 use App\Models\Accounting\Estimate;
10
 use App\Models\Accounting\Estimate;
10
 use Filament\Actions;
11
 use Filament\Actions;
17
 use Filament\Support\Enums\IconPosition;
18
 use Filament\Support\Enums\IconPosition;
18
 use Filament\Support\Enums\IconSize;
19
 use Filament\Support\Enums\IconSize;
19
 use Filament\Support\Enums\MaxWidth;
20
 use Filament\Support\Enums\MaxWidth;
21
+use Illuminate\Support\HtmlString;
20
 
22
 
21
 class ViewEstimate extends ViewRecord
23
 class ViewEstimate extends ViewRecord
22
 {
24
 {
63
     {
65
     {
64
         return $infolist
66
         return $infolist
65
             ->schema([
67
             ->schema([
68
+                BannerEntry::make('inactiveAdjustments')
69
+                    ->label('Inactive adjustments')
70
+                    ->warning()
71
+                    ->icon('heroicon-o-exclamation-triangle')
72
+                    ->visible(fn (Estimate $record) => $record->hasInactiveAdjustments() && $record->canBeApproved())
73
+                    ->columnSpanFull()
74
+                    ->description(function (Estimate $record) {
75
+                        $inactiveAdjustments = collect();
76
+
77
+                        foreach ($record->lineItems as $lineItem) {
78
+                            foreach ($lineItem->adjustments as $adjustment) {
79
+                                if ($adjustment->isInactive() && $inactiveAdjustments->doesntContain($adjustment->name)) {
80
+                                    $inactiveAdjustments->push($adjustment->name);
81
+                                }
82
+                            }
83
+                        }
84
+
85
+                        $adjustmentsList = $inactiveAdjustments->map(static function ($name) {
86
+                            return "<span class='font-medium'>{$name}</span>";
87
+                        })->join(', ');
88
+
89
+                        $output = "<p class='text-sm'>This estimate contains inactive adjustments that need to be addressed before approval: {$adjustmentsList}</p>";
90
+
91
+                        return new HtmlString($output);
92
+                    }),
66
                 Section::make('Estimate Details')
93
                 Section::make('Estimate Details')
67
                     ->columns(4)
94
                     ->columns(4)
68
                     ->schema([
95
                     ->schema([

+ 22
- 4
app/Models/Accounting/Estimate.php 查看文件

19
 use Filament\Actions\Action;
19
 use Filament\Actions\Action;
20
 use Filament\Actions\MountableAction;
20
 use Filament\Actions\MountableAction;
21
 use Filament\Actions\ReplicateAction;
21
 use Filament\Actions\ReplicateAction;
22
+use Filament\Notifications\Notification;
22
 use Illuminate\Database\Eloquent\Attributes\CollectedBy;
23
 use Illuminate\Database\Eloquent\Attributes\CollectedBy;
23
 use Illuminate\Database\Eloquent\Attributes\ObservedBy;
24
 use Illuminate\Database\Eloquent\Attributes\ObservedBy;
24
 use Illuminate\Database\Eloquent\Builder;
25
 use Illuminate\Database\Eloquent\Builder;
27
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
28
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
28
 use Illuminate\Database\Eloquent\Relations\HasOne;
29
 use Illuminate\Database\Eloquent\Relations\HasOne;
29
 use Illuminate\Support\Carbon;
30
 use Illuminate\Support\Carbon;
31
+use Livewire\Component;
30
 
32
 
31
 #[CollectedBy(DocumentCollection::class)]
33
 #[CollectedBy(DocumentCollection::class)]
32
 #[ObservedBy(EstimateObserver::class)]
34
 #[ObservedBy(EstimateObserver::class)]
266
             ->visible(function (self $record) {
268
             ->visible(function (self $record) {
267
                 return $record->canBeApproved();
269
                 return $record->canBeApproved();
268
             })
270
             })
271
+            ->requiresConfirmation()
269
             ->databaseTransaction()
272
             ->databaseTransaction()
270
             ->successNotificationTitle('Estimate approved')
273
             ->successNotificationTitle('Estimate approved')
271
-            ->action(function (self $record, MountableAction $action) {
272
-                $record->approveDraft();
273
-
274
-                $action->success();
274
+            ->action(function (self $record, MountableAction $action, Component $livewire) {
275
+                if ($record->hasInactiveAdjustments()) {
276
+                    $isViewPage = $livewire instanceof EstimateResource\Pages\ViewEstimate;
277
+
278
+                    if (! $isViewPage) {
279
+                        redirect(EstimateResource\Pages\ViewEstimate::getUrl(['record' => $record->id]));
280
+                    } else {
281
+                        Notification::make()
282
+                            ->warning()
283
+                            ->title('Cannot approve estimate')
284
+                            ->body('This estimate has inactive adjustments that must be addressed first.')
285
+                            ->persistent()
286
+                            ->send();
287
+                    }
288
+                } else {
289
+                    $record->approveDraft();
290
+
291
+                    $action->success();
292
+                }
275
             });
293
             });
276
     }
294
     }
277
 
295
 

Loading…
取消
儲存