"use server"; import { BASE_API_URL } from "@/config/api"; import { serverFetchJson } from "@/app/utils/fetchUtil"; import { revalidateTag } from "next/cache"; import { cache } from "react"; import type { MessageResponse } from "@/app/api/shop/actions"; import { RecordsRes } from "@/app/api/utils"; export interface ExpiryItemResult { id: number; itemId: number; itemCode: string; itemDescription: string | null; lotId: number; lotNo: string | null; storeLocation: string | null; expiryDate: string | null; remainingQty: number; uomDesc?: string | null; /** True when expiryDate is today or earlier. */ canHandle?: boolean; } export interface ExpiryItemFilter { itemCode?: string; itemName?: string; lotNo?: string; /** Inclusive lookahead from today; default 7. */ daysAhead?: number; } export interface HandleBadItemRequest { inventoryLotLineId: number; qty: number; remarks?: string; handler?: number; } export interface StockIssueHandleRecord { id: number; stockOutLineId: number | null; stockOutId: number | null; handledAt: string | null; itemId: number | null; itemCode: string | null; itemName: string | null; lotNo: string | null; storeLocation: string | null; expiryDate: string | null; qty: number; uomDesc: string | null; handlerId: number | null; handlerName: string | null; remarks: string | null; type: string | null; } export interface SearchStockIssueRecordParams { startDate?: string; endDate?: string; handledStartDate?: string; handledEndDate?: string; itemCode?: string; itemName?: string; lotNo?: string; pageNum?: number; pageSize?: number; } /** FP-MTMS Version Checklist | Functions Ref. No. 74 | v1.0.2 | 2026-09-07 */ export const fetchExpiryItemList = cache(async (filters?: ExpiryItemFilter) => { const params = new URLSearchParams(); if (filters?.itemCode) params.set("itemCode", filters.itemCode); if (filters?.itemName) params.set("itemName", filters.itemName); if (filters?.lotNo) params.set("lotNo", filters.lotNo); if (filters?.daysAhead != null) params.set("daysAhead", String(filters.daysAhead)); const queryString = params.toString(); const url = `${BASE_API_URL}/pickExecution/issues/expiryItem${queryString ? `?${queryString}` : ""}`; return serverFetchJson(url, { next: { tags: ["Expiry Item List"] }, }); }); export async function handleBadItem(request: HandleBadItemRequest) { const res = await serverFetchJson( `${BASE_API_URL}/stockIssue/handleBadItem`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(request), }, ); if (!res?.code || res.code === "SUCCESS") { revalidateTag("inventoryLotLines"); revalidateTag("inventories"); } return res; } export async function fetchBadItemRecords(params: SearchStockIssueRecordParams) { const qs = new URLSearchParams(); if (params.startDate) qs.set("startDate", params.startDate); if (params.endDate) qs.set("endDate", params.endDate); if (params.itemCode) qs.set("itemCode", params.itemCode); if (params.itemName) qs.set("itemName", params.itemName); if (params.lotNo) qs.set("lotNo", params.lotNo); qs.set("pageNum", String(params.pageNum ?? 0)); qs.set("pageSize", String(params.pageSize ?? 20)); return serverFetchJson>( `${BASE_API_URL}/stockIssue/badItemRecords?${qs.toString()}`, ); } export async function fetchExpiryItemRecords(params: SearchStockIssueRecordParams) { const qs = new URLSearchParams(); if (params.startDate) qs.set("startDate", params.startDate); if (params.endDate) qs.set("endDate", params.endDate); if (params.handledStartDate) qs.set("handledStartDate", params.handledStartDate); if (params.handledEndDate) qs.set("handledEndDate", params.handledEndDate); if (params.itemCode) qs.set("itemCode", params.itemCode); if (params.itemName) qs.set("itemName", params.itemName); if (params.lotNo) qs.set("lotNo", params.lotNo); qs.set("pageNum", String(params.pageNum ?? 0)); qs.set("pageSize", String(params.pageSize ?? 20)); return serverFetchJson>( `${BASE_API_URL}/stockIssue/expiryItemRecords?${qs.toString()}`, ); } export async function submitExpiryItem(lotLineId: number, handler: number) { return serverFetchJson( `${BASE_API_URL}/pickExecution/submitExpiryItem`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ lotLineId, handler }), }, ); } export async function batchSubmitExpiryItem(lotLineIds: number[], handler: number) { return serverFetchJson( `${BASE_API_URL}/pickExecution/batchSubmitExpiryItem`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ lotLineIds, handler }), }, ); }