Bläddra i källkod

update putaway

master
kelvinsuen 3 månader sedan
förälder
incheckning
4c4571d52b
10 ändrade filer med 209 tillägg och 45 borttagningar
  1. +4
    -1
      src/app/utils/formatUtil.ts
  2. +21
    -5
      src/components/PoDetail/PutAwayForm.tsx
  3. +0
    -1
      src/components/PoDetail/QcStockInModal.tsx
  4. +2
    -2
      src/components/PoSearch/PoSearch.tsx
  5. +26
    -10
      src/components/PutAwayScan/PutAwayModal.tsx
  6. +93
    -0
      src/components/PutAwayScan/PutAwayReviewGrid.tsx
  7. +40
    -22
      src/components/PutAwayScan/PutAwayScan.tsx
  8. +12
    -1
      src/components/PutAwayScan/index.ts
  9. +3
    -2
      src/i18n/zh/purchaseOrder.json
  10. +8
    -1
      src/i18n/zh/putAway.json

+ 4
- 1
src/app/utils/formatUtil.ts Visa fil

@@ -49,7 +49,10 @@ export const arrayToDayjs = (arr: ConfigType | (number | undefined)[], showTime:
tempArr = `${arr[0]?.toString().padStart(4, "0")}-${arr[1]?.toString().padStart(2, "0")}-${arr[2]?.toString().padStart(2, "0")}`;
if (showTime) {
// [year, month, day, hour, minute, second]
tempArr += ` ${arr[3]?.toString().padStart(2, "0")}:${arr[4]?.toString().padStart(2, "0")}:${arr[5]?.toString().padStart(2, "0")}`;
tempArr += ` ${
arr[3]?.toString().padStart(2, "0")}:${
arr[4]?.toString().padStart(2, "0")}:${
(arr[5] ?? 0)?.toString().padStart(2, "0")}`;
}
}



+ 21
- 5
src/components/PoDetail/PutAwayForm.tsx Visa fil

@@ -39,6 +39,7 @@ import { GridEditInputCell } from "@mui/x-data-grid";
import { StockInLine } from "@/app/api/po";
import { WarehouseResult } from "@/app/api/warehouse";
import {
arrayToDateTimeString,
OUTPUT_DATE_FORMAT,
stockInLineStatusMap,
} from "@/app/utils/formatUtil";
@@ -231,19 +232,33 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM
return `${params.api.getRowIndexRelativeToVisibleRows(params.id) + 1}.`
},
},
{
field: "putawayDate",
headerName: t("putawayDatetime"),
flex: 1,
editable: false,
renderCell(params) {
return `${(arrayToDateTimeString(params.value))}`;
},
},
{
field: "putawayUser",
headerName: t("putawayUser"),
flex: 1,
editable: false,
},
{
field: "qty",
headerName: t("qty"),
headerName: t("putawayQty"),
flex: 0.5,
editable: false,
// renderCell(params) {
// return <>100</>
// },
headerAlign: "right",
align: "right",
},
{
field: "warehouse",
headerName: t("warehouse"),
flex: 1,
flex: 2,
editable: false,
renderEditCell: (params) => {
const index = params.api.getRowIndexRelativeToVisibleRows(params.row.id)
@@ -275,6 +290,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM
// return <>{filteredWarehouse[0].name}</>
// },
},
// {
// field: "printQty",
// headerName: t("printQty"),


+ 0
- 1
src/components/PoDetail/QcStockInModal.tsx Visa fil

@@ -163,7 +163,6 @@ const [qcItems, setQcItems] = useState(dummyQCData)
setViewOnly(isViewOnly)
}
console.log("Modal ItemDetail updated:", itemDetail);
console.log("%c SHOW PUTAWAY? ", "color:lime", showPutaway);
if (showPutaway) { setTabIndex(1); } else { setTabIndex(0); }
}, [itemDetail]);



