| @@ -0,0 +1,23 @@ | |||
| "use server"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| // import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; | |||
| import { revalidateTag } from "next/cache"; | |||
| import { cache } from "react"; | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { QcItemResult } from "../settings/qcItem"; | |||
| import { RecordsRes } from "../utils"; | |||
| // import { BASE_API_URL } from "@/config/api"; | |||
| export interface LotLineInfo { | |||
| inventoryLotLineId: number, | |||
| lotNo: string, | |||
| remainingQty: number, | |||
| uom: string | |||
| } | |||
| export const fetchLotDetail = cache(async (stockInLineId: number) => { | |||
| return serverFetchJson<LotLineInfo>(`${BASE_API_URL}/inventoryLotLine/lot-detail/${stockInLineId}`, { | |||
| method: 'GET', | |||
| next: { tags: ["inventory"] }, | |||
| }); | |||
| }); | |||
| @@ -9,6 +9,10 @@ import { RecordsRes } from "../utils"; | |||
| import { ConsoPickOrderResult, PickOrderLineWithSuggestedLot, PickOrderResult, PreReleasePickOrderSummary } from "."; | |||
| // import { BASE_API_URL } from "@/config/api"; | |||
| export interface ReleasePickOrderInputs { | |||
| consoCode: string | |||
| assignTo: number, | |||
| } | |||
| export const consolidatePickOrder = async (ids: number[]) => { | |||
| const pickOrder = await serverFetchJson<any>(`${BASE_API_URL}/pickOrder/conso`, { | |||
| @@ -61,7 +65,7 @@ export const consolidatePickOrder_revert = async (ids: number[]) => { | |||
| } | |||
| }); | |||
| export const fetchConsoPickOrderLineClient = cache(async (queryParams?: Record<string, any>) => { | |||
| export const fetchPickOrderLineClient = cache(async (queryParams?: Record<string, any>) => { | |||
| if (queryParams) { | |||
| const queryString = new URLSearchParams(queryParams).toString(); | |||
| return serverFetchJson<RecordsRes<PickOrderLineWithSuggestedLot[]>>(`${BASE_API_URL}/pickOrder/get-pickorder-line-byPage?${queryString}`, { | |||
| @@ -77,8 +81,21 @@ export const consolidatePickOrder_revert = async (ids: number[]) => { | |||
| }); | |||
| export const fetchConsoDetail = cache(async (consoCode: string) => { | |||
| return serverFetchJson<PreReleasePickOrderSummary>(`${BASE_API_URL}/pickOrder/releaseConso/${consoCode}`, { | |||
| return serverFetchJson<PreReleasePickOrderSummary>(`${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`, { | |||
| method: 'GET', | |||
| next: { tags: ["pickorder"] }, | |||
| }); | |||
| }); | |||
| }); | |||
| export const releasePickOrder = async (data: ReleasePickOrderInputs) => { | |||
| console.log(data) | |||
| console.log(JSON.stringify(data)) | |||
| const po = await serverFetchJson<any>(`${BASE_API_URL}/pickOrder/releaseConso`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| revalidateTag("pickorder"); | |||
| return po | |||
| } | |||
| @@ -66,9 +66,12 @@ export interface PreReleasePickOrderSummary { | |||
| } | |||
| export interface PickOrderLineWithSuggestedLot { | |||
| id: number, | |||
| itemName: string, | |||
| qty: number, | |||
| uom: string | |||
| status: string | |||
| warehouse: string | |||
| suggestedLotNo: string | |||
| } | |||
| @@ -20,12 +20,23 @@ export interface PasswordInputs { | |||
| newPasswordCheck: string; | |||
| } | |||
| export interface NameList { | |||
| id: number | |||
| name: string | |||
| } | |||
| export const fetchUserDetails = cache(async (id: number) => { | |||
| return serverFetchJson<UserDetail>(`${BASE_API_URL}/user/${id}`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| }); | |||
| export const fetchNameList = cache(async () => { | |||
| return serverFetchJson<NameList[]>(`${BASE_API_URL}/user/name-list`, { | |||
| next: { tags: ["user"] }, | |||
| }); | |||
| }); | |||
| export const editUser = async (id: number, data: UserInputs) => { | |||
| const newUser = serverFetchWithNoContent(`${BASE_API_URL}/user/${id}`, { | |||
| method: "PUT", | |||
| @@ -67,6 +67,13 @@ export const stockInLineStatusMap: { [status: string]: number } = { | |||
| "rejected": 9, | |||
| }; | |||
| export const pickOrderStatusMap: { [status: string]: number } = { | |||
| "pending": 1, | |||
| "consolidated": 2, | |||
| "released": 3, | |||
| "completed": 4, | |||
| }; | |||
| export const calculateWeight = (qty: number, uom: Uom) => { | |||
| return qty * (uom.unit2Qty || 1) * (uom.unit3Qty || 1) * (uom.unit4Qty || 1); | |||
| } | |||
| @@ -19,9 +19,13 @@ import { PlayArrow } from "@mui/icons-material"; | |||
| import DoneIcon from "@mui/icons-material/Done"; | |||
| import { GridRowSelectionModel } from "@mui/x-data-grid"; | |||
| import { useQcCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider"; | |||
| import { fetchConsoPickOrderLineClient } from "@/app/api/pickorder/actions"; | |||
| import { fetchPickOrderLineClient } from "@/app/api/pickorder/actions"; | |||
| import { PickOrderLineWithSuggestedLot } from "@/app/api/pickorder"; | |||
| import { Pageable } from "@/app/utils/fetchUtil"; | |||
| import { QrCodeInfo } from "@/app/api/qrcode"; | |||
| import { QrCode } from "../QrCode"; | |||
| import { fetchLotDetail, LotLineInfo } from "@/app/api/inventory/actions"; | |||
| import { GridRowModesModel } from "@mui/x-data-grid"; | |||
| interface Props { | |||
| consoCode: string; | |||
| @@ -30,6 +34,7 @@ interface IsLoadingModel { | |||
| pickOrderLineTable: boolean; | |||
| stockOutLineTable: boolean; | |||
| } | |||
| const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| const { t } = useTranslation("pickOrder"); | |||
| const [selectedRow, setSelectRow] = useState<GridRowSelectionModel>(); | |||
| @@ -37,18 +42,23 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| pickOrderLineTable: false, | |||
| stockOutLineTable: false, | |||
| }); | |||
| const [criteriaArgs, setCriteriaArgs] = useState<Pageable>({ | |||
| const [polCriteriaArgs, setPolCriteriaArgs] = useState<Pageable>({ | |||
| pageNum: 1, | |||
| pageSize: 10, | |||
| }); | |||
| const [solCriteriaArgs, setSolCriteriaArgs] = useState<Pageable>({ | |||
| pageNum: 1, | |||
| pageSize: 10, | |||
| }); | |||
| const [polTotalCount, setPolTotalCount] = useState(0); | |||
| const [solTotalCount, setSolTotalCount] = useState(0); | |||
| const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | |||
| const [suggestedList, setSuggestedList] = useState< | |||
| const [pickOrderLine, setPickOrderLine] = useState< | |||
| PickOrderLineWithSuggestedLot[] | |||
| >([]); | |||
| const sugggestedLotColumn = useMemo<GridColDef[]>( | |||
| const pickOrderLineColumns = useMemo<GridColDef[]>( | |||
| () => [ | |||
| { | |||
| field: "id", | |||
| @@ -70,16 +80,21 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| headerName: "uom", | |||
| flex: 1, | |||
| }, | |||
| { | |||
| field: "warehouse", | |||
| headerName: "location", | |||
| flex: 1, | |||
| }, | |||
| { | |||
| field: "suggestedLotNo", | |||
| headerName: "suggestedLotNo", | |||
| flex: 1, | |||
| flex: 1.2, | |||
| }, | |||
| ], | |||
| [] | |||
| ); | |||
| const [actualList, setActualList] = useState([]); | |||
| const actualLotColumn = useMemo<GridColDef[]>( | |||
| const [stockOutLine, setStockOutLine] = useState([]); | |||
| const stockOutLineColumns = useMemo<GridColDef[]>( | |||
| () => [ | |||
| { | |||
| field: "code", | |||
| @@ -94,82 +109,43 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| const handleCompletePickOrder = useCallback(async () => {}, []); | |||
| const fetchSuggestedLotList = useCallback( | |||
| async (consoCode: string) => {}, | |||
| [] | |||
| ); | |||
| useEffect(() => { | |||
| console.log(selectedRow); | |||
| }, [selectedRow]); | |||
| const buttonData = useMemo(() => { | |||
| switch ("purchaseOrder.status".toLowerCase()) { | |||
| case "pending": | |||
| return { | |||
| buttonName: "start", | |||
| title: t("Do you want to start?"), | |||
| confirmButtonText: t("Start"), | |||
| successTitle: t("Start Success"), | |||
| errorTitle: t("Start Fail"), | |||
| buttonText: t("Start PO"), | |||
| buttonIcon: <PlayArrow />, | |||
| buttonColor: "success", | |||
| disabled: false, | |||
| onClick: handleStartPickOrder, | |||
| }; | |||
| case "receiving": | |||
| return { | |||
| buttonName: "complete", | |||
| title: t("Do you want to complete?"), | |||
| confirmButtonText: t("Complete"), | |||
| successTitle: t("Complete Success"), | |||
| errorTitle: t("Complete Fail"), | |||
| buttonText: t("Complete PO"), | |||
| buttonIcon: <DoneIcon />, | |||
| buttonColor: "info", | |||
| disabled: false, | |||
| onClick: handleCompletePickOrder, | |||
| }; | |||
| default: | |||
| return { | |||
| buttonName: "complete", | |||
| title: t("Do you want to complete?"), | |||
| confirmButtonText: t("Complete"), | |||
| successTitle: t("Complete Success"), | |||
| errorTitle: t("Complete Fail"), | |||
| buttonText: t("Complete PO"), | |||
| buttonIcon: <DoneIcon />, | |||
| buttonColor: "info", | |||
| disabled: true, | |||
| }; | |||
| // break; | |||
| } | |||
| }, [handleStartPickOrder, handleCompletePickOrder]); | |||
| const buttonData = useMemo( | |||
| () => ({ | |||
| buttonName: "complete", | |||
| title: t("Do you want to complete?"), | |||
| confirmButtonText: t("Complete"), | |||
| successTitle: t("Complete Success"), | |||
| errorTitle: t("Complete Fail"), | |||
| buttonText: t("Complete PO"), | |||
| buttonIcon: <DoneIcon />, | |||
| buttonColor: "info", | |||
| disabled: true, | |||
| }), | |||
| [] | |||
| ); | |||
| const [isOpenScanner, setOpenScanner] = useState(false); | |||
| const onOpenScanner = useCallback(() => { | |||
| setOpenScanner(true); | |||
| }, []); | |||
| const onCloseScanner = useCallback(() => { | |||
| setOpenScanner(false); | |||
| setOpenScanner((prev) => !prev); | |||
| }, []); | |||
| const fetchConsoPickOrderLine = useCallback( | |||
| const fetchPickOrderLine = useCallback( | |||
| async (params: Record<string, any>) => { | |||
| setIsLoadingModel((prev) => ({ | |||
| ...prev, | |||
| pickOrderLineTable: true, | |||
| })); | |||
| const res = await fetchConsoPickOrderLineClient({ | |||
| const res = await fetchPickOrderLineClient({ | |||
| ...params, | |||
| consoCode: consoCode, | |||
| }); | |||
| if (res) { | |||
| console.log(res); | |||
| setSuggestedList(res.records); | |||
| setPickOrderLine(res.records); | |||
| setPolTotalCount(res.total); | |||
| } else { | |||
| console.log("error"); | |||
| @@ -180,12 +156,28 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| pickOrderLineTable: false, | |||
| })); | |||
| }, | |||
| [fetchConsoPickOrderLineClient, consoCode] | |||
| [fetchPickOrderLineClient, consoCode] | |||
| ); | |||
| const fetchStockOutLine = useCallback( | |||
| async (params: Record<string, any>) => {}, | |||
| [] | |||
| ); | |||
| useEffect(() => { | |||
| fetchConsoPickOrderLine(criteriaArgs); | |||
| }, [criteriaArgs]); | |||
| fetchPickOrderLine(polCriteriaArgs); | |||
| }, [polCriteriaArgs]); | |||
| useEffect(() => { | |||
| fetchStockOutLine(solCriteriaArgs); | |||
| }, [solCriteriaArgs]); | |||
| const getLotDetail = useCallback( | |||
| async (stockInLineId: number): Promise<LotLineInfo> => { | |||
| const res = await fetchLotDetail(stockInLineId); | |||
| return res; | |||
| }, | |||
| [fetchLotDetail] | |||
| ); | |||
| const scanner = useQcCodeScanner(); | |||
| useEffect(() => { | |||
| @@ -196,19 +188,24 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| } | |||
| }, [isOpenScanner]); | |||
| // useEffect(() => { | |||
| // if (scanner.values.length > 0 && !Boolean(itemDetail)) { | |||
| // console.log(scanner.values[0]); | |||
| // const data: QrCodeInfo = JSON.parse(scanner.values[0]); | |||
| // console.log(data); | |||
| // if (data.stockInLineId) { | |||
| // console.log("still got in"); | |||
| // console.log(data.stockInLineId); | |||
| // setStockInLineId(data.stockInLineId); | |||
| // } | |||
| // scanner.resetScan(); | |||
| // } | |||
| // }, [scanner.values]); | |||
| useEffect(() => { | |||
| if (scanner.values.length > 0) { | |||
| console.log(scanner.values[0]); | |||
| const data: QrCodeInfo = JSON.parse(scanner.values[0]); | |||
| console.log(data); | |||
| if (data.stockInLineId) { | |||
| console.log("still got in"); | |||
| console.log(data.stockInLineId); | |||
| // fetch | |||
| getLotDetail(data.stockInLineId).then((value) => {}); | |||
| } | |||
| scanner.resetScan(); | |||
| } | |||
| }, [scanner.values]); | |||
| const homemade_Qrcode = { | |||
| stockInLineId: 156, | |||
| }; | |||
| return ( | |||
| <> | |||
| @@ -221,7 +218,7 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| </Grid> | |||
| <Grid item xs={8}> | |||
| <Button | |||
| onClick={buttonData.onClick} | |||
| // onClick={buttonData.onClick} | |||
| disabled={buttonData.disabled} | |||
| color={buttonData.buttonColor as ButtonProps["color"]} | |||
| startIcon={buttonData.buttonIcon} | |||
| @@ -236,27 +233,45 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| justifyContent="end" | |||
| alignItems="end" | |||
| > | |||
| <Button onClick={onOpenScanner}>{t("bind")}</Button> | |||
| <Button onClick={onOpenScanner}> | |||
| {isOpenScanner ? t("binding") : t("bind")} | |||
| </Button> | |||
| </Grid> | |||
| {/* homemade qrcode for testing purpose */} | |||
| {/* <Grid | |||
| item | |||
| xs={12} | |||
| style={{ display: "flex", justifyContent: "center" }} | |||
| > | |||
| <QrCode | |||
| content={homemade_Qrcode} | |||
| sx={{ width: 200, height: 200 }} | |||
| /> | |||
| </Grid> */} | |||
| </Grid> | |||
| <Grid container xs={12} justifyContent="space-between"> | |||
| {/* <Grid item xs={12} sx={{ height: 400 }}> | |||
| <StyledDataGrid rows={suggestedList} columns={columns} /> | |||
| <StyledDataGrid rows={pickOrderLine} columns={columns} /> | |||
| </Grid> */} | |||
| <Grid item xs={12} sx={{ height: 400 }}> | |||
| {isLoadingModel.pickOrderLineTable ? ( | |||
| <CircularProgress size={40} /> | |||
| ) : ( | |||
| <StyledDataGrid | |||
| rows={suggestedList} | |||
| columns={sugggestedLotColumn} | |||
| rows={pickOrderLine} | |||
| columns={pickOrderLineColumns} | |||
| rowSelectionModel={selectedRow} | |||
| onRowSelectionModelChange={(newRowSelectionModel) => { | |||
| setSelectRow(newRowSelectionModel); | |||
| }} | |||
| pageSizeOptions={[2, 10, 25, 50, 100]} | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: { pageSize: 10, page: 0 }, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[10, 25, 50, 100]} | |||
| onPaginationModelChange={async (model, details) => { | |||
| setCriteriaArgs({ | |||
| setPolCriteriaArgs({ | |||
| pageNum: model.page + 1, | |||
| pageSize: model.pageSize, | |||
| }); | |||
| @@ -266,7 +281,30 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => { | |||
| )} | |||
| </Grid> | |||
| <Grid item xs={12} sx={{ height: 400 }}> | |||
| <StyledDataGrid rows={actualList} columns={actualLotColumn} /> | |||
| <StyledDataGrid | |||
| rows={stockOutLine} | |||
| columns={stockOutLineColumns} | |||
| rowModesModel={rowModesModel} | |||
| onRowModesModelChange={setRowModesModel} | |||
| disableColumnMenu | |||
| editMode="row" | |||
| // processRowUpdate={processRowUpdate} | |||
| // onProcessRowUpdateError={onProcessRowUpdateError} | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: { pageSize: 10, page: 0 }, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[10, 25, 50, 100]} | |||
| onPaginationModelChange={async (model, details) => { | |||
| setSolCriteriaArgs({ | |||
| pageNum: model.page + 1, | |||
| pageSize: model.pageSize, | |||
| }); | |||
| }} | |||
| rowCount={solTotalCount} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Stack> | |||
| @@ -1,10 +1,13 @@ | |||
| import { | |||
| Autocomplete, | |||
| Box, | |||
| Button, | |||
| CircularProgress, | |||
| FormControl, | |||
| Grid, | |||
| Modal, | |||
| ModalProps, | |||
| TextField, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import { GridToolbarContainer } from "@mui/x-data-grid"; | |||
| @@ -21,7 +24,12 @@ import SearchResults, { | |||
| Column, | |||
| defaultPagingController, | |||
| } from "../SearchResults/SearchResults"; | |||
| import { ByItemsSummary, ConsoPickOrderResult, PickOrderLine, PickOrderResult } from "@/app/api/pickorder"; | |||
| import { | |||
| ByItemsSummary, | |||
| ConsoPickOrderResult, | |||
| PickOrderLine, | |||
| PickOrderResult, | |||
| } from "@/app/api/pickorder"; | |||
| import { useRouter, useSearchParams } from "next/navigation"; | |||
| import ConsolidatePickOrderItemSum from "./ConsolidatePickOrderItemSum"; | |||
| import ConsolidatePickOrderSum from "./ConsolidatePickOrderSum"; | |||
| @@ -29,8 +37,19 @@ import { GridInputRowSelectionModel } from "@mui/x-data-grid"; | |||
| import { | |||
| fetchConsoDetail, | |||
| fetchConsoPickOrderClient, | |||
| releasePickOrder, | |||
| ReleasePickOrderInputs, | |||
| } from "@/app/api/pickorder/actions"; | |||
| import { EditNote } from "@mui/icons-material"; | |||
| import { fetchNameList, NameList } from "@/app/api/user/actions"; | |||
| import { useField } from "@mui/x-date-pickers/internals"; | |||
| import { | |||
| FormProvider, | |||
| SubmitErrorHandler, | |||
| SubmitHandler, | |||
| useForm, | |||
| } from "react-hook-form"; | |||
| import { pickOrderStatusMap } from "@/app/utils/formatUtil"; | |||
| interface Props { | |||
| filterArgs: Record<string, any>; | |||
| @@ -47,6 +66,10 @@ const style = { | |||
| pb: 10, | |||
| width: 1500, | |||
| }; | |||
| interface DisableButton { | |||
| releaseBtn: boolean; | |||
| removeBtn: boolean; | |||
| } | |||
| const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| const { t } = useTranslation("pickOrder"); | |||
| @@ -60,9 +83,18 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| const [consoCode, setConsoCode] = useState<string | undefined>(); ///change back to undefined | |||
| const [revertIds, setRevertIds] = useState<GridInputRowSelectionModel>([]); | |||
| const [totalCount, setTotalCount] = useState<number>(); | |||
| const [usernameList, setUsernameList] = useState<NameList[]>([]); | |||
| const [byPickOrderRows, setByPickOrderRows] = useState< | |||
| Omit<PickOrderResult, "items">[] | undefined | |||
| >(undefined); | |||
| const [byItemsRows, setByItemsRows] = useState<ByItemsSummary[] | undefined>( | |||
| undefined | |||
| ); | |||
| const [disableRelease, setDisableRelease] = useState<boolean>(true); | |||
| const [byPickOrderRows, setByPickOrderRows] = useState<Omit<PickOrderResult, "items">[] | undefined>(undefined); | |||
| const [byItemsRows, setByItemsRows] = useState<ByItemsSummary[] | undefined>(undefined); | |||
| const formProps = useForm<ReleasePickOrderInputs>(); | |||
| const errors = formProps.formState.errors; | |||
| const openDetailModal = useCallback((consoCode: string) => { | |||
| setConsoCode(consoCode); | |||
| @@ -77,9 +109,14 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| const onDetailClick = useCallback( | |||
| (pickOrder: any) => { | |||
| console.log(pickOrder); | |||
| openDetailModal(pickOrder.consoCode); | |||
| const status = pickOrder.status | |||
| if (pickOrderStatusMap[status] >= 2) { | |||
| router.push(`/pickorder/detail?consoCode=${pickOrder.consoCode}`); | |||
| } else { | |||
| openDetailModal(pickOrder.consoCode); | |||
| } | |||
| }, | |||
| [openDetailModal] | |||
| [router, openDetailModal] | |||
| ); | |||
| const columns = useMemo<Column<ConsoPickOrderResult>[]>( | |||
| () => [ | |||
| @@ -93,6 +130,10 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| name: "consoCode", | |||
| label: t("consoCode"), | |||
| }, | |||
| { | |||
| name: "status", | |||
| label: t("status"), | |||
| }, | |||
| ], | |||
| [] | |||
| ); | |||
| @@ -127,6 +168,40 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| fetchNewPageConsoPickOrder(pagingController, filterArgs); | |||
| }, [fetchNewPageConsoPickOrder, pagingController, filterArgs]); | |||
| const isReleasable = useCallback((itemList: ByItemsSummary[]): boolean => { | |||
| var isReleasable = true; | |||
| for (const item of itemList) { | |||
| isReleasable = item.requiredQty >= item.availableQty; | |||
| if (!isReleasable) return isReleasable; | |||
| } | |||
| return isReleasable; | |||
| }, []); | |||
| const fetchConso = useCallback( | |||
| async (consoCode: string) => { | |||
| const res = await fetchConsoDetail(consoCode); | |||
| const nameListRes = await fetchNameList(); | |||
| if (res) { | |||
| console.log(res); | |||
| setByPickOrderRows(res.pickOrders); | |||
| // for testing | |||
| // for (const item of res.items) { | |||
| // item.availableQty = 1000; | |||
| // } | |||
| setByItemsRows(res.items); | |||
| setDisableRelease(isReleasable(res.items)); | |||
| } else { | |||
| console.log("error"); | |||
| console.log(res); | |||
| } | |||
| if (nameListRes) { | |||
| console.log(nameListRes); | |||
| setUsernameList(nameListRes); | |||
| } | |||
| }, | |||
| [isReleasable] | |||
| ); | |||
| const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>( | |||
| (...args) => { | |||
| closeDetailModal(); | |||
| @@ -135,32 +210,51 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| [closeDetailModal] | |||
| ); | |||
| const handleRelease = useCallback(() => { | |||
| console.log("release"); | |||
| router.push(`/pickorder/detail?consoCode=${consoCode}`); | |||
| }, [router, consoCode]); | |||
| const onChange = useCallback( | |||
| ( | |||
| event: React.SyntheticEvent, | |||
| newValue: NameList | |||
| ) => { | |||
| console.log(newValue); | |||
| formProps.setValue("assignTo", newValue.id); | |||
| }, | |||
| [] | |||
| ); | |||
| const onSubmit = useCallback<SubmitHandler<ReleasePickOrderInputs & {}>>( | |||
| async (data, event) => { | |||
| console.log(data); | |||
| try { | |||
| const res = await releasePickOrder(data) | |||
| console.log(res) | |||
| if (res.status = 200) { | |||
| router.push(`/pickorder/detail?consoCode=${data.consoCode}`); | |||
| } else { | |||
| throw Error("hv error") | |||
| } | |||
| } catch (error) { | |||
| console.log(error) | |||
| } | |||
| }, | |||
| [releasePickOrder] | |||
| ); | |||
| const onSubmitError = useCallback<SubmitErrorHandler<ReleasePickOrderInputs>>( | |||
| (errors) => {}, | |||
| [] | |||
| ); | |||
| const handleConsolidate_revert = useCallback(() => { | |||
| console.log(revertIds); | |||
| }, [revertIds]); | |||
| const fetchConso = useCallback(async (consoCode: string) => { | |||
| const res = await fetchConsoDetail(consoCode); | |||
| if (res) { | |||
| console.log(res); | |||
| setByPickOrderRows(res.pickOrders) | |||
| setByItemsRows(res.items) | |||
| } else { | |||
| console.log("error"); | |||
| console.log(res); | |||
| } | |||
| }, []); | |||
| useEffect(() => { | |||
| if (consoCode) { | |||
| fetchConso(consoCode); | |||
| formProps.setValue("consoCode", consoCode) | |||
| } | |||
| }, [consoCode]); | |||
| return ( | |||
| <> | |||
| <Grid | |||
| @@ -186,58 +280,89 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => { | |||
| </Grid> | |||
| {consoCode != undefined ? ( | |||
| <Modal open={modalOpen} onClose={closeHandler}> | |||
| <Box sx={{ ...style, maxHeight: 800 }}> | |||
| <Typography mb={2} variant="h4"> | |||
| {consoCode} | |||
| </Typography> | |||
| <Box sx={{ | |||
| height: 400, | |||
| overflowY: "auto" | |||
| }}> | |||
| <FormProvider {...formProps}> | |||
| <Box | |||
| sx={{ ...style, maxHeight: 800 }} | |||
| component="form" | |||
| onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | |||
| > | |||
| <Grid container> | |||
| <Grid item xs={12} sx={{ mt: 2 }}> | |||
| <ConsolidatePickOrderSum | |||
| rows={byPickOrderRows} | |||
| setRows={setByPickOrderRows} | |||
| consoCode={consoCode} | |||
| revertIds={revertIds} | |||
| setRevertIds={setRevertIds} | |||
| /> | |||
| <Grid item xs={8}> | |||
| <Typography mb={2} variant="h4"> | |||
| {consoCode} | |||
| </Typography> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <ConsolidatePickOrderItemSum | |||
| rows={byItemsRows} | |||
| setRows={setByItemsRows} | |||
| /> | |||
| <Grid | |||
| item | |||
| xs={4} | |||
| display="flex" | |||
| justifyContent="end" | |||
| alignItems="end" | |||
| > | |||
| <FormControl fullWidth> | |||
| <Autocomplete | |||
| disableClearable | |||
| fullWidth | |||
| getOptionLabel={(option) => option.name} | |||
| options={usernameList} | |||
| onChange={onChange} | |||
| renderInput={(params) => <TextField {...params} />} | |||
| /> | |||
| </FormControl> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> | |||
| <Grid container> | |||
| <Grid | |||
| item | |||
| xs={12} | |||
| display="flex" | |||
| justifyContent="end" | |||
| alignItems="end" | |||
| <Box | |||
| sx={{ | |||
| height: 400, | |||
| overflowY: "auto", | |||
| }} | |||
| > | |||
| <Button | |||
| disabled={(revertIds as number[]).length < 1} | |||
| variant="outlined" | |||
| onClick={handleConsolidate_revert} | |||
| sx={{ mr: 1 }} | |||
| > | |||
| {t("remove")} | |||
| </Button> | |||
| <Button | |||
| // disabled={selectedRows.length < 1} | |||
| variant="outlined" | |||
| onClick={handleRelease} | |||
| <Grid container> | |||
| <Grid item xs={12} sx={{ mt: 2 }}> | |||
| <ConsolidatePickOrderSum | |||
| rows={byPickOrderRows} | |||
| setRows={setByPickOrderRows} | |||
| consoCode={consoCode} | |||
| revertIds={revertIds} | |||
| setRevertIds={setRevertIds} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <ConsolidatePickOrderItemSum | |||
| rows={byItemsRows} | |||
| setRows={setByItemsRows} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> | |||
| <Grid container> | |||
| <Grid | |||
| item | |||
| xs={12} | |||
| display="flex" | |||
| justifyContent="end" | |||
| alignItems="end" | |||
| > | |||
| {t("release")} | |||
| </Button> | |||
| <Button | |||
| disabled={(revertIds as number[]).length < 1} | |||
| variant="outlined" | |||
| onClick={handleConsolidate_revert} | |||
| sx={{ mr: 1 }} | |||
| > | |||
| {t("remove")} | |||
| </Button> | |||
| <Button | |||
| disabled={disableRelease} | |||
| variant="outlined" | |||
| // onClick={handleRelease} | |||
| type="submit" | |||
| > | |||
| {t("release")} | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> | |||
| </Box> | |||
| </FormProvider> | |||
| </Modal> | |||
| ) : undefined} | |||
| </> | |||