"use server"; import { BASE_API_URL } from "@/config/api"; // import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; import { revalidateTag } from "next/cache"; import { cache } from "react"; import { serverFetchJson } from "@/app/utils/fetchUtil"; import { QcItemResult } from "../settings/qcItem"; import { RecordsRes } from "../utils"; import { ConsoPickOrderResult, PickOrderLineWithSuggestedLot, PickOrderResult, PreReleasePickOrderSummary, StockOutLine, } from "."; import { PurchaseQcResult } from "../po/actions"; import { StringNullableChain } from "lodash"; // import { BASE_API_URL } from "@/config/api"; import dayjs from "dayjs"; export interface SavePickOrderLineRequest { itemId: number qty: number uomId: number } export interface SavePickOrderRequest { type: string targetDate: string pickOrderLine: SavePickOrderLineRequest[] } export interface PostPickOrderResponse { id: number | null; name: string; code: string; type?: string; message: string | null; errorPosition: string entity?: T | T[]; consoCode?: string; } export interface PostStockOutLiineResponse { id: number | null; name: string; code: string; type?: string; message: string | null; errorPosition: string | keyof T; entity: T | T[] | null; } export interface ReleasePickOrderInputs { consoCode: string; assignTo: number; } export interface CreateStockOutLine { consoCode: string; pickOrderLineId: number; inventoryLotLineId: number; qty: number; } export interface UpdateStockOutLine { id: number; // consoCode: String, itemId: number; qty: number; pickOrderLineId: number; inventoryLotLineId?: number; status: string; pickTime?: string; // pickerId: number? } export interface PickOrderQcInput { qty: number; status: string; qcResult: PurchaseQcResult[]; } export interface PickOrderApprovalInput { allowQty: number; rejectQty: number; status: string; } export interface GetPickOrderInfoResponse { consoCode: string | null; pickOrders: GetPickOrderInfo[]; items: CurrentInventoryItemInfo[]; } export interface GetPickOrderInfo { id: number; code: string; consoCode: string | null; // 添加 consoCode 属性 targetDate: string | number[]; // Support both formats type: string; status: string; assignTo: number; groupName: string; // Add this field pickOrderLines: GetPickOrderLineInfo[]; } export interface GetPickOrderLineInfo { id: number; itemId: number; itemCode: string; itemName: string; availableQty: number| null; requiredQty: number; uomShortDesc: string; uomDesc: string; suggestedList: any[]; pickedQty: number; noLotLines: NoLotLineDto[]; } export interface NoLotLineDto { stockOutLineId: number; status: string; qty: number; created: string; modified: string; } export interface CurrentInventoryItemInfo { id: number; code: string; name: string; uomDesc: string; availableQty: number; requiredQty: number; } export interface SavePickOrderGroupRequest { groupIds?: number[]; names?: string[]; targetDate?: string; pickOrderId?: number | null; } export interface PickOrderGroupInfo { id: number; name: string; targetDate: string | null; pickOrderId: number | null; } export interface AssignPickOrderInputs { pickOrderIds: number[]; assignTo: number; } export interface LotDetailWithStockOutLine { lotId: number; lotNo: string; expiryDate: string; location: string; stockUnit: string; availableQty: number; requiredQty: number; actualPickQty: number; suggestedPickLotId: number; lotStatus: string; lotAvailability: string; stockOutLineId?: number; stockOutLineStatus?: string; stockOutLineQty?: number; } export interface PickAnotherLotFormData { pickOrderLineId: number; lotId: number; qty: number; type: string; handlerId?: number; category?: string; releasedBy?: number; recordDate?: string; } export const recordFailLot = async (data: PickAnotherLotFormData) => { const result = await serverFetchJson( `${BASE_API_URL}/suggestedPickLot/recordFailLot`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return result; }; export interface PickExecutionIssueData { type: string; pickOrderId: number; pickOrderCode: string; pickOrderCreateDate: string; pickExecutionDate: string; pickOrderLineId: number; itemId: number; itemCode: string; itemDescription: string; lotId: number|null; lotNo: string|null; storeLocation: string; requiredQty: number; actualPickQty: number; missQty: number; badItemQty: number; issueRemark: string; pickerName: string; handledBy?: number; } export type AutoAssignReleaseResponse = { id: number | null; name?: string | null; code?: string | null; type?: string | null; message?: string | null; errorPosition?: string | null; entity?: any; }; export interface PickOrderCompletionResponse { id: number | null; name: string; code: string; type?: string; message: string | null; errorPosition: string; entity?: { hasCompletedOrders: boolean; completedOrders: Array<{ pickOrderId: number; pickOrderCode: string; consoCode: string; isCompleted: boolean; stockOutStatus: string; totalLines: number; unfinishedLines: number; }>; allOrders: Array<{ pickOrderId: number; pickOrderCode: string; consoCode: string; isCompleted: boolean; stockOutStatus: string; totalLines: number; unfinishedLines: number; }>; }; } export interface UpdateSuggestedLotLineIdRequest { newLotLineId: number; } export interface stockReponse{ id: number; status: string; qty: number; lotId: number; lotNo: string; location: string; availableQty: number; noLot: boolean; } export interface FGPickOrderResponse { // 新增:支持多个 pick orders doPickOrderId: number; pickOrderIds?: number[]; pickOrderCodes?: string[]; // 改为数组 deliveryOrderIds?: number[]; deliveryNos?: string[]; // 改为数组 numberOfPickOrders?: number; lineCountsPerPickOrder?: number[];// 新增:pick order 数量 // 保留原有字段用于向后兼容(显示第一个 pick order) pickOrderId: number; pickOrderCode: string; pickOrderConsoCode: string; pickOrderTargetDate: string; pickOrderStatus: string; deliveryOrderId: number; deliveryNo: string; deliveryDate: string; shopId: number; shopCode: string; shopName: string; shopAddress: string; ticketNo: string; shopPoNo: string; numberOfCartons: number; DepartureTime: string; truckLanceCode: string; storeId: string; qrCodeData: number; } export interface DoPickOrderDetail { doPickOrder: { id: number; store_id: string; ticket_no: string; ticket_status: string; truck_id: number; truck_departure_time: string; shop_id: number; handled_by: number | null; loading_sequence: number; ticket_release_time: string | null; TruckLanceCode: string; ShopCode: string; ShopName: string; RequiredDeliveryDate: string; }; pickOrders: Array<{ pick_order_id: number; pick_order_code: string; do_order_id: number; delivery_order_code: string; consoCode: string; status: string; targetDate: string; }>; selectedPickOrderId: number; lotDetails: any[]; // 使用现有的 lot detail 结构 pickOrderCodes?: string; deliveryNos?: string; } export interface AutoAssignReleaseByStoreRequest { userId: number; storeId: string; // "2/F" | "4/F" } export interface UpdateDoPickOrderHideStatusRequest { id: number; name: string; code: string; type: string; message: string; errorPosition: string; } export interface CompletedDoPickOrderResponse { id: number; doPickOrderRecordId: number; // ✅ 新增 recordId: number | null; pickOrderId: number; pickOrderIds: number[]; // 新增:所有 pick order IDs pickOrderCode: string; pickOrderCodes: string; // 新增:所有 pick order codes (逗号分隔) pickOrderConsoCode: string; pickOrderStatus: string; deliveryOrderId: number; deliveryOrderIds: number[]; // 新增:所有 delivery order IDs deliveryNo: string; deliveryNos: string; // 新增:所有 delivery order codes (逗号分隔) deliveryDate: string; shopId: number; shopCode: string; shopName: string; shopAddress: string; ticketNo: string; shopPoNo: string; numberOfCartons: number; truckLanceCode: string; DepartureTime: string; // 新增 storeId: string; completedDate: string; fgPickOrders: FGPickOrderResponse[]; deliveryNoteCode: number; } // 新增:搜索参数接口 export interface CompletedDoPickOrderSearchParams { targetDate?: string; shopName?: string; deliveryNoteCode?: string; } export interface PickExecutionIssue { id: number; pickOrderId: number; pickOrderCode: string; pickOrderCreateDate: string; pickExecutionDate: string; pickOrderLineId: number; issueNo: string; joPickOrderId?: number; doPickOrderId?: number; issueCategory: string; itemId: number; itemCode: string; itemDescription: string; lotId?: number; lotNo?: string; storeLocation?: string; requiredQty: number; actualPickQty?: number; missQty?: number; badItemQty?: number; issueRemark?: string; pickerName?: string; handleStatus: string; handleDate?: string; handledBy?: string; created: string; createdBy: string; modified: string; modifiedBy: string; } export interface FetchPickExecutionIssuesParams { type?: "jo" | "do" | "material"; } export const fetchAllPickExecutionIssues = cache( async (params?: FetchPickExecutionIssuesParams): Promise => { const queryParams = new URLSearchParams(); if (params?.type) { queryParams.append("type", params.type); } const url = `${BASE_API_URL}/pickExecution/issues/all${ queryParams.toString() ? `?${queryParams.toString()}` : "" }`; const result = await serverFetchJson(url, { method: "GET", headers: { "Content-Type": "application/json" }, }); return result ?? []; } ); export interface UpdatePickExecutionIssueRequest { issueId: number; handleStatus: string; handleDate?: string; handledBy?: string; handleRemark?: string; } export interface StoreLaneSummary { storeId: string; rows: LaneRow[]; } export interface LaneRow { truckDepartureTime: string; lanes: LaneBtn[]; } export interface LaneBtn { truckLanceCode: string; unassigned: number; total: number; } export interface QrPickBatchSubmitRequest { userId: number; lines: QrPickSubmitLineRequest[]; } export interface QrPickSubmitLineRequest { stockOutLineId: number; pickOrderLineId: number; inventoryLotLineId: number | null; // ✅ 修复:应该是 nullable requiredQty: number | null; // ✅ 修复:添加 requiredQty actualPickQty: number | null; // ✅ 修复:添加 actualPickQty stockOutLineStatus: string | null; // ✅ 修复:添加 stockOutLineStatus pickOrderConsoCode: string | null; // ✅ 修复:添加 pickOrderConsoCode noLot: boolean; // ✅ 修复:添加 noLot } export interface UpdateStockOutLineStatusByQRCodeAndLotNoRequest { pickOrderLineId: number, inventoryLotNo: string, stockOutLineId: number, itemId: number, status: string } export interface batchSubmitListRequest { userId: number; lines: batchSubmitListLineRequest[]; } export interface batchSubmitListLineRequest { stockOutLineId: number; // 修复:改为 stockOutLineId(不是 stockInLineId) pickOrderLineId: number; inventoryLotLineId: number | null; // 添加:后端需要的字段 requiredQty: number; actualPickQty: number; stockOutLineStatus: string; pickOrderConsoCode: string; noLot: boolean; // 移除:lotNo 和 stockInLineId(后端不需要) } export const batchSubmitList = async (data: batchSubmitListRequest) => { // ✅ 确保发送的是对象,不是数组 const requestBody = Array.isArray(data) ? data[0] : data; console.log("📤 batchSubmitList - Request body type:", Array.isArray(requestBody) ? "array" : "object"); console.log("📤 batchSubmitList - Request body:", JSON.stringify(requestBody, null, 2)); const response = await serverFetchJson>( `${BASE_API_URL}/stockOutLine/batchSubmitList`, { method: "POST", body: JSON.stringify(requestBody), // ✅ 确保是对象 headers: { "Content-Type": "application/json", // ✅ 明确指定 Content-Type }, }, ); return response; }; export const updateStockOutLineStatusByQRCodeAndLotNo = async (data: UpdateStockOutLineStatusByQRCodeAndLotNoRequest) => { console.log(" Frontend: Calling updateStockOutLineStatusByQRCodeAndLotNo with data:", data); try { const response = await serverFetchJson>( `${BASE_API_URL}/stockOutLine/updateStatusByQRCodeAndLotNo`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data), }, ); console.log("✅ Frontend: API call successful, response:", response); return response; } catch (error) { console.error("❌ Frontend: API call failed:", error); throw error; } }; export const batchQrSubmit = async (data: QrPickBatchSubmitRequest) => { const response = await serverFetchJson>( `${BASE_API_URL}/stockOutLine/batchQrSubmit`, { method: "POST", body: JSON.stringify(data), }, ); return response; }; export const fetchDoPickOrderDetail = async ( doPickOrderId: number, selectedPickOrderId?: number ): Promise => { const url = selectedPickOrderId ? `${BASE_API_URL}/pickOrder/do-pick-order-detail/${doPickOrderId}?selectedPickOrderId=${selectedPickOrderId}` : `${BASE_API_URL}/pickOrder/do-pick-order-detail/${doPickOrderId}`; const response = await serverFetchJson(url, { method: "GET", }); return response; }; export const updatePickExecutionIssueStatus = async ( data: UpdatePickExecutionIssueRequest ): Promise => { const result = await serverFetchJson( `${BASE_API_URL}/pickExecution/updateIssueStatus`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, } ); revalidateTag("pickExecutionIssues"); return result; }; export async function fetchStoreLaneSummary(storeId: string, requiredDate?: string, releaseType?: string): Promise { const dateToUse = requiredDate || dayjs().format('YYYY-MM-DD'); const url = `${BASE_API_URL}/doPickOrder/summary-by-store?storeId=${encodeURIComponent(storeId)}&requiredDate=${encodeURIComponent(dateToUse)}&releaseType=${encodeURIComponent(releaseType || 'all')}`; const response = await serverFetchJson( url, { method: "GET", cache: "no-store", next: { revalidate: 0 } } ); return response; } // 按车道分配订单 export async function assignByLane( userId: number, storeId: string, truckLanceCode: string, truckDepartureTime?: string, requiredDate?: string ): Promise { const response = await serverFetchJson( `${BASE_API_URL}/doPickOrder/assign-by-lane`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ userId, storeId, truckLanceCode, truckDepartureTime, requiredDate, }), } ); return response; } // 新增:获取已完成的 DO Pick Orders API export const fetchCompletedDoPickOrders = async ( userId: number, searchParams?: CompletedDoPickOrderSearchParams ): Promise => { const params = new URLSearchParams(); if (searchParams?.deliveryNoteCode) { params.append('deliveryNoteCode', searchParams.deliveryNoteCode); } if (searchParams?.shopName) { params.append('shopName', searchParams.shopName); } if (searchParams?.targetDate) { params.append('targetDate', searchParams.targetDate); } const queryString = params.toString(); const url = `${BASE_API_URL}/pickOrder/completed-do-pick-orders/${userId}${queryString ? `?${queryString}` : ''}`; const response = await serverFetchJson(url, { method: "GET", }); return response; }; export const updatePickOrderHideStatus = async (pickOrderId: number, hide: boolean) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/update-hide-status/${pickOrderId}?hide=${hide}`, { method: "POST", headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; export const fetchFGPickOrders = async (pickOrderId: number) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/fg-pick-orders/${pickOrderId}`, { method: "GET", }, ); return response; }; export const fetchFGPickOrdersByUserId = async (userId: number) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/fg-pick-orders/${userId}`, { method: "GET", }, ); return response; }; export const updateSuggestedLotLineId = async (suggestedPickLotId: number, newLotLineId: number) => { const response = await serverFetchJson>( `${BASE_API_URL}/suggestedPickLot/update-suggested-lot/${suggestedPickLotId}`, { method: "POST", body: JSON.stringify({ newLotLineId }), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; export const autoAssignAndReleasePickOrder = async (userId: number): Promise => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/auto-assign-release/${userId}`, { method: "POST", headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; export const autoAssignAndReleasePickOrderByStore = async ( userId: number, storeId: string ): Promise => { const url = `${BASE_API_URL}/pickOrder/auto-assign-release-by-store?userId=${userId}&storeId=${encodeURIComponent(storeId)}`; const response = await serverFetchJson(url, { method: "POST", headers: { "Content-Type": "application/json" }, // no body next: { tags: ["pickorder"] }, }); revalidateTag("pickorder"); return response; }; export const checkPickOrderCompletion = async (userId: number): Promise => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/check-pick-completion/${userId}`, { method: "GET", headers: { "Content-Type": "application/json" }, }, ); return response; }; export const recordPickExecutionIssue = async (data: PickExecutionIssueData) => { const result = await serverFetchJson( `${BASE_API_URL}/pickExecution/recordIssue`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return result; }; export const resuggestPickOrder = async (pickOrderId: number) => { console.log("Resuggesting pick order:", pickOrderId); const result = await serverFetchJson( `${BASE_API_URL}/suggestedPickLot/resuggest/${pickOrderId}`, { method: "POST", headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return result; }; export const updateStockOutLineStatus = async (data: { id: number; status: string; qty?: number; remarks?: string; }) => { console.log("Updating stock out line status:", data); const result = await serverFetchJson>( `${BASE_API_URL}/stockOutLine/updateStatus`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return result; }; // Missing function 1: newassignPickOrder export const newassignPickOrder = async (data: AssignPickOrderInputs) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/assign`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; // Missing function 2: releaseAssignedPickOrders export const releaseAssignedPickOrders = async (data: AssignPickOrderInputs) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/release-assigned`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; // Get latest group name and create it automatically export const getLatestGroupNameAndCreate = async () => { return serverFetchJson( `${BASE_API_URL}/pickOrder/groups/latest`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }; // Get all groups export const fetchAllGroups = cache(async () => { return serverFetchJson( `${BASE_API_URL}/pickOrder/groups/list`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); // Create or update groups (flexible - can handle both cases) export const createOrUpdateGroups = async (data: SavePickOrderGroupRequest) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/groups/create`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; // Get groups by pick order ID export const fetchGroupsByPickOrderId = cache(async (pickOrderId: number) => { return serverFetchJson( `${BASE_API_URL}/pickOrder/groups/${pickOrderId}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); export const fetchPickOrderDetails = cache(async (ids: string) => { return serverFetchJson( `${BASE_API_URL}/pickOrder/detail/${ids}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); export interface PickOrderLotDetailResponse { lotId: number | null; // ✅ 改为可空 lotNo: string | null; // ✅ 改为可空 expiryDate: string | null; // ✅ 改为可空 location: string | null; // ✅ 改为可空 stockUnit: string | null; inQty: number | null; availableQty: number | null; // ✅ 改为可空 requiredQty: number; actualPickQty: number; suggestedPickLotId: number | null; lotStatus: string | null; lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable' | 'rejected'; stockOutLineId: number | null; // ✅ 添加 stockOutLineStatus: string | null; // ✅ 添加 stockOutLineQty: number | null; // ✅ 添加 totalPickedByAllPickOrders: number | null; // ✅ 添加 remainingAfterAllPickOrders: number | null; // ✅ 添加 noLot: boolean; // ✅ 关键:添加 noLot 字段 outQty?: number; // ✅ 添加 holdQty?: number; // ✅ 添加 } interface ALLPickOrderLotDetailResponse { // Pick Order Information pickOrderId: number; pickOrderCode: string; pickOrderTargetDate: string; pickOrderType: string; pickOrderStatus: string; pickOrderAssignTo: number; groupName: string; // Pick Order Line Information pickOrderLineId: number; pickOrderLineRequiredQty: number; pickOrderLineStatus: string; // Item Information itemId: number; itemCode: string; itemName: string; uomCode: string; uomDesc: string; // Lot Information lotId: number; lotNo: string; expiryDate: string; location: string; outQty: number; holdQty: number; stockUnit: string; availableQty: number; requiredQty: number; actualPickQty: number; totalPickedByAllPickOrders: number; suggestedPickLotId: number; lotStatus: string; stockOutLineId?: number; stockOutLineStatus?: string; stockOutLineQty?: number; lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable'|'rejected'; processingStatus: string; } interface SuggestionWithStatus { suggestionId: number; suggestionQty: number; suggestionCreated: string; lotLineId: number; lotNo: string; expiryDate: string; location: string; stockOutLineId?: number; stockOutLineStatus?: string; stockOutLineQty?: number; suggestionStatus: 'active' | 'completed' | 'rejected' | 'in_progress' | 'unknown'; } // 在 actions.ts 中修改接口定义 export interface FGPickOrderHierarchicalResponse { fgInfo: { doPickOrderId: number; ticketNo: string; storeId: string; shopCode: string; shopName: string; truckLanceCode: string; departureTime: string; }; pickOrders: Array<{ pickOrderId: number; pickOrderCode: string; doOrderId: number; deliveryOrderCode: string; consoCode: string; status: string; targetDate: string; pickOrderLines: Array<{ id: number; requiredQty: number; status: string; item: { id: number; code: string; name: string; uomCode: string; uomDesc: string; }; lots: Array; // 可以是空数组 }>; }>; } export interface CheckCompleteResponse { id: number | null; name: string; code: string; type?: string; message: string | null; errorPosition: string; } export interface LotSubstitutionConfirmRequest { pickOrderLineId: number; stockOutLineId: number; originalSuggestedPickLotId: number; newInventoryLotNo: string; } export const confirmLotSubstitution = async (data: LotSubstitutionConfirmRequest) => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/lot-substitution/confirm`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return response; }; export const checkAndCompletePickOrderByConsoCode = async (consoCode: string): Promise => { const response = await serverFetchJson( `${BASE_API_URL}/pickOrder/check-complete/${consoCode}`, { method: "POST", headers: { "Content-Type": "application/json", }, }, ); revalidateTag("pickorder"); return response; }; export const fetchPickOrderDetailsOptimized = cache(async (userId?: number) => { const url = userId ? `${BASE_API_URL}/pickOrder/detail-optimized?userId=${userId}` : `${BASE_API_URL}/pickOrder/detail-optimized`; return serverFetchJson( url, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); const fetchSuggestionsWithStatus = async (pickOrderLineId: number) => { try { const response = await fetch(`/api/suggestedPickLot/suggestions-with-status/${pickOrderLineId}`); const suggestions: SuggestionWithStatus[] = await response.json(); return suggestions; } catch (error) { console.error('Error fetching suggestions with status:', error); return []; } }; export const fetchAllPickOrderLotsHierarchical = cache(async (userId: number): Promise => { try { console.log("🔍 Fetching hierarchical pick order lots for userId:", userId); const data = await serverFetchJson( `${BASE_API_URL}/pickOrder/all-lots-hierarchical/${userId}`, { method: 'GET', next: { tags: ["pickorder"] }, } ); console.log(" Fetched hierarchical lot details:", data); return data; } catch (error) { console.error("❌ Error fetching hierarchical lot details:", error); return { pickOrder: null, pickOrderLines: [] }; } }); export const fetchLotDetailsByDoPickOrderRecordId = async (doPickOrderRecordId: number): Promise<{ fgInfo: any; pickOrders: any[]; }> => { try { console.log("🔍 Fetching lot details for doPickOrderRecordId:", doPickOrderRecordId); const data = await serverFetchJson<{ fgInfo: any; pickOrders: any[]; }>( `${BASE_API_URL}/pickOrder/lot-details-by-do-pick-order-record/${doPickOrderRecordId}`, { method: 'GET', next: { tags: ["pickorder"] }, } ); console.log(" Fetched hierarchical lot details:", data); return data; } catch (error) { console.error("❌ Error fetching lot details:", error); return { fgInfo: null, pickOrders: [] }; } }; // Update the existing function to use the non-auto-assign endpoint export const fetchALLPickOrderLineLotDetails = cache(async (userId: number): Promise => { try { console.log("🔍 Fetching all pick order line lot details for userId:", userId); // Use the non-auto-assign endpoint const data = await serverFetchJson( `${BASE_API_URL}/pickOrder/all-lots-with-details-no-auto-assign/${userId}`, { method: 'GET', next: { tags: ["pickorder"] }, } ); console.log(" Fetched lot details:", data); return data; } catch (error) { console.error("❌ Error fetching lot details:", error); return []; } }); export const fetchAllPickOrderDetails = cache(async (userId?: number) => { if (!userId) { return { consoCode: null, pickOrders: [], items: [] }; } // Use the correct endpoint with userId in the path const url = `${BASE_API_URL}/pickOrder/detail-optimized/${userId}`; return serverFetchJson( url, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); export const fetchPickOrderLineLotDetails = cache(async (pickOrderLineId: number) => { return serverFetchJson( `${BASE_API_URL}/pickOrder/lot-details/${pickOrderLineId}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); export const createPickOrder = async (data: SavePickOrderRequest) => { console.log(data); const po = await serverFetchJson( `${BASE_API_URL}/pickOrder/create`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return po; } export const assignPickOrder = async (ids: number[]) => { const pickOrder = await serverFetchJson( `${BASE_API_URL}/pickOrder/conso`, { method: "POST", body: JSON.stringify({ ids: ids }), headers: { "Content-Type": "application/json" }, }, ); // revalidateTag("po"); return pickOrder; }; export const consolidatePickOrder = async (ids: number[]) => { const pickOrder = await serverFetchJson( `${BASE_API_URL}/pickOrder/conso`, { method: "POST", body: JSON.stringify({ ids: ids }), headers: { "Content-Type": "application/json" }, }, ); return pickOrder; }; export const consolidatePickOrder_revert = async (ids: number[]) => { const pickOrder = await serverFetchJson( `${BASE_API_URL}/pickOrder/deconso`, { method: "POST", body: JSON.stringify({ ids: ids }), headers: { "Content-Type": "application/json" }, }, ); // revalidateTag("po"); return pickOrder; }; export const fetchPickOrderClient = cache( async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); return serverFetchJson>( `${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } else { return serverFetchJson>( `${BASE_API_URL}/pickOrder/getRecordByPage`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } }, ); export const fetchPickOrderWithStockClient = cache( async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); return serverFetchJson>( `${BASE_API_URL}/pickOrder/getRecordByPageWithStock?${queryString}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } else { return serverFetchJson>( `${BASE_API_URL}/pickOrder/getRecordByPageWithStock`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } }, ); export const fetchConsoPickOrderClient = cache( async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); return serverFetchJson>( `${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } else { return serverFetchJson>( `${BASE_API_URL}/pickOrder/getRecordByPage-conso`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } }, ); export const fetchPickOrderLineClient = cache( async (queryParams?: Record) => { if (queryParams) { const queryString = new URLSearchParams(queryParams).toString(); return serverFetchJson>( `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } else { return serverFetchJson>( `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`, { method: "GET", next: { tags: ["pickorder"] }, }, ); } }, ); export const fetchStockOutLineClient = cache( async (pickOrderLineId: number) => { return serverFetchJson( `${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }, ); export const fetchConsoDetail = cache(async (consoCode: string) => { return serverFetchJson( `${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); export const releasePickOrder = async (data: ReleasePickOrderInputs) => { console.log(data); console.log(JSON.stringify(data)); const po = await serverFetchJson<{ consoCode: string }>( `${BASE_API_URL}/pickOrder/releaseConso`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return po; }; export const createStockOutLine = async (data: CreateStockOutLine) => { console.log("triggering"); const po = await serverFetchJson>( `${BASE_API_URL}/stockOutLine/create`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return po; }; export const updateStockOutLine = async (data: UpdateStockOutLine) => { console.log(data); const po = await serverFetchJson>( `${BASE_API_URL}/stockOutLine/update`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return po; }; export const completeConsoPickOrder = async (consoCode: string) => { const po = await serverFetchJson>( `${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`, { method: "POST", headers: { "Content-Type": "application/json" }, }, ); revalidateTag("pickorder"); return po; }; export const fetchConsoStatus = cache(async (consoCode: string) => { return serverFetchJson<{ status: string }>( `${BASE_API_URL}/stockOut/get-status/${consoCode}`, { method: "GET", next: { tags: ["pickorder"] }, }, ); }); export interface ReleasedDoPickOrderResponse { id: number; storeId: string; ticketNo: string; pickOrderId: number; ticketStatus: string; doOrderId: number; shopId: number; handledBy: number; ticketReleaseTime: string; } export const fetchReleasedDoPickOrders = async (): Promise => { const response = await serverFetchJson( `${BASE_API_URL}/doPickOrder/released`, { method: "GET", }, ); return response; };