Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
36.36% covered (danger)
36.36%
8 / 22
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ShippingPackagingTransferService
36.36% covered (danger)
36.36%
8 / 22
20.00% covered (danger)
20.00%
1 / 5
35.77
0.00% covered (danger)
0.00%
0 / 1
 transfer
50.00% covered (danger)
50.00%
6 / 12
0.00% covered (danger)
0.00%
0 / 1
2.50
 assertProductIsNotCanceled
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 assertSufficientAmount
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 updateSenderPackingProduct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 removeEmptyShippingPackaging
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace Domain\ShippingPackaging\Services;
4
5use App\Events\ServiceProcessed;
6use App\Models\ShippingPackaging\ShippingPackaging;
7use App\Models\ShippingPackaging\ShippingPackagingProduct;
8use App\Models\User;
9use App\Helper\AppHelper;
10use Domain\ShippingPackaging\DTOs\ShippingPackagingTransferDTO;
11use Domain\ShippingPackaging\Exceptions\ShippingPackingException;
12use Illuminate\Support\Facades\DB;
13use Throwable;
14
15readonly class ShippingPackagingTransferService
16{
17    /**
18     * @param ShippingPackagingTransferDTO $packagingTransferDTO
19     * @param ShippingPackaging $receiver
20     * @param User $user
21     * @return void
22     * @throws Throwable
23     */
24    public function transfer(ShippingPackagingTransferDTO $packagingTransferDTO, ShippingPackaging $receiver, User $user): void
25    {
26        try {
27            DB::beginTransaction();
28
29            $shippingPackagingProduct = $packagingTransferDTO->shippingPackagingProduct;
30            $this->assertProductIsNotCanceled($shippingPackagingProduct);
31            $this->assertSufficientAmount($shippingPackagingProduct, $packagingTransferDTO->amount);
32
33            (new ShippingPackagingAddProductService())->updateOrCreateProduct($packagingTransferDTO->amount, $receiver, $shippingPackagingProduct->pickedItem);
34
35            $this->updateSenderPackingProduct($shippingPackagingProduct, $packagingTransferDTO->amount);
36
37            $this->removeEmptyShippingPackaging($shippingPackagingProduct->shippingPackaging, $user);
38
39            DB::commit();
40        } catch (Throwable $throwable) {
41            DB::rollBack();
42            throw $throwable;
43        }
44
45        ServiceProcessed::dispatch(self::class, $user);
46    }
47
48    private function assertProductIsNotCanceled(ShippingPackagingProduct $shippingPackagingProduct): void
49    {
50        if ($shippingPackagingProduct->isCanceled()) {
51            throw new ShippingPackingException(__('Canceled product cannot be transferred'));
52        }
53    }
54
55    /**
56     * @param $shippingPackagingProduct
57     * @param $amount
58     * @return void
59     */
60    private function assertSufficientAmount($shippingPackagingProduct, $amount): void
61    {
62        if (!$shippingPackagingProduct->hasAmount($amount)) {
63            throw new ShippingPackingException(__('Quantity exceeds total available'));
64        }
65    }
66
67    /**
68     * @param ShippingPackagingProduct $shippingPackagingProduct
69     * @param float $amount
70     * @return void
71     */
72    private function updateSenderPackingProduct(ShippingPackagingProduct $shippingPackagingProduct, float $amount): void
73    {
74        $shippingPackagingProduct->setAttribute('amount', round($shippingPackagingProduct->getAttribute('amount') - $amount, 2));
75
76        if ($shippingPackagingProduct->getAttribute('amount') == 0) {
77            $shippingPackagingProduct->delete();
78        } else {
79            $shippingPackagingProduct->save();
80        }
81    }
82
83    /**
84     * @param $shippingPackaging
85     * @param User $user
86     * @return void
87     * @throws Throwable
88     */
89    private function removeEmptyShippingPackaging($shippingPackaging, User $user): void
90    {
91        if ($shippingPackaging->products()->doesntExist()) {
92            (new ShippingPackagingDeleteService())->delete($shippingPackaging, $user);
93        }
94    }
95}