Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
6.59% covered (danger)
6.59%
6 / 91
14.29% covered (danger)
14.29%
1 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
RequestStoreService
6.59% covered (danger)
6.59%
6 / 91
14.29% covered (danger)
14.29%
1 / 7
198.36
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
 store
4.44% covered (danger)
4.44%
2 / 45
0.00% covered (danger)
0.00%
0 / 1
26.81
 ensureRequesterAccess
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 authenticateRequesterInSenior
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
1.04
 populateExportDTO
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
6
 fetchUser
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 processRequestLog
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Domain\Request\Services;
4
5use App\Events\ServiceProcessed;
6use App\Jobs\Senior\SeniorSyncRequestsJob;
7use App\Models\Request\Request;
8use App\Models\Request\RequestItem;
9use App\Models\User;
10use Carbon\Carbon;
11use Domain\Login\Integrations\AuthenticateSenior;
12use Domain\Request\DTOs\ExportRequestSeniorDTO;
13use Domain\Request\DTOs\RequestDTO;
14use Domain\Request\DTOs\RequestItemDTO;
15use Domain\Request\DTOs\RequestLogStoreDTO;
16use Domain\Request\Enums\RequestLogOperationEnum;
17use Domain\Request\Enums\RequestStatusEnum;
18use Domain\Request\Support\OriginTransactionCodeResolver;
19use Domain\Shared\Integrations\Senior\Exceptions\IntegrationSoapSeniorException;
20use Domain\Shared\Integrations\Senior\SeniorCredentialResolver;
21use Domain\Shared\Integrations\Senior\SeniorRequestExport;
22use Domain\User\Services\ImportSeniorUSerService;
23use Illuminate\Auth\Access\AuthorizationException;
24use Illuminate\Support\Facades\DB;
25use Throwable;
26
27readonly class RequestStoreService
28{
29    private User $user;
30
31    public function __construct(
32        User $user
33    )
34    {
35        $this->user = $user;
36    }
37
38    /**
39     * @param RequestDTO $requestDTO
40     * @return Request
41     * @throws IntegrationSoapSeniorException
42     * @throws Throwable
43     */
44    public function store(RequestDTO $requestDTO): Request
45    {
46        $this->ensureRequesterAccess();
47        $this->authenticateRequesterInSenior();
48
49        try {
50            DB::beginTransaction();
51
52            $this->fetchUser();
53
54            $requester = $requestDTO->requester ?? $this->user;
55
56            $request = new Request();
57            $request->fill($requestDTO->toArray());
58            $request->requester()->associate($requester);
59            $request->costCenter()->associate($requestDTO->costCenter);
60            $request->resourceCenter()->associate($requestDTO->resourceCenter);
61            $request->setAttribute('status', RequestStatusEnum::PENDING);
62
63            $request->setAttribute('applicant', json_encode([
64                'badge' => $requestDTO->applicant_badge,
65                'name'  => $requestDTO->applicant_name ?? null,
66            ]));
67
68            $request->setAttribute('resource', json_encode([
69                'code'        => $requestDTO->resource_code,
70                'description' => $requestDTO->resource_description ?? null,
71            ]));
72
73            $request->save();
74
75            $createdItems = [];
76            foreach($requestDTO->items as $item){
77                $createdItems[] = (new RequestItemStoreService())->store(
78                    RequestItemDTO::fromArray($item),
79                    $request,
80                    $this->user
81                );
82            }
83
84            $seniorRequestResponse = null;
85            foreach ($createdItems as $item) {
86                if (is_null($seniorRequestResponse)) {
87                    $seniorRequestResponse = (new SeniorRequestExport())->execute(
88                        $this->populateExportDTO($request, $item)
89                    );
90                } else {
91                    $seniorRequestResponse = (new SeniorRequestExport())->execute(
92                        $this->populateExportDTO($request, $item, $seniorRequestResponse->numEme)
93                    );
94                }
95
96                dispatch_sync(new SeniorSyncRequestsJob($seniorRequestResponse->numEme, $request, false));
97            }
98
99            $request->refresh();
100
101            $this->processRequestLog($request, $this->user);
102
103            DB::commit();
104        } catch (Throwable $exception) {
105            DB::rollBack();
106            throw $exception;
107        }
108
109        ServiceProcessed::dispatch(self::class, $this->user);
110        return $request;
111    }
112
113    /**
114     * @throws AuthorizationException
115     */
116    private function ensureRequesterAccess(): void
117    {
118        if (! $this->user->hasWarehouseRequesterAccess()) {
119            throw new AuthorizationException(__('This action is unauthorized'));
120        }
121    }
122
123    /**
124     * @throws IntegrationSoapSeniorException
125     * @throws \SoapFault
126     */
127    private function authenticateRequesterInSenior(): void
128    {
129        ['user' => $username, 'password' => $password] = (new SeniorCredentialResolver())
130            ->resolveForAuthenticatedUser($this->user);
131
132        AuthenticateSenior::login($username, $password);
133    }
134
135    /**
136     * @param Request $request
137     * @param RequestItem $requestItem
138     * @param int|null $numEme
139     * @return ExportRequestSeniorDTO
140     */
141    private function populateExportDTO(Request $request, RequestItem $requestItem, int $numEme = null): ExportRequestSeniorDTO
142    {
143        $requestId = $request->getKey();
144        $origin = $requestItem->product->family->origin;
145        $transactionCode = (new OriginTransactionCodeResolver())->forRequest($origin);
146
147        $newRequestItems[] = [
148            'codPro' => $requestItem->product->integration->getAttribute('parameters')['integration_product'],
149            'codDer' => $requestItem->product->integration->getAttribute('parameters')['integration_derivation'],
150            'qtdEme' => $requestItem->getAttribute('amount'),
151            'datEme' => Carbon::now()->format('d/m/Y'),
152            'ccuRes' => $requestItem->request->costCenter->integration->getAttribute('parameters')['cost_center_code'],
153            'obsEme' => '',
154            'codTns' => $transactionCode,
155        ];
156
157        if (isset($request->requester->getAttribute('integrations')['senior']['user_code'])) {
158            $usuSol = $request->requester->getAttribute('integrations')['senior']['user_code'];
159        }
160
161        return new ExportRequestSeniorDTO([
162            'identificadorSistema' => 'SOELX',
163            'codEmp'               => 1,
164            'codFil'               => 1,
165            'numEme'               => $numEme,
166            'tipoProcessamento'    => 1,
167            'itens'                => $newRequestItems,
168            'identificadorExterno' => $requestId,
169            'tipoOperacao'         => 'R',
170            'usuSol'               => $usuSol ?? null,
171            'usuRes'               => $usuSol ?? null,
172        ]);
173    }
174
175    /**
176     * @return void
177     * @throws IntegrationSoapSeniorException
178     */
179    private function fetchUser(): void
180    {
181        $seniorData = $this->user->integrations['senior'] ?? [];
182        $username = (new SeniorCredentialResolver())->resolveUsername($this->user);
183
184        if (empty($seniorData['user_code']) && !empty($username)) {
185            (new ImportSeniorUSerService())->import($username, 'username', $this->user);
186
187            $this->user->refresh();
188        }
189    }
190
191    /**
192     * @param Request $request
193     * @param User $user
194     * @return void
195     */
196    private function processRequestLog(
197        Request $request,
198        User $user): void
199    {
200        $RequestLogStoreDTO = new RequestLogStoreDTO([
201            'request'     => $request,
202            'stockIO'     => $request->stockIo,
203            'operation'   => RequestLogOperationEnum::STORED_REQUEST,
204            'user'        => $user,
205            'detail'      => $request->makeHidden('stockIO')->toJson(),
206            'observation' => "Requisição inserida: ". $request->getKey(),
207        ]);
208
209        (new RequestLogStoreService())->store($RequestLogStoreDTO, $user);
210    }
211}