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

PoInputGrid.tsx 27 KiB

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