Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
78.12% covered (warning)
78.12%
25 / 32
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
AddressUpdateOrderService
78.12% covered (warning)
78.12%
25 / 32
0.00% covered (danger)
0.00%
0 / 1
6.38
0.00% covered (danger)
0.00%
0 / 1
 updateOrder
78.12% covered (warning)
78.12%
25 / 32
0.00% covered (danger)
0.00%
0 / 1
6.38
1<?php
2
3namespace Domain\Address\Services;
4
5use App\Events\ServiceProcessed;
6use App\Models\Address\Address;
7use App\Models\User;
8use Exception;
9use Illuminate\Support\Facades\DB;
10
11readonly class AddressUpdateOrderService
12{
13    /**
14     * @param Address $address
15     * @param User $user
16     * @return void
17     * @throws Exception
18     */
19    public function updateOrder(Address $address, User $user): void
20    {
21        $newOrder = $address->getAttribute('order') ??
22            (Address::query()->where('parent_id', '=', $address->parent?->getKey())->max('order') ?? 1) + 1;
23        $oldOrder = $address->getOriginal('order');
24
25        try {
26            DB::beginTransaction();
27
28            if ($address->exists) {
29                $address->update(['order' => 0]);
30            }
31
32            $builder = Address::query()
33                ->where('parent_id', $address->parent?->getKey())
34                ->where('id', '!=', $address->getKey())
35                ->withTrashed();
36            if (!$address->exists || ($oldOrder > $newOrder)) {
37                if (!$address->exists) {
38                    $builder->where('order', '>=', $newOrder);
39                } else {
40                    $builder->whereBetween('order', [$newOrder, $oldOrder - 1]);
41                }
42                $builder->orderByDesc('order');
43                $builder->each(function (Address $address) {
44                    $address->setAttribute('order', $address->getAttribute('order') + 1);
45                    $address->save();
46                });
47            } else {
48                $builder
49                    ->whereBetween('order', [$oldOrder + 1, $newOrder])
50                    ->orderBy('order')
51                    ->each(function (Address $address) {
52                        $address->setAttribute('order', $address->getAttribute('order') - 1);
53                        $address->save();
54                    });
55            }
56
57            $address->setAttribute('order', $newOrder);
58
59            DB::commit();
60        } catch (Exception $exception) {
61            DB::rollBack();
62            throw $exception;
63        }
64
65        ServiceProcessed::dispatch(self::class, $user);
66    }
67}