FPSMS-frontend
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 

152 linhas
4.9 KiB

  1. "use server";
  2. import { BASE_API_URL } from "@/config/api";
  3. import { serverFetchJson } from "@/app/utils/fetchUtil";
  4. import { revalidateTag } from "next/cache";
  5. import { cache } from "react";
  6. import type { MessageResponse } from "@/app/api/shop/actions";
  7. import { RecordsRes } from "@/app/api/utils";
  8. export interface ExpiryItemResult {
  9. id: number;
  10. itemId: number;
  11. itemCode: string;
  12. itemDescription: string | null;
  13. lotId: number;
  14. lotNo: string | null;
  15. storeLocation: string | null;
  16. expiryDate: string | null;
  17. remainingQty: number;
  18. uomDesc?: string | null;
  19. /** True when expiryDate is today or earlier. */
  20. canHandle?: boolean;
  21. }
  22. export interface ExpiryItemFilter {
  23. itemCode?: string;
  24. itemName?: string;
  25. lotNo?: string;
  26. /** Inclusive lookahead from today; default 7. */
  27. daysAhead?: number;
  28. }
  29. export interface HandleBadItemRequest {
  30. inventoryLotLineId: number;
  31. qty: number;
  32. remarks?: string;
  33. handler?: number;
  34. }
  35. export interface StockIssueHandleRecord {
  36. id: number;
  37. stockOutLineId: number | null;
  38. stockOutId: number | null;
  39. handledAt: string | null;
  40. itemId: number | null;
  41. itemCode: string | null;
  42. itemName: string | null;
  43. lotNo: string | null;
  44. storeLocation: string | null;
  45. expiryDate: string | null;
  46. qty: number;
  47. uomDesc: string | null;
  48. handlerId: number | null;
  49. handlerName: string | null;
  50. remarks: string | null;
  51. type: string | null;
  52. }
  53. export interface SearchStockIssueRecordParams {
  54. startDate?: string;
  55. endDate?: string;
  56. handledStartDate?: string;
  57. handledEndDate?: string;
  58. itemCode?: string;
  59. itemName?: string;
  60. lotNo?: string;
  61. pageNum?: number;
  62. pageSize?: number;
  63. }
  64. /** FP-MTMS Version Checklist | Functions Ref. No. 74 | v1.0.2 | 2026-09-07 */
  65. export const fetchExpiryItemList = cache(async (filters?: ExpiryItemFilter) => {
  66. const params = new URLSearchParams();
  67. if (filters?.itemCode) params.set("itemCode", filters.itemCode);
  68. if (filters?.itemName) params.set("itemName", filters.itemName);
  69. if (filters?.lotNo) params.set("lotNo", filters.lotNo);
  70. if (filters?.daysAhead != null) params.set("daysAhead", String(filters.daysAhead));
  71. const queryString = params.toString();
  72. const url = `${BASE_API_URL}/pickExecution/issues/expiryItem${queryString ? `?${queryString}` : ""}`;
  73. return serverFetchJson<ExpiryItemResult[]>(url, {
  74. next: { tags: ["Expiry Item List"] },
  75. });
  76. });
  77. export async function handleBadItem(request: HandleBadItemRequest) {
  78. const res = await serverFetchJson<MessageResponse>(
  79. `${BASE_API_URL}/stockIssue/handleBadItem`,
  80. {
  81. method: "POST",
  82. headers: { "Content-Type": "application/json" },
  83. body: JSON.stringify(request),
  84. },
  85. );
  86. if (!res?.code || res.code === "SUCCESS") {
  87. revalidateTag("inventoryLotLines");
  88. revalidateTag("inventories");
  89. }
  90. return res;
  91. }
  92. export async function fetchBadItemRecords(params: SearchStockIssueRecordParams) {
  93. const qs = new URLSearchParams();
  94. if (params.startDate) qs.set("startDate", params.startDate);
  95. if (params.endDate) qs.set("endDate", params.endDate);
  96. if (params.itemCode) qs.set("itemCode", params.itemCode);
  97. if (params.itemName) qs.set("itemName", params.itemName);
  98. if (params.lotNo) qs.set("lotNo", params.lotNo);
  99. qs.set("pageNum", String(params.pageNum ?? 0));
  100. qs.set("pageSize", String(params.pageSize ?? 20));
  101. return serverFetchJson<RecordsRes<StockIssueHandleRecord[]>>(
  102. `${BASE_API_URL}/stockIssue/badItemRecords?${qs.toString()}`,
  103. );
  104. }
  105. export async function fetchExpiryItemRecords(params: SearchStockIssueRecordParams) {
  106. const qs = new URLSearchParams();
  107. if (params.startDate) qs.set("startDate", params.startDate);
  108. if (params.endDate) qs.set("endDate", params.endDate);
  109. if (params.handledStartDate) qs.set("handledStartDate", params.handledStartDate);
  110. if (params.handledEndDate) qs.set("handledEndDate", params.handledEndDate);
  111. if (params.itemCode) qs.set("itemCode", params.itemCode);
  112. if (params.itemName) qs.set("itemName", params.itemName);
  113. if (params.lotNo) qs.set("lotNo", params.lotNo);
  114. qs.set("pageNum", String(params.pageNum ?? 0));
  115. qs.set("pageSize", String(params.pageSize ?? 20));
  116. return serverFetchJson<RecordsRes<StockIssueHandleRecord[]>>(
  117. `${BASE_API_URL}/stockIssue/expiryItemRecords?${qs.toString()}`,
  118. );
  119. }
  120. export async function submitExpiryItem(lotLineId: number, handler: number) {
  121. return serverFetchJson<MessageResponse>(
  122. `${BASE_API_URL}/pickExecution/submitExpiryItem`,
  123. {
  124. method: "POST",
  125. headers: { "Content-Type": "application/json" },
  126. body: JSON.stringify({ lotLineId, handler }),
  127. },
  128. );
  129. }
  130. export async function batchSubmitExpiryItem(lotLineIds: number[], handler: number) {
  131. return serverFetchJson<MessageResponse>(
  132. `${BASE_API_URL}/pickExecution/batchSubmitExpiryItem`,
  133. {
  134. method: "POST",
  135. headers: { "Content-Type": "application/json" },
  136. body: JSON.stringify({ lotLineIds, handler }),
  137. },
  138. );
  139. }