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.
 
 

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