FPSMS-frontend
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

411 líneas
13 KiB

  1. "use client";
  2. import {
  3. ModalFormInput,
  4. PurchaseQCInput,
  5. PurchaseQcResult,
  6. StockInInput,
  7. StockInLineEntry,
  8. updateStockInLine,
  9. } from "@/app/api/po/actions";
  10. import { Box, Button, Modal, ModalProps, Stack } from "@mui/material";
  11. import {
  12. Dispatch,
  13. SetStateAction,
  14. useCallback,
  15. useContext,
  16. useEffect,
  17. useMemo,
  18. useState,
  19. } from "react";
  20. import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
  21. import { useTranslation } from "react-i18next";
  22. import QcForm from "./QcForm";
  23. import { QcItemWithChecks } from "@/app/api/qc";
  24. import { Check, CurrencyYuanRounded, TtyTwoTone } from "@mui/icons-material";
  25. import { PurchaseOrderLine, StockInLine } from "@/app/api/po";
  26. import { useSearchParams } from "next/navigation";
  27. import { StockInLineRow } from "./PoInputGrid";
  28. import EscalationForm from "./EscalationForm";
  29. import StockInForm from "./StockInForm";
  30. import PutawayForm from "./PutawayForm";
  31. import {
  32. INPUT_DATE_FORMAT,
  33. stockInLineStatusMap,
  34. } from "@/app/utils/formatUtil";
  35. import dayjs from "dayjs";
  36. import arraySupport from "dayjs/plugin/arraySupport";
  37. import { downloadFile } from "@/app/utils/commonUtil";
  38. import { fetchPoQrcode } from "@/app/api/pdf/actions";
  39. import UploadContext from "../UploadProvider/UploadProvider";
  40. import useUploadContext from "../UploadProvider/useUploadContext";
  41. dayjs.extend(arraySupport);
  42. interface CommonProps extends Omit<ModalProps, "children"> {
  43. // setRows: Dispatch<SetStateAction<PurchaseOrderLine[]>>;
  44. setEntries?: Dispatch<SetStateAction<StockInLineRow[]>>;
  45. setStockInLine?: Dispatch<SetStateAction<StockInLine[]>>;
  46. itemDetail: StockInLine & { qcResult?: PurchaseQcResult[] };
  47. setItemDetail: Dispatch<
  48. SetStateAction<
  49. | (StockInLine & {
  50. warehouseId?: number;
  51. })
  52. | undefined
  53. >
  54. >;
  55. qc?: QcItemWithChecks[];
  56. warehouse?: any[];
  57. type: "qc" | "stockIn" | "escalation" | "putaway";
  58. }
  59. interface QcProps extends CommonProps {
  60. qc: QcItemWithChecks[];
  61. type: "qc";
  62. }
  63. interface StockInProps extends CommonProps {
  64. // naming
  65. type: "stockIn";
  66. }
  67. interface PutawayProps extends CommonProps {
  68. warehouse: any[];
  69. type: "putaway";
  70. }
  71. interface EscalationProps extends CommonProps {
  72. // naming
  73. type: "escalation";
  74. }
  75. type Props = QcProps | StockInProps | PutawayProps | EscalationProps;
  76. const style = {
  77. position: "absolute",
  78. top: "50%",
  79. left: "50%",
  80. transform: "translate(-50%, -50%)",
  81. bgcolor: "background.paper",
  82. pt: 5,
  83. px: 5,
  84. pb: 10,
  85. width: { xs: "80%", sm: "80%", md: "80%" },
  86. };
  87. const PoQcStockInModal: React.FC<Props> = ({
  88. type,
  89. // setRows,
  90. setEntries,
  91. setStockInLine,
  92. open,
  93. onClose,
  94. itemDetail,
  95. setItemDetail,
  96. qc,
  97. warehouse,
  98. }) => {
  99. const { setIsUploading } = useUploadContext();
  100. const [serverError, setServerError] = useState("");
  101. const { t } = useTranslation();
  102. const params = useSearchParams();
  103. const [btnIsLoading, setBtnIsLoading] = useState(false);
  104. console.log(params.get("id"));
  105. console.log(itemDetail);
  106. console.log(itemDetail.qcResult);
  107. const formProps = useForm<ModalFormInput>({
  108. defaultValues: {
  109. ...itemDetail,
  110. // receiptDate: itemDetail.receiptDate || dayjs().add(-1, "month").format(INPUT_DATE_FORMAT),
  111. // warehouseId: itemDetail.defaultWarehouseId || 0
  112. },
  113. });
  114. // console.log(formProps);
  115. const errors = formProps.formState.errors;
  116. const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
  117. (...args) => {
  118. onClose?.(...args);
  119. // reset();
  120. },
  121. [onClose]
  122. );
  123. useEffect(() => {
  124. // setDefaultValues({...itemDetail});
  125. if (!itemDetail) {
  126. console.log(itemDetail);
  127. }
  128. }, [itemDetail]);
  129. // const fix0IndexedDate = useCallback((date: string | number[] | undefined) => {
  130. // if (Array.isArray(date)) {
  131. // console.log(date);
  132. // return dayjs([date[0], date[1] - 1, date[2]]).format("YYYY-MM-DD");
  133. // }
  134. // return date;
  135. // }, []);
  136. const checkStockIn = useCallback(
  137. (data: ModalFormInput): boolean => {
  138. let hasErrors = false;
  139. if (itemDetail.shelfLife && !data.productionDate && !data.expiryDate) {
  140. formProps.setError("productionDate", {
  141. message: "Please provide at least one",
  142. type: "invalid",
  143. });
  144. formProps.setError("expiryDate", {
  145. message: "Please provide at least one",
  146. type: "invalid",
  147. });
  148. hasErrors = true;
  149. }
  150. if (!itemDetail.shelfLife && !data.expiryDate) {
  151. formProps.setError("expiryDate", {
  152. message: "Please provide expiry date",
  153. type: "invalid",
  154. });
  155. hasErrors = true;
  156. }
  157. if (data.expiryDate && data.expiryDate < data.receiptDate!!) {
  158. formProps.setError("expiryDate", {
  159. message: "Expired",
  160. type: "invalid",
  161. });
  162. hasErrors = true;
  163. }
  164. return hasErrors;
  165. },
  166. [itemDetail, formProps]
  167. );
  168. const checkPutaway = useCallback(
  169. (data: ModalFormInput): boolean => {
  170. let hasErrors = false;
  171. console.log(data.warehouseId);
  172. if (!data.warehouseId || data.warehouseId <= 0) {
  173. formProps.setError("warehouseId", {
  174. message: "Please provide warehouseId",
  175. type: "invalid",
  176. });
  177. hasErrors = true;
  178. }
  179. return hasErrors;
  180. },
  181. [itemDetail, formProps]
  182. );
  183. const onSubmit = useCallback<SubmitHandler<ModalFormInput & {}>>(
  184. async (data, event) => {
  185. setBtnIsLoading(true);
  186. setIsUploading(true)
  187. formProps.clearErrors();
  188. let hasErrors = false;
  189. console.log(errors);
  190. console.log(data);
  191. console.log(itemDetail);
  192. // console.log(fix0IndexedDate(data.receiptDate));
  193. try {
  194. // add checking
  195. if (type === "stockIn") {
  196. hasErrors = checkStockIn(data)
  197. console.log(hasErrors)
  198. }
  199. if (type === "putaway") {
  200. hasErrors = checkPutaway(data);
  201. console.log(hasErrors)
  202. }
  203. //////////////////////// modify this mess later //////////////////////
  204. var productionDate = null;
  205. var expiryDate = null;
  206. var receiptDate = null;
  207. var acceptedQty = null;
  208. if (data.productionDate) {
  209. productionDate = dayjs(data.productionDate).format(INPUT_DATE_FORMAT);
  210. }
  211. if (data.expiryDate) {
  212. expiryDate = dayjs(data.expiryDate).format(INPUT_DATE_FORMAT);
  213. }
  214. if (data.receiptDate) {
  215. receiptDate = dayjs(data.receiptDate).format(INPUT_DATE_FORMAT);
  216. }
  217. // if ()
  218. if (data.qcResult) {
  219. acceptedQty =
  220. itemDetail.acceptedQty -
  221. data.qcResult.reduce((acc, curr) => acc + curr.failQty, 0);
  222. }
  223. const args = {
  224. id: itemDetail.id,
  225. purchaseOrderId: parseInt(params.get("id")!!),
  226. purchaseOrderLineId: itemDetail.purchaseOrderLineId,
  227. itemId: itemDetail.itemId,
  228. ...data,
  229. productionDate: productionDate,
  230. expiryDate: expiryDate,
  231. receiptDate: receiptDate,
  232. } as StockInLineEntry & ModalFormInput;
  233. //////////////////////////////////////////////////////////////////////
  234. if (hasErrors) {
  235. console.log(args);
  236. setServerError(t("An error has occurred. Please try again later."));
  237. setBtnIsLoading(false);
  238. setIsUploading(false)
  239. return;
  240. }
  241. console.log(args);
  242. // setBtnIsLoading(false);
  243. // setIsUploading(false)
  244. // return
  245. const res = await updateStockInLine(args);
  246. if (Boolean(res.id)) {
  247. // update entries
  248. const newEntries = res.entity as StockInLine[];
  249. console.log(newEntries);
  250. if (setEntries) {
  251. setEntries((prev) => {
  252. const updatedEntries = [...prev]; // Create a new array
  253. newEntries.forEach((item) => {
  254. const index = updatedEntries.findIndex((p) => p.id === item.id);
  255. if (index !== -1) {
  256. // Update existing item
  257. console.log(item);
  258. updatedEntries[index] = item;
  259. } else {
  260. // Add new item
  261. updatedEntries.push(item);
  262. }
  263. });
  264. return updatedEntries; // Return the new array
  265. });
  266. }
  267. if (setStockInLine) {
  268. setStockInLine((prev) => {
  269. const updatedEntries = [...prev]; // Create a new array
  270. newEntries.forEach((item) => {
  271. const index = updatedEntries.findIndex((p) => p.id === item.id);
  272. if (index !== -1) {
  273. // Update existing item
  274. console.log(item);
  275. updatedEntries[index] = item;
  276. } else {
  277. // Add new item
  278. updatedEntries.push(item);
  279. }
  280. });
  281. return updatedEntries; // Return the new array
  282. });
  283. }
  284. // add loading
  285. setBtnIsLoading(false);
  286. setIsUploading(false)
  287. setItemDetail(undefined);
  288. closeHandler({}, "backdropClick");
  289. }
  290. console.log(res);
  291. // if (res)
  292. } catch (e) {
  293. // server error
  294. setBtnIsLoading(false);
  295. setIsUploading(false)
  296. setServerError(t("An error has occurred. Please try again later."));
  297. console.log(e);
  298. }
  299. },
  300. [t, itemDetail, checkStockIn, checkPutaway]
  301. );
  302. const printQrcode = useCallback(async () => {
  303. setBtnIsLoading(true);
  304. setIsUploading(true)
  305. const postData = { stockInLineIds: [itemDetail.id] };
  306. // const postData = { stockInLineIds: [42,43,44] };
  307. const response = await fetchPoQrcode(postData);
  308. if (response) {
  309. console.log(response);
  310. downloadFile(new Uint8Array(response.blobValue), response.filename!!);
  311. }
  312. setBtnIsLoading(false);
  313. setIsUploading(false)
  314. }, [itemDetail, fetchPoQrcode, downloadFile]);
  315. const renderSubmitButton = useMemo((): boolean => {
  316. if (itemDetail) {
  317. const status = itemDetail.status;
  318. console.log(status);
  319. switch (type) {
  320. case "qc":
  321. return (
  322. stockInLineStatusMap[status] >= 1 &&
  323. stockInLineStatusMap[status] <= 2
  324. );
  325. case "escalation":
  326. return (
  327. stockInLineStatusMap[status] === 1 ||
  328. stockInLineStatusMap[status] >= 3 ||
  329. stockInLineStatusMap[status] <= 5
  330. );
  331. case "stockIn":
  332. return (
  333. stockInLineStatusMap[status] >= 3 &&
  334. stockInLineStatusMap[status] <= 6
  335. );
  336. case "putaway":
  337. return stockInLineStatusMap[status] === 7;
  338. default:
  339. return false; // Handle unexpected type
  340. }
  341. } else return false;
  342. }, [type, itemDetail]);
  343. // useEffect(() => {
  344. // console.log(renderSubmitButton)
  345. // }, [renderSubmitButton])
  346. return (
  347. <>
  348. <FormProvider {...formProps}>
  349. <Modal open={open} onClose={closeHandler}>
  350. <Box
  351. sx={style}
  352. component="form"
  353. onSubmit={formProps.handleSubmit(onSubmit)}
  354. >
  355. {itemDetail !== undefined && type === "qc" && (
  356. <QcForm qc={qc!!} itemDetail={itemDetail} disabled={renderSubmitButton}/>
  357. )}
  358. {itemDetail !== undefined && type === "stockIn" && (
  359. <StockInForm itemDetail={itemDetail} disabled={renderSubmitButton}/>
  360. )}
  361. {itemDetail !== undefined && type === "escalation" && (
  362. <EscalationForm itemDetail={itemDetail} disabled={renderSubmitButton}/>
  363. )}
  364. {itemDetail !== undefined && type === "putaway" && (
  365. <PutawayForm itemDetail={itemDetail} warehouse={warehouse!!} disabled={renderSubmitButton}/>
  366. )}
  367. <Stack direction="row" justifyContent="flex-end" gap={1}>
  368. {renderSubmitButton ? (
  369. <Button
  370. name="submit"
  371. variant="contained"
  372. startIcon={<Check />}
  373. type="submit"
  374. disabled={btnIsLoading}
  375. >
  376. {t("submit")}
  377. </Button>
  378. ) : undefined}
  379. {itemDetail !== undefined && type === "putaway" && (
  380. <Button
  381. name="print"
  382. variant="contained"
  383. // startIcon={<Check />}
  384. onClick={printQrcode}
  385. disabled={btnIsLoading}
  386. >
  387. {t("print")}
  388. </Button>
  389. )}
  390. </Stack>
  391. </Box>
  392. </Modal>
  393. </FormProvider>
  394. </>
  395. );
  396. };
  397. export default PoQcStockInModal;