Andrew Wallo 4 月之前
父節點
當前提交
5347bd1545

+ 105
- 40
app/Filament/Company/Resources/Purchases/BillResource.php 查看文件

35
 use Filament\Forms;
35
 use Filament\Forms;
36
 use Filament\Forms\Form;
36
 use Filament\Forms\Form;
37
 use Filament\Resources\Resource;
37
 use Filament\Resources\Resource;
38
-use Filament\Support\Enums\Alignment;
39
 use Filament\Support\Enums\MaxWidth;
38
 use Filament\Support\Enums\MaxWidth;
40
 use Filament\Tables;
39
 use Filament\Tables;
41
 use Filament\Tables\Table;
40
 use Filament\Tables\Table;
438
                         Bill::getReplicateAction(Tables\Actions\ReplicateAction::class),
437
                         Bill::getReplicateAction(Tables\Actions\ReplicateAction::class),
439
                         Tables\Actions\Action::make('recordPayment')
438
                         Tables\Actions\Action::make('recordPayment')
440
                             ->label('Record payment')
439
                             ->label('Record payment')
441
-                            ->stickyModalHeader()
442
-                            ->stickyModalFooter()
443
-                            ->modalFooterActionsAlignment(Alignment::End)
440
+                            ->slideOver()
444
                             ->modalWidth(MaxWidth::TwoExtraLarge)
441
                             ->modalWidth(MaxWidth::TwoExtraLarge)
445
-                            ->icon('heroicon-o-credit-card')
442
+                            ->icon('heroicon-m-credit-card')
446
                             ->visible(function (Bill $record) {
443
                             ->visible(function (Bill $record) {
447
                                 return $record->canRecordPayment();
444
                                 return $record->canRecordPayment();
448
                             })
445
                             })
