Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
30.93% covered (danger)
30.93%
30 / 97
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ShippingPackReportService
30.93% covered (danger)
30.93%
30 / 97
25.00% covered (danger)
25.00%
1 / 4
59.45
0.00% covered (danger)
0.00%
0 / 1
 complete
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 summarized
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 generateShippingPackagingReport
27.42% covered (danger)
27.42%
17 / 62
0.00% covered (danger)
0.00%
0 / 1
32.47
 getOrderDetails
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace Domain\ShippingPackaging\Reports;
4
5use App\Events\ServiceProcessed;
6use App\Helper\AppHelper;
7use App\Models\PickingOrder\PickingOrder;
8use App\Models\ShippingPackaging\ShippingPackaging;
9use App\Models\ShippingPackaging\ShippingPackagingProduct;
10use App\Models\StockIO\StockIO;
11use App\Models\User;
12use Carbon\Carbon;
13use Domain\Shared\Integrations\Senior\Exceptions\IntegrationSoapSeniorException;
14use Domain\Shared\Integrations\Senior\SeniorPreOrder;
15use Domain\StockIO\DTOs\SeniorPreOrderDTO;
16use Domain\StockIO\Enums\StockProductStatusEnum;
17use Illuminate\Database\Eloquent\Builder;
18use Illuminate\Support\Facades\Auth;
19use Illuminate\Support\Facades\Cache;
20
21class ShippingPackReportService
22{
23
24    public function complete(ShippingPackaging $shippingPackaging, User $user): array
25    {
26
27        $preInvoices = $this->generateShippingPackagingReport($shippingPackaging);
28
29        ServiceProcessed::dispatch(self::class, $user);
30        return [
31            'shippingPacking' => $shippingPackaging,
32            'preInvoices' => $preInvoices,
33            'now' => Carbon::now()->format('d/m/Y H:i'),
34            'generatedBy' => Auth::user()?->getAttribute('name') ?? '-',
35            'qrcode' => json_encode([
36                'type' => 'shipping_packaging',
37                'id' => $shippingPackaging->getKey()
38            ]),
39            'withItems' => true,
40        ];
41    }
42
43    /**
44     * @param ShippingPackaging $shippingPackaging
45     * @param User $user
46     * @return array
47     */
48    public function summarized(ShippingPackaging $shippingPackaging, User $user): array
49    {
50        $preInvoices = $this->generateShippingPackagingReport($shippingPackaging);
51
52        ServiceProcessed::dispatch(self::class, $user);
53        return [
54            'shippingPacking' => $shippingPackaging,
55            'preInvoices' => $preInvoices,
56            'now' => Carbon::now()->format('d/m/Y H:i'),
57            'generatedBy' => Auth::user()?->getAttribute('name') ?? '-',
58            'qrcode' => json_encode([
59                'type' => 'shipping_packaging',
60                'id' => $shippingPackaging->getKey()
61            ]),
62            'withItems' => false,
63        ];
64    }
65
66    /**
67     * @param ShippingPackaging $shippingPackaging
68     * @return array
69     */
70    private function generateShippingPackagingReport(ShippingPackaging $shippingPackaging): array
71    {
72        $shippingPackaging->load([
73            'products' => function ($query) {
74                $query->whereDoesntHave('pickedItem.stockIOProduct', function ($subQuery) {
75                    $subQuery->where('stock_io_products.status', StockProductStatusEnum::CANCELED);
76                });
77            },
78            'products.pickedItem.item.itemable.integration',
79            'products.pickedItem.item.product.measure',
80            'products.pickedItem.item.product.integration',
81            'products.pickedItem.item.product.unitMeasurement',
82            'products.pickedItem.stockIOProduct.integration',
83        ]);
84
85        $preInvoices = [];
86        $customerCache = [];
87
88        foreach ($shippingPackaging->products as $product) {
89            /** @var StockIO $output */
90            $output = $product->pickedItem->item->itemable;
91            $parameters = $output->integration->getAttribute('parameters');
92            $preInvoiceKey = "{$parameters['NUMANE']}/{$parameters['NUMPFA']}";
93
94            // Cache de clientes para evitar múltiplas chamadas
95            if (!isset($customerCache[$parameters['CODCLI']])) {
96                $customerCache[$parameters['CODCLI']] = Cache::remember(
97                    'customer_' . $parameters['CODCLI'],
98                    10,
99                    fn() => AppHelper::fetchCustomer($parameters['CODCLI'])
100                );
101            }
102
103            // Encontrar ou criar a pré-fatura no array
104            if (!isset($preInvoices[$preInvoiceKey])) {
105                $preInvoices[$preInvoiceKey] = [
106                    'pre-invoice' => $preInvoiceKey,
107                    'data-faturamento' => $parameters['PRVFAT'] ?? '',
108                    'customer' => $customerCache[$parameters['CODCLI']],
109                    'weight' => $parameters['PESBRU'] ?? 0,
110                    'value' => $parameters['VLRPFA'] ?? 0,
111                    'shippingType' => $parameters['CIFFOB'] ?? '',
112                    'picking-orders' => [],
113                    'orderDetails' => $this->getOrderDetails($parameters['NUMPFA'], $parameters['NUMANE']),
114                    'items' => [],
115                ];
116            }
117
118            // Buscar picking orders de forma otimizada
119            if (!isset($preInvoices[$preInvoiceKey]['picking-orders'])) {
120                $preInvoices[$preInvoiceKey]['picking-orders'] = [];
121            }
122
123            $novosPickingOrders = $output->pickingOrders()
124                ->whereHas('stockIOProducts', fn(Builder $query) =>
125                    $query->where('product_id', $product->pickedItem->item->product->getKey())
126                )
127                ->with('stockIO')
128                ->get(['id', 'stock_io_id']) // Busca apenas IDs para evitar sobrecarga
129                ->map(fn(PickingOrder $pickingOrder) => [
130                    'id' => $pickingOrder->getKey(),
131                    'weight' => $pickingOrder->totalWeight(),
132                    'position' => $pickingOrder->getPosition(),
133                    'VLRPFA' => $pickingOrder->getVlrPfa(),
134                    'PESBRU' => $pickingOrder->getPesBru()
135                ])
136                ->toArray();
137
138            // Indexa o array existente pelo ID para facilitar a comparação
139            $pickingOrdersExistentes = [];
140            foreach ($preInvoices[$preInvoiceKey]['picking-orders'] as $order) {
141                $pickingOrdersExistentes[$order['id']] = $order;
142            }
143
144            // Adiciona apenas os novos registros
145            foreach ($novosPickingOrders as $order) {
146                if (!isset($pickingOrdersExistentes[$order['id']])) {
147                    $pickingOrdersExistentes[$order['id']] = $order;
148                }
149            }
150
151            $preInvoices[$preInvoiceKey]['picking-orders'] = array_values($pickingOrdersExistentes);
152
153            // Adicionar o item
154            $preInvoices[$preInvoiceKey]['items'][] = $product;
155        }
156
157        // Resetar chaves numéricas do array final
158        $preInvoices = array_merge([], $preInvoices);
159
160        return $preInvoices;
161
162    }
163
164    /**
165     * @param string $numpfa
166     * @param string $numane
167     * @return array|null
168     */
169    private function getOrderDetails(string $numpfa, string $numane): ?array
170    {
171        try {
172            $getOrderDetails = (new SeniorPreOrder())->execute(new SeniorPreOrderDTO([
173                'codemp' => 1,
174                'codfil' => 1,
175                'numpfa' => $numpfa,
176                'numane' => $numane,
177            ]));
178        } catch (IntegrationSoapSeniorException $e) {
179            $getOrderDetails = null;
180        }
181        return $getOrderDetails;
182    }
183}