Andrew Wallo 4 月之前
父節點
當前提交
7e384b1a48

+ 17
- 0
app/Enums/Accounting/BillStatus.php 查看文件

36
             self::Open,
36
             self::Open,
37
         ];
37
         ];
38
     }
38
     }
39
+
40
+    public static function unpaidStatuses(): array
41
+    {
42
+        return [
43
+            self::Open,
44
+            self::Partial,
45
+            self::Overdue,
46
+        ];
47
+    }
48
+
49
+    public static function getUnpaidOptions(): array
50
+    {
51
+        return collect(self::cases())
52
+            ->filter(fn (self $case) => in_array($case, self::unpaidStatuses()))
53
+            ->mapWithKeys(fn (self $case) => [$case->value => $case->getLabel()])
54
+            ->toArray();
55
+    }
39
 }
56
 }

+ 29
- 31
app/Filament/Company/Resources/Purchases/BillResource/Pages/PayBills.php 查看文件

8
 use App\Models\Accounting\Bill;
8
 use App\Models\Accounting\Bill;
9
 use App\Models\Accounting\Transaction;
9
 use App\Models\Accounting\Transaction;
10
 use App\Models\Banking\BankAccount;
10
 use App\Models\Banking\BankAccount;
11
+use App\Utilities\Currency\CurrencyAccessor;
11
 use App\Utilities\Currency\CurrencyConverter;
12
 use App\Utilities\Currency\CurrencyConverter;
12
 use Filament\Actions;
13
 use Filament\Actions;
13
 use Filament\Forms;
14
 use Filament\Forms;
18
 use Filament\Tables;
19
 use Filament\Tables;
19
 use Filament\Tables\Columns\TextColumn;
20
 use Filament\Tables\Columns\TextColumn;
20
 use Filament\Tables\Columns\TextInputColumn;
21
 use Filament\Tables\Columns\TextInputColumn;
22
+use Filament\Tables\Enums\FiltersLayout;
21
 use Filament\Tables\Table;
23
 use Filament\Tables\Table;
24
+use Illuminate\Contracts\Support\Htmlable;
22
 use Illuminate\Database\Eloquent\Collection;
25
 use Illuminate\Database\Eloquent\Collection;
23
 use Livewire\Attributes\Computed;
26
 use Livewire\Attributes\Computed;
24
 
27
 
28
+/**
29
+ * @property Form $form
30
+ */
25
 class PayBills extends ListRecords
31
 class PayBills extends ListRecords
26
 {
32
 {
27
     protected static string $resource = BillResource::class;
33
     protected static string $resource = BillResource::class;
28
 
34
 
29
-    protected static ?string $title = 'Pay Bills';
30
-
31
-    protected static ?string $navigationLabel = 'Pay Bills';
32
-
33
     protected static string $view = 'filament.company.resources.purchases.bill-resource.pages.pay-bills';
35
     protected static string $view = 'filament.company.resources.purchases.bill-resource.pages.pay-bills';
34
 
36
 
35
     public array $paymentAmounts = [];
37
     public array $paymentAmounts = [];
36
 
38
 
37
     public ?array $data = [];
39
     public ?array $data = [];
38
 
40
 
39
-    public function getTitle(): string
41
+    public function getBreadcrumb(): ?string
40
     {
42
     {
41
-        return 'Pay Bills';
43
+        return 'Pay';
42
     }
44
     }
43
 
45
 
44
-    public function getBreadcrumb(): string
46
+    public function getTitle(): string | Htmlable
45
     {
47
     {
46
         return 'Pay Bills';
48
         return 'Pay Bills';
47
     }
49
     }
53
         $this->form->fill([
55
         $this->form->fill([
54
             'bank_account_id' => BankAccount::where('enabled', true)->first()?->id,
56
             'bank_account_id' => BankAccount::where('enabled', true)->first()?->id,
55
             'payment_date' => now(),
57
             'payment_date' => now(),
56
-            'payment_method' => PaymentMethod::Check->value,
58
+            'payment_method' => PaymentMethod::Check,
57
         ]);
59
         ]);
60
+
61
+        $this->reset('tableFilters');
58
     }
62
     }
59
 
63
 
60
     protected function getHeaderActions(): array
64
     protected function getHeaderActions(): array
157
             ->query(
161
             ->query(
158
                 Bill::query()
162
                 Bill::query()
159
                     ->with(['vendor'])
163
                     ->with(['vendor'])
160
-                    ->whereIn('status', [
161
-                        BillStatus::Open,
162
-                        BillStatus::Partial,
163
-                        BillStatus::Overdue,
164
-                    ])
164
+                    ->unpaid()
165
             )
165
             )
166
             ->selectable()
166
             ->selectable()
