| @@ -16,11 +16,11 @@ type Props = {} & SearchParams; | |||||
| const PoEdit: React.FC<Props> = async ({ searchParams }) => { | const PoEdit: React.FC<Props> = async ({ searchParams }) => { | ||||
| const type = "purchaseOrder"; | const type = "purchaseOrder"; | ||||
| const { t } = await getServerI18n(type); | const { t } = await getServerI18n(type); | ||||
| console.log(searchParams["id"]); | |||||
| //console.log(searchParams["id"]); | |||||
| const id = isString(searchParams["id"]) | const id = isString(searchParams["id"]) | ||||
| ? parseInt(searchParams["id"]) | ? parseInt(searchParams["id"]) | ||||
| : undefined; | : undefined; | ||||
| console.log(id); | |||||
| //console.log(id); | |||||
| if (!id) { | if (!id) { | ||||
| notFound(); | notFound(); | ||||
| } | } | ||||
| @@ -253,7 +253,7 @@ interface PolInputResult { | |||||
| dnQty: string, | dnQty: string, | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.1 | 2026-08-12 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.2 | 2026-09-07 */ | |||||
| const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | ||||
| const cameras = useContext(CameraContext); | const cameras = useContext(CameraContext); | ||||
| const { data: session } = useSession(); | const { data: session } = useSession(); | ||||
| @@ -678,11 +678,29 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | |||||
| }, 200); | }, 200); | ||||
| }; | }; | ||||
| const exceedOrderBy10Percent = orderQty > 0 && acceptedQty > orderQty * 1.1; | |||||
| if (exceedOrderBy10Percent) { | |||||
| const sils = row.stockInLine ?? []; | |||||
| const alreadyM18 = sils.reduce( | |||||
| (acc, sil) => acc + Number(sil.purchaseAcceptedQty ?? 0), | |||||
| 0, | |||||
| ); | |||||
| const alreadyStock = sils.reduce( | |||||
| (acc, sil) => acc + Number(sil.acceptedQty ?? 0), | |||||
| 0, | |||||
| ); | |||||
| const stockDemand = Number(row.stockUom?.stockQty ?? 0); | |||||
| const thisBatchStock = | |||||
| orderQty > 0 && stockDemand > 0 | |||||
| ? acceptedQty * (stockDemand / orderQty) | |||||
| : acceptedQty; | |||||
| const exceedByOrderUnit = | |||||
| orderQty > 0 && alreadyM18 + acceptedQty > orderQty * 1.1; | |||||
| const exceedByStockUnit = | |||||
| stockDemand > 0 && | |||||
| alreadyStock + thisBatchStock > stockDemand * 1.1; | |||||
| if (exceedByOrderUnit || exceedByStockUnit) { | |||||
| submitDialogWithWarning(doSubmit, t, { | submitDialogWithWarning(doSubmit, t, { | ||||
| title: t("Confirm submit"), | title: t("Confirm submit"), | ||||
| html: t("This batch quantity exceeds order quantity. Do you still want to submit?"), | |||||
| html: t("qtyExceedsOrderConfirm"), | |||||
| confirmButtonText: t("Submit"), | confirmButtonText: t("Submit"), | ||||
| }); | }); | ||||
| } else { | } else { | ||||
| @@ -834,6 +852,11 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | |||||
| <TableCell align="center"> | <TableCell align="center"> | ||||
| <Button | <Button | ||||
| variant="contained" | variant="contained" | ||||
| onMouseDown={(e) => { | |||||
| // Keep input focused so onBlur does not remount this row and swallow the click. | |||||
| e.preventDefault(); | |||||
| e.stopPropagation(); | |||||
| }} | |||||
| onClick={(e) => { | onClick={(e) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| handleStart(); | handleStart(); | ||||
| @@ -998,7 +1021,7 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | |||||
| <> | <> | ||||
| <Stack spacing={2}> | <Stack spacing={2}> | ||||
| {/* Area1: title */} | {/* Area1: title */} | ||||
| <Grid container xs={12} justifyContent="start"> | |||||
| <Grid container justifyContent="start"> | |||||
| <Grid item> | <Grid item> | ||||
| <Typography mb={2} variant="h4"> | <Typography mb={2} variant="h4"> | ||||
| {purchaseOrder.code} -{" "} | {purchaseOrder.code} -{" "} | ||||
| @@ -1153,7 +1176,7 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | |||||
| {/* Area4: Main Table */} | {/* Area4: Main Table */} | ||||
| <Grid container xs={12} justifyContent="start"> | |||||
| <Grid container justifyContent="start"> | |||||
| <Grid item xs={12}> | <Grid item xs={12}> | ||||
| <TableContainer component={Paper} sx={{ width: 'fit-content', overflow: 'auto' }}> | <TableContainer component={Paper} sx={{ width: 'fit-content', overflow: 'auto' }}> | ||||
| <Table aria-label="collapsible table" stickyHeader> | <Table aria-label="collapsible table" stickyHeader> | ||||
| @@ -1187,7 +1210,7 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => { | |||||
| </Grid> | </Grid> | ||||
| {/* area5: selected item info */} | {/* area5: selected item info */} | ||||
| <Grid container xs={12} justifyContent="start"> | |||||
| <Grid container justifyContent="start"> | |||||
| <Grid item xs={12}> | <Grid item xs={12}> | ||||
| <Typography variant="h6"> | <Typography variant="h6"> | ||||
| {selectedRow ? `已選擇貨品: ${selectedRow?.itemNo ? selectedRow.itemNo : 'N/A'} - ${selectedRow?.itemName ? selectedRow?.itemName : 'N/A'}` : "未選擇貨品"} | {selectedRow ? `已選擇貨品: ${selectedRow?.itemNo ? selectedRow.itemNo : 'N/A'} - ${selectedRow?.itemName ? selectedRow?.itemName : 'N/A'}` : "未選擇貨品"} | ||||
| @@ -170,7 +170,7 @@ class ProcessRowUpdateError extends Error { | |||||
| } | } | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.1 | 2026-08-12 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.2 | 2026-09-07 */ | |||||
| function PoInputGrid({ | function PoInputGrid({ | ||||
| // qc, | // qc, | ||||
| setRows, | setRows, | ||||
| @@ -71,7 +71,7 @@ interface CommonProps extends Omit<ModalProps, "children"> { | |||||
| interface Props extends CommonProps { | interface Props extends CommonProps { | ||||
| // itemDetail: StockInLine & { qcResult?: PurchaseQcResult[] } & { escResult?: EscalationResult[] }; | // itemDetail: StockInLine & { qcResult?: PurchaseQcResult[] } & { escResult?: EscalationResult[] }; | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.1 | 2026-08-12 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.2 | 2026-09-07 */ | |||||
| const PoQcStockInModalVer2: React.FC<Props> = ({ | const PoQcStockInModalVer2: React.FC<Props> = ({ | ||||
| open, | open, | ||||
| onClose, | onClose, | ||||
| @@ -29,6 +29,7 @@ type SearchParamNames = keyof SearchQuery; | |||||
| // cal offset (pageSize) | // cal offset (pageSize) | ||||
| // cal limit (pageSize) | // cal limit (pageSize) | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 76 | v1.0.0 | 2026-09-07 */ | |||||
| const PoSearch: React.FC<Props> = ({ | const PoSearch: React.FC<Props> = ({ | ||||
| po, | po, | ||||
| totalCount: initTotalCount, | totalCount: initTotalCount, | ||||
| @@ -150,7 +151,7 @@ const PoSearch: React.FC<Props> = ({ | |||||
| return <Grid>"N/A"</Grid> | return <Grid>"N/A"</Grid> | ||||
| } | } | ||||
| const items = value.split(",") | const items = value.split(",") | ||||
| return items.map((item) => <Grid key={item}>{item}</Grid>) | |||||
| return items.map((item, index) => <Grid key={`${index}-${item}`}>{item}</Grid>) | |||||
| }, []) | }, []) | ||||
| const columns = useMemo<Column<PoResult>[]>( | const columns = useMemo<Column<PoResult>[]>( | ||||
| @@ -272,8 +273,8 @@ const PoSearch: React.FC<Props> = ({ | |||||
| pagingController: Record<string, number>, | pagingController: Record<string, number>, | ||||
| filterArgs: Record<string, number>, | filterArgs: Record<string, number>, | ||||
| ) => { | ) => { | ||||
| console.log(pagingController); | |||||
| console.log(filterArgs); | |||||
| // console.log(pagingController); | |||||
| //console.log(filterArgs); | |||||
| const params = { | const params = { | ||||
| ...pagingController, | ...pagingController, | ||||
| ...filterArgs, | ...filterArgs, | ||||
| @@ -379,7 +380,7 @@ const PoSearch: React.FC<Props> = ({ | |||||
| ); | ); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| console.log(filteredPo) | |||||
| //console.log(filteredPo) | |||||
| }, [filteredPo]) | }, [filteredPo]) | ||||
| useEffect(() => { | useEffect(() => { | ||||
| @@ -404,7 +405,7 @@ const PoSearch: React.FC<Props> = ({ | |||||
| disabled={isM18LookupLoading} | disabled={isM18LookupLoading} | ||||
| onSearch={(query) => { | onSearch={(query) => { | ||||
| if (isM18LookupLoading) return; | if (isM18LookupLoading) return; | ||||
| console.log(query); | |||||
| //console.log(query); | |||||
| const code = typeof query.code === "string" ? query.code.trim() : ""; | const code = typeof query.code === "string" ? query.code.trim() : ""; | ||||
| if (code) { | if (code) { | ||||
| // When PO code is provided, ignore other search criteria (especially date ranges). | // When PO code is provided, ignore other search criteria (especially date ranges). | ||||
| @@ -72,7 +72,7 @@ interface Props extends CommonProps { | |||||
| // itemDetail: StockInLine & { qcResult?: PurchaseQcResult[] } & { escResult?: EscalationResult[] }; | // itemDetail: StockInLine & { qcResult?: PurchaseQcResult[] } & { escResult?: EscalationResult[] }; | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.1 | 2026-08-12 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.2 | 2026-09-07 */ | |||||
| const QcStockInModal: React.FC<Props> = ({ | const QcStockInModal: React.FC<Props> = ({ | ||||
| open, | open, | ||||
| onClose, | onClose, | ||||
| @@ -51,7 +51,7 @@ | |||||
| "acceptedPutawayQty": "Put Away Qty (This Batch)", | "acceptedPutawayQty": "Put Away Qty (This Batch)", | ||||
| "putawayQty": "Put Away Qty", | "putawayQty": "Put Away Qty", | ||||
| "Confirm submit": "Confirm Submit", | "Confirm submit": "Confirm Submit", | ||||
| "This batch quantity exceeds order quantity. Do you still want to submit?": "This batch quantity exceeds order quantity. Do you still want to submit?", | |||||
| "qtyExceedsOrderConfirm": "Cumulative received quantity exceeds order quantity. Do you still want to submit?", | |||||
| "acceptQty": "Accept Qty", | "acceptQty": "Accept Qty", | ||||
| "printQty": "Print Qty", | "printQty": "Print Qty", | ||||
| "qcResult": "QC Result", | "qcResult": "QC Result", | ||||
| @@ -51,7 +51,7 @@ | |||||
| "acceptedPutawayQty": "本批上架數量", | "acceptedPutawayQty": "本批上架數量", | ||||
| "putawayQty": "上架數量", | "putawayQty": "上架數量", | ||||
| "Confirm submit": "確定提交", | "Confirm submit": "確定提交", | ||||
| "This batch quantity exceeds order quantity. Do you still want to submit?": "本批收貨數量超出訂單數量。仍要提交嗎?", | |||||
| "qtyExceedsOrderConfirm": "累計收貨數量超出訂單數量。仍要提交嗎?", | |||||
| "acceptQty": "揀收數量", | "acceptQty": "揀收數量", | ||||
| "printQty": "列印數量", | "printQty": "列印數量", | ||||
| "qcResult": "品檢結果", | "qcResult": "品檢結果", | ||||