// actions.ts "use server"; import { cache } from 'react'; import { serverFetchJson } from "@/app/utils/fetchUtil"; // 改为 serverFetchJson import { BASE_API_URL } from "@/config/api"; export interface RecordsRes { records: T[]; total: number; } export interface InventoryLotDetailResponse { id: number; inventoryLotId: number; itemId: number; itemCode: string; itemName: string; lotNo: string; expiryDate: string; productionDate: string; stockInDate: string; inQty: number; outQty: number; holdQty: number; availableQty: number; uom: string; warehouseCode: string; warehouseName: string; warehouseSlot: string; warehouseArea: string; warehouse: string; varianceQty: number | null; status: string; remarks: string | null; stockTakeRecordStatus: string; stockTakeRecordId: number | null; firstStockTakeQty: number | null; secondStockTakeQty: number | null; firstBadQty: number | null; secondBadQty: number | null; approverQty: number | null; approverBadQty: number | null; finalQty: number | null; bookQty: number | null; } export const getInventoryLotDetailsBySection = async ( stockTakeSection: string, stockTakeId?: number | null, pageNum?: number, pageSize?: number ) => { console.log('🌐 [API] getInventoryLotDetailsBySection called with:', { stockTakeSection, stockTakeId, pageNum, pageSize }); const encodedSection = encodeURIComponent(stockTakeSection); let url = `${BASE_API_URL}/stockTakeRecord/inventoryLotDetailsBySection?stockTakeSection=${encodedSection}&pageNum=${pageNum}&pageSize=${pageSize}`; if (stockTakeId != null && stockTakeId > 0) { url += `&stockTakeId=${stockTakeId}`; } console.log(' [API] Full URL:', url); const response = await serverFetchJson>( url, { method: "GET", }, ); console.log('[API] Response received:', response); return response; } export interface SaveStockTakeRecordRequest { stockTakeRecordId?: number | null; inventoryLotLineId: number; qty: number; badQty: number; //stockTakerName: string; remark?: string | null; } export interface AllPickedStockTakeListReponse { id: number; stockTakeSession: string; lastStockTakeDate: string | null; status: string|null; approverName: string | null; currentStockTakeItemNumber: number; totalInventoryLotNumber: number; stockTakeId: number; stockTakerName: string | null; totalItemNumber: number; startTime: string | null; endTime: string | null; planStartDate: string | null; stockTakeSectionDescription: string | null; reStockTakeTrueFalse: boolean; } export const getApproverInventoryLotDetailsAll = async ( stockTakeId?: number | null, pageNum: number = 0, pageSize: number = 100 ) => { const params = new URLSearchParams(); params.append("pageNum", String(pageNum)); params.append("pageSize", String(pageSize)); if (stockTakeId != null && stockTakeId > 0) { params.append("stockTakeId", String(stockTakeId)); } const url = `${BASE_API_URL}/stockTakeRecord/approverInventoryLotDetailsAll?${params.toString()}`; const response = await serverFetchJson>( url, { method: "GET", }, ); return response; } export const importStockTake = async (data: FormData) => { const importStockTake = await serverFetchJson( `${BASE_API_URL}/stockTake/import`, { method: "POST", body: data, }, ); return importStockTake; } export const getStockTakeRecords = async () => { const stockTakeRecords = await serverFetchJson( // 改为 serverFetchJson `${BASE_API_URL}/stockTakeRecord/AllPickedStockOutRecordList`, { method: "GET", }, ); return stockTakeRecords; } export const getStockTakeRecordsPaged = async ( pageNum: number, pageSize: number, params?: { sectionDescription?: string; stockTakeSections?: string } ) => { const searchParams = new URLSearchParams(); searchParams.set("pageNum", String(pageNum)); searchParams.set("pageSize", String(pageSize)); if (params?.sectionDescription && params.sectionDescription !== "All") { searchParams.set("sectionDescription", params.sectionDescription); } if (params?.stockTakeSections?.trim()) { searchParams.set("stockTakeSections", params.stockTakeSections.trim()); } const url = `${BASE_API_URL}/stockTakeRecord/AllPickedStockOutRecordList?${searchParams.toString()}`; const res = await serverFetchJson>(url, { method: "GET" }); return res; }; export const getApproverStockTakeRecords = async () => { const stockTakeRecords = await serverFetchJson( // 改为 serverFetchJson `${BASE_API_URL}/stockTakeRecord/AllApproverStockTakeList`, { method: "GET", }, ); return stockTakeRecords; } export const createStockTakeForSections = async () => { const createStockTakeForSections = await serverFetchJson>( `${BASE_API_URL}/stockTake/createForSections`, { method: "POST", }, ); return createStockTakeForSections; } export const saveStockTakeRecord = async ( request: SaveStockTakeRecordRequest, stockTakeId: number, stockTakerId: number ) => { try { const result = await serverFetchJson( `${BASE_API_URL}/stockTakeRecord/saveStockTakeRecord?stockTakeId=${stockTakeId}&stockTakerId=${stockTakerId}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(request), }, ); console.log('saveStockTakeRecord: request:', request); console.log('saveStockTakeRecord: stockTakeId:', stockTakeId); console.log('saveStockTakeRecord: stockTakerId:', stockTakerId); return result; } catch (error: any) { // 尝试从错误响应中提取消息 if (error?.response) { try { const errorData = await error.response.json(); const errorWithMessage = new Error(errorData.message || errorData.error || "Failed to save stock take record"); (errorWithMessage as any).response = error.response; throw errorWithMessage; } catch { throw error; } } throw error; } } export interface BatchSaveStockTakeRecordRequest { stockTakeId: number; stockTakeSection: string; stockTakerId: number; //stockTakerName: string; } export interface BatchSaveStockTakeRecordResponse { successCount: number; errorCount: number; errors: string[]; } export const batchSaveStockTakeRecords = cache(async (data: BatchSaveStockTakeRecordRequest) => { return serverFetchJson(`${BASE_API_URL}/stockTakeRecord/batchSaveStockTakeRecords`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }) }) // Add these interfaces and functions export interface SaveApproverStockTakeRecordRequest { stockTakeRecordId?: number | null; qty: number; badQty: number; approverId?: number | null; approverQty?: number | null; approverBadQty?: number | null; } export interface BatchSaveApproverStockTakeRecordRequest { stockTakeId: number; stockTakeSection: string; approverId: number; variancePercentTolerance?: number | null; } export interface BatchSaveApproverStockTakeRecordResponse { successCount: number; errorCount: number; errors: string[]; } export interface BatchSaveApproverStockTakeAllRequest { stockTakeId: number; approverId: number; variancePercentTolerance?: number | null; } export const saveApproverStockTakeRecord = async ( request: SaveApproverStockTakeRecordRequest, stockTakeId: number ) => { try { const result = await serverFetchJson( `${BASE_API_URL}/stockTakeRecord/saveApproverStockTakeRecord?stockTakeId=${stockTakeId}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(request), }, ); return result; } catch (error: any) { if (error?.response) { try { const errorData = await error.response.json(); const errorWithMessage = new Error(errorData.message || errorData.error || "Failed to save approver stock take record"); (errorWithMessage as any).response = error.response; throw errorWithMessage; } catch { throw error; } } throw error; } } export const batchSaveApproverStockTakeRecords = cache(async (data: BatchSaveApproverStockTakeRecordRequest) => { return serverFetchJson( `${BASE_API_URL}/stockTakeRecord/batchSaveApproverStockTakeRecords`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, } ) } ) export const batchSaveApproverStockTakeRecordsAll = cache(async (data: BatchSaveApproverStockTakeAllRequest) => { return serverFetchJson( `${BASE_API_URL}/stockTakeRecord/batchSaveApproverStockTakeRecordsAll`, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, } ) }) export const updateStockTakeRecordStatusToNotMatch = async ( stockTakeRecordId: number ) => { try { const result = await serverFetchJson( `${BASE_API_URL}/stockTakeRecord/updateStockTakeRecordStatusToNotMatch?stockTakeRecordId=${stockTakeRecordId}`, { method: "POST", }, ); return result; } catch (error: any) { if (error?.response) { try { const errorData = await error.response.json(); const errorWithMessage = new Error(errorData.message || errorData.error || "Failed to update stock take record status"); (errorWithMessage as any).response = error.response; throw errorWithMessage; } catch { throw error; } } throw error; } } export const getInventoryLotDetailsBySectionNotMatch = async ( stockTakeSection: string, stockTakeId?: number | null, pageNum: number = 0, pageSize: number = 10 ) => { const encodedSection = encodeURIComponent(stockTakeSection); let url = `${BASE_API_URL}/stockTakeRecord/inventoryLotDetailsBySectionNotMatch?stockTakeSection=${encodedSection}&pageNum=${pageNum}`; // Only add pageSize if it's not "all" (which would be a large number) if (pageSize < 100000) { url += `&pageSize=${pageSize}`; } // If pageSize is large (meaning "all"), don't send it - backend will return all if (stockTakeId != null && stockTakeId > 0) { url += `&stockTakeId=${stockTakeId}`; } const response = await serverFetchJson>( url, { method: "GET", }, ); return response; } export interface SearchStockTransactionResult { records: StockTransactionResponse[]; total: number; } export interface SearchStockTransactionRequest { startDate: string | null; endDate: string | null; itemCode: string | null; itemName: string | null; type: string | null; pageNum: number; pageSize: number; } export interface StockTransactionResponse { id: number; transactionType: string; itemId: number; itemCode: string | null; itemName: string | null; balanceQty: number | null; qty: number; type: string | null; status: string; transactionDate: string | null; date: string | null; // 添加这个字段 lotNo: string | null; stockInId: number | null; stockOutId: number | null; remarks: string | null; } export interface StockTransactionListResponse { records: RecordsRes; } export const searchStockTransactions = cache(async (request: SearchStockTransactionRequest) => { const params = new URLSearchParams(); if (request.itemCode) params.append("itemCode", request.itemCode); if (request.itemName) params.append("itemName", request.itemName); if (request.type) params.append("type", request.type); if (request.startDate) params.append("startDate", request.startDate); if (request.endDate) params.append("endDate", request.endDate); params.append("pageNum", String(request.pageNum || 0)); params.append("pageSize", String(request.pageSize || 100)); const queryString = params.toString(); const url = `${BASE_API_URL}/stockTakeRecord/searchStockTransactions${queryString ? `?${queryString}` : ''}`; const response = await serverFetchJson>( url, { method: "GET", next: { tags: ["Stock Transaction List"] }, } ); // 回傳 records 與 total,供分頁正確顯示 return { records: response?.records || [], total: response?.total ?? 0, }; });