Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
48 / 48
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
TaxRatesApiController
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
6 / 6
11
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
 list
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
 detail
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 create
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 update
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 delete
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
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\Presentation\Api;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Modules\Tax\Application\DTO\TaxRateDto;
12use App\Modules\Tax\Application\Service\TaxApplicationService;
13use App\Modules\Tax\Domain\Model\TaxRate;
14use App\Shared\Infrastructure\Http\ApiResponseTrait;
15use Nyholm\Psr7\Factory\Psr17Factory;
16use Psr\Http\Message\ResponseInterface;
17use Psr\Http\Message\ServerRequestInterface;
18use Throwable;
19
20/**
21 * REST API controller for managing tax rates.
22 */
23final readonly class TaxRatesApiController
24{
25    use ApiResponseTrait;
26
27    /**
28     * TaxRatesApiController constructor.
29     */
30    public function __construct(
31        private TaxApplicationService $taxService,
32        private Psr17Factory $psr17Factory,
33    ) {
34    }
35
36    /**
37     * List all tax rates (GET /api/v1/tax/rates).
38     */
39    public function list(ServerRequestInterface $request): ResponseInterface
40    {
41        $params = $request->getQueryParams();
42        $filters = [];
43
44        if (isset($params['is_active'])) {
45            $filters['is_active'] = (int) $params['is_active'];
46        }
47        if (!empty($params['tax_status'])) {
48            $filters['tax_status'] = (string) $params['tax_status'];
49        }
50
51        $rates = $this->taxService->getTaxRates($filters);
52        $data = array_map(static fn(TaxRate $r): array => $r->toArray(), $rates);
53
54        return $this->jsonResponse($this->psr17Factory, ['success' => true, 'data' => $data]);
55    }
56
57    /**
58     * Get single tax rate (GET /api/v1/tax/rates/{id:\d+}).
59     */
60    public function detail(ServerRequestInterface $request): ResponseInterface
61    {
62        $id = (int) ($request->getAttribute('id') ?? 0);
63        $rate = $this->taxService->getTaxRate($id);
64
65        if ($rate === null) {
66            return $this->jsonResponse(
67                $this->psr17Factory,
68                ['success' => false, 'error' => 'Tax rate not found.'],
69                404
70            );
71        }
72
73        return $this->jsonResponse($this->psr17Factory, ['success' => true, 'data' => $rate->toArray()]);
74    }
75
76    /**
77     * Create new tax rate (POST /api/v1/tax/rates).
78     */
79    public function create(ServerRequestInterface $request): ResponseInterface
80    {
81        $body = $this->parseJsonBody($request);
82
83        try {
84            $dto = TaxRateDto::fromArray($body);
85            $saved = $this->taxService->saveTaxRate($dto);
86
87            return $this->jsonResponse(
88                $this->psr17Factory,
89                ['success' => true, 'data' => $saved->toArray()],
90                201
91            );
92        } catch (Throwable $e) {
93            return $this->jsonResponse(
94                $this->psr17Factory,
95                ['success' => false, 'error' => $e->getMessage()],
96                400
97            );
98        }
99    }
100
101    /**
102     * Update existing tax rate (PUT /api/v1/tax/rates/{id:\d+}).
103     */
104    public function update(ServerRequestInterface $request): ResponseInterface
105    {
106        $id = (int) ($request->getAttribute('id') ?? 0);
107        $body = $this->parseJsonBody($request);
108
109        try {
110            $dto = TaxRateDto::fromArray($body, $id);
111            $saved = $this->taxService->saveTaxRate($dto);
112
113            return $this->jsonResponse($this->psr17Factory, ['success' => true, 'data' => $saved->toArray()]);
114        } catch (Throwable $e) {
115            return $this->jsonResponse(
116                $this->psr17Factory,
117                ['success' => false, 'error' => $e->getMessage()],
118                400
119            );
120        }
121    }
122
123    /**
124     * Delete tax rate (DELETE /api/v1/tax/rates/{id:\d+}).
125     */
126    public function delete(ServerRequestInterface $request): ResponseInterface
127    {
128        $id = (int) ($request->getAttribute('id') ?? 0);
129        $success = $this->taxService->deleteTaxRate($id);
130
131        return $this->jsonResponse($this->psr17Factory, ['success' => $success]);
132    }
133}