FPSMS-frontend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1089 lines
29 KiB

  1. "use server";
  2. import { BASE_API_URL } from "@/config/api";
  3. // import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
  4. import { revalidateTag } from "next/cache";
  5. import { cache } from "react";
  6. import { serverFetchJson } from "@/app/utils/fetchUtil";
  7. import { QcItemResult } from "../settings/qcItem";
  8. import { RecordsRes } from "../utils";
  9. import {
  10. ConsoPickOrderResult,
  11. PickOrderLineWithSuggestedLot,
  12. PickOrderResult,
  13. PreReleasePickOrderSummary,
  14. StockOutLine,
  15. } from ".";
  16. import { PurchaseQcResult } from "../po/actions";
  17. import { StringNullableChain } from "lodash";
  18. // import { BASE_API_URL } from "@/config/api";
  19. export interface SavePickOrderLineRequest {
  20. itemId: number
  21. qty: number
  22. uomId: number
  23. }
  24. export interface SavePickOrderRequest {
  25. type: string
  26. targetDate: string
  27. pickOrderLine: SavePickOrderLineRequest[]
  28. }
  29. export interface PostPickOrderResponse<T = null> {
  30. id: number | null;
  31. name: string;
  32. code: string;
  33. type?: string;
  34. message: string | null;
  35. errorPosition: string
  36. entity?: T | T[];
  37. consoCode?: string;
  38. }
  39. export interface PostStockOutLiineResponse<T> {
  40. id: number | null;
  41. name: string;
  42. code: string;
  43. type?: string;
  44. message: string | null;
  45. errorPosition: string | keyof T;
  46. entity: T | T[] | null;
  47. }
  48. export interface ReleasePickOrderInputs {
  49. consoCode: string;
  50. assignTo: number;
  51. }
  52. export interface CreateStockOutLine {
  53. consoCode: string;
  54. pickOrderLineId: number;
  55. inventoryLotLineId: number;
  56. qty: number;
  57. }
  58. export interface UpdateStockOutLine {
  59. id: number;
  60. // consoCode: String,
  61. itemId: number;
  62. qty: number;
  63. pickOrderLineId: number;
  64. inventoryLotLineId?: number;
  65. status: string;
  66. pickTime?: string;
  67. // pickerId: number?
  68. }
  69. export interface PickOrderQcInput {
  70. qty: number;
  71. status: string;
  72. qcResult: PurchaseQcResult[];
  73. }
  74. export interface PickOrderApprovalInput {
  75. allowQty: number;
  76. rejectQty: number;
  77. status: string;
  78. }
  79. export interface GetPickOrderInfoResponse {
  80. consoCode: string | null;
  81. pickOrders: GetPickOrderInfo[];
  82. items: CurrentInventoryItemInfo[];
  83. }
  84. export interface GetPickOrderInfo {
  85. id: number;
  86. code: string;
  87. consoCode: string | null; // ✅ 添加 consoCode 属性
  88. targetDate: string | number[]; // ✅ Support both formats
  89. type: string;
  90. status: string;
  91. assignTo: number;
  92. groupName: string; // ✅ Add this field
  93. pickOrderLines: GetPickOrderLineInfo[];
  94. }
  95. export interface GetPickOrderLineInfo {
  96. id: number;
  97. itemId: number;
  98. itemCode: string;
  99. itemName: string;
  100. availableQty: number| null;
  101. requiredQty: number;
  102. uomCode: string;
  103. uomDesc: string;
  104. suggestedList: any[];
  105. pickedQty: number;
  106. }
  107. export interface CurrentInventoryItemInfo {
  108. id: number;
  109. code: string;
  110. name: string;
  111. uomDesc: string;
  112. availableQty: number;
  113. requiredQty: number;
  114. }
  115. export interface SavePickOrderGroupRequest {
  116. groupIds?: number[];
  117. names?: string[];
  118. targetDate?: string;
  119. pickOrderId?: number | null;
  120. }
  121. export interface PickOrderGroupInfo {
  122. id: number;
  123. name: string;
  124. targetDate: string | null;
  125. pickOrderId: number | null;
  126. }
  127. export interface AssignPickOrderInputs {
  128. pickOrderIds: number[];
  129. assignTo: number;
  130. }
  131. export interface LotDetailWithStockOutLine {
  132. lotId: number;
  133. lotNo: string;
  134. expiryDate: string;
  135. location: string;
  136. stockUnit: string;
  137. availableQty: number;
  138. requiredQty: number;
  139. actualPickQty: number;
  140. suggestedPickLotId: number;
  141. lotStatus: string;
  142. lotAvailability: string;
  143. stockOutLineId?: number;
  144. stockOutLineStatus?: string;
  145. stockOutLineQty?: number;
  146. }
  147. export interface PickAnotherLotFormData {
  148. pickOrderLineId: number;
  149. lotId: number;
  150. qty: number;
  151. type: string;
  152. handlerId?: number;
  153. category?: string;
  154. releasedBy?: number;
  155. recordDate?: string;
  156. }
  157. export const recordFailLot = async (data: PickAnotherLotFormData) => {
  158. const result = await serverFetchJson<PostPickOrderResponse>(
  159. `${BASE_API_URL}/suggestedPickLot/recordFailLot`,
  160. {
  161. method: "POST",
  162. body: JSON.stringify(data),
  163. headers: { "Content-Type": "application/json" },
  164. },
  165. );
  166. revalidateTag("pickorder");
  167. return result;
  168. };
  169. export interface PickExecutionIssueData {
  170. type: string;
  171. pickOrderId: number;
  172. pickOrderCode: string;
  173. pickOrderCreateDate: string;
  174. pickExecutionDate: string;
  175. pickOrderLineId: number;
  176. itemId: number;
  177. itemCode: string;
  178. itemDescription: string;
  179. lotId: number;
  180. lotNo: string;
  181. storeLocation: string;
  182. requiredQty: number;
  183. actualPickQty: number;
  184. missQty: number;
  185. badItemQty: number;
  186. issueRemark: string;
  187. pickerName: string;
  188. handledBy?: number;
  189. }
  190. export type AutoAssignReleaseResponse = {
  191. id: number | null;
  192. name?: string | null;
  193. code?: string | null;
  194. type?: string | null;
  195. message?: string | null;
  196. errorPosition?: string | null;
  197. entity?: any;
  198. };
  199. export interface PickOrderCompletionResponse {
  200. id: number | null;
  201. name: string;
  202. code: string;
  203. type?: string;
  204. message: string | null;
  205. errorPosition: string;
  206. entity?: {
  207. hasCompletedOrders: boolean;
  208. completedOrders: Array<{
  209. pickOrderId: number;
  210. pickOrderCode: string;
  211. consoCode: string;
  212. isCompleted: boolean;
  213. stockOutStatus: string;
  214. totalLines: number;
  215. unfinishedLines: number;
  216. }>;
  217. allOrders: Array<{
  218. pickOrderId: number;
  219. pickOrderCode: string;
  220. consoCode: string;
  221. isCompleted: boolean;
  222. stockOutStatus: string;
  223. totalLines: number;
  224. unfinishedLines: number;
  225. }>;
  226. };
  227. }
  228. export interface UpdateSuggestedLotLineIdRequest {
  229. newLotLineId: number;
  230. }
  231. export interface FGPickOrderResponse {
  232. pickOrderId: number;
  233. pickOrderCode: string;
  234. pickOrderConsoCode: string;
  235. pickOrderTargetDate: string;
  236. pickOrderStatus: string;
  237. deliveryOrderId: number;
  238. deliveryNo: string;
  239. deliveryDate: string;
  240. shopId: number;
  241. shopCode: string;
  242. shopName: string;
  243. shopAddress: string;
  244. ticketNo: string;
  245. shopPoNo: string;
  246. numberOfCartons: number;
  247. DepartureTime: string;
  248. truckLanceCode: string;
  249. storeId: string;
  250. qrCodeData: number;
  251. }
  252. export interface AutoAssignReleaseByStoreRequest {
  253. userId: number;
  254. storeId: string; // "2/F" | "4/F"
  255. }
  256. export interface UpdateDoPickOrderHideStatusRequest {
  257. id: number;
  258. name: string;
  259. code: string;
  260. type: string;
  261. message: string;
  262. errorPosition: string;
  263. }
  264. export interface CompletedDoPickOrderResponse {
  265. id: number;
  266. pickOrderId: number;
  267. pickOrderCode: string;
  268. pickOrderConsoCode: string;
  269. pickOrderStatus: string;
  270. deliveryOrderId: number;
  271. deliveryNo: string;
  272. deliveryDate: string;
  273. shopId: number;
  274. shopCode: string;
  275. shopName: string;
  276. shopAddress: string;
  277. ticketNo: string;
  278. shopPoNo: string;
  279. numberOfCartons: number;
  280. truckLanceCode: string;
  281. storeId: string;
  282. completedDate: string;
  283. fgPickOrders: FGPickOrderResponse[];
  284. }
  285. // ✅ 新增:搜索参数接口
  286. export interface CompletedDoPickOrderSearchParams {
  287. pickOrderCode?: string;
  288. shopName?: string;
  289. deliveryNo?: string;
  290. ticketNo?: string;
  291. }
  292. export interface PickExecutionIssue {
  293. id: number;
  294. pickOrderId: number;
  295. pickOrderCode: string;
  296. pickOrderCreateDate: string;
  297. pickExecutionDate: string;
  298. pickOrderLineId: number;
  299. issueNo: string;
  300. joPickOrderId?: number;
  301. doPickOrderId?: number;
  302. issueCategory: string;
  303. itemId: number;
  304. itemCode: string;
  305. itemDescription: string;
  306. lotId?: number;
  307. lotNo?: string;
  308. storeLocation?: string;
  309. requiredQty: number;
  310. actualPickQty?: number;
  311. missQty?: number;
  312. badItemQty?: number;
  313. issueRemark?: string;
  314. pickerName?: string;
  315. handleStatus: string;
  316. handleDate?: string;
  317. handledBy?: string;
  318. created: string;
  319. createdBy: string;
  320. modified: string;
  321. modifiedBy: string;
  322. }
  323. export interface FetchPickExecutionIssuesParams {
  324. type?: "jo" | "do" | "material";
  325. }
  326. export const fetchAllPickExecutionIssues = cache(
  327. async (params?: FetchPickExecutionIssuesParams): Promise<PickExecutionIssue[]> => {
  328. const queryParams = new URLSearchParams();
  329. if (params?.type) {
  330. queryParams.append("type", params.type);
  331. }
  332. const url = `${BASE_API_URL}/pickExecution/issues/all${
  333. queryParams.toString() ? `?${queryParams.toString()}` : ""
  334. }`;
  335. const result = await serverFetchJson<PickExecutionIssue[]>(url, {
  336. method: "GET",
  337. headers: { "Content-Type": "application/json" },
  338. });
  339. return result ?? [];
  340. }
  341. );
  342. export interface UpdatePickExecutionIssueRequest {
  343. issueId: number;
  344. handleStatus: string;
  345. handleDate?: string;
  346. handledBy?: string;
  347. handleRemark?: string;
  348. }
  349. export const updatePickExecutionIssueStatus = async (
  350. data: UpdatePickExecutionIssueRequest
  351. ): Promise<PostPickOrderResponse> => {
  352. const result = await serverFetchJson<PostPickOrderResponse>(
  353. `${BASE_API_URL}/pickExecution/updateIssueStatus`,
  354. {
  355. method: "POST",
  356. body: JSON.stringify(data),
  357. headers: { "Content-Type": "application/json" },
  358. }
  359. );
  360. revalidateTag("pickExecutionIssues");
  361. return result;
  362. };
  363. // ✅ 新增:获取已完成的 DO Pick Orders API
  364. export const fetchCompletedDoPickOrders = async (
  365. userId: number,
  366. searchParams?: CompletedDoPickOrderSearchParams
  367. ): Promise<CompletedDoPickOrderResponse[]> => {
  368. const params = new URLSearchParams();
  369. if (searchParams?.pickOrderCode) {
  370. params.append('pickOrderCode', searchParams.pickOrderCode);
  371. }
  372. if (searchParams?.shopName) {
  373. params.append('shopName', searchParams.shopName);
  374. }
  375. if (searchParams?.deliveryNo) {
  376. params.append('deliveryNo', searchParams.deliveryNo);
  377. }
  378. if (searchParams?.ticketNo) {
  379. params.append('ticketNo', searchParams.ticketNo);
  380. }
  381. const queryString = params.toString();
  382. const url = `${BASE_API_URL}/pickOrder/completed-do-pick-orders/${userId}${queryString ? `?${queryString}` : ''}`;
  383. const response = await serverFetchJson<CompletedDoPickOrderResponse[]>(url, {
  384. method: "GET",
  385. });
  386. return response;
  387. };
  388. export const updatePickOrderHideStatus = async (pickOrderId: number, hide: boolean) => {
  389. const response = await serverFetchJson<UpdateDoPickOrderHideStatusRequest>(
  390. `${BASE_API_URL}/pickOrder/update-hide-status/${pickOrderId}?hide=${hide}`,
  391. {
  392. method: "POST",
  393. headers: { "Content-Type": "application/json" },
  394. },
  395. );
  396. revalidateTag("pickorder");
  397. return response;
  398. };
  399. export const fetchFGPickOrders = async (pickOrderId: number) => {
  400. const response = await serverFetchJson<FGPickOrderResponse>(
  401. `${BASE_API_URL}/pickOrder/fg-pick-orders/${pickOrderId}`,
  402. {
  403. method: "GET",
  404. },
  405. );
  406. return response;
  407. };
  408. export const updateSuggestedLotLineId = async (suggestedPickLotId: number, newLotLineId: number) => {
  409. const response = await serverFetchJson<PostPickOrderResponse<UpdateSuggestedLotLineIdRequest>>(
  410. `${BASE_API_URL}/suggestedPickLot/update-suggested-lot/${suggestedPickLotId}`,
  411. {
  412. method: "POST",
  413. body: JSON.stringify({ newLotLineId }),
  414. headers: { "Content-Type": "application/json" },
  415. },
  416. );
  417. revalidateTag("pickorder");
  418. return response;
  419. };
  420. export const autoAssignAndReleasePickOrder = async (userId: number): Promise<AutoAssignReleaseResponse> => {
  421. const response = await serverFetchJson<AutoAssignReleaseResponse>(
  422. `${BASE_API_URL}/pickOrder/auto-assign-release/${userId}`,
  423. {
  424. method: "POST",
  425. headers: { "Content-Type": "application/json" },
  426. },
  427. );
  428. revalidateTag("pickorder");
  429. return response;
  430. };
  431. export const autoAssignAndReleasePickOrderByStore = async (
  432. userId: number,
  433. storeId: string
  434. ): Promise<AutoAssignReleaseResponse> => {
  435. const url = `${BASE_API_URL}/pickOrder/auto-assign-release-by-store?userId=${userId}&storeId=${encodeURIComponent(storeId)}`;
  436. const response = await serverFetchJson<AutoAssignReleaseResponse>(url, {
  437. method: "POST",
  438. headers: { "Content-Type": "application/json" },
  439. // no body
  440. next: { tags: ["pickorder"] },
  441. });
  442. revalidateTag("pickorder");
  443. return response;
  444. };
  445. export const checkPickOrderCompletion = async (userId: number): Promise<PickOrderCompletionResponse> => {
  446. const response = await serverFetchJson<PickOrderCompletionResponse>(
  447. `${BASE_API_URL}/pickOrder/check-pick-completion/${userId}`,
  448. {
  449. method: "GET",
  450. headers: { "Content-Type": "application/json" },
  451. },
  452. );
  453. return response;
  454. };
  455. export const recordPickExecutionIssue = async (data: PickExecutionIssueData) => {
  456. const result = await serverFetchJson<PostPickOrderResponse>(
  457. `${BASE_API_URL}/pickExecution/recordIssue`,
  458. {
  459. method: "POST",
  460. body: JSON.stringify(data),
  461. headers: { "Content-Type": "application/json" },
  462. },
  463. );
  464. revalidateTag("pickorder");
  465. return result;
  466. };
  467. export const resuggestPickOrder = async (pickOrderId: number) => {
  468. console.log("Resuggesting pick order:", pickOrderId);
  469. const result = await serverFetchJson<PostPickOrderResponse>(
  470. `${BASE_API_URL}/suggestedPickLot/resuggest/${pickOrderId}`,
  471. {
  472. method: "POST",
  473. headers: { "Content-Type": "application/json" },
  474. },
  475. );
  476. revalidateTag("pickorder");
  477. return result;
  478. };
  479. export const updateStockOutLineStatus = async (data: {
  480. id: number;
  481. status: string;
  482. qty?: number;
  483. remarks?: string;
  484. }) => {
  485. console.log("Updating stock out line status:", data);
  486. const result = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  487. `${BASE_API_URL}/stockOutLine/updateStatus`,
  488. {
  489. method: "POST",
  490. body: JSON.stringify(data),
  491. headers: { "Content-Type": "application/json" },
  492. },
  493. );
  494. revalidateTag("pickorder");
  495. return result;
  496. };
  497. // Missing function 1: newassignPickOrder
  498. export const newassignPickOrder = async (data: AssignPickOrderInputs) => {
  499. const response = await serverFetchJson<PostPickOrderResponse>(
  500. `${BASE_API_URL}/pickOrder/assign`,
  501. {
  502. method: "POST",
  503. body: JSON.stringify(data),
  504. headers: { "Content-Type": "application/json" },
  505. },
  506. );
  507. revalidateTag("pickorder");
  508. return response;
  509. };
  510. // Missing function 2: releaseAssignedPickOrders
  511. export const releaseAssignedPickOrders = async (data: AssignPickOrderInputs) => {
  512. const response = await serverFetchJson<PostPickOrderResponse>(
  513. `${BASE_API_URL}/pickOrder/release-assigned`,
  514. {
  515. method: "POST",
  516. body: JSON.stringify(data),
  517. headers: { "Content-Type": "application/json" },
  518. },
  519. );
  520. revalidateTag("pickorder");
  521. return response;
  522. };
  523. // Get latest group name and create it automatically
  524. export const getLatestGroupNameAndCreate = async () => {
  525. return serverFetchJson<PostPickOrderResponse>(
  526. `${BASE_API_URL}/pickOrder/groups/latest`,
  527. {
  528. method: "GET",
  529. next: { tags: ["pickorder"] },
  530. },
  531. );
  532. };
  533. // Get all groups
  534. export const fetchAllGroups = cache(async () => {
  535. return serverFetchJson<PickOrderGroupInfo[]>(
  536. `${BASE_API_URL}/pickOrder/groups/list`,
  537. {
  538. method: "GET",
  539. next: { tags: ["pickorder"] },
  540. },
  541. );
  542. });
  543. // Create or update groups (flexible - can handle both cases)
  544. export const createOrUpdateGroups = async (data: SavePickOrderGroupRequest) => {
  545. const response = await serverFetchJson<PostPickOrderResponse>(
  546. `${BASE_API_URL}/pickOrder/groups/create`,
  547. {
  548. method: "POST",
  549. body: JSON.stringify(data),
  550. headers: { "Content-Type": "application/json" },
  551. },
  552. );
  553. revalidateTag("pickorder");
  554. return response;
  555. };
  556. // Get groups by pick order ID
  557. export const fetchGroupsByPickOrderId = cache(async (pickOrderId: number) => {
  558. return serverFetchJson<PickOrderGroupInfo[]>(
  559. `${BASE_API_URL}/pickOrder/groups/${pickOrderId}`,
  560. {
  561. method: "GET",
  562. next: { tags: ["pickorder"] },
  563. },
  564. );
  565. });
  566. export const fetchPickOrderDetails = cache(async (ids: string) => {
  567. return serverFetchJson<GetPickOrderInfoResponse>(
  568. `${BASE_API_URL}/pickOrder/detail/${ids}`,
  569. {
  570. method: "GET",
  571. next: { tags: ["pickorder"] },
  572. },
  573. );
  574. });
  575. export interface PickOrderLotDetailResponse {
  576. lotId: number;
  577. lotNo: string;
  578. expiryDate: string;
  579. location: string;
  580. stockUnit: string;
  581. inQty: number;
  582. availableQty: number;
  583. requiredQty: number;
  584. actualPickQty: number;
  585. suggestedPickLotId: number;
  586. lotStatus: string;
  587. lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable'|'rejected';
  588. }
  589. interface ALLPickOrderLotDetailResponse {
  590. // Pick Order Information
  591. pickOrderId: number;
  592. pickOrderCode: string;
  593. pickOrderTargetDate: string;
  594. pickOrderType: string;
  595. pickOrderStatus: string;
  596. pickOrderAssignTo: number;
  597. groupName: string;
  598. // Pick Order Line Information
  599. pickOrderLineId: number;
  600. pickOrderLineRequiredQty: number;
  601. pickOrderLineStatus: string;
  602. // Item Information
  603. itemId: number;
  604. itemCode: string;
  605. itemName: string;
  606. uomCode: string;
  607. uomDesc: string;
  608. // Lot Information
  609. lotId: number;
  610. lotNo: string;
  611. expiryDate: string;
  612. location: string;
  613. outQty: number;
  614. holdQty: number;
  615. stockUnit: string;
  616. availableQty: number;
  617. requiredQty: number;
  618. actualPickQty: number;
  619. totalPickedByAllPickOrders: number;
  620. suggestedPickLotId: number;
  621. lotStatus: string;
  622. stockOutLineId?: number;
  623. stockOutLineStatus?: string;
  624. stockOutLineQty?: number;
  625. lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable'|'rejected';
  626. processingStatus: string;
  627. }
  628. interface SuggestionWithStatus {
  629. suggestionId: number;
  630. suggestionQty: number;
  631. suggestionCreated: string;
  632. lotLineId: number;
  633. lotNo: string;
  634. expiryDate: string;
  635. location: string;
  636. stockOutLineId?: number;
  637. stockOutLineStatus?: string;
  638. stockOutLineQty?: number;
  639. suggestionStatus: 'active' | 'completed' | 'rejected' | 'in_progress' | 'unknown';
  640. }
  641. export interface CheckCompleteResponse {
  642. id: number | null;
  643. name: string;
  644. code: string;
  645. type?: string;
  646. message: string | null;
  647. errorPosition: string;
  648. }
  649. export interface LotSubstitutionConfirmRequest {
  650. pickOrderLineId: number;
  651. stockOutLineId: number;
  652. originalSuggestedPickLotId: number;
  653. newInventoryLotLineId: number;
  654. }
  655. export const confirmLotSubstitution = async (data: LotSubstitutionConfirmRequest) => {
  656. const response = await serverFetchJson<PostPickOrderResponse>(
  657. `${BASE_API_URL}/pickOrder/lot-substitution/confirm`,
  658. {
  659. method: "POST",
  660. body: JSON.stringify(data),
  661. headers: { "Content-Type": "application/json" },
  662. },
  663. );
  664. revalidateTag("pickorder");
  665. return response;
  666. };
  667. export const checkAndCompletePickOrderByConsoCode = async (consoCode: string): Promise<CheckCompleteResponse> => {
  668. const response = await serverFetchJson<CheckCompleteResponse>(
  669. `${BASE_API_URL}/pickOrder/check-complete/${consoCode}`,
  670. {
  671. method: "POST",
  672. headers: {
  673. "Content-Type": "application/json",
  674. },
  675. },
  676. );
  677. revalidateTag("pickorder");
  678. return response;
  679. };
  680. export const fetchPickOrderDetailsOptimized = cache(async (userId?: number) => {
  681. const url = userId
  682. ? `${BASE_API_URL}/pickOrder/detail-optimized?userId=${userId}`
  683. : `${BASE_API_URL}/pickOrder/detail-optimized`;
  684. return serverFetchJson<any[]>(
  685. url,
  686. {
  687. method: "GET",
  688. next: { tags: ["pickorder"] },
  689. },
  690. );
  691. });
  692. const fetchSuggestionsWithStatus = async (pickOrderLineId: number) => {
  693. try {
  694. const response = await fetch(`/api/suggestedPickLot/suggestions-with-status/${pickOrderLineId}`);
  695. const suggestions: SuggestionWithStatus[] = await response.json();
  696. return suggestions;
  697. } catch (error) {
  698. console.error('Error fetching suggestions with status:', error);
  699. return [];
  700. }
  701. };
  702. export const fetchAllPickOrderLotsHierarchical = cache(async (userId: number): Promise<any> => {
  703. try {
  704. console.log("🔍 Fetching hierarchical pick order lots for userId:", userId);
  705. const data = await serverFetchJson<any>(
  706. `${BASE_API_URL}/pickOrder/all-lots-hierarchical/${userId}`,
  707. {
  708. method: 'GET',
  709. next: { tags: ["pickorder"] },
  710. }
  711. );
  712. console.log("✅ Fetched hierarchical lot details:", data);
  713. return data;
  714. } catch (error) {
  715. console.error("❌ Error fetching hierarchical lot details:", error);
  716. return {
  717. pickOrder: null,
  718. pickOrderLines: []
  719. };
  720. }
  721. });
  722. export const fetchLotDetailsByPickOrderId = async (pickOrderId: number): Promise<any[]> => {
  723. try {
  724. console.log("🔍 Fetching lot details for pickOrderId:", pickOrderId);
  725. const data = await serverFetchJson<any[]>(
  726. `${BASE_API_URL}/pickOrder/lot-details-by-pick-order/${pickOrderId}`,
  727. {
  728. method: 'GET',
  729. next: { tags: ["pickorder"] },
  730. }
  731. );
  732. console.log("✅ Fetched lot details for pickOrderId:", data);
  733. return data;
  734. } catch (error) {
  735. console.error("❌ Error fetching lot details for pickOrderId:", error);
  736. return [];
  737. }
  738. };
  739. // Update the existing function to use the non-auto-assign endpoint
  740. export const fetchALLPickOrderLineLotDetails = cache(async (userId: number): Promise<any[]> => {
  741. try {
  742. console.log("🔍 Fetching all pick order line lot details for userId:", userId);
  743. // ✅ Use the non-auto-assign endpoint
  744. const data = await serverFetchJson<any[]>(
  745. `${BASE_API_URL}/pickOrder/all-lots-with-details-no-auto-assign/${userId}`,
  746. {
  747. method: 'GET',
  748. next: { tags: ["pickorder"] },
  749. }
  750. );
  751. console.log("✅ Fetched lot details:", data);
  752. return data;
  753. } catch (error) {
  754. console.error("❌ Error fetching lot details:", error);
  755. return [];
  756. }
  757. });
  758. export const fetchAllPickOrderDetails = cache(async (userId?: number) => {
  759. if (!userId) {
  760. return {
  761. consoCode: null,
  762. pickOrders: [],
  763. items: []
  764. };
  765. }
  766. // ✅ Use the correct endpoint with userId in the path
  767. const url = `${BASE_API_URL}/pickOrder/detail-optimized/${userId}`;
  768. return serverFetchJson<GetPickOrderInfoResponse>(
  769. url,
  770. {
  771. method: "GET",
  772. next: { tags: ["pickorder"] },
  773. },
  774. );
  775. });
  776. export const fetchPickOrderLineLotDetails = cache(async (pickOrderLineId: number) => {
  777. return serverFetchJson<PickOrderLotDetailResponse[]>(
  778. `${BASE_API_URL}/pickOrder/lot-details/${pickOrderLineId}`,
  779. {
  780. method: "GET",
  781. next: { tags: ["pickorder"] },
  782. },
  783. );
  784. });
  785. export const createPickOrder = async (data: SavePickOrderRequest) => {
  786. console.log(data);
  787. const po = await serverFetchJson<PostPickOrderResponse>(
  788. `${BASE_API_URL}/pickOrder/create`,
  789. {
  790. method: "POST",
  791. body: JSON.stringify(data),
  792. headers: { "Content-Type": "application/json" },
  793. },
  794. );
  795. revalidateTag("pickorder");
  796. return po;
  797. }
  798. export const assignPickOrder = async (ids: number[]) => {
  799. const pickOrder = await serverFetchJson<any>(
  800. `${BASE_API_URL}/pickOrder/conso`,
  801. {
  802. method: "POST",
  803. body: JSON.stringify({ ids: ids }),
  804. headers: { "Content-Type": "application/json" },
  805. },
  806. );
  807. // revalidateTag("po");
  808. return pickOrder;
  809. };
  810. export const consolidatePickOrder = async (ids: number[]) => {
  811. const pickOrder = await serverFetchJson<any>(
  812. `${BASE_API_URL}/pickOrder/conso`,
  813. {
  814. method: "POST",
  815. body: JSON.stringify({ ids: ids }),
  816. headers: { "Content-Type": "application/json" },
  817. },
  818. );
  819. return pickOrder;
  820. };
  821. export const consolidatePickOrder_revert = async (ids: number[]) => {
  822. const pickOrder = await serverFetchJson<any>(
  823. `${BASE_API_URL}/pickOrder/deconso`,
  824. {
  825. method: "POST",
  826. body: JSON.stringify({ ids: ids }),
  827. headers: { "Content-Type": "application/json" },
  828. },
  829. );
  830. // revalidateTag("po");
  831. return pickOrder;
  832. };
  833. export const fetchPickOrderClient = cache(
  834. async (queryParams?: Record<string, any>) => {
  835. if (queryParams) {
  836. const queryString = new URLSearchParams(queryParams).toString();
  837. return serverFetchJson<RecordsRes<PickOrderResult[]>>(
  838. `${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`,
  839. {
  840. method: "GET",
  841. next: { tags: ["pickorder"] },
  842. },
  843. );
  844. } else {
  845. return serverFetchJson<RecordsRes<PickOrderResult[]>>(
  846. `${BASE_API_URL}/pickOrder/getRecordByPage`,
  847. {
  848. method: "GET",
  849. next: { tags: ["pickorder"] },
  850. },
  851. );
  852. }
  853. },
  854. );
  855. export const fetchPickOrderWithStockClient = cache(
  856. async (queryParams?: Record<string, any>) => {
  857. if (queryParams) {
  858. const queryString = new URLSearchParams(queryParams).toString();
  859. return serverFetchJson<RecordsRes<GetPickOrderInfo[]>>(
  860. `${BASE_API_URL}/pickOrder/getRecordByPageWithStock?${queryString}`,
  861. {
  862. method: "GET",
  863. next: { tags: ["pickorder"] },
  864. },
  865. );
  866. } else {
  867. return serverFetchJson<RecordsRes<GetPickOrderInfo[]>>(
  868. `${BASE_API_URL}/pickOrder/getRecordByPageWithStock`,
  869. {
  870. method: "GET",
  871. next: { tags: ["pickorder"] },
  872. },
  873. );
  874. }
  875. },
  876. );
  877. export const fetchConsoPickOrderClient = cache(
  878. async (queryParams?: Record<string, any>) => {
  879. if (queryParams) {
  880. const queryString = new URLSearchParams(queryParams).toString();
  881. return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(
  882. `${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`,
  883. {
  884. method: "GET",
  885. next: { tags: ["pickorder"] },
  886. },
  887. );
  888. } else {
  889. return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(
  890. `${BASE_API_URL}/pickOrder/getRecordByPage-conso`,
  891. {
  892. method: "GET",
  893. next: { tags: ["pickorder"] },
  894. },
  895. );
  896. }
  897. },
  898. );
  899. export const fetchPickOrderLineClient = cache(
  900. async (queryParams?: Record<string, any>) => {
  901. if (queryParams) {
  902. const queryString = new URLSearchParams(queryParams).toString();
  903. return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(
  904. `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`,
  905. {
  906. method: "GET",
  907. next: { tags: ["pickorder"] },
  908. },
  909. );
  910. } else {
  911. return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(
  912. `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`,
  913. {
  914. method: "GET",
  915. next: { tags: ["pickorder"] },
  916. },
  917. );
  918. }
  919. },
  920. );
  921. export const fetchStockOutLineClient = cache(
  922. async (pickOrderLineId: number) => {
  923. return serverFetchJson<StockOutLine[]>(
  924. `${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`,
  925. {
  926. method: "GET",
  927. next: { tags: ["pickorder"] },
  928. },
  929. );
  930. },
  931. );
  932. export const fetchConsoDetail = cache(async (consoCode: string) => {
  933. return serverFetchJson<PreReleasePickOrderSummary>(
  934. `${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`,
  935. {
  936. method: "GET",
  937. next: { tags: ["pickorder"] },
  938. },
  939. );
  940. });
  941. export const releasePickOrder = async (data: ReleasePickOrderInputs) => {
  942. console.log(data);
  943. console.log(JSON.stringify(data));
  944. const po = await serverFetchJson<{ consoCode: string }>(
  945. `${BASE_API_URL}/pickOrder/releaseConso`,
  946. {
  947. method: "POST",
  948. body: JSON.stringify(data),
  949. headers: { "Content-Type": "application/json" },
  950. },
  951. );
  952. revalidateTag("pickorder");
  953. return po;
  954. };
  955. export const createStockOutLine = async (data: CreateStockOutLine) => {
  956. console.log("triggering");
  957. const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  958. `${BASE_API_URL}/stockOutLine/create`,
  959. {
  960. method: "POST",
  961. body: JSON.stringify(data),
  962. headers: { "Content-Type": "application/json" },
  963. },
  964. );
  965. revalidateTag("pickorder");
  966. return po;
  967. };
  968. export const updateStockOutLine = async (data: UpdateStockOutLine) => {
  969. console.log(data);
  970. const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  971. `${BASE_API_URL}/stockOutLine/update`,
  972. {
  973. method: "POST",
  974. body: JSON.stringify(data),
  975. headers: { "Content-Type": "application/json" },
  976. },
  977. );
  978. revalidateTag("pickorder");
  979. return po;
  980. };
  981. export const completeConsoPickOrder = async (consoCode: string) => {
  982. const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  983. `${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`,
  984. {
  985. method: "POST",
  986. headers: { "Content-Type": "application/json" },
  987. },
  988. );
  989. revalidateTag("pickorder");
  990. return po;
  991. };
  992. export const fetchConsoStatus = cache(async (consoCode: string) => {
  993. return serverFetchJson<{ status: string }>(
  994. `${BASE_API_URL}/stockOut/get-status/${consoCode}`,
  995. {
  996. method: "GET",
  997. next: { tags: ["pickorder"] },
  998. },
  999. );
  1000. });
  1001. export interface ReleasedDoPickOrderResponse {
  1002. id: number;
  1003. storeId: string;
  1004. ticketNo: string;
  1005. pickOrderId: number;
  1006. ticketStatus: string;
  1007. doOrderId: number;
  1008. shopId: number;
  1009. handledBy: number;
  1010. ticketReleaseTime: string;
  1011. }
  1012. export const fetchReleasedDoPickOrders = async (): Promise<ReleasedDoPickOrderResponse[]> => {
  1013. const response = await serverFetchJson<ReleasedDoPickOrderResponse[]>(
  1014. `${BASE_API_URL}/doPickOrder/released`,
  1015. {
  1016. method: "GET",
  1017. },
  1018. );
  1019. return response;
  1020. };