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

909 linhas
26 KiB

  1. "use client";
  2. import {
  3. Box,
  4. Button,
  5. ButtonProps,
  6. Card,
  7. CardContent,
  8. CardHeader,
  9. CircularProgress,
  10. Grid,
  11. Stack,
  12. Tooltip,
  13. Typography,
  14. } from "@mui/material";
  15. import PlayArrowIcon from "@mui/icons-material/PlayArrow";
  16. import { useTranslation } from "react-i18next";
  17. import StyledDataGrid from "../StyledDataGrid";
  18. import { useCallback, useEffect, useMemo, useState } from "react";
  19. import {
  20. GridColDef,
  21. GridRowId,
  22. GridRowIdGetter,
  23. GridRowModel,
  24. GridRowModes,
  25. useGridApiRef,
  26. GridRenderEditCellParams,
  27. GridEditInputCell,
  28. GridRowParams,
  29. } from "@mui/x-data-grid";
  30. import DoneIcon from "@mui/icons-material/Done";
  31. import { GridRowSelectionModel } from "@mui/x-data-grid";
  32. import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
  33. import {
  34. completeConsoPickOrder,
  35. CreateStockOutLine,
  36. createStockOutLine,
  37. fetchConsoStatus,
  38. fetchPickOrderLineClient,
  39. fetchStockOutLineClient,
  40. PickOrderApprovalInput,
  41. PickOrderQcInput,
  42. } from "@/app/api/pickOrder/actions";
  43. import {
  44. PickOrderLineWithSuggestedLot,
  45. StockOutLine,
  46. } from "@/app/api/pickOrder";
  47. import { Pageable } from "@/app/utils/fetchUtil";
  48. import { QrCodeInfo } from "@/app/api/qrcode";
  49. import { QrCode } from "../QrCode";
  50. import { fetchLotDetail, LotLineInfo } from "@/app/api/inventory/actions";
  51. import { GridRowModesModel } from "@mui/x-data-grid";
  52. import { stockOutLineStatusMap } from "@/app/utils/formatUtil";
  53. import { GridActionsCellItem } from "@mui/x-data-grid";
  54. import DoDisturbIcon from "@mui/icons-material/DoDisturb";
  55. import useUploadContext from "../UploadProvider/useUploadContext";
  56. import { FitAllCell } from "@/app/utils/gridUtil";
  57. import { QcItemWithChecks } from "@/app/api/qc";
  58. import QcForm from "./QcForm";
  59. import { fetchPickOrderQcResult, QcResult } from "@/app/api/qc/actions";
  60. import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
  61. import AutoFixNormalIcon from "@mui/icons-material/AutoFixNormal";
  62. import ApprovalForm from "./ApprovalForm";
  63. import InfoIcon from "@mui/icons-material/Info";
  64. import VerifiedIcon from "@mui/icons-material/Verified";
  65. import { isNullOrUndefined } from "html5-qrcode/esm/core";
  66. interface Props {
  67. qc: QcItemWithChecks[];
  68. consoCode: string;
  69. }
  70. interface IsLoadingModel {
  71. pickOrderLineTable: boolean;
  72. stockOutLineTable: boolean;
  73. }
  74. export type StockOutLineEntryError = {
  75. [field in keyof StockOutLine]?: string;
  76. };
  77. export type StockOutLineRow = Partial<
  78. StockOutLine & {
  79. id: number;
  80. isActive: boolean | undefined;
  81. _isNew: boolean;
  82. _error: StockOutLineEntryError;
  83. }
  84. >;
  85. class ProcessRowUpdateError extends Error {
  86. public readonly row: StockOutLineRow;
  87. public readonly errors: StockOutLineEntryError | undefined;
  88. constructor(
  89. row: StockOutLineRow,
  90. message?: string,
  91. errors?: StockOutLineEntryError,
  92. ) {
  93. super(message);
  94. this.row = row;
  95. this.errors = errors;
  96. Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
  97. }
  98. }
  99. export type formDefaultValues = StockOutLine &
  100. (PickOrderQcInput | PickOrderApprovalInput);
  101. const PickOrderDetail: React.FC<Props> = ({ consoCode, qc }) => {
  102. const { t } = useTranslation("pickOrder");
  103. const apiRef = useGridApiRef();
  104. const [qcResult, setQcResult] = useState([] as QcResult[]);
  105. const [selectedRow, setSelectedRow] = useState<GridRowSelectionModel>([]);
  106. const [currPol, setCurrPol] = useState<PickOrderLineWithSuggestedLot>();
  107. const [isChangeLotSolId, setIsChangeLotSolId] = useState<number | undefined>(
  108. undefined,
  109. );
  110. const [formDefaultValues, setFormDefaultValues] =
  111. useState<formDefaultValues>();
  112. const [isLoadingModel, setIsLoadingModel] = useState<IsLoadingModel>({
  113. pickOrderLineTable: false,
  114. stockOutLineTable: false,
  115. });
  116. const [polCriteriaArgs, setPolCriteriaArgs] = useState<Pageable>({
  117. pageNum: 1,
  118. pageSize: 10,
  119. });
  120. const [solCriteriaArgs, setSolCriteriaArgs] = useState<Pageable>({
  121. pageNum: 1,
  122. pageSize: 10,
  123. });
  124. const [polTotalCount, setPolTotalCount] = useState(0);
  125. const [solTotalCount, setSolTotalCount] = useState(0);
  126. const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
  127. const [btnIsLoading, setBtnIsLoading] = useState(false);
  128. const { setIsUploading } = useUploadContext();
  129. const [pickOrderLine, setPickOrderLine] = useState<
  130. PickOrderLineWithSuggestedLot[]
  131. >([]);
  132. const pickOrderLineColumns = useMemo<GridColDef[]>(
  133. () => [
  134. {
  135. field: "id",
  136. headerName: "pickOrderLineId",
  137. flex: 1,
  138. },
  139. {
  140. field: "itemName",
  141. headerName: "itemId",
  142. flex: 1,
  143. },
  144. {
  145. field: "qty",
  146. headerName: "qty",
  147. flex: 1,
  148. },
  149. {
  150. field: "uom",
  151. headerName: "uom",
  152. flex: 1,
  153. },
  154. // {
  155. // field: "lotLineId",
  156. // headerName: "lotLineId",
  157. // flex: 1,
  158. // },
  159. {
  160. field: "warehouse",
  161. headerName: "location",
  162. flex: 1,
  163. renderCell: (params) => {
  164. // console.log(params.row.warehouse)
  165. return params.row.warehouse;
  166. if (isNullOrUndefined(params.row.warehouse)) {
  167. return <></>;
  168. } else {
  169. const warehouseList = JSON.parse(
  170. `{${params.row.warehouse}}`,
  171. ) as string[];
  172. return FitAllCell(warehouseList);
  173. }
  174. },
  175. },
  176. {
  177. field: "suggestedLotNo",
  178. headerName: "suggestedLotNo",
  179. flex: 1.2,
  180. renderCell: (params) => {
  181. return params.row.suggestedLotNo;
  182. if (isNullOrUndefined(params.row.suggestedLotNo)) return <></>;
  183. const suggestedLotNoList = JSON.parse(
  184. params.row.suggestedLotNo,
  185. ) as string[];
  186. return FitAllCell(suggestedLotNoList);
  187. },
  188. },
  189. {
  190. field: "status",
  191. headerName: t("status"),
  192. flex: 0.5,
  193. renderCell: (params) => {
  194. return t(`${params.row.status}`);
  195. },
  196. },
  197. ],
  198. [],
  199. );
  200. const [isDisableComplete, setIsDisableComplete] = useState(true);
  201. const [status, setStatus] = useState("");
  202. const getConsoStatus = useCallback(async () => {
  203. const status = await fetchConsoStatus(consoCode);
  204. console.log(status);
  205. setStatus(status.status);
  206. }, [fetchConsoStatus]);
  207. const fetchPickOrderLine = useCallback(
  208. async (params: Record<string, any>) => {
  209. setIsLoadingModel((prev) => ({
  210. ...prev,
  211. pickOrderLineTable: true,
  212. }));
  213. const res = await fetchPickOrderLineClient({
  214. ...params,
  215. consoCode: consoCode,
  216. });
  217. if (res) {
  218. console.log(res);
  219. console.log(res.records.every((line) => line.status == "completed"));
  220. setIsDisableComplete(res.records[0].poStatus === "completed");
  221. // setIsDisableComplete(() =>
  222. // res.records.every((line) => line.status !== "completed"),
  223. // );
  224. setPickOrderLine(res.records);
  225. setPolTotalCount(res.total);
  226. } else {
  227. console.log("error");
  228. console.log(res);
  229. }
  230. setIsLoadingModel((prev) => ({
  231. ...prev,
  232. pickOrderLineTable: false,
  233. }));
  234. },
  235. [fetchPickOrderLineClient, consoCode],
  236. );
  237. const [stockOutLine, setStockOutLine] = useState<StockOutLine[]>([]);
  238. const getRowId = useCallback<GridRowIdGetter<StockOutLineRow>>(
  239. (row) => row.id as number,
  240. [],
  241. );
  242. const [qcOpen, setQcOpen] = useState(false);
  243. const [approvalOpen, setApprovalOpen] = useState(false);
  244. const closeQcModal = useCallback(() => {
  245. setQcOpen(false);
  246. }, []);
  247. const openQcModal = useCallback(() => {
  248. setQcOpen(true);
  249. }, []);
  250. const closeApprovalModal = useCallback(() => {
  251. setApprovalOpen(false);
  252. }, []);
  253. const openApprovalModal = useCallback(() => {
  254. setApprovalOpen(true);
  255. }, []);
  256. const triggerRefetch = useCallback(() => {
  257. setSelectedRow((prev) => prev);
  258. }, []);
  259. const handleDelete = useCallback(
  260. (id: GridRowId) => () => {
  261. setStockOutLine((prev) => prev.filter((e) => getRowId(e) !== id));
  262. },
  263. [getRowId],
  264. );
  265. const handleStart = useCallback(
  266. (id: GridRowId, params: any) => () => {
  267. setBtnIsLoading(true);
  268. setRowModesModel((prev) => ({
  269. ...prev,
  270. [id]: { mode: GridRowModes.View },
  271. }));
  272. setTimeout(async () => {
  273. // post stock in line
  274. const oldId = params.row.id;
  275. console.log(params.row);
  276. // console.log(currPol);
  277. const postData = {
  278. consoCode: consoCode,
  279. pickOrderLineId: params.row.pickOrderLineId,
  280. inventoryLotLineId: params.row.inventoryLotLineId,
  281. qty: params.row.qty,
  282. } as CreateStockOutLine;
  283. console.log(postData);
  284. // return
  285. console.log("triggering");
  286. const res = await createStockOutLine(postData);
  287. if (res) {
  288. console.log(res);
  289. setStockOutLine((prev) =>
  290. prev.map((p) =>
  291. p.id === oldId ? (res.entity as StockOutLine) : p,
  292. ),
  293. );
  294. }
  295. setBtnIsLoading(false);
  296. // do post directly to test
  297. // openStartModal();
  298. }, 500);
  299. },
  300. [createStockOutLine],
  301. );
  302. useEffect(() => {
  303. console.log(stockOutLine);
  304. }, [stockOutLine]);
  305. const handleApproval = useCallback(
  306. (id: GridRowId, params: any) => async () => {
  307. setBtnIsLoading(true);
  308. console.log(params.row.qty);
  309. console.log(params.row);
  310. setFormDefaultValues({
  311. ...(params.row as StockOutLine),
  312. status: "lot-change",
  313. } as StockOutLine & PickOrderApprovalInput);
  314. setTimeout(() => {
  315. // open qc modal
  316. console.log("delayed");
  317. openApprovalModal();
  318. setBtnIsLoading(false);
  319. }, 200);
  320. },
  321. [],
  322. );
  323. const handleLotChange = useCallback(
  324. (id: GridRowId, params: GridRowParams<any>) => async () => {
  325. setOpenScanner((prev) => !prev);
  326. console.log(id);
  327. setIsChangeLotSolId((prev) => {
  328. if (prev != undefined) return undefined;
  329. return id as number;
  330. });
  331. },
  332. [],
  333. );
  334. useEffect(() => {
  335. console.log(isChangeLotSolId);
  336. }, [isChangeLotSolId]);
  337. const handleComplete = useCallback(
  338. (id: GridRowId, params: any) => async () => {
  339. setBtnIsLoading(true);
  340. setRowModesModel((prev) => ({
  341. ...prev,
  342. [id]: { mode: GridRowModes.View },
  343. }));
  344. getQcResult(id as number).then((qcResult) => {
  345. setQcResult(qcResult);
  346. });
  347. console.log(params.row.qty);
  348. console.log(params.row);
  349. setFormDefaultValues({
  350. ...(params.row as StockOutLine),
  351. qty: params.row.qty,
  352. status: "completed",
  353. } as StockOutLine & PickOrderQcInput);
  354. setTimeout(() => {
  355. // open qc modal
  356. console.log("delayed");
  357. openQcModal();
  358. setBtnIsLoading(false);
  359. }, 200);
  360. },
  361. [],
  362. );
  363. const stockOutLineColumns = useMemo<GridColDef[]>(
  364. () => [
  365. {
  366. field: "itemName",
  367. headerName: "item name",
  368. flex: 1,
  369. },
  370. {
  371. field: "qty",
  372. headerName: "qty",
  373. editable: true,
  374. flex: 1,
  375. type: "number",
  376. // renderEditCell(params: GridRenderEditCellParams<StockOutLineRow>) {
  377. // const errorMessage =
  378. // params.row._error?.[params.field as keyof StockOutLineEntryError];
  379. // const content = (
  380. // <GridEditInputCell
  381. // {...params}
  382. // inputProps={{ min: 0 }}
  383. // />
  384. // );
  385. // return errorMessage ? (
  386. // <Tooltip title={t(errorMessage)}>
  387. // <Box width="100%">{content}</Box>
  388. // </Tooltip>
  389. // ) : (
  390. // content
  391. // );
  392. // },
  393. },
  394. {
  395. field: "lotNo",
  396. headerName: "lotNo",
  397. flex: 1,
  398. },
  399. {
  400. field: "status",
  401. headerName: t("status"),
  402. flex: 0.5,
  403. renderCell: (params) => {
  404. return t(`${params.row.status}`);
  405. },
  406. },
  407. {
  408. field: "actions",
  409. type: "actions",
  410. headerName: `${t("start")}
  411. | ${t("approval")}
  412. | ${t("lot change")}
  413. | ${t("checkout")}
  414. | ${t("delete")}`,
  415. flex: 1.5,
  416. cellClassName: "actions",
  417. getActions: (params) => {
  418. const status = params.row.status.toLowerCase();
  419. return [
  420. <GridActionsCellItem
  421. icon={<PlayArrowIcon />}
  422. label="start"
  423. sx={{
  424. color: "primary.main",
  425. // marginRight: 1,
  426. }}
  427. disabled={!(stockOutLineStatusMap[status] === 0)}
  428. // set _isNew to false after posting
  429. // or check status
  430. onClick={handleStart(params.row.id, params)}
  431. color="inherit"
  432. key="edit"
  433. />,
  434. <GridActionsCellItem
  435. icon={<VerifiedIcon />}
  436. label="approval"
  437. sx={{
  438. color: "primary.main",
  439. // marginRight: 1,
  440. }}
  441. disabled={stockOutLineStatusMap[status] !== 2}
  442. // set _isNew to false after posting
  443. // or check status
  444. onClick={handleApproval(params.row.id, params)} // start scanning for that row
  445. color="inherit"
  446. key="edit"
  447. />,
  448. <GridActionsCellItem
  449. icon={<AutoFixNormalIcon />}
  450. label="lot change" ///
  451. sx={{
  452. color: "primary.main",
  453. // marginRight: 1,
  454. }}
  455. disabled={stockOutLineStatusMap[status] !== 3}
  456. // set _isNew to false after posting
  457. // or check status
  458. onClick={handleLotChange(params.row.id, params)} // start scanning for that row
  459. color="inherit"
  460. key="edit"
  461. />,
  462. <GridActionsCellItem
  463. icon={<ShoppingCartIcon />}
  464. label="qcAndPick"
  465. sx={{
  466. color: "primary.main",
  467. // marginRight: 1,
  468. }}
  469. disabled={
  470. !params.row.inventoryLotLineId ||
  471. stockOutLineStatusMap[status] === 2 ||
  472. stockOutLineStatusMap[status] >= 4 ||
  473. stockOutLineStatusMap[status] === 0
  474. }
  475. // set _isNew to false after posting
  476. // or check status
  477. onClick={handleComplete(params.row.id, params)}
  478. color="inherit"
  479. key="edit"
  480. />,
  481. <GridActionsCellItem
  482. key={1}
  483. icon={<DoDisturbIcon />}
  484. label="Delete"
  485. sx={{
  486. color: "error.main",
  487. }}
  488. disabled={stockOutLineStatusMap[status] > 0}
  489. onClick={handleDelete(params.row.id)}
  490. />,
  491. // <GridActionsCellItem
  492. // icon={<InfoIcon />}
  493. // label="debug button"
  494. // sx={{
  495. // color: "error.main",
  496. // }}
  497. // onClick={() => console.log(params.row)}
  498. // />,
  499. ];
  500. },
  501. },
  502. ],
  503. [stockOutLineStatusMap, handleStart, handleDelete],
  504. );
  505. const fetchStockOutLine = useCallback(
  506. async (params: Record<string, any>, selectedRow: GridRowSelectionModel) => {
  507. const _selectedRow = selectedRow as number[];
  508. console.log(params);
  509. console.log(_selectedRow);
  510. // fetch
  511. const res = await fetchStockOutLineClient(_selectedRow[0]);
  512. console.log(res);
  513. // set state
  514. setStockOutLine(res);
  515. },
  516. [],
  517. );
  518. const addRow = useCallback(
  519. (qrcode: LotLineInfo) => {
  520. const newEntry = {
  521. id: Date.now(),
  522. _isNew: true,
  523. itemId: qrcode.itemId,
  524. itemName: qrcode.itemName,
  525. itemNo: qrcode.itemNo,
  526. lotNo: qrcode.lotNo,
  527. inventoryLotLineId: qrcode.inventoryLotLineId,
  528. qty: 0,
  529. pickOrderLineId: selectedRow[0] as number,
  530. status: "draft",
  531. };
  532. setStockOutLine((prev) => [...prev, newEntry]);
  533. setRowModesModel((model) => ({
  534. ...model,
  535. [getRowId(newEntry)]: {
  536. mode: GridRowModes.Edit,
  537. },
  538. }));
  539. },
  540. [getRowId, selectedRow],
  541. );
  542. // need modify this later
  543. const changeRow = useCallback(
  544. (id: number, qrcode: LotLineInfo) => {
  545. console.log(stockOutLine);
  546. console.log(stockOutLine.find((line) => line.id === id));
  547. const rowToSave = {
  548. ...stockOutLine.find((line) => line.id === id),
  549. itemId: qrcode.itemId,
  550. itemName: qrcode.itemName,
  551. itemNo: qrcode.itemNo,
  552. lotNo: qrcode.lotNo,
  553. inventoryLotLineId: qrcode.inventoryLotLineId,
  554. };
  555. console.log(rowToSave);
  556. const newEntries = stockOutLine.map((e) =>
  557. getRowId(e) === id ? rowToSave : e,
  558. );
  559. setStockOutLine(newEntries as StockOutLine[]);
  560. },
  561. [stockOutLine, getRowId],
  562. );
  563. /// handle refetch all data
  564. useEffect(() => {
  565. if (!qcOpen || !approvalOpen) {
  566. triggerRefetch();
  567. getConsoStatus();
  568. fetchPickOrderLine(polCriteriaArgs);
  569. // getConsoStatus()
  570. }
  571. if (selectedRow.length > 0) fetchStockOutLine(solCriteriaArgs, selectedRow);
  572. }, [
  573. qcOpen,
  574. approvalOpen,
  575. solCriteriaArgs,
  576. selectedRow,
  577. triggerRefetch,
  578. polCriteriaArgs,
  579. getConsoStatus,
  580. ]);
  581. const getLotDetail = useCallback(
  582. async (stockInLineId: number): Promise<LotLineInfo> => {
  583. const res = await fetchLotDetail(stockInLineId);
  584. console.log("res");
  585. console.log(res);
  586. return res;
  587. },
  588. [fetchLotDetail],
  589. );
  590. const getQcResult = useCallback(
  591. async (stockOutLineId: number): Promise<QcResult[]> => {
  592. const res = await fetchPickOrderQcResult(stockOutLineId);
  593. console.log("res");
  594. console.log(res);
  595. return res;
  596. },
  597. [fetchPickOrderQcResult],
  598. );
  599. const [isOpenScanner, setOpenScanner] = useState(false);
  600. const onOpenScanner = useCallback(() => {
  601. setOpenScanner((prev) => !prev);
  602. }, []);
  603. const scanner = useQrCodeScannerContext();
  604. useEffect(() => {
  605. if (isOpenScanner && !scanner.isScanning) {
  606. scanner.startScan();
  607. } else if (!isOpenScanner && scanner.isScanning) {
  608. scanner.stopScan();
  609. }
  610. }, [isOpenScanner]);
  611. const homemade_Qrcode = {
  612. // stockInLineId: 156, // eggs
  613. // stockInLineId: 162, // chicken wings
  614. stockInLineId: 168, // sesame
  615. };
  616. useEffect(() => {
  617. if (scanner.values.length > 0) {
  618. console.log(scanner.values[0]);
  619. const data: QrCodeInfo = JSON.parse(scanner.values[0]);
  620. console.log(data);
  621. if (data.stockInLineId) {
  622. setIsUploading(true);
  623. // fetch
  624. getLotDetail(data.stockInLineId).then((qrcode) => {
  625. // add row
  626. if (isChangeLotSolId) {
  627. changeRow(isChangeLotSolId, qrcode);
  628. } else {
  629. addRow(qrcode);
  630. }
  631. });
  632. setIsUploading(false);
  633. }
  634. scanner.resetScan();
  635. }
  636. }, [
  637. isChangeLotSolId,
  638. scanner.values,
  639. selectedRow,
  640. changeRow,
  641. addRow,
  642. getLotDetail,
  643. ]);
  644. const mannuallyAddRow = useCallback(() => {
  645. getLotDetail(homemade_Qrcode.stockInLineId).then((qrcode) => {
  646. addRow(qrcode);
  647. // scanner.resetScan();
  648. });
  649. }, [addRow, homemade_Qrcode]);
  650. const validation = useCallback(
  651. (
  652. newRow: GridRowModel<StockOutLineRow>,
  653. // rowModel: GridRowSelectionModel
  654. ): StockOutLineEntryError | undefined => {
  655. const error: StockOutLineEntryError = {};
  656. const checkQty = currPol?.qty;
  657. console.log(newRow);
  658. if (!newRow.qty || newRow.qty <= 0) {
  659. error["qty"] = t("illegal qty");
  660. }
  661. return Object.keys(error).length > 0 ? error : undefined;
  662. },
  663. [currPol],
  664. );
  665. const processRowUpdate = useCallback(
  666. (
  667. newRow: GridRowModel<StockOutLineRow>,
  668. originalRow: GridRowModel<StockOutLineRow>,
  669. ) => {
  670. const errors = validation(newRow); // change to validation
  671. console.log(newRow);
  672. if (errors) {
  673. throw new ProcessRowUpdateError(
  674. originalRow,
  675. "validation error",
  676. errors,
  677. );
  678. }
  679. const { _isNew, _error, ...updatedRow } = newRow;
  680. const rowToSave = {
  681. ...updatedRow,
  682. } satisfies StockOutLineRow;
  683. console.log(rowToSave);
  684. const newEntries = stockOutLine.map((e) =>
  685. getRowId(e) === getRowId(originalRow) ? rowToSave : e,
  686. );
  687. console.log(newEntries);
  688. setStockOutLine(newEntries as StockOutLine[]);
  689. return rowToSave;
  690. },
  691. [stockOutLine, validation],
  692. );
  693. const onProcessRowUpdateError = useCallback(
  694. (updateError: ProcessRowUpdateError) => {
  695. const errors = updateError.errors;
  696. const oldRow = updateError.row;
  697. apiRef.current.updateRows([{ ...oldRow, _error: errors }]);
  698. },
  699. [apiRef],
  700. );
  701. const handleCompleteOrder = useCallback(async () => {
  702. const res = await completeConsoPickOrder(consoCode);
  703. if (res.message === "completed") {
  704. console.log(res);
  705. // completed
  706. triggerRefetch();
  707. // setIsCompletedOrder(false)
  708. } else {
  709. // not completed
  710. triggerRefetch();
  711. }
  712. }, [consoCode, triggerRefetch, completeConsoPickOrder]);
  713. return (
  714. <>
  715. <Stack spacing={2}>
  716. <Grid container xs={12} justifyContent="start">
  717. <Grid item xs={12}>
  718. <Typography variant="h4" marginInlineEnd={2}>
  719. {consoCode} - {status}
  720. </Typography>
  721. </Grid>
  722. <Grid item xs={8}>
  723. <Button
  724. // onClick={buttonData.onClick}
  725. disabled={isDisableComplete}
  726. color={"info"}
  727. startIcon={<DoneIcon />}
  728. onClick={handleCompleteOrder}
  729. >
  730. {t("Complete Pick Order")}
  731. </Button>
  732. </Grid>
  733. <Grid
  734. item
  735. xs={4}
  736. display="flex"
  737. justifyContent="end"
  738. alignItems="end"
  739. >
  740. {/* <Button
  741. onClick={mannuallyAddRow}
  742. disabled={selectedRow.length === 0}
  743. >
  744. {isOpenScanner ? t("manual scanning") : t("manual scan")}
  745. </Button> */}
  746. <Button
  747. onClick={onOpenScanner}
  748. disabled={isDisableComplete ?? selectedRow.length === 0}
  749. >
  750. {isOpenScanner ? t("binding") : t("bind")}
  751. </Button>
  752. </Grid>
  753. {/* homemade qrcode for testing purpose */}
  754. <Grid
  755. item
  756. xs={12}
  757. style={{ display: "flex", justifyContent: "center" }}
  758. >
  759. <QrCode
  760. content={homemade_Qrcode}
  761. sx={{ width: 200, height: 200 }}
  762. />
  763. </Grid>
  764. </Grid>
  765. <Grid container xs={12} justifyContent="space-between">
  766. {/* <Grid item xs={12} sx={{ height: 400 }}>
  767. <StyledDataGrid rows={pickOrderLine} columns={columns} />
  768. </Grid> */}
  769. <Grid item xs={12} sx={{ height: 400 }}>
  770. {isLoadingModel.pickOrderLineTable && pickOrderLine == undefined ? (
  771. <CircularProgress size={40} />
  772. ) : (
  773. <StyledDataGrid
  774. rows={pickOrderLine}
  775. columns={pickOrderLineColumns}
  776. rowSelectionModel={selectedRow}
  777. onRowSelectionModelChange={(newRowSelectionModel) => {
  778. setSelectedRow(newRowSelectionModel);
  779. if (newRowSelectionModel && newRowSelectionModel.length > 0) {
  780. const pol = pickOrderLine.find(
  781. (item) => item.id === newRowSelectionModel[0],
  782. );
  783. console.log(pol);
  784. setCurrPol(pol);
  785. }
  786. }}
  787. initialState={{
  788. pagination: {
  789. paginationModel: { pageSize: 10, page: 0 },
  790. },
  791. }}
  792. pageSizeOptions={[10, 25, 50, 100]}
  793. onPaginationModelChange={async (model, details) => {
  794. setPolCriteriaArgs({
  795. pageNum: model.page + 1,
  796. pageSize: model.pageSize,
  797. });
  798. }}
  799. rowCount={polTotalCount}
  800. />
  801. )}
  802. </Grid>
  803. <Grid item xs={12} sx={{ height: 400 }}>
  804. {isChangeLotSolId}
  805. <StyledDataGrid
  806. apiRef={apiRef}
  807. rows={stockOutLine}
  808. columns={stockOutLineColumns}
  809. rowModesModel={rowModesModel}
  810. onRowModesModelChange={setRowModesModel}
  811. disableColumnMenu
  812. editMode="row"
  813. processRowUpdate={processRowUpdate}
  814. onProcessRowUpdateError={onProcessRowUpdateError}
  815. isCellEditable={(params) => {
  816. const status = params.row.status.toLowerCase();
  817. return (
  818. stockOutLineStatusMap[status] === 0 ||
  819. stockOutLineStatusMap[status] === 3
  820. );
  821. }}
  822. initialState={{
  823. pagination: {
  824. paginationModel: { pageSize: 10, page: 0 },
  825. },
  826. }}
  827. pageSizeOptions={[10, 25, 50, 100]}
  828. onPaginationModelChange={async (model, details) => {
  829. setSolCriteriaArgs({
  830. pageNum: model.page + 1,
  831. pageSize: model.pageSize,
  832. });
  833. }}
  834. rowCount={solTotalCount}
  835. />
  836. </Grid>
  837. </Grid>
  838. </Stack>
  839. {/* modals */}
  840. {qcOpen && formDefaultValues != undefined && (
  841. <QcForm
  842. qcDefaultValues={formDefaultValues as StockOutLine & PickOrderQcInput}
  843. qc={qc}
  844. disabled={false}
  845. open={qcOpen}
  846. onClose={closeQcModal}
  847. />
  848. )}
  849. {approvalOpen && formDefaultValues != undefined && (
  850. <ApprovalForm
  851. approvalDefaultValues={
  852. formDefaultValues as StockOutLine & PickOrderApprovalInput
  853. }
  854. disabled={false}
  855. open={approvalOpen}
  856. onClose={closeApprovalModal}
  857. />
  858. )}
  859. </>
  860. );
  861. };
  862. export default PickOrderDetail;