|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373 |
- "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<T = null> {
- id: number | null;
- name: string;
- code: string;
- type?: string;
- message: string | null;
- errorPosition: string
- entity?: T | T[];
- consoCode?: string;
- }
- export interface PostStockOutLiineResponse<T> {
- 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<PostPickOrderResponse>(
- `${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<PickExecutionIssue[]> => {
- 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<PickExecutionIssue[]>(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<PostPickOrderResponse<batchSubmitListRequest>>(
- `${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<PostPickOrderResponse<UpdateStockOutLineStatusByQRCodeAndLotNoRequest>>(
- `${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<PostPickOrderResponse<QrPickBatchSubmitRequest>>(
- `${BASE_API_URL}/stockOutLine/batchQrSubmit`,
- {
- method: "POST",
- body: JSON.stringify(data),
- },
- );
- return response;
- };
-
- export const fetchDoPickOrderDetail = async (
- doPickOrderId: number,
- selectedPickOrderId?: number
- ): Promise<DoPickOrderDetail> => {
- 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<DoPickOrderDetail>(url, {
- method: "GET",
- });
-
- return response;
- };
- export const updatePickExecutionIssueStatus = async (
- data: UpdatePickExecutionIssueRequest
- ): Promise<PostPickOrderResponse> => {
- const result = await serverFetchJson<PostPickOrderResponse>(
- `${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<StoreLaneSummary> {
- 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<StoreLaneSummary>(
- 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<any> {
- 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<CompletedDoPickOrderResponse[]> => {
- 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<CompletedDoPickOrderResponse[]>(url, {
- method: "GET",
- });
-
- return response;
- };
- export const updatePickOrderHideStatus = async (pickOrderId: number, hide: boolean) => {
- const response = await serverFetchJson<UpdateDoPickOrderHideStatusRequest>(
- `${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<FGPickOrderResponse>(
- `${BASE_API_URL}/pickOrder/fg-pick-orders/${pickOrderId}`,
- {
- method: "GET",
- },
- );
- return response;
- };
- export const fetchFGPickOrdersByUserId = async (userId: number) => {
- const response = await serverFetchJson<FGPickOrderResponse[]>(
- `${BASE_API_URL}/pickOrder/fg-pick-orders/${userId}`,
- {
- method: "GET",
- },
- );
- return response;
- };
- export const updateSuggestedLotLineId = async (suggestedPickLotId: number, newLotLineId: number) => {
- const response = await serverFetchJson<PostPickOrderResponse<UpdateSuggestedLotLineIdRequest>>(
- `${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<AutoAssignReleaseResponse> => {
- const response = await serverFetchJson<AutoAssignReleaseResponse>(
- `${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<AutoAssignReleaseResponse> => {
- const url = `${BASE_API_URL}/pickOrder/auto-assign-release-by-store?userId=${userId}&storeId=${encodeURIComponent(storeId)}`;
- const response = await serverFetchJson<AutoAssignReleaseResponse>(url, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- // no body
- next: { tags: ["pickorder"] },
- });
- revalidateTag("pickorder");
- return response;
- };
- export const checkPickOrderCompletion = async (userId: number): Promise<PickOrderCompletionResponse> => {
- const response = await serverFetchJson<PickOrderCompletionResponse>(
- `${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<PostPickOrderResponse>(
- `${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<PostPickOrderResponse>(
- `${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<PostStockOutLiineResponse<StockOutLine>>(
- `${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<PostPickOrderResponse>(
- `${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<PostPickOrderResponse>(
- `${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<PostPickOrderResponse>(
- `${BASE_API_URL}/pickOrder/groups/latest`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- };
-
- // Get all groups
- export const fetchAllGroups = cache(async () => {
- return serverFetchJson<PickOrderGroupInfo[]>(
- `${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<PostPickOrderResponse>(
- `${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<PickOrderGroupInfo[]>(
- `${BASE_API_URL}/pickOrder/groups/${pickOrderId}`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- });
-
- export const fetchPickOrderDetails = cache(async (ids: string) => {
- return serverFetchJson<GetPickOrderInfoResponse>(
- `${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<any>; // 可以是空数组
- }>;
- }>;
- }
- 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<PostPickOrderResponse>(
- `${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<CheckCompleteResponse> => {
- const response = await serverFetchJson<CheckCompleteResponse>(
- `${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<any[]>(
- 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<any> => {
- try {
- console.log("🔍 Fetching hierarchical pick order lots for userId:", userId);
-
- const data = await serverFetchJson<any>(
- `${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<any[]> => {
- try {
- console.log("🔍 Fetching all pick order line lot details for userId:", userId);
-
- // Use the non-auto-assign endpoint
- const data = await serverFetchJson<any[]>(
- `${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<GetPickOrderInfoResponse>(
- url,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- });
-
- export const fetchPickOrderLineLotDetails = cache(async (pickOrderLineId: number) => {
- return serverFetchJson<PickOrderLotDetailResponse[]>(
- `${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<PostPickOrderResponse>(
- `${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<any>(
- `${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<any>(
- `${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<any>(
- `${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<string, any>) => {
- if (queryParams) {
- const queryString = new URLSearchParams(queryParams).toString();
- return serverFetchJson<RecordsRes<PickOrderResult[]>>(
- `${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- } else {
- return serverFetchJson<RecordsRes<PickOrderResult[]>>(
- `${BASE_API_URL}/pickOrder/getRecordByPage`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- }
- },
- );
-
-
- export const fetchPickOrderWithStockClient = cache(
- async (queryParams?: Record<string, any>) => {
- if (queryParams) {
- const queryString = new URLSearchParams(queryParams).toString();
- return serverFetchJson<RecordsRes<GetPickOrderInfo[]>>(
- `${BASE_API_URL}/pickOrder/getRecordByPageWithStock?${queryString}`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- } else {
- return serverFetchJson<RecordsRes<GetPickOrderInfo[]>>(
- `${BASE_API_URL}/pickOrder/getRecordByPageWithStock`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- }
- },
- );
-
- export const fetchConsoPickOrderClient = cache(
- async (queryParams?: Record<string, any>) => {
- if (queryParams) {
- const queryString = new URLSearchParams(queryParams).toString();
- return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(
- `${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- } else {
- return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(
- `${BASE_API_URL}/pickOrder/getRecordByPage-conso`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- }
- },
- );
-
- export const fetchPickOrderLineClient = cache(
- async (queryParams?: Record<string, any>) => {
- if (queryParams) {
- const queryString = new URLSearchParams(queryParams).toString();
- return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(
- `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- } else {
- return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(
- `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- }
- },
- );
-
- export const fetchStockOutLineClient = cache(
- async (pickOrderLineId: number) => {
- return serverFetchJson<StockOutLine[]>(
- `${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`,
- {
- method: "GET",
- next: { tags: ["pickorder"] },
- },
- );
- },
- );
-
- export const fetchConsoDetail = cache(async (consoCode: string) => {
- return serverFetchJson<PreReleasePickOrderSummary>(
- `${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<PostStockOutLiineResponse<StockOutLine>>(
- `${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<PostStockOutLiineResponse<StockOutLine>>(
- `${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<PostStockOutLiineResponse<StockOutLine>>(
- `${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<ReleasedDoPickOrderResponse[]> => {
- const response = await serverFetchJson<ReleasedDoPickOrderResponse[]>(
- `${BASE_API_URL}/doPickOrder/released`,
- {
- method: "GET",
- },
- );
- return response;
- };
|