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.
 
 

1087 line
28 KiB

  1. "use server";
  2. import { cache } from 'react';
  3. import { Pageable, serverFetchBlob, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
  4. import { JobOrder, JoStatus, Machine, Operator } from ".";
  5. import { BASE_API_URL } from "@/config/api";
  6. import { revalidateTag } from "next/cache";
  7. import { convertObjToURLSearchParams } from "@/app/utils/commonUtil";
  8. import { FileResponse } from "@/app/api/pdf/actions";
  9. export interface SaveJo {
  10. bomId: number;
  11. planStart: string;
  12. planEnd: string;
  13. reqQty: number;
  14. type: string;
  15. //jobType?: string;
  16. jobTypeId?: number;
  17. }
  18. export interface SaveJoResponse {
  19. id: number;
  20. }
  21. export interface SearchJoResultRequest extends Pageable {
  22. code: string;
  23. itemName?: string;
  24. planStart?: string;
  25. planStartTo?: string;
  26. jobTypeName?: string;
  27. }
  28. export interface productProcessLineQtyRequest {
  29. productProcessLineId: number;
  30. outputFromProcessQty: number;
  31. outputFromProcessUom: string;
  32. defectQty: number;
  33. defectUom: string;
  34. scrapQty: number;
  35. scrapUom: string;
  36. }
  37. export interface SearchJoResultResponse {
  38. records: JobOrder[];
  39. total: number;
  40. }
  41. // DEPRECIATED
  42. export interface SearchJoResult {
  43. id: number;
  44. code: string;
  45. itemCode: string;
  46. name: string;
  47. reqQty: number;
  48. uom: string;
  49. status: JoStatus;
  50. }
  51. export interface UpdateJoRequest {
  52. id: number;
  53. status: string;
  54. }
  55. // For Jo Button Actions
  56. export interface CommonActionJoRequest {
  57. id: number;
  58. }
  59. export interface CommonActionJoResponse {
  60. id: number;
  61. entity: { status: JoStatus }
  62. }
  63. // For Jo Process
  64. export interface IsOperatorExistResponse<T> {
  65. id: number | null;
  66. name: string;
  67. code: string;
  68. type?: string;
  69. message: string | null;
  70. errorPosition: string | keyof T;
  71. entity: T;
  72. }
  73. export interface isCorrectMachineUsedResponse<T> {
  74. id: number | null;
  75. name: string;
  76. code: string;
  77. type?: string;
  78. message: string | null;
  79. errorPosition: string | keyof T;
  80. entity: T;
  81. }
  82. export interface JobOrderDetail {
  83. id: number;
  84. code: string;
  85. name: string;
  86. reqQty: number;
  87. uom: string;
  88. pickLines: any[];
  89. jobTypeName: string;
  90. status: string;
  91. }
  92. export interface UnassignedJobOrderPickOrder {
  93. pickOrderId: number;
  94. pickOrderCode: string;
  95. pickOrderConsoCode: string;
  96. pickOrderTargetDate: string;
  97. pickOrderStatus: string;
  98. jobOrderId: number;
  99. jobOrderCode: string;
  100. jobOrderName: string;
  101. reqQty: number;
  102. uom: string;
  103. planStart: string;
  104. planEnd: string;
  105. }
  106. export interface AssignJobOrderResponse {
  107. id: number | null;
  108. code: string | null;
  109. name: string | null;
  110. type: string | null;
  111. message: string | null;
  112. errorPosition: string | null;
  113. }
  114. export interface PrintPickRecordRequest{
  115. pickOrderId: number;
  116. printerId: number;
  117. printQty: number;
  118. }
  119. export interface PrintPickRecordResponse{
  120. success: boolean;
  121. message?: string
  122. }
  123. export interface PrintFGStockInLabelRequest {
  124. stockInLineId: number;
  125. printerId: number;
  126. printQty?: number;
  127. }
  128. export const printFGStockInLabel = cache(async(data: PrintFGStockInLabelRequest) => {
  129. const params = new URLSearchParams();
  130. if (data.stockInLineId) {
  131. params.append('stockInLineId', data.stockInLineId.toString());
  132. }
  133. params.append('printerId', data.printerId.toString());
  134. if (data.printQty !== undefined && data.printQty !== null) {
  135. params.append('printQty', data.printQty.toString());
  136. }
  137. return serverFetchWithNoContent(
  138. `${BASE_API_URL}/jo/print-FGStockInLabel?${params.toString()}`,
  139. {
  140. method: "GET",
  141. next: {
  142. tags: ["printFGStockInLabel"],
  143. },
  144. }
  145. );
  146. });
  147. export const recordSecondScanIssue = cache(async (
  148. pickOrderId: number,
  149. itemId: number,
  150. data: {
  151. qty: number; // verified qty (actual pick qty)
  152. missQty?: number; // 添加:miss qty
  153. badItemQty?: number; // 添加:bad item qty
  154. isMissing: boolean;
  155. isBad: boolean;
  156. reason: string;
  157. createdBy: number;
  158. type?: string; // type 也应该是可选的
  159. }
  160. ) => {
  161. return serverFetchJson<any>(
  162. `${BASE_API_URL}/jo/second-scan-issue/${pickOrderId}/${itemId}`,
  163. {
  164. method: "POST",
  165. headers: { "Content-Type": "application/json" },
  166. body: JSON.stringify(data),
  167. next: { tags: ["jo-second-scan"] },
  168. },
  169. );
  170. });
  171. export interface ProductProcessResponse {
  172. id: number;
  173. productProcessCode: string;
  174. status: string;
  175. startTime?: string;
  176. endTime?: string;
  177. date: string;
  178. bomId?: number;
  179. jobOrderId?: number;
  180. }
  181. export interface ProductProcessLineResponse {
  182. id: number,
  183. bomprocessId: number,
  184. operatorId: number,
  185. operatorName: string,
  186. equipmentId: number,
  187. handlerId: number,
  188. seqNo: number,
  189. name: string,
  190. description: string,
  191. equipmentDetailId: number,
  192. equipment_name: string,
  193. equipmentDetailCode: string,
  194. status: string,
  195. byproductId: number,
  196. byproductName: string,
  197. byproductQty: number,
  198. byproductUom: string,
  199. scrapQty: number,
  200. defectQty: number,
  201. defectUom: string,
  202. outputFromProcessQty: number,
  203. outputFromProcessUom: string,
  204. durationInMinutes: number,
  205. prepTimeInMinutes: number,
  206. postProdTimeInMinutes: number,
  207. startTime: string,
  208. endTime: string,
  209. }
  210. export interface ProductProcessWithLinesResponse {
  211. id: number;
  212. productProcessCode: string;
  213. status: string;
  214. startTime?: string;
  215. endTime?: string;
  216. date: string;
  217. bomId?: number;
  218. jobOrderId?: number;
  219. jobOrderCode: string;
  220. jobOrderStatus: string;
  221. jobType: string;
  222. isDark: string;
  223. isDense: number;
  224. isFloat: string;
  225. timeSequence: number;
  226. complexity: number;
  227. scrapRate: number;
  228. allergicSubstance: string;
  229. itemId: number;
  230. itemCode: string;
  231. itemName: string;
  232. outputQty: number;
  233. outputQtyUom: string;
  234. productionPriority: number;
  235. jobOrderLines: JobOrderLineInfo[];
  236. productProcessLines: ProductProcessLineResponse[];
  237. }
  238. export interface UpdateProductProcessLineQtyRequest {
  239. productProcessLineId: number;
  240. outputFromProcessQty: number;
  241. outputFromProcessUom: string;
  242. byproductName: string;
  243. byproductQty: number;
  244. byproductUom: string;
  245. defectQty: number;
  246. defectUom: string;
  247. defect2Qty: number;
  248. defect2Uom: string;
  249. defect3Qty: number;
  250. defect3Uom: string;
  251. defectDescription: string;
  252. defectDescription2: string;
  253. defectDescription3: string;
  254. scrapQty: number;
  255. scrapUom: string;
  256. }
  257. export interface UpdateProductProcessLineQtyResponse {
  258. id: number;
  259. outputFromProcessQty: number;
  260. outputFromProcessUom: string;
  261. defectQty: number;
  262. defectUom: string;
  263. defect2Qty: number;
  264. defect2Uom: string;
  265. defect3Qty: number;
  266. defect3Uom: string;
  267. defectDescription: string;
  268. defectDescription2: string;
  269. defectDescription3: string;
  270. scrapQty: number;
  271. scrapUom: string;
  272. byproductName: string;
  273. byproductQty: number;
  274. byproductUom: string;
  275. }
  276. export interface AllProductProcessResponse {
  277. id: number;
  278. productProcessCode: string;
  279. status: string;
  280. startTime?: string;
  281. endTime?: string;
  282. date: string;
  283. bomId?: number;
  284. }
  285. export interface AllJoborderProductProcessInfoResponse {
  286. id: number;
  287. productProcessCode: string;
  288. status: string;
  289. startTime?: string;
  290. endTime?: string;
  291. date: string;
  292. matchStatus: string;
  293. bomId?: number;
  294. assignedTo: number;
  295. pickOrderId: number;
  296. pickOrderStatus: string;
  297. itemCode: string;
  298. itemName: string;
  299. requiredQty: number;
  300. jobOrderId: number;
  301. uom: string;
  302. stockInLineId: number;
  303. jobOrderCode: string;
  304. productProcessLineCount: number;
  305. FinishedProductProcessLineCount: number;
  306. lines: ProductProcessInfoResponse[];
  307. }
  308. export interface ProductProcessInfoResponse {
  309. id: number;
  310. operatorId?: number;
  311. operatorName?: string;
  312. equipmentId?: number;
  313. equipmentName?: string;
  314. startTime?: string;
  315. endTime?: string;
  316. status: string;
  317. }
  318. export interface ProductProcessLineQrscanUpadteRequest {
  319. productProcessLineId: number;
  320. //operatorId?: number;
  321. //equipmentId?: number;
  322. equipmentTypeSubTypeEquipmentNo?: string;
  323. staffNo?: string;
  324. }
  325. export interface NewProductProcessLineQrscanUpadteRequest{
  326. productProcessLineId: number;
  327. equipmentCode?: string;
  328. staffNo?: string;
  329. }
  330. export interface ProductProcessLineDetailResponse {
  331. id: number,
  332. productProcessId: number,
  333. bomProcessId: number,
  334. operatorId: number,
  335. equipmentType: string,
  336. operatorName: string,
  337. handlerId: number,
  338. seqNo: number,
  339. isDark: string,
  340. isDense: number,
  341. isFloat: string,
  342. outputQtyUom: string,
  343. outputQty: number,
  344. pickOrderId: number,
  345. jobOrderCode: string,
  346. jobOrderId: number,
  347. name: string,
  348. description: string,
  349. equipment: string,
  350. startTime: string,
  351. endTime: string,
  352. defectQty: number,
  353. defectUom: string,
  354. scrapQty: number,
  355. scrapUom: string,
  356. byproductId: number,
  357. byproductName: string,
  358. byproductQty: number,
  359. byproductUom: string | undefined,
  360. totalStockQty: number,
  361. insufficientStockQty: number,
  362. sufficientStockQty: number,
  363. productionPriority: number,
  364. productProcessLines: ProductProcessLineInfoResponse[],
  365. jobOrderLineInfo: JobOrderLineInfo[],
  366. }
  367. export interface JobOrderProcessLineDetailResponse {
  368. id: number;
  369. productProcessId: number;
  370. bomProcessId: number;
  371. operatorId: number;
  372. equipmentType: string | null;
  373. operatorName: string;
  374. handlerId: number;
  375. seqNo: number;
  376. durationInMinutes: number;
  377. name: string;
  378. description: string;
  379. equipmentId: number;
  380. startTime: string | number[]; // API 返回的是数组格式
  381. endTime: string | number[]; // API 返回的是数组格式
  382. status: string;
  383. outputFromProcessQty: number;
  384. outputFromProcessUom: string;
  385. defectQty: number;
  386. defectUom: string;
  387. defectDescription: string;
  388. defectQty2: number;
  389. defectUom2: string;
  390. defectDescription2: string;
  391. defectQty3: number;
  392. defectUom3: string;
  393. defectDescription3: string;
  394. scrapQty: number;
  395. scrapUom: string;
  396. byproductId: number;
  397. byproductName: string;
  398. byproductQty: number;
  399. byproductUom: string;
  400. productProcessIssueId: number;
  401. productProcessIssueStatus: string;
  402. }
  403. export interface JobOrderLineInfo {
  404. id: number,
  405. jobOrderId: number,
  406. jobOrderCode: string,
  407. itemId: number,
  408. itemCode: string,
  409. itemName: string,
  410. reqQty: number,
  411. stockQty: number,
  412. uom: string,
  413. shortUom: string,
  414. availableStatus: string,
  415. bomProcessId: number,
  416. bomProcessSeqNo: number,
  417. }
  418. export interface ProductProcessLineInfoResponse {
  419. id: number,
  420. bomprocessId: number,
  421. operatorId: number,
  422. operatorName: string,
  423. equipmentId: number,
  424. handlerId: number,
  425. seqNo: number,
  426. name: string,
  427. description: string,
  428. equipment_name: string,
  429. equipmentDetailCode: string,
  430. status: string,
  431. byproductId: number,
  432. byproductName: string,
  433. byproductQty: number,
  434. byproductUom: string,
  435. scrapQty: number,
  436. defectQty: number,
  437. defectUom: string,
  438. durationInMinutes: number,
  439. prepTimeInMinutes: number,
  440. postProdTimeInMinutes: number,
  441. outputFromProcessQty: number,
  442. outputFromProcessUom: string,
  443. startTime: string,
  444. endTime: string
  445. }
  446. export interface AllJoPickOrderResponse {
  447. id: number;
  448. pickOrderId: number | null;
  449. pickOrderCode: string | null;
  450. jobOrderId: number | null;
  451. jobOrderCode: string | null;
  452. jobOrderTypeId: number | null;
  453. jobOrderType: string | null;
  454. itemId: number;
  455. itemName: string;
  456. reqQty: number;
  457. uomId: number;
  458. uomName: string;
  459. jobOrderStatus: string;
  460. finishedPickOLineCount: number;
  461. }
  462. export interface UpdateJoPickOrderHandledByRequest {
  463. pickOrderId: number;
  464. itemId: number;
  465. userId: number;
  466. }
  467. export interface JobTypeResponse {
  468. id: number;
  469. name: string;
  470. }
  471. export interface SaveProductProcessIssueTimeRequest {
  472. productProcessLineId: number;
  473. reason: string;
  474. }
  475. export interface JobOrderLotsHierarchicalResponse {
  476. pickOrder: PickOrderInfoResponse;
  477. pickOrderLines: PickOrderLineWithLotsResponse[];
  478. }
  479. export interface PickOrderInfoResponse {
  480. id: number | null;
  481. code: string | null;
  482. consoCode: string | null;
  483. targetDate: string | null;
  484. type: string | null;
  485. status: string | null;
  486. assignTo: number | null;
  487. jobOrder: JobOrderBasicInfoResponse;
  488. }
  489. export interface JobOrderBasicInfoResponse {
  490. id: number;
  491. code: string;
  492. name: string;
  493. }
  494. export interface PickOrderLineWithLotsResponse {
  495. id: number;
  496. itemId: number | null;
  497. itemCode: string | null;
  498. itemName: string | null;
  499. requiredQty: number | null;
  500. uomCode: string | null;
  501. uomDesc: string | null;
  502. status: string | null;
  503. handler: string | null;
  504. lots: LotDetailResponse[];
  505. }
  506. export interface LotDetailResponse {
  507. lotId: number | null;
  508. lotNo: string | null;
  509. expiryDate: string | null;
  510. location: string | null;
  511. availableQty: number | null;
  512. requiredQty: number | null;
  513. actualPickQty: number | null;
  514. processingStatus: string | null;
  515. lotAvailability: string | null;
  516. pickOrderId: number | null;
  517. pickOrderCode: string | null;
  518. pickOrderConsoCode: string | null;
  519. pickOrderLineId: number | null;
  520. stockOutLineId: number | null;
  521. suggestedPickLotId: number | null;
  522. stockOutLineQty: number | null;
  523. stockOutLineStatus: string | null;
  524. routerIndex: number | null;
  525. routerArea: string | null;
  526. routerRoute: string | null;
  527. uomShortDesc: string | null;
  528. matchStatus?: string | null;
  529. matchBy?: number | null;
  530. matchQty?: number | null;
  531. }
  532. export interface JobOrderListForPrintQrCodeResponse {
  533. id: number;
  534. code: string;
  535. name: string;
  536. reqQty: number;
  537. stockOutLineId: number;
  538. stockOutLineQty: number;
  539. stockOutLineStatus: string;
  540. finihedTime: string;
  541. }
  542. export const saveProductProcessIssueTime = cache(async (request: SaveProductProcessIssueTimeRequest) => {
  543. return serverFetchJson<any>(
  544. `${BASE_API_URL}/product-process/Demo/ProcessLine/issue`,
  545. {
  546. method: "POST",
  547. headers: { "Content-Type": "application/json" },
  548. body: JSON.stringify(request),
  549. }
  550. );
  551. });
  552. export const saveProductProcessResumeTime = cache(async (productProcessIssueId: number) => {
  553. return serverFetchJson<any>(
  554. `${BASE_API_URL}/product-process/Demo/ProcessLine/resume/${productProcessIssueId}`,
  555. {
  556. method: "POST",
  557. }
  558. );
  559. });
  560. export const deleteJobOrder=cache(async (jobOrderId: number) => {
  561. return serverFetchJson<any>(
  562. `${BASE_API_URL}/jo/demo/deleteJobOrder/${jobOrderId}`,
  563. {
  564. method: "POST",
  565. }
  566. );
  567. });
  568. export const fetchAllJobTypes = cache(async () => {
  569. return serverFetchJson<JobTypeResponse[]>(
  570. `${BASE_API_URL}/jo/jobTypes`,
  571. {
  572. method: "GET",
  573. }
  574. );
  575. });
  576. export const updateJoPickOrderHandledBy = cache(async (request: UpdateJoPickOrderHandledByRequest) => {
  577. return serverFetchJson<any>(
  578. `${BASE_API_URL}/jo/update-jo-pick-order-handled-by`,
  579. {
  580. method: "POST",
  581. body: JSON.stringify(request),
  582. headers: { "Content-Type": "application/json" },
  583. },
  584. );
  585. });
  586. export const fetchJobOrderLotsHierarchicalByPickOrderId = cache(async (pickOrderId: number) => {
  587. return serverFetchJson<JobOrderLotsHierarchicalResponse>(
  588. `${BASE_API_URL}/jo/all-lots-hierarchical-by-pick-order/${pickOrderId}`,
  589. {
  590. method: "GET",
  591. next: { tags: ["jo-hierarchical"] },
  592. },
  593. );
  594. });
  595. export const fetchAllJoPickOrders = cache(async () => {
  596. return serverFetchJson<AllJoPickOrderResponse[]>(
  597. `${BASE_API_URL}/jo/AllJoPickOrder`,
  598. {
  599. method: "GET",
  600. }
  601. );
  602. });
  603. export const fetchProductProcessLineDetail = cache(async (lineId: number) => {
  604. return serverFetchJson<JobOrderProcessLineDetailResponse>(
  605. `${BASE_API_URL}/product-process/Demo/ProcessLine/detail/${lineId}`,
  606. {
  607. method: "GET",
  608. }
  609. );
  610. });
  611. export const updateProductProcessLineQty = cache(async (request: UpdateProductProcessLineQtyRequest) => {
  612. return serverFetchJson<UpdateProductProcessLineQtyResponse>(
  613. `${BASE_API_URL}/product-process/Demo/ProcessLine/update/qty/${request.productProcessLineId}`,
  614. {
  615. method: "POST",
  616. headers: { "Content-Type": "application/json" },
  617. body: JSON.stringify(request),
  618. }
  619. );
  620. });
  621. export const updateProductProcessLineQrscan = cache(async (request: ProductProcessLineQrscanUpadteRequest) => {
  622. const requestBody: any = {
  623. productProcessLineId: request.productProcessLineId,
  624. //operatorId: request.operatorId,
  625. //equipmentId: request.equipmentId,
  626. equipmentTypeSubTypeEquipmentNo: request.equipmentTypeSubTypeEquipmentNo,
  627. staffNo: request.staffNo,
  628. };
  629. if (request.equipmentTypeSubTypeEquipmentNo !== undefined) {
  630. requestBody["EquipmentType-SubType-EquipmentNo"] = request.equipmentTypeSubTypeEquipmentNo;
  631. }
  632. return serverFetchJson<any>(
  633. `${BASE_API_URL}/product-process/Demo/update`,
  634. {
  635. method: "POST",
  636. headers: { "Content-Type": "application/json" },
  637. body: JSON.stringify(requestBody),
  638. }
  639. );
  640. });
  641. export const newUpdateProductProcessLineQrscan = cache(async (request: NewProductProcessLineQrscanUpadteRequest) => {
  642. return serverFetchJson<any>(
  643. `${BASE_API_URL}/product-process/Demo/NewUpdate`,
  644. {
  645. method: "POST",
  646. headers: { "Content-Type": "application/json" },
  647. body: JSON.stringify(request),
  648. }
  649. );
  650. });
  651. export const fetchAllJoborderProductProcessInfo = cache(async () => {
  652. return serverFetchJson<AllJoborderProductProcessInfoResponse[]>(
  653. `${BASE_API_URL}/product-process/Demo/Process/all`,
  654. {
  655. method: "GET",
  656. next: { tags: ["productProcess"] },
  657. }
  658. );
  659. });
  660. /*
  661. export const updateProductProcessLineQty = async (request: UpdateProductProcessLineQtyRequest) => {
  662. return serverFetchJson<UpdateProductProcessLineQtyResponse>(
  663. `${BASE_API_URL}/product-process/lines/${request.productProcessLineId}/update/qty`,
  664. {
  665. method: "POST",
  666. headers: { "Content-Type": "application/json" },
  667. body: JSON.stringify(request),
  668. }
  669. );
  670. };
  671. */
  672. export const startProductProcessLine = async (lineId: number) => {
  673. return serverFetchJson<any>(
  674. `${BASE_API_URL}/product-process/Demo/ProcessLine/start/${lineId}`,
  675. {
  676. method: "POST",
  677. headers: { "Content-Type": "application/json" },
  678. }
  679. );
  680. };
  681. export const completeProductProcessLine = async (lineId: number) => {
  682. return serverFetchJson<any>(
  683. `${BASE_API_URL}/product-process/Demo/ProcessLine/complete/${lineId}`,
  684. {
  685. method: "POST",
  686. headers: { "Content-Type": "application/json" },
  687. }
  688. );
  689. };
  690. // 查询所有 production processes
  691. export const fetchProductProcesses = cache(async () => {
  692. return serverFetchJson<{ content: ProductProcessResponse[] }>(
  693. `${BASE_API_URL}/product-process`,
  694. {
  695. method: "GET",
  696. next: { tags: ["productProcess"] },
  697. }
  698. );
  699. });
  700. // 根据 ID 查询
  701. export const fetchProductProcessById = cache(async (id: number) => {
  702. return serverFetchJson<ProductProcessResponse>(
  703. `${BASE_API_URL}/product-process/${id}`,
  704. {
  705. method: "GET",
  706. next: { tags: ["productProcess"] },
  707. }
  708. );
  709. });
  710. export const updateProductProcessPriority = cache(async (productProcessId: number, productionPriority: number) => {
  711. return serverFetchJson<any>(
  712. `${BASE_API_URL}/product-process/Demo/Process/update/priority/${productProcessId}/${productionPriority}`,
  713. {
  714. method: "POST",
  715. }
  716. );
  717. });
  718. // 根据 Job Order ID 查询
  719. export const fetchProductProcessesByJobOrderId = cache(async (jobOrderId: number) => {
  720. return serverFetchJson<ProductProcessWithLinesResponse[]>(
  721. `${BASE_API_URL}/product-process/demo/joid/${jobOrderId}`,
  722. {
  723. method: "GET",
  724. next: { tags: ["productProcess"] },
  725. }
  726. );
  727. });
  728. // 获取 process 的所有 lines
  729. export const fetchProductProcessLines = cache(async (processId: number) => {
  730. return serverFetchJson<ProductProcessLineResponse[]>(
  731. `${BASE_API_URL}/product-process/${processId}/lines`,
  732. {
  733. method: "GET",
  734. next: { tags: ["productProcessLines"] },
  735. }
  736. );
  737. });
  738. // 创建 production process
  739. export const createProductProcess = async (data: {
  740. bomId: number;
  741. jobOrderId?: number;
  742. date?: string;
  743. }) => {
  744. return serverFetchJson<{ id: number; productProcessCode: string; linesCreated: number }>(
  745. `${BASE_API_URL}/product-process`,
  746. {
  747. method: "POST",
  748. headers: { "Content-Type": "application/json" },
  749. body: JSON.stringify(data),
  750. }
  751. );
  752. };
  753. // 更新 line 产出数据
  754. export const updateLineOutput = async (lineId: number, data: {
  755. outputQty?: number;
  756. outputUom?: string;
  757. defectQty?: number;
  758. defectUom?: string;
  759. scrapQty?: number;
  760. scrapUom?: string;
  761. byproductName?: string;
  762. byproductQty?: number;
  763. byproductUom?: string;
  764. }) => {
  765. return serverFetchJson<ProductProcessLineResponse>(
  766. `${BASE_API_URL}/product-process/lines/${lineId}/output`,
  767. {
  768. method: "PUT",
  769. headers: { "Content-Type": "application/json" },
  770. body: JSON.stringify(data),
  771. }
  772. );
  773. };
  774. export const updateSecondQrScanStatus = cache(async (pickOrderId: number, itemId: number, userId: number, qty: number) => {
  775. return serverFetchJson<any>(
  776. `${BASE_API_URL}/jo/update-match-status`,
  777. {
  778. method: "POST",
  779. body: JSON.stringify({
  780. pickOrderId,
  781. itemId,
  782. userId,
  783. qty
  784. }),
  785. headers: {
  786. 'Content-Type': 'application/json',
  787. },
  788. next: { tags: ["update-match-status"] },
  789. },
  790. );
  791. });
  792. export const submitSecondScanQuantity = cache(async (
  793. pickOrderId: number,
  794. itemId: number,
  795. data: { qty: number; isMissing?: boolean; isBad?: boolean; reason?: string }
  796. ) => {
  797. return serverFetchJson<any>(
  798. `${BASE_API_URL}/jo/second-scan-submit/${pickOrderId}/${itemId}`,
  799. {
  800. method: "POST",
  801. headers: { "Content-Type": "application/json" },
  802. body: JSON.stringify(data),
  803. next: { tags: ["jo-second-scan"] },
  804. },
  805. );
  806. });
  807. // 获取未分配的 Job Order pick orders
  808. export const fetchUnassignedJobOrderPickOrders = cache(async () => {
  809. return serverFetchJson<UnassignedJobOrderPickOrder[]>(
  810. `${BASE_API_URL}/jo/unassigned-job-order-pick-orders`,
  811. {
  812. method: "GET",
  813. next: { tags: ["jo-unassigned"] },
  814. },
  815. );
  816. });
  817. // 分配 Job Order pick order 给用户
  818. export const assignJobOrderPickOrder = async (pickOrderId: number, userId: number) => {
  819. return serverFetchJson<AssignJobOrderResponse>(
  820. `${BASE_API_URL}/jo/assign-job-order-pick-order/${pickOrderId}/${userId}`,
  821. {
  822. method: "POST",
  823. headers: { "Content-Type": "application/json" },
  824. }
  825. );
  826. };
  827. export const unAssignJobOrderPickOrder = async (pickOrderId: number) => {
  828. return serverFetchJson<AssignJobOrderResponse>(
  829. `${BASE_API_URL}/jo/unassign-job-order-pick-order/${pickOrderId}`,
  830. {
  831. method: "POST",
  832. headers: { "Content-Type": "application/json" },
  833. }
  834. );
  835. };
  836. // 获取 Job Order 分层数据
  837. export const fetchJobOrderLotsHierarchical = cache(async (userId: number) => {
  838. return serverFetchJson<JobOrderLotsHierarchicalResponse>(
  839. `${BASE_API_URL}/jo/all-lots-hierarchical/${userId}`,
  840. {
  841. method: "GET",
  842. next: { tags: ["jo-hierarchical"] },
  843. },
  844. );
  845. });
  846. export const fetchCompletedJobOrderPickOrders = cache(async (userId: number) => {
  847. return serverFetchJson<any>(
  848. `${BASE_API_URL}/jo/completed-job-order-pick-orders/${userId}`,
  849. {
  850. method: "GET",
  851. next: { tags: ["jo-completed"] },
  852. },
  853. );
  854. });
  855. // 获取已完成的 Job Order pick orders
  856. export const fetchCompletedJobOrderPickOrdersrecords = cache(async () => {
  857. return serverFetchJson<any>(
  858. `${BASE_API_URL}/jo/completed-job-order-pick-orders-only`,
  859. {
  860. method: "GET",
  861. next: { tags: ["jo-completed"] },
  862. },
  863. );
  864. });
  865. export const fetchJoForPrintQrCode = cache(async (date: string) => {
  866. return serverFetchJson<JobOrderListForPrintQrCodeResponse[]>(
  867. `${BASE_API_URL}/jo/joForPrintQrCode/${date}`,
  868. {
  869. method: "GET",
  870. next: { tags: ["jo-print-qr-code"] },
  871. },
  872. );
  873. });
  874. // 获取已完成的 Job Order pick order records
  875. export const fetchCompletedJobOrderPickOrderRecords = cache(async (userId: number) => {
  876. return serverFetchJson<any[]>(
  877. `${BASE_API_URL}/jo/completed-job-order-pick-order-records/${userId}`,
  878. {
  879. method: "GET",
  880. next: { tags: ["jo-records"] },
  881. },
  882. );
  883. });
  884. export const fetchJobOrderDetailByCode = cache(async (code: string) => {
  885. return serverFetchJson<JobOrderDetail>(
  886. `${BASE_API_URL}/jo/detailByCode/${code}`,
  887. {
  888. method: "GET",
  889. next: { tags: ["jo"] },
  890. },
  891. );
  892. });
  893. export const isOperatorExist = async (username: string) => {
  894. const isExist = await serverFetchJson<IsOperatorExistResponse<Operator>>(
  895. `${BASE_API_URL}/jop/isOperatorExist`,
  896. {
  897. method: "POST",
  898. body: JSON.stringify({ username }),
  899. headers: { "Content-Type": "application/json" },
  900. },
  901. );
  902. revalidateTag("po");
  903. return isExist;
  904. };
  905. export const isCorrectMachineUsed = async (machineCode: string) => {
  906. const isExist = await serverFetchJson<isCorrectMachineUsedResponse<Machine>>(
  907. `${BASE_API_URL}/jop/isCorrectMachineUsed`,
  908. {
  909. method: "POST",
  910. body: JSON.stringify({ machineCode }),
  911. headers: { "Content-Type": "application/json" },
  912. },
  913. );
  914. revalidateTag("po");
  915. return isExist;
  916. };
  917. export const fetchJos = cache(async (data?: SearchJoResultRequest) => {
  918. const queryStr = convertObjToURLSearchParams(data)
  919. console.log("queryStr", queryStr)
  920. const fullUrl = `${BASE_API_URL}/jo/getRecordByPage?${queryStr}`;
  921. console.log("fetchJos full URL:", fullUrl);
  922. console.log("fetchJos BASE_API_URL:", BASE_API_URL);
  923. const response = await serverFetchJson<SearchJoResultResponse>(
  924. `${BASE_API_URL}/jo/getRecordByPage?${queryStr}`,
  925. {
  926. method: "GET",
  927. headers: { "Content-Type": "application/json" },
  928. next: {
  929. tags: ["jos"]
  930. }
  931. }
  932. )
  933. console.log("fetchJos response:", response)
  934. return response
  935. })
  936. export const updateJo = cache(async (data: UpdateJoRequest) => {
  937. return serverFetchJson<SaveJoResponse>(`${BASE_API_URL}/jo/update`,
  938. {
  939. method: "POST",
  940. body: JSON.stringify(data),
  941. headers: { "Content-Type": "application/json" },
  942. })
  943. })
  944. export const releaseJo = cache(async (data: CommonActionJoRequest) => {
  945. const response = serverFetchJson<CommonActionJoResponse>(`${BASE_API_URL}/jo/release`,
  946. {
  947. method: "POST",
  948. body: JSON.stringify(data),
  949. headers: { "Content-Type": "application/json" },
  950. })
  951. // Invalidate the cache after releasing
  952. revalidateTag("jo");
  953. return response;
  954. })
  955. export const startJo = cache(async (data: CommonActionJoRequest) => {
  956. const response = serverFetchJson<CommonActionJoResponse>(`${BASE_API_URL}/jo/start`,
  957. {
  958. method: "POST",
  959. body: JSON.stringify(data),
  960. headers: { "Content-Type": "application/json" },
  961. })
  962. // Invalidate the cache after starting
  963. revalidateTag("jo");
  964. return response;
  965. })
  966. export const manualCreateJo = cache(async (data: SaveJo) => {
  967. return serverFetchJson<SaveJoResponse>(`${BASE_API_URL}/jo/manualCreate`, {
  968. method: "POST",
  969. body: JSON.stringify(data),
  970. headers: { "Content-Type": "application/json" }
  971. })
  972. })
  973. export const fetchCompletedJobOrderPickOrdersWithCompletedSecondScan = cache(async (userId: number) => {
  974. return serverFetchJson<any[]>(`${BASE_API_URL}/jo/completed-job-order-pick-orders-with-completed-second-scan/${userId}`, {
  975. method: "GET",
  976. headers: { "Content-Type": "application/json" }
  977. })
  978. })
  979. export const fetchCompletedJobOrderPickOrderLotDetails = cache(async (pickOrderId: number) => {
  980. return serverFetchJson<any[]>(`${BASE_API_URL}/jo/completed-job-order-pick-order-lot-details/${pickOrderId}`, {
  981. method: "GET",
  982. headers: { "Content-Type": "application/json" }
  983. })
  984. })
  985. export const fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick = cache(async (pickOrderId: number) => {
  986. return serverFetchJson<any[]>(`${BASE_API_URL}/jo/completed-job-order-pick-order-lot-details-completed-pick/${pickOrderId}`, {
  987. method: "GET",
  988. headers: { "Content-Type": "application/json" }
  989. })
  990. })
  991. export async function PrintPickRecord(request: PrintPickRecordRequest){
  992. const params = new URLSearchParams();
  993. params.append('pickOrderId', request.pickOrderId.toString())
  994. params.append('printerId', request.printerId.toString())
  995. if (request.printQty !== null && request.printQty !== undefined) {
  996. params.append('printQty', request.printQty.toString());
  997. }
  998. //const response = await serverFetchWithNoContent(`${BASE_API_URL}/jo/print-PickRecord?${params.toString()}`,{
  999. const response = await serverFetchWithNoContent(`${BASE_API_URL}/jo/print-PickRecord?${params.toString()}`,{
  1000. method: "GET"
  1001. });
  1002. return { success: true, message: "Print job sent successfully (Pick Record)" } as PrintPickRecordResponse;
  1003. }
  1004. export interface ExportFGStockInLabelRequest {
  1005. stockInLineId: number;
  1006. }
  1007. export const fetchFGStockInLabel = async (data: ExportFGStockInLabelRequest): Promise<FileResponse> => {
  1008. const reportBlob = await serverFetchBlob<FileResponse>(
  1009. `${BASE_API_URL}/jo/FGStockInLabel`,
  1010. {
  1011. method: "POST",
  1012. body: JSON.stringify(data),
  1013. headers: { "Content-Type": "application/json" },
  1014. },
  1015. );
  1016. return reportBlob;
  1017. };