Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

InvoiceTotalViewModel.php 2.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. <?php
  2. namespace App\View\Models;
  3. use App\Enums\Accounting\AdjustmentComputation;
  4. use App\Models\Accounting\Adjustment;
  5. use App\Models\Accounting\Invoice;
  6. use App\Utilities\Currency\CurrencyConverter;
  7. class InvoiceTotalViewModel
  8. {
  9. public function __construct(
  10. public ?Invoice $invoice,
  11. public ?array $data = null
  12. ) {}
  13. public function buildViewData(): array
  14. {
  15. $lineItems = collect($this->data['lineItems'] ?? []);
  16. $subtotal = $lineItems->sum(function ($item) {
  17. $quantity = max((float) ($item['quantity'] ?? 0), 0);
  18. $unitPrice = max((float) ($item['unit_price'] ?? 0), 0);
  19. return $quantity * $unitPrice;
  20. });
  21. $taxTotal = $lineItems->reduce(function ($carry, $item) {
  22. $quantity = max((float) ($item['quantity'] ?? 0), 0);
  23. $unitPrice = max((float) ($item['unit_price'] ?? 0), 0);
  24. $salesTaxes = $item['salesTaxes'] ?? [];
  25. $lineTotal = $quantity * $unitPrice;
  26. $taxAmount = Adjustment::whereIn('id', $salesTaxes)
  27. ->pluck('rate')
  28. ->sum(fn ($rate) => $lineTotal * ($rate / 100));
  29. return $carry + $taxAmount;
  30. }, 0);
  31. // Calculate discount based on method
  32. $discountMethod = $this->data['discount_method'] ?? 'line_items';
  33. if ($discountMethod === 'line_items') {
  34. $discountTotal = $lineItems->reduce(function ($carry, $item) {
  35. $quantity = max((float) ($item['quantity'] ?? 0), 0);
  36. $unitPrice = max((float) ($item['unit_price'] ?? 0), 0);
  37. $salesDiscounts = $item['salesDiscounts'] ?? [];
  38. $lineTotal = $quantity * $unitPrice;
  39. $discountAmount = Adjustment::whereIn('id', $salesDiscounts)
  40. ->pluck('rate')
  41. ->sum(fn ($rate) => $lineTotal * ($rate / 100));
  42. return $carry + $discountAmount;
  43. }, 0);
  44. } else {
  45. $discountComputation = $this->data['discount_computation'] ?? AdjustmentComputation::Percentage;
  46. $discountRate = (float) ($this->data['discount_rate'] ?? 0);
  47. if ($discountComputation === AdjustmentComputation::Percentage) {
  48. $discountTotal = $subtotal * ($discountRate / 100);
  49. } else {
  50. $discountTotal = $discountRate;
  51. }
  52. }
  53. $grandTotal = $subtotal + ($taxTotal - $discountTotal);
  54. return [
  55. 'subtotal' => CurrencyConverter::formatToMoney($subtotal),
  56. 'taxTotal' => CurrencyConverter::formatToMoney($taxTotal),
  57. 'discountTotal' => CurrencyConverter::formatToMoney($discountTotal),
  58. 'grandTotal' => CurrencyConverter::formatToMoney($grandTotal),
  59. ];
  60. }
  61. }