Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 75
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
TransferTaskPushProductService
0.00% covered (danger)
0.00%
0 / 75
0.00% covered (danger)
0.00%
0 / 11
462
0.00% covered (danger)
0.00%
0 / 1
 push
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
6
 populateItemToTransferDTO
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 markTransferTaskProductAsPicked
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 validateTransferTaskStatus
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 findPickedItem
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 updatePickedProductStatus
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 transferItem
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
6
 handlePickedTransferTaskProduct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 validateTransferTaskProductStatus
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 validateTransferTaskProductAmount
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getExistsOtherPickedTransferTaskProductTrasferring
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Domain\TransferTask\Services;
4
5use App\Models\{Address\Address, Item\Item, TransferTask\PickedTransferTaskProduct, TransferTask\TransferTask, TransferTask\TransferTaskProduct, User};
6use App\Helper\AppHelper;
7use Domain\Address\Exceptions\AddressException;
8use Domain\Item\Exceptions\ItemNotFoundException;
9use Domain\Transaction\{Enums\TransactionOutputReasonEnum, Enums\TransactionTypeEnum};
10use Domain\Transferable\{DTOs\TransferItemDTO,
11    Exceptions\CantTransferItemException,
12    Services\TransferableTransferItemService};
13use Domain\TransferTask\{DTOs\TransferTaskPickProductDTO, Enums\PickedTransferTaskProductStatusEnum, Exceptions\PickedTransferTaskProductStatusException, Exceptions\TransferTaskStatusException};
14use Exception;
15use Illuminate\{Database\Eloquent\Builder, Support\Facades\DB};
16use Throwable;
17
18readonly class TransferTaskPushProductService
19{
20    /**
21     * @param TransferTaskPickProductDTO $transferTaskProductDTO
22     * @param Address $recipient
23     * @param User $user
24     * @return void
25     * @throws Throwable
26     */
27    public function push(TransferTaskPickProductDTO $transferTaskProductDTO, Address $recipient, User $user): void
28    {
29        try {
30            DB::beginTransaction();
31
32            // $this->validateTransferTaskProductStatus($transferTaskProductDTO->transferTaskProduct);
33            // $this->validateTransferTaskStatus($transferTaskProductDTO->transferTaskProduct->transferTask);
34
35            $pickedTransferTaskProduct = $this->findPickedItem($transferTaskProductDTO);
36
37            $itemPickedTransferTask = $pickedTransferTaskProduct->item;
38
39            // if ($this->validateTransferTaskProductAmount($pickedTransferTaskProduct, $transferTaskProductDTO)){
40            //     $pickedTransferTaskProduct->update(['item_id' => null]);
41            // }
42
43            $item = $this->transferItem(
44                $itemPickedTransferTask,
45                $this->populateItemToTransferDTO($itemPickedTransferTask, $transferTaskProductDTO->amount),
46                $recipient,
47                $user,
48                $transferTaskProductDTO->observation
49            );
50
51            $this->handlePickedTransferTaskProduct(
52                $pickedTransferTaskProduct,
53                $transferTaskProductDTO,
54                $item,
55                $user
56            );
57
58            DB::commit();
59        } catch (Throwable $throwable) {
60            DB::rollBack();
61            throw $throwable;
62        }
63    }
64
65    /**
66     * @param Item $itemToTransfer
67     * @param float $amount
68     * @param array $readingLogDTOs
69     * @return TransferItemDTO
70     */
71    private function populateItemToTransferDTO(Item $itemToTransfer, float $amount, array $readingLogDTOs = []): TransferItemDTO
72    {
73        return new TransferItemDTO([
74            'item' => $itemToTransfer,
75            'amount' => $amount,
76            'reading_logs' => $readingLogDTOs,
77        ]);
78    }
79
80    /**
81     * @param TransferTaskProduct $transferTaskProduct
82     * @return void
83     */
84    private function markTransferTaskProductAsPicked(TransferTaskProduct $transferTaskProduct): void
85    {
86        $transferTaskProduct->pick();
87        $transferTaskProduct->save();
88    }
89
90    /**
91     * @param TransferTask $transferTask
92     * @return void
93     */
94    private function validateTransferTaskStatus(TransferTask $transferTask): void
95    {
96        if ($transferTask->isPending()) {
97            $transferTask->start();
98            $transferTask->save();
99        }
100
101        if ($transferTask->isCanceled()) {
102            throw new TransferTaskStatusException(__('Task is canceled'));
103        }
104
105        if ($transferTask->isConcluded()) {
106            throw new TransferTaskStatusException(__('Task is concluded'));
107        }
108    }
109
110    /**
111     * @param TransferTaskPickProductDTO $transferTaskProductDTO
112     * @return PickedTransferTaskProduct
113     */
114    public function findPickedItem(TransferTaskPickProductDTO $transferTaskProductDTO): PickedTransferTaskProduct
115    {
116        $pickedTransferTaskProduct = $transferTaskProductDTO->transferTaskProduct->pickedTransferTaskProduct()
117            ->whereHas('item', function (Builder $builder) use ($transferTaskProductDTO) {
118                $builder->whereHas('integration', function (Builder $builder) use ($transferTaskProductDTO) {
119                    $builder->where('parameters->production_order', $transferTaskProductDTO->productionOrder);
120                });
121            })
122            ->get();
123
124        if (!$pickedTransferTaskProduct) {
125            throw new ItemNotFoundException(__('Item not found'));
126        }
127
128        if ($pickedTransferTaskProduct->pluck('status')->doesntContain(PickedTransferTaskProductStatusEnum::TRANSFERRING)) {
129            throw new PickedTransferTaskProductStatusException(__('All items already transferred'));
130        }
131
132        return $pickedTransferTaskProduct->where('status', PickedTransferTaskProductStatusEnum::TRANSFERRING)->first();
133    }
134
135    /**
136     * @param PickedTransferTaskProduct $pickedTransferTaskProduct
137     * @return void
138     */
139    private function updatePickedProductStatus(PickedTransferTaskProduct $pickedTransferTaskProduct): void
140    {
141        $pickedTransferTaskProduct->pick();
142        $pickedTransferTaskProduct->save();
143    }
144
145    /**
146     * @param PickedTransferTaskProduct $pickedTransferTaskProduct
147     * @param TransferItemDTO $itemToTransferDTO
148     * @param Address $recipient
149     * @param User $user
150     * @return Item
151     * @throws Exception
152     */
153    private function transferItem(Item $item, TransferItemDTO $itemToTransferDTO, Address $recipient, User $user, ?string $observation = null): Item
154    {
155        $address = $item->itemable;
156        if (!$address instanceof Address) {
157            throw new AddressException(__('The sender is not an Address'));
158        }
159
160        return (new TransferableTransferItemService())->transferOne(
161            $itemToTransferDTO,
162            $address,
163            $recipient,
164            TransactionTypeEnum::TRANSFER,
165            TransactionOutputReasonEnum::PRE_ORDER->value,
166            $user,
167            $observation,
168            $address->sector->value
169        );
170    }
171
172    /**
173     * @param PickedTransferTaskProduct $pickedTransferTaskProduct
174     * @param TransferTaskPickProductDTO $transferTaskProductDTO
175     * @param Item $item
176     * @param User $user
177     * @return void
178     */
179    private function handlePickedTransferTaskProduct(PickedTransferTaskProduct $pickedTransferTaskProduct, TransferTaskPickProductDTO $transferTaskProductDTO, Item $item, User $user): void
180    {
181        if ($this->validateTransferTaskProductAmount($pickedTransferTaskProduct, $transferTaskProductDTO)) {
182            $this->updatePickedProductStatus($pickedTransferTaskProduct);
183            if ($this->getExistsOtherPickedTransferTaskProductTrasferring($transferTaskProductDTO)){
184                $this->markTransferTaskProductAsPicked($transferTaskProductDTO->transferTaskProduct);
185            }
186        } else {
187            (new PickedTransferTaskProductStoreService())->store($transferTaskProductDTO, $item, $user, 'pick');
188            $pickedTransferTaskProduct->setAttribute('amount', round($pickedTransferTaskProduct->getAttribute('amount') - $transferTaskProductDTO->amount, 2));
189            $pickedTransferTaskProduct->save();
190        }
191    }
192
193    /**
194     * @param TransferTaskProduct $transferTaskProduct
195     * @return void
196     */
197    public function validateTransferTaskProductStatus(TransferTaskProduct $transferTaskProduct): void
198    {
199        if ($transferTaskProduct->isPicked()) {
200            throw new CantTransferItemException(__('Product is already picked'));
201        }
202    }
203
204    public function validateTransferTaskProductAmount(PickedTransferTaskProduct $pickedTransferTaskProduct, TransferTaskPickProductDTO $transferTaskProductDTO): bool
205    {
206        return $pickedTransferTaskProduct->getAttribute('amount') == $transferTaskProductDTO->amount;
207    }
208
209    public function getExistsOtherPickedTransferTaskProductTrasferring(TransferTaskPickProductDTO $transferTaskProductDTO): bool
210    {
211        $transferTaskProducts = $transferTaskProductDTO->transferTaskProduct->pickedTransferTaskProduct()
212            ->where('status', PickedTransferTaskProductStatusEnum::TRANSFERRING)
213            ->get();
214
215        return $transferTaskProducts->isEmpty();
216    }
217}