Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
30.00% covered (danger)
30.00%
75 / 250
29.41% covered (danger)
29.41%
5 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
StockIOQueryBuilder
30.00% covered (danger)
30.00%
75 / 250
29.41% covered (danger)
29.41%
5 / 17
1900.85
0.00% covered (danger)
0.00%
0 / 1
 visibleTo
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 searchInput
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
42
 searchInputConcluded
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
72
 searchOutputOnJoinedIntegration
47.22% covered (danger)
47.22%
17 / 36
0.00% covered (danger)
0.00%
0 / 1
48.08
 searchOutput
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 1
240
 searchOutputRequest
70.15% covered (warning)
70.15%
47 / 67
0.00% covered (danger)
0.00%
0 / 1
19.21
 onlyInputs
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 onlyOutputs
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 withoutConcluded
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 onlyProductionOrder
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 onlyPreInvoice
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 onlyRequests
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 withoutSync
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 onlyConcluded
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 findByProductOrder
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 onlyTeam
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 bySector
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Domain\StockIO\QueryBuilders;
4
5use App\Models\User;
6use Domain\StockIO\DTOs\SearchStockInputDTO;
7use Domain\StockIO\DTOs\SearchStockOutputDTO;
8use Domain\StockIO\DTOs\SearchStockOutputRequestDTO;
9use Domain\StockIO\Enums\StockInputReasonEnum;
10use Domain\StockIO\Enums\StockOutputReasonEnum;
11use Domain\StockIO\Enums\StockStatusEnum;
12use Domain\StockIO\Enums\StockTypeEnum;
13use Domain\User\Enums\AccessLevel;
14use Illuminate\Database\Eloquent\Builder;
15
16/**
17 * @method StockIOQueryBuilder toSync()
18 */
19class StockIOQueryBuilder extends Builder
20{
21    /**
22     * @param User|null $user
23     * @return $this
24     */
25    public function visibleTo(?User $user = null): static
26    {
27        if ($user->hasAccess(AccessLevel::SEPARATOR->value) || $user->hasAccess(AccessLevel::STORER->value)) {
28            $this->where(function ($query) use ($user) {
29                $query->where('responsible_id', '=', $user->getKey());
30            });
31        }
32
33        return $this;
34    }
35
36    /**
37     * @param SearchStockInputDTO $searchStockInputDTO
38     * @return $this
39     */
40    public function searchInput(SearchStockInputDTO $searchStockInputDTO): static
41    {
42
43        $this->whereHas('stockIOProducts', function (Builder $query) use ($searchStockInputDTO) {
44            $query->whereHas('pickedItems', function (Builder $query) use ($searchStockInputDTO) {
45                $query->whereHas('item', function (Builder $queryItem) use ($searchStockInputDTO) {
46                    if ($searchStockInputDTO->integrationProduct) {
47                        $queryItem->whereHas('product', function ($queryProduct) use ($searchStockInputDTO) {
48                            $queryProduct->whereHas('integration', function ($queryIntegration) use ($searchStockInputDTO) {
49                                $queryIntegration->where('parameters->integration_product', '=', $searchStockInputDTO->integrationProduct);
50                            });
51                        });
52                    }
53
54                    if ($searchStockInputDTO->integrationDerivation) {
55                        $queryItem->whereHas('product', function ($queryProduct) use ($searchStockInputDTO) {
56                            $queryProduct->whereHas('integration', function ($queryIntegration) use ($searchStockInputDTO) {
57                                $queryIntegration->where('parameters->integration_derivation', '=', $searchStockInputDTO->integrationDerivation);
58                            });
59                        });
60                    }
61
62                    if ($searchStockInputDTO->integrationBarcode) {
63                        $queryItem->whereHas('product', function ($queryProduct) use ($searchStockInputDTO) {
64                            $queryProduct->whereHas('integration', function ($queryIntegration) use ($searchStockInputDTO) {
65                                $queryIntegration->where('parameters->integration_barcode', '=', $searchStockInputDTO->integrationBarcode);
66                            });
67                        });
68                    }
69
70                    if ($searchStockInputDTO->integrationCompany) {
71                        $queryItem->whereHas('product', function ($queryProduct) use ($searchStockInputDTO) {
72                            $queryProduct->whereHas('integration', function ($queryIntegration) use ($searchStockInputDTO) {
73                                $queryIntegration->where('parameters->integration_company', '=', $searchStockInputDTO->integrationCompany);
74                            });
75                        });
76                    }
77
78                    if ($searchStockInputDTO->productionOrder) {
79                        $this->whereHas('integration', function (Builder $query) use ($searchStockInputDTO) {
80                            $query->where('parameters->production_order', $searchStockInputDTO->productionOrder);
81                        });
82                    }
83                });
84            });
85        });
86
87
88        return $this;
89    }
90
91    public function searchInputConcluded(SearchStockInputDTO $searchStockInputDTO): static
92    {
93
94        $this->whereHas('transferable', function (Builder $builderTransferable) use ($searchStockInputDTO) {
95            if ($searchStockInputDTO->integrationProduct) {
96                $builderTransferable->whereHas('transactionsFrom', function (Builder $query) use ($searchStockInputDTO) {
97                    $query->where('item->product->integration->parameters->integration_product', '=', $searchStockInputDTO->integrationProduct);
98                });
99            }
100
101            if ($searchStockInputDTO->integrationDerivation) {
102                $builderTransferable->whereHas('transactionsFrom', function (Builder $query) use ($searchStockInputDTO) {
103                    $query->where('item->product->integration->parameters->integration_derivation', '=', $searchStockInputDTO->integrationDerivation);
104                });
105            }
106
107            if ($searchStockInputDTO->integrationBarcode) {
108                $builderTransferable->whereHas('transactionsFrom', function (Builder $query) use ($searchStockInputDTO) {
109                    $query->where('item->product->integration->parameters->integration_barcode', '=', $searchStockInputDTO->integrationBarcode);
110                });
111            }
112
113            if ($searchStockInputDTO->integrationCompany) {
114                $builderTransferable->whereHas('transactionsFrom', function (Builder $query) use ($searchStockInputDTO) {
115                    $query->where('item->product->integration->parameters->integration_company', '=', $searchStockInputDTO->integrationCompany);
116                });
117            }
118
119            if ($searchStockInputDTO->integrationCode) {
120                $builderTransferable->whereHas('transactionsFrom', function (Builder $query) use ($searchStockInputDTO) {
121                    $query->where('item->product->integration->parameters->integration_code', '=', $searchStockInputDTO->integrationCode);
122                });
123            }
124
125            if ($searchStockInputDTO->movementDate) {
126                $builderTransferable->whereHas('transactionsFrom', function (Builder $query) use ($searchStockInputDTO) {
127                    $query->whereBetween('item->integration->parameters->movement_date', [
128                        $searchStockInputDTO->movementDate[0]->startOfDay()->format('Y-m-d\TH:i:s'),
129                        $searchStockInputDTO->movementDate[1]->endOfDay()->format('Y-m-d\TH:i:s'),
130                    ]);
131                });
132            }
133
134        });
135
136        if ($searchStockInputDTO->productionOrder) {
137            $this->whereHas('integration', function (Builder $query) use ($searchStockInputDTO) {
138                $query->where('parameters->production_order', $searchStockInputDTO->productionOrder);
139            });
140        }
141
142        return $this;
143    }
144
145    /**
146     * @param SearchStockOutputDTO $searchStockOutputDTO
147     * @return $this
148     */
149    public function searchOutputOnJoinedIntegration(SearchStockOutputDTO $searchStockOutputDTO): static
150    {
151        if ($searchStockOutputDTO->clientCode) {
152            $this->where('integrations.parameters->CODCLI', $searchStockOutputDTO->clientCode);
153        }
154
155        if ($searchStockOutputDTO->shipmentAnalysisNumber) {
156            $this->where('integrations.parameters->NUMANE', $searchStockOutputDTO->shipmentAnalysisNumber);
157        }
158
159        if ($searchStockOutputDTO->proformaInvoice) {
160            $this->where('integrations.parameters->NUMPFA', $searchStockOutputDTO->proformaInvoice);
161        }
162
163        if ($searchStockOutputDTO->invoicing) {
164            $this->whereBetween('integrations.parameters->PRVFAT', [
165                $searchStockOutputDTO->invoicing[0]->startOfDay()->format('Y-m-d\TH:i:s'),
166                $searchStockOutputDTO->invoicing[1]->endOfDay()->format('Y-m-d\TH:i:s'),
167            ]);
168        }
169
170        if ($searchStockOutputDTO->orderNumber) {
171            $this->whereHas('stockIOProducts', function (Builder $query) use ($searchStockOutputDTO) {
172                $query->whereHas('integration', function (Builder $query) use ($searchStockOutputDTO) {
173                    $query->where('parameters->NUMPED', $searchStockOutputDTO->orderNumber);
174                });
175            });
176        }
177
178        if ($searchStockOutputDTO->urgent) {
179            $this->where('urgent', $searchStockOutputDTO->urgent);
180        }
181
182        if ($searchStockOutputDTO->start_date) {
183            $this->where('stock_ios.created_at', '>=', $searchStockOutputDTO->start_date->startOfDay());
184        }
185
186        if ($searchStockOutputDTO->end_date) {
187            $this->where('stock_ios.created_at', '<=', $searchStockOutputDTO->end_date->endOfDay());
188        }
189
190        if ($searchStockOutputDTO->status) {
191            $this->whereIn('status', $searchStockOutputDTO->status);
192        }
193
194        if ($searchStockOutputDTO->id) {
195            $this->where('stock_ios.id', $searchStockOutputDTO->id);
196        }
197
198        if (isset($searchStockOutputDTO->allItemsInTask)) {
199            if ($searchStockOutputDTO->allItemsInTask == 1) {
200                $this->whereRaw('(SELECT count(1) FROM picking_orders WHERE stock_ios.id = picking_orders.stock_io_id) = 0');
201            } elseif ($searchStockOutputDTO->allItemsInTask == 2) {
202                $this->whereRaw('(SELECT count(1) FROM picking_orders WHERE stock_ios.id = picking_orders.stock_io_id) > 0');
203            } elseif ($searchStockOutputDTO->allItemsInTask == 3) {
204                $this->whereRaw('(SELECT count(1)
205                                    FROM stock_io_products
206                                   WHERE stock_ios.id = stock_io_products.stock_io_id) = (SELECT count(1)
207                                                                                            FROM picking_orders
208                                                                                           WHERE stock_ios.id = picking_orders.stock_io_id
209                                                                                             AND EXISTS (SELECT 1
210                                                                                                           FROM stock_io_products
211                                                                                                          INNER JOIN picking_order_products ON stock_io_products.id = picking_order_products.stock_io_product_id
212                                                                                                          WHERE picking_orders.id = picking_order_products.picking_order_id
213                                                                                                          ORDER BY stock_io_products.id ASC))');
214            }
215        }
216
217        return $this;
218    }
219
220    public function searchOutput(SearchStockOutputDTO $searchStockOutputDTO): static
221    {
222        if ($searchStockOutputDTO->clientCode) {
223            $this->whereHas('integration', function (Builder $query) use ($searchStockOutputDTO) {
224                $query->where('parameters->CODCLI', $searchStockOutputDTO->clientCode);
225            });
226        }
227
228        if ($searchStockOutputDTO->shipmentAnalysisNumber) {
229            $this->whereHas('integration', function (Builder $query) use ($searchStockOutputDTO) {
230                $query->where('parameters->NUMANE', $searchStockOutputDTO->shipmentAnalysisNumber);
231            });
232        }
233
234        if ($searchStockOutputDTO->proformaInvoice) {
235            $this->whereHas('integration', function (Builder $query) use ($searchStockOutputDTO) {
236                $query->where('parameters->NUMPFA', $searchStockOutputDTO->proformaInvoice);
237            });
238        }
239
240        if ($searchStockOutputDTO->invoicing) {
241            $this->whereHas('integration', function (Builder $query) use ($searchStockOutputDTO) {
242                $query->whereBetween('parameters->PRVFAT', [
243                    $searchStockOutputDTO->invoicing[0]->startOfDay()->format('Y-m-d\TH:i:s'),
244                    $searchStockOutputDTO->invoicing[1]->endOfDay()->format('Y-m-d\TH:i:s'),
245                ]);
246            });
247        }
248
249        if ($searchStockOutputDTO->orderNumber) {
250            $this->whereHas('stockIOProducts', function (Builder $query) use ($searchStockOutputDTO) {
251                $query->whereHas('integration', function (Builder $query) use ($searchStockOutputDTO) {
252                    $query->where('parameters->NUMPED', $searchStockOutputDTO->orderNumber);
253                });
254            });
255        }
256
257        if ($searchStockOutputDTO->urgent) {
258            $this->where('urgent', $searchStockOutputDTO->urgent);
259        }
260
261        if ($searchStockOutputDTO->start_date) {
262            $this->where('stock_ios.created_at', '>=', $searchStockOutputDTO->start_date->startOfDay());
263        }
264
265        if ($searchStockOutputDTO->end_date) {
266            $this->where('stock_ios.created_at', '<=', $searchStockOutputDTO->end_date->endOfDay());
267        }
268        if ($searchStockOutputDTO->status) {
269            $this->whereIn('status', $searchStockOutputDTO->status);
270        }
271        if ($searchStockOutputDTO->id) {
272            $this->where('stock_ios.id', $searchStockOutputDTO->id);
273        }
274
275        if (isset($searchStockOutputDTO->allItemsInTask)) {
276            if($searchStockOutputDTO->allItemsInTask == 1){
277                $this->whereRaw('(SELECT count(1) FROM picking_orders WHERE stock_ios.id = picking_orders.stock_io_id) = 0');
278            } elseif($searchStockOutputDTO->allItemsInTask == 2) {
279                $this->whereRaw('(SELECT count(1) FROM picking_orders WHERE stock_ios.id = picking_orders.stock_io_id) > 0');
280            } elseif($searchStockOutputDTO->allItemsInTask == 3) {
281                $this->whereRaw('(SELECT count(1)
282                                    FROM stock_io_products
283                                   WHERE stock_ios.id = stock_io_products.stock_io_id) = (SELECT count(1)
284                                                                                            FROM picking_orders
285                                                                                           WHERE stock_ios.id = picking_orders.stock_io_id
286                                                                                             AND EXISTS (SELECT 1
287                                                                                                           FROM stock_io_products
288                                                                                                          INNER JOIN picking_order_products ON stock_io_products.id = picking_order_products.stock_io_product_id
289                                                                                                          WHERE picking_orders.id = picking_order_products.picking_order_id
290                                                                                                          ORDER BY stock_io_products.id ASC))');
291            }
292        }
293
294        return $this;
295    }
296
297    /**
298     * @param SearchStockOutputRequestDTO $searchStockOutputRequestDTO
299     * @return $this
300     */
301    public function searchOutputRequest(SearchStockOutputRequestDTO $searchStockOutputRequestDTO): static
302    {
303        if ($searchStockOutputRequestDTO->id) {
304            $this->where('stock_ios.id', $searchStockOutputRequestDTO->id);
305        }
306
307        if ($searchStockOutputRequestDTO->created_at) {
308            $this->whereBetween('stock_ios.created_at', [
309                $searchStockOutputRequestDTO->created_at[0]->startOfDay(),
310                $searchStockOutputRequestDTO->created_at[1]->endOfDay(),
311            ]);
312        }
313
314        if ($searchStockOutputRequestDTO->requester) {
315            $this->whereHas('integration', function (Builder $query) use ($searchStockOutputRequestDTO) {
316                $query->whereRaw("parameters->>'request_user' IN (
317                    SELECT users.integrations->'senior'->>'user_code'
318                    FROM users
319                    WHERE users.name ILIKE ?
320                    AND users.deleted_at IS NULL
321                )", ['%' . $searchStockOutputRequestDTO->requester . '%']);
322            });
323
324        }
325
326        if ($searchStockOutputRequestDTO->status) {
327            $this->whereIn('status', $searchStockOutputRequestDTO->status);
328        }
329
330        if ($searchStockOutputRequestDTO->cost_center) {
331            $this->whereHas('request', function (Builder $query) use ($searchStockOutputRequestDTO) {
332                $query->where('cost_center_id', $searchStockOutputRequestDTO->cost_center->getKey());
333            });
334        }
335
336        if ($searchStockOutputRequestDTO->start_date) {
337            $this->where('stock_ios.start_date', '>=', $searchStockOutputRequestDTO->start_date->startOfDay());
338        }
339
340        if ($searchStockOutputRequestDTO->end_date) {
341            $this->where('stock_ios.end_date', '<=', $searchStockOutputRequestDTO->end_date->endOfDay());
342        }
343
344        if ($searchStockOutputRequestDTO->product_code) {
345            $this->whereHas('stockIOProducts', function (Builder $query) use ($searchStockOutputRequestDTO) {
346                $query->whereHas('integration', function (Builder $query) use ($searchStockOutputRequestDTO) {
347                    $query->where('parameters->product_code', $searchStockOutputRequestDTO->product_code);
348                });
349            });
350        }
351
352        if ($searchStockOutputRequestDTO->request_number) {
353            $this->whereHas('integration', function (Builder $query) use ($searchStockOutputRequestDTO) {
354                $query->where('parameters->request_number', $searchStockOutputRequestDTO->request_number);
355            });
356        }
357
358        if (!is_null($searchStockOutputRequestDTO->has_purchase_solicitation)) {
359            $purchaseSolicitationCondition = "NULLIF(BTRIM(COALESCE(parameters->>'purchase_solicitation_number', '')), '') IS NOT NULL
360                AND BTRIM(COALESCE(parameters->>'purchase_solicitation_number', '')) <> '0'";
361            $legacySolicitationCondition = "NULLIF(BTRIM(COALESCE(parameters->>'solicitation_number', '')), '') IS NOT NULL
362                AND BTRIM(COALESCE(parameters->>'solicitation_number', '')) <> '0'";
363
364            if ($searchStockOutputRequestDTO->has_purchase_solicitation) {
365                $this->where(function (Builder $query) use ($purchaseSolicitationCondition, $legacySolicitationCondition) {
366                    $query->whereHas('stockIOProducts.integration', function (Builder $integrationQuery) use ($purchaseSolicitationCondition) {
367                        $integrationQuery->whereRaw($purchaseSolicitationCondition);
368                    })->orWhereHas('integration', function (Builder $integrationQuery) use ($legacySolicitationCondition) {
369                        $integrationQuery->whereRaw($legacySolicitationCondition);
370                    });
371                });
372            } else {
373                $this->whereDoesntHave('stockIOProducts.integration', function (Builder $integrationQuery) use ($purchaseSolicitationCondition) {
374                    $integrationQuery->whereRaw($purchaseSolicitationCondition);
375                })->whereDoesntHave('integration', function (Builder $integrationQuery) use ($legacySolicitationCondition) {
376                    $integrationQuery->whereRaw($legacySolicitationCondition);
377                });
378            }
379        }
380
381        if ($searchStockOutputRequestDTO->product) {
382            $product = $searchStockOutputRequestDTO->product;
383
384            $this->whereHas('stockIOProducts', function (Builder $query) use ($product) {
385                $query->whereHas('product', function (Builder $query) use ($product) {
386                    $query->where(function (Builder $query) use ($product) {
387                        if (is_numeric($product)) {
388                            $query->orWhere('products.id', (int) $product);
389                        }
390
391                        $query->orWhere('products.description', 'ILIKE', '%' . $product . '%')
392                            ->orWhereHas('integration', function (Builder $query) use ($product) {
393                                $query->whereRaw("parameters->>'integration_product' ILIKE ?", ['%' . $product . '%']);
394                            });
395                    });
396                })->orWhereHas('integration', function (Builder $query) use ($product) {
397                    $query->whereRaw("parameters->>'product_code' ILIKE ?", ['%' . $product . '%']);
398                });
399            });
400        }
401
402        return $this;
403    }
404
405    /**
406     * @return $this
407     */
408    public function onlyInputs(): static
409    {
410        $this->where('type', '=', StockTypeEnum::INPUT->value);
411
412        return $this;
413    }
414
415    /**
416     * @return $this
417     */
418    public function onlyOutputs(): static
419    {
420        $this->where('type', '=', StockTypeEnum::OUTPUT->value);
421
422        return $this;
423    }
424
425    /**
426     * @return $this
427     */
428    public function withoutConcluded(): static
429    {
430        $this->where('status', '!=', StockStatusEnum::CONCLUDED->value);
431
432        return $this;
433    }
434
435    /**
436     * @return $this
437     */
438    public function onlyProductionOrder(): static
439    {
440        $this->where('reason', '=', StockInputReasonEnum::PRODUCTION_ORDER->value);
441
442        return $this;
443    }
444
445    /**
446     * @return $this
447     */
448    public function onlyPreInvoice(): static
449    {
450        $this->where('reason', '=', StockOutputReasonEnum::PRE_INVOICE->value);
451
452        return $this;
453    }
454
455    public function onlyRequests(): static
456    {
457        $this->whereIn('reason', [
458                StockOutputReasonEnum::SYNCED_REQUEST,
459                StockOutputReasonEnum::REQUEST
460            ]);
461
462        return $this;
463    }
464
465
466    public function withoutSync(): static
467    {
468        $this->whereNotIn('status', [StockStatusEnum::SYNCING->value, StockStatusEnum::SYNC_FAIL->value]);
469
470        return $this;
471    }
472
473    /**
474     * @return $this
475     */
476    public function onlyConcluded(): static
477    {
478        $this->where('stock_ios.status', '=', StockStatusEnum::CONCLUDED->value);
479
480        return $this;
481    }
482
483    /**
484     * @param string $productOrder
485     * @return $this
486     */
487    public function findByProductOrder(string $productOrder): static
488    {
489        $this->whereHas('integration', function (Builder $query) use ($productOrder) {
490            $query->where('parameters->production_order', $productOrder);
491        });
492
493        return $this;
494    }
495
496    /**
497     * @param User $user
498     * @return $this
499     */
500    public function onlyTeam(User $user): static
501    {
502        if (!$user->isMaster()) {
503            $this->whereIn('team_id', $user->teams?->pluck('id')->values());
504        }
505
506        return $this;
507    }
508
509    /**
510     * @param User $user
511     * @return $this
512     */
513    public function bySector(User $user)
514    {
515        $sector = $user->currentSector();
516
517        $this->where('stock_ios.sector', $sector);
518
519        return $this;
520    }
521}