Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
PickingOrderProductSyncService
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 5
156
0.00% covered (danger)
0.00%
0 / 1
 sync
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
30
 getStockIOProductAmount
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 verifyStockProductAmountExceeded
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 linkPickedItemsWithPickingOrderProducts
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 processInvoiceLog
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace Domain\PickingOrder\Services\V2;
4
5use Illuminate\Support\Facades\DB;
6
7use App\Events\ServiceProcessed;
8use App\Models\PickingOrder\PickingOrder;
9use App\Models\StockIO\StockIO;
10use App\Models\StockIO\StockIOProduct;
11use App\Models\User;
12
13use Domain\PickingOrder\Enums\PickingOrderStatusEnum;
14use Domain\Request\DTOs\RequestLogStoreDTO;
15use Domain\Request\Enums\RequestLogOperationEnum;
16use Domain\Request\Services\RequestLogStoreService;
17use Domain\StockIO\Exceptions\StockIOProductAmountExceededException;
18
19readonly class PickingOrderProductSyncService
20{
21
22    /**
23     * @param array $stockIOProducts
24     * @param PickingOrder $pickingOrder
25     * @param User $user
26     * @param bool $syncPickedItems
27     * @return void
28     */
29    public function sync(array $stockIOProducts, PickingOrder $pickingOrder, User $user, bool $syncPickedItems): void
30    {
31        foreach ($stockIOProducts as $stockIOProduct) {
32            $existingStockIOProducts = DB::table('picking_order_products')
33                ->where('status', '<>', PickingOrderStatusEnum::CONCLUDED->value)
34                ->where('stock_io_product_id', $stockIOProduct['id'])
35                ->get();
36
37            $amount = isset($stockIOProduct['amount']) && !is_null($stockIOProduct['amount']) ?
38                $stockIOProduct['amount'] :
39                $this->getStockIOProductAmount($stockIOProduct['id']);
40
41            $this->verifyStockProductAmountExceeded($stockIOProduct, $amount + $existingStockIOProducts->sum('amount'));
42
43            $syncData[$stockIOProduct['id']] = [
44                'type' => $stockIOProduct['type'],
45                'status' => PickingOrderStatusEnum::PENDING->value,
46                'amount' => $amount,
47            ];
48        }
49
50        $pickingOrder->stockIOProducts()->sync($syncData);
51
52        if ($syncPickedItems)
53            $this->linkPickedItemsWithPickingOrderProducts($pickingOrder);
54
55        $this->processInvoiceLog($stockIOProducts, $pickingOrder, $user);
56
57        ServiceProcessed::dispatch(self::class, $user);
58    }
59
60    /**
61     * @param int $stockIOProductId
62     * @return float
63     */
64    private function getStockIOProductAmount(int $stockIOProductId): float
65    {
66        return (StockIOProduct::query()
67            ->where('id', $stockIOProductId)
68            ->select('amount')
69            ->first())->amount;
70    }
71
72    /**
73     * @param array $stockIOProduct
74     * @param float $amount
75     */
76    private function verifyStockProductAmountExceeded(array $stockIOProduct, float $amount): void
77    {
78        $stockProduct = StockIOProduct::find($stockIOProduct['id']);
79
80        if ($stockProduct->getAttribute('amount') < $amount) {
81            throw new StockIOProductAmountExceededException(
82                __('The amount informed exceed the stockIO product amount :stockIOProduct',
83                   ['stockIOProduct' => $stockIOProduct['id']]
84                )
85            );
86        }
87    }
88
89    /**
90     * @param PickingOrder $pickingOrder
91     */
92    private function linkPickedItemsWithPickingOrderProducts(PickingOrder $pickingOrder): void
93    {
94        $pickingOrder->pickingOrderProduct()->each(function ($pickingOrderProduct) {
95            $pickingOrderProduct->stockIOProduct->pickedItems()->each(function ($pickedItem) use ($pickingOrderProduct) {
96                $pickedItem->pickingOrderProduct()->associate($pickingOrderProduct);
97                $pickedItem->save();
98            });
99        });
100    }
101
102    /**
103     * @param array $stockIOProducts
104     * @param PickingOrder $pickingOrder
105     * @param User $user
106     */
107    private function processInvoiceLog(array $stockIOProducts, PickingOrder $pickingOrder, User $user): void
108    {
109        $stockIOs = StockIO::query()
110            ->whereHas('stockIOProducts', function ($builder) use ($stockIOProducts){
111                $builder->whereIn('stock_io_products.id', collect($stockIOProducts)->pluck('id'));
112            })
113            ->get('id')
114            ->keyBy('id');
115
116
117        foreach ($stockIOs as $stockIO) {
118            $requestLogStoreDTO = new RequestLogStoreDTO([
119                'request'     => $stockIO->request ? $stockIO->request : null,
120                'stockIO'     => $stockIO,
121                'operation'   => RequestLogOperationEnum::CREATED_PICKING_ORDER,
122                'user'        => $user,
123                'detail'      => $pickingOrder->toJson(),
124                'observation' => "Tarefa de separação inserida: ". $pickingOrder->getKey(),
125            ]);
126
127            (new RequestLogStoreService())->store($requestLogStoreDTO, $user);
128        }
129    }
130}