Andrew Wallo 5 个月前
父节点
当前提交
b5c4a100a9

+ 27
- 1
database/factories/Accounting/BillFactory.php 查看文件

2
 
2
 
3
 namespace Database\Factories\Accounting;
3
 namespace Database\Factories\Accounting;
4
 
4
 
5
+use App\Enums\Accounting\AdjustmentComputation;
5
 use App\Enums\Accounting\BillStatus;
6
 use App\Enums\Accounting\BillStatus;
7
+use App\Enums\Accounting\DocumentDiscountMethod;
6
 use App\Enums\Accounting\PaymentMethod;
8
 use App\Enums\Accounting\PaymentMethod;
7
 use App\Models\Accounting\Bill;
9
 use App\Models\Accounting\Bill;
8
 use App\Models\Accounting\DocumentLineItem;
10
 use App\Models\Accounting\DocumentLineItem;
11
 use App\Models\Company;
13
 use App\Models\Company;
12
 use App\Models\Setting\DocumentDefault;
14
 use App\Models\Setting\DocumentDefault;
13
 use App\Utilities\Currency\CurrencyConverter;
15
 use App\Utilities\Currency\CurrencyConverter;
16
+use App\Utilities\RateCalculator;
14
 use Illuminate\Database\Eloquent\Factories\Factory;
17
 use Illuminate\Database\Eloquent\Factories\Factory;
15
 use Illuminate\Support\Carbon;
18
 use Illuminate\Support\Carbon;
16
 
19
 
49
             'date' => $billDate,
52
             'date' => $billDate,
50
             'due_date' => Carbon::parse($billDate)->addDays($dueDays),
53
             'due_date' => Carbon::parse($billDate)->addDays($dueDays),
51
             'status' => BillStatus::Open,
54
             'status' => BillStatus::Open,
55
+            'discount_method' => $this->faker->randomElement(DocumentDiscountMethod::class),
56
+            'discount_computation' => AdjustmentComputation::Percentage,
57
+            'discount_rate' => function (array $attributes) {
58
+                $discountMethod = DocumentDiscountMethod::parse($attributes['discount_method']);
59
+
60
+                if ($discountMethod?->isPerDocument()) {
61
+                    return $this->faker->numberBetween(50000, 200000); // 5% - 20%
62
+                }
63
+
64
+                return 0;
65
+            },
52
             'currency_code' => function (array $attributes) {
66
             'currency_code' => function (array $attributes) {
53
                 $vendor = Vendor::find($attributes['vendor_id']);
67
                 $vendor = Vendor::find($attributes['vendor_id']);
54
 
68
 
226
 
240
 
227
         $subtotalCents = $bill->lineItems()->sum('subtotal');
241
         $subtotalCents = $bill->lineItems()->sum('subtotal');
228
         $taxTotalCents = $bill->lineItems()->sum('tax_total');
242
         $taxTotalCents = $bill->lineItems()->sum('tax_total');
229
-        $discountTotalCents = $bill->lineItems()->sum('discount_total');
243
+
244
+        $discountTotalCents = 0;
245
+
246
+        if ($bill->discount_method?->isPerLineItem()) {
247
+            $discountTotalCents = $bill->lineItems()->sum('discount_total');
248
+        } elseif ($bill->discount_method?->isPerDocument() && $bill->discount_rate) {
249
+            if ($bill->discount_computation?->isPercentage()) {
250
+                $scaledRate = RateCalculator::parseLocalizedRate($bill->discount_rate);
251
+                $discountTotalCents = RateCalculator::calculatePercentage($subtotalCents, $scaledRate);
252
+            } else {
253
+                $discountTotalCents = CurrencyConverter::convertToCents($bill->discount_rate, $bill->currency_code);
254
+            }
255
+        }
230
 
256
 
231
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
257
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
232
         $currencyCode = $bill->currency_code;
258
         $currencyCode = $bill->currency_code;

+ 15
- 3
database/factories/Accounting/DocumentLineItemFactory.php 查看文件

56
                 ]);
56
                 ]);
57
 
57
 
58
                 $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
58
                 $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
59
-                $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
59
+
60
+                // Only sync discounts if the discount method is per_line_item
61
+                if ($lineItem->documentable->discount_method?->isPerLineItem() ?? true) {
62
+                    $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
63
+                }
60
 
64
 
61
                 $lineItem->refresh();
65
                 $lineItem->refresh();
62
 
66
 
88
                 ]);
92
                 ]);
89
 
