Quellcode durchsuchen

update pick order

master
MSI\derek vor 1 Monat
Ursprung
Commit
198469f6d5
15 geänderte Dateien mit 1393 neuen und 100 gelöschten Zeilen
  1. +72
    -1
      src/app/api/pickOrder/actions.ts
  2. +14
    -2
      src/app/api/qc/actions.ts
  3. +5
    -2
      src/app/utils/formatUtil.ts
  4. +26
    -0
      src/app/utils/gridUtil.tsx
  5. +3
    -2
      src/components/CreateItem/CreateItem.tsx
  6. +132
    -0
      src/components/PickOrderDetail/ApprovalContent.tsx
  7. +137
    -0
      src/components/PickOrderDetail/ApprovalForm.tsx
  8. +606
    -60
      src/components/PickOrderDetail/PickOrderDetail.tsx
  9. +6
    -6
      src/components/PickOrderDetail/PickOrderDetailWrapper.tsx
  10. +247
    -0
      src/components/PickOrderDetail/QcContent.tsx
  11. +119
    -0
      src/components/PickOrderDetail/QcForm.tsx
  12. +18
    -21
      src/components/PickOrderSearch/ConsolidatedPickOrders.tsx
  13. +4
    -1
      src/components/PoDetail/PoDetail.tsx
  14. +3
    -4
      src/components/PoDetail/PoInputGrid.tsx
  15. +1
    -1
      src/components/PoDetail/QcForm.tsx

+ 72
- 1
src/app/api/pickOrder/actions.ts Datei anzeigen

@@ -6,14 +6,55 @@ import { cache } from "react";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { QcItemResult } from "../settings/qcItem";
import { RecordsRes } from "../utils";
import { ConsoPickOrderResult, PickOrderLineWithSuggestedLot, PickOrderResult, PreReleasePickOrderSummary } from ".";
import { ConsoPickOrderResult, PickOrderLineWithSuggestedLot, PickOrderResult, PreReleasePickOrderSummary, StockOutLine } from ".";
import { PurchaseQcResult } from "../po/actions";
// import { BASE_API_URL } from "@/config/api";
export interface PostStockOutLiineResponse<T> {
id: number | null;
name: string;
code: string;
type?: string
message: string | null;
errorPosition: string | keyof T;
entity: T | T[]
}

export interface ReleasePickOrderInputs {
consoCode: string
assignTo: number,
}

export interface CreateStockOutLine {
consoCode: string,
pickOrderLineId: number,
inventoryLotLineId: number,
qty: number,
}

export interface UpdateStockOutLine {
id: number,
// consoCode: String,
itemId: number,
qty: number,
pickOrderLineId: number,
inventoryLotLineId?: number,
status: string,
pickTime?: string,
// pickerId: number?
}

export interface PickOrderQcInput {
qty: number
status: string
qcResult: PurchaseQcResult[];
}

export interface PickOrderApprovalInput {
allowQty: number
rejectQty: number
status: string
}

