FPSMS-frontend
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

PoInputGrid.tsx 27 KiB

6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
7ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
6ヶ月前
7ヶ月前
7ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
7ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
7ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
7ヶ月前
4ヶ月前
4ヶ月前
7ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
4ヶ月前
6ヶ月前
6ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
4ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
6ヶ月前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  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;