|
- "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: []
- };
- }
- };
-
- 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;
- };
|