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.
 
 

919 regels
27 KiB

  1. "use client";
  2. import {
  3. FooterPropsOverrides,
  4. GridActionsCellItem,
  5. GridCellParams,
  6. GridRowId,
  7. GridRowIdGetter,
  8. GridRowModel,
  9. GridRowModes,
  10. GridRowModesModel,
  11. GridToolbarContainer,
  12. useGridApiRef,
  13. } from "@mui/x-data-grid";
  14. import {
  15. Dispatch,
  16. MutableRefObject,
  17. SetStateAction,
  18. useCallback,
  19. useEffect,
  20. useMemo,
  21. useState,
  22. } from "react";
  23. import StyledDataGrid from "../StyledDataGrid";
  24. import { GridColDef } from "@mui/x-data-grid";
  25. import { Box, Button, Grid, Typography } from "@mui/material";
  26. import { useTranslation } from "react-i18next";
  27. import { Add } from "@mui/icons-material";
  28. import SaveIcon from "@mui/icons-material/Save";
  29. import DeleteIcon from "@mui/icons-material/Delete";
  30. import CancelIcon from "@mui/icons-material/Cancel";
  31. import FactCheckIcon from "@mui/icons-material/FactCheck";
  32. import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
  33. import { QcItemWithChecks } from "src/app/api/qc";
  34. import PlayArrowIcon from "@mui/icons-material/PlayArrow";
  35. import { PurchaseOrderLine, StockInLine } from "@/app/api/po";
  36. import { createStockInLine, PurchaseQcResult } from "@/app/api/po/actions";
  37. import { useSearchParams } from "next/navigation";
  38. import {
  39. returnWeightUnit,
  40. calculateWeight,
  41. stockInLineStatusMap,
  42. } from "@/app/utils/formatUtil";
  43. // import PoQcStockInModal from "./PoQcStockInModal";
  44. import NotificationImportantIcon from "@mui/icons-material/NotificationImportant";
  45. import { WarehouseResult } from "@/app/api/warehouse";
  46. import LooksOneIcon from "@mui/icons-material/LooksOne";
  47. import LooksTwoIcon from "@mui/icons-material/LooksTwo";
  48. import Looks3Icon from "@mui/icons-material/Looks3";
  49. import axiosInstance from "@/app/(main)/axios/axiosInstance";
  50. // import axios, { AxiosRequestConfig } from "axios";
  51. import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api";
  52. import qs from "qs";
  53. import QrCodeIcon from "@mui/icons-material/QrCode";
  54. import { downloadFile } from "@/app/utils/commonUtil";
  55. import { fetchPoQrcode } from "@/app/api/pdf/actions";
  56. import { fetchQcResult } from "@/app/api/qc/actions";
  57. import PoQcStockInModal from "./PoQcStockInModal";
  58. import DoDisturbIcon from "@mui/icons-material/DoDisturb";
  59. import { useSession } from "next-auth/react";
  60. import PoQcStockInModalVer2 from "./QcStockInModalVer2";
  61. import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil";
  62. interface ResultWithId {
  63. id: number;
  64. }
  65. interface Props {
  66. qc: QcItemWithChecks[];
  67. setRows: Dispatch<SetStateAction<PurchaseOrderLine[]>>;
  68. setStockInLine: Dispatch<SetStateAction<StockInLine[]>>;
  69. setProcessedQty: Dispatch<SetStateAction<number>>;
  70. itemDetail: PurchaseOrderLine;
  71. stockInLine: StockInLine[];
  72. warehouse: WarehouseResult[];
  73. }
  74. export type StockInLineEntryError = {
  75. [field in keyof StockInLine]?: string;
  76. };
  77. export type StockInLineRow = Partial<
  78. StockInLine & {
  79. isActive: boolean | undefined;
  80. _isNew: boolean;
  81. _error: StockInLineEntryError;
  82. } & ResultWithId
  83. >;
  84. class ProcessRowUpdateError extends Error {
  85. public readonly row: StockInLineRow;
  86. public readonly errors: StockInLineEntryError | undefined;
  87. constructor(
  88. row: StockInLineRow,
  89. message?: string,
  90. errors?: StockInLineEntryError,
  91. ) {
  92. super(message);
  93. this.row = row;
  94. this.errors = errors;
  95. Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
  96. }
  97. }
  98. function PoInputGrid({
  99. qc,
  100. setRows,
  101. setStockInLine,
  102. setProcessedQty,
  103. itemDetail,
  104. stockInLine,
  105. warehouse,
  106. }: Props) {
  107. console.log(itemDetail);
  108. const { t } = useTranslation("purchaseOrder");
  109. const apiRef = useGridApiRef();
  110. const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
  111. const getRowId = useCallback<GridRowIdGetter<StockInLineRow>>(
  112. (row) => row.id as number,
  113. [],
  114. );
  115. console.log(stockInLine);
  116. const [entries, setEntries] = useState<StockInLineRow[]>(stockInLine || []);
  117. const [modalInfo, setModalInfo] = useState<
  118. StockInLine & { qcResult?: PurchaseQcResult[] }
  119. >();
  120. const [qcOpen, setQcOpen] = useState(false);
  121. const [escalOpen, setEscalOpen] = useState(false);
  122. const [stockInOpen, setStockInOpen] = useState(false);
  123. const [putAwayOpen, setPutAwayOpen] = useState(false);
  124. const [rejectOpen, setRejectOpen] = useState(false);
  125. const [btnIsLoading, setBtnIsLoading] = useState(false);
  126. const [currQty, setCurrQty] = useState(() => {
  127. const total = entries.reduce(
  128. (acc, curr) => acc + (curr.acceptedQty || 0),
  129. 0,
  130. );
  131. return total;
  132. });
  133. const { data: session } = useSession();
  134. useEffect(() => {
  135. const completedList = entries.filter(
  136. (e) => stockInLineStatusMap[e.status!] >= 8,
  137. );
  138. const processedQty = completedList.reduce(
  139. (acc, curr) => acc + (curr.acceptedQty || 0),
  140. 0,
  141. );
  142. setProcessedQty(processedQty);
  143. }, [entries, setProcessedQty]);
  144. const handleDelete = useCallback(
  145. (id: GridRowId) => () => {
  146. setEntries((es) => es.filter((e) => getRowId(e) !== id));
  147. },
  148. [getRowId],
  149. );
  150. const closeQcModal = useCallback(() => {
  151. setQcOpen(false);
  152. }, []);
  153. const openQcModal = useCallback(() => {
  154. setQcOpen(true);
  155. }, []);
  156. const closeStockInModal = useCallback(() => {
  157. setStockInOpen(false);
  158. }, []);
  159. const openStockInModal = useCallback(() => {
  160. setStockInOpen(true);
  161. }, []);
  162. const closePutAwayModal = useCallback(() => {
  163. setPutAwayOpen(false);
  164. }, []);
  165. const openPutAwayModal = useCallback(() => {
  166. setPutAwayOpen(true);
  167. }, []);
  168. const closeEscalationModal = useCallback(() => {
  169. setEscalOpen(false);
  170. }, []);
  171. const openEscalationModal = useCallback(() => {
  172. setEscalOpen(true);
  173. }, []);
  174. const closeRejectModal = useCallback(() => {
  175. setRejectOpen(false);
  176. }, []);
  177. const openRejectModal = useCallback(() => {
  178. setRejectOpen(true);
  179. }, []);
  180. const handleStart = useCallback(
  181. (id: GridRowId, params: any) => () => {
  182. setBtnIsLoading(true);
  183. setRowModesModel((prev) => ({
  184. ...prev,
  185. [id]: { mode: GridRowModes.View },
  186. }));
  187. setTimeout(async () => {
  188. // post stock in line
  189. const oldId = params.row.id;
  190. const postData = {
  191. itemId: params.row.itemId,
  192. itemNo: params.row.itemNo,
  193. itemName: params.row.itemName,
  194. purchaseOrderId: params.row.purchaseOrderId,
  195. purchaseOrderLineId: params.row.purchaseOrderLineId,
  196. acceptedQty: params.row.acceptedQty,
  197. };
  198. const res = await createStockInLine(postData);
  199. console.log(res);
  200. setEntries((prev) =>
  201. prev.map((p) => (p.id === oldId ? (res.entity as StockInLine) : p)),
  202. );
  203. setStockInLine(
  204. (prev) =>
  205. prev.map((p) =>
  206. p.id === oldId ? (res.entity as StockInLine) : p,
  207. ) as StockInLine[],
  208. );
  209. setBtnIsLoading(false);
  210. // do post directly to test
  211. // openStartModal();
  212. }, 200);
  213. },
  214. [setStockInLine],
  215. );
  216. const fetchQcDefaultValue = useCallback(async (stockInLineId: GridRowId) => {
  217. return await fetchQcResult(stockInLineId as number);
  218. }, []);
  219. const handleQC = useCallback(
  220. (id: GridRowId, params: any) => async () => {
  221. setBtnIsLoading(true);
  222. setRowModesModel((prev) => ({
  223. ...prev,
  224. [id]: { mode: GridRowModes.View },
  225. }));
  226. const qcResult = await fetchQcDefaultValue(id);
  227. console.log(params.row);
  228. console.log(qcResult);
  229. setModalInfo({
  230. ...params.row,
  231. qcResult: qcResult,
  232. });
  233. // set default values
  234. setTimeout(() => {
  235. // open qc modal
  236. console.log("delayed");
  237. openQcModal();
  238. setBtnIsLoading(false);
  239. }, 200);
  240. },
  241. [fetchQcDefaultValue, openQcModal],
  242. );
  243. const [newOpen, setNewOpen] = useState(false);
  244. const closeNewModal = useCallback(() => {
  245. setNewOpen(false);
  246. }, []);
  247. const openNewModal = useCallback(() => {
  248. setNewOpen(true);
  249. }, []);
  250. const handleNewQC = useCallback(
  251. (id: GridRowId, params: any) => async () => {
  252. setBtnIsLoading(true);
  253. setRowModesModel((prev) => ({
  254. ...prev,
  255. [id]: { mode: GridRowModes.View },
  256. }));
  257. const qcResult = await fetchQcDefaultValue(id);
  258. console.log(params.row);
  259. console.log(qcResult);
  260. setModalInfo({
  261. ...params.row,
  262. qcResult: qcResult,
  263. });
  264. // set default values
  265. setTimeout(() => {
  266. // open qc modal
  267. console.log("delayed");
  268. openNewModal();
  269. setBtnIsLoading(false);
  270. }, 200);
  271. },
  272. [fetchQcDefaultValue, openNewModal],
  273. );
  274. const handleEscalation = useCallback(
  275. (id: GridRowId, params: any) => () => {
  276. // setBtnIsLoading(true);
  277. setRowModesModel((prev) => ({
  278. ...prev,
  279. [id]: { mode: GridRowModes.View },
  280. }));
  281. setModalInfo(params.row);
  282. setTimeout(() => {
  283. // open qc modal
  284. console.log("delayed");
  285. openEscalationModal();
  286. // setBtnIsLoading(false);
  287. }, 200);
  288. },
  289. [openEscalationModal],
  290. );
  291. const handleReject = useCallback(
  292. (id: GridRowId, params: any) => () => {
  293. setRowModesModel((prev) => ({
  294. ...prev,
  295. [id]: { mode: GridRowModes.View },
  296. }));
  297. setModalInfo(params.row);
  298. setTimeout(() => {
  299. // open stock in modal
  300. // openPutAwayModal();
  301. // return the record with its status as pending
  302. // update layout
  303. console.log("delayed");
  304. openRejectModal();
  305. // printQrcode(params.row);
  306. }, 200);
  307. },
  308. [openRejectModal],
  309. );
  310. const handleStockIn = useCallback(
  311. (id: GridRowId, params: any) => () => {
  312. // setBtnIsLoading(true);
  313. setRowModesModel((prev) => ({
  314. ...prev,
  315. [id]: { mode: GridRowModes.View },
  316. }));
  317. setModalInfo(params.row);
  318. setTimeout(() => {
  319. // open stock in modal
  320. openStockInModal();
  321. // return the record with its status as pending
  322. // update layout
  323. console.log("delayed");
  324. // setBtnIsLoading(false);
  325. }, 200);
  326. },
  327. [openStockInModal],
  328. );
  329. const handlePutAway = useCallback(
  330. (id: GridRowId, params: any) => () => {
  331. // setBtnIsLoading(true);
  332. setRowModesModel((prev) => ({
  333. ...prev,
  334. [id]: { mode: GridRowModes.View },
  335. }));
  336. setModalInfo(params.row);
  337. setTimeout(() => {
  338. // open stock in modal
  339. openPutAwayModal();
  340. // return the record with its status as pending
  341. // update layout
  342. console.log("delayed");
  343. // setBtnIsLoading(false);
  344. }, 200);
  345. },
  346. [openPutAwayModal],
  347. );
  348. const printQrcode = useCallback(
  349. async (row: any) => {
  350. setBtnIsLoading(true);
  351. console.log(row.id);
  352. const postData = { stockInLineIds: [row.id] };
  353. // const postData = { stockInLineIds: [42,43,44] };
  354. const response = await fetchPoQrcode(postData);
  355. if (response) {
  356. console.log(response);
  357. downloadFile(new Uint8Array(response.blobValue), response.filename!);
  358. }
  359. setBtnIsLoading(false);
  360. },
  361. [],
  362. );
  363. // const handleQrCode = useCallback(
  364. // (id: GridRowId, params: any) => () => {
  365. // setRowModesModel((prev) => ({
  366. // ...prev,
  367. // [id]: { mode: GridRowModes.View },
  368. // }));
  369. // setModalInfo(params.row);
  370. // setTimeout(() => {
  371. // // open stock in modal
  372. // // openPutAwayModal();
  373. // // return the record with its status as pending
  374. // // update layout
  375. // console.log("delayed");
  376. // printQrcode(params.row);
  377. // }, 200);
  378. // },
  379. // [printQrcode],
  380. // );
  381. const columns = useMemo<GridColDef[]>(
  382. () => [
  383. // {
  384. // field: "itemNo",
  385. // headerName: t("itemNo"),
  386. // width: 100,
  387. // // flex: 0.4,
  388. // },
  389. {
  390. field: "dnNo",
  391. headerName: t("dnNo"),
  392. width: 125,
  393. renderCell: () => {
  394. return <>DN0000001</>
  395. }
  396. // flex: 0.4,
  397. },
  398. {
  399. field: "dnDate",
  400. headerName: t("dnDate"),
  401. width: 125,
  402. renderCell: () => {
  403. return <>07/08/2025</>
  404. }
  405. // flex: 0.4,
  406. },
  407. // {
  408. // field: "itemName",
  409. // headerName: t("itemName"),
  410. // width: 100,
  411. // // flex: 0.6,
  412. // },
  413. {
  414. field: "acceptedQty",
  415. headerName: t("acceptedQty"),
  416. // flex: 0.5,
  417. width: 125,
  418. type: "number",
  419. // editable: true,
  420. // replace with tooltip + content
  421. renderCell: (params) => {
  422. return integerFormatter.format(params.value)
  423. }
  424. },
  425. {
  426. field: "uom",
  427. headerName: t("uom"),
  428. width: 120,
  429. // flex: 0.5,
  430. renderCell: (params) => {
  431. return params.row.uom.code;
  432. },
  433. },
  434. {
  435. field: "weight",
  436. headerName: t("weight"),
  437. width: 120,
  438. // flex: 0.5,
  439. renderCell: (params) => {
  440. const weight = calculateWeight(
  441. params.row.acceptedQty,
  442. params.row.uom,
  443. );
  444. const weightUnit = returnWeightUnit(params.row.uom);
  445. return `${decimalFormatter.format(weight)} ${weightUnit}`;
  446. },
  447. },
  448. {
  449. field: "status",
  450. headerName: t("status"),
  451. width: 70,
  452. // flex: 0.5,
  453. renderCell: (params) => {
  454. return t(`${params.row.status}`);
  455. },
  456. },
  457. {
  458. field: "actions",
  459. type: "actions",
  460. // headerName: `${t("start")} | ${t("qc")} | ${t("escalation")} | ${t(
  461. // "stock in",
  462. // )} | ${t("putaway")} | ${t("delete")}`,
  463. headerName: "動作",
  464. // headerName: "start | qc | escalation | stock in | putaway | delete",
  465. width: 300,
  466. // flex: 2,
  467. cellClassName: "actions",
  468. getActions: (params) => {
  469. // console.log(params.row.status);
  470. const status = params.row.status.toLowerCase();
  471. // console.log(stockInLineStatusMap[status]);
  472. // console.log(session?.user?.abilities?.includes("APPROVAL"));
  473. return [
  474. <GridActionsCellItem
  475. icon={<Button variant="contained">{t("qc processing")}</Button>}
  476. label="start"
  477. sx={{
  478. color: "primary.main",
  479. // marginRight: 1,
  480. }}
  481. // disabled={!(stockInLineStatusMap[status] === 0)}
  482. // set _isNew to false after posting
  483. // or check status
  484. onClick={handleNewQC(params.row.id, params)}
  485. color="inherit"
  486. key="edit"
  487. />,
  488. <GridActionsCellItem
  489. icon={<Button variant="contained">{t("putawayBtn")}</Button>}
  490. label="start"
  491. sx={{
  492. color: "primary.main",
  493. // marginRight: 1,
  494. }}
  495. // disabled={!(stockInLineStatusMap[status] === 0)}
  496. // set _isNew to false after posting
  497. // or check status
  498. onClick={handleStart(params.row.id, params)}
  499. color="inherit"
  500. key="edit"
  501. />,
  502. // <GridActionsCellItem
  503. // icon={<Button variant="contained">{t("qc processing")}</Button>}
  504. // label="start"
  505. // sx={{
  506. // color: "primary.main",
  507. // // marginRight: 1,
  508. // }}
  509. // disabled={!(stockInLineStatusMap[status] === 0)}
  510. // // set _isNew to false after posting
  511. // // or check status
  512. // onClick={handleStart(params.row.id, params)}
  513. // color="inherit"
  514. // key="edit"
  515. // />,
  516. // <GridActionsCellItem
  517. // icon={<FactCheckIcon />}
  518. // label="qc"
  519. // sx={{
  520. // color: "primary.main",
  521. // // marginRight: 1,
  522. // }}
  523. // disabled={
  524. // // stockInLineStatusMap[status] === 9 ||
  525. // stockInLineStatusMap[status] < 1
  526. // }
  527. // // set _isNew to false after posting
  528. // // or check status
  529. // onClick={handleQC(params.row.id, params)}
  530. // color="inherit"
  531. // key="edit"
  532. // />,
  533. // <GridActionsCellItem
  534. // icon={<NotificationImportantIcon />}
  535. // label="escalation"
  536. // sx={{
  537. // color: "primary.main",
  538. // // marginRight: 1,
  539. // }}
  540. // disabled={
  541. // stockInLineStatusMap[status] === 9 ||
  542. // stockInLineStatusMap[status] <= 0 ||
  543. // stockInLineStatusMap[status] >= 5
  544. // }
  545. // // set _isNew to false after posting
  546. // // or check status
  547. // onClick={handleEscalation(params.row.id, params)}
  548. // color="inherit"
  549. // key="edit"
  550. // />,
  551. // <GridActionsCellItem
  552. // icon={<ShoppingCartIcon />}
  553. // label="stockin"
  554. // sx={{
  555. // color: "primary.main",
  556. // // marginRight: 1,
  557. // }}
  558. // disabled={
  559. // stockInLineStatusMap[status] === 9 ||
  560. // stockInLineStatusMap[status] <= 2 ||
  561. // stockInLineStatusMap[status] >= 7 ||
  562. // (stockInLineStatusMap[status] >= 3 &&
  563. // stockInLineStatusMap[status] <= 5 &&
  564. // !session?.user?.abilities?.includes("APPROVAL"))
  565. // }
  566. // // set _isNew to false after posting
  567. // // or check status
  568. // onClick={handleStockIn(params.row.id, params)}
  569. // color="inherit"
  570. // key="edit"
  571. // />,
  572. // <GridActionsCellItem
  573. // icon={<ShoppingCartIcon />}
  574. // label="putaway"
  575. // sx={{
  576. // color: "primary.main",
  577. // // marginRight: 1,
  578. // }}
  579. // disabled={
  580. // stockInLineStatusMap[status] === 9 ||
  581. // stockInLineStatusMap[status] < 7
  582. // }
  583. // // set _isNew to false after posting
  584. // // or check status
  585. // onClick={handlePutAway(params.row.id, params)}
  586. // color="inherit"
  587. // key="edit"
  588. // />,
  589. // // <GridActionsCellItem
  590. // // icon={<QrCodeIcon />}
  591. // // label="putaway"
  592. // // sx={{
  593. // // color: "primary.main",
  594. // // // marginRight: 1,
  595. // // }}
  596. // // disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] !== 8}
  597. // // // set _isNew to false after posting
  598. // // // or check status
  599. // // onClick={handleQrCode(params.row.id, params)}
  600. // // color="inherit"
  601. // // key="edit"
  602. // // />,
  603. // <GridActionsCellItem
  604. // icon={
  605. // stockInLineStatusMap[status] >= 1 ? (
  606. // <DoDisturbIcon />
  607. // ) : (
  608. // <DeleteIcon />
  609. // )
  610. // }
  611. // label="Delete"
  612. // sx={{
  613. // color: "error.main",
  614. // }}
  615. // disabled={
  616. // stockInLineStatusMap[status] >= 7 &&
  617. // stockInLineStatusMap[status] <= 9
  618. // }
  619. // onClick={
  620. // stockInLineStatusMap[status] === 0
  621. // ? handleDelete(params.row.id)
  622. // : handleReject(params.row.id, params)
  623. // }
  624. // color="inherit"
  625. // key="edit"
  626. // />,
  627. ];
  628. },
  629. },
  630. ],
  631. [t, handleStart, handleQC, handleEscalation, session?.user?.abilities, handleStockIn, handlePutAway, handleDelete, handleReject],
  632. );
  633. const addRow = useCallback(() => {
  634. console.log(itemDetail);
  635. const newEntry = {
  636. id: Date.now(),
  637. _isNew: true,
  638. itemId: itemDetail.itemId,
  639. purchaseOrderId: itemDetail.purchaseOrderId,
  640. purchaseOrderLineId: itemDetail.id,
  641. itemNo: itemDetail.itemNo,
  642. itemName: itemDetail.itemName,
  643. acceptedQty: itemDetail.qty - currQty, // this bug
  644. uom: itemDetail.uom,
  645. status: "draft",
  646. };
  647. setEntries((e) => [...e, newEntry]);
  648. setRowModesModel((model) => ({
  649. ...model,
  650. [getRowId(newEntry)]: {
  651. mode: GridRowModes.Edit,
  652. // fieldToFocus: "projectId",
  653. },
  654. }));
  655. }, [currQty, getRowId, itemDetail]);
  656. const validation = useCallback(
  657. (
  658. newRow: GridRowModel<StockInLineRow>,
  659. // rowModel: GridRowSelectionModel
  660. ): StockInLineEntryError | undefined => {
  661. const error: StockInLineEntryError = {};
  662. console.log(newRow);
  663. console.log(currQty);
  664. if (newRow.acceptedQty && newRow.acceptedQty > itemDetail.qty) {
  665. error["acceptedQty"] = t("qty cannot be greater than remaining qty");
  666. }
  667. return Object.keys(error).length > 0 ? error : undefined;
  668. },
  669. [currQty, itemDetail.qty, t],
  670. );
  671. const processRowUpdate = useCallback(
  672. (
  673. newRow: GridRowModel<StockInLineRow>,
  674. originalRow: GridRowModel<StockInLineRow>,
  675. ) => {
  676. const errors = validation(newRow); // change to validation
  677. if (errors) {
  678. throw new ProcessRowUpdateError(
  679. originalRow,
  680. "validation error",
  681. errors,
  682. );
  683. }
  684. const { _isNew, _error, ...updatedRow } = newRow;
  685. const rowToSave = {
  686. ...updatedRow,
  687. } satisfies StockInLineRow;
  688. const newEntries = entries.map((e) =>
  689. getRowId(e) === getRowId(originalRow) ? rowToSave : e,
  690. );
  691. setStockInLine(newEntries as StockInLine[]);
  692. console.log("triggered");
  693. setEntries(newEntries);
  694. //update remaining qty
  695. const total = newEntries.reduce(
  696. (acc, curr) => acc + (curr.acceptedQty || 0),
  697. 0,
  698. );
  699. setCurrQty(total);
  700. return rowToSave;
  701. },
  702. [validation, entries, setStockInLine, getRowId],
  703. );
  704. const onProcessRowUpdateError = useCallback(
  705. (updateError: ProcessRowUpdateError) => {
  706. const errors = updateError.errors;
  707. const oldRow = updateError.row;
  708. apiRef.current.updateRows([{ ...oldRow, _error: errors }]);
  709. },
  710. [apiRef],
  711. );
  712. const footer = (
  713. <>
  714. {/* <Box display="flex" gap={2} alignItems="center">
  715. <Button
  716. disableRipple
  717. variant="outlined"
  718. startIcon={<Add />}
  719. disabled={itemDetail.qty - currQty <= 0}
  720. onClick={addRow}
  721. size="small"
  722. >
  723. {t("Record pol")}
  724. </Button>
  725. </Box> */}
  726. </>
  727. );
  728. return (
  729. <>
  730. <StyledDataGrid
  731. getRowId={getRowId}
  732. apiRef={apiRef}
  733. autoHeight
  734. sx={{
  735. "--DataGrid-overlayHeight": "100px",
  736. ".MuiDataGrid-row .MuiDataGrid-cell.hasError": {
  737. border: "1px solid",
  738. borderColor: "error.main",
  739. },
  740. ".MuiDataGrid-row .MuiDataGrid-cell.hasWarning": {
  741. border: "1px solid",
  742. borderColor: "warning.main",
  743. },
  744. }}
  745. disableColumnMenu
  746. editMode="row"
  747. rows={entries}
  748. rowModesModel={rowModesModel}
  749. onRowModesModelChange={setRowModesModel}
  750. processRowUpdate={processRowUpdate}
  751. onProcessRowUpdateError={onProcessRowUpdateError}
  752. columns={columns}
  753. isCellEditable={(params) => {
  754. const status = params.row.status.toLowerCase();
  755. return (
  756. stockInLineStatusMap[status] >= 0 ||
  757. stockInLineStatusMap[status] <= 1
  758. );
  759. }}
  760. getCellClassName={(params: GridCellParams<StockInLineRow>) => {
  761. let classname = "";
  762. if (params.row._error) {
  763. classname = "hasError";
  764. }
  765. return classname;
  766. }}
  767. slots={{
  768. footer: FooterToolbar,
  769. noRowsOverlay: NoRowsOverlay,
  770. }}
  771. slotProps={{
  772. footer: { child: footer },
  773. }}
  774. />
  775. {modalInfo !== undefined && (
  776. <>
  777. <PoQcStockInModalVer2
  778. // setRows={setRows}
  779. setEntries={setEntries}
  780. setStockInLine={setStockInLine}
  781. setItemDetail={setModalInfo}
  782. qc={qc}
  783. warehouse={warehouse}
  784. open={newOpen}
  785. onClose={closeNewModal}
  786. itemDetail={modalInfo}
  787. />
  788. </>
  789. )
  790. }
  791. {modalInfo !== undefined && (
  792. <>
  793. <PoQcStockInModal
  794. type={"qc"}
  795. // setRows={setRows}
  796. setEntries={setEntries}
  797. setStockInLine={setStockInLine}
  798. setItemDetail={setModalInfo}
  799. qc={qc}
  800. open={qcOpen}
  801. onClose={closeQcModal}
  802. itemDetail={modalInfo}
  803. />
  804. </>
  805. )}
  806. {modalInfo !== undefined && (
  807. <>
  808. <PoQcStockInModal
  809. type={"escalation"}
  810. // setRows={setRows}
  811. setEntries={setEntries}
  812. setStockInLine={setStockInLine}
  813. setItemDetail={setModalInfo}
  814. // qc={qc}
  815. open={escalOpen}
  816. onClose={closeEscalationModal}
  817. itemDetail={modalInfo}
  818. />
  819. </>
  820. )}
  821. {modalInfo !== undefined && (
  822. <>
  823. <PoQcStockInModal
  824. type={"reject"}
  825. // setRows={setRows}
  826. setEntries={setEntries}
  827. setStockInLine={setStockInLine}
  828. setItemDetail={setModalInfo}
  829. // qc={qc}
  830. open={rejectOpen}
  831. onClose={closeRejectModal}
  832. itemDetail={modalInfo}
  833. />
  834. </>
  835. )}
  836. {modalInfo !== undefined && (
  837. <>
  838. <PoQcStockInModal
  839. type={"stockIn"}
  840. // setRows={setRows}
  841. setEntries={setEntries}
  842. setStockInLine={setStockInLine}
  843. // qc={qc}
  844. setItemDetail={setModalInfo}
  845. open={stockInOpen}
  846. onClose={closeStockInModal}
  847. itemDetail={modalInfo}
  848. />
  849. </>
  850. )}
  851. {modalInfo !== undefined && (
  852. <>
  853. <PoQcStockInModal
  854. type={"putaway"}
  855. // setRows={setRows}
  856. setEntries={setEntries}
  857. setStockInLine={setStockInLine}
  858. setItemDetail={setModalInfo}
  859. open={putAwayOpen}
  860. warehouse={warehouse}
  861. onClose={closePutAwayModal}
  862. itemDetail={modalInfo}
  863. />
  864. </>
  865. )}
  866. </>
  867. );
  868. }
  869. const NoRowsOverlay: React.FC = () => {
  870. const { t } = useTranslation("home");
  871. return (
  872. <Box
  873. display="flex"
  874. justifyContent="center"
  875. alignItems="center"
  876. height="100%"
  877. >
  878. <Typography variant="caption">{t("Add some entries!")}</Typography>
  879. </Box>
  880. );
  881. };
  882. const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => {
  883. return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>;
  884. };
  885. export default PoInputGrid;