export const consolidatePickOrder = async (ids: number[]) => {
const pickOrder = await serverFetchJson<any>(`${BASE_API_URL}/pickOrder/conso`, {
method: "POST",
@@ -80,6 +121,13 @@ export const consolidatePickOrder_revert = async (ids: number[]) => {
}
});

export const fetchStockOutLineClient = cache(async (pickOrderLineId: number) => {
return serverFetchJson<StockOutLine[]>(`${BASE_API_URL}/stockOutLine/getByPickOrderLineId/${pickOrderLineId}`, {
method: 'GET',
next: { tags: ["pickorder"] },
});
});

export const fetchConsoDetail = cache(async (consoCode: string) => {
return serverFetchJson<PreReleasePickOrderSummary>(`${BASE_API_URL}/pickOrder/pre-release-info/${consoCode}`, {
method: 'GET',
@@ -98,4 +146,27 @@ export const consolidatePickOrder_revert = async (ids: number[]) => {
});
revalidateTag("pickorder");
return po
}

export const createStockOutLine = async (data: CreateStockOutLine) => {
console.log("triggering")
const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>(`${BASE_API_URL}/stockOutLine/create`, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
revalidateTag("pickorder");
return po
}

export const updateStockOutLine = async (data: UpdateStockOutLine) => {
console.log(data)
const po = await serverFetchJson<PostStockOutLiineResponse<StockOutLine>>
(`${BASE_API_URL}/stockOutLine/update`, {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
revalidateTag("pickorder");
return po
}

+ 14
- 2
src/app/api/qc/actions.ts Datei anzeigen

@@ -8,7 +8,13 @@ import { serverFetchJson } from "../../utils/fetchUtil";
import { QcItemWithChecks } from ".";

export interface QcResult {

id: number
qcItemId: number
name: string
code: string
stockInLineId?: number
stockOutLineId?: number
failQty: number
}

export const fetchQcItemCheck = cache(async (itemId?: number) => {
@@ -21,7 +27,13 @@ export const fetchQcItemCheck = cache(async (itemId?: number) => {

export const fetchQcResult = cache(async (id: number) => {
return serverFetchJson<any[]>(`${BASE_API_URL}/qcResult/${id}`, {
return serverFetchJson<QcResult[]>(`${BASE_API_URL}/qcResult/${id}`, {
next: { tags: ["qc"] },
});
});

export const fetchPickOrderQcResult = cache(async (id: number) => {
return serverFetchJson<QcResult[]>(`${BASE_API_URL}/qcResult/pick-order/${id}`, {
next: { tags: ["qc"] },
});
});

+ 5
- 2
src/app/utils/formatUtil.ts Datei anzeigen

@@ -1,6 +1,7 @@
import dayjs, { ConfigType, Dayjs } from "dayjs";
import { Uom } from "../api/settings/uom";
import { ListIterateeCustom, every, isArray, isNaN, isNull, isUndefined, take } from "lodash";
import { Box, BoxProps, } from "@mui/material";

export const manhourFormatter = new Intl.NumberFormat("en-HK", {
minimumFractionDigits: 2,
@@ -74,8 +75,11 @@ export const stockInLineStatusMap: { [status: string]: number } = {
export const stockOutLineStatusMap: { [status: string]: number } = {
"draft": 0,
"pending": 1, // waiting for qc
"determine1": 2, // waiting for qc
"lot-change": 3, // waiting for qc
// after qc = completed
"completed": 2,
"completed": 4,
"rejected": 5,
};

export const pickOrderStatusMap: { [status: string]: number } = {
@@ -92,4 +96,3 @@ export const calculateWeight = (qty: number, uom: Uom) => {
export const returnWeightUnit = (uom: Uom) => {
return uom.unit4 || uom.unit3 || uom.unit2 || uom.unit1;
}


+ 26
- 0
src/app/utils/gridUtil.tsx Datei anzeigen

@@ -0,0 +1,26 @@
"use client";

import { Box, Grid } from "@mui/material";

export function FitAllCell(list: (string | number)[]) {
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
maxHeight: 100,
overflowY: "scroll",
scrollbarWidth: "none", // For Firefox
"&::-webkit-scrollbar": {
display: "none", // For Chrome, Safari, and Opera
},
}}
>
{list.map((item, index) => (
<Grid sx={{ mt: 1 }} key={index}>
{`${item}`}
</Grid>
))}
</Box>
);
}

+ 3
- 2
src/components/CreateItem/CreateItem.tsx Datei anzeigen

@@ -160,7 +160,9 @@ const CreateItem: React.FC<Props> = ({
component="form"
onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
>
<Grid>
<Grid
>
<Typography mb={2} variant="h4">
{t(`${mode} ${title}`)}
</Typography>
@@ -185,7 +187,6 @@ const CreateItem: React.FC<Props> = ({
variant="contained"
startIcon={<Check />}
type="submit"
// disabled={submitDisabled}
>
{isEditMode ? t("Save") : t("Confirm")}
</Button>


+ 132
- 0
src/components/PickOrderDetail/ApprovalContent.tsx Datei anzeigen

@@ -0,0 +1,132 @@
"use client";

import {
Box,
Card,
CardContent,
Grid,
Stack,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import StyledDataGrid from "../StyledDataGrid";
import { useCallback, useEffect, useMemo } from "react";
import {
GridColDef,
GridRowIdGetter,
GridRowModel,
useGridApiContext,
GridRenderCellParams,
GridRenderEditCellParams,
useGridApiRef,
} from "@mui/x-data-grid";
import InputDataGrid from "../InputDataGrid";
import { TableRow } from "../InputDataGrid/InputDataGrid";
import { QcItemWithChecks } from "@/app/api/qc";
import { GridEditInputCell } from "@mui/x-data-grid";
import { StockInLine } from "@/app/api/po";
import { stockInLineStatusMap } from "@/app/utils/formatUtil";
import { PickOrderApprovalInput } from "@/app/api/pickorder/actions";
import { StockOutLine } from "@/app/api/pickorder";

interface Props {
// approvalDefaultValues: StockInLine;
// qc: QcItemWithChecks[];
approvalDefaultValues: StockOutLine & PickOrderApprovalInput;

disabled: boolean
}

const ApprovalContent: React.FC<Props> = ({
// qc,
approvalDefaultValues,
disabled
}) => {
const { t } = useTranslation("purchaseOrder");
const apiRef = useGridApiRef();
const {
register,
formState: { errors, defaultValues, touchedFields },
watch,
control,
setValue,
getValues,
reset,
resetField,
setError,
clearErrors,
} = useFormContext<PickOrderApprovalInput>();
console.log(approvalDefaultValues)

// const status = "rejected"
const totalQty = approvalDefaultValues.qty
const allowQty = watch("allowQty");
const rejectQty = watch("rejectQty");

return (
<Grid container justifyContent="flex-start" alignItems="flex-start">
<Grid item xs={12}>
<Typography variant="h6" display="block" marginBlockEnd={1}>
{t(`Lot Change Approval`)}
</Typography>
</Grid>
{/* <Grid item xs={12}>
<Typography variant="h6" display="block" marginBlockEnd={1}>
{t(`to be processed`)}: {approvalDefaultValues.rejectQty - rejectQty}
</Typography>
</Grid> */}
<Grid
container
justifyContent="flex-start"
alignItems="flex-start"
spacing={2}
sx={{ mt: 0.5 }}
>
<Grid item xs={6}>
<TextField
label={t("allowQty")}
fullWidth
{...register("allowQty", {
required: "allowQty required!",
min: 0,
valueAsNumber: true,
max: approvalDefaultValues.allowQty
})}
disabled={disabled}
defaultValue={approvalDefaultValues.allowQty}
error={Boolean(errors.allowQty)}
helperText={errors.allowQty?.message}
/>
</Grid>
<Grid item xs={6}>
<TextField
label={t("rejectQty")}
fullWidth
{...register("rejectQty", {
required: "rejectQty required!",
min: 0,
valueAsNumber: true,
max: approvalDefaultValues.rejectQty
})}
disabled={disabled}
defaultValue={approvalDefaultValues.rejectQty}
error={Boolean(errors.rejectQty)}
helperText={errors.rejectQty?.message}
/>
</Grid>
</Grid>
<Grid
container
justifyContent="flex-start"
alignItems="flex-start"
spacing={2}
sx={{ mt: 0.5 }}
>
</Grid>
</Grid>
);
};
export default ApprovalContent;

+ 137
- 0
src/components/PickOrderDetail/ApprovalForm.tsx Datei anzeigen

@@ -0,0 +1,137 @@
import { QcItemWithChecks } from "@/app/api/qc";
import useUploadContext from "../UploadProvider/useUploadContext";
import {
PickOrderApprovalInput,
PickOrderQcInput,
updateStockOutLine,
UpdateStockOutLine,
} from "@/app/api/pickorder/actions";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import QcContent from "./QcContent";
import { Box, Button, Modal, ModalProps, Stack } from "@mui/material";
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Check } from "@mui/icons-material";
import { StockOutLine } from "@/app/api/pickorder";
import dayjs from "dayjs";
import { INPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT } from "@/app/utils/formatUtil";
import ApprovalContent from "./ApprovalContent";

const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
// overflow: "scroll",
bgcolor: "background.paper",
pt: 5,
px: 5,
pb: 10,
display: "block",
width: { xs: "60%", sm: "60%", md: "60%" },
};

interface Props extends Omit<ModalProps, "children"> {
// qc: QcItemWithChecks[];
approvalDefaultValues: StockOutLine & PickOrderApprovalInput;
disabled: boolean;
}

const ApprovalForm: React.FC<Props> = ({
// qc,
approvalDefaultValues,
disabled,
open,
onClose,
}) => {
const { setIsUploading } = useUploadContext();
const { t } = useTranslation("pickOrder");
const formProps = useForm<PickOrderApprovalInput>({
defaultValues: {
allowQty: approvalDefaultValues.qty,
rejectQty: 0,
status: approvalDefaultValues.status,
},
});

const errors = formProps.formState.errors;
const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
(...args) => {
onClose?.(...args);
// reset();
},
[onClose]
);

const onSubmit = useCallback<SubmitHandler<PickOrderApprovalInput & {}>>(
async (data, event) => {
console.log(data);
// checking later
// post
let hasError = false;
if (data.allowQty + data.rejectQty != approvalDefaultValues.qty) {
formProps.setError("allowQty", {
message: "illegal qty",
type: "required",
});
formProps.setError("rejectQty", {
message: "illegal qty",
type: "required",
});
}
if (hasError) {
return
}
const postData: UpdateStockOutLine = {
id: approvalDefaultValues.id,
itemId: approvalDefaultValues.itemId,
pickOrderLineId: approvalDefaultValues.pickOrderLineId,
qty: data.allowQty, //allow qty
status: data.status,
// pickTime: dayjs().format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`),
};
console.log(postData);
// return;
const res = await updateStockOutLine(postData);
if (res) {
console.log(res);
closeHandler({}, "backdropClick");
} else {
console.log(res);
console.log("bug la");
}
},
[t]
);
return (
<>
<FormProvider {...formProps}>
<Modal open={open} onClose={closeHandler}>
<Box
sx={style}
component="form"
onSubmit={formProps.handleSubmit(onSubmit)}
>
<ApprovalContent
approvalDefaultValues={approvalDefaultValues}
disabled={disabled}
/>
<Stack direction="row" justifyContent="flex-end" gap={1}>
{!disabled ? (
<Button
name="submit"
variant="contained"
startIcon={<Check />}
type="submit"
>
{t("submit")}
</Button>
) : undefined}
</Stack>
</Box>
</Modal>
</FormProvider>
</>
);
};
export default ApprovalForm;

+ 606
- 60
src/components/PickOrderDetail/PickOrderDetail.tsx Datei anzeigen

@@ -1,6 +1,7 @@
"use client";

import {
Box,
Button,
ButtonProps,
Card,
@@ -9,25 +10,61 @@ import {
CircularProgress,
Grid,
Stack,
Tooltip,
Typography,
} from "@mui/material";
import PlayArrowIcon from "@mui/icons-material/PlayArrow";
import { useTranslation } from "react-i18next";
import StyledDataGrid from "../StyledDataGrid";
import { useCallback, useEffect, useMemo, useState } from "react";
import { GridColDef } from "@mui/x-data-grid";
import {
GridColDef,
GridRowId,
GridRowIdGetter,
GridRowModel,
GridRowModes,
useGridApiRef,
GridRenderEditCellParams,
GridEditInputCell,
GridRowParams,
} from "@mui/x-data-grid";
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 { fetchPickOrderLineClient } from "@/app/api/pickorder/actions";
import { PickOrderLineWithSuggestedLot } from "@/app/api/pickorder";
import {
CreateStockOutLine,
createStockOutLine,
fetchPickOrderLineClient,
fetchStockOutLineClient,
PickOrderApprovalInput,
PickOrderQcInput,
} from "@/app/api/pickorder/actions";
import {
PickOrderLineWithSuggestedLot,
StockOutLine,
} 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";
import { stockOutLineStatusMap } from "@/app/utils/formatUtil";
import { GridActionsCellItem } from "@mui/x-data-grid";
import DoDisturbIcon from "@mui/icons-material/DoDisturb";
import useUploadContext from "../UploadProvider/useUploadContext";
import { FitAllCell } from "@/app/utils/gridUtil";
import { QcItemWithChecks } from "@/app/api/qc";
import QcForm from "./QcForm";
import { fetchPickOrderQcResult, QcResult } from "@/app/api/qc/actions";
import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
import AutoFixNormalIcon from "@mui/icons-material/AutoFixNormal";
import ApprovalForm from "./ApprovalForm";
import InfoIcon from "@mui/icons-material/Info";
import VerifiedIcon from "@mui/icons-material/Verified";

interface Props {
qc: QcItemWithChecks[];
consoCode: string;
}
interface IsLoadingModel {
@@ -35,9 +72,50 @@ interface IsLoadingModel {
stockOutLineTable: boolean;
}

const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
export type StockOutLineEntryError = {
[field in keyof StockOutLine]?: string;
};

export type StockOutLineRow = Partial<
StockOutLine & {
id: number;
isActive: boolean | undefined;
_isNew: boolean;
_error: StockOutLineEntryError;
}
>;

class ProcessRowUpdateError extends Error {
public readonly row: StockOutLineRow;
public readonly errors: StockOutLineEntryError | undefined;
constructor(
row: StockOutLineRow,
message?: string,
errors?: StockOutLineEntryError
) {
super(message);
this.row = row;
this.errors = errors;

Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
}
}

export type formDefaultValues = StockOutLine &
(PickOrderQcInput | PickOrderApprovalInput);

const PickOrderDetail: React.FC<Props> = ({ consoCode, qc }) => {
const { t } = useTranslation("pickOrder");
const [selectedRow, setSelectRow] = useState<GridRowSelectionModel>();
const apiRef = useGridApiRef();
const [qcResult, setQcResult] = useState([] as QcResult[]);
const [selectedRow, setSelectedRow] = useState<GridRowSelectionModel>([]);
const [currPol, setCurrPol] = useState<PickOrderLineWithSuggestedLot>();
const [isChangeLotSolId, setIsChangeLotSolId] = useState<number | undefined>(
undefined
);

const [formDefaultValues, setFormDefaultValues] =
useState<formDefaultValues>();
const [isLoadingModel, setIsLoadingModel] = useState<IsLoadingModel>({
pickOrderLineTable: false,
stockOutLineTable: false,
@@ -53,6 +131,8 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
const [polTotalCount, setPolTotalCount] = useState(0);
const [solTotalCount, setSolTotalCount] = useState(0);
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
const [btnIsLoading, setBtnIsLoading] = useState(false);
const { setIsUploading } = useUploadContext();

const [pickOrderLine, setPickOrderLine] = useState<
PickOrderLineWithSuggestedLot[]
@@ -80,58 +160,36 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
headerName: "uom",
flex: 1,
},
{
field: "lotLineId",
headerName: "lotLineId",
flex: 1,
},
{
field: "warehouse",
headerName: "location",
flex: 1,
renderCell: (params) => {
if (!params.row.warehouse) return <></>;
const warehouseList = JSON.parse(params.row.warehouse) as string[];
return FitAllCell(warehouseList);
},
},
{
field: "suggestedLotNo",
headerName: "suggestedLotNo",
flex: 1.2,
renderCell: (params) => {
if (!params.row.suggestedLotNo) return <></>;
const suggestedLotNoList = JSON.parse(
params.row.suggestedLotNo
) as string[];
return FitAllCell(suggestedLotNoList);
},
},
],
[]
);
const [stockOutLine, setStockOutLine] = useState([]);
const stockOutLineColumns = useMemo<GridColDef[]>(
() => [
{
field: "code",
headerName: "actual lot (out line",
flex: 1,
},
],
[]
);

const handleStartPickOrder = useCallback(async () => {}, []);

const handleCompletePickOrder = useCallback(async () => {}, []);

useEffect(() => {
console.log(selectedRow);
}, [selectedRow]);

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((prev) => !prev);
}, []);

const fetchPickOrderLine = useCallback(
async (params: Record<string, any>) => {
@@ -158,27 +216,397 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
},
[fetchPickOrderLineClient, consoCode]
);

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 [stockOutLine, setStockOutLine] = useState<StockOutLine[]>([]);

const getRowId = useCallback<GridRowIdGetter<StockOutLineRow>>(
(row) => row.id as number,
[]
);
const [qcOpen, setQcOpen] = useState(false);
const [approvalOpen, setApprovalOpen] = useState(false);

const closeQcModal = useCallback(() => {
setQcOpen(false);
}, []);
const openQcModal = useCallback(() => {
setQcOpen(true);
}, []);

const closeApprovalModal = useCallback(() => {
setApprovalOpen(false);
}, []);
const openApprovalModal = useCallback(() => {
setApprovalOpen(true);
}, []);

const triggerRefetch = useCallback(() => {
setSelectedRow((prev) => prev);
}, []);

const handleDelete = useCallback(
(id: GridRowId) => () => {
setStockOutLine((prev) => prev.filter((e) => getRowId(e) !== id));
},
[getRowId]
);

const handleStart = useCallback(
(id: GridRowId, params: any) => () => {
setBtnIsLoading(true);
setRowModesModel((prev) => ({
...prev,
[id]: { mode: GridRowModes.View },
}));
setTimeout(async () => {
// post stock in line
const oldId = params.row.id;
console.log(params.row);
// console.log(currPol);
const postData = {
consoCode: consoCode,
pickOrderLineId: params.row.pickOrderLineId,
inventoryLotLineId: params.row.inventoryLotLineId,
qty: params.row.qty,
} as CreateStockOutLine;
console.log(postData);
// return
console.log("triggering");
const res = await createStockOutLine(postData);
if (res) {
console.log(res);
setStockOutLine((prev) =>
prev.map((p) => (p.id === oldId ? (res.entity as StockOutLine) : p))
);
}
setBtnIsLoading(false);
// do post directly to test
// openStartModal();
}, 500);
},
[createStockOutLine]
);

useEffect(() => {
console.log(stockOutLine);
}, [stockOutLine]);

const handleApproval = useCallback(
(id: GridRowId, params: any) => async () => {
setBtnIsLoading(true);
console.log(params.row.qty);
console.log(params.row);
setFormDefaultValues({
...(params.row as StockOutLine),
status: "lot-change",
} as StockOutLine & PickOrderApprovalInput);
setTimeout(() => {
// open qc modal
console.log("delayed");
openApprovalModal();
setBtnIsLoading(false);
}, 200);
},
[]
);

const handleLotChange = useCallback(
(id: GridRowId, params: GridRowParams<any>) => async () => {
setOpenScanner((prev) => !prev);
console.log(id);
setIsChangeLotSolId((prev) => {
if (prev != undefined) return undefined
return id as number
});
},
[]
);

useEffect(() => {
console.log(isChangeLotSolId)
}, [isChangeLotSolId])

const handleComplete = useCallback(
(id: GridRowId, params: any) => async () => {
setBtnIsLoading(true);
setRowModesModel((prev) => ({
...prev,
[id]: { mode: GridRowModes.View },
}));
getQcResult(id as number).then((qcResult) => {
setQcResult(qcResult);
});
console.log(params.row.qty);
console.log(params.row);
setFormDefaultValues({
...(params.row as StockOutLine),
qty: params.row.qty,
status: "completed",
} as StockOutLine & PickOrderQcInput);
setTimeout(() => {
// open qc modal
console.log("delayed");
openQcModal();
setBtnIsLoading(false);
}, 200);
},
[]
);

const stockOutLineColumns = useMemo<GridColDef[]>(
() => [
{
field: "itemName",
headerName: "item name",
flex: 1,
},
{
field: "qty",
headerName: "qty",
editable: true,
flex: 1,
type: "number",
// renderEditCell(params: GridRenderEditCellParams<StockOutLineRow>) {
// const errorMessage =
// params.row._error?.[params.field as keyof StockOutLineEntryError];
// const content = (
// <GridEditInputCell
// {...params}
// inputProps={{ min: 0 }}
// />
// );
// return errorMessage ? (
// <Tooltip title={t(errorMessage)}>
// <Box width="100%">{content}</Box>
// </Tooltip>
// ) : (
// content
// );
// },
},
{
field: "lotNo",
headerName: "lotNo",
flex: 1,
},
{
field: "status",
headerName: t("status"),
flex: 0.5,
renderCell: (params) => {
return t(`${params.row.status}`);
},
},
{
field: "actions",
type: "actions",
headerName: `${t("start")}
| ${t("approval")}
| ${t("lot change")}
| ${t("checkout")}
| ${t("delete")}`,
flex: 1.5,
cellClassName: "actions",
getActions: (params) => {
const status = params.row.status.toLowerCase();
return [
<GridActionsCellItem
icon={<PlayArrowIcon />}
label="start"
sx={{
color: "primary.main",
// marginRight: 1,
}}
disabled={!(stockOutLineStatusMap[status] === 0)}
// set _isNew to false after posting
// or check status
onClick={handleStart(params.row.id, params)}
color="inherit"
key="edit"
/>,
<GridActionsCellItem
icon={<VerifiedIcon />}
label="approval"
sx={{
color: "primary.main",
// marginRight: 1,
}}
disabled={stockOutLineStatusMap[status] !== 2}
// set _isNew to false after posting
// or check status
onClick={handleApproval(params.row.id, params)} // start scanning for that row
color="inherit"
key="edit"
/>,
<GridActionsCellItem
icon={<AutoFixNormalIcon />}
label="lot change" ///
sx={{
color: "primary.main",
// marginRight: 1,
}}
disabled={stockOutLineStatusMap[status] !== 3}
// set _isNew to false after posting
// or check status
onClick={handleLotChange(params.row.id, params)} // start scanning for that row
color="inherit"
key="edit"
/>,
<GridActionsCellItem
icon={<ShoppingCartIcon />}
label="qcAndPick"
sx={{
color: "primary.main",
// marginRight: 1,
}}
disabled={
!params.row.inventoryLotLineId ||
stockOutLineStatusMap[status] === 2 ||
stockOutLineStatusMap[status] === 5
}
// set _isNew to false after posting
// or check status
onClick={handleComplete(params.row.id, params)}
color="inherit"
key="edit"
/>,
<GridActionsCellItem
icon={<DoDisturbIcon />}
label="Delete"
sx={{
color: "error.main",
}}
disabled={stockOutLineStatusMap[status] > 0}
onClick={handleDelete(params.row.id)}
/>,
<GridActionsCellItem
icon={<InfoIcon />}
label="debug button"
sx={{
color: "error.main",
}}
onClick={() => console.log(params.row)}
/>,
];
},
},
],
[stockOutLineStatusMap, handleStart, handleDelete]
);

const fetchStockOutLine = useCallback(
async (params: Record<string, any>) => {},
async (params: Record<string, any>, selectedRow: GridRowSelectionModel) => {
const _selectedRow = selectedRow as number[];
console.log(params);
console.log(_selectedRow);
// fetch
const res = await fetchStockOutLineClient(_selectedRow[0]);
console.log(res);
// set state
setStockOutLine(res);
},
[]
);

const addRow = useCallback(
(qrcode: LotLineInfo) => {
const newEntry = {
id: Date.now(),
_isNew: true,
itemId: qrcode.itemId,
itemName: qrcode.itemName,
itemNo: qrcode.itemNo,
lotNo: qrcode.lotNo,
inventoryLotLineId: qrcode.inventoryLotLineId,
qty: 0,
pickOrderLineId: selectedRow[0] as number,
status: "draft",
};
setStockOutLine((prev) => [...prev, newEntry]);
setRowModesModel((model) => ({
...model,
[getRowId(newEntry)]: {
mode: GridRowModes.Edit,
},
}));
},
[getRowId, selectedRow]
);

// need modify this later
const changeRow = useCallback(
(id: number, qrcode: LotLineInfo) => {
console.log(stockOutLine);
console.log(stockOutLine.find((line) => line.id === id));
const rowToSave = {
...stockOutLine.find((line) => line.id === id),
itemId: qrcode.itemId,
itemName: qrcode.itemName,
itemNo: qrcode.itemNo,
lotNo: qrcode.lotNo,
inventoryLotLineId: qrcode.inventoryLotLineId,
};
console.log(rowToSave);
const newEntries = stockOutLine.map((e) =>
getRowId(e) === id ? rowToSave : e
);
setStockOutLine(newEntries as StockOutLine[]);
},
[stockOutLine, getRowId]
);

useEffect(() => {
fetchPickOrderLine(polCriteriaArgs);
}, [polCriteriaArgs]);

useEffect(() => {
fetchStockOutLine(solCriteriaArgs);
}, [solCriteriaArgs]);
if (!qcOpen || !approvalOpen) {
console.log("triggering")
triggerRefetch();
}
if (selectedRow.length > 0) fetchStockOutLine(solCriteriaArgs, selectedRow);
}, [qcOpen, approvalOpen, solCriteriaArgs, selectedRow, triggerRefetch]);

const getLotDetail = useCallback(
async (stockInLineId: number): Promise<LotLineInfo> => {
const res = await fetchLotDetail(stockInLineId);
console.log("res");
console.log(res);
return res;
},
[fetchLotDetail]
);

const getQcResult = useCallback(
async (stockOutLineId: number): Promise<QcResult[]> => {
const res = await fetchPickOrderQcResult(stockOutLineId);
console.log("res");
console.log(res);
return res;
},
[fetchPickOrderQcResult]
);

const [isOpenScanner, setOpenScanner] = useState(false);
const onOpenScanner = useCallback(() => {
setOpenScanner((prev) => !prev);
}, []);

const scanner = useQcCodeScanner();
useEffect(() => {
if (isOpenScanner && !scanner.isScanning) {
@@ -188,24 +616,102 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
}
}, [isOpenScanner]);

const homemade_Qrcode = {
stockInLineId: 156, // eggs
// stockInLineId: 162, // chicken wings
};

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);
setIsUploading(true);
// fetch
getLotDetail(data.stockInLineId).then((value) => {});
getLotDetail(data.stockInLineId).then((qrcode) => {
// add row
if (isChangeLotSolId) {
changeRow(isChangeLotSolId, qrcode);
} else {
addRow(qrcode);
}
});
setIsUploading(false);
}
scanner.resetScan();
}
}, [scanner.values]);
}, [
isChangeLotSolId,
scanner.values,
selectedRow,
changeRow,
addRow,
getLotDetail,
]);

const homemade_Qrcode = {
stockInLineId: 156,
};
const mannuallyAddRow = useCallback(() => {
getLotDetail(homemade_Qrcode.stockInLineId).then((qrcode) => {
addRow(qrcode);
// scanner.resetScan();
});
}, [addRow, homemade_Qrcode]);

const validation = useCallback(
(
newRow: GridRowModel<StockOutLineRow>
// rowModel: GridRowSelectionModel
): StockOutLineEntryError | undefined => {
const error: StockOutLineEntryError = {};
const checkQty = currPol?.qty;
console.log(newRow);
if (!newRow.qty || newRow.qty <= 0) {
error["qty"] = t("illegal qty");
}
return Object.keys(error).length > 0 ? error : undefined;
},
[currPol]
);

const processRowUpdate = useCallback(
(
newRow: GridRowModel<StockOutLineRow>,
originalRow: GridRowModel<StockOutLineRow>
) => {
const errors = validation(newRow); // change to validation
console.log(newRow);
if (errors) {
throw new ProcessRowUpdateError(
originalRow,
"validation error",
errors
);
}
const { _isNew, _error, ...updatedRow } = newRow;
const rowToSave = {
...updatedRow,
} satisfies StockOutLineRow;
console.log(rowToSave);
const newEntries = stockOutLine.map((e) =>
getRowId(e) === getRowId(originalRow) ? rowToSave : e
);
console.log(newEntries);

setStockOutLine(newEntries as StockOutLine[]);
return rowToSave;
},
[stockOutLine, validation]
);

const onProcessRowUpdateError = useCallback(
(updateError: ProcessRowUpdateError) => {
const errors = updateError.errors;
const oldRow = updateError.row;

apiRef.current.updateRows([{ ...oldRow, _error: errors }]);
},
[apiRef]
);

return (
<>
@@ -233,7 +739,13 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
justifyContent="end"
alignItems="end"
>
<Button onClick={onOpenScanner}>
<Button
onClick={mannuallyAddRow}
disabled={selectedRow.length === 0}
>
{isOpenScanner ? t("manual scanning") : t("manual scan")}
</Button>
<Button onClick={onOpenScanner} disabled={selectedRow.length === 0}>
{isOpenScanner ? t("binding") : t("bind")}
</Button>
</Grid>
@@ -254,7 +766,7 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
<StyledDataGrid rows={pickOrderLine} columns={columns} />
</Grid> */}
<Grid item xs={12} sx={{ height: 400 }}>
{isLoadingModel.pickOrderLineTable ? (
{isLoadingModel.pickOrderLineTable && pickOrderLine == undefined ? (
<CircularProgress size={40} />
) : (
<StyledDataGrid
@@ -262,7 +774,14 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
columns={pickOrderLineColumns}
rowSelectionModel={selectedRow}
onRowSelectionModelChange={(newRowSelectionModel) => {
setSelectRow(newRowSelectionModel);
setSelectedRow(newRowSelectionModel);
if (newRowSelectionModel && newRowSelectionModel.length > 0) {
const pol = pickOrderLine.find(
(item) => item.id === newRowSelectionModel[0]
);
console.log(pol);
setCurrPol(pol);
}
}}
initialState={{
pagination: {
@@ -282,15 +801,22 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
</Grid>
<Grid item xs={12} sx={{ height: 400 }}>
<StyledDataGrid
apiRef={apiRef}
rows={stockOutLine}
columns={stockOutLineColumns}
rowModesModel={rowModesModel}
onRowModesModelChange={setRowModesModel}
disableColumnMenu
editMode="row"
// processRowUpdate={processRowUpdate}
// onProcessRowUpdateError={onProcessRowUpdateError}

processRowUpdate={processRowUpdate}
onProcessRowUpdateError={onProcessRowUpdateError}
isCellEditable={(params) => {
const status = params.row.status.toLowerCase();
return (
stockOutLineStatusMap[status] === 0 ||
stockOutLineStatusMap[status] === 3
);
}}
initialState={{
pagination: {
paginationModel: { pageSize: 10, page: 0 },
@@ -308,6 +834,26 @@ const PickOrderDetail: React.FC<Props> = ({ consoCode }) => {
</Grid>
</Grid>
</Stack>
{/* modals */}
{qcOpen && formDefaultValues != undefined && (
<QcForm
qcDefaultValues={formDefaultValues as StockOutLine & PickOrderQcInput}
qc={qc}
disabled={false}
open={qcOpen}
onClose={closeQcModal}
/>
)}
{approvalOpen && formDefaultValues != undefined && (
<ApprovalForm
approvalDefaultValues={
formDefaultValues as StockOutLine & PickOrderApprovalInput
}
disabled={false}
open={approvalOpen}
onClose={closeApprovalModal}
/>
)}
</>
);
};


+ 6
- 6
src/components/PickOrderDetail/PickOrderDetailWrapper.tsx Datei anzeigen

@@ -20,14 +20,14 @@ type Props = {
};

const PoDetailWrapper: React.FC<Props> & SubComponents = async ({ consoCode }) => {
// const [poWithStockInLine, warehouse, qc] = await Promise.all([
// fetchPoWithStockInLines(id),
// fetchWarehouseList(),
// fetchQcItemCheck(),
// ]);
const [
qc
] = await Promise.all([
fetchQcItemCheck(),
]);
// const poWithStockInLine = await fetchPoWithStockInLines(id)

return <PickOrderDetail consoCode={consoCode}/>;
return <PickOrderDetail consoCode={consoCode} qc={qc}/>;
};

PoDetailWrapper.Loading = PickOrderDetailLoading;


+ 247
- 0
src/components/PickOrderDetail/QcContent.tsx Datei anzeigen

@@ -0,0 +1,247 @@
"use client";

import { PurchaseQcResult, PurchaseQCInput } from "@/app/api/po/actions";
import {
Box,
Card,
CardContent,
Grid,
Stack,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import StyledDataGrid from "../StyledDataGrid";
import { useCallback, useEffect, useMemo, useState } from "react";
import {
GridColDef,
GridRowIdGetter,
GridRowModel,
useGridApiContext,
GridRenderCellParams,
GridRenderEditCellParams,
useGridApiRef,
} from "@mui/x-data-grid";
import InputDataGrid from "../InputDataGrid";
import { TableRow } from "../InputDataGrid/InputDataGrid";
import { GridEditInputCell } from "@mui/x-data-grid";
import { StockInLine } from "@/app/api/po";
import { stockInLineStatusMap } from "@/app/utils/formatUtil";
import { fetchQcItemCheck, fetchQcResult } from "@/app/api/qc/actions";
import { QcItemWithChecks } from "@/app/api/qc";
import axios from "@/app/(main)/axios/axiosInstance";
import { NEXT_PUBLIC_API_URL } from "@/config/api";
import axiosInstance from "@/app/(main)/axios/axiosInstance";
import TwoLineCell from "../PoDetail/TwoLineCell";
import QcSelect from "../PoDetail/QcSelect";
import { PickOrderQcInput } from "@/app/api/pickorder/actions";

interface Props {
qcDefaultValues: PickOrderQcInput
qc: QcItemWithChecks[];
disabled: boolean
}
type EntryError =
| {
[field in keyof PurchaseQcResult]?: string;
}
| undefined;

type PoQcRow = TableRow<Partial<PurchaseQcResult>, EntryError>;
// fetchQcItemCheck
const QcContent: React.FC<Props> = ({ qc, qcDefaultValues, disabled }) => {
const { t } = useTranslation("purchaseOrder");
const apiRef = useGridApiRef();
const {
register,
formState: { errors, defaultValues, touchedFields },
watch,
control,
setValue,
getValues,
reset,
resetField,
setError,
clearErrors,
} = useFormContext<PickOrderQcInput>();
console.log(qcDefaultValues);
console.log(defaultValues);

//// validate form
const accQty = watch("qty");
const validateForm = useCallback(() => {
console.log(accQty);
if (accQty > qcDefaultValues.qty) {
setError("qty", {
message: `${t("qty must not greater than")} ${qcDefaultValues.qty}`,
type: "required",
});
}
if (accQty < 1) {
setError("qty", {
message: t("minimal value is 1"),
type: "required",
});
}
if (isNaN(accQty)) {
setError("qty", {
message: t("value must be a number"),
type: "required",
});
}
}, [accQty]);

useEffect(() => {
clearErrors();
validateForm();
}, [validateForm]);
// const [recordQty, setRecordQty] = useState(0);
const columns = useMemo<GridColDef[]>(
() => [
{
field: "qcItemId",
headerName: t("qc Check"),
flex: 1,
editable: !disabled,
valueFormatter(params) {
const row = params.id ? params.api.getRow<PoQcRow>(params.id) : null;
if (!row) {
return null;
}
const Qc = qc.find((q) => q.id === row.qcItemId);
return Qc ? `${Qc.code} - ${Qc.name}` : t("Please select QC");
},
renderCell(params: GridRenderCellParams<PoQcRow, number>) {
console.log(params.value);
return <TwoLineCell>{params.formattedValue}</TwoLineCell>;
},
renderEditCell(params: GridRenderEditCellParams<PoQcRow, number>) {
const errorMessage =
params.row._error?.[params.field as keyof PurchaseQcResult];
console.log(errorMessage);
const content = (
<QcSelect
allQcs={qc}
value={params.row.qcItemId}
onQcSelect={async (qcItemId) => {
await params.api.setEditCellValue({
id: params.id,
field: "qcItemId",
value: qcItemId,
});
// await params.api.setEditCellValue({
// id: params.id,
// field: "type",
// value: "determine1",
// });
}}
/>
);
return errorMessage ? (
<Tooltip title={errorMessage}>
<Box width="100%">{content}</Box>
</Tooltip>
) : (
content
);
},
},
{
field: "failQty",
headerName: t("failQty"),
flex: 1,
editable: !disabled,
type: "number",
renderEditCell(params: GridRenderEditCellParams<PoQcRow>) {
// const recordQty = params.row.qty
// if (recordQty !== undefined) {
// setUnrecordQty((prev) => prev - recordQty)
// }
const errorMessage =
params.row._error?.[params.field as keyof PurchaseQcResult];
const content = <GridEditInputCell {...params} />;
return errorMessage ? (
<Tooltip title={t(errorMessage)}>
<Box width="100%">{content}</Box>
</Tooltip>
) : (
content
);
},
},
],
[qc]
);
/// validate datagrid
const validation = useCallback(
(newRow: GridRowModel<PoQcRow>): EntryError => {
const error: EntryError = {};
const { qcItemId, failQty } = newRow;
if (!qcItemId || qcItemId <= 0) {
error["qcItemId"] = t("select qc");
}
if (!failQty || failQty <= 0) {
error["failQty"] = t("enter a failQty");
}
if (failQty && failQty > qcDefaultValues.qty) {
error["failQty"] = t("qty too big");
}
return Object.keys(error).length > 0 ? error : undefined;
},
[]
);

return (
<Grid container justifyContent="flex-start" alignItems="flex-start">
<Grid item xs={12}>
<Typography variant="h6" display="block" marginBlockEnd={1}>
{t("Qc Detail")}
</Typography>
</Grid>
<Grid
container
justifyContent="flex-start"
alignItems="flex-start"
spacing={2}
sx={{ mt: 0.5 }}
>
<Grid item xs={12} lg={12}>
<TextField
label={t("accepted Qty")}
fullWidth
// value={qcDefaultValues.qty}
{...register("qty", {
required: "qty required!",
valueAsNumber: true,
max: qcDefaultValues.qty,
})}
disabled={disabled}
error={Boolean(errors.qty)}
helperText={errors.qty?.message}
/>
</Grid>
</Grid>
<Grid
container
justifyContent="flex-start"
alignItems="flex-start"
spacing={2}
sx={{ mt: 0.5 }}
>
<Grid item xs={12}>
<InputDataGrid<PickOrderQcInput, PurchaseQcResult, EntryError>
apiRef={apiRef}
checkboxSelection={false}
_formKey={"qcResult"}
columns={columns}
validateRow={validation}
needAdd={!disabled}
/>
</Grid>
</Grid>
</Grid>
);
};
export default QcContent;

+ 119
- 0
src/components/PickOrderDetail/QcForm.tsx Datei anzeigen

@@ -0,0 +1,119 @@
import { QcItemWithChecks } from "@/app/api/qc";
import useUploadContext from "../UploadProvider/useUploadContext";
import { PickOrderQcInput, updateStockOutLine, UpdateStockOutLine } from "@/app/api/pickorder/actions";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import QcContent from "./QcContent";
import { Box, Button, Modal, ModalProps, Stack } from "@mui/material";
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Check } from "@mui/icons-material";
import { StockOutLine } from "@/app/api/pickorder";
import dayjs from "dayjs";
import { INPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT } from "@/app/utils/formatUtil";

const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
// overflow: "scroll",
bgcolor: "background.paper",
pt: 5,
px: 5,
pb: 10,
display: "block",
width: { xs: "60%", sm: "60%", md: "60%" },
};

interface Props extends Omit<ModalProps, "children"> {
qc: QcItemWithChecks[];
qcDefaultValues: StockOutLine & PickOrderQcInput;
disabled: boolean;
}

const QcForm: React.FC<Props> = ({
qc,
qcDefaultValues,
disabled,
open,
onClose,
}) => {
const { setIsUploading } = useUploadContext();
const { t } = useTranslation("pickOrder");
const formProps = useForm<PickOrderQcInput>({
defaultValues: {
qty: qcDefaultValues.qty,
status: qcDefaultValues.status
},
});

const errors = formProps.formState.errors;
const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
(...args) => {
onClose?.(...args);
// reset();
},
[onClose]
);

const onSubmit = useCallback<SubmitHandler<PickOrderQcInput & {}>>(
async (data, event) => {
console.log(data);
console.log(qcDefaultValues);
// checking later
// post
const postData: UpdateStockOutLine = {
id: qcDefaultValues.id,
itemId: qcDefaultValues.itemId,
pickOrderLineId: qcDefaultValues.pickOrderLineId,
inventoryLotLineId: qcDefaultValues.inventoryLotLineId,
qty: data.qty,
status: data.status,
// pickTime: dayjs().format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`),
}
console.log(postData)
// return
const res = await updateStockOutLine(postData)
if (res) {
console.log(res)
closeHandler({}, "backdropClick");
} else {
console.log(res)
console.log("bug la")
}
},
[updateStockOutLine]
);
return (
<>
<FormProvider {...formProps}>
<Modal open={open} onClose={closeHandler}>
<Box
sx={style}
component="form"
onSubmit={formProps.handleSubmit(onSubmit)}
>
<QcContent
qc={qc}
qcDefaultValues={qcDefaultValues}
disabled={disabled}
/>
<Stack direction="row" justifyContent="flex-end" gap={1}>
{!disabled ? (
<Button
name="submit"
variant="contained"
startIcon={<Check />}
type="submit"
>
{t("submit")}
</Button>
) : undefined}
</Stack>
</Box>
</Modal>
</FormProvider>
</>
);
};
export default QcForm;

+ 18
- 21
src/components/PickOrderSearch/ConsolidatedPickOrders.tsx Datei anzeigen

@@ -109,8 +109,8 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => {
const onDetailClick = useCallback(
(pickOrder: any) => {
console.log(pickOrder);
const status = pickOrder.status
if (pickOrderStatusMap[status] >= 2) {
const status = pickOrder.status;
if (pickOrderStatusMap[status] >= 3) {
router.push(`/pickorder/detail?consoCode=${pickOrder.consoCode}`);
} else {
openDetailModal(pickOrder.consoCode);
@@ -210,31 +210,28 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => {
[closeDetailModal]
);


const onChange = useCallback(
(
event: React.SyntheticEvent,
newValue: NameList
) => {
console.log(newValue);
formProps.setValue("assignTo", newValue.id);
},
[]
);
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")
const res = await releasePickOrder(data);
console.log(res);
console.log(res.status);
if ((res.status === 200)) {
router.push(`/pickorder/detail?consoCode=${data.consoCode}`);
} else {
console.log(res);
}
} catch (error) {
console.log(error)
console.log(error);
}
},
[releasePickOrder]
@@ -251,7 +248,7 @@ const ConsolidatedPickOrders: React.FC<Props> = ({ filterArgs }) => {
useEffect(() => {
if (consoCode) {
fetchConso(consoCode);
formProps.setValue("consoCode", consoCode)
formProps.setValue("consoCode", consoCode);
}
}, [consoCode]);



+ 4
- 1
src/components/PoDetail/PoDetail.tsx Datei anzeigen

@@ -75,6 +75,7 @@ import ReactQrCodeScannerModal, {
import QrModal from "./QrModal";
import { PlayArrow } from "@mui/icons-material";
import DoneIcon from "@mui/icons-material/Done";
import { QrCode } from "../QrCode";

type Props = {
po: PoResult;
@@ -272,6 +273,7 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
// break;
}
}, [purchaseOrder, handleStartPo, handleCompletePo]);

return (
<>
<Stack
@@ -283,7 +285,8 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
<Grid item>
<Typography mb={2} variant="h4">
{/* {purchaseOrder.code} - {currPoStatus} */}
{purchaseOrder.code} - {t(`${purchaseOrder.status.toLowerCase()}`)}
{purchaseOrder.code} -{" "}
{t(`${purchaseOrder.status.toLowerCase()}`)}
</Typography>
</Grid>
</Grid>


+ 3
- 4
src/components/PoDetail/PoInputGrid.tsx Datei anzeigen

@@ -413,7 +413,6 @@ function PoInputGrid({
renderCell: (params) => {
return t(`${params.row.status}`)
}
// editable: true,
},
{
field: "actions",
@@ -423,10 +422,10 @@ function PoInputGrid({
flex: 1.5,
cellClassName: "actions",
getActions: (params) => {
console.log(params.row.status);
// console.log(params.row.status);
const status = params.row.status.toLowerCase();
console.log(stockInLineStatusMap[status]);
console.log(session?.user?.abilities?.includes("APPROVAL"));
// console.log(stockInLineStatusMap[status]);
// console.log(session?.user?.abilities?.includes("APPROVAL"));
return [
<GridActionsCellItem
icon={<PlayArrowIcon />}


+ 1
- 1
src/components/PoDetail/QcForm.tsx Datei anzeigen

@@ -96,7 +96,7 @@ const QcForm: React.FC<Props> = ({ qc, itemDetail, disabled }) => {
clearErrors();
validateForm();
}, [validateForm]);
// const [recordQty, setRecordQty] = useState(0);
const columns = useMemo<GridColDef[]>(
() => [
{


Laden…
Abbrechen
Speichern