diff --git a/src/app/api/po/actions.ts b/src/app/api/po/actions.ts index f417fad..73fcb9a 100644 --- a/src/app/api/po/actions.ts +++ b/src/app/api/po/actions.ts @@ -26,9 +26,9 @@ export interface StockInLineEntry { expiryDate?: string } -export interface PurchaseQcCheck { - qcCheckId: number; - qty: number; +export interface PurchaseQcResult { + qcItemId: number; + failQty: number; } export interface StockInInput { status: string @@ -41,15 +41,17 @@ export interface StockInInput { } export interface PurchaseQCInput { status: string + acceptedQty: number sampleRate: number; sampleWeight: number; totalWeight: number; - qcCheck: PurchaseQcCheck[]; + qcResult: PurchaseQcResult[]; } export interface EscalationInput { status: string handler: string - stockInLine: StockInLineEntry[] + acceptedQty: number + rejectedQty: number } export interface PutawayInput { status: string diff --git a/src/app/utils/formatUtil.ts b/src/app/utils/formatUtil.ts index f791121..760885e 100644 --- a/src/app/utils/formatUtil.ts +++ b/src/app/utils/formatUtil.ts @@ -16,14 +16,15 @@ export const integerFormatter = new Intl.NumberFormat("en-HK", { }) -export const stockInLineStatusMap: { [status: string]: {key: string, value: number} } = { - draft: { key: "draft", value: 0 }, - pending: { key: "pending", value: 1 }, - qc: { key: "qc", value: 2 }, - determine1: { key: "determine1", value: 3 }, - determine2: { key: "determine2", value: 4 }, - determine3: { key: "determine3", value: 5 }, - receiving: { key: "receiving", value: 6 }, - received: { key: "received", value: 7 }, - completed: { key: "completed", value: 8 }, +export const stockInLineStatusMap: { [status: string]: number } = { + "draft": 0, + "pending": 1, + "qc": 2, + "determine1": 3, + "determine2": 4, + "determine3": 5, + "receiving": 6, + "received": 7, + "completed": 8, + "rejected": 9, }; \ No newline at end of file diff --git a/src/components/PoDetail/EscalationForm.tsx b/src/components/PoDetail/EscalationForm.tsx index 5162936..93626d6 100644 --- a/src/components/PoDetail/EscalationForm.tsx +++ b/src/components/PoDetail/EscalationForm.tsx @@ -43,8 +43,6 @@ type EntryError = } | undefined; -type PoEscalationRow = TableRow, EntryError>; - const EscalationForm: React.FC = ({ // qc, itemDetail, @@ -64,98 +62,38 @@ const EscalationForm: React.FC = ({ clearErrors, } = useFormContext(); console.log(itemDetail) - const columns = useMemo( - () => [ - // { - // field: "qcCheckId", - // headerName: "qc Check", - // flex: 1, - // editable: true, - // valueFormatter(params) { - // const row = params.id ? params.api.getRow(params.id) : null; - // if (!row) { - // return null; - // } - // const Qc = qc.find((q) => q.id === row.qcCheckId); - // return Qc ? `${Qc.code} - ${Qc.name}` : t("Please select QC"); - // }, - // renderCell(params: GridRenderCellParams) { - // console.log(params.value); - // return {params.formattedValue}; - // }, - // renderEditCell(params: GridRenderEditCellParams) { - // const errorMessage = - // params.row._error?.[params.field as keyof StockInLineEntry]; - // console.log(errorMessage); - // const content = ( - // { - // await params.api.setEditCellValue({ - // id: params.id, - // field: "qcCheckId", - // value: qcCheckId, - // }); - // }} - // /> - // ); - // return errorMessage ? ( - // - // {content} - // - // ) : ( - // content - // ); - // }, - // }, - { - field: "qty", - headerName: "qty", - flex: 1, - editable: true, - type: "number", - renderEditCell(params: GridRenderEditCellParams) { - const errorMessage = - params.row._error?.[params.field as keyof StockInLineEntry]; - const content = ; - return errorMessage ? ( - - {content} - - ) : ( - content - ); - }, - }, - ], - [] - ); - const validationTest = useCallback( - (newRow: GridRowModel): EntryError => { - const error: EntryError = {}; - // const { qcCheckId, qty } = newRow; - // if (!qcCheckId || qcCheckId <= 0) { - // error["qcCheckId"] = "select qc"; - // } - // if (!qty || qty <= 0) { - // error["qty"] = "enter a qty"; - // } - return Object.keys(error).length > 0 ? error : undefined; - }, - [] - ); - + + const [status, determineCount] = useMemo(() => { + switch (itemDetail.status) { + case "pending": + return ["determine1", 1]; + case "determine1": + return ["determine2", 2]; + case "determine2": + return ["determine3", 3]; + default: + return ["receiving", "receive or reject" ]; + } + }, [itemDetail]) + + const acceptedQty = watch("acceptedQty") + const rejectedQty = watch("rejectedQty") + useEffect(() => { console.log("triggered") - // setValue("status", stockInLineStatusMap.determine1.key) + setValue("status", status) }, []) return ( - {t("Qc Detail")} + {t(`Escalation`)}: {determineCount} + + + + + {t(`to be processed`)}: {itemDetail.acceptedQty - acceptedQty - rejectedQty} = ({ spacing={2} sx={{ mt: 0.5 }} > - + {/* = ({ error={Boolean(errors.handler)} helperText={errors.handler?.message} /> + */} + + - + @@ -197,15 +150,6 @@ const EscalationForm: React.FC = ({ spacing={2} sx={{ mt: 0.5 }} > - - - apiRef={apiRef} - checkboxSelection={false} - _formKey={"stockInLine"} - columns={columns} - validateRow={validationTest} - /> - ); diff --git a/src/components/PoDetail/PoInputGrid.tsx b/src/components/PoDetail/PoInputGrid.tsx index e39e8ce..7690db6 100644 --- a/src/components/PoDetail/PoInputGrid.tsx +++ b/src/components/PoDetail/PoInputGrid.tsx @@ -110,12 +110,9 @@ function PoInputGrid({ return total; }); - useEffect(() => { - - }, []) useEffect(() => { const completedList = entries.filter( - (e) => e.status === stockInLineStatusMap.completed.key + (e) => e.status === "completed" ); const processedQty = completedList.reduce( (acc, curr) => acc + (curr.acceptedQty || 0), @@ -176,21 +173,21 @@ function PoInputGrid({ }, [] ); - // const handleEscalation = useCallback( - // (id: GridRowId, params: any) => () => { - // setRowModesModel((prev) => ({ - // ...prev, - // [id]: { mode: GridRowModes.View }, - // })); - // setModalInfo(params.row); - // setTimeout(() => { - // // open qc modal - // console.log("delayed"); - // openEscalationModal(); - // }, 200); - // }, - // [] - // ); + const handleEscalation = useCallback( + (id: GridRowId, params: any) => () => { + setRowModesModel((prev) => ({ + ...prev, + [id]: { mode: GridRowModes.View }, + })); + setModalInfo(params.row); + setTimeout(() => { + // open qc modal + console.log("delayed"); + openEscalationModal(); + }, 200); + }, + [] + ); const handleStockIn = useCallback( (id: GridRowId, params: any) => () => { setRowModesModel((prev) => ({ @@ -281,7 +278,7 @@ function PoInputGrid({ { field: "actions", type: "actions", - headerName: "start | qc | stock in | putaway | delete", + headerName: "start | qc | escalation | stock in | putaway | delete", flex: 1.5, cellClassName: "actions", getActions: (params) => { @@ -295,7 +292,7 @@ function PoInputGrid({ color: "primary.main", marginRight: 2, }} - disabled={!(stockInLineStatusMap[status].value === 0)} + disabled={!(stockInLineStatusMap[status] === 0)} // set _isNew to false after posting // or check status onClick={handleStart(params.row.id, params)} @@ -310,8 +307,9 @@ function PoInputGrid({ marginRight: 2, }} disabled={ - stockInLineStatusMap[status].value <= 0 || - stockInLineStatusMap[status].value >= 5 + // stockInLineStatusMap[status] <= 0 || + // stockInLineStatusMap[status] >= 5 + stockInLineStatusMap[status] != 1 } // set _isNew to false after posting // or check status @@ -319,23 +317,23 @@ function PoInputGrid({ color="inherit" key="edit" />, - // } - // label="escalation" - // sx={{ - // color: "primary.main", - // marginRight: 2, - // }} - // disabled={ - // stockInLineStatusMap[status].value <= 0 || - // stockInLineStatusMap[status].value >= 5 - // } - // // set _isNew to false after posting - // // or check status - // onClick={handleEscalation(params.row.id, params)} - // color="inherit" - // key="edit" - // />, + } + label="escalation" + sx={{ + color: "primary.main", + marginRight: 2, + }} + disabled={ + stockInLineStatusMap[status] <= 0 || + stockInLineStatusMap[status] >= 5 + } + // set _isNew to false after posting + // or check status + onClick={handleEscalation(params.row.id, params)} + color="inherit" + key="edit" + />, } label="stockin" @@ -343,7 +341,7 @@ function PoInputGrid({ color: "primary.main", marginRight: 2, }} - disabled={stockInLineStatusMap[status].value !== 6} + disabled={stockInLineStatusMap[status] !== 6} // set _isNew to false after posting // or check status onClick={handleStockIn(params.row.id, params)} @@ -357,7 +355,7 @@ function PoInputGrid({ color: "primary.main", marginRight: 2, }} - disabled={stockInLineStatusMap[status].value !== 7} + disabled={stockInLineStatusMap[status] !== 7} // set _isNew to false after posting // or check status onClick={handlePutAway(params.row.id, params)} @@ -370,7 +368,7 @@ function PoInputGrid({ sx={{ color: "error.main", }} - disabled={stockInLineStatusMap[status].value !== 0} + disabled={stockInLineStatusMap[status] !== 0} // disabled={Boolean(params.row.status)} onClick={handleDelete(params.row.id)} color="inherit" @@ -510,8 +508,8 @@ function PoInputGrid({ isCellEditable={(params) => { const status = params.row.status.toLowerCase(); return ( - stockInLineStatusMap[status].value >= 0 || - stockInLineStatusMap[status].value <= 1 + stockInLineStatusMap[status] >= 0 || + stockInLineStatusMap[status] <= 1 ); }} getCellClassName={(params: GridCellParams) => { diff --git a/src/components/PoDetail/PoQcStockInModal.tsx b/src/components/PoDetail/PoQcStockInModal.tsx index 54fcaca..9b57454 100644 --- a/src/components/PoDetail/PoQcStockInModal.tsx +++ b/src/components/PoDetail/PoQcStockInModal.tsx @@ -7,10 +7,9 @@ import { FormProvider, SubmitHandler, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import QcForm from "./QcForm"; import { QcItemWithChecks } from "@/app/api/qc"; -import { Check } from "@mui/icons-material"; +import { Check, CurrencyYuanRounded } from "@mui/icons-material"; import { StockInLine } from "@/app/api/po"; import { useSearchParams } from "next/navigation"; -import { stockInLineStatusMap } from "@/app/utils/formatUtil"; import { StockInLineRow } from "./PoInputGrid"; import EscalationForm from "./EscalationForm"; import StockInForm from "./StockInForm"; @@ -86,25 +85,10 @@ const PoQcStockInModal: React.FC = ({ setDefaultValues({}); }, []); - // status to be posted - // const getPostingStatus = useCallback( - // (type: string) => { - // switch (type) { - // case "qc": - // return stockInLineStatusMap.receiving.key; - // case "stockIn": - // return stockInLineStatusMap.received.key; - // case "putaway": - // return stockInLineStatusMap.completed.key; - // default: - // return stockInLineStatusMap.pending.key; - // } - // }, [] - // ) - const onSubmit = useCallback>( async (data, event) => { let hasErrors = false; + console.log("errors"); console.log(errors); console.log(data); console.log(itemDetail); @@ -118,23 +102,28 @@ const PoQcStockInModal: React.FC = ({ if (data.productionDate && data.productionDate.length > 0) { productionDate = data.productionDate } - if (data.acceptedQty) { - acceptedQty = parseInt(data.acceptedQty.toString()) - } else { - acceptedQty = data.sampleRate + if (data.qcResult) { + acceptedQty = itemDetail.acceptedQty - data.qcResult.reduce((acc, curr) => acc + curr.failQty, 0) } + console.log(acceptedQty) + // if (data.acceptedQty) { + // console.log("1") + // acceptedQty = parseInt(data.acceptedQty.toString()) + // } else { + // console.log("2") + // acceptedQty = data.sampleRate + // } const args = { id: itemDetail.id, purchaseOrderId: parseInt(params.get("id")!!), purchaseOrderLineId: itemDetail.purchaseOrderLineId, itemId: itemDetail.itemId, ...data, - acceptedQty: acceptedQty, productionDate: productionDate, } as StockInLineEntry & ModalFormInput; ////////////////////////////////////////////////////////////////////// console.log(args) - return + // return if (hasErrors) { setServerError(t("An error has occurred. Please try again later.")); return false; diff --git a/src/components/PoDetail/PutawayForm.tsx b/src/components/PoDetail/PutawayForm.tsx index 9442d7b..25262da 100644 --- a/src/components/PoDetail/PutawayForm.tsx +++ b/src/components/PoDetail/PutawayForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { PurchaseQcCheck, PutawayInput } from "@/app/api/po/actions"; +import { PurchaseQcResult, PutawayInput } from "@/app/api/po/actions"; import { Autocomplete, Box, @@ -43,11 +43,11 @@ interface Props { } type EntryError = | { - [field in keyof PurchaseQcCheck]?: string; + [field in keyof PurchaseQcResult]?: string; } | undefined; -// type PoQcRow = TableRow, EntryError>; +// type PoQcRow = TableRow, EntryError>; const PutawayForm: React.FC = ({ itemDetail, warehouse }) => { const { t } = useTranslation(); @@ -107,7 +107,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse }) => { ); useEffect(() => { - setValue("status", stockInLineStatusMap.completed.key) + setValue("status", "completed") }, []) return ( @@ -173,7 +173,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse }) => { sx={{ mt: 0.5 }} > {/* - + apiRef={apiRef} checkboxSelection={false} _formKey={"qcCheck"} diff --git a/src/components/PoDetail/QcForm.tsx b/src/components/PoDetail/QcForm.tsx index 6f01eec..3b267fb 100644 --- a/src/components/PoDetail/QcForm.tsx +++ b/src/components/PoDetail/QcForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { PurchaseQcCheck, PurchaseQCInput } from "@/app/api/po/actions"; +import { PurchaseQcResult, PurchaseQCInput } from "@/app/api/po/actions"; import { Box, Card, @@ -35,6 +35,7 @@ import { fetchQcItemCheck } from "@/app/api/qc/actions"; import { QcItemWithChecks } from "@/app/api/qc"; import axios from "@/app/(main)/axios/axiosInstance"; import { NEXT_PUBLIC_API_URL } from "@/config/api"; +import axiosInstance from "@/app/(main)/axios/axiosInstance"; interface Props { itemDetail: StockInLine; @@ -42,11 +43,11 @@ interface Props { } type EntryError = | { - [field in keyof PurchaseQcCheck]?: string; + [field in keyof PurchaseQcResult]?: string; } | undefined; -type PoQcRow = TableRow, EntryError>; +type PoQcRow = TableRow, EntryError>; // fetchQcItemCheck const QcForm: React.FC = ({ qc, itemDetail }) => { const { t } = useTranslation(); @@ -67,6 +68,10 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { // const [qc, setQc] = useState([]) // const fetchQcCheck = useCallback(async () => { + // const authHeader = axiosInstance.defaults.headers['Authorization']; + // if (!authHeader) { + // return; // Exit the function if the token is not set + // } // const params = { // itemId: itemDetail.itemId // } @@ -77,11 +82,12 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { // useEffect(() => { // fetchQcCheck() // }, [fetchQcCheck]) + const [recordQty, setRecordQty] = useState(0); const columns = useMemo( () => [ { - field: "qcCheckId", + field: "qcItemId", headerName: "qc Check", flex: 1, editable: true, @@ -90,7 +96,7 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { if (!row) { return null; } - const Qc = qc.find((q) => q.id === row.qcCheckId); + const Qc = qc.find((q) => q.id === row.qcItemId); return Qc ? `${Qc.code} - ${Qc.name}` : t("Please select QC"); }, renderCell(params: GridRenderCellParams) { @@ -99,18 +105,23 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { }, renderEditCell(params: GridRenderEditCellParams) { const errorMessage = - params.row._error?.[params.field as keyof PurchaseQcCheck]; + params.row._error?.[params.field as keyof PurchaseQcResult]; console.log(errorMessage); const content = ( { + value={params.row.qcItemId} + onQcSelect={async (qcItemId) => { await params.api.setEditCellValue({ id: params.id, - field: "qcCheckId", - value: qcCheckId, + field: "qcItemId", + value: qcItemId, }); + // await params.api.setEditCellValue({ + // id: params.id, + // field: "type", + // value: "determine1", + // }); }} /> ); @@ -124,8 +135,8 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { }, }, { - field: "qty", - headerName: "qty", + field: "failQty", + headerName: "failQty", flex: 1, editable: true, type: "number", @@ -135,7 +146,7 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { // setUnrecordQty((prev) => prev - recordQty) // } const errorMessage = - params.row._error?.[params.field as keyof PurchaseQcCheck]; + params.row._error?.[params.field as keyof PurchaseQcResult]; const content = ; return errorMessage ? ( @@ -152,15 +163,15 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { const validation = useCallback( (newRow: GridRowModel): EntryError => { const error: EntryError = {}; - const { qcCheckId, qty } = newRow; - if (!qcCheckId || qcCheckId <= 0) { - error["qcCheckId"] = "select qc"; + const { qcItemId, failQty } = newRow; + if (!qcItemId || qcItemId <= 0) { + error["qcItemId"] = "select qc"; } - if (!qty || qty <= 0) { - error["qty"] = "enter a qty"; + if (!failQty || failQty <= 0) { + error["failQty"] = "enter a failQty"; } - if (qty && qty > itemDetail.acceptedQty) { - error["qty"] = "qty too big"; + if (failQty && failQty > itemDetail.acceptedQty) { + error["failQty"] = "qty too big"; } return Object.keys(error).length > 0 ? error : undefined; }, @@ -169,7 +180,7 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { useEffect(() => { console.log(itemDetail) - var status = stockInLineStatusMap.receiving.key + var status = "receiving" // switch (itemDetail.status) { // case 'pending': // status = "receiving" @@ -194,15 +205,16 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { > @@ -224,6 +236,7 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { fullWidth {...register("sampleRate", { required: "sampleRate required!", + valueAsNumber: true })} error={Boolean(errors.sampleRate)} helperText={errors.sampleRate?.message} @@ -260,10 +273,10 @@ const QcForm: React.FC = ({ qc, itemDetail }) => { sx={{ mt: 0.5 }} > - + apiRef={apiRef} checkboxSelection={false} - _formKey={"qcCheck"} + _formKey={"qcResult"} columns={columns} validateRow={validation} /> diff --git a/src/components/PoDetail/QcSelect.tsx b/src/components/PoDetail/QcSelect.tsx index 7207021..e365f8a 100644 --- a/src/components/PoDetail/QcSelect.tsx +++ b/src/components/PoDetail/QcSelect.tsx @@ -19,7 +19,7 @@ interface CommonProps { interface SingleAutocompleteProps extends CommonProps { value: number | string | undefined; - onQcSelect: (qcCheckId: number) => void | Promise; + onQcSelect: (qcItemId: number) => void | Promise; // multiple: false; } diff --git a/src/components/PoDetail/StockInForm.tsx b/src/components/PoDetail/StockInForm.tsx index f96ba21..3557e07 100644 --- a/src/components/PoDetail/StockInForm.tsx +++ b/src/components/PoDetail/StockInForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { PurchaseQcCheck, PurchaseQCInput, StockInInput } from "@/app/api/po/actions"; +import { PurchaseQcResult, PurchaseQCInput, StockInInput } from "@/app/api/po/actions"; import { Box, Card, @@ -31,8 +31,7 @@ import QcSelect from "./QcSelect"; import { QcItemWithChecks } from "@/app/api/qc"; import { GridEditInputCell } from "@mui/x-data-grid"; import { StockInLine } from "@/app/api/po"; -import { stockInLineStatusMap } from "@/app/utils/formatUtil"; -// change PurchaseQcCheck to stock in entry props +// change PurchaseQcResult to stock in entry props interface Props { itemDetail: StockInLine; // qc: QcItemWithChecks[]; @@ -43,7 +42,7 @@ type EntryError = } | undefined; -// type PoQcRow = TableRow, EntryError>; +// type PoQcRow = TableRow, EntryError>; const StockInForm: React.FC = ({ // qc, @@ -67,7 +66,7 @@ const StockInForm: React.FC = ({ useEffect(() => { console.log("triggered") - setValue("status", stockInLineStatusMap.received.key) + setValue("status", "received") }, []) return ( @@ -159,7 +158,7 @@ const StockInForm: React.FC = ({ sx={{ mt: 0.5 }} > {/* - + apiRef={apiRef} checkboxSelection={false} _formKey={"qcCheck"}