Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
CalculateDocumentRequest
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
2 / 2
9
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromArray
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Modules\Tax\Application\DTO;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11/**
12 * Data Transfer Object for simulating or calculating multi-item document taxes.
13 */
14final readonly class CalculateDocumentRequest
15{
16    /**
17     * CalculateDocumentRequest constructor.
18     *
19     * @param array<int, array{
20     *     unit_price: float,
21     *     quantity: float,
22     *     discount?: float,
23     *     tax_rate_id?: int,
24     *     tax_code?: string,
25     *     cost_price?: float|null,
26     *     item_type?: string
27     * }> $items
28     * @param string $customerType
29     * @param string $geoZone
30     * @param float $globalDiscount
31     * @param float $shippingNet
32     * @param int|null $shippingTaxRateId
33     * @param float $returnableDeposits
34     * @param string $roundingStrategy
35     * @param string $roundingMethod
36     */
37    public function __construct(
38        public array $items = [],
39        public string $customerType = 'all',
40        public string $geoZone = 'domestic',
41        public float $globalDiscount = 0.0,
42        public float $shippingNet = 0.0,
43        public ?int $shippingTaxRateId = null,
44        public float $returnableDeposits = 0.0,
45        public string $roundingStrategy = 'line_level',
46        public string $roundingMethod = 'half_up',
47    ) {
48    }
49
50    /**
51     * Create DTO from request payload.
52     *
53     * @param array<string, mixed> $data
54     */
55    public static function fromArray(array $data): self
56    {
57        $rawItems = isset($data['items']) && is_array($data['items']) ? $data['items'] : [];
58        $items = [];
59
60        foreach ($rawItems as $raw) {
61            $items[] = [
62                'unit_price' => (float) ($raw['unit_price'] ?? 0.0),
63                'quantity' => (float) ($raw['quantity'] ?? 1.0),
64                'discount' => (float) ($raw['discount'] ?? 0.0),
65                'tax_rate_id' => isset($raw['tax_rate_id']) ? (int) $raw['tax_rate_id'] : null,
66                'tax_code' => isset($raw['tax_code']) ? (string) $raw['tax_code'] : null,
67                'cost_price' => isset($raw['cost_price']) ? (float) $raw['cost_price'] : null,
68                'item_type' => (string) ($raw['item_type'] ?? 'product'),
69            ];
70        }
71
72        return new self(
73            items: $items,
74            customerType: (string) ($data['customer_type'] ?? 'all'),
75            geoZone: (string) ($data['geo_zone'] ?? 'domestic'),
76            globalDiscount: (float) ($data['global_discount'] ?? 0.0),
77            shippingNet: (float) ($data['shipping_net'] ?? 0.0),
78            shippingTaxRateId: isset($data['shipping_tax_rate_id']) ? (int) $data['shipping_tax_rate_id'] : null,
79            returnableDeposits: (float) ($data['returnable_deposits'] ?? 0.0),
80            roundingStrategy: (string) ($data['rounding_strategy'] ?? 'line_level'),
81            roundingMethod: (string) ($data['rounding_method'] ?? 'half_up'),
82        );
83    }
84}