@@ -31,6 +31,7 @@ export interface PurchaseQcCheck { | |||||
qty: number; | qty: number; | ||||
} | } | ||||
export interface StockInInput { | export interface StockInInput { | ||||
status: string | |||||
productLotNo?: string, | productLotNo?: string, | ||||
receiptDate: string | receiptDate: string | ||||
acceptedQty: number | acceptedQty: number | ||||
@@ -39,18 +40,23 @@ export interface StockInInput { | |||||
expiryDate: string | expiryDate: string | ||||
} | } | ||||
export interface PurchaseQCInput { | export interface PurchaseQCInput { | ||||
status: string | |||||
sampleRate: number; | sampleRate: number; | ||||
sampleWeight: number; | sampleWeight: number; | ||||
totalWeight: number; | totalWeight: number; | ||||
qcCheck: PurchaseQcCheck[]; | qcCheck: PurchaseQcCheck[]; | ||||
} | } | ||||
export interface EscalationInput { | export interface EscalationInput { | ||||
status: string | |||||
handler: string | handler: string | ||||
stockInLine: StockInLineEntry[] | stockInLine: StockInLineEntry[] | ||||
} | } | ||||
export interface PutawayInput { | export interface PutawayInput { | ||||
handler: string | |||||
stockInLine: StockInLineEntry[] | |||||
status: string | |||||
acceptedQty: number | |||||
warehouseId: number | |||||
// handler: string | |||||
// stockInLine: StockInLineEntry[] | |||||
} | } | ||||
export type ModalFormInput = Partial<PurchaseQCInput & StockInInput & EscalationInput & PutawayInput> | export type ModalFormInput = Partial<PurchaseQCInput & StockInInput & EscalationInput & PutawayInput> | ||||
@@ -20,6 +20,7 @@ export interface PurchaseOrderLine { | |||||
itemNo: string | itemNo: string | ||||
itemName: string | itemName: string | ||||
qty: number | qty: number | ||||
processed: number | |||||
uom?: string | uom?: string | ||||
price: number | price: number | ||||
status: string | status: string | ||||
@@ -0,0 +1,15 @@ | |||||
"use server"; | |||||
import { BASE_API_URL } from "@/config/api"; | |||||
import { revalidateTag } from "next/cache"; | |||||
import { cache } from "react"; | |||||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
import { QcItemWithChecks } from "."; | |||||
export const fetchQcItemCheck = cache(async (itemId?: number) => { | |||||
var url = `${BASE_API_URL}/qcCheck` | |||||
if (itemId) url +=`/${itemId}` | |||||
return serverFetchJson<QcItemWithChecks[]>(url, { | |||||
next: { tags: ["qc"] }, | |||||
}); | |||||
}); | |||||
@@ -1,12 +1,30 @@ | |||||
import { cache } from "react"; | import { cache } from "react"; | ||||
import "server-only"; | import "server-only"; | ||||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
import { BASE_API_URL } from "@/config/api"; | |||||
export interface QcItemWithChecks { | export interface QcItemWithChecks { | ||||
id: number; | id: number; | ||||
code: string; | code: string; | ||||
name: string; | name: string; | ||||
itemId: number; | itemId: number; | ||||
lowerLimit: number; | |||||
upperLimit: number; | |||||
description: string; | |||||
lowerLimit: number | undefined; | |||||
upperLimit: number | undefined; | |||||
description: string | undefined; | |||||
} | } | ||||
export const fetchQcItemCheckList = cache(async () => { | |||||
return serverFetchJson<QcItemWithChecks[]>(`${BASE_API_URL}/qc/list`, { | |||||
next: { tags: ["qc"] }, | |||||
}); | |||||
}); | |||||
export const fetchQcItemCheck = cache(async (itemId?: number) => { | |||||
var url = `${BASE_API_URL}/qcCheck` | |||||
if (itemId) url +=`/${itemId}` | |||||
return serverFetchJson<QcItemWithChecks[]>(url, { | |||||
next: { tags: ["qc"] }, | |||||
}); | |||||
}); |
@@ -1,7 +1,7 @@ | |||||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
import { BASE_API_URL } from "@/config/api"; | |||||
import { cache } from "react"; | import { cache } from "react"; | ||||
import "server-only"; | import "server-only"; | ||||
import { serverFetchJson } from "src/app/utils/fetchUtil"; | |||||
import { BASE_API_URL } from "src/config/api"; | |||||
export interface TaskGroup { | export interface TaskGroup { | ||||
id: number; | id: number; | ||||
@@ -0,0 +1,17 @@ | |||||
import { cache } from "react"; | |||||
import "server-only"; | |||||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
import { BASE_API_URL } from "@/config/api"; | |||||
export interface WarehouseResult { | |||||
id: number | |||||
code: string | |||||
name: string | |||||
description: string | |||||
} | |||||
export const fetchWarehouseList = cache(async () => { | |||||
return serverFetchJson<WarehouseResult[]>(`${BASE_API_URL}/warehouse`, { | |||||
next: { tags: ["warehouse"] }, | |||||
}); | |||||
}); |
@@ -14,7 +14,7 @@ import { | |||||
import { useFormContext } from "react-hook-form"; | import { useFormContext } from "react-hook-form"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import StyledDataGrid from "../StyledDataGrid"; | import StyledDataGrid from "../StyledDataGrid"; | ||||
import { useCallback, useMemo } from "react"; | |||||
import { useCallback, useEffect, useMemo } from "react"; | |||||
import { | import { | ||||
GridColDef, | GridColDef, | ||||
GridRowIdGetter, | GridRowIdGetter, | ||||
@@ -31,6 +31,7 @@ import QcSelect from "./QcSelect"; | |||||
import { QcItemWithChecks } from "@/app/api/qc"; | import { QcItemWithChecks } from "@/app/api/qc"; | ||||
import { GridEditInputCell } from "@mui/x-data-grid"; | import { GridEditInputCell } from "@mui/x-data-grid"; | ||||
import { StockInLine } from "@/app/api/po"; | import { StockInLine } from "@/app/api/po"; | ||||
import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | |||||
interface Props { | interface Props { | ||||
itemDetail: StockInLine; | itemDetail: StockInLine; | ||||
@@ -144,6 +145,12 @@ const EscalationForm: React.FC<Props> = ({ | |||||
}, | }, | ||||
[] | [] | ||||
); | ); | ||||
useEffect(() => { | |||||
console.log("triggered") | |||||
// setValue("status", stockInLineStatusMap.determine1.key) | |||||
}, []) | |||||
return ( | return ( | ||||
<Grid container justifyContent="flex-start" alignItems="flex-start"> | <Grid container justifyContent="flex-start" alignItems="flex-start"> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
@@ -1,6 +1,11 @@ | |||||
"use client"; | "use client"; | ||||
import { fetchPoWithStockInLines, PoResult, PurchaseOrderLine, StockInLine } from "@/app/api/po"; | |||||
import { | |||||
fetchPoWithStockInLines, | |||||
PoResult, | |||||
PurchaseOrderLine, | |||||
StockInLine, | |||||
} from "@/app/api/po"; | |||||
import { | import { | ||||
Box, | Box, | ||||
Button, | Button, | ||||
@@ -35,10 +40,12 @@ import InputDataGrid, { | |||||
import PoInputGrid from "./PoInputGrid"; | import PoInputGrid from "./PoInputGrid"; | ||||
import { QcItemWithChecks } from "@/app/api/qc"; | import { QcItemWithChecks } from "@/app/api/qc"; | ||||
import { useSearchParams } from "next/navigation"; | import { useSearchParams } from "next/navigation"; | ||||
import { WarehouseResult } from "@/app/api/warehouse"; | |||||
type Props = { | type Props = { | ||||
po: PoResult; | po: PoResult; | ||||
qc: QcItemWithChecks[] | |||||
qc: QcItemWithChecks[]; | |||||
warehouse: WarehouseResult[]; | |||||
}; | }; | ||||
type EntryError = | type EntryError = | ||||
@@ -48,20 +55,17 @@ type EntryError = | |||||
| undefined; | | undefined; | ||||
// type PolRow = TableRow<Partial<StockInLine>, EntryError>; | // type PolRow = TableRow<Partial<StockInLine>, EntryError>; | ||||
const PoDetail: React.FC<Props> = ({ | |||||
po, | |||||
// poLine, | |||||
qc | |||||
}) => { | |||||
const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => { | |||||
const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
const [rows, setRows] = useState<PurchaseOrderLine[]>(po.pol || []); | const [rows, setRows] = useState<PurchaseOrderLine[]>(po.pol || []); | ||||
const params = useSearchParams() | |||||
const params = useSearchParams(); | |||||
function Row(props: { row: PurchaseOrderLine }) { | function Row(props: { row: PurchaseOrderLine }) { | ||||
const { row } = props; | const { row } = props; | ||||
const [open, setOpen] = useState(false); | const [open, setOpen] = useState(false); | ||||
const [processedQty, setProcessedQty] = useState(row.processed); | |||||
return ( | return ( | ||||
<> | <> | ||||
<TableRow sx={{ "& > *": { borderBottom: "unset" }, color: "black" }}> | <TableRow sx={{ "& > *": { borderBottom: "unset" }, color: "black" }}> | ||||
@@ -77,30 +81,30 @@ const PoDetail: React.FC<Props> = ({ | |||||
<TableCell align="left">{row.itemNo}</TableCell> | <TableCell align="left">{row.itemNo}</TableCell> | ||||
<TableCell align="left">{row.itemName}</TableCell> | <TableCell align="left">{row.itemName}</TableCell> | ||||
<TableCell align="left">{row.qty}</TableCell> | <TableCell align="left">{row.qty}</TableCell> | ||||
<TableCell align="left">{processedQty}</TableCell> | |||||
<TableCell align="left">{row.uom}</TableCell> | <TableCell align="left">{row.uom}</TableCell> | ||||
<TableCell align="left">{row.price}</TableCell> | <TableCell align="left">{row.price}</TableCell> | ||||
{/* <TableCell align="left">{row.expiryDate}</TableCell> */} | {/* <TableCell align="left">{row.expiryDate}</TableCell> */} | ||||
<TableCell align="left">{row.status}</TableCell> | <TableCell align="left">{row.status}</TableCell> | ||||
</TableRow> | </TableRow> | ||||
<TableRow> | <TableRow> | ||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}> | |||||
{/* <TableCell /> */} | |||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={12}> | |||||
<Collapse in={open} timeout="auto" unmountOnExit> | <Collapse in={open} timeout="auto" unmountOnExit> | ||||
<Table> | <Table> | ||||
<TableBody> | <TableBody> | ||||
<TableRow> | <TableRow> | ||||
{/* <Button | |||||
onClick={()=> { | |||||
console.log(row) | |||||
console.log(row.stockInLine) | |||||
}} | |||||
>console log</Button> */} | |||||
<TableCell> | |||||
<PoInputGrid | |||||
qc={qc} | |||||
setRows={setRows} | |||||
itemDetail={row} | |||||
stockInLine={row.stockInLine} | |||||
/> | |||||
<TableCell align="right"> | |||||
<Box> | |||||
<PoInputGrid | |||||
qc={qc} | |||||
setRows={setRows} | |||||
setProcessedQty={setProcessedQty} | |||||
itemDetail={row} | |||||
stockInLine={row.stockInLine} | |||||
warehouse={warehouse} | |||||
/> | |||||
</Box> | |||||
</TableCell> | </TableCell> | ||||
</TableRow> | </TableRow> | ||||
</TableBody> | </TableBody> | ||||
@@ -133,6 +137,7 @@ const PoDetail: React.FC<Props> = ({ | |||||
<TableCell>{t("itemNo")}</TableCell> | <TableCell>{t("itemNo")}</TableCell> | ||||
<TableCell align="left">{t("itemName")}</TableCell> | <TableCell align="left">{t("itemName")}</TableCell> | ||||
<TableCell align="left">{t("qty")}</TableCell> | <TableCell align="left">{t("qty")}</TableCell> | ||||
<TableCell align="left">processed</TableCell> | |||||
<TableCell align="left">{t("uom")}</TableCell> | <TableCell align="left">{t("uom")}</TableCell> | ||||
<TableCell align="left">{t("price")}</TableCell> | <TableCell align="left">{t("price")}</TableCell> | ||||
{/* <TableCell align="left">{t("expiryDate")}</TableCell> */} | {/* <TableCell align="left">{t("expiryDate")}</TableCell> */} | ||||
@@ -8,6 +8,8 @@ import { fetchPoWithStockInLines, PoResult } from "@/app/api/po"; | |||||
import PoDetailLoading from "./PoDetailLoading"; | import PoDetailLoading from "./PoDetailLoading"; | ||||
import PoDetail from "./PoDetail"; | import PoDetail from "./PoDetail"; | ||||
import { QcItemWithChecks } from "@/app/api/qc"; | import { QcItemWithChecks } from "@/app/api/qc"; | ||||
import { fetchWarehouseList } from "@/app/api/warehouse"; | |||||
import { fetchQcItemCheck } from "@/app/api/qc/actions"; | |||||
interface SubComponents { | interface SubComponents { | ||||
Loading: typeof PoDetailLoading; | Loading: typeof PoDetailLoading; | ||||
@@ -19,35 +21,22 @@ type Props = { | |||||
const PoDetailWrapper: React.FC<Props> & SubComponents = async ({ id }) => { | const PoDetailWrapper: React.FC<Props> & SubComponents = async ({ id }) => { | ||||
const [ | const [ | ||||
poWithStockInLine | |||||
poWithStockInLine, | |||||
warehouse, | |||||
qc, | |||||
] = await Promise.all([ | ] = await Promise.all([ | ||||
fetchPoWithStockInLines(id) | |||||
fetchPoWithStockInLines(id), | |||||
fetchWarehouseList(), | |||||
fetchQcItemCheck() | |||||
]) | ]) | ||||
// const poWithStockInLine = await fetchPoWithStockInLines(id) | // const poWithStockInLine = await fetchPoWithStockInLines(id) | ||||
console.log(poWithStockInLine) | console.log(poWithStockInLine) | ||||
const qc: QcItemWithChecks[] = [ // just qc | |||||
{ | |||||
id: 1, | |||||
code: "code1", | |||||
name: "name1", | |||||
itemId: 1, | |||||
lowerLimit: 1, | |||||
upperLimit: 3, | |||||
description: 'desc', | |||||
}, | |||||
{ | |||||
id: 2, | |||||
code: "code2", | |||||
name: "name2", | |||||
itemId: 1, | |||||
lowerLimit: 1, | |||||
upperLimit: 3, | |||||
description: 'desc', | |||||
}, | |||||
] | |||||
console.log(warehouse) | |||||
console.log(qc) | |||||
return <PoDetail po={poWithStockInLine} qc={qc} />; | |||||
return <PoDetail po={poWithStockInLine} qc={qc} warehouse={warehouse}/>; | |||||
}; | }; | ||||
PoDetailWrapper.Loading = PoDetailLoading; | PoDetailWrapper.Loading = PoDetailLoading; | ||||
@@ -37,7 +37,8 @@ import { createStockInLine, testFetch } from "@/app/api/po/actions"; | |||||
import { useSearchParams } from "next/navigation"; | import { useSearchParams } from "next/navigation"; | ||||
import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | ||||
import PoQcStockInModal from "./PoQcStockInModal"; | import PoQcStockInModal from "./PoQcStockInModal"; | ||||
import NotificationImportantIcon from '@mui/icons-material/NotificationImportant'; | |||||
import NotificationImportantIcon from "@mui/icons-material/NotificationImportant"; | |||||
import { WarehouseResult } from "@/app/api/warehouse"; | |||||
interface ResultWithId { | interface ResultWithId { | ||||
id: number; | id: number; | ||||
} | } | ||||
@@ -45,8 +46,10 @@ interface ResultWithId { | |||||
interface Props { | interface Props { | ||||
qc: QcItemWithChecks[]; | qc: QcItemWithChecks[]; | ||||
setRows: Dispatch<SetStateAction<PurchaseOrderLine[]>>; | setRows: Dispatch<SetStateAction<PurchaseOrderLine[]>>; | ||||
setProcessedQty: Dispatch<SetStateAction<number>>; | |||||
itemDetail: PurchaseOrderLine; | itemDetail: PurchaseOrderLine; | ||||
stockInLine: StockInLine[]; | stockInLine: StockInLine[]; | ||||
warehouse: WarehouseResult[]; | |||||
} | } | ||||
export type StockInLineEntryError = { | export type StockInLineEntryError = { | ||||
@@ -64,7 +67,11 @@ export type StockInLineRow = Partial< | |||||
class ProcessRowUpdateError extends Error { | class ProcessRowUpdateError extends Error { | ||||
public readonly row: StockInLineRow; | public readonly row: StockInLineRow; | ||||
public readonly errors: StockInLineEntryError | undefined; | public readonly errors: StockInLineEntryError | undefined; | ||||
constructor(row: StockInLineRow, message?: string, errors?: StockInLineEntryError) { | |||||
constructor( | |||||
row: StockInLineRow, | |||||
message?: string, | |||||
errors?: StockInLineEntryError | |||||
) { | |||||
super(message); | super(message); | ||||
this.row = row; | this.row = row; | ||||
this.errors = errors; | this.errors = errors; | ||||
@@ -73,7 +80,14 @@ class ProcessRowUpdateError extends Error { | |||||
} | } | ||||
} | } | ||||
function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
function PoInputGrid({ | |||||
qc, | |||||
setRows, | |||||
setProcessedQty, | |||||
itemDetail, | |||||
stockInLine, | |||||
warehouse, | |||||
}: Props) { | |||||
const { t } = useTranslation("home"); | const { t } = useTranslation("home"); | ||||
const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | ||||
@@ -83,25 +97,32 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
); | ); | ||||
console.log(stockInLine); | console.log(stockInLine); | ||||
const [entries, setEntries] = useState<StockInLineRow[]>(stockInLine || []); | const [entries, setEntries] = useState<StockInLineRow[]>(stockInLine || []); | ||||
const [modalInfo, setModalInfo] = useState<StockInLine>() | |||||
const [modalInfo, setModalInfo] = useState<StockInLine>(); | |||||
const [qcOpen, setQcOpen] = useState(false); | const [qcOpen, setQcOpen] = useState(false); | ||||
const [escalOpen, setEscalOpen] = useState(false); | const [escalOpen, setEscalOpen] = useState(false); | ||||
const [stockInOpen, setStockInOpen] = useState(false); | const [stockInOpen, setStockInOpen] = useState(false); | ||||
const [putAwayOpen, setPutAwayOpen] = useState(false); | const [putAwayOpen, setPutAwayOpen] = useState(false); | ||||
const [type, setType] = useState<"qc" | "stockIn">("qc"); | |||||
const [defaultQty, setDefaultQty] = useState(() => { | |||||
const total = entries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); | |||||
return itemDetail.qty - total; | |||||
const [currQty, setCurrQty] = useState(() => { | |||||
const total = entries.reduce( | |||||
(acc, curr) => acc + (curr.acceptedQty || 0), | |||||
0 | |||||
); | |||||
return total; | |||||
}); | }); | ||||
const params = useSearchParams() | |||||
// const refetchData = useCallback(async () => { | |||||
// const id = parseInt(params.get("id")!!) | |||||
// const res = await testFetch(id) | |||||
// const pol = res.pol!! | |||||
// console.log(pol) | |||||
// setRows(pol); | |||||
// }, [params]) | |||||
useEffect(() => { | |||||
}, []) | |||||
useEffect(() => { | |||||
const completedList = entries.filter( | |||||
(e) => e.status === stockInLineStatusMap.completed.key | |||||
); | |||||
const processedQty = completedList.reduce( | |||||
(acc, curr) => acc + (curr.acceptedQty || 0), | |||||
0 | |||||
); | |||||
setProcessedQty(processedQty); | |||||
}, [entries]); | |||||
const handleDelete = useCallback( | const handleDelete = useCallback( | ||||
(id: GridRowId) => () => { | (id: GridRowId) => () => { | ||||
@@ -119,8 +140,8 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
// post stock in line | // post stock in line | ||||
console.log("delayed"); | console.log("delayed"); | ||||
console.log(params); | console.log(params); | ||||
const oldId = params.row.id | |||||
console.log(oldId) | |||||
const oldId = params.row.id; | |||||
console.log(oldId); | |||||
const postData = { | const postData = { | ||||
itemId: params.row.itemId, | itemId: params.row.itemId, | ||||
itemNo: params.row.itemNo, | itemNo: params.row.itemNo, | ||||
@@ -128,10 +149,12 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
purchaseOrderId: params.row.purchaseOrderId, | purchaseOrderId: params.row.purchaseOrderId, | ||||
purchaseOrderLineId: params.row.purchaseOrderLineId, | purchaseOrderLineId: params.row.purchaseOrderLineId, | ||||
acceptedQty: params.row.acceptedQty, | acceptedQty: params.row.acceptedQty, | ||||
} | |||||
const res = await createStockInLine(postData) | |||||
console.log(res) | |||||
setEntries((prev) => prev.map((p) => p.id === oldId ? res.entity as StockInLine : p)) | |||||
}; | |||||
const res = await createStockInLine(postData); | |||||
console.log(res); | |||||
setEntries((prev) => | |||||
prev.map((p) => (p.id === oldId ? (res.entity as StockInLine) : p)) | |||||
); | |||||
// do post directly to test | // do post directly to test | ||||
// openStartModal(); | // openStartModal(); | ||||
}, 200); | }, 200); | ||||
@@ -144,7 +167,7 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
...prev, | ...prev, | ||||
[id]: { mode: GridRowModes.View }, | [id]: { mode: GridRowModes.View }, | ||||
})); | })); | ||||
setModalInfo(params.row) | |||||
setModalInfo(params.row); | |||||
setTimeout(() => { | setTimeout(() => { | ||||
// open qc modal | // open qc modal | ||||
console.log("delayed"); | console.log("delayed"); | ||||
@@ -153,31 +176,31 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
}, | }, | ||||
[] | [] | ||||
); | ); | ||||
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( | const handleStockIn = useCallback( | ||||
(id: GridRowId, params: any) => () => { | (id: GridRowId, params: any) => () => { | ||||
setRowModesModel((prev) => ({ | setRowModesModel((prev) => ({ | ||||
...prev, | ...prev, | ||||
[id]: { mode: GridRowModes.View }, | [id]: { mode: GridRowModes.View }, | ||||
})); | })); | ||||
setModalInfo(params.row) | |||||
setModalInfo(params.row); | |||||
setTimeout(() => { | setTimeout(() => { | ||||
// open stock in modal | // open stock in modal | ||||
openStockInModal() | |||||
openStockInModal(); | |||||
// return the record with its status as pending | // return the record with its status as pending | ||||
// update layout | // update layout | ||||
console.log("delayed"); | console.log("delayed"); | ||||
@@ -192,10 +215,10 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
...prev, | ...prev, | ||||
[id]: { mode: GridRowModes.View }, | [id]: { mode: GridRowModes.View }, | ||||
})); | })); | ||||
setModalInfo(params.row) | |||||
setModalInfo(params.row); | |||||
setTimeout(() => { | setTimeout(() => { | ||||
// open stock in modal | // open stock in modal | ||||
openPutAwayModal() | |||||
openPutAwayModal(); | |||||
// return the record with its status as pending | // return the record with its status as pending | ||||
// update layout | // update layout | ||||
console.log("delayed"); | console.log("delayed"); | ||||
@@ -236,7 +259,7 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
() => [ | () => [ | ||||
{ | { | ||||
field: "itemNo", | field: "itemNo", | ||||
flex: .8, | |||||
flex: 0.8, | |||||
}, | }, | ||||
{ | { | ||||
field: "itemName", | field: "itemName", | ||||
@@ -253,24 +276,24 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
{ | { | ||||
field: "status", | field: "status", | ||||
flex: 0.5, | flex: 0.5, | ||||
editable: true | |||||
// editable: true, | |||||
}, | }, | ||||
{ | { | ||||
field: "actions", | field: "actions", | ||||
type: "actions", | type: "actions", | ||||
headerName: "start | qc | escalate | stock in | putaway | delete", | |||||
headerName: "start | qc | stock in | putaway | delete", | |||||
flex: 1.5, | flex: 1.5, | ||||
cellClassName: "actions", | cellClassName: "actions", | ||||
getActions: (params) => { | getActions: (params) => { | ||||
console.log(params.row.status); | console.log(params.row.status); | ||||
const status = params.row.status.toLowerCase() | |||||
const status = params.row.status.toLowerCase(); | |||||
return [ | return [ | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
icon={<PlayArrowIcon />} | icon={<PlayArrowIcon />} | ||||
label="start" | label="start" | ||||
sx={{ | sx={{ | ||||
color: "primary.main", | color: "primary.main", | ||||
marginRight: 2 | |||||
marginRight: 2, | |||||
}} | }} | ||||
disabled={!(stockInLineStatusMap[status].value === 0)} | disabled={!(stockInLineStatusMap[status].value === 0)} | ||||
// set _isNew to false after posting | // set _isNew to false after posting | ||||
@@ -284,35 +307,41 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
label="qc" | label="qc" | ||||
sx={{ | sx={{ | ||||
color: "primary.main", | color: "primary.main", | ||||
marginRight: 2 | |||||
marginRight: 2, | |||||
}} | }} | ||||
disabled={stockInLineStatusMap[status].value <= 0 || stockInLineStatusMap[status].value >= 5} | |||||
disabled={ | |||||
stockInLineStatusMap[status].value <= 0 || | |||||
stockInLineStatusMap[status].value >= 5 | |||||
} | |||||
// set _isNew to false after posting | // set _isNew to false after posting | ||||
// or check status | // or check status | ||||
onClick={handleQC(params.row.id, params)} | onClick={handleQC(params.row.id, params)} | ||||
color="inherit" | color="inherit" | ||||
key="edit" | key="edit" | ||||
/>, | />, | ||||
<GridActionsCellItem | |||||
icon={<NotificationImportantIcon />} | |||||
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" | |||||
/>, | |||||
// <GridActionsCellItem | |||||
// icon={<NotificationImportantIcon />} | |||||
// 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" | |||||
// />, | |||||
<GridActionsCellItem | <GridActionsCellItem | ||||
icon={<ShoppingCartIcon />} | icon={<ShoppingCartIcon />} | ||||
label="stockin" | label="stockin" | ||||
sx={{ | sx={{ | ||||
color: "primary.main", | color: "primary.main", | ||||
marginRight: 2 | |||||
marginRight: 2, | |||||
}} | }} | ||||
disabled={stockInLineStatusMap[status].value !== 6} | disabled={stockInLineStatusMap[status].value !== 6} | ||||
// set _isNew to false after posting | // set _isNew to false after posting | ||||
@@ -326,7 +355,7 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
label="putaway" | label="putaway" | ||||
sx={{ | sx={{ | ||||
color: "primary.main", | color: "primary.main", | ||||
marginRight: 2 | |||||
marginRight: 2, | |||||
}} | }} | ||||
disabled={stockInLineStatusMap[status].value !== 7} | disabled={stockInLineStatusMap[status].value !== 7} | ||||
// set _isNew to false after posting | // set _isNew to false after posting | ||||
@@ -363,7 +392,7 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
purchaseOrderLineId: itemDetail.id, | purchaseOrderLineId: itemDetail.id, | ||||
itemNo: itemDetail.itemNo, | itemNo: itemDetail.itemNo, | ||||
itemName: itemDetail.itemName, | itemName: itemDetail.itemName, | ||||
acceptedQty: defaultQty, | |||||
acceptedQty: itemDetail.qty - currQty, // this bug | |||||
status: "draft", | status: "draft", | ||||
}; | }; | ||||
setEntries((e) => [...e, newEntry]); | setEntries((e) => [...e, newEntry]); | ||||
@@ -374,7 +403,7 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
// fieldToFocus: "projectId", | // fieldToFocus: "projectId", | ||||
}, | }, | ||||
})); | })); | ||||
}, [getRowId]); | |||||
}, [currQty, getRowId]); | |||||
const validation = useCallback( | const validation = useCallback( | ||||
( | ( | ||||
newRow: GridRowModel<StockInLineRow> | newRow: GridRowModel<StockInLineRow> | ||||
@@ -382,16 +411,19 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
): StockInLineEntryError | undefined => { | ): StockInLineEntryError | undefined => { | ||||
const error: StockInLineEntryError = {}; | const error: StockInLineEntryError = {}; | ||||
console.log(newRow); | console.log(newRow); | ||||
console.log(defaultQty); | |||||
if (newRow.acceptedQty && newRow.acceptedQty > defaultQty) { | |||||
console.log(currQty); | |||||
if (newRow.acceptedQty && newRow.acceptedQty > itemDetail.qty) { | |||||
error["acceptedQty"] = "qty cannot be greater than remaining qty"; | error["acceptedQty"] = "qty cannot be greater than remaining qty"; | ||||
} | } | ||||
return Object.keys(error).length > 0 ? error : undefined; | return Object.keys(error).length > 0 ? error : undefined; | ||||
}, | }, | ||||
[defaultQty] | |||||
[currQty] | |||||
); | ); | ||||
const processRowUpdate = useCallback( | const processRowUpdate = useCallback( | ||||
(newRow: GridRowModel<StockInLineRow>, originalRow: GridRowModel<StockInLineRow>) => { | |||||
( | |||||
newRow: GridRowModel<StockInLineRow>, | |||||
originalRow: GridRowModel<StockInLineRow> | |||||
) => { | |||||
const errors = validation(newRow); // change to validation | const errors = validation(newRow); // change to validation | ||||
if (errors) { | if (errors) { | ||||
throw new ProcessRowUpdateError( | throw new ProcessRowUpdateError( | ||||
@@ -409,8 +441,11 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
); | ); | ||||
setEntries(newEntries); | setEntries(newEntries); | ||||
//update remaining qty | //update remaining qty | ||||
const total = newEntries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); | |||||
setDefaultQty(itemDetail.qty - total); | |||||
const total = newEntries.reduce( | |||||
(acc, curr) => acc + (curr.acceptedQty || 0), | |||||
0 | |||||
); | |||||
setCurrQty(total); | |||||
return rowToSave; | return rowToSave; | ||||
}, | }, | ||||
[getRowId, entries] | [getRowId, entries] | ||||
@@ -426,17 +461,20 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
[apiRef] | [apiRef] | ||||
); | ); | ||||
useEffect(() => { | |||||
const total = entries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); | |||||
setDefaultQty(itemDetail.qty - total); | |||||
}, [entries]); | |||||
// useEffect(() => { | |||||
// const total = entries.reduce( | |||||
// (acc, curr) => acc + (curr.acceptedQty || 0), | |||||
// 0 | |||||
// ); | |||||
// setDefaultQty(itemDetail.qty - total); | |||||
// }, [entries]); | |||||
const footer = ( | const footer = ( | ||||
<Box display="flex" gap={2} alignItems="center"> | <Box display="flex" gap={2} alignItems="center"> | ||||
<Button | <Button | ||||
disableRipple | disableRipple | ||||
variant="outlined" | variant="outlined" | ||||
startIcon={<Add />} | startIcon={<Add />} | ||||
disabled={defaultQty <= 0} | |||||
disabled={itemDetail.qty - currQty <= 0} | |||||
onClick={addRow} | onClick={addRow} | ||||
size="small" | size="small" | ||||
> | > | ||||
@@ -469,6 +507,13 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
processRowUpdate={processRowUpdate} | processRowUpdate={processRowUpdate} | ||||
onProcessRowUpdateError={onProcessRowUpdateError} | onProcessRowUpdateError={onProcessRowUpdateError} | ||||
columns={columns} | columns={columns} | ||||
isCellEditable={(params) => { | |||||
const status = params.row.status.toLowerCase(); | |||||
return ( | |||||
stockInLineStatusMap[status].value >= 0 || | |||||
stockInLineStatusMap[status].value <= 1 | |||||
); | |||||
}} | |||||
getCellClassName={(params: GridCellParams<StockInLineRow>) => { | getCellClassName={(params: GridCellParams<StockInLineRow>) => { | ||||
let classname = ""; | let classname = ""; | ||||
if (params.row._error) { | if (params.row._error) { | ||||
@@ -512,14 +557,14 @@ function PoInputGrid({ qc, setRows, itemDetail, stockInLine }: Props) { | |||||
open={stockInOpen} | open={stockInOpen} | ||||
onClose={closeStockInModal} | onClose={closeStockInModal} | ||||
itemDetail={modalInfo!!} | itemDetail={modalInfo!!} | ||||
/> | |||||
/> | |||||
</> | </> | ||||
<> | <> | ||||
<PoQcStockInModal | <PoQcStockInModal | ||||
type={"putaway"} | type={"putaway"} | ||||
setEntries={setEntries} | setEntries={setEntries} | ||||
open={putAwayOpen} | open={putAwayOpen} | ||||
warehouse={[]} | |||||
warehouse={warehouse} | |||||
onClose={closePutAwayModal} | onClose={closePutAwayModal} | ||||
itemDetail={modalInfo!!} | itemDetail={modalInfo!!} | ||||
/> | /> | ||||
@@ -14,6 +14,7 @@ import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | |||||
import { StockInLineRow } from "./PoInputGrid"; | import { StockInLineRow } from "./PoInputGrid"; | ||||
import EscalationForm from "./EscalationForm"; | import EscalationForm from "./EscalationForm"; | ||||
import StockInForm from "./StockInForm"; | import StockInForm from "./StockInForm"; | ||||
import PutawayForm from "./PutawayForm"; | |||||
interface CommonProps extends Omit<ModalProps, "children"> { | interface CommonProps extends Omit<ModalProps, "children"> { | ||||
setEntries: Dispatch<SetStateAction<StockInLineRow[]>> | setEntries: Dispatch<SetStateAction<StockInLineRow[]>> | ||||
@@ -86,20 +87,20 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||||
}, []); | }, []); | ||||
// status to be posted | // 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 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<SubmitHandler<ModalFormInput & {}>>( | const onSubmit = useCallback<SubmitHandler<ModalFormInput & {}>>( | ||||
async (data, event) => { | async (data, event) => { | ||||
@@ -108,10 +109,6 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||||
console.log(data); | console.log(data); | ||||
console.log(itemDetail); | console.log(itemDetail); | ||||
try { | try { | ||||
console.log(type) | |||||
var status = getPostingStatus(type) | |||||
// if escalation, take data.status as status | |||||
console.log(status) | |||||
// add checking | // add checking | ||||
// const qty = data.sampleRate | // const qty = data.sampleRate | ||||
@@ -134,11 +131,10 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||||
...data, | ...data, | ||||
acceptedQty: acceptedQty, | acceptedQty: acceptedQty, | ||||
productionDate: productionDate, | productionDate: productionDate, | ||||
status: status, | |||||
} as StockInLineEntry & ModalFormInput; | } as StockInLineEntry & ModalFormInput; | ||||
////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////// | ||||
console.log(args) | console.log(args) | ||||
// return | |||||
return | |||||
if (hasErrors) { | if (hasErrors) { | ||||
setServerError(t("An error has occurred. Please try again later.")); | setServerError(t("An error has occurred. Please try again later.")); | ||||
return false; | return false; | ||||
@@ -188,6 +184,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||||
{type === "qc" && <QcForm qc={qc} itemDetail={itemDetail} />} | {type === "qc" && <QcForm qc={qc} itemDetail={itemDetail} />} | ||||
{type === "stockIn" && <StockInForm itemDetail={itemDetail} />} | {type === "stockIn" && <StockInForm itemDetail={itemDetail} />} | ||||
{type === "escalation" && <EscalationForm itemDetail={itemDetail} />} | {type === "escalation" && <EscalationForm itemDetail={itemDetail} />} | ||||
{type === "putaway" && <PutawayForm itemDetail={itemDetail} warehouse={warehouse} />} | |||||
<Stack direction="row" justifyContent="flex-end" gap={1}> | <Stack direction="row" justifyContent="flex-end" gap={1}> | ||||
<Button | <Button | ||||
name="submit" | name="submit" | ||||
@@ -1,10 +1,12 @@ | |||||
"use client"; | "use client"; | ||||
import { PurchaseQcCheck, PurchaseQCInput } from "@/app/api/po/actions"; | |||||
import { PurchaseQcCheck, PutawayInput } from "@/app/api/po/actions"; | |||||
import { | import { | ||||
Autocomplete, | |||||
Box, | Box, | ||||
Card, | Card, | ||||
CardContent, | CardContent, | ||||
FormControl, | |||||
Grid, | Grid, | ||||
Stack, | Stack, | ||||
TextField, | TextField, | ||||
@@ -14,7 +16,7 @@ import { | |||||
import { useFormContext } from "react-hook-form"; | import { useFormContext } from "react-hook-form"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import StyledDataGrid from "../StyledDataGrid"; | import StyledDataGrid from "../StyledDataGrid"; | ||||
import { useCallback, useMemo, useState } from "react"; | |||||
import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
import { | import { | ||||
GridColDef, | GridColDef, | ||||
GridRowIdGetter, | GridRowIdGetter, | ||||
@@ -31,10 +33,13 @@ import QcSelect from "./QcSelect"; | |||||
import { QcItemWithChecks } from "@/app/api/qc"; | import { QcItemWithChecks } from "@/app/api/qc"; | ||||
import { GridEditInputCell } from "@mui/x-data-grid"; | import { GridEditInputCell } from "@mui/x-data-grid"; | ||||
import { StockInLine } from "@/app/api/po"; | import { StockInLine } from "@/app/api/po"; | ||||
import { WarehouseResult } from "@/app/api/warehouse"; | |||||
import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | |||||
interface Props { | interface Props { | ||||
itemDetail: StockInLine; | itemDetail: StockInLine; | ||||
qc: QcItemWithChecks[]; | |||||
warehouse: WarehouseResult[]; | |||||
// qc: QcItemWithChecks[]; | |||||
} | } | ||||
type EntryError = | type EntryError = | ||||
| { | | { | ||||
@@ -42,12 +47,9 @@ type EntryError = | |||||
} | } | ||||
| undefined; | | undefined; | ||||
type PoQcRow = TableRow<Partial<PurchaseQcCheck>, EntryError>; | |||||
// type PoQcRow = TableRow<Partial<PurchaseQcCheck>, EntryError>; | |||||
const PutawayForm: React.FC<Props> = ({ | |||||
qc, | |||||
itemDetail, | |||||
}) => { | |||||
const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse }) => { | |||||
const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
const { | const { | ||||
@@ -61,97 +63,52 @@ const PutawayForm: React.FC<Props> = ({ | |||||
resetField, | resetField, | ||||
setError, | setError, | ||||
clearErrors, | clearErrors, | ||||
} = useFormContext<PurchaseQCInput>(); | |||||
console.log(itemDetail) | |||||
const [recordQty, setRecordQty] = useState(0) | |||||
const columns = useMemo<GridColDef[]>( | |||||
() => [ | |||||
} = useFormContext<PutawayInput>(); | |||||
console.log(itemDetail); | |||||
const [recordQty, setRecordQty] = useState(0); | |||||
const [warehouseId, setWarehouseId] = useState(0); | |||||
const filteredWarehouse = useMemo(() => { | |||||
// do filtering here if any | |||||
return warehouse; | |||||
}, []); | |||||
const options = useMemo(() => { | |||||
return [ | |||||
{ | { | ||||
field: "qcCheckId", | |||||
headerName: "qc Check", | |||||
flex: 1, | |||||
editable: true, | |||||
valueFormatter(params) { | |||||
const row = params.id ? params.api.getRow<PoQcRow>(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<PoQcRow, number>) { | |||||
console.log(params.value); | |||||
return <TwoLineCell>{params.formattedValue}</TwoLineCell>; | |||||
}, | |||||
renderEditCell(params: GridRenderEditCellParams<PoQcRow, number>) { | |||||
const errorMessage = | |||||
params.row._error?.[params.field as keyof PurchaseQcCheck]; | |||||
console.log(errorMessage); | |||||
const content = ( | |||||
<QcSelect | |||||
allQcs={qc} | |||||
value={params.row.qcCheckId} | |||||
onQcSelect={async (qcCheckId) => { | |||||
await params.api.setEditCellValue({ | |||||
id: params.id, | |||||
field: "qcCheckId", | |||||
value: qcCheckId, | |||||
}); | |||||
}} | |||||
/> | |||||
); | |||||
return errorMessage ? ( | |||||
<Tooltip title={t(errorMessage)}> | |||||
<Box width="100%">{content}</Box> | |||||
</Tooltip> | |||||
) : ( | |||||
content | |||||
); | |||||
}, | |||||
}, | |||||
{ | |||||
field: "qty", | |||||
headerName: "qty", | |||||
flex: 1, | |||||
editable: true, | |||||
type: "number", | |||||
renderEditCell(params: GridRenderEditCellParams<PoQcRow>) { | |||||
// const recordQty = params.row.qty | |||||
// if (recordQty !== undefined) { | |||||
// setUnrecordQty((prev) => prev - recordQty) | |||||
// } | |||||
const errorMessage = | |||||
params.row._error?.[params.field as keyof PurchaseQcCheck]; | |||||
const content = <GridEditInputCell {...params} />; | |||||
return errorMessage ? ( | |||||
<Tooltip title={t(errorMessage)}> | |||||
<Box width="100%">{content}</Box> | |||||
</Tooltip> | |||||
) : ( | |||||
content | |||||
); | |||||
}, | |||||
value: -1, // think think sin | |||||
label: t("Select warehouse"), | |||||
group: "default", | |||||
}, | }, | ||||
], | |||||
[] | |||||
); | |||||
const validation = useCallback( | |||||
(newRow: GridRowModel<PoQcRow>): 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"; | |||||
} | |||||
if (qty && qty > itemDetail.acceptedQty) { | |||||
error["qty"] = "qty too big"; | |||||
} | |||||
return Object.keys(error).length > 0 ? error : undefined; | |||||
...filteredWarehouse.map((w) => ({ | |||||
value: w.id, | |||||
label: `${w.code} - ${w.name}`, | |||||
group: "existing", | |||||
})), | |||||
]; | |||||
}, [filteredWarehouse]); | |||||
const currentValue = | |||||
warehouseId > 0 | |||||
? options.find((o) => o.value === warehouseId) | |||||
: options.find((o) => o.value === getValues("warehouseId")) || options[0]; | |||||
const onChange = useCallback( | |||||
( | |||||
event: React.SyntheticEvent, | |||||
newValue: { value: number; group: string } | { value: number }[] | |||||
) => { | |||||
const singleNewVal = newValue as { | |||||
value: number; | |||||
group: string; | |||||
}; | |||||
console.log(singleNewVal); | |||||
setValue("warehouseId", singleNewVal.value); | |||||
setWarehouseId(singleNewVal.value); | |||||
}, | }, | ||||
[] | [] | ||||
); | ); | ||||
useEffect(() => { | |||||
setValue("status", stockInLineStatusMap.completed.key) | |||||
}, []) | |||||
return ( | return ( | ||||
<Grid container justifyContent="flex-start" alignItems="flex-start"> | <Grid container justifyContent="flex-start" alignItems="flex-start"> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
@@ -172,58 +129,40 @@ const PutawayForm: React.FC<Props> = ({ | |||||
fullWidth | fullWidth | ||||
value={itemDetail.acceptedQty} | value={itemDetail.acceptedQty} | ||||
disabled | disabled | ||||
// {...register("sampleRate", { | |||||
// required: "sampleRate required!", | |||||
// })} | |||||
// error={Boolean(errors.sampleRate)} | |||||
// helperText={errors.sampleRate?.message} | |||||
/> | /> | ||||
</Grid> | |||||
</Grid> | |||||
<Grid item xs={6}> | <Grid item xs={6}> | ||||
<TextField | <TextField | ||||
label={t("Total record qty")} | label={t("Total record qty")} | ||||
fullWidth | fullWidth | ||||
value={recordQty} | value={recordQty} | ||||
disabled | disabled | ||||
// {...register("sampleRate", { | |||||
// required: "sampleRate required!", | |||||
// })} | |||||
// error={Boolean(errors.sampleRate)} | |||||
// helperText={errors.sampleRate?.message} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={4}> | |||||
<TextField | |||||
label={t("sampleRate")} | |||||
fullWidth | |||||
{...register("sampleRate", { | |||||
required: "sampleRate required!", | |||||
})} | |||||
error={Boolean(errors.sampleRate)} | |||||
helperText={errors.sampleRate?.message} | |||||
/> | /> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={4}> | <Grid item xs={4}> | ||||
<TextField | <TextField | ||||
label={t("sampleWeight")} | |||||
label={t("acceptedQty")} | |||||
fullWidth | fullWidth | ||||
{...register("sampleWeight", { | |||||
required: "sampleWeight required!", | |||||
{...register("acceptedQty", { | |||||
required: "acceptedQty required!", | |||||
})} | })} | ||||
error={Boolean(errors.sampleWeight)} | |||||
helperText={errors.sampleWeight?.message} | |||||
error={Boolean(errors.acceptedQty)} | |||||
helperText={errors.acceptedQty?.message} | |||||
/> | /> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={4}> | <Grid item xs={4}> | ||||
<TextField | |||||
label={t("totalWeight")} | |||||
fullWidth | |||||
{...register("totalWeight", { | |||||
required: "totalWeight required!", | |||||
})} | |||||
error={Boolean(errors.totalWeight)} | |||||
helperText={errors.totalWeight?.message} | |||||
/> | |||||
<FormControl fullWidth> | |||||
<Autocomplete | |||||
noOptionsText={t("No Warehouse")} | |||||
disableClearable | |||||
fullWidth | |||||
value={currentValue} | |||||
onChange={onChange} | |||||
getOptionLabel={(option) => option.label} | |||||
options={options} | |||||
renderInput={(params) => <TextField {...params} />} | |||||
/> | |||||
</FormControl> | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
<Grid | <Grid | ||||
@@ -233,15 +172,15 @@ const PutawayForm: React.FC<Props> = ({ | |||||
spacing={2} | spacing={2} | ||||
sx={{ mt: 0.5 }} | sx={{ mt: 0.5 }} | ||||
> | > | ||||
<Grid item xs={12}> | |||||
<InputDataGrid<PurchaseQCInput, PurchaseQcCheck, EntryError> | |||||
{/* <Grid item xs={12}> | |||||
<InputDataGrid<PutawayInput, PurchaseQcCheck, EntryError> | |||||
apiRef={apiRef} | apiRef={apiRef} | ||||
checkboxSelection={false} | checkboxSelection={false} | ||||
_formKey={"qcCheck"} | _formKey={"qcCheck"} | ||||
columns={columns} | columns={columns} | ||||
validateRow={validation} | validateRow={validation} | ||||
/> | /> | ||||
</Grid> | |||||
</Grid> */} | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
@@ -14,7 +14,7 @@ import { | |||||
import { useFormContext } from "react-hook-form"; | import { useFormContext } from "react-hook-form"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import StyledDataGrid from "../StyledDataGrid"; | import StyledDataGrid from "../StyledDataGrid"; | ||||
import { useCallback, useMemo, useState } from "react"; | |||||
import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
import { | import { | ||||
GridColDef, | GridColDef, | ||||
GridRowIdGetter, | GridRowIdGetter, | ||||
@@ -28,9 +28,13 @@ import InputDataGrid from "../InputDataGrid"; | |||||
import { TableRow } from "../InputDataGrid/InputDataGrid"; | import { TableRow } from "../InputDataGrid/InputDataGrid"; | ||||
import TwoLineCell from "./TwoLineCell"; | import TwoLineCell from "./TwoLineCell"; | ||||
import QcSelect from "./QcSelect"; | import QcSelect from "./QcSelect"; | ||||
import { QcItemWithChecks } from "@/app/api/qc"; | |||||
import { GridEditInputCell } from "@mui/x-data-grid"; | import { GridEditInputCell } from "@mui/x-data-grid"; | ||||
import { StockInLine } from "@/app/api/po"; | import { StockInLine } from "@/app/api/po"; | ||||
import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | |||||
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"; | |||||
interface Props { | interface Props { | ||||
itemDetail: StockInLine; | itemDetail: StockInLine; | ||||
@@ -43,11 +47,8 @@ type EntryError = | |||||
| undefined; | | undefined; | ||||
type PoQcRow = TableRow<Partial<PurchaseQcCheck>, EntryError>; | type PoQcRow = TableRow<Partial<PurchaseQcCheck>, EntryError>; | ||||
const QcForm: React.FC<Props> = ({ | |||||
qc, | |||||
itemDetail, | |||||
}) => { | |||||
// fetchQcItemCheck | |||||
const QcForm: React.FC<Props> = ({ qc, itemDetail }) => { | |||||
const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
const { | const { | ||||
@@ -62,8 +63,21 @@ const QcForm: React.FC<Props> = ({ | |||||
setError, | setError, | ||||
clearErrors, | clearErrors, | ||||
} = useFormContext<PurchaseQCInput>(); | } = useFormContext<PurchaseQCInput>(); | ||||
console.log(itemDetail) | |||||
const [recordQty, setRecordQty] = useState(0) | |||||
console.log(itemDetail); | |||||
// const [qc, setQc] = useState<QcItemWithChecks[]>([]) | |||||
// const fetchQcCheck = useCallback(async () => { | |||||
// const params = { | |||||
// itemId: itemDetail.itemId | |||||
// } | |||||
// console.log(params) | |||||
// const res = await axios.get<QcItemWithChecks[]>(`${NEXT_PUBLIC_API_URL}/qcCheck`, { params }) | |||||
// console.log(res) | |||||
// }, [axios]) | |||||
// useEffect(() => { | |||||
// fetchQcCheck() | |||||
// }, [fetchQcCheck]) | |||||
const [recordQty, setRecordQty] = useState(0); | |||||
const columns = useMemo<GridColDef[]>( | const columns = useMemo<GridColDef[]>( | ||||
() => [ | () => [ | ||||
{ | { | ||||
@@ -133,7 +147,7 @@ const QcForm: React.FC<Props> = ({ | |||||
}, | }, | ||||
}, | }, | ||||
], | ], | ||||
[] | |||||
[qc] | |||||
); | ); | ||||
const validation = useCallback( | const validation = useCallback( | ||||
(newRow: GridRowModel<PoQcRow>): EntryError => { | (newRow: GridRowModel<PoQcRow>): EntryError => { | ||||
@@ -152,6 +166,18 @@ const QcForm: React.FC<Props> = ({ | |||||
}, | }, | ||||
[] | [] | ||||
); | ); | ||||
useEffect(() => { | |||||
console.log(itemDetail) | |||||
var status = stockInLineStatusMap.receiving.key | |||||
// switch (itemDetail.status) { | |||||
// case 'pending': | |||||
// status = "receiving" | |||||
// break; | |||||
// } | |||||
setValue("status", status) | |||||
}, [itemDetail]) | |||||
return ( | return ( | ||||
<Grid container justifyContent="flex-start" alignItems="flex-start"> | <Grid container justifyContent="flex-start" alignItems="flex-start"> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
@@ -178,7 +204,7 @@ const QcForm: React.FC<Props> = ({ | |||||
// error={Boolean(errors.sampleRate)} | // error={Boolean(errors.sampleRate)} | ||||
// helperText={errors.sampleRate?.message} | // helperText={errors.sampleRate?.message} | ||||
/> | /> | ||||
</Grid> | |||||
</Grid> | |||||
<Grid item xs={6}> | <Grid item xs={6}> | ||||
<TextField | <TextField | ||||
label={t("Total record qty")} | label={t("Total record qty")} | ||||
@@ -191,7 +217,7 @@ const QcForm: React.FC<Props> = ({ | |||||
// error={Boolean(errors.sampleRate)} | // error={Boolean(errors.sampleRate)} | ||||
// helperText={errors.sampleRate?.message} | // helperText={errors.sampleRate?.message} | ||||
/> | /> | ||||
</Grid> | |||||
</Grid> | |||||
<Grid item xs={4}> | <Grid item xs={4}> | ||||
<TextField | <TextField | ||||
label={t("sampleRate")} | label={t("sampleRate")} | ||||
@@ -14,7 +14,7 @@ import { | |||||
import { useFormContext } from "react-hook-form"; | import { useFormContext } from "react-hook-form"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import StyledDataGrid from "../StyledDataGrid"; | import StyledDataGrid from "../StyledDataGrid"; | ||||
import { useCallback, useMemo } from "react"; | |||||
import { useCallback, useEffect, useMemo } from "react"; | |||||
import { | import { | ||||
GridColDef, | GridColDef, | ||||
GridRowIdGetter, | GridRowIdGetter, | ||||
@@ -31,6 +31,7 @@ import QcSelect from "./QcSelect"; | |||||
import { QcItemWithChecks } from "@/app/api/qc"; | import { QcItemWithChecks } from "@/app/api/qc"; | ||||
import { GridEditInputCell } from "@mui/x-data-grid"; | import { GridEditInputCell } from "@mui/x-data-grid"; | ||||
import { StockInLine } from "@/app/api/po"; | import { StockInLine } from "@/app/api/po"; | ||||
import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | |||||
// change PurchaseQcCheck to stock in entry props | // change PurchaseQcCheck to stock in entry props | ||||
interface Props { | interface Props { | ||||
itemDetail: StockInLine; | itemDetail: StockInLine; | ||||
@@ -64,6 +65,11 @@ const StockInForm: React.FC<Props> = ({ | |||||
} = useFormContext<StockInInput>(); | } = useFormContext<StockInInput>(); | ||||
console.log(itemDetail) | console.log(itemDetail) | ||||
useEffect(() => { | |||||
console.log("triggered") | |||||
setValue("status", stockInLineStatusMap.received.key) | |||||
}, []) | |||||
return ( | return ( | ||||
<Grid container justifyContent="flex-start" alignItems="flex-start"> | <Grid container justifyContent="flex-start" alignItems="flex-start"> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||