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

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