Andrew Wallo 9 个月前
父节点
当前提交
54ed7c4925

+ 55
- 0
app/Collections/Accounting/DocumentCollection.php 查看文件

1
+<?php
2
+
3
+namespace App\Collections\Accounting;
4
+
5
+use App\Utilities\Currency\CurrencyAccessor;
6
+use App\Utilities\Currency\CurrencyConverter;
7
+use Illuminate\Database\Eloquent\Collection;
8
+
9
+class DocumentCollection extends Collection
10
+{
11
+    public function sumMoneyInCents(string $column): int
12
+    {
13
+        return $this->reduce(static function ($carry, $document) use ($column) {
14
+            return $carry + $document->getRawOriginal($column);
15
+        }, 0);
16
+    }
17
+
18
+    public function sumMoneyFormattedSimple(string $column, ?string $currency = null): string
19
+    {
20
+        $currency ??= CurrencyAccessor::getDefaultCurrency();
21
+
22
+        $totalCents = $this->sumMoneyInCents($column);
23
+
24
+        return CurrencyConverter::convertCentsToFormatSimple($totalCents, $currency);
25
+    }
26
+
27
+    public function sumMoneyFormatted(string $column, ?string $currency = null): string
28
+    {
29
+        $currency ??= CurrencyAccessor::getDefaultCurrency();
30
+
31
+        $totalCents = $this->sumMoneyInCents($column);
32
+
33
+        return CurrencyConverter::formatCentsToMoney($totalCents, $currency);
34
+    }
35
+
36
+    public function sumMoneyInDefaultCurrency(string $column): int
37
+    {
38
+        $defaultCurrency = CurrencyAccessor::getDefaultCurrency();
39
+
40
+        return $this->reduce(static function ($carry, $document) use ($column, $defaultCurrency) {
41
+            $amountInCents = $document->getRawOriginal($column);
42
+            $documentCurrency = $document->currency_code ?? $defaultCurrency;
43
+
44
+            if ($documentCurrency !== $defaultCurrency) {
45
+                $amountInCents = CurrencyConverter::convertBalance(
46
+                    $amountInCents,
47
+                    $documentCurrency,
48
+                    $defaultCurrency
49
+                );
50
+            }
51
+
52
+            return $carry + $amountInCents;
53
+        }, 0);
54
+    }
55
+}

+ 0
- 36
app/Collections/Accounting/InvoiceCollection.php 查看文件

1
-<?php
2
-
3
-namespace App\Collections\Accounting;
4
-
5
-use App\Models\Accounting\Invoice;
6
-use App\Utilities\Currency\CurrencyAccessor;
7
-use App\Utilities\Currency\CurrencyConverter;
8
-use Illuminate\Database\Eloquent\Collection;
9
-
10
-class InvoiceCollection extends Collection
11
-{
12
-    public function sumMoneyInCents(string $column): int
13
-    {
14
-        return $this->reduce(static function ($carry, Invoice $invoice) use ($column) {
15
-            return $carry + $invoice->getRawOriginal($column);
16
-        }, 0);
17
-    }
18
-
19
-    public function sumMoneyFormattedSimple(string $column, ?string $currency = null): string
20
-    {
21
-        $currency ??= CurrencyAccessor::getDefaultCurrency();
22
-
23
-        $totalCents = $this->sumMoneyInCents($column);
24
-
25
-        return CurrencyConverter::convertCentsToFormatSimple($totalCents, $currency);
26
-    }
27
-
28
-    public function sumMoneyFormatted(string $column, ?string $currency = null): string
29
-    {
30
-        $currency ??= CurrencyAccessor::getDefaultCurrency();
31
-
32
-        $totalCents = $this->sumMoneyInCents($column);
33
-
34
-        return CurrencyConverter::formatCentsToMoney($totalCents, $currency);
35
-    }
36
-}

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

