Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

InvoiceTotalViewModel.php 2.9KB

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