Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
69.57% covered (warning)
69.57%
16 / 23
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ShippingPackagingAddProductService
69.57% covered (warning)
69.57%
16 / 23
16.67% covered (danger)
16.67%
1 / 6
14.41
0.00% covered (danger)
0.00%
0 / 1
 execute
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 validateDtoInstance
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 checkShippingPackagingState
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 validateItemAmount
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 handlePausedPackaging
33.33% covered (danger)
33.33%
1 / 3
0.00% covered (danger)
0.00%
0 / 1
3.19
 updateOrCreateProduct
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
2.06
1<?php
2
3namespace Domain\ShippingPackaging\Services;
4
5use App\Events\ServiceProcessed;
6use App\Models\PickedItem;
7use App\Models\ShippingPackaging\ShippingPackaging;
8use App\Models\ShippingPackaging\ShippingPackagingProduct;
9use App\Models\User;
10use App\Helper\AppHelper;
11use Domain\Shared\Interfaces\DataTransferObjectInterface;
12use Domain\ShippingPackaging\DTOs\ShippingPackagingAddProductDTO;
13use Domain\ShippingPackaging\Exceptions\ShippingPackingException;
14use DomainException;
15
16readonly class ShippingPackagingAddProductService
17{
18    /**
19     * @param ShippingPackagingAddProductDTO $dto
20     * @param ShippingPackaging $shippingPackaging
21     * @param PickedItem $pickedItem
22     * @param User $user
23     * @return void
24     */
25    public function execute(DataTransferObjectInterface $dto, ShippingPackaging $shippingPackaging, PickedItem $pickedItem, User $user): void
26    {
27        $this->validateDtoInstance($dto);
28        $this->checkShippingPackagingState($shippingPackaging);
29
30        $this->validateItemAmount($dto, $pickedItem);
31
32        $this->handlePausedPackaging($shippingPackaging, $user);
33
34        $this->updateOrCreateProduct($dto->amount, $shippingPackaging, $pickedItem);
35
36        ServiceProcessed::dispatch(self::class, $user);
37    }
38
39    private function validateDtoInstance(DataTransferObjectInterface $dto): void
40    {
41        if (!$dto instanceof ShippingPackagingAddProductDTO) {
42            throw new DomainException(__('The DTO is not from a valid instance'));
43        }
44    }
45
46    private function checkShippingPackagingState(ShippingPackaging $shippingPackaging): void
47    {
48        if ($shippingPackaging->isFinished()) {
49            throw new ShippingPackingException(__('Shipping packaging is finished'));
50        }
51    }
52
53    private function validateItemAmount(ShippingPackagingAddProductDTO $dto, PickedItem $fetchedItem): void
54    {
55        if ($dto->amount > $fetchedItem->getAttribute('amount')) {
56            throw new ShippingPackingException(__('Quantity ordered exceeds item availability'));
57        }
58    }
59
60    private function handlePausedPackaging(ShippingPackaging $shippingPackaging, User $user): void
61    {
62        if ($shippingPackaging->isPaused()) {
63            $shippingPackagingService = new ShippingPackagingStartService();
64            $shippingPackagingService->pause($shippingPackaging, $user);
65        }
66    }
67
68    public function updateOrCreateProduct(float $amount, ShippingPackaging $shippingPackaging, PickedItem $pickedItem): void
69    {
70        $existingProduct = $shippingPackaging->products()->where('picked_item_id', $pickedItem->getKey())->first();
71        if ($existingProduct) {
72            $existingProduct->setAttribute('amount', round($existingProduct->getAttribute('amount') + $amount, 2));
73            $existingProduct->save();
74        } else {
75            $newProduct = new ShippingPackagingProduct();
76            $newProduct->pickedItem()->associate($pickedItem);
77            $newProduct->setAttribute('amount', $amount);
78            $shippingPackaging->products()->save($newProduct);
79        }
80    }
81}