| @@ -1,3 +1,4 @@ | |||||
| import { fetchPrinterCombo } from "@/app/api/settings/printer"; | |||||
| import { fetchEscalationCombo } from "@/app/api/user"; | import { fetchEscalationCombo } from "@/app/api/user"; | ||||
| import { SearchParams } from "@/app/utils/fetchUtil"; | import { SearchParams } from "@/app/utils/fetchUtil"; | ||||
| import { TypeEnum } from "@/app/utils/typeEnum"; | import { TypeEnum } from "@/app/utils/typeEnum"; | ||||
| @@ -25,6 +26,7 @@ const PoEdit: React.FC<Props> = async ({ searchParams }) => { | |||||
| } | } | ||||
| fetchEscalationCombo() | fetchEscalationCombo() | ||||
| fetchPrinterCombo() | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -6,10 +6,11 @@ import { revalidateTag } from "next/cache"; | |||||
| import { cache } from "react"; | import { cache } from "react"; | ||||
| import { PoResult, StockInLine } from "."; | import { PoResult, StockInLine } from "."; | ||||
| //import { serverFetchJson } from "@/app/utils/fetchUtil"; | //import { serverFetchJson } from "@/app/utils/fetchUtil"; | ||||
| import { serverFetchJson } from "../../utils/fetchUtil"; | |||||
| import { serverFetchJson, serverFetchWithNoContent } from "../../utils/fetchUtil"; | |||||
| import { QcItemResult } from "../settings/qcItem"; | import { QcItemResult } from "../settings/qcItem"; | ||||
| import { RecordsRes } from "../utils"; | import { RecordsRes } from "../utils"; | ||||
| import { Uom } from "../settings/uom"; | import { Uom } from "../settings/uom"; | ||||
| import { convertObjToURLSearchParams } from "@/app/utils/commonUtil"; | |||||
| // import { BASE_API_URL } from "@/config/api"; | // import { BASE_API_URL } from "@/config/api"; | ||||
| export interface PostStockInLineResponse<T> { | export interface PostStockInLineResponse<T> { | ||||
| @@ -81,26 +82,34 @@ export interface EscalationInput { | |||||
| acceptedQty?: number; // this is the qty to be escalated | acceptedQty?: number; // this is the qty to be escalated | ||||
| // escalationQty: number | // escalationQty: number | ||||
| } | } | ||||
| export interface PutawayLine { | |||||
| export interface PutAwayLine { | |||||
| id?: number | id?: number | ||||
| qty: number | qty: number | ||||
| warehouseId: number; | warehouseId: number; | ||||
| warehouse: string; | warehouse: string; | ||||
| printQty: number | |||||
| printQty: number; | |||||
| _isNew?: boolean; | |||||
| printQty?: number; | |||||
| } | } | ||||
| export interface PutawayInput { | |||||
| export interface PutAwayInput { | |||||
| status: string; | status: string; | ||||
| acceptedQty: number; | acceptedQty: number; | ||||
| warehouseId: number; | warehouseId: number; | ||||
| putawayLine: PutawayLine[] | |||||
| putAwayLines: PutAwayLine[] | |||||
| } | } | ||||
| export type ModalFormInput = Partial< | export type ModalFormInput = Partial< | ||||
| PurchaseQCInput & StockInInput & PutawayInput | |||||
| PurchaseQCInput & StockInInput & PutAwayInput | |||||
| > & { | > & { | ||||
| escalationLog? : Partial<EscalationInput> | escalationLog? : Partial<EscalationInput> | ||||
| }; | }; | ||||
| export interface PrintQrCodeForSilRequest { | |||||
| stockInLineId: number; | |||||
| printerId: number; | |||||
| printQty?: number; | |||||
| } | |||||
| export const testFetch = cache(async (id: number) => { | export const testFetch = cache(async (id: number) => { | ||||
| return serverFetchJson<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | return serverFetchJson<PoResult>(`${BASE_API_URL}/po/detail/${id}`, { | ||||
| next: { tags: ["po"] }, | next: { tags: ["po"] }, | ||||
| @@ -217,3 +226,16 @@ export const testing = cache(async (queryParams?: Record<string, any>) => { | |||||
| ); | ); | ||||
| } | } | ||||
| }); | }); | ||||
| export const printQrCodeForSil = cache(async(data: PrintQrCodeForSilRequest) => { | |||||
| const params = convertObjToURLSearchParams(data) | |||||
| return serverFetchWithNoContent(`${BASE_API_URL}/stockInLine/printQrCode?${params}`, | |||||
| { | |||||
| method: "GET", | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| next: { | |||||
| tags: ["printQrCodeForSil"], | |||||
| }, | |||||
| }, | |||||
| ) | |||||
| }) | |||||
| @@ -6,6 +6,7 @@ import { serverFetchJson } from "../../utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "../../../config/api"; | import { BASE_API_URL } from "../../../config/api"; | ||||
| import { Uom } from "../settings/uom"; | import { Uom } from "../settings/uom"; | ||||
| import { RecordsRes } from "../utils"; | import { RecordsRes } from "../utils"; | ||||
| import { PutAwayLine } from "./actions"; | |||||
| export interface PoResult { | export interface PoResult { | ||||
| id: number; | id: number; | ||||
| @@ -82,6 +83,7 @@ export interface StockInLine { | |||||
| dnDate?: number[]; | dnDate?: number[]; | ||||
| stockQty?: number; | stockQty?: number; | ||||
| handlerId?: number; | handlerId?: number; | ||||
| putAwayLines?: PutAwayLine[]; | |||||
| } | } | ||||
| export const fetchPoList = cache(async (queryParams?: Record<string, any>) => { | export const fetchPoList = cache(async (queryParams?: Record<string, any>) => { | ||||
| @@ -0,0 +1,21 @@ | |||||
| import { serverFetchJson } from '@/app/utils/fetchUtil'; | |||||
| import { BASE_API_URL } from '@/config/api'; | |||||
| import { cache } from "react"; | |||||
| import "server-only"; | |||||
| export interface PrinterCombo { | |||||
| id: number; | |||||
| value: number; | |||||
| label?: string; | |||||
| code?: string; | |||||
| name?: string; | |||||
| description?: string; | |||||
| ip?: string; | |||||
| port?: number; | |||||
| } | |||||
| export const fetchPrinterCombo = cache(async () => { | |||||
| return serverFetchJson<PrinterCombo[]>(`${BASE_API_URL}/printers/combo`, { | |||||
| next: { tags: ["qcItems"] }, | |||||
| }) | |||||
| }) | |||||
| @@ -10,8 +10,20 @@ export interface WarehouseResult { | |||||
| description: string; | description: string; | ||||
| } | } | ||||
| export interface WarehouseCombo { | |||||
| id: number; | |||||
| value: number; | |||||
| label: string; | |||||
| } | |||||
| export const fetchWarehouseList = cache(async () => { | export const fetchWarehouseList = cache(async () => { | ||||
| return serverFetchJson<WarehouseResult[]>(`${BASE_API_URL}/warehouse`, { | return serverFetchJson<WarehouseResult[]>(`${BASE_API_URL}/warehouse`, { | ||||
| next: { tags: ["warehouse"] }, | next: { tags: ["warehouse"] }, | ||||
| }); | }); | ||||
| }); | }); | ||||
| export const fetchWarehouseCombo = cache(async () => { | |||||
| return serverFetchJson<WarehouseCombo[]>(`${BASE_API_URL}/warehouse/combo`, { | |||||
| next: { tags: ["warehouseCombo"] }, | |||||
| }); | |||||
| }); | |||||
| @@ -74,6 +74,7 @@ export interface InputDataGridProps<T, V, E> { | |||||
| validateRow: (newRow: GridRowModel<TableRow<V, E>>) => E; | validateRow: (newRow: GridRowModel<TableRow<V, E>>) => E; | ||||
| needAdd?: boolean; | needAdd?: boolean; | ||||
| showRemoveBtn?: boolean; | showRemoveBtn?: boolean; | ||||
| addRowDefaultValue?: Partial<V>; | |||||
| } | } | ||||
| export interface SelectionInputDataGridProps<T, V, E> { | export interface SelectionInputDataGridProps<T, V, E> { | ||||
| @@ -85,6 +86,7 @@ export interface SelectionInputDataGridProps<T, V, E> { | |||||
| validateRow: (newRow: GridRowModel<TableRow<V, E>>) => E; | validateRow: (newRow: GridRowModel<TableRow<V, E>>) => E; | ||||
| needAdd?: boolean; | needAdd?: boolean; | ||||
| showRemoveBtn?: boolean; | showRemoveBtn?: boolean; | ||||
| addRowDefaultValue?: Partial<V>; | |||||
| } | } | ||||
| export type Props<T, V, E> = | export type Props<T, V, E> = | ||||
| @@ -112,6 +114,7 @@ function InputDataGrid<T, V, E>({ | |||||
| validateRow, | validateRow, | ||||
| needAdd, | needAdd, | ||||
| showRemoveBtn = true, | showRemoveBtn = true, | ||||
| addRowDefaultValue = {}, | |||||
| }: Props<T, V, E>) { | }: Props<T, V, E>) { | ||||
| const { | const { | ||||
| t, | t, | ||||
| @@ -126,13 +129,13 @@ function InputDataGrid<T, V, E>({ | |||||
| [], | [], | ||||
| ); | ); | ||||
| const list: TableRow<V, E>[] = getValues(formKey); | const list: TableRow<V, E>[] = getValues(formKey); | ||||
| console.log(list) | |||||
| // console.log(list) | |||||
| const [rows, setRows] = useState<TableRow<V, E>[]>(() => { | const [rows, setRows] = useState<TableRow<V, E>[]>(() => { | ||||
| const list: TableRow<V, E>[] = getValues(formKey); | const list: TableRow<V, E>[] = getValues(formKey); | ||||
| console.log(list) | |||||
| // console.log(list) | |||||
| return list && list.length > 0 ? list : []; | return list && list.length > 0 ? list : []; | ||||
| }); | }); | ||||
| console.log(rows) | |||||
| // console.log(rows) | |||||
| // const originalRows = list && list.length > 0 ? list : []; | // const originalRows = list && list.length > 0 ? list : []; | ||||
| const originalRows = useMemo(() => ( | const originalRows = useMemo(() => ( | ||||
| list && list.length > 0 ? list : [] | list && list.length > 0 ? list : [] | ||||
| @@ -145,7 +148,7 @@ function InputDataGrid<T, V, E>({ | |||||
| const rowModel: GridRowSelectionModel = getValues( | const rowModel: GridRowSelectionModel = getValues( | ||||
| `${formKey}_active`, | `${formKey}_active`, | ||||
| ) as GridRowSelectionModel; | ) as GridRowSelectionModel; | ||||
| console.log(rowModel); | |||||
| // console.log(rowModel); | |||||
| return rowModel; | return rowModel; | ||||
| }); | }); | ||||
| @@ -162,7 +165,7 @@ function InputDataGrid<T, V, E>({ | |||||
| (updateError: ProcessRowUpdateError<T, E>) => { | (updateError: ProcessRowUpdateError<T, E>) => { | ||||
| const errors = updateError.errors; | const errors = updateError.errors; | ||||
| const row = updateError.row; | const row = updateError.row; | ||||
| console.log(errors); | |||||
| // console.log(errors); | |||||
| apiRef.current.updateRows([{ ...row, _error: errors }]); | apiRef.current.updateRows([{ ...row, _error: errors }]); | ||||
| }, | }, | ||||
| [apiRef], | [apiRef], | ||||
| @@ -176,7 +179,7 @@ function InputDataGrid<T, V, E>({ | |||||
| ///////////////// | ///////////////// | ||||
| // validation here | // validation here | ||||
| const errors = validateRow(newRow); | const errors = validateRow(newRow); | ||||
| console.log(newRow); | |||||
| // console.log(newRow); | |||||
| if (errors) { | if (errors) { | ||||
| throw new ProcessRowUpdateError( | throw new ProcessRowUpdateError( | ||||
| originalRow, | originalRow, | ||||
| @@ -189,7 +192,6 @@ function InputDataGrid<T, V, E>({ | |||||
| const rowToSave = { | const rowToSave = { | ||||
| ...updatedRow, | ...updatedRow, | ||||
| } as TableRow<V, E>; /// test | } as TableRow<V, E>; /// test | ||||
| console.log(rowToSave); | |||||
| setRows((rw) => | setRows((rw) => | ||||
| rw.map((r) => (getRowId(r) === getRowId(originalRow) ? rowToSave : r)), | rw.map((r) => (getRowId(r) === getRowId(originalRow) ? rowToSave : r)), | ||||
| ); | ); | ||||
| @@ -198,8 +200,8 @@ function InputDataGrid<T, V, E>({ | |||||
| [validateRow, getRowId], | [validateRow, getRowId], | ||||
| ); | ); | ||||
| const addRow = useCallback(() => { | |||||
| const newEntry = { id: Date.now(), _isNew: true } as TableRow<V, E>; | |||||
| const addRow = useCallback((addRowDefaultValue: Partial<V>) => { | |||||
| const newEntry = { ...addRowDefaultValue, id: Date.now(), _isNew: true } as TableRow<V, E>; | |||||
| setRows((prev) => [...prev, newEntry]); | setRows((prev) => [...prev, newEntry]); | ||||
| setRowModesModel((model) => ({ | setRowModesModel((model) => ({ | ||||
| ...model, | ...model, | ||||
| @@ -290,7 +292,6 @@ function InputDataGrid<T, V, E>({ | |||||
| // sync useForm | // sync useForm | ||||
| useEffect(() => { | useEffect(() => { | ||||
| // console.log(formKey) | // console.log(formKey) | ||||
| // console.log(rows) | |||||
| setValue(formKey, rows); | setValue(formKey, rows); | ||||
| }, [formKey, rows, setValue]); | }, [formKey, rows, setValue]); | ||||
| @@ -300,7 +301,7 @@ function InputDataGrid<T, V, E>({ | |||||
| disableRipple | disableRipple | ||||
| variant="outlined" | variant="outlined" | ||||
| startIcon={<Add />} | startIcon={<Add />} | ||||
| onClick={addRow} | |||||
| onClick={() => addRow(addRowDefaultValue)} | |||||
| size="small" | size="small" | ||||
| > | > | ||||
| 新增 | 新增 | ||||
| @@ -1,6 +1,6 @@ | |||||
| "use client"; | "use client"; | ||||
| import { PurchaseQcResult, PutawayInput, PutawayLine } from "@/app/api/po/actions"; | |||||
| import { PurchaseQcResult, PutAwayInput, PutAwayLine } from "@/app/api/po/actions"; | |||||
| import { | import { | ||||
| Autocomplete, | Autocomplete, | ||||
| Box, | Box, | ||||
| @@ -61,11 +61,11 @@ interface Props { | |||||
| } | } | ||||
| type EntryError = | type EntryError = | ||||
| | { | | { | ||||
| [field in keyof PutawayLine]?: string; | |||||
| [field in keyof PutAwayLine]?: string; | |||||
| } | } | ||||
| | undefined; | | undefined; | ||||
| type PutawayRow = TableRow<Partial<PutawayLine>, EntryError>; | |||||
| type PutawayRow = TableRow<Partial<PutAwayLine>, EntryError>; | |||||
| const style = { | const style = { | ||||
| position: "absolute", | position: "absolute", | ||||
| @@ -93,7 +93,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| resetField, | resetField, | ||||
| setError, | setError, | ||||
| clearErrors, | clearErrors, | ||||
| } = useFormContext<PutawayInput>(); | |||||
| } = useFormContext<PutAwayInput>(); | |||||
| console.log(itemDetail); | console.log(itemDetail); | ||||
| // const [recordQty, setRecordQty] = useState(0); | // const [recordQty, setRecordQty] = useState(0); | ||||
| const [warehouseId, setWarehouseId] = useState(itemDetail.defaultWarehouseId); | const [warehouseId, setWarehouseId] = useState(itemDetail.defaultWarehouseId); | ||||
| @@ -143,7 +143,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| }, | }, | ||||
| [], | [], | ||||
| ); | ); | ||||
| console.log(watch("putawayLine")) | |||||
| console.log(watch("putAwayLines")) | |||||
| // const accQty = watch("acceptedQty"); | // const accQty = watch("acceptedQty"); | ||||
| // const validateForm = useCallback(() => { | // const validateForm = useCallback(() => { | ||||
| // console.log(accQty); | // console.log(accQty); | ||||
| @@ -492,10 +492,10 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| style={{ display: "flex", justifyContent: "center" }} | style={{ display: "flex", justifyContent: "center" }} | ||||
| > | > | ||||
| {/* <QrCode content={qrContent} sx={{ width: 200, height: 200 }} /> */} | {/* <QrCode content={qrContent} sx={{ width: 200, height: 200 }} /> */} | ||||
| <InputDataGrid<PutawayInput, PutawayLine, EntryError> | |||||
| <InputDataGrid<PutAwayInput, PutAwayLine, EntryError> | |||||
| apiRef={apiRef} | apiRef={apiRef} | ||||
| checkboxSelection={false} | checkboxSelection={false} | ||||
| _formKey={"putawayLine"} | |||||
| _formKey={"putAwayLines"} | |||||
| columns={columns} | columns={columns} | ||||
| validateRow={validation} | validateRow={validation} | ||||
| needAdd={true} | needAdd={true} | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { PutawayLine } from "@/app/api/po/actions" | |||||
| import { PutAwayLine } from "@/app/api/po/actions" | |||||
| export interface QcData { | export interface QcData { | ||||
| id: number, | id: number, | ||||
| @@ -67,7 +67,7 @@ export const dummyEscalationHistory: EscalationData[] = [ | |||||
| }, | }, | ||||
| ] | ] | ||||
| export const dummyPutawayLine: PutawayLine[] = [ | |||||
| export const dummyPutawayLine: PutAwayLine[] = [ | |||||
| { | { | ||||
| id: 1, | id: 1, | ||||
| qty: 100, | qty: 100, | ||||
| @@ -80,7 +80,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| const formProps = useForm<any>({ | const formProps = useForm<any>({ | ||||
| defaultValues: { | defaultValues: { | ||||
| ...itemDetail, | ...itemDetail, | ||||
| putawayLine: dummyPutawayLine, | |||||
| putAwayLine: dummyPutawayLine, | |||||
| // receiptDate: itemDetail.receiptDate || dayjs().add(-1, "month").format(INPUT_DATE_FORMAT), | // receiptDate: itemDetail.receiptDate || dayjs().add(-1, "month").format(INPUT_DATE_FORMAT), | ||||
| // warehouseId: itemDetail.defaultWarehouseId || 0 | // warehouseId: itemDetail.defaultWarehouseId || 0 | ||||
| }, | }, | ||||
| @@ -79,6 +79,7 @@ import { DatePicker, LocalizationProvider, zhHK } from "@mui/x-date-pickers"; | |||||
| import { debounce } from "lodash"; | import { debounce } from "lodash"; | ||||
| import LoadingComponent from "../General/LoadingComponent"; | import LoadingComponent from "../General/LoadingComponent"; | ||||
| import { getMailTemplateForStockInLine } from "@/app/api/mailTemplate/actions"; | import { getMailTemplateForStockInLine } from "@/app/api/mailTemplate/actions"; | ||||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||||
| //import { useRouter } from "next/navigation"; | //import { useRouter } from "next/navigation"; | ||||
| @@ -86,6 +87,7 @@ type Props = { | |||||
| po: PoResult; | po: PoResult; | ||||
| qc: QcItemWithChecks[]; | qc: QcItemWithChecks[]; | ||||
| warehouse: WarehouseResult[]; | warehouse: WarehouseResult[]; | ||||
| printerCombo: PrinterCombo[]; | |||||
| }; | }; | ||||
| type EntryError = | type EntryError = | ||||
| @@ -188,7 +190,7 @@ interface PolInputResult { | |||||
| dnQty: number, | dnQty: number, | ||||
| } | } | ||||
| const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => { | |||||
| const PoDetail: React.FC<Props> = ({ po, qc, warehouse, printerCombo }) => { | |||||
| const cameras = useContext(CameraContext); | const cameras = useContext(CameraContext); | ||||
| // console.log(cameras); | // console.log(cameras); | ||||
| const { t } = useTranslation("purchaseOrder"); | const { t } = useTranslation("purchaseOrder"); | ||||
| @@ -858,6 +860,7 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => { | |||||
| warehouse={warehouse} | warehouse={warehouse} | ||||
| fetchPoDetail={fetchPoDetail} | fetchPoDetail={fetchPoDetail} | ||||
| handleMailTemplateForStockInLine={handleMailTemplateForStockInLine} | handleMailTemplateForStockInLine={handleMailTemplateForStockInLine} | ||||
| printerCombo={printerCombo} | |||||
| /> | /> | ||||
| </Box> | </Box> | ||||
| </TableCell> | </TableCell> | ||||
| @@ -11,6 +11,7 @@ import { QcItemWithChecks } from "@/app/api/qc"; | |||||
| import { fetchWarehouseList } from "@/app/api/warehouse"; | import { fetchWarehouseList } from "@/app/api/warehouse"; | ||||
| import { fetchQcItemCheck } from "@/app/api/qc/actions"; | import { fetchQcItemCheck } from "@/app/api/qc/actions"; | ||||
| import { fetchEscalationCombo } from "@/app/api/user"; | import { fetchEscalationCombo } from "@/app/api/user"; | ||||
| import { fetchPrinterCombo } from "@/app/api/settings/printer"; | |||||
| interface SubComponents { | interface SubComponents { | ||||
| Loading: typeof PoDetailLoading; | Loading: typeof PoDetailLoading; | ||||
| @@ -25,16 +26,18 @@ const PoDetailWrapper: React.FC<Props> & SubComponents = async ({ id }) => { | |||||
| poWithStockInLine, | poWithStockInLine, | ||||
| warehouse, | warehouse, | ||||
| qc, | qc, | ||||
| escalationCombo | |||||
| escalationCombo, | |||||
| printerCombo, | |||||
| ] = await Promise.all([ | ] = await Promise.all([ | ||||
| fetchPoWithStockInLines(id), | fetchPoWithStockInLines(id), | ||||
| fetchWarehouseList(), | fetchWarehouseList(), | ||||
| fetchQcItemCheck(), | fetchQcItemCheck(), | ||||
| fetchEscalationCombo(), | fetchEscalationCombo(), | ||||
| fetchPrinterCombo() | |||||
| ]); | ]); | ||||
| // const poWithStockInLine = await fetchPoWithStockInLines(id) | // const poWithStockInLine = await fetchPoWithStockInLines(id) | ||||
| return <PoDetail po={poWithStockInLine} qc={qc} warehouse={warehouse} />; | |||||
| return <PoDetail po={poWithStockInLine} qc={qc} warehouse={warehouse} printerCombo={printerCombo} />; | |||||
| }; | }; | ||||
| PoDetailWrapper.Loading = PoDetailLoading; | PoDetailWrapper.Loading = PoDetailLoading; | ||||
| @@ -62,6 +62,7 @@ import { useSession } from "next-auth/react"; | |||||
| // import { SessionWithTokens } from "src/config/authConfig"; | // import { SessionWithTokens } from "src/config/authConfig"; | ||||
| import PoQcStockInModalVer2 from "./QcStockInModalVer2"; | import PoQcStockInModalVer2 from "./QcStockInModalVer2"; | ||||
| import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | ||||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||||
| import { EscalationResult } from "@/app/api/escalation"; | import { EscalationResult } from "@/app/api/escalation"; | ||||
| import { fetchEscalationLogsByStockInLines } from "@/app/api/escalation/actions"; | import { fetchEscalationLogsByStockInLines } from "@/app/api/escalation/actions"; | ||||
| import { SessionWithTokens } from "@/config/authConfig"; | import { SessionWithTokens } from "@/config/authConfig"; | ||||
| @@ -80,6 +81,7 @@ interface Props { | |||||
| warehouse: WarehouseResult[]; | warehouse: WarehouseResult[]; | ||||
| fetchPoDetail: (poId: string) => void; | fetchPoDetail: (poId: string) => void; | ||||
| handleMailTemplateForStockInLine: (stockInLineId: number) => void; | handleMailTemplateForStockInLine: (stockInLineId: number) => void; | ||||
| printerCombo: PrinterCombo[]; | |||||
| } | } | ||||
| export type StockInLineEntryError = { | export type StockInLineEntryError = { | ||||
| @@ -119,7 +121,8 @@ function PoInputGrid({ | |||||
| stockInLine, | stockInLine, | ||||
| warehouse, | warehouse, | ||||
| fetchPoDetail, | fetchPoDetail, | ||||
| handleMailTemplateForStockInLine | |||||
| handleMailTemplateForStockInLine, | |||||
| printerCombo | |||||
| }: Props) { | }: Props) { | ||||
| console.log(itemDetail); | console.log(itemDetail); | ||||
| const { t } = useTranslation("purchaseOrder"); | const { t } = useTranslation("purchaseOrder"); | ||||
| @@ -301,7 +304,7 @@ const closeNewModal = useCallback(() => { | |||||
| const handleNewQC = useCallback( | const handleNewQC = useCallback( | ||||
| (id: GridRowId, params: any) => async() => { | (id: GridRowId, params: any) => async() => { | ||||
| // console.log(id) | // console.log(id) | ||||
| // console.log(params) | |||||
| console.log("params", params.row) | |||||
| // setBtnIsLoading(true); | // setBtnIsLoading(true); | ||||
| setRowModesModel((prev) => ({ | setRowModesModel((prev) => ({ | ||||
| ...prev, | ...prev, | ||||
| @@ -939,6 +942,7 @@ const closeNewModal = useCallback(() => { | |||||
| onClose={closeNewModal} | onClose={closeNewModal} | ||||
| itemDetail={modalInfo} | itemDetail={modalInfo} | ||||
| handleMailTemplateForStockInLine={handleMailTemplateForStockInLine} | handleMailTemplateForStockInLine={handleMailTemplateForStockInLine} | ||||
| printerCombo={printerCombo} | |||||
| /> | /> | ||||
| </> | </> | ||||
| ) | ) | ||||
| @@ -28,7 +28,7 @@ import { useSearchParams } from "next/navigation"; | |||||
| 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"; | |||||
| import PutAwayForm from "./PutAwayForm"; | |||||
| import { | import { | ||||
| INPUT_DATE_FORMAT, | INPUT_DATE_FORMAT, | ||||
| stockInLineStatusMap, | stockInLineStatusMap, | ||||
| @@ -437,7 +437,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||||
| /> | /> | ||||
| )} | )} | ||||
| {itemDetail !== undefined && type === "putaway" && ( | {itemDetail !== undefined && type === "putaway" && ( | ||||
| <PutawayForm | |||||
| <PutAwayForm | |||||
| itemDetail={itemDetail} | itemDetail={itemDetail} | ||||
| warehouse={warehouse!} | warehouse={warehouse!} | ||||
| disabled={!renderSubmitButton} | disabled={!renderSubmitButton} | ||||
| @@ -1,6 +1,6 @@ | |||||
| "use client"; | "use client"; | ||||
| import { PurchaseQcResult, PutawayInput, PutawayLine } from "@/app/api/po/actions"; | |||||
| import { PurchaseQcResult, PutAwayInput, PutAwayLine } from "@/app/api/po/actions"; | |||||
| import { | import { | ||||
| Autocomplete, | Autocomplete, | ||||
| Box, | Box, | ||||
| @@ -50,7 +50,8 @@ import { QrCodeInfo } from "@/app/api/qrcode"; | |||||
| import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider"; | import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider"; | ||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import arraySupport from "dayjs/plugin/arraySupport"; | import arraySupport from "dayjs/plugin/arraySupport"; | ||||
| import { dummyPutawayLine } from "./dummyQcTemplate"; | |||||
| import { dummyPutAwayLine } from "./dummyQcTemplate"; | |||||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||||
| dayjs.extend(arraySupport); | dayjs.extend(arraySupport); | ||||
| interface Props { | interface Props { | ||||
| @@ -58,14 +59,15 @@ interface Props { | |||||
| warehouse: WarehouseResult[]; | warehouse: WarehouseResult[]; | ||||
| disabled: boolean; | disabled: boolean; | ||||
| // qc: QcItemWithChecks[]; | // qc: QcItemWithChecks[]; | ||||
| printerCombo: PrinterCombo[]; | |||||
| } | } | ||||
| type EntryError = | type EntryError = | ||||
| | { | | { | ||||
| [field in keyof PutawayLine]?: string; | |||||
| [field in keyof PutAwayLine]?: string; | |||||
| } | } | ||||
| | undefined; | | undefined; | ||||
| type PutawayRow = TableRow<Partial<PutawayLine>, EntryError>; | |||||
| type PutAwayRow = TableRow<Partial<PutAwayLine>, EntryError>; | |||||
| const style = { | const style = { | ||||
| position: "absolute", | position: "absolute", | ||||
| @@ -79,7 +81,7 @@ const style = { | |||||
| width: "auto", | width: "auto", | ||||
| }; | }; | ||||
| const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, printerCombo }) => { | |||||
| const { t } = useTranslation("purchaseOrder"); | const { t } = useTranslation("purchaseOrder"); | ||||
| const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
| const { | const { | ||||
| @@ -93,7 +95,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| resetField, | resetField, | ||||
| setError, | setError, | ||||
| clearErrors, | clearErrors, | ||||
| } = useFormContext<PutawayInput>(); | |||||
| } = useFormContext<PutAwayInput>(); | |||||
| console.log(itemDetail); | console.log(itemDetail); | ||||
| // const [recordQty, setRecordQty] = useState(0); | // const [recordQty, setRecordQty] = useState(0); | ||||
| const [warehouseId, setWarehouseId] = useState(itemDetail.defaultWarehouseId); | const [warehouseId, setWarehouseId] = useState(itemDetail.defaultWarehouseId); | ||||
| @@ -143,7 +145,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| }, | }, | ||||
| [], | [], | ||||
| ); | ); | ||||
| console.log(watch("putawayLine")) | |||||
| console.log(watch("putAwayLines")) | |||||
| // const accQty = watch("acceptedQty"); | // const accQty = watch("acceptedQty"); | ||||
| // const validateForm = useCallback(() => { | // const validateForm = useCallback(() => { | ||||
| // console.log(accQty); | // console.log(accQty); | ||||
| @@ -274,6 +276,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| field: "qty", | field: "qty", | ||||
| headerName: t("qty"), | headerName: t("qty"), | ||||
| flex: 1, | flex: 1, | ||||
| editable: true, | |||||
| // renderCell(params) { | // renderCell(params) { | ||||
| // return <>100</> | // return <>100</> | ||||
| // }, | // }, | ||||
| @@ -282,6 +285,33 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| field: "warehouse", | field: "warehouse", | ||||
| headerName: t("warehouse"), | headerName: t("warehouse"), | ||||
| flex: 1, | flex: 1, | ||||
| editable: true, | |||||
| renderEditCell: (params) => { | |||||
| const index = params.api.getRowIndexRelativeToVisibleRows(params.row.id) | |||||
| // console.log(index) | |||||
| // console.log(watch(`putAwayLines.${index}.warehouse`)) | |||||
| return <Autocomplete | |||||
| fullWidth | |||||
| disableClearable | |||||
| options={options} | |||||
| // defaultValue={options.find((o) => o.value === itemDetail.defaultWarehouseId)} | |||||
| // value={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))} | |||||
| defaultValue={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))} | |||||
| onChange={(event, value) => { | |||||
| params.api.setEditCellValue({ id: params.id, field: params.field, value: options.find((o) => o.value === value.value)?.label ?? ""}) | |||||
| params.api.setEditCellValue({ id: params.id, field: "warehouseId", value: value.value}) | |||||
| // setValue(`putAwayLines.${index}.warehouseId`, value.value) | |||||
| // setValue(`putAwayLines.${index}.warehouse`, options.find((o) => o.value === value.value)?.label ?? "") | |||||
| }} | |||||
| renderInput={(params) => ( | |||||
| <TextField | |||||
| {...params} | |||||
| variant="outlined" | |||||
| // label={t("Warehouse")} | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| } | |||||
| // renderCell(params) { | // renderCell(params) { | ||||
| // return <>{filteredWarehouse[0].name}</> | // return <>{filteredWarehouse[0].name}</> | ||||
| // }, | // }, | ||||
| @@ -290,6 +320,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| field: "printQty", | field: "printQty", | ||||
| headerName: t("printQty"), | headerName: t("printQty"), | ||||
| flex: 1, | flex: 1, | ||||
| editable: true, | |||||
| // renderCell(params) { | // renderCell(params) { | ||||
| // return <>100</> | // return <>100</> | ||||
| // }, | // }, | ||||
| @@ -297,7 +328,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| ], []) | ], []) | ||||
| const validation = useCallback( | const validation = useCallback( | ||||
| (newRow: GridRowModel<PutawayRow>): EntryError => { | |||||
| (newRow: GridRowModel<PutAwayRow>): EntryError => { | |||||
| const error: EntryError = {}; | const error: EntryError = {}; | ||||
| const { qty, warehouseId, printQty } = newRow; | const { qty, warehouseId, printQty } = newRow; | ||||
| @@ -306,6 +337,13 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| [], | [], | ||||
| ); | ); | ||||
| const addRowDefaultValue = useMemo(() => { | |||||
| const defaultMaxQty = watch("acceptedQty") - watch("putAwayLines").reduce((acc, cur) => acc + cur.qty, 0) | |||||
| const defaultWarehouseId = itemDetail.defaultWarehouseId ?? 1 | |||||
| const defaultWarehouse = options.find((o) => o.value === defaultWarehouseId)?.label | |||||
| return {qty: defaultMaxQty, warehouseId: defaultWarehouseId, warehouse: defaultWarehouse, printQty: 1 } as Partial<PutAwayLine> | |||||
| }, []) | |||||
| 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}> | ||||
| @@ -493,14 +531,15 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| style={{ display: "flex", justifyContent: "center" }} | style={{ display: "flex", justifyContent: "center" }} | ||||
| > | > | ||||
| {/* <QrCode content={qrContent} sx={{ width: 200, height: 200 }} /> */} | {/* <QrCode content={qrContent} sx={{ width: 200, height: 200 }} /> */} | ||||
| <InputDataGrid<PutawayInput, PutawayLine, EntryError> | |||||
| <InputDataGrid<PutAwayInput, PutAwayLine, EntryError> | |||||
| apiRef={apiRef} | apiRef={apiRef} | ||||
| checkboxSelection={false} | checkboxSelection={false} | ||||
| _formKey={"putawayLine"} | |||||
| _formKey={"putAwayLines"} | |||||
| columns={columns} | columns={columns} | ||||
| validateRow={validation} | validateRow={validation} | ||||
| needAdd={true} | needAdd={true} | ||||
| showRemoveBtn={false} | showRemoveBtn={false} | ||||
| addRowDefaultValue={addRowDefaultValue} | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| @@ -525,4 +564,4 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => { | |||||
| </Grid> | </Grid> | ||||
| ); | ); | ||||
| }; | }; | ||||
| export default PutawayForm; | |||||
| export default PutAwayForm; | |||||
| @@ -1,14 +1,16 @@ | |||||
| "use client"; | "use client"; | ||||
| import { StockInLine } from "@/app/api/po"; | import { StockInLine } from "@/app/api/po"; | ||||
| import { ModalFormInput, PurchaseQcResult, StockInLineEntry, updateStockInLine, PurchaseQCInput } from "@/app/api/po/actions"; | |||||
| import { ModalFormInput, PurchaseQcResult, StockInLineEntry, updateStockInLine, PurchaseQCInput, printQrCodeForSil, PrintQrCodeForSilRequest } from "@/app/api/po/actions"; | |||||
| import { QcItemWithChecks, QcData } from "@/app/api/qc"; | import { QcItemWithChecks, QcData } from "@/app/api/qc"; | ||||
| import { | import { | ||||
| Autocomplete, | |||||
| Box, | Box, | ||||
| Button, | Button, | ||||
| Grid, | Grid, | ||||
| Modal, | Modal, | ||||
| ModalProps, | ModalProps, | ||||
| Stack, | Stack, | ||||
| TextField, | |||||
| Typography, | Typography, | ||||
| } from "@mui/material"; | } from "@mui/material"; | ||||
| import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from "react"; | import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from "react"; | ||||
| @@ -20,10 +22,16 @@ import StockInFormVer2 from "./StockInFormVer2"; | |||||
| import PutawayForm from "./PutawayForm"; | import PutawayForm from "./PutawayForm"; | ||||
| import QcComponent from "./QcComponent"; | import QcComponent from "./QcComponent"; | ||||
| import { dummyPutawayLine, dummyQCData } from "./dummyQcTemplate"; | import { dummyPutawayLine, dummyQCData } from "./dummyQcTemplate"; | ||||
| import QcFormVer2 from "./QcFormVer2"; | |||||
| import PutAwayForm from "./PutAwayForm"; | |||||
| import { dummyPutAwayLine, dummyQCData } from "./dummyQcTemplate"; | |||||
| import { useGridApiRef } from "@mui/x-data-grid"; | import { useGridApiRef } from "@mui/x-data-grid"; | ||||
| import {submitDialogWithWarning} from "../Swal/CustomAlerts"; | import {submitDialogWithWarning} from "../Swal/CustomAlerts"; | ||||
| import { arrayToDateString, arrayToInputDateString, dayjsToInputDateString, INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||||
| import { INPUT_DATE_FORMAT, arrayToDateString, arrayToInputDateString, dayjsToInputDateString } from "@/app/utils/formatUtil"; | |||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import { fetchPoQrcode } from "@/app/api/pdf/actions"; | |||||
| import { downloadFile } from "@/app/utils/commonUtil"; | |||||
| import { PrinterCombo } from "@/app/api/settings/printer"; | |||||
| import { watch } from "fs"; | import { watch } from "fs"; | ||||
| import { EscalationResult } from "@/app/api/escalation"; | import { EscalationResult } from "@/app/api/escalation"; | ||||
| import { SessionWithTokens } from "@/config/authConfig"; | import { SessionWithTokens } from "@/config/authConfig"; | ||||
| @@ -60,6 +68,7 @@ interface CommonProps extends Omit<ModalProps, "children"> { | |||||
| warehouse?: any[]; | warehouse?: any[]; | ||||
| // type: "qc" | "stockIn" | "escalation" | "putaway" | "reject"; | // type: "qc" | "stockIn" | "escalation" | "putaway" | "reject"; | ||||
| handleMailTemplateForStockInLine: (stockInLineId: number) => void; | handleMailTemplateForStockInLine: (stockInLineId: number) => void; | ||||
| printerCombo: PrinterCombo[]; | |||||
| onClose: () => void; | onClose: () => void; | ||||
| } | } | ||||
| interface Props extends CommonProps { | interface Props extends CommonProps { | ||||
| @@ -78,19 +87,25 @@ const PoQcStockInModalVer2: React.FC<Props> = ({ | |||||
| qc, | qc, | ||||
| warehouse, | warehouse, | ||||
| handleMailTemplateForStockInLine, | handleMailTemplateForStockInLine, | ||||
| printerCombo | |||||
| }) => { | }) => { | ||||
| const { | const { | ||||
| t, | t, | ||||
| i18n: { language }, | i18n: { language }, | ||||
| } = useTranslation("purchaseOrder"); | } = useTranslation("purchaseOrder"); | ||||
| // Select Printer | |||||
| const [selectedPrinter, setSelectedPrinter] = useState(printerCombo[0]) | |||||
| const defaultNewValue = useMemo(() => { | const defaultNewValue = useMemo(() => { | ||||
| return ( | return ( | ||||
| { | { | ||||
| ...itemDetail, | ...itemDetail, | ||||
| status: itemDetail.status ?? "pending", | status: itemDetail.status ?? "pending", | ||||
| dnDate: arrayToInputDateString(itemDetail.dnDate)?? dayjsToInputDateString(dayjs()), | dnDate: arrayToInputDateString(itemDetail.dnDate)?? dayjsToInputDateString(dayjs()), | ||||
| putawayLine: dummyPutawayLine, | |||||
| // putAwayLines: dummyPutAwayLine, | |||||
| // putAwayLines: itemDetail.putAwayLines.map((line) => (return {...line, printQty: 1})) ?? [], | |||||
| putAwayLines: itemDetail.putAwayLines?.map((line) => ({...line, printQty: 1})) ?? [], | |||||
| qcResult: (itemDetail.qcResult && itemDetail.qcResult?.length > 0) ? itemDetail.qcResult : [],//[...dummyQCData], | qcResult: (itemDetail.qcResult && itemDetail.qcResult?.length > 0) ? itemDetail.qcResult : [],//[...dummyQCData], | ||||
| escResult: (itemDetail.escResult && itemDetail.escResult?.length > 0) ? itemDetail.escResult : [], | escResult: (itemDetail.escResult && itemDetail.escResult?.length > 0) ? itemDetail.escResult : [], | ||||
| receiptDate: itemDetail.receiptDate ?? dayjs().add(0, "month").format(INPUT_DATE_FORMAT), | receiptDate: itemDetail.receiptDate ?? dayjs().add(0, "month").format(INPUT_DATE_FORMAT), | ||||
| @@ -123,6 +138,17 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| } else return false; | } else return false; | ||||
| }; | }; | ||||
| useEffect(() => { | |||||
| formProps.reset({ | |||||
| ...itemDetail, | |||||
| dnDate: dayjsToInputDateString(dayjs()), | |||||
| // putAwayLines: dummyPutAwayLine, | |||||
| putAwayLines: itemDetail.putAwayLines?.map((line) => ({...line, printQty: 1})) ?? [], | |||||
| }) | |||||
| setOpenPutaway(isPutaway); | |||||
| }, [open, itemDetail]) | |||||
| const [viewOnly, setViewOnly] = useState(false); | const [viewOnly, setViewOnly] = useState(false); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| if (itemDetail && itemDetail.status) { | if (itemDetail && itemDetail.status) { | ||||
| @@ -248,7 +274,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| if (validationErrors.length > 0) { | if (validationErrors.length > 0) { | ||||
| console.error("QC Validation failed:", validationErrors); | console.error("QC Validation failed:", validationErrors); | ||||
| alert(`未完成品檢: ${validationErrors}`); | |||||
| alert(`未完成品檢: ${validationErrors}`); | |||||
| return; | return; | ||||
| } | } | ||||
| @@ -275,7 +301,6 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| // const qcData = data; | // const qcData = data; | ||||
| console.log("QC Data for submission:", qcData); | console.log("QC Data for submission:", qcData); | ||||
| if (data.qcDecision == 3) { // Escalate | if (data.qcDecision == 3) { // Escalate | ||||
| const escalationLog = { | const escalationLog = { | ||||
| type : "qc", | type : "qc", | ||||
| @@ -286,12 +311,10 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| } | } | ||||
| console.log("ESCALATION RESULT", escalationLog); | console.log("ESCALATION RESULT", escalationLog); | ||||
| await postStockInLine({...qcData, escalationLog}); | await postStockInLine({...qcData, escalationLog}); | ||||
| } else { | } else { | ||||
| await postStockInLine(qcData); | await postStockInLine(qcData); | ||||
| } | } | ||||
| if (qcData.qcAccept) { | if (qcData.qcAccept) { | ||||
| // submitDialogWithWarning(onOpenPutaway, t, {title:"Save success, confirm to proceed?", | // submitDialogWithWarning(onOpenPutaway, t, {title:"Save success, confirm to proceed?", | ||||
| // confirmButtonText: t("confirm putaway"), html: ""}); | // confirmButtonText: t("confirm putaway"), html: ""}); | ||||
| @@ -312,7 +335,6 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| console.log("Submitting", submitData); | console.log("Submitting", submitData); | ||||
| const res = await updateStockInLine(submitData); | const res = await updateStockInLine(submitData); | ||||
| console.log("Result ", res); | |||||
| return res; | return res; | ||||
| },[itemDetail]) | },[itemDetail]) | ||||
| @@ -357,13 +379,16 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| expiryDate : arrayToInputDateString(data.expiryDate), | expiryDate : arrayToInputDateString(data.expiryDate), | ||||
| receiptDate : arrayToInputDateString(data.receiptDate), | receiptDate : arrayToInputDateString(data.receiptDate), | ||||
| // for putaway data | |||||
| inventoryLotLines: data.putAwayLines?.filter((line) => Boolean(line._isNew)) | |||||
| // Add other putaway specific fields | // Add other putaway specific fields | ||||
| } as ModalFormInput; | } as ModalFormInput; | ||||
| console.log("Putaway Data:", putawayData); | console.log("Putaway Data:", putawayData); | ||||
| // Handle putaway submission logic here | // Handle putaway submission logic here | ||||
| const res = await postStockInLine(putawayData); | const res = await postStockInLine(putawayData); | ||||
| console.log("Result ", res); | |||||
| console.log("result ", res); | |||||
| // Close modal after successful putaway | // Close modal after successful putaway | ||||
| closeHandler({}, "backdropClick"); | closeHandler({}, "backdropClick"); | ||||
| @@ -371,11 +396,32 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| [closeHandler], | [closeHandler], | ||||
| ); | ); | ||||
| // Print handler | // Print handler | ||||
| const onPrint = useCallback(() => { | |||||
| console.log("Print putaway documents"); | |||||
| const [isPrinting, setIsPrinting] = useState(false) | |||||
| const handlePrint = useCallback(async () => { | |||||
| // console.log("Print putaway documents"); | |||||
| console.log("%c data", "background: white; color: red", formProps.watch("putAwayLines")); | |||||
| // Handle print logic here | // Handle print logic here | ||||
| window.print(); | |||||
| }, []); | |||||
| // window.print(); | |||||
| // const postData = { stockInLineIds: [itemDetail.id]}; | |||||
| // const response = await fetchPoQrcode(postData); | |||||
| // if (response) { | |||||
| // downloadFile(new Uint8Array(response.blobValue), response.filename) | |||||
| // } | |||||
| try { | |||||
| setIsPrinting(() => true) | |||||
| const data: PrintQrCodeForSilRequest = { | |||||
| stockInLineId: itemDetail.id, | |||||
| printerId: selectedPrinter.id, | |||||
| printQty: formProps.watch("putAwayLines")?.reduce((acc, cur) => acc + cur.printQty, 0) | |||||
| } | |||||
| const response = await printQrCodeForSil(data); | |||||
| if (response) { | |||||
| console.log(response) | |||||
| } | |||||
| } finally { | |||||
| setIsPrinting(() => false) | |||||
| } | |||||
| }, [itemDetail.id]); | |||||
| const acceptQty = formProps.watch("acceptedQty") | const acceptQty = formProps.watch("acceptedQty") | ||||
| @@ -395,7 +441,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| console.log(qcItems) | console.log(qcItems) | ||||
| // checkQcIsPassed(qcItems) | // checkQcIsPassed(qcItems) | ||||
| }, [qcItems, checkQcIsPassed]) | }, [qcItems, checkQcIsPassed]) | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <FormProvider {...formProps}> | <FormProvider {...formProps}> | ||||
| @@ -410,26 +456,44 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||||
| marginRight: 3, | marginRight: 3, | ||||
| }} | }} | ||||
| > | > | ||||
| {openPutaway ? ( | |||||
| {openPutaway ? ( | |||||
| <Box | <Box | ||||
| component="form" | component="form" | ||||
| onSubmit={formProps.handleSubmit(onSubmitPutaway)} | onSubmit={formProps.handleSubmit(onSubmitPutaway)} | ||||
| > | > | ||||
| <PutawayForm | |||||
| <PutAwayForm | |||||
| printerCombo={printerCombo} | |||||
| itemDetail={itemDetail} | itemDetail={itemDetail} | ||||
| warehouse={warehouse!} | warehouse={warehouse!} | ||||
| disabled={viewOnly} | disabled={viewOnly} | ||||
| /> | /> | ||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | <Stack direction="row" justifyContent="flex-end" gap={1}> | ||||
| <Autocomplete | |||||
| disableClearable | |||||
| options={printerCombo} | |||||
| defaultValue={selectedPrinter} | |||||
| onChange={(event, value) => { | |||||
| setSelectedPrinter(value) | |||||
| }} | |||||
| renderInput={(params) => ( | |||||
| <TextField | |||||
| {...params} | |||||
| variant="outlined" | |||||
| label={t("Printer")} | |||||
| sx={{ width: 300}} | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| <Button | <Button | ||||
| id="printButton" | id="printButton" | ||||
| type="button" | type="button" | ||||
| variant="contained" | variant="contained" | ||||
| color="primary" | color="primary" | ||||
| sx={{ mt: 1 }} | sx={{ mt: 1 }} | ||||
| onClick={onPrint} | |||||
| onClick={handlePrint} | |||||
| disabled={isPrinting} | |||||
| > | > | ||||
| {t("print")} | |||||
| {isPrinting ? t("Printing") : t("print")} | |||||
| </Button> | </Button> | ||||
| <Button | <Button | ||||
| id="putawaySubmit" | id="putawaySubmit" | ||||
| @@ -20,7 +20,7 @@ import { | |||||
| StockInLineEntry, | StockInLineEntry, | ||||
| updateStockInLine, | updateStockInLine, | ||||
| } from "@/app/api/po/actions"; | } from "@/app/api/po/actions"; | ||||
| import PutawayForm from "./PutawayForm"; | |||||
| import PutAwayForm from "./PutAwayForm"; | |||||
| import { StockInLine } from "@/app/api/po"; | import { StockInLine } from "@/app/api/po"; | ||||
| import { WarehouseResult } from "@/app/api/warehouse"; | import { WarehouseResult } from "@/app/api/warehouse"; | ||||
| import { QrCodeInfo } from "@/app/api/qrcode"; | import { QrCodeInfo } from "@/app/api/qrcode"; | ||||
| @@ -204,7 +204,7 @@ const QrModal: React.FC<Props> = ({ open, onClose, warehouse }) => { | |||||
| </Typography> | </Typography> | ||||
| ) : ( | ) : ( | ||||
| <> | <> | ||||
| <PutawayForm | |||||
| <PutAwayForm | |||||
| itemDetail={itemDetail} | itemDetail={itemDetail} | ||||
| warehouse={warehouse} | warehouse={warehouse} | ||||
| disabled={false} | disabled={false} | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { PutawayLine } from "@/app/api/po/actions" | |||||
| import { PutAwayLine } from "@/app/api/po/actions" | |||||
| import { QcData } from "@/app/api/qc" | import { QcData } from "@/app/api/qc" | ||||
| // export interface QcData { | // export interface QcData { | ||||
| @@ -73,12 +73,12 @@ export const dummyEscalationHistory: EscalationData[] = [ | |||||
| }, | }, | ||||
| ] | ] | ||||
| export const dummyPutawayLine: PutawayLine[] = [ | |||||
| export const dummyPutAwayLine: PutAwayLine[] = [ | |||||
| { | { | ||||
| id: 1, | id: 1, | ||||
| qty: 100, | qty: 100, | ||||
| warehouseId: 1, | warehouseId: 1, | ||||
| warehouse: "W001 - 憶兆 3樓A倉", | warehouse: "W001 - 憶兆 3樓A倉", | ||||
| printQty: 100 | |||||
| printQty: 1 | |||||
| } | } | ||||
| ] | ] | ||||
| @@ -133,5 +133,7 @@ | |||||
| "bind": "綁定", | "bind": "綁定", | ||||
| "Search": "搜尋", | "Search": "搜尋", | ||||
| "Found": "已找到", | "Found": "已找到", | ||||
| "escalation processing": "處理上報記錄" | |||||
| "escalation processing": "處理上報記錄", | |||||
| "Printer": "列印機", | |||||
| "Printing": "列印中" | |||||
| } | } | ||||