Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
71.70% covered (warning)
71.70%
76 / 106
11.11% covered (danger)
11.11%
1 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
PickingOrderQueryBuilder
71.70% covered (warning)
71.70%
76 / 106
11.11% covered (danger)
11.11%
1 / 9
55.21
0.00% covered (danger)
0.00%
0 / 1
 visibleTo
92.11% covered (success)
92.11%
35 / 38
0.00% covered (danger)
0.00%
0 / 1
5.01
 onlyConcluded
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 withoutConcluded
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 onlySeparated
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 withoutSeparated
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 search
77.42% covered (warning)
77.42%
24 / 31
0.00% covered (danger)
0.00%
0 / 1
11.15
 hasStockIOFilters
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 applyStockIOFilters
42.86% covered (danger)
42.86%
6 / 14
0.00% covered (danger)
0.00%
0 / 1
9.66
 filterByPickingOrderDates
63.64% covered (warning)
63.64%
7 / 11
0.00% covered (danger)
0.00%
0 / 1
4.77
1<?php
2
3namespace Domain\StockIO\QueryBuilders;
4
5use App\Models\User;
6use Carbon\Carbon;
7use Domain\PickingOrder\DTOs\PickingOrderSearchDTO;
8use Domain\PickingOrder\Enums\PickingOrderStatusEnum;
9use Domain\Shared\Enums\SectorEnum;
10use Domain\User\Enums\AccessLevel;
11use Illuminate\Database\Eloquent\Builder;
12use function collect;
13
14class PickingOrderQueryBuilder extends Builder
15{
16    public function visibleTo(?User $user = null): static
17    {
18        if ($user->hasAccess(AccessLevel::SEPARATOR->value)) {
19            $this->where(function ($query) use ($user) {
20                $query->where('picking_orders.responsible_id', '=', $user->getKey());
21            });
22        }
23
24        if ($user->hasAccess(AccessLevel::ADMIN->value) || $user->hasAccess(AccessLevel::MASTER->value)) {
25            if ($user->currentSector() == SectorEnum::EXPEDITION->value) {
26                $teamIds = $user->teams->pluck('id');
27
28                $this->where(function (Builder $query) use ($teamIds) {
29                    $query->where(function (Builder $directStockIOQuery) use ($teamIds) {
30                        $directStockIOQuery
31                            ->whereNotNull('picking_orders.stock_io_id')
32                            ->whereHas('stockIO', function (Builder $stockIOQuery) use ($teamIds) {
33                                $stockIOQuery->whereIn('team_id', $teamIds);
34                            });
35                    })->orWhere(function (Builder $indirectStockIOQuery) use ($teamIds) {
36                        $indirectStockIOQuery
37                            ->whereNull('picking_orders.stock_io_id')
38                            ->whereHas('stockIOProducts.stockIO', function (Builder $stockIOQuery) use ($teamIds) {
39                                $stockIOQuery->whereIn('team_id', $teamIds);
40                            });
41                    });
42                });
43            } else {
44                $this->where(function (Builder $query) {
45                    $query->where(function (Builder $directStockIOQuery) {
46                        $directStockIOQuery
47                            ->whereNotNull('picking_orders.stock_io_id')
48                            ->whereHas('stockIO', function (Builder $stockIOQuery) {
49                                $stockIOQuery->where('sector', SectorEnum::WAREHOUSE->value);
50                            });
51                    })->orWhere(function (Builder $indirectStockIOQuery) {
52                        $indirectStockIOQuery
53                            ->whereNull('picking_orders.stock_io_id')
54                            ->whereHas('stockIOProducts.stockIO', function (Builder $stockIOQuery) {
55                                $stockIOQuery->where('sector', SectorEnum::WAREHOUSE->value);
56                            });
57                    });
58                });
59            }
60        }
61
62        return $this;
63    }
64
65    public function onlyConcluded(): static
66    {
67        $this->where('picking_orders.status', PickingOrderStatusEnum::CONCLUDED->value);
68
69        return $this;
70    }
71
72    public function withoutConcluded(): static
73    {
74        $this->where('picking_orders.status', '!=', PickingOrderStatusEnum::CONCLUDED->value);
75
76        return $this;
77    }
78
79    public function onlySeparated(): static
80    {
81        $this->where('picking_orders.status', PickingOrderStatusEnum::SEPARATED->value);
82
83        return $this;
84    }
85
86    public function withoutSeparated(): static
87    {
88        $this->where('picking_orders.status', '!=', PickingOrderStatusEnum::SEPARATED->value);
89
90        return $this;
91    }
92
93    public function search(PickingOrderSearchDTO $pickingOrderSearchDTO, string $conditional = 'and'): static
94    {
95        if ($pickingOrderSearchDTO->pickingOrderSearchDateEnum) {
96            $this->where('picking_orders.created_at', '>=', Carbon::now()->subDays($pickingOrderSearchDTO->pickingOrderSearchDateEnum->value));
97        }
98
99        if ($pickingOrderSearchDTO->responsible->isNotEmpty()) {
100            $this->whereIn('picking_orders.responsible_id', $pickingOrderSearchDTO->responsible->values());
101        }
102
103        if ($pickingOrderSearchDTO->status->isNotEmpty()) {
104            $this->whereIn('picking_orders.status', $pickingOrderSearchDTO->status->values());
105        }
106
107        if ($this->hasStockIOFilters($pickingOrderSearchDTO)) {
108            $this->where(function (Builder $query) use ($pickingOrderSearchDTO) {
109                $query->where(function (Builder $directStockIOQuery) use ($pickingOrderSearchDTO) {
110                    $directStockIOQuery
111                        ->whereNotNull('picking_orders.stock_io_id')
112                        ->whereHas('stockIO', function (Builder $queryStockIO) use ($pickingOrderSearchDTO) {
113                            $this->applyStockIOFilters($queryStockIO, $pickingOrderSearchDTO);
114                        });
115                })->orWhere(function (Builder $indirectStockIOQuery) use ($pickingOrderSearchDTO) {
116                    $indirectStockIOQuery
117                        ->whereNull('picking_orders.stock_io_id')
118                        ->whereHas('stockIOProducts.stockIO', function (Builder $queryStockIO) use ($pickingOrderSearchDTO) {
119                            $this->applyStockIOFilters($queryStockIO, $pickingOrderSearchDTO);
120                        });
121                    });
122                });
123        }
124
125        if ($conditional === 'or') {
126            if ($pickingOrderSearchDTO->startDate || $pickingOrderSearchDTO->endDate || $pickingOrderSearchDTO->createdDate) {
127                $this->where(function (Builder $query) use ($pickingOrderSearchDTO, $conditional) {
128                    $this->filterByPickingOrderDates($pickingOrderSearchDTO, $query, $conditional);
129                });
130            }
131        } else {
132            $this->filterByPickingOrderDates($pickingOrderSearchDTO, $this, $conditional);
133        }
134
135        if($pickingOrderSearchDTO->id) {
136            $this->where('picking_orders.id', $pickingOrderSearchDTO->id);
137        }
138
139        return $this;
140    }
141
142    private function hasStockIOFilters(PickingOrderSearchDTO $pickingOrderSearchDTO): bool
143    {
144        return $pickingOrderSearchDTO->type
145            || $pickingOrderSearchDTO->stockIOId
146            || $pickingOrderSearchDTO->preInvoice
147            || $pickingOrderSearchDTO->customer->isNotEmpty();
148    }
149
150    private function applyStockIOFilters(Builder $queryStockIO, PickingOrderSearchDTO $pickingOrderSearchDTO): void
151    {
152        if ($pickingOrderSearchDTO->type) {
153            $queryStockIO->where('type', $pickingOrderSearchDTO->type);
154        }
155
156        if ($pickingOrderSearchDTO->stockIOId) {
157            $queryStockIO->whereKey($pickingOrderSearchDTO->stockIOId);
158        }
159
160        if ($pickingOrderSearchDTO->preInvoice) {
161            $queryStockIO->whereHas('integration', function (Builder $queryIntegration) use ($pickingOrderSearchDTO) {
162                $preInvoices = collect($pickingOrderSearchDTO->preInvoice);
163                $queryIntegration->whereIn('parameters->NUMPFA', $preInvoices->pluck('pre_invoice'));
164                $queryIntegration->whereIn('parameters->NUMANE', $preInvoices->pluck('load'));
165            });
166        }
167
168        if ($pickingOrderSearchDTO->customer->isNotEmpty()) {
169            $queryStockIO->whereHas('integration', function (Builder $queryIntegration) use ($pickingOrderSearchDTO) {
170                $queryIntegration->whereIn('parameters->CODCLI', $pickingOrderSearchDTO->customer->values());
171            });
172        }
173    }
174
175    /**
176     * @param PickingOrderSearchDTO $pickingOrderSearchDTO
177     * @param Builder $query
178     * @param string $conditional
179     * @return void
180     */
181    private function filterByPickingOrderDates(PickingOrderSearchDTO $pickingOrderSearchDTO, Builder $query, string $conditional): void
182    {
183        $filters = [
184            'start_date'  => $pickingOrderSearchDTO->startDate,
185            'end_date'    => $pickingOrderSearchDTO->endDate,
186            'created_at'  => $pickingOrderSearchDTO->createdDate,
187        ];
188
189        foreach ($filters as $column => $dates){
190            if($dates) {
191                $query->{$conditional === 'or' ? 'orWhereBetween' : 'whereBetween'}("picking_orders.$column",[
192                    $dates[0]->startOfDay(),
193                    $dates[1]->endOfDay()
194                ]);
195            }
196        }
197    }
198}