Explorar el Código

update

create_edit_user
MSI\derek hace 3 meses
padre
commit
a6ad0f36a6
Se han modificado 11 ficheros con 176 adiciones y 75 borrados
  1. +4
    -1
      src/app/api/po/index.ts
  2. +20
    -0
      src/app/api/settings/uom/index.ts
  3. +12
    -1
      src/app/utils/formatUtil.ts
  4. +23
    -4
      src/components/PoDetail/PoDetail.tsx
  5. +29
    -10
      src/components/PoDetail/PoInputGrid.tsx
  6. +29
    -35
      src/components/PoDetail/PoQcStockInModal.tsx
  7. +15
    -0
      src/components/PoDetail/PutawayForm.tsx
  8. +15
    -15
      src/components/PoDetail/QcForm.tsx
  9. +15
    -0
      src/components/QrCode/QrCode.tsx
  10. +1
    -0
      src/components/QrCode/index.ts
  11. +13
    -9
      src/components/RoughSchedule/RoughScheduleWrapper.tsx

+ 4
- 1
src/app/api/po/index.ts Ver fichero

@@ -2,6 +2,7 @@ import { cache } from "react";
import "server-only";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { Uom } from "../settings/uom";

export interface PoResult {
id: number
@@ -21,7 +22,7 @@ export interface PurchaseOrderLine {
itemName: string
qty: number
processed: number
uom?: string
uom: Uom
price: number
status: string
stockInLine: StockInLine[]
@@ -35,6 +36,7 @@ export interface StockInLine {
itemId: number
itemNo: string
itemName: string
itemType: string
demandQty: number
acceptedQty: number
price: number
@@ -45,6 +47,7 @@ export interface StockInLine {
supplier: string
lotNo: string
poCode: string
uom: Uom
}

export const fetchPoList = cache(async () => {


+ 20
- 0
src/app/api/settings/uom/index.ts Ver fichero

@@ -0,0 +1,20 @@
import { cache } from "react";
import "server-only";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";

export interface Uom {
id: number
code: string
name: string
unit1: string
unit1Qty: number
unit2?: string
unit2Qty: number
unit3?: string
unit3Qty: number
unit4?: string
unit4Qty: number
sizeInGram: number
gramPerSmallestUnit: number
}

+ 12
- 1
src/app/utils/formatUtil.ts Ver fichero

@@ -1,3 +1,5 @@
import { Uom } from "../api/settings/uom";

export const manhourFormatter = new Intl.NumberFormat("en-HK", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
@@ -27,4 +29,13 @@ export const stockInLineStatusMap: { [status: string]: number } = {
"received": 7,
"completed": 8,
"rejected": 9,
};
};

export const calculateWeight = (qty: number, uom: Uom) => {
return qty * (uom.unit2Qty || 1) * (uom.unit3Qty || 1) * (uom.unit4Qty || 1);
}

export const returnWeightUnit = (uom: Uom) => {
return uom.unit4 || uom.unit3 || uom.unit2 || uom.unit1;
}


+ 23
- 4
src/components/PoDetail/PoDetail.tsx Ver fichero

@@ -41,6 +41,7 @@ import PoInputGrid from "./PoInputGrid";
import { QcItemWithChecks } from "@/app/api/qc";
import { useSearchParams } from "next/navigation";
import { WarehouseResult } from "@/app/api/warehouse";
import { calculateWeight, returnWeightUnit } from "@/app/utils/formatUtil";

type Props = {
po: PoResult;
@@ -65,7 +66,19 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
const { row } = props;
const [open, setOpen] = useState(false);
const [processedQty, setProcessedQty] = useState(row.processed);
const [currStatus, setCurrStatus] = useState(row.status);

useEffect(() => {
if (processedQty === row.qty) {
setCurrStatus("completed".toUpperCase());
} else if (processedQty > 0) {
setCurrStatus("receiving".toUpperCase());
} else {
setCurrStatus("pending".toUpperCase());
}
}, [processedQty]);
const totalWeight = useMemo(() => calculateWeight(row.qty, row.uom), []);
const weightUnit = useMemo(() => returnWeightUnit(row.uom), []);
return (
<>
<TableRow sx={{ "& > *": { borderBottom: "unset" }, color: "black" }}>
@@ -82,14 +95,18 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
<TableCell align="left">{row.itemName}</TableCell>
<TableCell align="left">{row.qty}</TableCell>
<TableCell align="left">{processedQty}</TableCell>
<TableCell align="left">{row.uom}</TableCell>
<TableCell align="left">{row.uom?.code}</TableCell>
<TableCell align="left">
{totalWeight} {weightUnit}
</TableCell>
{/* <TableCell align="left">{weightUnit}</TableCell> */}
<TableCell align="left">{row.price}</TableCell>
{/* <TableCell align="left">{row.expiryDate}</TableCell> */}
<TableCell align="left">{row.status}</TableCell>
<TableCell align="left">{currStatus}</TableCell>
</TableRow>
<TableRow>
{/* <TableCell /> */}
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={12}>
{/* <TableCell /> */}
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={12}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Table>
<TableBody>
@@ -139,6 +156,8 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
<TableCell align="left">{t("qty")}</TableCell>
<TableCell align="left">processed</TableCell>
<TableCell align="left">{t("uom")}</TableCell>
<TableCell align="left">{t("total weight")}</TableCell>
{/* <TableCell align="left">{t("weight unit")}</TableCell> */}
<TableCell align="left">{t("price")}</TableCell>
{/* <TableCell align="left">{t("expiryDate")}</TableCell> */}
<TableCell align="left">{t("status")}</TableCell>


+ 29
- 10
src/components/PoDetail/PoInputGrid.tsx Ver fichero

@@ -35,7 +35,7 @@ import PlayArrowIcon from "@mui/icons-material/PlayArrow";
import { PurchaseOrderLine, StockInLine } from "@/app/api/po";
import { createStockInLine, testFetch } from "@/app/api/po/actions";
import { useSearchParams } from "next/navigation";
import { stockInLineStatusMap } from "@/app/utils/formatUtil";
import { returnWeightUnit, calculateWeight, stockInLineStatusMap } from "@/app/utils/formatUtil";
import PoQcStockInModal from "./PoQcStockInModal";
import NotificationImportantIcon from "@mui/icons-material/NotificationImportant";
import { WarehouseResult } from "@/app/api/warehouse";
@@ -43,7 +43,7 @@ import LooksOneIcon from '@mui/icons-material/LooksOne';
import LooksTwoIcon from '@mui/icons-material/LooksTwo';
import Looks3Icon from '@mui/icons-material/Looks3';
import axiosInstance from "@/app/(main)/axios/axiosInstance";
import axios, { AxiosRequestConfig } from "axios";
// import axios, { AxiosRequestConfig } from "axios";
import { NEXT_PUBLIC_API_URL } from "@/config/api";
import qs from 'qs';
import QrCodeIcon from '@mui/icons-material/QrCode';
@@ -172,11 +172,12 @@ function PoInputGrid({
const fetchQcDefaultValue = useCallback(async () => {
const authHeader = axiosInstance.defaults.headers['Authorization'];
if (!authHeader) {
return; // Exit the function if the token is not set
return; // Exit the function if the token is not set
}
const res = await axios.get<QcItemWithChecks[]>(`${NEXT_PUBLIC_API_URL}/qcResult/${itemDetail.id}`)
console.log(authHeader)
const res = await axiosInstance.get<QcItemWithChecks[]>(`${NEXT_PUBLIC_API_URL}/qcResult/${itemDetail.id}`)
console.log(res)
}, [axiosInstance, axios])
}, [axiosInstance])

const handleQC = useCallback(
(id: GridRowId, params: any) => async () => {
@@ -320,6 +321,24 @@ function PoInputGrid({
editable: true,
// replace with tooltip + content
},
{
field: "uom",
headerName: "uom",
flex: 0.5,
renderCell: (params) => {
return params.row.uom.code;
},
},
{
field: "weight",
headerName: "weight",
flex: 0.5,
renderCell: (params) => {
const weight = calculateWeight(params.row.acceptedQty, params.row.uom);
const weightUnit = returnWeightUnit(params.row.uom);
return `${weight} ${weightUnit}`;
},
},
{
field: "status",
flex: 0.5,
@@ -329,7 +348,7 @@ function PoInputGrid({
field: "actions",
type: "actions",
headerName: "start | qc | escalation | stock in | putaway | delete",
flex: 1.5,
flex: 1,
cellClassName: "actions",
getActions: (params) => {
console.log(params.row.status);
@@ -357,9 +376,7 @@ function PoInputGrid({
// marginRight: 1,
}}
disabled={
// stockInLineStatusMap[status] <= 0 ||
// stockInLineStatusMap[status] >= 5
stockInLineStatusMap[status] != 1
stockInLineStatusMap[status] < 1
}
// set _isNew to false after posting
// or check status
@@ -405,7 +422,7 @@ function PoInputGrid({
color: "primary.main",
// marginRight: 1,
}}
disabled={stockInLineStatusMap[status] !== 7}
disabled={stockInLineStatusMap[status] < 7}
// set _isNew to false after posting
// or check status
onClick={handlePutAway(params.row.id, params)}
@@ -446,6 +463,7 @@ function PoInputGrid({
);

const addRow = useCallback(() => {
console.log(itemDetail)
const newEntry = {
id: Date.now(),
_isNew: true,
@@ -455,6 +473,7 @@ function PoInputGrid({
itemNo: itemDetail.itemNo,
itemName: itemDetail.itemName,
acceptedQty: itemDetail.qty - currQty, // this bug
uom: itemDetail.uom,
status: "draft",
};
setEntries((e) => [...e, newEntry]);


+ 29
- 35
src/components/PoDetail/PoQcStockInModal.tsx Ver fichero

@@ -14,6 +14,7 @@ import { StockInLineRow } from "./PoInputGrid";
import EscalationForm from "./EscalationForm";
import StockInForm from "./StockInForm";
import PutawayForm from "./PutawayForm";
import { stockInLineStatusMap } from "@/app/utils/formatUtil";

interface CommonProps extends Omit<ModalProps, "children"> {
setEntries: Dispatch<SetStateAction<StockInLineRow[]>>
@@ -88,7 +89,6 @@ const PoQcStockInModal: React.FC<Props> = ({
const onSubmit = useCallback<SubmitHandler<ModalFormInput & {}>>(
async (data, event) => {
let hasErrors = false;
console.log("errors");
console.log(errors);
console.log(data);
console.log(itemDetail);
@@ -105,14 +105,6 @@ const PoQcStockInModal: React.FC<Props> = ({
if (data.qcResult) {
acceptedQty = itemDetail.acceptedQty - data.qcResult.reduce((acc, curr) => acc + curr.failQty, 0)
}
console.log(acceptedQty)
// if (data.acceptedQty) {
// console.log("1")
// acceptedQty = parseInt(data.acceptedQty.toString())
// } else {
// console.log("2")
// acceptedQty = data.sampleRate
// }
const args = {
id: itemDetail.id,
purchaseOrderId: parseInt(params.get("id")!!),
@@ -130,7 +122,7 @@ const PoQcStockInModal: React.FC<Props> = ({
}
const res = await updateStockInLine(args)
if (Boolean(res.id)) {
// set entries
// update entries
const newEntries = res.entity as StockInLine[]
setEntries((prev) => {
const updatedEntries = [...prev]; // Create a new array
@@ -149,7 +141,6 @@ const PoQcStockInModal: React.FC<Props> = ({
// add loading
closeHandler({}, "backdropClick")
}

console.log(res)
// if (res)
} catch (e) {
@@ -161,20 +152,20 @@ const PoQcStockInModal: React.FC<Props> = ({
[t, itemDetail]
);
const canSubmit = useMemo(() => {
if (type === "qc") {
// console.log(itemDetail.status)
return formProps.formState.isValid
}
if (type === "stockIn") {
return formProps.formState.isValid
}
if (type === "putaway") {
return formProps.formState.isValid
}
return true
const renderSubmitButton = useMemo((): Boolean => {
if (itemDetail) {
const status = itemDetail.status
switch (type) {
case "qc":
return stockInLineStatusMap[status] === 1
case "putaway":
return stockInLineStatusMap[status] === 7
default:
return false; // Handle unexpected type
}
} else return false
}, [type, itemDetail])
console.log(canSubmit)
renderSubmitButton
return (
<>
<Modal open={open} onClose={closeHandler}>
@@ -188,17 +179,20 @@ const PoQcStockInModal: React.FC<Props> = ({
{type === "stockIn" && <StockInForm itemDetail={itemDetail} />}
{type === "escalation" && <EscalationForm itemDetail={itemDetail} />}
{type === "putaway" && <PutawayForm itemDetail={itemDetail} warehouse={warehouse} />}
<Stack direction="row" justifyContent="flex-end" gap={1}>
<Button
name="submit"
variant="contained"
startIcon={<Check />}
type="submit"
// disabled={submitDisabled}
>
{t("submit")}
</Button>
</Stack>
{renderSubmitButton ? (
<Stack direction="row" justifyContent="flex-end" gap={1}>
<Button
name="submit"
variant="contained"
startIcon={<Check />}
type="submit"
// disabled={submitDisabled}
>
{t("submit")}
</Button>
</Stack>
) : undefined
}
</Box>
</FormProvider>
</Modal>


+ 15
- 0
src/components/PoDetail/PutawayForm.tsx Ver fichero

@@ -35,6 +35,8 @@ import { GridEditInputCell } from "@mui/x-data-grid";
import { StockInLine } from "@/app/api/po";
import { WarehouseResult } from "@/app/api/warehouse";
import { stockInLineStatusMap } from "@/app/utils/formatUtil";
import { QRCodeSVG } from 'qrcode.react';
import { QrCode } from "../QrCode";

interface Props {
itemDetail: StockInLine;
@@ -106,6 +108,15 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse }) => {
[]
);

const qrContent = useMemo(() => ({
itemId: itemDetail.itemId,
lotNo: itemDetail.lotNo,
// expiryDate: itemDetail.expiryDate,
// productionDate: itemDetail.productionDate,
// supplier: itemDetail.supplier,
// poCode: itemDetail.poCode,
}),[itemDetail])

useEffect(() => {
setValue("status", "completed")
}, [])
@@ -197,6 +208,7 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse }) => {
max: itemDetail.acceptedQty,
valueAsNumber: true,
})}
defaultValue={itemDetail.acceptedQty}
error={Boolean(errors.acceptedQty)}
helperText={errors.acceptedQty?.message}
/>
@@ -215,6 +227,9 @@ const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse }) => {
/>
</FormControl>
</Grid>
<Grid item xs={12} style={{ display: 'flex', justifyContent: 'center' }}>
<QrCode content={qrContent} sx={{width: 200, height: 200}}/>
</Grid>
</Grid>
<Grid
container


+ 15
- 15
src/components/PoDetail/QcForm.tsx Ver fichero

@@ -67,21 +67,21 @@ const QcForm: React.FC<Props> = ({ qc, itemDetail }) => {
console.log(itemDetail);
// const [qc, setQc] = useState<QcItemWithChecks[]>([])
// const fetchQcCheck = useCallback(async () => {
// const authHeader = axiosInstance.defaults.headers['Authorization'];
// if (!authHeader) {
// return; // Exit the function if the token is not set
// }
// const params = {
// itemId: itemDetail.itemId
// }
// console.log(params)
// const res = await axios.get<QcItemWithChecks[]>(`${NEXT_PUBLIC_API_URL}/qcCheck`, { params })
// console.log(res)
// }, [axios])
// useEffect(() => {
// fetchQcCheck()
// }, [fetchQcCheck])
const fetchQcCheck = useCallback(async () => {
const authHeader = axiosInstance.defaults.headers['Authorization'];
if (!authHeader) {
return; // Exit the function if the token is not set
}
const params = {
itemId: itemDetail.itemId
}
console.log(params)
const res = await axios.get<QcItemWithChecks[]>(`${NEXT_PUBLIC_API_URL}/qcCheck`, { params })
console.log(res)
}, [axios])
useEffect(() => {
fetchQcCheck()
}, [fetchQcCheck])

const [recordQty, setRecordQty] = useState(0);
const columns = useMemo<GridColDef[]>(


+ 15
- 0
src/components/QrCode/QrCode.tsx Ver fichero

@@ -0,0 +1,15 @@
"use client"

import { QRCodeSVG } from 'qrcode.react';
import { CSSProperties } from 'react';

interface Props {
content: any;
sx?: CSSProperties;
}

export default function QrCode({ content, sx }: Props) {
console.log(content);
const jsonStr = JSON.stringify(content);
return <QRCodeSVG value={jsonStr} style={sx} />;
}

+ 1
- 0
src/components/QrCode/index.ts Ver fichero

@@ -0,0 +1 @@
export {default as QrCode} from "./QrCode"

+ 13
- 9
src/components/RoughSchedule/RoughScheduleWrapper.tsx Ver fichero

@@ -1,17 +1,21 @@
import { fetchAllItems, } from "@/app/api/settings/item";
import {RoughScheduleLoading} from "./RoughScheduleLoading";
import { fetchAllItems } from "@/app/api/settings/item";
import { RoughScheduleLoading } from "./RoughScheduleLoading";
import RSOverview from "./RoughSchedileSearchView";

interface SubComponents {
Loading: typeof RoughScheduleLoading;
Loading: typeof RoughScheduleLoading;
}

const RoughScheduleWrapper: ({}: {}) => Promise<JSX.Element> = async ({
// type,
}) => {
// console.log(type)
var result = await fetchAllItems()
return <RSOverview records={result} />;
type Props = {};

const RoughScheduleWrapper: React.FC<Props> & SubComponents = async (
{
// type,
}
) => {
// console.log(type)
var result = await fetchAllItems();
return <RSOverview records={[]} />;
};

RoughScheduleWrapper.Loading = RoughScheduleLoading;


Cargando…
Cancelar
Guardar