457
                             ->form([
454
                             ->form([
458
                                 Forms\Components\DatePicker::make('posted_at')
455
                                 Forms\Components\DatePicker::make('posted_at')
459
                                     ->label('Date'),
456
                                     ->label('Date'),
460
-                                Forms\Components\TextInput::make('amount')
461
-                                    ->label('Amount')
462
-                                    ->required()
463
-                                    ->money(fn (Bill $record) => $record->currency_code)
464
-                                    ->live(onBlur: true)
465
-                                    ->helperText(function (Bill $record, $state) {
457
+                                Forms\Components\Grid::make()
458
+                                    ->schema([
459
+                                        Forms\Components\Select::make('bank_account_id')
460
+                                            ->label('Account')
461
+                                            ->required()
462
+                                            ->live()
463
+                                            ->options(function () {
464
+                                                return BankAccount::query()
465
+                                                    ->join('accounts', 'bank_accounts.account_id', '=', 'accounts.id')
466
+                                                    ->select(['bank_accounts.id', 'accounts.name', 'accounts.currency_code'])
467
+                                                    ->get()
468
+                                                    ->mapWithKeys(function ($account) {
469
+                                                        $label = $account->name;
470
+                                                        if ($account->currency_code) {
471
+                                                            $label .= " ({$account->currency_code})";
472
+                                                        }
473
+
474
+                                                        return [$account->id => $label];
475
+                                                    })
476
+                                                    ->toArray();
477
+                                            })
478
+                                            ->searchable(),
479
+                                        Forms\Components\TextInput::make('amount')
480
+                                            ->label('Amount')
481
+                                            ->required()
482
+                                            ->money(fn (Bill $record) => $record->currency_code)
483
+                                            ->live(onBlur: true)
484
+                                            ->helperText(function (Bill $record, $state) {
485
+                                                $billCurrency = $record->currency_code;
486
+
487
+                                                if (! CurrencyConverter::isValidAmount($state, 'USD')) {
488
+                                                    return null;
489
+                                                }
490
+
491
+                                                $amountDue = $record->amount_due;
492
+
493
+                                                $amount = CurrencyConverter::convertToCents($state, 'USD');
494
+
495
+                                                if ($amount <= 0) {
496
+                                                    return 'Please enter a valid positive amount';
497
+                                                }
498
+
499
+                                                $newAmountDue = $amountDue - $amount;
500
+
501
+                                                return match (true) {
502
+                                                    $newAmountDue > 0 => 'Amount due after payment will be ' . CurrencyConverter::formatCentsToMoney($newAmountDue, $billCurrency),
503
+                                                    $newAmountDue === 0 => 'Bill will be fully paid',
504
+                                                    default => 'Amount exceeds bill total by ' . CurrencyConverter::formatCentsToMoney(abs($newAmountDue), $billCurrency),
505
+                                                };
506
+                                            })
507
+                                            ->rules([
508
+                                                static fn (): Closure => static function (string $attribute, $value, Closure $fail) {
509
+                                                    if (! CurrencyConverter::isValidAmount($value, 'USD')) {
510
+                                                        $fail('Please enter a valid amount');
511
+                                                    }
512
+                                                },
513
+                                            ]),
514
+                                    ])->columns(2),
515
+                                Forms\Components\Placeholder::make('currency_conversion')
516
+                                    ->label('Currency Conversion')
517
+                                    ->content(function (Forms\Get $get, Bill $record) {
518
+                                        $amount = $get('amount');
519
+                                        $bankAccountId = $get('bank_account_id');
520
+
466
                                         $billCurrency = $record->currency_code;
521
                                         $billCurrency = $record->currency_code;
467
-                                        if (! CurrencyConverter::isValidAmount($state, 'USD')) {
522
+
523
+                                        if (empty($amount) || empty($bankAccountId) || ! CurrencyConverter::isValidAmount($amount, 'USD')) {
524
+                                            return null;
525
+                                        }
526
+
527
+                                        $bankAccount = BankAccount::with('account')->find($bankAccountId);
528
+                                        if (! $bankAccount) {
468
                                             return null;
529
                                             return null;
469
                                         }
530
                                         }
470
 
531
 
471
-                                        $amountDue = $record->amount_due;
472
-                                        $amount = CurrencyConverter::convertToCents($state, 'USD');
532
+                                        $bankCurrency = $bankAccount->account->currency_code ?? CurrencyAccessor::getDefaultCurrency();
473
 
533
 
474
-                                        if ($amount <= 0) {
475
-                                            return 'Please enter a valid positive amount';
534
+                                        // If currencies are the same, no conversion needed
535
+                                        if ($billCurrency === $bankCurrency) {
536
+                                            return null;
476
                                         }
537
                                         }
477
 
538
 
478
-                                        $newAmountDue = $amountDue - $amount;
539
+                                        // Convert amount from bill currency to bank currency
540
+                                        $amountInBillCurrencyCents = CurrencyConverter::convertToCents($amount, 'USD');
541
+                                        $amountInBankCurrencyCents = CurrencyConverter::convertBalance(
542
+                                            $amountInBillCurrencyCents,
543
+                                            $billCurrency,
544
+                                            $bankCurrency
545
+                                        );
479
 
546
 
480
-                                        return match (true) {
481
-                                            $newAmountDue > 0 => 'Amount due after payment will be ' . CurrencyConverter::formatCentsToMoney($newAmountDue, $billCurrency),
482
-                                            $newAmountDue === 0 => 'Bill will be fully paid',
483
-                                            default => 'Amount exceeds bill total by ' . CurrencyConverter::formatCentsToMoney(abs($newAmountDue), $billCurrency),
484
-                                        };
547
+                                        $formattedBankAmount = CurrencyConverter::formatCentsToMoney($amountInBankCurrencyCents, $bankCurrency);
548
+
549
+                                        return "Payment will be recorded as {$formattedBankAmount} in the bank account's currency ({$bankCurrency}).";
485
                                     })
550
                                     })
486
-                                    ->rules([
487
-                                        static fn (): Closure => static function (string $attribute, $value, Closure $fail) {
488
-                                            if (! CurrencyConverter::isValidAmount($value, 'USD')) {
489
-                                                $fail('Please enter a valid amount');
490
-                                            }
491
-                                        },
492
-                                    ]),
551
+                                    ->hidden(function (Forms\Get $get, Bill $record) {
552
+                                        $bankAccountId = $get('bank_account_id');
553
+                                        if (empty($bankAccountId)) {
554
+                                            return true;
555
+                                        }
556
+
557
+                                        $billCurrency = $record->currency_code;
558
+
559
+                                        $bankAccount = BankAccount::with('account')->find($bankAccountId);
560
+                                        if (! $bankAccount) {
561
+                                            return true;
562
+                                        }
563
+
564
+                                        $bankCurrency = $bankAccount->account->currency_code ?? CurrencyAccessor::getDefaultCurrency();
565
+
566
+                                        // Hide if currencies are the same
567
+                                        return $billCurrency === $bankCurrency;
568
+                                    }),
493
                                 Forms\Components\Select::make('payment_method')
569
                                 Forms\Components\Select::make('payment_method')
494
                                     ->label('Payment method')
570
                                     ->label('Payment method')
495
                                     ->required()
571
                                     ->required()
496
                                     ->options(PaymentMethod::class),
572
                                     ->options(PaymentMethod::class),
497
-                                Forms\Components\Select::make('bank_account_id')
498
-                                    ->label('Account')
499
-                                    ->required()
500
-                                    ->options(function () {
501
-                                        return BankAccount::query()
502
-                                            ->join('accounts', 'bank_accounts.account_id', '=', 'accounts.id')
503
-                                            ->select(['bank_accounts.id', 'accounts.name'])
504
-                                            ->pluck('accounts.name', 'bank_accounts.id')
505
-                                            ->toArray();
506
-                                    })
507
-                                    ->searchable(),
508
                                 Forms\Components\Textarea::make('notes')
573
                                 Forms\Components\Textarea::make('notes')
509
                                     ->label('Notes'),
574
                                     ->label('Notes'),
510
                             ])
575
                             ])