+ 2
- 2
src/components/PoSearch/PoSearch.tsx Visa fil

@@ -48,7 +48,7 @@ const PoSearch: React.FC<Props> = ({
const searchCriteria: Criterion<SearchParamNames>[] = useMemo(() => {
const searchCriteria: Criterion<SearchParamNames>[] = [
{ label: t("Supplier"), paramName: "supplier", type: "text" },
{ label: t("Po No."), paramName: "code", type: "text" },
{ label: t("PO No."), paramName: "code", type: "text" },
{
label: t("Escalated"),
paramName: "escalated",
@@ -141,7 +141,7 @@ const PoSearch: React.FC<Props> = ({
},
{
name: "code",
label: `${t("Po No.")} &\n${t("Supplier")}`,
label: `${t("PO No.")} &\n${t("Supplier")}`,
renderCell: (params) => {
return <>{params.code}<br/>{params.supplier}</>
},


+ 26
- 10
src/components/PutAwayScan/PutAwayModal.tsx Visa fil

@@ -35,6 +35,7 @@ import StockInForm from "../PoDetail/StockInForm";
import { arrayToDateString, INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import { QrCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider";
import { msg } from "../Swal/CustomAlerts";
import { PutAwayRecord } from ".";


interface Props extends Omit<ModalProps, "children"> {
@@ -42,6 +43,7 @@ interface Props extends Omit<ModalProps, "children"> {
stockInLineId: number;
warehouseId: number;
scanner: QrCodeScanner;
addPutAwayHistory: (putAwayData: PutAwayRecord) => void;
}
const style = {
position: "absolute",
@@ -69,7 +71,7 @@ const scannerStyle = {
width: { xs: "60%", sm: "60%", md: "60%" },
};

const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId, warehouseId, scanner }) => {
const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId, warehouseId, scanner, addPutAwayHistory }) => {
const { t } = useTranslation("putAway");
const [serverError, setServerError] = useState("");
const params = useSearchParams();
@@ -77,7 +79,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
const [isOpenScanner, setIsOpenScanner] = useState<boolean>(false);
const [itemDetail, setItemDetail] = useState<StockInLine>();
const [putAwayQty, setPutAwayQty] = useState<number>(0);
const [totalPutAwayQty, setTotalPutAwayQty] = useState<number>(0);
const [unavailableText, setUnavailableText] = useState<string | undefined>(
undefined,
);
@@ -124,7 +126,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
(...args) => {
setVerified(false);
setItemDetail(undefined);
setPutAwayQty(0);
setTotalPutAwayQty(0);
onClose?.(...args);
// reset();
},
@@ -177,7 +179,8 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
formProps.reset({
...defaultNewValue
})
setPutQty(itemDetail?.demandQty);
const total = itemDetail.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0;
setPutQty(itemDetail?.demandQty - total);
console.log("%c Loaded data:", "color:lime", defaultNewValue);
} else {
switch (itemDetail.status) {
@@ -201,8 +204,8 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
const res = await fetchStockInLineInfo(stockInLineId);
console.log("%c Fetched Stock In Line Info:", "color:gold", res);

const totalPutAwayQty = res.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0;
setPutAwayQty(totalPutAwayQty);
const total = res.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0;
setTotalPutAwayQty(total);
setItemDetail(res);
} catch (e) {
console.log("%c Error when fetching Stock In Line: ", "color:red", e);
@@ -224,9 +227,9 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
if (!Number.isInteger(qty)) {
setQtyError(t("value must be integer"));
}
if (qty > itemDetail?.acceptedQty!! - putAwayQty) {
if (qty > itemDetail?.demandQty!! - totalPutAwayQty) {
setQtyError(`${t("putQty must not greater than")} ${
itemDetail?.acceptedQty!! - putAwayQty}` );
itemDetail?.demandQty!! - totalPutAwayQty}` );
} else
// if (qty > itemDetail?.acceptedQty!!) {
// setQtyError(`${t("putQty must not greater than")} ${
@@ -290,11 +293,24 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
// update entries
console.log("%c Update Success:", "color:green", res);
// add loading

const putAwayData = {
itemName: itemDetail?.itemName,
itemCode: itemDetail?.itemNo,
poCode: itemDetail?.poCode,
lotNo: itemDetail?.lotNo,
warehouse: warehouse.find((w) => w.id == warehouseId)?.name,
putQty: putQty,
uom: itemDetail?.uom?.udfudesc,
} as PutAwayRecord;

addPutAwayHistory(putAwayData);

msg("貨品上架成功!");
closeHandler({}, "backdropClick");
}
console.log(res);
// console.log(res);
// if (res)
} catch (e) {
// server error
@@ -393,7 +409,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
lineHeight: "1.2",
},
}}
defaultValue={itemDetail?.acceptedQty!! - putAwayQty}
defaultValue={itemDetail?.demandQty!! - totalPutAwayQty}
// defaultValue={itemDetail.demandQty}
onChange={(e) => {
const value = e.target.value;


+ 93
- 0
src/components/PutAwayScan/PutAwayReviewGrid.tsx Visa fil

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

import {
Paper,
} from "@mui/material";
import { useEffect, useMemo } from "react";
import StyledDataGrid from "../StyledDataGrid";
import { useTranslation } from "react-i18next";
import { GridColDef } from "@mui/x-data-grid";
import { PutAwayRecord } from ".";

type Props = {
putAwayHistory : PutAwayRecord[];
};

const PutAwayReviewGrid: React.FC<Props> = ({ putAwayHistory }) => {
const { t } = useTranslation("putAway");
const columns: GridColDef[] = useMemo(() => [
{
field: "index",
headerName: t(""),
flex: 0.5,
renderCell: (params) => {
return (<b>{params.id}.</b>);
},
disableColumnMenu: true,
},
{
field: "poCode",
headerName: t("poCode"),
flex: 2,
disableColumnMenu: true,
},
{
field: "itemCode",
headerName: t("itemCode"),
flex: 1,
disableColumnMenu: true,
},
{
field: "itemName",
headerName: t("itemName"),
flex: 2,
disableColumnMenu: true,
},
{
field: "putQty",
headerName: t("putawayQty"),
flex: 1,
headerAlign: 'right',
align: 'right',
disableColumnMenu: true,
},
{
field: "uom",
headerName: t("uom"),
flex: 1.5,
disableColumnMenu: true,
},
{
field: "warehouse",
headerName: t("warehouse"),
flex: 2,
disableColumnMenu: true,
},
], []
)

return (<>
<Paper>
<StyledDataGrid
columns={columns}
rows={putAwayHistory}
autoHeight
sx={{
'& .MuiDataGrid-columnHeaderTitle': {
whiteSpace: 'nowrap',
overflow: 'visible',
textOverflow: 'clip',
lineHeight: 'normal',
paddingRight: '0px',
},
'& .MuiDataGrid-columnHeader': {
padding: '0 4px 0 4px',
},
}}
/>
</Paper>
</>)
}

export default PutAwayReviewGrid;

+ 40
- 22
src/components/PutAwayScan/PutAwayScan.tsx Visa fil

@@ -29,6 +29,8 @@ import {
import { useSearchParams } from "next/navigation";
import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
import PutAwayModal from "./PutAwayModal";
import { PutAwayRecord } from ".";
import PutAwayReviewGrid from "./PutAwayReviewGrid";

type Props = {
warehouse : WarehouseResult[];
@@ -43,6 +45,7 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
const [openPutAwayModal, setOpenPutAwayModal] = useState(false);
const [scannedSilId, setScannedSilId] = useState<number>(0); // TODO use QR code info
const [scannedWareHouseId, setScannedWareHouseId] = useState<number>(0); // TODO use QR code info
const [putAwayHistory, setPutAwayHistory] = useState<PutAwayRecord[]>([]);

// QR Code Scanner
const scanner = useQrCodeScannerContext();
@@ -115,6 +118,12 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
};
}

const addPutAwayHistory = (putAwayData: PutAwayRecord) => {
console.log("%c Added new data to Putaway history: ", "color:orange", putAwayData);
const newPutaway = { ...putAwayData, id: putAwayHistory.length + 1 };
setPutAwayHistory([...putAwayHistory, newPutaway]); // Create a new array with the new row
// putAwayHistory.push(putAwayData);
};

useEffect(() => {
if (scannedSilId > 0) {
@@ -170,29 +179,38 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
}
}, [scanner.values]);

return (<>
<Paper sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center',}}
>
<Typography variant="h4">
{scanDisplay == "pending" ? t("Pending scan") : t("Rescan")}
</Typography>
<QrCodeScanner sx={{padding: "10px", fontSize : "150px"}}/>
</Paper>
<PutAwayModal
open={openPutAwayModal}
onClose={closeModal}
warehouse={warehouse}
stockInLineId={scannedSilId}
warehouseId={scannedWareHouseId}
scanner={scanner}
return (<>
<Paper sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center',}}
>
<Typography variant="h4">
{scanDisplay == "pending" ? t("Pending scan") : t("Rescan")}
</Typography>
<QrCodeScanner sx={{padding: "10px", fontSize : "150px"}}/>
</Paper>
{putAwayHistory.length > 0 && (<>
<Typography variant="h5">
{t("putAwayHistory")}
</Typography>
<PutAwayReviewGrid
putAwayHistory={putAwayHistory}
/>
</>)
</>)}
<PutAwayModal
open={openPutAwayModal}
onClose={closeModal}
warehouse={warehouse}
stockInLineId={scannedSilId}
warehouseId={scannedWareHouseId}
scanner={scanner}
addPutAwayHistory={addPutAwayHistory}
/>
</>)
}

export default PutAwayScan;

+ 12
- 1
src/components/PutAwayScan/index.ts Visa fil

@@ -1 +1,12 @@
export { default } from "./PutAwayScanWrapper"
export { default } from "./PutAwayScanWrapper"

export interface PutAwayRecord {
id: number;
itemName: string;
itemCode?: string;
warehouse: string;
putQty: number;
lotNo?: string;
poCode?: string;
uom?: string;
};

+ 3
- 2
src/i18n/zh/purchaseOrder.json Visa fil

@@ -25,7 +25,6 @@
"Complete PO": "完成採購訂單",
"General": "一般",
"Bind Storage": "綁定倉位",
"Po No.": "採購訂單編號",
"PO No.": "採購訂單編號",
"itemNo": "貨品編號",
"itemName": "貨品名稱",
@@ -149,5 +148,7 @@
"value must be integer": "請輸入整數",
"dn and qc info": "來貨及品檢詳情",
"Qc Decision": "品檢詳情",
"Print Qty": "列印數量"
"Print Qty": "列印數量",
"putawayDatetime": "上架時間",
"putawayUser": "上架同事"
}

+ 8
- 1
src/i18n/zh/putAway.json Visa fil

@@ -9,9 +9,16 @@
"Please scan warehouse qr code": "請掃瞄倉庫二維碼",
"scan loading": "載入中,請稍候…",
"warehouse": "倉庫",
"putawayQty": "上架數量",
"putQty": "是次上架數量",
"minimal value is 1": "最小為1",
"putQty must not greater than": "上架數量不得大於",
"value must be integer": "必須是整數",
"value must be a number": "必須是數字"
"value must be a number": "必須是數字",
"putAwayHistory": "是次上架記錄",
"itemName": "貨品名稱",
"lotNo": "貨品批號",
"poCode": "採購訂單編號",
"itemCode": "貨品編號",
"uom": "單位"
}

Laddar…
Avbryt
Spara