93
 
90
                 $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
94
                 $lineItem->salesTaxes()->syncWithoutDetaching($offering->salesTaxes->pluck('id')->toArray());
91
-                $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
95
+
96
+                // Only sync discounts if the discount method is per_line_item
97
+                if ($lineItem->documentable->discount_method?->isPerLineItem() ?? true) {
98
+                    $lineItem->salesDiscounts()->syncWithoutDetaching($offering->salesDiscounts->pluck('id')->toArray());
99
+                }
92
 
100
 
93
                 $lineItem->refresh();
101
                 $lineItem->refresh();
94
 
102
 
120
                 ]);
128
                 ]);
121
 
129
 
122
                 $lineItem->purchaseTaxes()->syncWithoutDetaching($offering->purchaseTaxes->pluck('id')->toArray());
130
                 $lineItem->purchaseTaxes()->syncWithoutDetaching($offering->purchaseTaxes->pluck('id')->toArray());
123
-                $lineItem->purchaseDiscounts()->syncWithoutDetaching($offering->purchaseDiscounts->pluck('id')->toArray());
131
+
132
+                // Only sync discounts if the discount method is per_line_item
133
+                if ($lineItem->documentable->discount_method?->isPerLineItem() ?? true) {
134
+                    $lineItem->purchaseDiscounts()->syncWithoutDetaching($offering->purchaseDiscounts->pluck('id')->toArray());
135
+                }
124
 
136
 
125
                 $lineItem->refresh();
137
                 $lineItem->refresh();
126
 
138
 

+ 27
- 1
database/factories/Accounting/EstimateFactory.php 查看文件

2
 
2
 
3
 namespace Database\Factories\Accounting;
3
 namespace Database\Factories\Accounting;
4
 
4
 
5
+use App\Enums\Accounting\AdjustmentComputation;
6
+use App\Enums\Accounting\DocumentDiscountMethod;
5
 use App\Enums\Accounting\EstimateStatus;
7
 use App\Enums\Accounting\EstimateStatus;
6
 use App\Models\Accounting\DocumentLineItem;
8
 use App\Models\Accounting\DocumentLineItem;
7
 use App\Models\Accounting\Estimate;
9
 use App\Models\Accounting\Estimate;
9
 use App\Models\Company;
11
 use App\Models\Company;
10
 use App\Models\Setting\DocumentDefault;
12
 use App\Models\Setting\DocumentDefault;
11
 use App\Utilities\Currency\CurrencyConverter;
13
 use App\Utilities\Currency\CurrencyConverter;
14
+use App\Utilities\RateCalculator;
12
 use Illuminate\Database\Eloquent\Factories\Factory;
15
 use Illuminate\Database\Eloquent\Factories\Factory;
13
 use Illuminate\Support\Carbon;
16
 use Illuminate\Support\Carbon;
14
 
17
 
41
             'date' => $estimateDate,
44
             'date' => $estimateDate,
42
             'expiration_date' => Carbon::parse($estimateDate)->addDays($this->faker->numberBetween(14, 30)),
45
             'expiration_date' => Carbon::parse($estimateDate)->addDays($this->faker->numberBetween(14, 30)),
43
             'status' => EstimateStatus::Draft,
46
             'status' => EstimateStatus::Draft,