+ 1
- 0
app/Filament/Company/Resources/Purchases/BillResource/RelationManagers/PaymentsRelationManager.php 查看文件

216
                 Tables\Actions\CreateAction::make()
216
                 Tables\Actions\CreateAction::make()
217
                     ->label('Record payment')
217
                     ->label('Record payment')
218
                     ->modalHeading(fn (Tables\Actions\CreateAction $action) => $action->getLabel())
218
                     ->modalHeading(fn (Tables\Actions\CreateAction $action) => $action->getLabel())
219
+                    ->slideOver()
219
                     ->modalWidth(MaxWidth::TwoExtraLarge)
220
                     ->modalWidth(MaxWidth::TwoExtraLarge)
220
                     ->visible(function () {
221
                     ->visible(function () {
221
                         return $this->getOwnerRecord()->canRecordPayment();
222
                         return $this->getOwnerRecord()->canRecordPayment();

+ 109
- 151
app/Filament/Company/Resources/Sales/InvoiceResource.php 查看文件

2
 
2
 
3
 namespace App\Filament\Company\Resources\Sales;
3
 namespace App\Filament\Company\Resources\Sales;
4
 
4
 
5
-use App\Collections\Accounting\DocumentCollection;
6
 use App\Enums\Accounting\AdjustmentCategory;
5
 use App\Enums\Accounting\AdjustmentCategory;
7
 use App\Enums\Accounting\AdjustmentStatus;
6
 use App\Enums\Accounting\AdjustmentStatus;
8
 use App\Enums\Accounting\AdjustmentType;
7
 use App\Enums\Accounting\AdjustmentType;
40
 use Filament\Forms\Form;
39
 use Filament\Forms\Form;
41
 use Filament\Notifications\Notification;
40
 use Filament\Notifications\Notification;
42
 use Filament\Resources\Resource;
41
 use Filament\Resources\Resource;
43
-use Filament\Support\Enums\Alignment;
44
 use Filament\Support\Enums\MaxWidth;
42
 use Filament\Support\Enums\MaxWidth;
45
 use Filament\Tables;
43
 use Filament\Tables;
46
 use Filament\Tables\Table;
44
 use Filament\Tables\Table;
493
                         Invoice::getMarkAsSentAction(Tables\Actions\Action::class),
491
                         Invoice::getMarkAsSentAction(Tables\Actions\Action::class),
494
                         Tables\Actions\Action::make('recordPayment')
492
                         Tables\Actions\Action::make('recordPayment')
495
                             ->label(fn (Invoice $record) => $record->status === InvoiceStatus::Overpaid ? 'Refund Overpayment' : 'Record Payment')
493
                             ->label(fn (Invoice $record) => $record->status === InvoiceStatus::Overpaid ? 'Refund Overpayment' : 'Record Payment')
496
-                            ->stickyModalHeader()
497
-                            ->stickyModalFooter()
498
-                            ->modalFooterActionsAlignment(Alignment::End)
494
+                            ->slideOver()
499
                             ->modalWidth(MaxWidth::TwoExtraLarge)
495
                             ->modalWidth(MaxWidth::TwoExtraLarge)
500
-                            ->icon('heroicon-o-credit-card')
496
+                            ->icon('heroicon-m-credit-card')
501
                             ->visible(function (Invoice $record) {
497
                             ->visible(function (Invoice $record) {
502
                                 return $record->canRecordPayment();
498
                                 return $record->canRecordPayment();
503
                             })
499
                             })
504
                             ->mountUsing(function (Invoice $record, Form $form) {
500
                             ->mountUsing(function (Invoice $record, Form $form) {
505
                                 $form->fill([
501
                                 $form->fill([
506
                                     'posted_at' => now(),
502
                                     'posted_at' => now(),
507
-                                    'amount' => $record->status === InvoiceStatus::Overpaid ? ltrim($record->amount_due, '-') : $record->amount_due,
503
+                                    'amount' => abs($record->amount_due),
508
                                 ]);
504
                                 ]);
509
                             })
505
                             })
510
                             ->databaseTransaction()
506
                             ->databaseTransaction()
512
                             ->form([
508
                             ->form([
513
                                 Forms\Components\DatePicker::make('posted_at')
509
                                 Forms\Components\DatePicker::make('posted_at')
514
                                     ->label('Date'),
510
                                     ->label('Date'),
515
-                                Forms\Components\TextInput::make('amount')
516
-                                    ->label('Amount')
517
-                                    ->required()
518
-                                    ->money(fn (Invoice $record) => $record->currency_code)
519
-                                    ->live(onBlur: true)
520
-                                    ->helperText(function (Invoice $record, $state) {
511
+                                Forms\Components\Grid::make()
512
+                                    ->schema([
513
+                                        Forms\Components\Select::make('bank_account_id')
514
+                                            ->label('Account')
515
+                                            ->required()
516
+                                            ->live()
517
+                                            ->options(function () {
518
+                                                return BankAccount::query()
519
+                                                    ->join('accounts', 'bank_accounts.account_id', '=', 'accounts.id')
520
+                                                    ->select(['bank_accounts.id', 'accounts.name', 'accounts.currency_code'])
521
+                                                    ->get()
522
+                                                    ->mapWithKeys(function ($account) {
523
+                                                        $label = $account->name;
524
+                                                        if ($account->currency_code) {
525
+                                                            $label .= " ({$account->currency_code})";
526
+                                                        }
527
+
528
+                                                        return [$account->id => $label];
529
+                                                    })
530
+                                                    ->toArray();
531
+                                            })
532
+                                            ->searchable(),
533
+                                        Forms\Components\TextInput::make('amount')
534
+                                            ->label('Amount')
535
+                                            ->required()
536
+                                            ->money(fn (Invoice $record) => $record->currency_code)
537
+                                            ->live(onBlur: true)
538
+                                            ->helperText(function (Invoice $record, $state) {
539
+                                                $invoiceCurrency = $record->currency_code;
540
+
541
+                                                if (! CurrencyConverter::isValidAmount($state, 'USD')) {
542
+                                                    return null;
543
+                                                }
544
+
545
+                                                $amountDue = $record->amount_due;
546
+
547
+                                                $amount = CurrencyConverter::convertToCents($state, 'USD');
548
+
549
+                                                if ($amount <= 0) {
550
+                                                    return 'Please enter a valid positive amount';
551
+                                                }
552
+
553
+                                                if ($record->status === InvoiceStatus::Overpaid) {
554
+                                                    $newAmountDue = $amountDue + $amount;
555
+                                                } else {
556
+                                                    $newAmountDue = $amountDue - $amount;
557
+                                                }
558
+
559
+                                                return match (true) {
560
+                                                    $newAmountDue > 0 => 'Amount due after payment will be ' . CurrencyConverter::formatCentsToMoney($newAmountDue, $invoiceCurrency),
561
+                                                    $newAmountDue === 0 => 'Invoice will be fully paid',
562
+                                                    default => 'Invoice will be overpaid by ' . CurrencyConverter::formatCentsToMoney(abs($newAmountDue), $invoiceCurrency),
563
+                                                };
564
+                                            })
565
+                                            ->rules([
566
+                                                static fn (): Closure => static function (string $attribute, $value, Closure $fail) {
567
+                                                    if (! CurrencyConverter::isValidAmount($value, 'USD')) {
568
+                                                        $fail('Please enter a valid amount');
569
+                                                    }
570
+                                                },
571
+                                            ]),
572
+                                    ])->columns(2),
573
+                                Forms\Components\Placeholder::make('currency_conversion')
574
+                                    ->label('Currency Conversion')
575
+                                    ->content(function (Forms\Get $get, Invoice $record) {
576
+                                        $amount = $get('amount');
577
+                                        $bankAccountId = $get('bank_account_id');
578
+
521
                                         $invoiceCurrency = $record->currency_code;
579
                                         $invoiceCurrency = $record->currency_code;
522
-                                        if (! CurrencyConverter::isValidAmount($state, 'USD')) {
580
+
581
+                                        if (empty($amount) || empty($bankAccountId) || ! CurrencyConverter::isValidAmount($amount, 'USD')) {
523
                                             return null;
582
                                             return null;
524
                                         }
583
                                         }
525
 
584
 
526
-                                        $amountDue = $record->amount_due;
585
+                                        $bankAccount = BankAccount::with('account')->find($bankAccountId);
586
+                                        if (! $bankAccount) {
587
+                                            return null;
588
+                                        }
527
 
589
 
528
-                                        $amount = CurrencyConverter::convertToCents($state, 'USD');
590
+                                        $bankCurrency = $bankAccount->account->currency_code ?? CurrencyAccessor::getDefaultCurrency();
529
 
591
 
530
-                                        if ($amount <= 0) {
531
-                                            return 'Please enter a valid positive amount';
592
+                                        // If currencies are the same, no conversion needed
593
+                                        if ($invoiceCurrency === $bankCurrency) {
594
+                                            return null;
532
                                         }
595
                                         }
533
 
596
 
534
-                                        if ($record->status === InvoiceStatus::Overpaid) {
535
-                                            $newAmountDue = $amountDue + $amount;
536
-                                        } else {
537
-                                            $newAmountDue = $amountDue - $amount;
538
-                                        }
597
+                                        // Convert amount from invoice currency to bank currency
598
+                                        $amountInInvoiceCurrencyCents = CurrencyConverter::convertToCents($amount, 'USD');
599
+                                        $amountInBankCurrencyCents = CurrencyConverter::convertBalance(
600
+                                            $amountInInvoiceCurrencyCents,
601
+                                            $invoiceCurrency,
602
+                                            $bankCurrency
603
+                                        );
604
+
605
+                                        $formattedBankAmount = CurrencyConverter::formatCentsToMoney($amountInBankCurrencyCents, $bankCurrency);
539
 
606
 
540
-                                        return match (true) {
541
-                                            $newAmountDue > 0 => 'Amount due after payment will be ' . CurrencyConverter::formatCentsToMoney($newAmountDue, $invoiceCurrency),
542
-                                            $newAmountDue === 0 => 'Invoice will be fully paid',
543
-                                            default => 'Invoice will be overpaid by ' . CurrencyConverter::formatCentsToMoney(abs($newAmountDue), $invoiceCurrency),
544
-                                        };
607
+                                        return "Payment will be recorded as {$formattedBankAmount} in the bank account's currency ({$bankCurrency}).";
545
                                     })
608
                                     })
546
-                                    ->rules([
547
-                                        static fn (): Closure => static function (string $attribute, $value, Closure $fail) {
548
-                                            if (! CurrencyConverter::isValidAmount($value, 'USD')) {
549
-                                                $fail('Please enter a valid amount');
550
-                                            }
551
-                                        },
552
-                                    ]),
609
+                                    ->hidden(function (Forms\Get $get, Invoice $record) {
610
+                                        $bankAccountId = $get('bank_account_id');
611
+                                        if (empty($bankAccountId)) {
612
+                                            return true;
613
+                                        }
614
+
615
+                                        $invoiceCurrency = $record->currency_code;
616
+
617
+                                        $bankAccount = BankAccount::with('account')->find($bankAccountId);
618
+                                        if (! $bankAccount) {
619
+                                            return true;
620
+                                        }
621
+
622
+                                        $bankCurrency = $bankAccount->account->currency_code ?? CurrencyAccessor::getDefaultCurrency();
623
+
624
+                                        // Hide if currencies are the same
625
+                                        return $invoiceCurrency === $bankCurrency;
626
+                                    }),
553
                                 Forms\Components\Select::make('payment_method')
627
                                 Forms\Components\Select::make('payment_method')
554
                                     ->label('Payment method')
628
                                     ->label('Payment method')
555
                                     ->required()
629
                                     ->required()
556
                                     ->options(PaymentMethod::class),
630
                                     ->options(PaymentMethod::class),
557
-                                Forms\Components\Select::make('bank_account_id')
558
-                                    ->label('Account')
559
-                                    ->required()
560
-                                    ->options(function () {
561
-                                        return BankAccount::query()
562
-                                            ->join('accounts', 'bank_accounts.account_id', '=', 'accounts.id')
563
-                                            ->select(['bank_accounts.id', 'accounts.name'])
564
-                                            ->pluck('accounts.name', 'bank_accounts.id')
565
-                                            ->toArray();
566
-                                    })
567
-                                    ->searchable(),
568
                                 Forms\Components\Textarea::make('notes')
631
                                 Forms\Components\Textarea::make('notes')
569
                                     ->label('Notes'),
632
                                     ->label('Notes'),
570
                             ])
633
                             ])
670
                                 $record->markAsSent();
733
                                 $record->markAsSent();
671
                             });
734
                             });