431
                             if ($cantRecordPayments) {
431
                             if ($cantRecordPayments) {
432
                                 Notification::make()
432
                                 Notification::make()
433
                                     ->title('Payment Recording Failed')
433
                                     ->title('Payment Recording Failed')
434
-                                    ->body('Bills that are either paid or voided cannot be processed through bulk payments. Please adjust your selection and try again.')
434
+                                    ->body('Bills that are either paid, voided, or are in a foreign currency cannot be processed through bulk payments. Please adjust your selection and try again.')
435
                                     ->persistent()
435
                                     ->persistent()
436
                                     ->danger()
436
                                     ->danger()
437
                                     ->send();
437
                                     ->send();

+ 7
- 4
app/Filament/Company/Resources/Purchases/BillResource/Widgets/BillOverview.php 查看文件

24
         $unpaidBills = $this->getPageTableQuery()
24
         $unpaidBills = $this->getPageTableQuery()
25
             ->whereIn('status', [BillStatus::Unpaid, BillStatus::Partial, BillStatus::Overdue]);
25
             ->whereIn('status', [BillStatus::Unpaid, BillStatus::Partial, BillStatus::Overdue]);
26
 
26
 
27
-        $amountToPay = $unpaidBills->sum('amount_due');
27
+        $amountToPay = $unpaidBills->get()->sumMoneyInDefaultCurrency('amount_due');
28
 
28
 
29
         $amountOverdue = $unpaidBills
29
         $amountOverdue = $unpaidBills
30
             ->clone()
30
             ->clone()
31
             ->where('status', BillStatus::Overdue)
31
             ->where('status', BillStatus::Overdue)
32
-            ->sum('amount_due');
32
+            ->get()
33
+            ->sumMoneyInDefaultCurrency('amount_due');
33
 
34
 
34
         $amountDueWithin7Days = $unpaidBills
35
         $amountDueWithin7Days = $unpaidBills
35
             ->clone()
36
             ->clone()
36
             ->whereBetween('due_date', [today(), today()->addWeek()])
37
             ->whereBetween('due_date', [today(), today()->addWeek()])
37
-            ->sum('amount_due');
38
+            ->get()
39
+            ->sumMoneyInDefaultCurrency('amount_due');
38
 
40
 
39
         $averagePaymentTime = $this->getPageTableQuery()
41
         $averagePaymentTime = $this->getPageTableQuery()
40
             ->whereNotNull('paid_at')
42
             ->whereNotNull('paid_at')
49
                 today()->subMonth()->startOfMonth(),
51
                 today()->subMonth()->startOfMonth(),
50
                 today()->subMonth()->endOfMonth(),
52
                 today()->subMonth()->endOfMonth(),
51
             ])
53
             ])
52
-            ->sum('amount_paid');
54
+            ->get()
55
+            ->sumMoneyInDefaultCurrency('amount_paid');
53
 
56
 
54
         return [
57
         return [
55
             EnhancedStatsOverviewWidget\EnhancedStat::make('Total To Pay', CurrencyConverter::formatCentsToMoney($amountToPay))
58
             EnhancedStatsOverviewWidget\EnhancedStat::make('Total To Pay', CurrencyConverter::formatCentsToMoney($amountToPay))

+ 5
- 5
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\InvoiceCollection;
5
+use App\Collections\Accounting\DocumentCollection;
6
 use App\Enums\Accounting\DocumentDiscountMethod;
6
 use App\Enums\Accounting\DocumentDiscountMethod;
7
 use App\Enums\Accounting\DocumentType;
7
 use App\Enums\Accounting\DocumentType;
8
 use App\Enums\Accounting\InvoiceStatus;
8
 use App\Enums\Accounting\InvoiceStatus;
555
                             if ($cantRecordPayments) {
555
                             if ($cantRecordPayments) {
556
                                 Notification::make()
556
                                 Notification::make()
557
                                     ->title('Payment Recording Failed')
557
                                     ->title('Payment Recording Failed')
558
-                                    ->body('Invoices that are either draft, paid, overpaid, or voided cannot be processed through bulk payments. Please adjust your selection and try again.')
558
+                                    ->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.')
559
                                     ->persistent()
559
                                     ->persistent()
560
                                     ->danger()
560
                                     ->danger()
561
                                     ->send();
561
                                     ->send();
563
                                 $action->cancel(true);
563
                                 $action->cancel(true);
564
                             }
564
                             }
565
                         })
