$progress * @return array */ public function forRequest(User $actor, WarehouseRequest $request, array $progress): array { abort_unless(auth()->id() === $actor->id && app(WarehouseWorkdesk::class)->canView($actor, $request), 403); if (! Schema::hasTable('supply_records')) { return ['groups' => [], 'ready' => false]; } // Last version that actually mentioned this request: future shared purchases // must not be retroactively attributed to a request already fulfilled. $matched = SupplyRecord::query()->where('kind', 'auto_need')->where('warehouse_id', $request->warehouse_id); if (DB::getDriverName() === 'pgsql') { $matched->whereRaw("EXISTS (SELECT 1 FROM jsonb_array_elements(supply_records.snapshot::jsonb->'origins') o WHERE o->>'warehouse_request_id' = ?)", [(string) $request->id]); } else { $matched->whereRaw("EXISTS (SELECT 1 FROM json_each(supply_records.snapshot, '$.origins') o WHERE json_extract(o.value, '$.warehouse_request_id') = ?)", [$request->id]); } $records = SupplyRecord::query()->whereIn('id', $matched->selectRaw('MAX(id)')->groupBy('record_key'))->orderBy('stock_item_id')->get(); $current = app(SupplyPlanning::class)->latest('auto_need')->whereIn('record_key', $records->pluck('record_key'))->get()->keyBy('record_key'); $corrections = app(InventoryReversals::class)->corrections('receipt'); $groups = []; foreach ($records as $record) { $indexes = []; foreach ($record->snapshot['origins'] as $origin) { $index = $origin['line_index']; if ($origin['warehouse_request_id'] === $request->id && isset($request->snapshot['lines'][$index]) && $request->snapshot['lines'][$index]['item']['id'] === $record->stock_item_id) { $indexes[] = $index; } } if ($indexes === []) { continue; } $latest = $current->get($record->record_key) ?? $record; $ids = array_values(array_unique($record->data['requisition_ids'] ?? [])); $purchases = Requisition::query()->visibleTo($actor)->whereIn('id', $ids)->with('steps')->orderBy('id')->get(); $rows = []; foreach ($purchases as $purchase) { $orders = []; foreach (PurchaseOrder::query()->visibleTo($actor)->where('requisition_id', $purchase->id)->orderBy('id')->get() as $order) { $receipts = []; foreach (DB::table('goods_receipt_items as i')->join('goods_receipts as g', 'g.id', '=', 'i.goods_receipt_id') ->where('i.tenant_id', $actor->tenant_id)->where('g.tenant_id', $actor->tenant_id)->where('g.purchase_order_id', $order->id) ->where('g.warehouse_id', $request->warehouse_id)->where('i.stock_item_id', $record->stock_item_id) ->orderBy('i.id')->get(['i.id', 'g.id as receipt_id', 'g.received_on', 'i.accepted_milli']) as $receipt) { $receipts[] = ['id' => $receipt->receipt_id, 'item_id' => $receipt->id, 'received_on' => $receipt->received_on, 'accepted_milli' => (int) $receipt->accepted_milli, 'reversed' => isset($corrections[$receipt->id])]; } $orders[] = ['id' => $order->id, 'number' => $order->number, 'href' => $actor->hasFunctions(['admin', 'procurement', 'finance', 'department_head']) ? '/ordens/'.$order->id : null, 'receipts' => $receipts, 'effective_received_milli' => array_sum(array_map(fn ($row) => $row['reversed'] ? 0 : $row['accepted_milli'], $receipts))]; } $next = $purchase->status === 'pending' ? $purchase->steps->firstWhere('decision', 'pending') : null; $rows[] = ['id' => $purchase->id, 'number' => $purchase->number, 'status' => $purchase->status, 'href' => '/requisicoes/'.$purchase->id, 'next_task' => $next === null ? null : (OrganizationAccess::PERMISSIONS[$next->role] ?? $next->role), 'orders' => $orders]; } $unreserved = array_sum(array_map(fn ($index) => max(0, $progress['remaining'][$index] - $progress['reserved'][$index]), $indexes)); $groups[] = ['item' => $request->snapshot['lines'][$indexes[0]]['item'], 'line_indexes' => array_values(array_unique($indexes)), 'origin_need_id' => $record->id, 'current_need_id' => $latest->id, 'need_state' => $latest->state, 'message' => $latest->data['message'] ?? '', 'unreserved_milli' => $unreserved, 'purchases' => $rows, 'restricted' => $purchases->count() !== count($ids)]; } return ['ready' => true, 'groups' => $groups]; } /** @return array|null */ public function purchaseOrigin(User $actor, Requisition $purchase): ?array { $origin = app(AutomaticPurchases::class)->origin($purchase); if ($origin === null) { return null; } $sources = WarehouseRequest::query()->whereIn('id', array_column($origin['origins'], 'warehouse_request_id'))->get()->keyBy('id'); $origin['origins'] = array_map(function ($row) use ($sources, $actor) { $request = $sources->get($row['warehouse_request_id']); return [...$row, 'href' => $request !== null && app(WarehouseWorkdesk::class)->canView($actor, $request) ? '/stock/requisicoes/'.$request->id : null]; }, $origin['origins']); return $origin; } }