| @@ -207,7 +207,7 @@ interface PolInputResult { | |||||
| dnQty: string, | dnQty: string, | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| 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(); | ||||
| @@ -77,7 +77,7 @@ type Props = { | |||||
| onSubmitted: (row: PurchaseOrderLine) => void; | onSubmitted: (row: PurchaseOrderLine) => void; | ||||
| }; | }; | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| export const PoDetailRow = memo(function PoDetailRow({ | export const PoDetailRow = memo(function PoDetailRow({ | ||||
| row, | row, | ||||
| selected, | selected, | ||||
| @@ -155,7 +155,7 @@ class ProcessRowUpdateError extends Error { | |||||
| } | } | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| function PoInputGrid({ | function PoInputGrid({ | ||||
| // qc, | // qc, | ||||
| setRows, | setRows, | ||||
| @@ -55,6 +55,7 @@ import dayjs from "dayjs"; | |||||
| import arraySupport from "dayjs/plugin/arraySupport"; | import arraySupport from "dayjs/plugin/arraySupport"; | ||||
| import { dummyPutAwayLine } from "../Qc/dummyQcTemplate"; | import { dummyPutAwayLine } from "../Qc/dummyQcTemplate"; | ||||
| import { GridRowModesModel } from "@mui/x-data-grid"; | import { GridRowModesModel } from "@mui/x-data-grid"; | ||||
| import { displayPutAwayLineQtyFromOriginSil } from "./originSilPutAwayQty"; | |||||
| dayjs.extend(arraySupport); | dayjs.extend(arraySupport); | ||||
| interface Props { | interface Props { | ||||
| @@ -86,6 +87,7 @@ const style = { | |||||
| width: "auto", | width: "auto", | ||||
| }; | }; | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, suggestedLocationCode, setRowModesModel, setRowSelectionModel }) => { | const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, suggestedLocationCode, setRowModesModel, setRowSelectionModel }) => { | ||||
| const { t } = useTranslation("purchaseOrder"); | const { t } = useTranslation("purchaseOrder"); | ||||
| const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
| @@ -241,8 +243,13 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, sugg | |||||
| headerAlign: "right", | headerAlign: "right", | ||||
| align: "right", | align: "right", | ||||
| renderCell(params) { | renderCell(params) { | ||||
| const displayQty = displayPutAwayLineQtyFromOriginSil( | |||||
| itemDetail, | |||||
| Number(params.value), | |||||
| params.row._isNew, | |||||
| ); | |||||
| return <span style={{fontSize:24}}> | return <span style={{fontSize:24}}> | ||||
| {params.value} | |||||
| {displayQty} | |||||
| </span> | </span> | ||||
| } | } | ||||
| }, | }, | ||||
| @@ -309,7 +316,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, sugg | |||||
| // return <>100</> | // return <>100</> | ||||
| // }, | // }, | ||||
| // }, | // }, | ||||
| ], []) | |||||
| ], [itemDetail, t]) | |||||
| const validation = useCallback( | const validation = useCallback( | ||||
| (newRow: GridRowModel<PutAwayRow>): EntryError => { | (newRow: GridRowModel<PutAwayRow>): EntryError => { | ||||
| @@ -395,7 +402,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, sugg | |||||
| <TextField | <TextField | ||||
| label={t("acceptedPutawayQty")} // TODO: fix it back to acceptedQty after db is fixed | label={t("acceptedPutawayQty")} // TODO: fix it back to acceptedQty after db is fixed | ||||
| fullWidth | fullWidth | ||||
| value={itemDetail.qty ?? itemDetail.purchaseAcceptedQty ?? itemDetail.acceptedQty ?? itemDetail.demandQty} | |||||
| value={itemDetail.purchaseAcceptedQty ?? itemDetail.acceptedQty ?? itemDetail.qty ?? itemDetail.demandQty} | |||||
| disabled | disabled | ||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| @@ -21,6 +21,7 @@ import { useTranslation } from "react-i18next"; | |||||
| import StockInForm from "../StockIn/StockInForm"; | import StockInForm from "../StockIn/StockInForm"; | ||||
| import QcComponent from "../Qc/QcComponent"; | import QcComponent from "../Qc/QcComponent"; | ||||
| import PutAwayForm from "./PutAwayForm"; | import PutAwayForm from "./PutAwayForm"; | ||||
| import { mapPutAwayLinesFromOriginSil } from "./originSilPutAwayQty"; | |||||
| import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid"; | import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid"; | ||||
| import {msg, submitDialogWithWarning} from "../Swal/CustomAlerts"; | import {msg, submitDialogWithWarning} from "../Swal/CustomAlerts"; | ||||
| import { INPUT_DATE_FORMAT, arrayToDateString, dayjsToDateTimeString } from "@/app/utils/formatUtil"; | import { INPUT_DATE_FORMAT, arrayToDateString, dayjsToDateTimeString } from "@/app/utils/formatUtil"; | ||||
| @@ -71,7 +72,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.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| const PoQcStockInModalVer2: React.FC<Props> = ({ | const PoQcStockInModalVer2: React.FC<Props> = ({ | ||||
| open, | open, | ||||
| onClose, | onClose, | ||||
| @@ -205,7 +206,7 @@ const PoQcStockInModalVer2: React.FC<Props> = ({ | |||||
| // escResult: (d.escResult && d.escResult?.length > 0) ? d.escResult : [], | // escResult: (d.escResult && d.escResult?.length > 0) ? d.escResult : [], | ||||
| // qcResult: (d.qcResult && d.qcResult?.length > 0) ? d.qcResult : [],//[...dummyQCData], | // qcResult: (d.qcResult && d.qcResult?.length > 0) ? d.qcResult : [],//[...dummyQCData], | ||||
| warehouseId: d.defaultWarehouseId ?? 1, | warehouseId: d.defaultWarehouseId ?? 1, | ||||
| putAwayLines: d.putAwayLines?.map((line) => ({...line, printQty: 1, _isNew: false, _disableDelete: true})) ?? [], | |||||
| putAwayLines: mapPutAwayLinesFromOriginSil(d, d.putAwayLines), | |||||
| } as ModalFormInput | } as ModalFormInput | ||||
| ) | ) | ||||
| } return undefined | } return undefined | ||||
| @@ -26,7 +26,7 @@ type Props = { | |||||
| onRound?: (mode: StockQtyRoundMode) => void; | onRound?: (mode: StockQtyRoundMode) => void; | ||||
| }; | }; | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| export default function StockInLineRowActions({ | export default function StockInLineRowActions({ | ||||
| btnSx, | btnSx, | ||||
| onPrimaryClick, | onPrimaryClick, | ||||
| @@ -0,0 +1,60 @@ | |||||
| import { PutAwayLine, StockInLine } from "@/app/api/stockIn"; | |||||
| type OriginSil = Pick< | |||||
| StockInLine, | |||||
| "jobOrderId" | "purchaseAcceptedQty" | "acceptedQty" | |||||
| >; | |||||
| /** | |||||
| * FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 | |||||
| * Path A: inventory_lot_line → inventory_lot → stock_in_line (the SIL that opened the lot). | |||||
| * Never use inventory_lot_line.inQty — ADJ/TKE is added onto the same line later. | |||||
| * | |||||
| * PO: purchaseAcceptedQty (M18 / 採購單位) | |||||
| * JO: acceptedQty (庫存/生產單位;JO 通常沒有 acceptedQtyM18) | |||||
| */ | |||||
| export function originSilPutAwayDisplayQty(origin: OriginSil): number { | |||||
| if (origin.jobOrderId) { | |||||
| const stock = Number(origin.acceptedQty); | |||||
| return Number.isFinite(stock) && stock > 0 ? stock : 0; | |||||
| } | |||||
| const purchase = Number(origin.purchaseAcceptedQty); | |||||
| if (Number.isFinite(purchase) && purchase > 0) return purchase; | |||||
| const stock = Number(origin.acceptedQty); | |||||
| return Number.isFinite(stock) && stock > 0 ? stock : 0; | |||||
| } | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| export function originSilPutAwayStockQty(origin: OriginSil): number { | |||||
| const stock = Number(origin.acceptedQty); | |||||
| return Number.isFinite(stock) && stock > 0 ? stock : 0; | |||||
| } | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| export function mapPutAwayLinesFromOriginSil( | |||||
| origin: OriginSil, | |||||
| lines: PutAwayLine[] | undefined, | |||||
| ): PutAwayLine[] { | |||||
| const existing = lines ?? []; | |||||
| const displayQty = originSilPutAwayDisplayQty(origin); | |||||
| const stockQty = originSilPutAwayStockQty(origin); | |||||
| return existing.map((line) => ({ | |||||
| ...line, | |||||
| printQty: 1, | |||||
| _isNew: false, | |||||
| _disableDelete: true, | |||||
| ...(displayQty > 0 ? { qty: displayQty } : {}), | |||||
| ...(stockQty > 0 ? { stockQty } : {}), | |||||
| })); | |||||
| } | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| export function displayPutAwayLineQtyFromOriginSil( | |||||
| origin: OriginSil, | |||||
| lineQty: number, | |||||
| isNew: boolean | undefined, | |||||
| ): number { | |||||
| if (isNew) return lineQty; | |||||
| const originQty = originSilPutAwayDisplayQty(origin); | |||||
| return originQty > 0 ? originQty : lineQty; | |||||
| } | |||||
| @@ -81,6 +81,7 @@ function convertPoBatchToStockQty( | |||||
| } | } | ||||
| /** | /** | ||||
| * FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 | |||||
| * Preview converted stock qty for a 來貨數 batch. | * Preview converted stock qty for a 來貨數 batch. | ||||
| * Matches create-stock-in: ratio convert, then integer HALF_UP for 包/箱/PCS, else 2 decimals. | * Matches create-stock-in: ratio convert, then integer HALF_UP for 包/箱/PCS, else 2 decimals. | ||||
| */ | */ | ||||
| @@ -104,7 +105,7 @@ export function isNotIntegerQty(qty: number): boolean { | |||||
| } | } | ||||
| /** | /** | ||||
| * FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.4 | 2026-09-10 | |||||
| * FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 | |||||
| * PO 收貨/品檢:pending 或 escalated 且庫存數量非整數時需選擇 CEILING / FLOOR | * PO 收貨/品檢:pending 或 escalated 且庫存數量非整數時需選擇 CEILING / FLOOR | ||||
| */ | */ | ||||
| export function needsPoQcStockQtyRound( | export function needsPoQcStockQtyRound( | ||||
| @@ -118,7 +119,7 @@ export function needsPoQcStockQtyRound( | |||||
| return isNotIntegerQty(Number(acceptedQty ?? 0)); | return isNotIntegerQty(Number(acceptedQty ?? 0)); | ||||
| } | } | ||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| export function roundStockQty(before: number, mode: StockQtyRoundMode): number { | export function roundStockQty(before: number, mode: StockQtyRoundMode): number { | ||||
| if (mode === "CEILING") return Math.ceil(before); | if (mode === "CEILING") return Math.ceil(before); | ||||
| return Math.floor(before); | return Math.floor(before); | ||||
| @@ -24,6 +24,7 @@ import PutAwayForm from "../PoDetail/PutAwayForm"; | |||||
| import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid"; | import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid"; | ||||
| import {msg, submitDialogWithWarning} from "../Swal/CustomAlerts"; | import {msg, submitDialogWithWarning} from "../Swal/CustomAlerts"; | ||||
| import { needsPoQcStockQtyRound } from "../PoDetail/stockQtyRound"; | import { needsPoQcStockQtyRound } from "../PoDetail/stockQtyRound"; | ||||
| import { mapPutAwayLinesFromOriginSil } from "../PoDetail/originSilPutAwayQty"; | |||||
| import { INPUT_DATE_FORMAT, arrayToDateString, dayjsToDateTimeString } from "@/app/utils/formatUtil"; | import { INPUT_DATE_FORMAT, arrayToDateString, dayjsToDateTimeString } from "@/app/utils/formatUtil"; | ||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import { fetchPoQrcode } from "@/app/api/pdf/actions"; | import { fetchPoQrcode } from "@/app/api/pdf/actions"; | ||||
| @@ -73,7 +74,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.4 | 2026-09-10 */ | |||||
| /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.5 | 2026-09-18 */ | |||||
| const QcStockInModal: React.FC<Props> = ({ | const QcStockInModal: React.FC<Props> = ({ | ||||
| open, | open, | ||||
| onClose, | onClose, | ||||
| @@ -231,7 +232,7 @@ const QcStockInModal: React.FC<Props> = ({ | |||||
| // escResult: (d.escResult && d.escResult?.length > 0) ? d.escResult : [], | // escResult: (d.escResult && d.escResult?.length > 0) ? d.escResult : [], | ||||
| // qcResult: (d.qcResult && d.qcResult?.length > 0) ? d.qcResult : [],//[...dummyQCData], | // qcResult: (d.qcResult && d.qcResult?.length > 0) ? d.qcResult : [],//[...dummyQCData], | ||||
| warehouseId: d.defaultWarehouseId ?? 1141, | warehouseId: d.defaultWarehouseId ?? 1141, | ||||
| putAwayLines: d.putAwayLines?.map((line) => ({...line, printQty: 1, _isNew: false, _disableDelete: true})) ?? [], | |||||
| putAwayLines: mapPutAwayLinesFromOriginSil(d, d.putAwayLines), | |||||
| } as ModalFormInput | } as ModalFormInput | ||||
| ) | ) | ||||
| } return undefined | } return undefined | ||||