47
+            'discount_method' => $this->faker->randomElement(DocumentDiscountMethod::class),
48
+            'discount_computation' => AdjustmentComputation::Percentage,
49
+            'discount_rate' => function (array $attributes) {
50
+                $discountMethod = DocumentDiscountMethod::parse($attributes['discount_method']);
51
+
52
+                if ($discountMethod?->isPerDocument()) {
53
+                    return $this->faker->numberBetween(50000, 200000); // 5% - 20%
54
+                }
55
+
56
+                return 0;
57
+            },
44
             'currency_code' => function (array $attributes) {
58
             'currency_code' => function (array $attributes) {
45
                 $client = Client::find($attributes['client_id']);
59
                 $client = Client::find($attributes['client_id']);
46
 
60
 
207
 
221
 
208
         $subtotalCents = $estimate->lineItems()->sum('subtotal');
222
         $subtotalCents = $estimate->lineItems()->sum('subtotal');
209
         $taxTotalCents = $estimate->lineItems()->sum('tax_total');
223
         $taxTotalCents = $estimate->lineItems()->sum('tax_total');
210
-        $discountTotalCents = $estimate->lineItems()->sum('discount_total');
224
+
225
+        $discountTotalCents = 0;
226
+
227
+        if ($estimate->discount_method?->isPerLineItem()) {
228
+            $discountTotalCents = $estimate->lineItems()->sum('discount_total');
229
+        } elseif ($estimate->discount_method?->isPerDocument() && $estimate->discount_rate) {
230
+            if ($estimate->discount_computation?->isPercentage()) {
231
+                $scaledRate = RateCalculator::parseLocalizedRate($estimate->discount_rate);
232
+                $discountTotalCents = RateCalculator::calculatePercentage($subtotalCents, $scaledRate);
233
+            } else {
234
+                $discountTotalCents = CurrencyConverter::convertToCents($estimate->discount_rate, $estimate->currency_code);
235
+            }
236
+        }
211
 
237
 
212
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
238
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
213
         $currencyCode = $estimate->currency_code;
239
         $currencyCode = $estimate->currency_code;

+ 27
- 1
database/factories/Accounting/InvoiceFactory.php 查看文件

2
 
2
 
3
 namespace Database\Factories\Accounting;
3
 namespace Database\Factories\Accounting;
4
 
4
 
5
+use App\Enums\Accounting\AdjustmentComputation;
6
+use App\Enums\Accounting\DocumentDiscountMethod;
5
 use App\Enums\Accounting\InvoiceStatus;
7
 use App\Enums\Accounting\InvoiceStatus;
6
 use App\Enums\Accounting\PaymentMethod;
8
 use App\Enums\Accounting\PaymentMethod;
7
 use App\Models\Accounting\DocumentLineItem;
9
 use App\Models\Accounting\DocumentLineItem;
11
 use App\Models\Company;
13
 use App\Models\Company;
12
 use App\Models\Setting\DocumentDefault;
14
 use App\Models\Setting\DocumentDefault;
13
 use App\Utilities\Currency\CurrencyConverter;
15
 use App\Utilities\Currency\CurrencyConverter;
16
+use App\Utilities\RateCalculator;
14
 use Illuminate\Database\Eloquent\Factories\Factory;
17
 use Illuminate\Database\Eloquent\Factories\Factory;
15
 use Illuminate\Support\Carbon;
18
 use Illuminate\Support\Carbon;
16
 
19
 
43
             'date' => $invoiceDate,
46
             'date' => $invoiceDate,
44
             'due_date' => Carbon::parse($invoiceDate)->addDays($this->faker->numberBetween(14, 60)),
47
             'due_date' => Carbon::parse($invoiceDate)->addDays($this->faker->numberBetween(14, 60)),
45
             'status' => InvoiceStatus::Draft,
48
             'status' => InvoiceStatus::Draft,
49
+            'discount_method' => $this->faker->randomElement(DocumentDiscountMethod::class),
50
+            'discount_computation' => AdjustmentComputation::Percentage,
51
+            'discount_rate' => function (array $attributes) {
52
+                $discountMethod = DocumentDiscountMethod::parse($attributes['discount_method']);
53
+
54
+                if ($discountMethod?->isPerDocument()) {
55
+                    return $this->faker->numberBetween(50000, 200000); // 5% - 20%
56
+                }
57
+
58
+                return 0;
59
+            },
46
             'currency_code' => function (array $attributes) {
60
             'currency_code' => function (array $attributes) {
47
                 $client = Client::find($attributes['client_id']);
61
                 $client = Client::find($attributes['client_id']);
48
 
62
 
251
 
265
 
252
         $subtotalCents = $invoice->lineItems()->sum('subtotal');
266
         $subtotalCents = $invoice->lineItems()->sum('subtotal');
253
         $taxTotalCents = $invoice->lineItems()->sum('tax_total');
267
         $taxTotalCents = $invoice->lineItems()->sum('tax_total');
254
-        $discountTotalCents = $invoice->lineItems()->sum('discount_total');
268
+
269
+        $discountTotalCents = 0;
270
+
271
+        if ($invoice->discount_method?->isPerLineItem()) {
272
+            $discountTotalCents = $invoice->lineItems()->sum('discount_total');
273
+        } elseif ($invoice->discount_method?->isPerDocument() && $invoice->discount_rate) {
274
+            if ($invoice->discount_computation?->isPercentage()) {
275
+                $scaledRate = RateCalculator::parseLocalizedRate($invoice->discount_rate);
276
+                $discountTotalCents = RateCalculator::calculatePercentage($subtotalCents, $scaledRate);
277
+            } else {
278
+                $discountTotalCents = CurrencyConverter::convertToCents($invoice->discount_rate, $invoice->currency_code);
279
+            }
280
+        }
255
 
281
 
256
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
282
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
257
         $currencyCode = $invoice->currency_code;
283
         $currencyCode = $invoice->currency_code;

+ 27
- 1
database/factories/Accounting/RecurringInvoiceFactory.php 查看文件

2
 
2
 
3
 namespace Database\Factories\Accounting;
3
 namespace Database\Factories\Accounting;
4
 
4
 
5
+use App\Enums\Accounting\AdjustmentComputation;
5
 use App\Enums\Accounting\DayOfMonth;
6
 use App\Enums\Accounting\DayOfMonth;
6
 use App\Enums\Accounting\DayOfWeek;
7
 use App\Enums\Accounting\DayOfWeek;
8
+use App\Enums\Accounting\DocumentDiscountMethod;
7
 use App\Enums\Accounting\EndType;
9
 use App\Enums\Accounting\EndType;
8
 use App\Enums\Accounting\Frequency;
10
 use App\Enums\Accounting\Frequency;
9
 use App\Enums\Accounting\IntervalType;
11
 use App\Enums\Accounting\IntervalType;
15
 use App\Models\Common\Client;
17
 use App\Models\Common\Client;
16
 use App\Models\Company;
18
 use App\Models\Company;
17
 use App\Utilities\Currency\CurrencyConverter;
19
 use App\Utilities\Currency\CurrencyConverter;
20
+use App\Utilities\RateCalculator;
18
 use Illuminate\Database\Eloquent\Factories\Factory;
21
 use Illuminate\Database\Eloquent\Factories\Factory;
19
 use Illuminate\Support\Carbon;
22
 use Illuminate\Support\Carbon;
20
 
23
 
43
             'order_number' => $this->faker->unique()->numerify('ORD-####'),
46
             'order_number' => $this->faker->unique()->numerify('ORD-####'),
44
             'payment_terms' => PaymentTerms::Net30,
47
             'payment_terms' => PaymentTerms::Net30,
45
             'status' => RecurringInvoiceStatus::Draft,
48
             'status' => RecurringInvoiceStatus::Draft,
49
+            'discount_method' => $this->faker->randomElement(DocumentDiscountMethod::class),
50
+            'discount_computation' => AdjustmentComputation::Percentage,
51
+            'discount_rate' => function (array $attributes) {
52
+                $discountMethod = DocumentDiscountMethod::parse($attributes['discount_method']);
53
+
54
+                if ($discountMethod?->isPerDocument()) {
55
+                    return $this->faker->numberBetween(50000, 200000); // 5% - 20%
56
+                }
57
+
58
+                return 0;
59
+            },
46
             'currency_code' => function (array $attributes) {
60
             'currency_code' => function (array $attributes) {
47
                 $client = Client::find($attributes['client_id']);
61
                 $client = Client::find($attributes['client_id']);
48
 
62
 
301
 
315
 
302
         $subtotalCents = $recurringInvoice->lineItems()->sum('subtotal');
316
         $subtotalCents = $recurringInvoice->lineItems()->sum('subtotal');
303
         $taxTotalCents = $recurringInvoice->lineItems()->sum('tax_total');
317
         $taxTotalCents = $recurringInvoice->lineItems()->sum('tax_total');
304
-        $discountTotalCents = $recurringInvoice->lineItems()->sum('discount_total');
318
+
319
+        $discountTotalCents = 0;
320
+
321
+        if ($recurringInvoice->discount_method?->isPerLineItem()) {
322
+            $discountTotalCents = $recurringInvoice->lineItems()->sum('discount_total');
323
+        } elseif ($recurringInvoice->discount_method?->isPerDocument() && $recurringInvoice->discount_rate) {
324
+            if ($recurringInvoice->discount_computation?->isPercentage()) {
325
+                $scaledRate = RateCalculator::parseLocalizedRate($recurringInvoice->discount_rate);
326
+                $discountTotalCents = RateCalculator::calculatePercentage($subtotalCents, $scaledRate);
327
+            } else {
328
+                $discountTotalCents = CurrencyConverter::convertToCents($recurringInvoice->discount_rate, $recurringInvoice->currency_code);
329
+            }
330
+        }
305
 
331
 
306
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
332
         $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
307
         $currencyCode = $recurringInvoice->currency_code;
333
         $currencyCode = $recurringInvoice->currency_code;

正在加载...
取消
保存