672
 
735
 
673
-                            $action->success();
674
-                        }),
675
-                    Tables\Actions\BulkAction::make('recordPayments')
676
-                        ->label('Record payments')
677
-                        ->icon('heroicon-o-credit-card')
678
-                        ->stickyModalHeader()
679
-                        ->stickyModalFooter()
680
-                        ->modalFooterActionsAlignment(Alignment::End)
681
-                        ->modalWidth(MaxWidth::TwoExtraLarge)
682
-                        ->databaseTransaction()
683
-                        ->successNotificationTitle('Payments recorded')
684
-                        ->failureNotificationTitle('Failed to Record Payments')
685
-                        ->deselectRecordsAfterCompletion()
686
-                        ->beforeFormFilled(function (Collection $records, Tables\Actions\BulkAction $action) {
687
-                            $isInvalid = $records->contains(fn (Invoice $record) => ! $record->canBulkRecordPayment());
688
-
689
-                            if ($isInvalid) {
690
-                                Notification::make()
691
-                                    ->title('Payment recording failed')
692
-                                    ->body('Invoices that are either draft, paid, overpaid, voided, or are in a foreign currency cannot be processed through bulk payments. Please adjust your selection and try again.')
693
-                                    ->persistent()
694
-                                    ->danger()
695
-                                    ->send();
696
-
697
-                                $action->cancel(true);
698
-                            }
699
-                        })
700
-                        ->mountUsing(function (DocumentCollection $records, Form $form) {
701
-                            $totalAmountDue = $records->sum('amount_due');
702
-
703
-                            $form->fill([
704
-                                'posted_at' => now(),
705
-                                'amount' => $totalAmountDue,
706
-                            ]);
707
-                        })
708
-                        ->form([
709
-                            Forms\Components\DatePicker::make('posted_at')
710
-                                ->label('Date'),
711
-                            Forms\Components\TextInput::make('amount')
712
-                                ->label('Amount')
713
-                                ->required()
714
-                                ->money()
715
-                                ->rules([
716
-                                    static fn (): Closure => static function (string $attribute, $value, Closure $fail) {
717
-                                        if (! CurrencyConverter::isValidAmount($value)) {
718
-                                            $fail('Please enter a valid amount');
719
-                                        }
720
-                                    },
721
-                                ]),
722
-                            Forms\Components\Select::make('payment_method')
723
-                                ->label('Payment method')
724
-                                ->required()
725
-                                ->options(PaymentMethod::class),
726
-                            Forms\Components\Select::make('bank_account_id')
727
-                                ->label('Account')
728
-                                ->required()
729
-                                ->options(function () {
730
-                                    return BankAccount::query()
731
-                                        ->join('accounts', 'bank_accounts.account_id', '=', 'accounts.id')
732
-                                        ->select(['bank_accounts.id', 'accounts.name'])
733
-                                        ->pluck('accounts.name', 'bank_accounts.id')
734
-                                        ->toArray();
735
-                                })
736
-                                ->searchable(),
737
-                            Forms\Components\Textarea::make('notes')
738
-                                ->label('Notes'),
739
-                        ])
740
-                        ->before(function (DocumentCollection $records, Tables\Actions\BulkAction $action, array $data) {
741
-                            $totalPaymentAmount = $data['amount'] ?? 0;
742
-                            $totalAmountDue = $records->sum('amount_due');
743
-
744
-                            if ($totalPaymentAmount > $totalAmountDue) {
745
-                                $formattedTotalAmountDue = CurrencyConverter::formatCentsToMoney($totalAmountDue);
746
-
747
-                                Notification::make()
748
-                                    ->title('Excess payment amount')
749
-                                    ->body("The payment amount exceeds the total amount due of {$formattedTotalAmountDue}. Please adjust the payment amount and try again.")
750
-                                    ->persistent()
751
-                                    ->warning()
752
-                                    ->send();
753
-
754
-                                $action->halt(true);
755
-                            }
756
-                        })
757
-                        ->action(function (DocumentCollection $records, Tables\Actions\BulkAction $action, array $data) {
758
-                            $totalPaymentAmount = $data['amount'] ?? 0;
759
-
760
-                            $remainingAmount = $totalPaymentAmount;
761
-
762
-                            $records->each(function (Invoice $record) use (&$remainingAmount, $data) {
763
-                                $amountDue = $record->amount_due;
764
-
765
-                                if ($amountDue <= 0 || $remainingAmount <= 0) {
766
-                                    return;
767
-                                }
768
-
769
-                                $paymentAmount = min($amountDue, $remainingAmount);
770
-
771
-                                $data['amount'] = $paymentAmount;
772
-
773
-                                $record->recordPayment($data);
774
-
775
-                                $remainingAmount -= $paymentAmount;
776
-                            });
777
-
778
                             $action->success();
736
                             $action->success();
779
                         }),