565
                         })
566
-                        ->mountUsing(function (InvoiceCollection $records, Form $form) {
566
+                        ->mountUsing(function (DocumentCollection $records, Form $form) {
567
                             $totalAmountDue = $records->sumMoneyFormattedSimple('amount_due');
567
                             $totalAmountDue = $records->sumMoneyFormattedSimple('amount_due');
568
 
568
 
569
                             $form->fill([
569
                             $form->fill([
599
                             Forms\Components\Textarea::make('notes')
599
                             Forms\Components\Textarea::make('notes')
600
                                 ->label('Notes'),
600
                                 ->label('Notes'),
601
                         ])
601
                         ])
602
-                        ->before(function (InvoiceCollection $records, Tables\Actions\BulkAction $action, array $data) {
602
+                        ->before(function (DocumentCollection $records, Tables\Actions\BulkAction $action, array $data) {
603
                             $totalPaymentAmount = CurrencyConverter::convertToCents($data['amount']);
603
                             $totalPaymentAmount = CurrencyConverter::convertToCents($data['amount']);
604
                             $totalAmountDue = $records->sumMoneyInCents('amount_due');
604
                             $totalAmountDue = $records->sumMoneyInCents('amount_due');
605
 
605
 
616
                                 $action->halt(true);
616
                                 $action->halt(true);
617
                             }
617
                             }
618
                         })
618
                         })
619
-                        ->action(function (InvoiceCollection $records, Tables\Actions\BulkAction $action, array $data) {
619
+                        ->action(function (DocumentCollection $records, Tables\Actions\BulkAction $action, array $data) {
620
                             $totalPaymentAmount = CurrencyConverter::convertToCents($data['amount']);
620
                             $totalPaymentAmount = CurrencyConverter::convertToCents($data['amount']);
621
 
621
 
622
                             $remainingAmount = $totalPaymentAmount;
622
                             $remainingAmount = $totalPaymentAmount;

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

23
     {
23
     {
24
         $unpaidInvoices = $this->getPageTableQuery()->unpaid();
24
         $unpaidInvoices = $this->getPageTableQuery()->unpaid();
25
 
25
 
26
-        $amountUnpaid = $unpaidInvoices->sum('amount_due');
26
+        $amountUnpaid = $unpaidInvoices->get()->sumMoneyInDefaultCurrency('amount_due');
27
 
27
 
28
         $amountOverdue = $unpaidInvoices
28
         $amountOverdue = $unpaidInvoices
29
             ->clone()
29
             ->clone()
30
             ->where('status', InvoiceStatus::Overdue)
30
             ->where('status', InvoiceStatus::Overdue)
31
-            ->sum('amount_due');
31
+            ->get()
32
+            ->sumMoneyInDefaultCurrency('amount_due');
32
 
33
 
33
         $amountDueWithin30Days = $unpaidInvoices
34
         $amountDueWithin30Days = $unpaidInvoices
34
             ->clone()
35
             ->clone()
35
             ->whereBetween('due_date', [today(), today()->addMonth()])
36
             ->whereBetween('due_date', [today(), today()->addMonth()])
36
-            ->sum('amount_due');
37
+            ->get()
38
+            ->sumMoneyInDefaultCurrency('amount_due');
37
 
39
 
38
         $validInvoices = $this->getPageTableQuery()
40
         $validInvoices = $this->getPageTableQuery()
39
             ->whereNotIn('status', [
41
             ->whereNotIn('status', [
41
                 InvoiceStatus::Draft,
43
                 InvoiceStatus::Draft,
42
             ]);
44
             ]);
43
 
45
 
44
-        $totalValidInvoiceAmount = $validInvoices->sum('total');
46
+        $totalValidInvoiceAmount = $validInvoices->get()->sumMoneyInDefaultCurrency('total');
45
 
47
 
46
         $totalValidInvoiceCount = $validInvoices->count();
48
         $totalValidInvoiceCount = $validInvoices->count();
47
 
49
 

+ 4
- 1
app/Models/Accounting/Bill.php 查看文件

4
 
4
 
5
 use App\Casts\MoneyCast;
5
 use App\Casts\MoneyCast;
6
 use App\Casts\RateCast;
6
 use App\Casts\RateCast;
7
+use App\Collections\Accounting\DocumentCollection;
7
 use App\Concerns\Blamable;
8
 use App\Concerns\Blamable;
8
 use App\Concerns\CompanyOwned;
9
 use App\Concerns\CompanyOwned;
9
 use App\Enums\Accounting\AdjustmentComputation;
10
 use App\Enums\Accounting\AdjustmentComputation;
20
 use App\Utilities\Currency\CurrencyConverter;
21
 use App\Utilities\Currency\CurrencyConverter;
21
 use Filament\Actions\MountableAction;
22
 use Filament\Actions\MountableAction;
22
 use Filament\Actions\ReplicateAction;
23
 use Filament\Actions\ReplicateAction;
24
+use Illuminate\Database\Eloquent\Attributes\CollectedBy;
23
 use Illuminate\Database\Eloquent\Attributes\ObservedBy;
25
 use Illuminate\Database\Eloquent\Attributes\ObservedBy;
24
 use Illuminate\Database\Eloquent\Builder;
26
 use Illuminate\Database\Eloquent\Builder;
25
 use Illuminate\Database\Eloquent\Casts\Attribute;
27
 use Illuminate\Database\Eloquent\Casts\Attribute;
31
 use Illuminate\Support\Carbon;
33
 use Illuminate\Support\Carbon;
32
 
34
 
33
 #[ObservedBy(BillObserver::class)]
35
 #[ObservedBy(BillObserver::class)]
36
+#[CollectedBy(DocumentCollection::class)]
34
 class Bill extends Model
37
 class Bill extends Model
35
 {
38
 {
36
     use Blamable;
39
     use Blamable;
136
         return ! in_array($this->status, [
139
         return ! in_array($this->status, [
137
             BillStatus::Paid,
140
             BillStatus::Paid,
138
             BillStatus::Void,
141
             BillStatus::Void,
139
-        ]);
142
+        ]) && $this->currency_code === CurrencyAccessor::getDefaultCurrency();
140
     }
143
     }
141
 
144
 
142
     public function hasPayments(): bool
145
     public function hasPayments(): bool

+ 3
- 3
app/Models/Accounting/Invoice.php 查看文件

4
 
4
 
5
 use App\Casts\MoneyCast;
5
 use App\Casts\MoneyCast;
6
 use App\Casts\RateCast;
6
 use App\Casts\RateCast;
7
-use App\Collections\Accounting\InvoiceCollection;
7
+use App\Collections\Accounting\DocumentCollection;
8
 use App\Concerns\Blamable;
8
 use App\Concerns\Blamable;
9
 use App\Concerns\CompanyOwned;
9
 use App\Concerns\CompanyOwned;
10
 use App\Enums\Accounting\AdjustmentComputation;
10
 use App\Enums\Accounting\AdjustmentComputation;
34
 use Illuminate\Support\Carbon;
34
 use Illuminate\Support\Carbon;
35
 
35
 
36
 #[ObservedBy(InvoiceObserver::class)]
36
 #[ObservedBy(InvoiceObserver::class)]
37
-#[CollectedBy(InvoiceCollection::class)]
37
+#[CollectedBy(DocumentCollection::class)]
38
 class Invoice extends Model
38
 class Invoice extends Model
39
 {
39
 {
40
     use Blamable;
40
     use Blamable;
169
             InvoiceStatus::Paid,
169
             InvoiceStatus::Paid,
170
             InvoiceStatus::Void,
170
             InvoiceStatus::Void,
171
             InvoiceStatus::Overpaid,
171
             InvoiceStatus::Overpaid,
172
-        ]);
172
+        ]) && $this->currency_code === CurrencyAccessor::getDefaultCurrency();
173
     }
173
     }
174
 
174
 
175
     public function canBeOverdue(): bool
175
     public function canBeOverdue(): bool

正在加载...
取消
保存