| @@ -352,6 +352,8 @@ export interface AllJoborderProductProcessInfoResponse { | |||
| uom: string; | |||
| isDrink?: boolean | null; | |||
| stockInLineId: number; | |||
| /** Stock-in-line current status (e.g. receiving/received/partially_completed/completed/rejected). */ | |||
| stockInLineStatus?: string | null; | |||
| jobOrderCode: string; | |||
| productProcessLineCount: number; | |||
| FinishedProductProcessLineCount: number; | |||
| @@ -798,6 +800,8 @@ export const fetchJoborderProductProcessesPage = cache(async (params: { | |||
| qcReady?: boolean | null; | |||
| type?: string | null; | |||
| includePutaway?: boolean | null; | |||
| /** all | completed | notCompleted */ | |||
| putawayStatus?: string | null; | |||
| page?: number; | |||
| size?: number; | |||
| }) => { | |||
| @@ -808,6 +812,7 @@ export const fetchJoborderProductProcessesPage = cache(async (params: { | |||
| bomIds, | |||
| qcReady, | |||
| includePutaway, | |||
| putawayStatus, | |||
| type, | |||
| page = 0, | |||
| size = 50, | |||
| @@ -825,6 +830,7 @@ export const fetchJoborderProductProcessesPage = cache(async (params: { | |||
| if (includePutaway !== undefined && includePutaway !== null) { | |||
| queryParts.push(`includePutaway=${includePutaway}`); | |||
| } | |||
| if (putawayStatus) queryParts.push(`putawayStatus=${encodeURIComponent(putawayStatus)}`); | |||
| queryParts.push(`page=${page}`); | |||
| queryParts.push(`size=${size}`); | |||
| @@ -60,6 +60,9 @@ interface ProductProcessListProps { | |||
| onSelectMatchingStock: (jobOrderId: number|undefined, productProcessId: number|undefined,pickOrderId: number|undefined) => void; | |||
| printerCombo: PrinterCombo[]; | |||
| qcReady: boolean; | |||
| includePutaway?: boolean | null; | |||
| /** all | completed | notCompleted */ | |||
| putawayStatus?: string | null; | |||
| listPersistedState: ProductionProcessListPersistedState; | |||
| onListPersistedStateChange: React.Dispatch< | |||
| React.SetStateAction<ProductionProcessListPersistedState> | |||
| @@ -93,6 +96,8 @@ const ProductProcessList: React.FC<ProductProcessListProps> = ({ | |||
| printerCombo, | |||
| onSelectMatchingStock, | |||
| qcReady, | |||
| includePutaway, | |||
| putawayStatus, | |||
| listPersistedState, | |||
| onListPersistedStateChange, | |||
| }) => { | |||
| @@ -258,7 +263,8 @@ const ProductProcessList: React.FC<ProductProcessListProps> = ({ | |||
| itemCode: appliedSearch.itemCode, | |||
| jobOrderCode: appliedSearch.jobOrderCode, | |||
| qcReady, | |||
| includePutaway: qcReady ? true : null, | |||
| includePutaway: includePutaway ?? (qcReady ? true : null), | |||
| putawayStatus, | |||
| type: typeParam, | |||
| page, | |||
| size: PAGE_SIZE, | |||
| @@ -273,7 +279,7 @@ const ProductProcessList: React.FC<ProductProcessListProps> = ({ | |||
| } finally { | |||
| setLoading(false); | |||
| } | |||
| }, [listPersistedState, qcReady]); | |||
| }, [listPersistedState, qcReady, includePutaway, putawayStatus]); | |||
| useEffect(() => { | |||
| fetchProcesses(); | |||
| @@ -36,7 +36,10 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| const [productionListState, setProductionListState] = useState( | |||
| createDefaultProductionProcessListPersistedState, | |||
| ); | |||
| const [finishedQcListState, setFinishedQcListState] = useState( | |||
| const [waitingPutawayListState, setWaitingPutawayListState] = useState( | |||
| createDefaultProductionProcessListPersistedState, | |||
| ); | |||
| const [putawayedListState, setPutawayedListState] = useState( | |||
| createDefaultProductionProcessListPersistedState, | |||
| ); | |||
| const { data: session } = useSession() as { data: SessionWithTokens | null }; | |||
| @@ -199,7 +202,8 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| <Tabs value={tabIndex} onChange={handleTabChange} sx={{ mb: 2 }}> | |||
| <Tab label={t("Production Process")} /> | |||
| <Tab label={t("Finished QC Job Orders")} /> | |||
| <Tab label={t("Waiting QC Put Away Job Orders")} /> | |||
| <Tab label={t("Put Awayed Job Orders")} /> | |||
| <Tab label={t("Job Process Status Dashboard")} /> | |||
| <Tab label={t("Operator KPI Dashboard")} /> | |||
| <Tab label={t("Production Equipment Status Dashboard")} /> | |||
| @@ -231,8 +235,10 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| <ProductionProcessList | |||
| printerCombo={printerCombo} | |||
| qcReady={true} | |||
| listPersistedState={finishedQcListState} | |||
| onListPersistedStateChange={setFinishedQcListState} | |||
| includePutaway={true} | |||
| putawayStatus="notCompleted" | |||
| listPersistedState={waitingPutawayListState} | |||
| onListPersistedStateChange={setWaitingPutawayListState} | |||
| onSelectProcess={(jobOrderId) => { | |||
| const id = jobOrderId ?? null; | |||
| if (id !== null) { | |||
| @@ -248,13 +254,36 @@ const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCo | |||
| }} | |||
| /> | |||
| )} | |||
| {tabIndex === 2 && ( | |||
| <JobProcessStatus /> | |||
| {tabIndex === 2 && ( | |||
| <ProductionProcessList | |||
| printerCombo={printerCombo} | |||
| qcReady={true} | |||
| includePutaway={true} | |||
| putawayStatus="completed" | |||
| listPersistedState={putawayedListState} | |||
| onListPersistedStateChange={setPutawayedListState} | |||
| onSelectProcess={(jobOrderId) => { | |||
| const id = jobOrderId ?? null; | |||
| if (id !== null) { | |||
| setSelectedProcessId(id); | |||
| } | |||
| }} | |||
| onSelectMatchingStock={(jobOrderId, productProcessId, pickOrderId) => { | |||
| setSelectedMatchingStock({ | |||
| jobOrderId: jobOrderId || 0, | |||
| productProcessId: productProcessId || 0, | |||
| pickOrderId: pickOrderId || 0, | |||
| }); | |||
| }} | |||
| /> | |||
| )} | |||
| {tabIndex === 3 && ( | |||
| <OperatorKpiDashboard /> | |||
| <JobProcessStatus /> | |||
| )} | |||
| {tabIndex === 4 && ( | |||
| <OperatorKpiDashboard /> | |||
| )} | |||
| {tabIndex === 5 && ( | |||
| <EquipmentStatusDashboard /> | |||
| )} | |||
| </Box> | |||
| @@ -128,6 +128,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId | |||
| ...defaultNewValue, | |||
| }, | |||
| }); | |||
| const { isSubmitting } = formProps.formState; | |||
| const errors = formProps.formState.errors; | |||
| useEffect(() => { | |||
| @@ -646,7 +647,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId | |||
| }, | |||
| }} | |||
| // onClick={formProps.handleSubmit()} | |||
| disabled={!verified || qtyError != ""} | |||
| disabled={!verified || qtyError != "" || isSubmitting} | |||
| > | |||
| {t("confirm putaway")} | |||
| </Button> | |||
| @@ -12,6 +12,8 @@ | |||
| "Please Select BOM": "請選擇 BOM", | |||
| "No Lot": "沒有批號", | |||
| "Select All": "全選", | |||
| "Waiting QC Put Away Job Orders": "待QC上架工單", | |||
| "Put Awayed Job Orders": "已上架工單", | |||
| "Loading BOM Detail...": "正在載入 BOM 明細…", | |||
| "Output Quantity": "使用數量", | |||
| "Process & Equipment": "製程與設備", | |||