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.
 
 

1141 lines
30 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 interface StoreLaneSummary {
  350. storeId: string;
  351. rows: LaneRow[];
  352. }
  353. export interface LaneRow {
  354. truckDepartureTime: string;
  355. lanes: LaneBtn[];
  356. }
  357. export interface LaneBtn {
  358. truckLanceCode: string;
  359. unassigned: number;
  360. total: number;
  361. }
  362. export const updatePickExecutionIssueStatus = async (
  363. data: UpdatePickExecutionIssueRequest
  364. ): Promise<PostPickOrderResponse> => {
  365. const result = await serverFetchJson<PostPickOrderResponse>(
  366. `${BASE_API_URL}/pickExecution/updateIssueStatus`,
  367. {
  368. method: "POST",
  369. body: JSON.stringify(data),
  370. headers: { "Content-Type": "application/json" },
  371. }
  372. );
  373. revalidateTag("pickExecutionIssues");
  374. return result;
  375. };
  376. export async function fetchStoreLaneSummary(storeId: string): Promise<StoreLaneSummary> {
  377. // ✅ 硬编码测试日期 - 改成你想测试的日期
  378. const testDate = "2025-10-16"; // 或者 "2025-10-16", "2025-10-17" 等
  379. const response = await serverFetchJson<StoreLaneSummary>(
  380. `${BASE_API_URL}/doPickOrder/summary-by-store?storeId=${encodeURIComponent(storeId)}&requiredDate=${testDate}`,
  381. {
  382. method: "GET",
  383. }
  384. );
  385. return response;
  386. }
  387. // 按车道分配订单
  388. export async function assignByLane(
  389. userId: number,
  390. storeId: string,
  391. truckLanceCode: string,
  392. truckDepartureTime?: string
  393. ): Promise<any> {
  394. const response = await serverFetchJson(
  395. `${BASE_API_URL}/doPickOrder/assign-by-lane`,
  396. {
  397. method: "POST",
  398. headers: {
  399. "Content-Type": "application/json",
  400. },
  401. body: JSON.stringify({
  402. userId,
  403. storeId,
  404. truckLanceCode,
  405. truckDepartureTime,
  406. }),
  407. }
  408. );
  409. return response;
  410. }
  411. // ✅ 新增:获取已完成的 DO Pick Orders API
  412. export const fetchCompletedDoPickOrders = async (
  413. userId: number,
  414. searchParams?: CompletedDoPickOrderSearchParams
  415. ): Promise<CompletedDoPickOrderResponse[]> => {
  416. const params = new URLSearchParams();
  417. if (searchParams?.pickOrderCode) {
  418. params.append('pickOrderCode', searchParams.pickOrderCode);
  419. }
  420. if (searchParams?.shopName) {
  421. params.append('shopName', searchParams.shopName);
  422. }
  423. if (searchParams?.deliveryNo) {
  424. params.append('deliveryNo', searchParams.deliveryNo);
  425. }
  426. if (searchParams?.ticketNo) {
  427. params.append('ticketNo', searchParams.ticketNo);
  428. }
  429. const queryString = params.toString();
  430. const url = `${BASE_API_URL}/pickOrder/completed-do-pick-orders/${userId}${queryString ? `?${queryString}` : ''}`;
  431. const response = await serverFetchJson<CompletedDoPickOrderResponse[]>(url, {
  432. method: "GET",
  433. });
  434. return response;
  435. };
  436. export const updatePickOrderHideStatus = async (pickOrderId: number, hide: boolean) => {
  437. const response = await serverFetchJson<UpdateDoPickOrderHideStatusRequest>(
  438. `${BASE_API_URL}/pickOrder/update-hide-status/${pickOrderId}?hide=${hide}`,
  439. {
  440. method: "POST",
  441. headers: { "Content-Type": "application/json" },
  442. },
  443. );
  444. revalidateTag("pickorder");
  445. return response;
  446. };
  447. export const fetchFGPickOrders = async (pickOrderId: number) => {
  448. const response = await serverFetchJson<FGPickOrderResponse>(
  449. `${BASE_API_URL}/pickOrder/fg-pick-orders/${pickOrderId}`,
  450. {
  451. method: "GET",
  452. },
  453. );
  454. return response;
  455. };
  456. export const updateSuggestedLotLineId = async (suggestedPickLotId: number, newLotLineId: number) => {
  457. const response = await serverFetchJson<PostPickOrderResponse<UpdateSuggestedLotLineIdRequest>>(
  458. `${BASE_API_URL}/suggestedPickLot/update-suggested-lot/${suggestedPickLotId}`,
  459. {
  460. method: "POST",
  461. body: JSON.stringify({ newLotLineId }),
  462. headers: { "Content-Type": "application/json" },
  463. },
  464. );
  465. revalidateTag("pickorder");
  466. return response;
  467. };
  468. export const autoAssignAndReleasePickOrder = async (userId: number): Promise<AutoAssignReleaseResponse> => {
  469. const response = await serverFetchJson<AutoAssignReleaseResponse>(
  470. `${BASE_API_URL}/pickOrder/auto-assign-release/${userId}`,
  471. {
  472. method: "POST",
  473. headers: { "Content-Type": "application/json" },
  474. },
  475. );
  476. revalidateTag("pickorder");
  477. return response;
  478. };
  479. export const autoAssignAndReleasePickOrderByStore = async (
  480. userId: number,
  481. storeId: string
  482. ): Promise<AutoAssignReleaseResponse> => {
  483. const url = `${BASE_API_URL}/pickOrder/auto-assign-release-by-store?userId=${userId}&storeId=${encodeURIComponent(storeId)}`;
  484. const response = await serverFetchJson<AutoAssignReleaseResponse>(url, {
  485. method: "POST",
  486. headers: { "Content-Type": "application/json" },
  487. // no body
  488. next: { tags: ["pickorder"] },
  489. });
  490. revalidateTag("pickorder");
  491. return response;
  492. };
  493. export const checkPickOrderCompletion = async (userId: number): Promise<PickOrderCompletionResponse> => {
  494. const response = await serverFetchJson<PickOrderCompletionResponse>(
  495. `${BASE_API_URL}/pickOrder/check-pick-completion/${userId}`,
  496. {
  497. method: "GET",
  498. headers: { "Content-Type": "application/json" },
  499. },
  500. );
  501. return response;
  502. };
  503. export const recordPickExecutionIssue = async (data: PickExecutionIssueData) => {
  504. const result = await serverFetchJson<PostPickOrderResponse>(
  505. `${BASE_API_URL}/pickExecution/recordIssue`,
  506. {
  507. method: "POST",
  508. body: JSON.stringify(data),
  509. headers: { "Content-Type": "application/json" },
  510. },
  511. );
  512. revalidateTag("pickorder");
  513. return result;
  514. };
  515. export const resuggestPickOrder = async (pickOrderId: number) => {
  516. console.log("Resuggesting pick order:", pickOrderId);
  517. const result = await serverFetchJson<PostPickOrderResponse>(
  518. `${BASE_API_URL}/suggestedPickLot/resuggest/${pickOrderId}`,
  519. {
  520. method: "POST",
  521. headers: { "Content-Type": "application/json" },
  522. },
  523. );
  524. revalidateTag("pickorder");
  525. return result;
  526. };
  527. export const updateStockOutLineStatus = async (data: {
  528. id: number;
  529. status: string;
  530. qty?: number;
  531. remarks?: string;
  532. }) => {
  533. console.log("Updating stock out line status:", data);
  534. const result = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  535. `${BASE_API_URL}/stockOutLine/updateStatus`,
  536. {
  537. method: "POST",
  538. body: JSON.stringify(data),
  539. headers: { "Content-Type": "application/json" },
  540. },
  541. );
  542. revalidateTag("pickorder");
  543. return result;
  544. };
  545. // Missing function 1: newassignPickOrder
  546. export const newassignPickOrder = async (data: AssignPickOrderInputs) => {
  547. const response = await serverFetchJson<PostPickOrderResponse>(
  548. `${BASE_API_URL}/pickOrder/assign`,
  549. {
  550. method: "POST",
  551. body: JSON.stringify(data),
  552. headers: { "Content-Type": "application/json" },
  553. },
  554. );
  555. revalidateTag("pickorder");
  556. return response;
  557. };
  558. // Missing function 2: releaseAssignedPickOrders
  559. export const releaseAssignedPickOrders = async (data: AssignPickOrderInputs) => {
  560. const response = await serverFetchJson<PostPickOrderResponse>(
  561. `${BASE_API_URL}/pickOrder/release-assigned`,
  562. {
  563. method: "POST",
  564. body: JSON.stringify(data),
  565. headers: { "Content-Type": "application/json" },
  566. },
  567. );
  568. revalidateTag("pickorder");
  569. return response;
  570. };
  571. // Get latest group name and create it automatically
  572. export const getLatestGroupNameAndCreate = async () => {
  573. return serverFetchJson<PostPickOrderResponse>(
  574. `${BASE_API_URL}/pickOrder/groups/latest`,
  575. {
  576. method: "GET",
  577. next: { tags: ["pickorder"] },
  578. },
  579. );
  580. };
  581. // Get all groups
  582. export const fetchAllGroups = cache(async () => {
  583. return serverFetchJson<PickOrderGroupInfo[]>(
  584. `${BASE_API_URL}/pickOrder/groups/list`,
  585. {
  586. method: "GET",
  587. next: { tags: ["pickorder"] },
  588. },
  589. );
  590. });
  591. // Create or update groups (flexible - can handle both cases)
  592. export const createOrUpdateGroups = async (data: SavePickOrderGroupRequest) => {
  593. const response = await serverFetchJson<PostPickOrderResponse>(
  594. `${BASE_API_URL}/pickOrder/groups/create`,
  595. {
  596. method: "POST",
  597. body: JSON.stringify(data),
  598. headers: { "Content-Type": "application/json" },
  599. },
  600. );
  601. revalidateTag("pickorder");
  602. return response;
  603. };
  604. // Get groups by pick order ID
  605. export const fetchGroupsByPickOrderId = cache(async (pickOrderId: number) => {
  606. return serverFetchJson<PickOrderGroupInfo[]>(
  607. `${BASE_API_URL}/pickOrder/groups/${pickOrderId}`,
  608. {
  609. method: "GET",
  610. next: { tags: ["pickorder"] },
  611. },
  612. );
  613. });
  614. export const fetchPickOrderDetails = cache(async (ids: string) => {
  615. return serverFetchJson<GetPickOrderInfoResponse>(
  616. `${BASE_API_URL}/pickOrder/detail/${ids}`,
  617. {
  618. method: "GET",
  619. next: { tags: ["pickorder"] },
  620. },
  621. );
  622. });
  623. export interface PickOrderLotDetailResponse {
  624. lotId: number;
  625. lotNo: string;
  626. expiryDate: string;
  627. location: string;
  628. stockUnit: string;
  629. inQty: number;
  630. availableQty: number;
  631. requiredQty: number;
  632. actualPickQty: number;
  633. suggestedPickLotId: number;
  634. lotStatus: string;
  635. lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable'|'rejected';
  636. }
  637. interface ALLPickOrderLotDetailResponse {
  638. // Pick Order Information
  639. pickOrderId: number;
  640. pickOrderCode: string;
  641. pickOrderTargetDate: string;
  642. pickOrderType: string;
  643. pickOrderStatus: string;
  644. pickOrderAssignTo: number;
  645. groupName: string;
  646. // Pick Order Line Information
  647. pickOrderLineId: number;
  648. pickOrderLineRequiredQty: number;
  649. pickOrderLineStatus: string;
  650. // Item Information
  651. itemId: number;
  652. itemCode: string;
  653. itemName: string;
  654. uomCode: string;
  655. uomDesc: string;
  656. // Lot Information
  657. lotId: number;
  658. lotNo: string;
  659. expiryDate: string;
  660. location: string;
  661. outQty: number;
  662. holdQty: number;
  663. stockUnit: string;
  664. availableQty: number;
  665. requiredQty: number;
  666. actualPickQty: number;
  667. totalPickedByAllPickOrders: number;
  668. suggestedPickLotId: number;
  669. lotStatus: string;
  670. stockOutLineId?: number;
  671. stockOutLineStatus?: string;
  672. stockOutLineQty?: number;
  673. lotAvailability: 'available' | 'insufficient_stock' | 'expired' | 'status_unavailable'|'rejected';
  674. processingStatus: string;
  675. }
  676. interface SuggestionWithStatus {
  677. suggestionId: number;
  678. suggestionQty: number;
  679. suggestionCreated: string;
  680. lotLineId: number;
  681. lotNo: string;
  682. expiryDate: string;
  683. location: string;
  684. stockOutLineId?: number;
  685. stockOutLineStatus?: string;
  686. stockOutLineQty?: number;
  687. suggestionStatus: 'active' | 'completed' | 'rejected' | 'in_progress' | 'unknown';
  688. }
  689. export interface CheckCompleteResponse {
  690. id: number | null;
  691. name: string;
  692. code: string;
  693. type?: string;
  694. message: string | null;
  695. errorPosition: string;
  696. }
  697. export interface LotSubstitutionConfirmRequest {
  698. pickOrderLineId: number;
  699. stockOutLineId: number;
  700. originalSuggestedPickLotId: number;
  701. newInventoryLotLineId: number;
  702. }
  703. export const confirmLotSubstitution = async (data: LotSubstitutionConfirmRequest) => {
  704. const response = await serverFetchJson<PostPickOrderResponse>(
  705. `${BASE_API_URL}/pickOrder/lot-substitution/confirm`,
  706. {
  707. method: "POST",
  708. body: JSON.stringify(data),
  709. headers: { "Content-Type": "application/json" },
  710. },
  711. );
  712. revalidateTag("pickorder");
  713. return response;
  714. };
  715. export const checkAndCompletePickOrderByConsoCode = async (consoCode: string): Promise<CheckCompleteResponse> => {
  716. const response = await serverFetchJson<CheckCompleteResponse>(
  717. `${BASE_API_URL}/pickOrder/check-complete/${consoCode}`,
  718. {
  719. method: "POST",
  720. headers: {
  721. "Content-Type": "application/json",
  722. },
  723. },
  724. );
  725. revalidateTag("pickorder");
  726. return response;
  727. };
  728. export const fetchPickOrderDetailsOptimized = cache(async (userId?: number) => {
  729. const url = userId
  730. ? `${BASE_API_URL}/pickOrder/detail-optimized?userId=${userId}`
  731. : `${BASE_API_URL}/pickOrder/detail-optimized`;
  732. return serverFetchJson<any[]>(
  733. url,
  734. {
  735. method: "GET",
  736. next: { tags: ["pickorder"] },
  737. },
  738. );
  739. });
  740. const fetchSuggestionsWithStatus = async (pickOrderLineId: number) => {
  741. try {
  742. const response = await fetch(`/api/suggestedPickLot/suggestions-with-status/${pickOrderLineId}`);
  743. const suggestions: SuggestionWithStatus[] = await response.json();
  744. return suggestions;
  745. } catch (error) {
  746. console.error('Error fetching suggestions with status:', error);
  747. return [];
  748. }
  749. };
  750. export const fetchAllPickOrderLotsHierarchical = cache(async (userId: number): Promise<any> => {
  751. try {
  752. console.log("🔍 Fetching hierarchical pick order lots for userId:", userId);
  753. const data = await serverFetchJson<any>(
  754. `${BASE_API_URL}/pickOrder/all-lots-hierarchical/${userId}`,
  755. {
  756. method: 'GET',
  757. next: { tags: ["pickorder"] },
  758. }
  759. );
  760. console.log("✅ Fetched hierarchical lot details:", data);
  761. return data;
  762. } catch (error) {
  763. console.error("❌ Error fetching hierarchical lot details:", error);
  764. return {
  765. pickOrder: null,
  766. pickOrderLines: []
  767. };
  768. }
  769. });
  770. export const fetchLotDetailsByPickOrderId = async (pickOrderId: number): Promise<any[]> => {
  771. try {
  772. console.log("🔍 Fetching lot details for pickOrderId:", pickOrderId);
  773. const data = await serverFetchJson<any[]>(
  774. `${BASE_API_URL}/pickOrder/lot-details-by-pick-order/${pickOrderId}`,
  775. {
  776. method: 'GET',
  777. next: { tags: ["pickorder"] },
  778. }
  779. );
  780. console.log("✅ Fetched lot details for pickOrderId:", data);
  781. return data;
  782. } catch (error) {
  783. console.error("❌ Error fetching lot details for pickOrderId:", error);
  784. return [];
  785. }
  786. };
  787. // Update the existing function to use the non-auto-assign endpoint
  788. export const fetchALLPickOrderLineLotDetails = cache(async (userId: number): Promise<any[]> => {
  789. try {
  790. console.log("🔍 Fetching all pick order line lot details for userId:", userId);
  791. // ✅ Use the non-auto-assign endpoint
  792. const data = await serverFetchJson<any[]>(
  793. `${BASE_API_URL}/pickOrder/all-lots-with-details-no-auto-assign/${userId}`,
  794. {
  795. method: 'GET',
  796. next: { tags: ["pickorder"] },
  797. }
  798. );
  799. console.log("✅ Fetched lot details:", data);
  800. return data;
  801. } catch (error) {
  802. console.error("❌ Error fetching lot details:", error);
  803. return [];
  804. }
  805. });
  806. export const fetchAllPickOrderDetails = cache(async (userId?: number) => {
  807. if (!userId) {
  808. return {
  809. consoCode: null,
  810. pickOrders: [],
  811. items: []
  812. };
  813. }
  814. // ✅ Use the correct endpoint with userId in the path
  815. const url = `${BASE_API_URL}/pickOrder/detail-optimized/${userId}`;
  816. return serverFetchJson<GetPickOrderInfoResponse>(
  817. url,
  818. {
  819. method: "GET",
  820. next: { tags: ["pickorder"] },
  821. },
  822. );
  823. });
  824. export const fetchPickOrderLineLotDetails = cache(async (pickOrderLineId: number) => {
  825. return serverFetchJson<PickOrderLotDetailResponse[]>(
  826. `${BASE_API_URL}/pickOrder/lot-details/${pickOrderLineId}`,
  827. {
  828. method: "GET",
  829. next: { tags: ["pickorder"] },
  830. },
  831. );
  832. });
  833. export const createPickOrder = async (data: SavePickOrderRequest) => {
  834. console.log(data);
  835. const po = await serverFetchJson<PostPickOrderResponse>(
  836. `${BASE_API_URL}/pickOrder/create`,
  837. {
  838. method: "POST",
  839. body: JSON.stringify(data),
  840. headers: { "Content-Type": "application/json" },
  841. },
  842. );
  843. revalidateTag("pickorder");
  844. return po;
  845. }
  846. export const assignPickOrder = async (ids: number[]) => {
  847. const pickOrder = await serverFetchJson<any>(
  848. `${BASE_API_URL}/pickOrder/conso`,
  849. {
  850. method: "POST",
  851. body: JSON.stringify({ ids: ids }),
  852. headers: { "Content-Type": "application/json" },
  853. },
  854. );
  855. // revalidateTag("po");
  856. return pickOrder;
  857. };
  858. export const consolidatePickOrder = async (ids: number[]) => {
  859. const pickOrder = await serverFetchJson<any>(
  860. `${BASE_API_URL}/pickOrder/conso`,
  861. {
  862. method: "POST",
  863. body: JSON.stringify({ ids: ids }),
  864. headers: { "Content-Type": "application/json" },
  865. },
  866. );
  867. return pickOrder;
  868. };
  869. export const consolidatePickOrder_revert = async (ids: number[]) => {
  870. const pickOrder = await serverFetchJson<any>(
  871. `${BASE_API_URL}/pickOrder/deconso`,
  872. {
  873. method: "POST",
  874. body: JSON.stringify({ ids: ids }),
  875. headers: { "Content-Type": "application/json" },
  876. },
  877. );
  878. // revalidateTag("po");
  879. return pickOrder;
  880. };
  881. export const fetchPickOrderClient = cache(
  882. async (queryParams?: Record<string, any>) => {
  883. if (queryParams) {
  884. const queryString = new URLSearchParams(queryParams).toString();
  885. return serverFetchJson<RecordsRes<PickOrderResult[]>>(
  886. `${BASE_API_URL}/pickOrder/getRecordByPage?${queryString}`,
  887. {
  888. method: "GET",
  889. next: { tags: ["pickorder"] },
  890. },
  891. );
  892. } else {
  893. return serverFetchJson<RecordsRes<PickOrderResult[]>>(
  894. `${BASE_API_URL}/pickOrder/getRecordByPage`,
  895. {
  896. method: "GET",
  897. next: { tags: ["pickorder"] },
  898. },
  899. );
  900. }
  901. },
  902. );
  903. export const fetchPickOrderWithStockClient = cache(
  904. async (queryParams?: Record<string, any>) => {
  905. if (queryParams) {
  906. const queryString = new URLSearchParams(queryParams).toString();
  907. return serverFetchJson<RecordsRes<GetPickOrderInfo[]>>(
  908. `${BASE_API_URL}/pickOrder/getRecordByPageWithStock?${queryString}`,
  909. {
  910. method: "GET",
  911. next: { tags: ["pickorder"] },
  912. },
  913. );
  914. } else {
  915. return serverFetchJson<RecordsRes<GetPickOrderInfo[]>>(
  916. `${BASE_API_URL}/pickOrder/getRecordByPageWithStock`,
  917. {
  918. method: "GET",
  919. next: { tags: ["pickorder"] },
  920. },
  921. );
  922. }
  923. },
  924. );
  925. export const fetchConsoPickOrderClient = cache(
  926. async (queryParams?: Record<string, any>) => {
  927. if (queryParams) {
  928. const queryString = new URLSearchParams(queryParams).toString();
  929. return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(
  930. `${BASE_API_URL}/pickOrder/getRecordByPage-conso?${queryString}`,
  931. {
  932. method: "GET",
  933. next: { tags: ["pickorder"] },
  934. },
  935. );
  936. } else {
  937. return serverFetchJson<RecordsRes<ConsoPickOrderResult[]>>(
  938. `${BASE_API_URL}/pickOrder/getRecordByPage-conso`,
  939. {
  940. method: "GET",
  941. next: { tags: ["pickorder"] },
  942. },
  943. );
  944. }
  945. },
  946. );
  947. export const fetchPickOrderLineClient = cache(
  948. async (queryParams?: Record<string, any>) => {
  949. if (queryParams) {
  950. const queryString = new URLSearchParams(queryParams).toString();
  951. return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(
  952. `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`,
  953. {
  954. method: "GET",
  955. next: { tags: ["pickorder"] },
  956. },
  957. );
  958. } else {
  959. return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(
  960. `${BASE_API_URL}/pickOrder/get-pickorder-line-byPage`,
  961. {
  962. method: "GET",
  963. next: { tags: ["pickorder"] },
  964. },
  965. );
  966. }
  967. },
  968. );
  969. export const fetchStockOutLineClient = cache(
  970. async (pickOrderLineId: number) => {
  971. return serverFetchJson<StockOutLine[]>(
  972. `${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`,
  973. {
  974. method: "GET",
  975. next: { tags: ["pickorder"] },
  976. },
  977. );
  978. },
  979. );
  980. export const fetchConsoDetail = cache(async (consoCode: string) => {
  981. return serverFetchJson<PreReleasePickOrderSummary>(
  982. `${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`,
  983. {
  984. method: "GET",
  985. next: { tags: ["pickorder"] },
  986. },
  987. );
  988. });
  989. export const releasePickOrder = async (data: ReleasePickOrderInputs) => {
  990. console.log(data);
  991. console.log(JSON.stringify(data));
  992. const po = await serverFetchJson<{ consoCode: string }>(
  993. `${BASE_API_URL}/pickOrder/releaseConso`,
  994. {
  995. method: "POST",
  996. body: JSON.stringify(data),
  997. headers: { "Content-Type": "application/json" },
  998. },
  999. );
  1000. revalidateTag("pickorder");
  1001. return po;
  1002. };
  1003. export const createStockOutLine = async (data: CreateStockOutLine) => {
  1004. console.log("triggering");
  1005. const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  1006. `${BASE_API_URL}/stockOutLine/create`,
  1007. {
  1008. method: "POST",
  1009. body: JSON.stringify(data),
  1010. headers: { "Content-Type": "application/json" },
  1011. },
  1012. );
  1013. revalidateTag("pickorder");
  1014. return po;
  1015. };
  1016. export const updateStockOutLine = async (data: UpdateStockOutLine) => {
  1017. console.log(data);
  1018. const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  1019. `${BASE_API_URL}/stockOutLine/update`,
  1020. {
  1021. method: "POST",
  1022. body: JSON.stringify(data),
  1023. headers: { "Content-Type": "application/json" },
  1024. },
  1025. );
  1026. revalidateTag("pickorder");
  1027. return po;
  1028. };
  1029. export const completeConsoPickOrder = async (consoCode: string) => {
  1030. const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(
  1031. `${BASE_API_URL}/pickOrder/consoPickOrder/complete/${consoCode}`,
  1032. {
  1033. method: "POST",
  1034. headers: { "Content-Type": "application/json" },
  1035. },
  1036. );
  1037. revalidateTag("pickorder");
  1038. return po;
  1039. };
  1040. export const fetchConsoStatus = cache(async (consoCode: string) => {
  1041. return serverFetchJson<{ status: string }>(
  1042. `${BASE_API_URL}/stockOut/get-status/${consoCode}`,
  1043. {
  1044. method: "GET",
  1045. next: { tags: ["pickorder"] },
  1046. },
  1047. );
  1048. });
  1049. export interface ReleasedDoPickOrderResponse {
  1050. id: number;
  1051. storeId: string;
  1052. ticketNo: string;
  1053. pickOrderId: number;
  1054. ticketStatus: string;
  1055. doOrderId: number;
  1056. shopId: number;
  1057. handledBy: number;
  1058. ticketReleaseTime: string;
  1059. }
  1060. export const fetchReleasedDoPickOrders = async (): Promise<ReleasedDoPickOrderResponse[]> => {
  1061. const response = await serverFetchJson<ReleasedDoPickOrderResponse[]>(
  1062. `${BASE_API_URL}/doPickOrder/released`,
  1063. {
  1064. method: "GET",
  1065. },
  1066. );
  1067. return response;
  1068. };