Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.33% covered (warning)
83.33%
40 / 48
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
DiscountRatesApiController
82.98% covered (warning)
82.98%
39 / 47
66.67% covered (warning)
66.67%
4 / 6
11.60
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 list
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
3.10
 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
45.45% covered (danger)
45.45%
5 / 11
0.00% covered (danger)
0.00%
0 / 1
2.65
 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\Discount\Presentation\Api;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Modules\Discount\Application\DTO\DiscountRateDto;
12use App\Modules\Discount\Application\Service\DiscountApplicationService;
13use App\Modules\Discount\Domain\Model\DiscountRate;
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 discount rates (/api/v1/discounts).
22 */
23final readonly class DiscountRatesApiController
24{
25    use ApiResponseTrait;
26
27    /**
28     * DiscountRatesApiController constructor.
29     */
30    public function __construct(
31        private DiscountApplicationService $discountService,
32        private Psr17Factory $psr17Factory,
33    ) {
34    }
35
36    /**
37     * List all discount rates (GET /api/v1/discounts).
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['discount_type'])) {
48            $filters['discount_type'] = (string) $params['discount_type'];
49        }
50
51        $rates = $this->discountService->getDiscounts($filters);
52        $data = array_map(static fn(DiscountRate $r): array => $r->toArray(), $rates);
53
54        return $this->jsonResponse($this->psr17Factory, ['success' => true, 'data' => $data]);
55    }
56
57    /**
58     * Get single discount rate (GET /api/v1/discounts/{id:\d+}).
59     */
60    public function detail(ServerRequestInterface $request): ResponseInterface
61    {
62        $id = (int) ($request->getAttribute('id') ?? 0);
63        $rate = $this->discountService->getDiscount($id);
64
65        if ($rate === null) {
66            return $this->jsonResponse(
67                $this->psr17Factory,
68                ['success' => false, 'error' => 'Discount 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 discount rate (POST /api/v1/discounts).
78     */
79    public function create(ServerRequestInterface $request): ResponseInterface
80    {
81        $body = $this->parseJsonBody($request);
82
83        try {
84            $dto = DiscountRateDto::fromArray($body);
85            $saved = $this->discountService->saveDiscount($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 discount rate (PUT /api/v1/discounts/{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 = DiscountRateDto::fromArray($body, $id);
111            $saved = $this->discountService->saveDiscount($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 discount rate (DELETE /api/v1/discounts/{id:\d+}).
125     */
126    public function delete(ServerRequestInterface $request): ResponseInterface
127    {
128        $id = (int) ($request->getAttribute('id') ?? 0);
129        $success = $this->discountService->deleteDiscount($id);
130
131        return $this->jsonResponse($this->psr17Factory, ['success' => $success]);
132    }
133}