Sfoglia il codice sorgente

update stock in line

reset-do-picking-order
CANCERYS\kw093 1 settimana fa
parent
commit
2548b7a007
6 ha cambiato i file con 86 aggiunte e 68 eliminazioni
  1. +5
    -0
      src/app/api/stockIn/index.ts
  2. +33
    -12
      src/components/PoDetail/PoDetail.tsx
  3. +5
    -4
      src/components/PoDetail/PoInputGrid.tsx
  4. +2
    -2
      src/components/PoDetail/QcStockInModal.tsx
  5. +8
    -4
      src/components/PutAwayScan/PutAwayModal.tsx
  6. +33
    -46
      src/components/StockIn/StockInForm.tsx

+ 5
- 0
src/app/api/stockIn/index.ts Vedi File

@@ -109,6 +109,8 @@ export interface StockInLine {
itemType: string;
demandQty: number;
acceptedQty: number;
purchaseDemandQty?: number;
purchaseAcceptedQty?: number;
qty?: number;
receivedQty?: number;
processed?: number;
@@ -124,6 +126,8 @@ export interface StockInLine {
lotNo?: string;
poCode?: string;
uom?: Uom;
purchaseUomDesc?: string;
stockUomDesc?: string;
joCode?: string;
warehouseCode?: string;
defaultWarehouseId: number; // id for now
@@ -150,6 +154,7 @@ export interface EscalationInput {
export interface PutAwayLine {
id?: number
qty: number
stockQty?: number
warehouseId: number;
warehouse: string;
printQty: number;


+ 33
- 12
src/components/PoDetail/PoDetail.tsx Vedi File

@@ -451,7 +451,10 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => {
const oldId = row.id;
const acceptedQty = Number(polInputList[rowIndex].dnQty);
if (isNaN(acceptedQty) || acceptedQty <= 0) { alert("來貨數量必須大於0!"); return; } // Temp check, need update

if (!Number.isInteger(acceptedQty)) {
alert("來貨數量必須是整數(不能有小數)!");
return;
}
const postData = {
dnNo: dnFormProps.watch("dnNo"),
receiptDate: outputDateStringToInputDateString(dnFormProps.watch("receiptDate")),
@@ -491,22 +494,30 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => {
break;
case "dnQty":
// Allow empty input
if (raw.trim() === '') {
polInputList[rowIndex].dnQty = 0;
break;
}
const trimmed = raw.trim();

if (trimmed === "") {
polInputList[rowIndex].dnQty = 0;
break;
}
/*
// Keep digits only
const cleaned = raw.replace(/[^\d]/g, '');
if (cleaned === '') {
// If the user typed only non-digits, keep previous value
break;
}
*/
const parsed = Number(trimmed);

// Parse and clamp to non-negative integer
const next = Math.max(0, Math.floor(Number(cleaned)));
polInputList[rowIndex].dnQty = next;
// 不是合法數字(例如 "abc")
if (!Number.isFinite(parsed)) {
polInputList[rowIndex].dnQty = 0; // 或保留舊值,看你需求
break;
}

polInputList[rowIndex].dnQty = parsed; // 這裡允許小數,先存起來
break;
default:
break;
}
@@ -515,9 +526,16 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => {

// const [focusField, setFocusField] = useState<HTMLInputElement>();

const purchaseToStockRatio = (row.stockUom.purchaseRatioN ?? 1) / (row.stockUom.purchaseRatioD ?? 1) * (row.stockUom.stockRatioD ?? 1) / (row.stockUom.stockRatioN ?? 1)
const receivedTotal = decimalFormatter.format(row.stockInLine.filter((sil) => sil.purchaseOrderLineId === row.id).reduce((acc, cur) => acc + (cur.acceptedQty ?? 0),0) * purchaseToStockRatio);
const highlightColor = (Number(receivedTotal.replace(/,/g, '')) <= 0) ? "red" : "inherit";
// 本批收貨數量(訂單單位): 使用者在該行輸入的 dnQty
const batchPurchaseQty = polInputList[rowIndex]?.dnQty ?? 0;

// 已來貨總數(庫存單位): 同一 POL 底下所有 stock_in_line.acceptedQty 的合計
const totalStockReceived = row.stockInLine
.filter((sil) => sil.purchaseOrderLineId === row.id)
.reduce((acc, cur) => acc + (cur.acceptedQty ?? 0), 0);
const receivedTotalText = decimalFormatter.format(totalStockReceived);
const highlightColor =
Number(receivedTotalText.replace(/,/g, "")) <= 0 ? "red" : "inherit";
return (
<>
@@ -552,7 +570,10 @@ const PoDetail: React.FC<Props> = ({ po, warehouse, printerCombo }) => {
<TableCell align="right">{integerFormatter.format(row.processed)}</TableCell>
<TableCell align="left">{row.uom?.udfudesc}</TableCell>
{/* <TableCell align="right">{decimalFormatter.format(row.stockUom.stockQty)}</TableCell> */}
<TableCell sx={{ color: highlightColor}} align="right">{receivedTotal}</TableCell>
{/* <TableCell sx={{ color: highlightColor}} align="right">{receivedTotal}</TableCell> */}
<TableCell sx={{ color: highlightColor }} align="right">
{decimalFormatter.format(totalStockReceived)}
</TableCell>
<TableCell sx={{ color: highlightColor}} align="left">{row.stockUom.stockUomDesc}</TableCell>
{/* <TableCell align="right">
{decimalFormatter.format(totalWeight)} {weightUnit}


+ 5
- 4
src/components/PoDetail/PoInputGrid.tsx Vedi File

@@ -524,7 +524,8 @@ function PoInputGrid({
// editable: true,
// replace with tooltip + content
renderCell: (params) => {
return integerFormatter.format(params.value)
const qty = params.row.purchaseAcceptedQty ?? params.row.acceptedQty ?? 0;
return integerFormatter.format(qty);
}
},
{
@@ -545,9 +546,9 @@ function PoInputGrid({
// editable: true,
// replace with tooltip + content
renderCell: (params) => {
const baseQty = (params.row.acceptedQty ?? 0) * (itemDetail.stockUom.purchaseRatioN ?? 1) / (itemDetail.stockUom.purchaseRatioD ?? 1)
const stockQty = baseQty * (itemDetail.stockUom.stockRatioD ?? 1) / (itemDetail.stockUom.stockRatioN ?? 1)
return decimalFormatter.format(stockQty)
// acceptedQty 現在就是庫存單位數量
const stockQty = params.row.acceptedQty ?? 0;
return decimalFormatter.format(stockQty);
}
},
{


+ 2
- 2
src/components/PoDetail/QcStockInModal.tsx Vedi File

@@ -198,7 +198,7 @@ const PoQcStockInModalVer2: React.FC<Props> = ({
expiryDate: d.expiryDate ? arrayToDateString(d.expiryDate, "input") : undefined,
receiptDate: d.receiptDate ? arrayToDateString(d.receiptDate, "input")
: dayjs().add(0, "month").format(INPUT_DATE_FORMAT),
acceptQty: d.demandQty?? d.acceptedQty,
acceptQty: d.acceptedQty ?? d.demandQty,
// escResult: (d.escResult && d.escResult?.length > 0) ? d.escResult : [],
// qcResult: (d.qcResult && d.qcResult?.length > 0) ? d.qcResult : [],//[...dummyQCData],
warehouseId: d.defaultWarehouseId ?? 1,
@@ -451,7 +451,7 @@ const PoQcStockInModalVer2: React.FC<Props> = ({
async (data, event) => {
// Extract only putaway related fields
const putawayData = {
acceptQty: Number(data.acceptQty?? (stockInLineInfo?.demandQty?? (stockInLineInfo?.acceptedQty))), //TODO improve
acceptQty: Number(data.acceptQty ?? (stockInLineInfo?.acceptedQty ?? stockInLineInfo?.demandQty)), //TODO improve
warehouseId: data.warehouseId,
status: data.status, //TODO Fix it!
// ...data,


+ 8
- 4
src/components/PutAwayScan/PutAwayModal.tsx Vedi File

@@ -251,7 +251,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
formProps.reset({
...defaultNewValue
})
const total = itemDetail.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0;
const total = itemDetail.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? p.qty ?? 0), 0) ?? 0;
setPutQty(itemDetail?.acceptedQty - total);
// ✅ Get first warehouse from existing put away lines
@@ -294,7 +294,7 @@ 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 total = res.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0;
const total = res.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? p.qty ?? 0), 0) ?? 0;
setTotalPutAwayQty(total);
setItemDetail(res);
} catch (e) {
@@ -346,6 +346,10 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
// qty: acceptQty;
// }
try {
if (!itemDetail?.id || itemDetail.acceptedQty === undefined || itemDetail.acceptedQty === null) {
alert("找不到收貨數量(acceptedQty),請重新掃碼再試。");
return;
}
// 确定最终使用的 warehouseId
const effectiveWarehouseId = warehouseId > 0
? warehouseId
@@ -361,8 +365,8 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
purchaseOrderId: itemDetail?.purchaseOrderId,
purchaseOrderLineId: itemDetail?.purchaseOrderLineId,
itemId: itemDetail?.itemId,
acceptedQty: itemDetail?.acceptedQty,
acceptQty: itemDetail?.acceptedQty,
acceptedQty: Number(itemDetail.acceptedQty),
acceptQty: Number(itemDetail.acceptedQty),
status: "received",
// purchaseOrderId: parseInt(params.get("id")!),
// purchaseOrderLineId: itemDetail?.purchaseOrderLineId,


+ 33
- 46
src/components/StockIn/StockInForm.tsx Vedi File

@@ -370,47 +370,38 @@ const StockInForm: React.FC<Props> = ({
/>
</Grid></>
)}
{putawayMode && (
{putawayMode ? (
<>
<Grid item xs={6}>
<TextField
label={"本批次庫存收貨數量"}
fullWidth
sx={compactFields ? undefined : textfieldSx}
disabled={true}
value={`${itemDetail.acceptedQty ?? 0} (${itemDetail.stockUomDesc ?? ""})`}
/>
</Grid>
<Grid item xs={6}>
<TextField
label={"本批次採購收貨數量"}
fullWidth
sx={compactFields ? undefined : textfieldSx}
disabled={true}
value={`${itemDetail.purchaseAcceptedQty ?? 0} (${itemDetail.purchaseUomDesc ?? ""})`}
/>
</Grid>
<Grid item xs={6}>
<TextField
label={"已上架數量"}
fullWidth
sx={compactFields ? undefined : textfieldSx}
disabled={true}
value={`${itemDetail.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? 0), 0) ?? 0} (${itemDetail.stockUomDesc ?? ""})`}
/>
</Grid>
</>
) : (
<Grid item xs={6}>
<TextField
label={t("acceptedQty")}
fullWidth
sx={compactFields ? undefined : textfieldSx}
disabled={true}
value={itemDetail.acceptedQty}
// disabled={true}
// disabled={disabled}
// error={Boolean(errors.acceptedQty)}
// helperText={errors.acceptedQty?.message}
/>
</Grid>
)}
<Grid item xs={6}>
<TextField
label={t("uom")}
fullWidth
{...register("uom.udfudesc", {
required: "uom required!",
})}
// value={uom?.code}
sx={compactFields ? undefined : textfieldSx}
disabled={true}
/>
</Grid>
<Grid item xs={6}>
{putawayMode ? (
<TextField
label={t("processedQty")}
fullWidth
sx={compactFields ? undefined : textfieldSx}
disabled={true}
value={itemDetail.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0}
// disabled={true}
// disabled={disabled}
// error={Boolean(errors.acceptedQty)}
// helperText={errors.acceptedQty?.message}
/>
) : (
<TextField
label={t("acceptedQty")}
fullWidth
@@ -419,13 +410,9 @@ const StockInForm: React.FC<Props> = ({
{...register("acceptedQty", {
required: "acceptedQty required!",
})}
// disabled={true}
// disabled={disabled}
// error={Boolean(errors.acceptedQty)}
// helperText={errors.acceptedQty?.message}
/>
)}
</Grid>
</Grid>
)}
{/* <Grid item xs={4}>
<TextField
label={t("acceptedWeight")}


Caricamento…
Annulla
Salva