167
             ->columns([
167
             ->columns([
168
                 TextColumn::make('vendor.name')
168
                 TextColumn::make('vendor.name')
169
                     ->label('Vendor')
169
                     ->label('Vendor')
170
-                    ->searchable()
171
                     ->sortable(),
170
                     ->sortable(),
172
                 TextColumn::make('bill_number')
171
                 TextColumn::make('bill_number')
173
                     ->label('Bill #')
172
                     ->label('Bill #')
174
-                    ->searchable()
175
                     ->sortable(),
173
                     ->sortable(),
176
                 TextColumn::make('due_date')
174
                 TextColumn::make('due_date')
177
                     ->label('Due Date')
175
                     ->label('Due Date')
179
                     ->sortable(),
177
                     ->sortable(),
180
                 TextColumn::make('amount_due')
178
                 TextColumn::make('amount_due')
181
                     ->label('Amount Due')
179
                     ->label('Amount Due')
182
-                    ->currencyWithConversion(fn (Bill $record) => $record->currency_code)
180
+                    ->currency(static fn (Bill $record) => $record->currency_code)
183
                     ->alignEnd()
181
                     ->alignEnd()
184
                     ->sortable(),
182
                     ->sortable(),
185
                 TextInputColumn::make('payment_amount')
183
                 TextInputColumn::make('payment_amount')
193
                             return '0.00';
191
                             return '0.00';
194
                         }
192
                         }
195
 
193
 
196
-                        $paymentCents = CurrencyConverter::convertToCents($state, $record->currency_code);
194
+                        $paymentCents = CurrencyConverter::convertToCents($state, 'USD');
197
 
195
 
198
                         // Validate payment doesn't exceed amount due
196
                         // Validate payment doesn't exceed amount due
199
                         if ($paymentCents > $record->amount_due) {
197
                         if ($paymentCents > $record->amount_due) {
203
                                 ->warning()
201
                                 ->warning()
204
                                 ->send();
202
                                 ->send();
205
 
203
 
206
-                            $maxAmount = CurrencyConverter::convertCentsToFormatSimple($record->amount_due, $record->currency_code);
204
+                            $maxAmount = CurrencyConverter::convertCentsToFormatSimple($record->amount_due, 'USD');
207
                             $this->paymentAmounts[$record->id] = $record->amount_due;
205
                             $this->paymentAmounts[$record->id] = $record->amount_due;
208
 
206
 
209
                             return $maxAmount;
207
                             return $maxAmount;
216
                     ->getStateUsing(function (Bill $record) {
214
                     ->getStateUsing(function (Bill $record) {
217
                         $paymentAmount = $this->paymentAmounts[$record->id] ?? 0;
215
                         $paymentAmount = $this->paymentAmounts[$record->id] ?? 0;
218
 
216
 
219
-                        return CurrencyConverter::convertCentsToFormatSimple($paymentAmount, $record->currency_code);
217
+                        return CurrencyConverter::convertCentsToFormatSimple($paymentAmount, 'USD');
220
                     }),
218
                     }),
221
             ])
219
             ])
222
             ->actions([
220
             ->actions([
258
                     }),
256
                     }),
259
             ])
257
             ])
260
             ->filters([
258
             ->filters([
259
+                Tables\Filters\SelectFilter::make('currency')
260
+                    ->selectablePlaceholder(false)
261
+                    ->default(CurrencyAccessor::getDefaultCurrency())
262
+                    ->relationship('currency', 'name')
263
+                    ->searchable()
264
+                    ->preload(),
261
                 Tables\Filters\SelectFilter::make('vendor')
265
                 Tables\Filters\SelectFilter::make('vendor')
262
                     ->relationship('vendor', 'name')
266
                     ->relationship('vendor', 'name')
263
                     ->searchable()
267
                     ->searchable()
264
                     ->preload(),
268
                     ->preload(),
265
                 Tables\Filters\SelectFilter::make('status')
269
                 Tables\Filters\SelectFilter::make('status')
266
                     ->multiple()
270
                     ->multiple()
267
-                    ->options([
268
-                        BillStatus::Open->value => 'Open',
269
-                        BillStatus::Partial->value => 'Partial',
270
-                        BillStatus::Overdue->value => 'Overdue',
271
-                    ])
272
-                    ->default([BillStatus::Open->value, BillStatus::Overdue->value]),
273
-            ])
271
+                    ->options(BillStatus::getUnpaidOptions()),
272
+            ], layout: FiltersLayout::AboveContent)
274
             ->defaultSort('due_date')
273
             ->defaultSort('due_date')
275
             ->striped()
274
             ->striped()
276
             ->paginated(false);
275
             ->paginated(false);
284
     #[Computed]
283
     #[Computed]
285
     public function totalSelectedPaymentAmount(): string
284
     public function totalSelectedPaymentAmount(): string
286
     {
285
     {
287
-        $selectedIds = array_keys($this->getSelectedTableRecords()->toArray());
288
-        $total = collect($selectedIds)
289
-            ->map(fn ($id) => $this->paymentAmounts[$id] ?? 0)
290
-            ->sum();
286
+        $total = array_sum($this->paymentAmounts);
287
+
288
+        $currencyCode = $this->getTableFilterState('currency')['value'];
291
 
289
 
292
-        return CurrencyConverter::formatCentsToMoney($total);
290
+        return CurrencyConverter::formatCentsToMoney($total, $currencyCode);
293
     }
291
     }
294
 }
292
 }

+ 1
- 13
resources/views/filament/company/resources/purchases/bill-resource/pages/pay-bills.blade.php 查看文件

6
                     {{ $this->form }}
6
                     {{ $this->form }}
7
                 </div>
7
                 </div>
8
                 <div class="text-right">
8
                 <div class="text-right">
9
-                    <div class="text-sm text-gray-500">Total Selected:</div>
9
+                    <div class="text-sm text-gray-500">Total Payment Amount</div>
10
                     <div class="text-xl font-semibold text-gray-900" id="total-amount">{{ $this->totalSelectedPaymentAmount }}</div>
10
                     <div class="text-xl font-semibold text-gray-900" id="total-amount">{{ $this->totalSelectedPaymentAmount }}</div>
11
                 </div>
11
                 </div>
12
             </div>
12
             </div>
14
 
14
 
15
         {{ $this->table }}
15
         {{ $this->table }}
16
     </div>
16
     </div>
17
-
18
-    <script>
19
-        // Update total when table state changes
20
-        document.addEventListener('livewire:navigated', function() {
21
-            updateTotal();
22
-        });
23
-
24
-        function updateTotal() {
25
-            // This would need to be implemented to calculate total from selected bills
26
-            // For now, it's a placeholder
27
-        }
28
-    </script>
29
 </x-filament-panels::page>
17
 </x-filament-panels::page>

Loading…
取消
儲存