737
                         }),
780
                 ]),
738
                 ]),

+ 4
- 6
app/Filament/Company/Resources/Sales/InvoiceResource/RelationManagers/PaymentsRelationManager.php 查看文件

115
                                 };
115
                                 };
116
                             })
116
                             })
117
                             ->rules([
117
                             ->rules([
118
-                                static fn (RelationManager $livewire): Closure => static function (string $attribute, $value, Closure $fail) use ($livewire) {
119
-                                    /** @var Invoice $invoice */
120
-                                    $invoice = $livewire->getOwnerRecord();
121
-
122
-                                    if (! CurrencyConverter::isValidAmount($value, $invoice->currency_code)) {
118
+                                static fn (): Closure => static function (string $attribute, $value, Closure $fail) {
119
+                                    if (! CurrencyConverter::isValidAmount($value, 'USD')) {
123
                                         $fail('Please enter a valid amount');
120
                                         $fail('Please enter a valid amount');
124
                                     }
121
                                     }
125
                                 },
122
                                 },
232
                 Tables\Actions\CreateAction::make()
229
                 Tables\Actions\CreateAction::make()
233
                     ->label(fn () => $this->getOwnerRecord()->status === InvoiceStatus::Overpaid ? 'Refund Overpayment' : 'Record Payment')
230
                     ->label(fn () => $this->getOwnerRecord()->status === InvoiceStatus::Overpaid ? 'Refund Overpayment' : 'Record Payment')
234
                     ->modalHeading(fn (Tables\Actions\CreateAction $action) => $action->getLabel())
231
                     ->modalHeading(fn (Tables\Actions\CreateAction $action) => $action->getLabel())
232
+                    ->slideOver()
235
                     ->modalWidth(MaxWidth::TwoExtraLarge)
233
                     ->modalWidth(MaxWidth::TwoExtraLarge)
236
                     ->visible(function () {
234
                     ->visible(function () {
237
                         return $this->getOwnerRecord()->canRecordPayment();
235
                         return $this->getOwnerRecord()->canRecordPayment();
240
                         $record = $this->getOwnerRecord();
238
                         $record = $this->getOwnerRecord();
241
                         $form->fill([
239
                         $form->fill([
242
                             'posted_at' => now(),
240
                             'posted_at' => now(),
243
-                            'amount' => $record->status === InvoiceStatus::Overpaid ? ltrim($record->amount_due, '-') : $record->amount_due,
241
+                            'amount' => abs($record->amount_due),
244
                         ]);
242
                         ]);
245
                     })
243
                     })
246
                     ->databaseTransaction()
244
                     ->databaseTransaction()

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

11
                     {{ $this->form }}
11
                     {{ $this->form }}
12
                 </div>
12
                 </div>
13
                 <div class="text-right">
13
                 <div class="text-right">
14
-                    <div class="text-sm uppercase text-gray-500 dark:text-gray-400">Total Payment Amount</div>
15
-                    <div class="text-3xl font-semibold text-gray-900 dark:text-white">{{ $this->totalPaymentAmount }}</div>
14
+                    <div class="text-xs font-medium text-gray-500 dark:text-gray-400">
15
+                        Total Payment Amount
16
+                    </div>
17
+                    <div class="text-3xl font-bold text-gray-900 dark:text-white tabular-nums">
18
+                        {{ $this->totalPaymentAmount }}
19
+                    </div>
16
                 </div>
20
                 </div>
17
             </div>
21
             </div>
18
         </x-filament::section>
22
         </x-filament::section>

Loading…
取消
儲存