From 79edfec1f6e6789d3f6cc57db3cb0cfdffd64c32 Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期二, 24 二月 2026 15:50:32 +0800
Subject: [PATCH] 库位拣料出库数量调整
---
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java | 124 +++++++--
rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx | 2
rsf-admin/src/page/stockItem/StockItemCreate.jsx | 11
rsf-open-api/src/main/java/com/vincent/rsf/openApi/entity/params/ReportParams.java | 2
rsf-server/src/main/java/com/vincent/rsf/server/common/utils/QuantityUtils.java | 77 ++++++
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java | 2
rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx | 7
rsf-admin/src/page/orders/transfer/TransferCreate.jsx | 3
rsf-admin/src/page/stockItem/StockItemEdit.jsx | 11
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java | 173 ++++++++++---
rsf-admin/src/page/locItem/LocItemList.jsx | 2
rsf-admin/src/page/orders/check/SelectMatnrModal.jsx | 3
rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx | 3
rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx | 7
rsf-admin/src/page/orders/outStock/OutOrderModal.jsx | 4
rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx | 6
rsf-admin/src/page/locItem/LocItemEdit.jsx | 7
rsf-admin/src/page/orders/asnOrder/POItemModal.jsx | 5
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java | 2
rsf-admin/src/page/orders/transfer/ManualCreate.jsx | 3
rsf-admin/src/page/orders/outStock/OutOrderList.jsx | 6
rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx | 8
rsf-admin/src/page/orders/outStock/OutOrderItemList.jsx | 8
rsf-admin/src/page/work/components/locItemInfoModal.jsx | 3
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java | 6
rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx | 2
rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx | 4
rsf-admin/src/page/orders/outStock/OutStockPublic.jsx | 18
rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx | 4
rsf-admin/src/page/task/TaskPanel.jsx | 2
rsf-server/src/main/resources/mapper/manager/LocItemMapper.xml | 21 +
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocItemMapper.java | 6
rsf-admin/src/page/components/QuantityInput.jsx | 23 +
rsf-admin/src/page/task/TaskItemList.jsx | 4
rsf-admin/src/page/work/outBound/OutBoundList.jsx | 6
rsf-admin/src/page/locItem/LocItemCreate.jsx | 7
rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx | 5
rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx | 4
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java | 28 +
rsf-admin/src/utils/common.js | 32 ++
rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx | 3
rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx | 15
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaCheckOrderController.java | 2
rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java | 2
rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx | 6
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/ReportParams.java | 2
46 files changed, 518 insertions(+), 163 deletions(-)
diff --git a/rsf-admin/src/page/components/QuantityInput.jsx b/rsf-admin/src/page/components/QuantityInput.jsx
new file mode 100644
index 0000000..de7d7f6
--- /dev/null
+++ b/rsf-admin/src/page/components/QuantityInput.jsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { NumberInput } from 'react-admin';
+import { maxDecimalPlaces } from '@/utils/common';
+
+const MAX_DECIMALS = 6;
+const QUANTITY_VALIDATE = [maxDecimalPlaces(MAX_DECIMALS, '鏈�澶�6浣嶅皬鏁�')];
+
+/**
+ * 鏁伴噺杈撳叆妗嗭細鏀寔鏈�澶� 6 浣嶅皬鏁帮紝瓒呰繃鏃舵彁绀哄苟闃绘鎻愪氦
+ */
+const QuantityInput = (props) => {
+ const { validate = [], helperText, ...rest } = props;
+ const mergedValidate = Array.isArray(validate) ? [...QUANTITY_VALIDATE, ...validate] : [...QUANTITY_VALIDATE, validate];
+ return (
+ <NumberInput
+ validate={mergedValidate}
+ helperText={helperText ?? '鏈�澶�6浣嶅皬鏁�'}
+ {...rest}
+ />
+ );
+};
+
+export default QuantityInput;
diff --git a/rsf-admin/src/page/locItem/LocItemCreate.jsx b/rsf-admin/src/page/locItem/LocItemCreate.jsx
index 9dc1fde..8a78582 100644
--- a/rsf-admin/src/page/locItem/LocItemCreate.jsx
+++ b/rsf-admin/src/page/locItem/LocItemCreate.jsx
@@ -30,6 +30,7 @@
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
+import QuantityInput from "../components/QuantityInput";
const LocItemCreate = (props) => {
const { open, setOpen } = props;
@@ -186,19 +187,19 @@
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
- <NumberInput
+ <QuantityInput
label="table.field.locItem.anfme"
source="anfme"
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
- <NumberInput
+ <QuantityInput
label="table.field.locItem.qty"
source="qty"
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
- <NumberInput
+ <QuantityInput
label="table.field.locItem.workQty"
source="workQty"
/>
diff --git a/rsf-admin/src/page/locItem/LocItemEdit.jsx b/rsf-admin/src/page/locItem/LocItemEdit.jsx
index 8073eed..5c85ef7 100644
--- a/rsf-admin/src/page/locItem/LocItemEdit.jsx
+++ b/rsf-admin/src/page/locItem/LocItemEdit.jsx
@@ -23,6 +23,7 @@
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
+import QuantityInput from "../components/QuantityInput";
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
@@ -165,19 +166,19 @@
/>
</Stack>
<Stack direction='row' gap={2}>
- <NumberInput
+ <QuantityInput
label="table.field.locItem.anfme"
source="anfme"
/>
</Stack>
<Stack direction='row' gap={2}>
- <NumberInput
+ <QuantityInput
label="table.field.locItem.qty"
source="qty"
/>
</Stack>
<Stack direction='row' gap={2}>
- <NumberInput
+ <QuantityInput
label="table.field.locItem.workQty"
source="workQty"
/>
diff --git a/rsf-admin/src/page/locItem/LocItemList.jsx b/rsf-admin/src/page/locItem/LocItemList.jsx
index 008c672..f293130 100644
--- a/rsf-admin/src/page/locItem/LocItemList.jsx
+++ b/rsf-admin/src/page/locItem/LocItemList.jsx
@@ -163,7 +163,7 @@
<TextField source="maktx" label="table.field.locItem.maktx" />,
<TextField source="matnrCode" label="table.field.locItem.matnrCode" />,
<TextField source="unit" label="table.field.locItem.unit" />,
- <NumberField source="anfme" label="table.field.locItem.anfme" />,
+ <NumberField source="anfme" label="table.field.locItem.anfme" options={{ maximumFractionDigits: 6 }} />,
<TextField source="batch" label="table.field.locItem.batch" />,
<NumberField source="splrId" label="table.field.locItem.splrId" />,
<TextField source="spec" label="table.field.locItem.spec" />,
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx b/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx
index 5b99a52..cc1c6f1 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnCreateByPoModal.jsx
@@ -175,8 +175,8 @@
<TextField source="type$" label="table.field.purchase.type" />
<TextField source="wkType$" label="table.field.purchase.wkType" />
<TextField source="source" label="table.field.purchase.source" />
- <NumberField source="anfme" label="table.field.purchase.anfme" />
- <NumberField source="qty" label="table.field.purchase.qty" />
+ <NumberField source="anfme" label="table.field.purchase.anfme" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="qty" label="table.field.purchase.qty" options={{ maximumFractionDigits: 6 }} />
<TextField source="channel" label="table.field.purchase.channel" />
<TextField source="platCode" label="table.field.purchase.platCode" />
<DateField source="preArr" label="table.field.purchase.preArr" showTime />
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
index c659223..73cc1ac 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx
@@ -190,10 +190,10 @@
<TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />,
<TextField source="spec" label="table.field.asnOrderItem.spec" />,
<TextField source="model" label="table.field.asnOrderItem.model" />,
- <NumberField source="anfme" label="table.field.asnOrderItem.anfme" />,
- <NumberField source="qty" label="table.field.asnOrderItem.qty" />,
+ <NumberField source="anfme" label="table.field.asnOrderItem.anfme" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ maximumFractionDigits: 6 }} />,
<TextField source="stockUnit" label="table.field.asnOrderItem.stockUnit" />,
- <NumberField source="purQty" label="table.field.asnOrderItem.purQty" />,
+ <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ maximumFractionDigits: 6 }} />,
<TextField source="purUnit" label="table.field.asnOrderItem.purUnit" />,
<TextField source="splrCode" label="table.field.asnOrderItem.splrCode" />,
<TextField source="splrName" label="table.field.asnOrderItem.splrName" />,
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
index 11ed2a0..bbd50f4 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx
@@ -166,8 +166,8 @@
<NumberField source="poId" label="table.field.asnOrder.poId" />
<TextField source="type$" label="table.field.asnOrder.type" />
<TextField cellClassName="wkType" source="wkType$" label="table.field.asnOrder.wkType" />
- <NumberField source="anfme" label="table.field.asnOrder.anfme" />
- <NumberField source="qty" label="table.field.asnOrder.qty" />
+ <NumberField source="anfme" label="table.field.asnOrder.anfme" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="qty" label="table.field.asnOrder.qty" options={{ maximumFractionDigits: 6 }} />
<DateField source="arrTime" label="table.field.asnOrder.arrTime" showTime />
<TextField source="rleStatus$" label="table.field.asnOrder.rleStatus" sortable={false} />
<TextField source="logisNo" label="table.field.asnOrder.logisNo" />
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
index d26ea4c..c665217 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx
@@ -59,6 +59,7 @@
import SaveIcon from '@mui/icons-material/Save';
import AsnWareModal from "./AsnWareModal";
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import _, { set } from 'lodash';
import "./asnOrder.css";
@@ -518,7 +519,7 @@
minWidth: 100,
flex: 1,
editable: true,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
headerClassName: "custom",
},
// {
diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx
index 1353f3b..bd8a4c0 100644
--- a/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx
@@ -8,7 +8,7 @@
useListContext,
} from 'react-admin';
import PanelTypography from "../../components/PanelTypography";
-import * as Common from '@/utils/common'
+import { formatQuantity } from '@/utils/common';
import { styled } from "@mui/material/styles";
import request from '@/utils/request';
import debounce from 'lodash/debounce';
@@ -75,7 +75,8 @@
},
{
field: 'anfme',
- headerName: translate('table.field.asnOrderItem.purQty')
+ headerName: translate('table.field.asnOrderItem.purQty'),
+ valueFormatter: (v) => formatQuantity(v)
},
{
field: 'stockUnit',
@@ -91,7 +92,8 @@
},
{
field: 'qty',
- headerName: translate('table.field.asnOrderItem.qty')
+ headerName: translate('table.field.asnOrderItem.qty'),
+ valueFormatter: (v) => formatQuantity(v)
},
{
field: 'splrBatch',
diff --git a/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx b/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx
index 6f527d1..e09c0f4 100644
--- a/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx
@@ -208,9 +208,9 @@
<TextField source="matnrCode" label="table.field.asnOrderItem.matnrCode" />,
<TextField source="maktx" label="table.field.asnOrderItem.maktx" />,
<TextField source="splrBatch" label="table.field.asnOrderItem.splrBatch" />,
- <NumberField source="anfme" label="table.field.asnOrderItem.anfme" />,
- <NumberField source="qty" label="table.field.asnOrderItem.qty" />,
- <NumberField source="purQty" label="table.field.asnOrderItem.purQty" />,
+ <NumberField source="anfme" label="table.field.asnOrderItem.anfme" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ maximumFractionDigits: 6 }} />,
// <TextField source="splrName" label="table.field.asnOrderItem.splrName" />,
<TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />,
// <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />,
diff --git a/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx b/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx
index 65d8f88..a97eab4 100644
--- a/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx
+++ b/rsf-admin/src/page/orders/asnOrder/POItemModal.jsx
@@ -50,6 +50,7 @@
import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import { Add, Edit, Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
import { DataGrid, useGridApiRef, GRID_DATE_COL_DEF, GRID_DATETIME_COL_DEF, getGridDateOperators, useGridApiContext } from '@mui/x-data-grid';
@@ -277,7 +278,7 @@
minWidth: 100,
flex: 1,
editable: true,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
headerClassName: "custom",
},
{
@@ -286,7 +287,7 @@
type: 'number',
minWidth: 100,
flex: 1,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
},
{
field: 'unit',
diff --git a/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx b/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx
index a25c4c0..e6bb6f6 100644
--- a/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx
+++ b/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx
@@ -48,6 +48,7 @@
import MatnrInfoModal from "./MatnrInfoModal";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import { Add, Edit, Delete } from '@mui/icons-material';
import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
import DictionarySelect from "../../components/DictionarySelect";
@@ -416,7 +417,7 @@
minWidth: 120,
flex: 1,
editable: true,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
headerClassName: "custom",
},
{
diff --git a/rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx b/rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx
index e3d652a..b0834ab 100644
--- a/rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx
+++ b/rsf-admin/src/page/orders/outStock/MatnrInfoModal.jsx
@@ -20,6 +20,7 @@
import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import { DataGrid } from '@mui/x-data-grid';
import SaveIcon from '@mui/icons-material/Save';
import TreeSelectInput from "@/page/components/TreeSelectInput";
@@ -60,12 +61,14 @@
})
}
+ const getRowId = (row) => (row.locUseStatus$ != null ? `${row.id}_${row.locUseStatus$}` : String(row.id));
+
const handleSubmit = () => {
const hasarr = data.map(el => +el.matnrId);
const selectedData = selectedRows
- .filter((item) => !hasarr.includes(item))
- .map((id) => tableData.find((row) => row.id === id))
- .filter(Boolean);
+ .map((id) => tableData.find((row) => getRowId(row) === id))
+ .filter(Boolean)
+ .filter((row) => !hasarr.includes(row.id));
const deduped = [...new Map(selectedData.map((s) => [s.id, s])).values()];
const value = deduped.map((el, i) => {
const dynamicFields = dyFields.reduce((acc, item) => {
@@ -200,6 +203,7 @@
setDyFields={setDyFields}
selectedRows={selectedRows}
setSelectedRows={setSelectedRows}
+ getRowId={getRowId}
/>
</Box>
</DialogContent>
@@ -216,7 +220,7 @@
export default MatnrInfoModal;
-const AsnWareModalTable = ({ tableData, setTableData, page, isLoading, pageSize, setPage, rowCount, selectedRows, setSelectedRows, dyFields, setDyFields }) => {
+const AsnWareModalTable = ({ tableData, setTableData, page, isLoading, pageSize, setPage, rowCount, selectedRows, setSelectedRows, dyFields, setDyFields, getRowId }) => {
const translate = useTranslate();
const notify = useNotify();
@@ -232,7 +236,7 @@
{ field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 },
{ field: 'purchaseUnit', headerName: translate('table.field.matnr.purUnit'), width: 100 },
{ field: 'stockUnit', headerName: translate('table.field.matnr.stockUnit'), width: 100 },
- { field: 'stockQty', headerName: translate('table.field.matnr.stockQty') || '搴撳瓨鏁伴噺', width: 110, type: 'number', valueFormatter: (v) => (v != null ? Number(v) : 0) },
+ { field: 'stockQty', headerName: translate('table.field.matnr.stockQty') || '搴撳瓨鏁伴噺', width: 110, type: 'number', valueFormatter: (v) => formatQuantity(v) },
{ field: 'locUseStatus$', headerName: translate('table.field.loc.useStatus'), width: 120 },
{ field: 'locCodes$', headerName: translate('table.field.loc.locCode'), width: 180, flex: 1 },
{ field: 'stockLeval$', headerName: translate('table.field.matnr.stockLevel'), width: 100, sortable: false },
@@ -273,6 +277,7 @@
<div style={{ height: 400, width: '100%' }}>
<DataGrid
size="small"
+ getRowId={getRowId}
rows={tableData}
columns={columns}
checkboxSelection
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderItemList.jsx b/rsf-admin/src/page/orders/outStock/OutOrderItemList.jsx
index c78604b..5fd6707 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderItemList.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderItemList.jsx
@@ -181,10 +181,10 @@
<TextField source="matnrCode" label="table.field.outStockItem.matnrCode" />,
<TextField source="maktx" label="table.field.outStockItem.maktx" />,
<TextField source="platOrderCode" label="table.field.outStockItem.platOrderCode" />,
- <NumberField source="anfme" label="table.field.outStockItem.anfme" />,
- <NumberField source="purQty" label="table.field.outStockItem.purQty" />,
- <NumberField source="workQty" label="table.field.outStockItem.workQty" />,
- <NumberField source="qty" label="table.field.outStockItem.qty" />,
+ <NumberField source="anfme" label="table.field.outStockItem.anfme" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="purQty" label="table.field.outStockItem.purQty" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="qty" label="table.field.outStockItem.qty" options={{ maximumFractionDigits: 6 }} />,
<TextField source="stockUnit" label="table.field.outStockItem.stockUnit" />,
<TextField source="splrBatch" label="table.field.outStockItem.splrBatch" />,
<TextField source="purUnit" label="table.field.outStockItem.purUnit" />,
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
index 944d128..873320e 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderList.jsx
@@ -216,9 +216,9 @@
<TextField source="poCode" label="table.field.outStock.poCode" />
<TextField source="type$" label="table.field.outStock.type" />
<TextField cellClassName="wkType" source="wkType$" label="table.field.outStock.wkType" />
- <NumberField source="anfme" label="table.field.outStock.anfme" />
- <NumberField source="workQty" label="table.field.outStock.workQty" />
- <NumberField source="qty" label="table.field.outStock.qty" />
+ <NumberField source="anfme" label="table.field.outStock.anfme" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="workQty" label="table.field.outStock.workQty" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="qty" label="table.field.outStock.qty" options={{ maximumFractionDigits: 6 }} />
<TextField source="logisNo" label="table.field.outStock.logisNo" />
<TextField source="rleStatus$" label="table.field.outStock.rleStatus" sortable={false} />
<TextField source="updateBy$" label="common.field.updateBy" />
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx b/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx
index 67594a4..f7e5c60 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderModal.jsx
@@ -270,8 +270,8 @@
<TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" />
<TextField source="maktx" label="table.field.deliveryItem.matnrName" />
<TextField source="unit" label="table.field.deliveryItem.unit" />
- <NumberField source="anfme" label="table.field.deliveryItem.anfme" />
- <NumberField source="workQty" label="table.field.outStockItem.workQty" />
+ <NumberField source="anfme" label="table.field.deliveryItem.anfme" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ maximumFractionDigits: 6 }} />
<TextField source="splrName" label="table.field.deliveryItem.splrName" />
<TextField source="splrBatch" label="table.field.deliveryItem.splrBatch" />
<TextField source="updateBy$" label="common.field.updateBy" />
diff --git a/rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx b/rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx
index 6acbd99..ad5ced6 100644
--- a/rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutOrderPreview.jsx
@@ -9,6 +9,7 @@
useGetList,
} from 'react-admin';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import { styled } from '@mui/material/styles';
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import { DataGrid, useGridApiContext, GridActionsCellItem, useGridApiRef } from '@mui/x-data-grid';
@@ -105,6 +106,7 @@
{ field: 'maktx', headerName: '鐗╂枡鍚嶇О', width: 190 },
{
field: 'anfme', headerName: '鍑哄簱鏁伴噺', width: 110, type: 'number', editable: true,
+ valueFormatter: (v) => formatQuantity(v),
valueGetter: (value, row) => {
return row.anfme - row.workQty - row.qty;
},
@@ -119,6 +121,7 @@
},
{
field: 'workQty', headerName: '鍓╀綑鏁伴噺', width: 110, type: 'number',
+ valueFormatter: (v) => formatQuantity(v),
valueGetter: (value, row) => {
return row.anfme - row.workQty - row.qty;
},
diff --git a/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx b/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
index 2046043..9831e8c 100644
--- a/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
+++ b/rsf-admin/src/page/orders/outStock/OutStockPublic.jsx
@@ -43,6 +43,7 @@
import { styled } from '@mui/material/styles';
import { DataGrid, useGridApiContext, GridActionsCellItem, useGridApiRef } from '@mui/x-data-grid';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import ConfirmationNumberOutlinedIcon from '@mui/icons-material/ConfirmationNumberOutlined';
import CloseSharpIcon from '@mui/icons-material/CloseSharp';
import ConfirmButton from '../../components/ConfirmButton';
@@ -227,12 +228,14 @@
console.log('API杩斿洖鐨勬暟鎹�:', responseData);
// 澶勭悊杩斿洖鐨勬暟鎹紝纭繚鏁版嵁缁撴瀯姝g‘
const processedData = (responseData || []).map((item, index) => {
+ // 鍑哄簱鍗曚笅鍙戜换鍔★細浼樺厛鐢ㄥ悗绔繑鍥炵殑 siteNo/sitesNo锛屾病鏈夊垯榛樿 1001
+ const defaultSiteNo = item.siteNo || item.sitesNo || '1001';
// 濡傛灉鏁版嵁鏈� locItem 宓屽缁撴瀯锛岄渶瑕佸睍寮�
if (item.locItem) {
return {
...item.locItem,
id: item.locItem.id || `temp_${index}`,
- siteNo: item.siteNo,
+ siteNo: defaultSiteNo,
staNos: item.staNos || [],
sourceId: item.sourceId,
source: item.source
@@ -241,7 +244,8 @@
// 濡傛灉鏁版嵁宸茬粡鏄墎骞崇粨鏋勶紝鐩存帴杩斿洖
return {
...item,
- id: item.id || `temp_${index}`
+ id: item.id || `temp_${index}`,
+ siteNo: defaultSiteNo
};
});
console.log('澶勭悊鍚庣殑鏁版嵁:', processedData);
@@ -334,9 +338,9 @@
<TextField source="poCode" label="table.field.outStockItem.poCode" />
<TextField source="matnrCode" label="table.field.outStockItem.matnrCode" />
<TextField source="maktx" label="table.field.outStockItem.maktx" />
- <NumberField source="anfme" label="table.field.outStockItem.anfme" />
- <NumberField source="workQty" label="table.field.outStockItem.workQty" />
- <NumberField source="qty" label="table.field.outStockItem.qty" />
+ <NumberField source="anfme" label="table.field.outStockItem.anfme" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="qty" label="table.field.outStockItem.qty" options={{ maximumFractionDigits: 6 }} />
<TextField source="stockUnit" label="table.field.outStockItem.stockUnit" />
<TextField source="splrName" label="table.field.outStockItem.splrName" />
</StyledDatagrid>
@@ -393,7 +397,7 @@
{ field: 'matnrCode', headerName: '鐗╂枡缂栫爜', width: 120 },
{ field: 'batch', headerName: '鎵规', width: 90 },
{ field: 'unit', headerName: '鍗曚綅', width: 60 },
- { field: 'outQty', headerName: '鍑哄簱鏁伴噺', width: 110, },
+ { field: 'outQty', headerName: '鍑哄簱鏁伴噺', width: 110, valueFormatter: (v) => formatQuantity(v) },
{
field: 'anfme', headerName: '搴撳瓨鏁伴噺', width: 110,
renderCell: (params) => (
@@ -449,7 +453,7 @@
return (
hasStock ? (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
- <span>{value}</span>
+ <span>{formatQuantity(value)}</span>
</Box>
) : (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
diff --git a/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx b/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
index e3c59a2..cbf48e8 100644
--- a/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
+++ b/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
@@ -54,6 +54,7 @@
import SaveIcon from '@mui/icons-material/Save';
import MatnrInfoModal from "./MatnrInfoModal";
import request from '@/utils/request';
+import { formatQuantity, hasMoreThan6Decimals } from '@/utils/common';
import "./asnOrder.css";
const SelectMatnrModal = (props) => {
@@ -123,6 +124,10 @@
const handleSubmit = async () => {
setFinally();
+ if (tabelData.some((item) => hasMoreThan6Decimals(item.anfme))) {
+ notify('鏈�澶�6浣嶅皬鏁�', { type: 'error' });
+ return;
+ }
setDisabled(true);
try {
if (asnId === 0) {
@@ -435,7 +440,7 @@
minWidth: 100,
flex: 1,
editable: true,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
headerClassName: "custom",
},
{
diff --git a/rsf-admin/src/page/orders/transfer/ManualCreate.jsx b/rsf-admin/src/page/orders/transfer/ManualCreate.jsx
index 2990e16..60ef7a7 100644
--- a/rsf-admin/src/page/orders/transfer/ManualCreate.jsx
+++ b/rsf-admin/src/page/orders/transfer/ManualCreate.jsx
@@ -47,6 +47,7 @@
import { minHeight, padding } from "@mui/system";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import _, { set } from 'lodash';
const ManualCreate = (props) => {
@@ -363,7 +364,7 @@
minWidth: 100,
flex: 1,
editable: true,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
},
{
field: 'splrCode',
diff --git a/rsf-admin/src/page/orders/transfer/TransferCreate.jsx b/rsf-admin/src/page/orders/transfer/TransferCreate.jsx
index a6a754e..088573a 100644
--- a/rsf-admin/src/page/orders/transfer/TransferCreate.jsx
+++ b/rsf-admin/src/page/orders/transfer/TransferCreate.jsx
@@ -36,6 +36,7 @@
import DictSelect from "../../components/DictSelect";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
const TransferCreate = (props) => {
const { open, setOpen, orderId } = props;
@@ -233,7 +234,7 @@
minWidth: 100,
flex: 1,
editable: true,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
headerClassName: "custom",
},
{
diff --git a/rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx b/rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx
index 6fc96b8..5cd738f 100644
--- a/rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx
+++ b/rsf-admin/src/page/statistics/stockManage/WarehouseStockInfo.jsx
@@ -49,6 +49,7 @@
import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import { Add, Edit, Delete } from '@mui/icons-material';
import { DataGrid, useGridApiRef, GRID_DATE_COL_DEF, GRID_DATETIME_COL_DEF, getGridDateOperators, useGridApiContext } from '@mui/x-data-grid';
import { LocalizationProvider, DatePicker, DateTimePicker } from '@mui/x-date-pickers';
@@ -293,7 +294,7 @@
minWidth: 100,
flex: 1,
editable: false,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
},
{
field: 'workQty',
@@ -301,7 +302,7 @@
type: 'number',
minWidth: 100,
flex: 1,
- valueFormatter: (val) => val < 0 ? 0 : val,
+ valueFormatter: (val) => formatQuantity(val != null && val >= 0 ? val : 0),
},
{
field: 'unit',
diff --git a/rsf-admin/src/page/stockItem/StockItemCreate.jsx b/rsf-admin/src/page/stockItem/StockItemCreate.jsx
index 925f54a..90bb02d 100644
--- a/rsf-admin/src/page/stockItem/StockItemCreate.jsx
+++ b/rsf-admin/src/page/stockItem/StockItemCreate.jsx
@@ -28,6 +28,7 @@
Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
+import QuantityInput from "../components/QuantityInput";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
@@ -125,10 +126,10 @@
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
- <NumberInput
+ <QuantityInput
label="table.field.stockItem.anfme"
source="anfme"
- validate={required()}
+ validate={[required()]}
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
@@ -139,10 +140,10 @@
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
- <NumberInput
+ <QuantityInput
label="table.field.stockItem.workQty"
source="workQty"
- validate={required()}
+ validate={[required()]}
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
@@ -160,7 +161,7 @@
/>
</Grid>
<Grid item xs={6} display="flex" gap={1}>
- <NumberInput
+ <QuantityInput
label="table.field.stockItem.qty"
source="qty"
/>
diff --git a/rsf-admin/src/page/stockItem/StockItemEdit.jsx b/rsf-admin/src/page/stockItem/StockItemEdit.jsx
index c87afcc..8c952ed 100644
--- a/rsf-admin/src/page/stockItem/StockItemEdit.jsx
+++ b/rsf-admin/src/page/stockItem/StockItemEdit.jsx
@@ -28,6 +28,7 @@
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
+import QuantityInput from "../components/QuantityInput";
const FormToolbar = () => {
const { getValues } = useFormContext();
@@ -104,10 +105,10 @@
/>
</Stack>
<Stack direction='row' gap={2}>
- <NumberInput
+ <QuantityInput
label="table.field.stockItem.anfme"
source="anfme"
- validate={required()}
+ validate={[required()]}
/>
</Stack>
<Stack direction='row' gap={2}>
@@ -118,10 +119,10 @@
/>
</Stack>
<Stack direction='row' gap={2}>
- <NumberInput
+ <QuantityInput
label="table.field.stockItem.workQty"
source="workQty"
- validate={required()}
+ validate={[required()]}
/>
</Stack>
<Stack direction='row' gap={2}>
@@ -139,7 +140,7 @@
/>
</Stack>
<Stack direction='row' gap={2}>
- <NumberInput
+ <QuantityInput
label="table.field.stockItem.qty"
source="qty"
/>
diff --git a/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx b/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx
index 5dc09cb..63661ba 100644
--- a/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx
+++ b/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx
@@ -24,6 +24,7 @@
import SelectMatnrInfo from "./SelectMatnrInfo";
import SaveIcon from '@mui/icons-material/Save';
import request from '@/utils/request';
+import { formatQuantity, hasMoreThan6Decimals } from '@/utils/common';
import "./asnOrder.css";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
@@ -80,6 +81,10 @@
}
}));
+ if (value.some((el) => hasMoreThan6Decimals(el.anfme) || hasMoreThan6Decimals(el.reviseQty))) {
+ notify('鏈�澶�6浣嶅皬鏁�');
+ return;
+ }
saveReviseLog(value);
};
@@ -238,6 +243,7 @@
minWidth: 100,
flex: 1,
editable: false,
+ valueFormatter: (v) => formatQuantity(v),
},
{
field: 'reviseQty',
@@ -247,6 +253,7 @@
flex: 1,
editable: true,
headerClassName: "custom",
+ valueFormatter: (v) => formatQuantity(v),
},
{
field: 'batch',
diff --git a/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx b/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx
index f848cf8..670c8ac 100644
--- a/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx
+++ b/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx
@@ -95,8 +95,8 @@
<TextField source="matnrCode" label="table.field.locItem.matnrCode" />
<TextField source="maktx" label="table.field.locItem.maktx" />
<TextField source="unit" label="table.field.locItem.unit" />
- <NumberField source="anfme" label="table.field.locItem.anfme" />
- <NumberField source="reviseQty" label="table.field.locItem.reviseQty" />
+ <NumberField source="anfme" label="table.field.locItem.anfme" options={{ maximumFractionDigits: 6 }} />
+ <NumberField source="reviseQty" label="table.field.locItem.reviseQty" options={{ maximumFractionDigits: 6 }} />
<CheckDiffField source="diffQty" label="table.field.locItem.diffQty" />
<TextField source="batch" label="table.field.locItem.batch" />
<TextField source="spec" label="table.field.locItem.spec" />
diff --git a/rsf-admin/src/page/task/TaskItemList.jsx b/rsf-admin/src/page/task/TaskItemList.jsx
index fc18fcd..3518ae1 100644
--- a/rsf-admin/src/page/task/TaskItemList.jsx
+++ b/rsf-admin/src/page/task/TaskItemList.jsx
@@ -153,8 +153,8 @@
<TextField source="maktx" label="table.field.taskItem.maktx" />,
<TextField source="matnrCode" label="table.field.taskItem.matnrCode" />,
<TextField source="unit" label="table.field.taskItem.unit" />,
- <NumberField source="anfme" label="table.field.taskItem.anfme" />,
- <NumberField source="qty" label="table.field.taskItem.qty" />,
+ <NumberField source="anfme" label="table.field.taskItem.anfme" options={{ maximumFractionDigits: 6 }} />,
+ <NumberField source="qty" label="table.field.taskItem.qty" options={{ maximumFractionDigits: 6 }} />,
<TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />,
<TextField source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />,
<TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />,
diff --git a/rsf-admin/src/page/task/TaskPanel.jsx b/rsf-admin/src/page/task/TaskPanel.jsx
index c9c429d..0a001ad 100644
--- a/rsf-admin/src/page/task/TaskPanel.jsx
+++ b/rsf-admin/src/page/task/TaskPanel.jsx
@@ -70,7 +70,7 @@
<TextField source="maktx" label="table.field.taskItem.maktx" />
<TextField source="matnrCode" label="table.field.taskItem.matnrCode" />
<TextField source="unit" label="table.field.taskItem.unit" />
- <NumberField source="anfme" label="table.field.taskItem.anfme" />
+ <NumberField source="anfme" label="table.field.taskItem.anfme" options={{ maximumFractionDigits: 6 }} />
<TextField source="batch" label="table.field.taskItem.batch" />
<TextField source="spec" label="table.field.taskItem.spec" />
<TextField source="model" label="table.field.taskItem.model" />
diff --git a/rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx b/rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx
index 89f8a5e..4fdab48 100644
--- a/rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx
+++ b/rsf-admin/src/page/work/checkOutBound/CheckOutBoundList.jsx
@@ -56,6 +56,7 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import LocItemInfoModal from "../components/locItemInfoModal";
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
@@ -220,6 +221,7 @@
type: 'number',
width: 100,
editable: false,
+ valueFormatter: (v) => formatQuantity(v),
},
// {
// field: 'workQty',
diff --git a/rsf-admin/src/page/work/components/locItemInfoModal.jsx b/rsf-admin/src/page/work/components/locItemInfoModal.jsx
index c986926..c589cd8 100644
--- a/rsf-admin/src/page/work/components/locItemInfoModal.jsx
+++ b/rsf-admin/src/page/work/components/locItemInfoModal.jsx
@@ -15,6 +15,7 @@
import DialogCloseButton from "../../components/DialogCloseButton";
import { useTranslate, useNotify, useRefresh } from 'react-admin';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import { DataGrid } from '@mui/x-data-grid';
import SaveIcon from '@mui/icons-material/Save';
import TreeSelectInput from "@/page/components/TreeSelectInput";
@@ -179,7 +180,7 @@
{ field: 'matnrCode', headerName: translate('table.field.locItem.matnrCode'), width: 200 },
{ field: 'maktx', headerName: translate('table.field.locItem.maktx'), width: 300 },
{ field: 'batch', headerName: translate('table.field.locItem.batch'), width: 100 },
- { field: 'anfme', headerName: translate('table.field.locItem.anfme'), width: 100 },
+ { field: 'anfme', headerName: translate('table.field.locItem.anfme'), width: 100, valueFormatter: (v) => formatQuantity(v) },
{ field: 'unit', headerName: translate('table.field.locItem.unit'), width: 100 },
])
diff --git a/rsf-admin/src/page/work/outBound/OutBoundList.jsx b/rsf-admin/src/page/work/outBound/OutBoundList.jsx
index f36d6f0..dc70f67 100644
--- a/rsf-admin/src/page/work/outBound/OutBoundList.jsx
+++ b/rsf-admin/src/page/work/outBound/OutBoundList.jsx
@@ -57,6 +57,7 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import LocItemInfoModal from "../components/locItemInfoModal";
import { Delete } from '@mui/icons-material';
import StaSelect from "../components/StaSelect";
@@ -219,8 +220,8 @@
width: 100,
type: 'number',
editable: true,
- headerClassName: "custom",
-
+ headerClassName: "custom",
+ valueFormatter: (v) => formatQuantity(v),
},
{
field: 'anfme',
@@ -228,6 +229,7 @@
type: 'number',
width: 100,
editable: false,
+ valueFormatter: (v) => formatQuantity(v),
},
// {
// field: 'workQty',
diff --git a/rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx b/rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
index a036f5e..a106b5b 100644
--- a/rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
+++ b/rsf-admin/src/page/work/stockTransfer/stockTransferList.jsx
@@ -57,6 +57,7 @@
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import request from '@/utils/request';
+import { formatQuantity } from '@/utils/common';
import LocItemInfoModal from "../components/locItemInfoModal";
import { Delete } from '@mui/icons-material';
import _, { set } from 'lodash';
@@ -268,6 +269,7 @@
type: 'number',
width: 100,
editable: false,
+ valueFormatter: (v) => formatQuantity(v),
},
// {
// field: 'workQty',
diff --git a/rsf-admin/src/utils/common.js b/rsf-admin/src/utils/common.js
index 309c6eb..3874cd3 100644
--- a/rsf-admin/src/utils/common.js
+++ b/rsf-admin/src/utils/common.js
@@ -1,4 +1,36 @@
+/** 搴撳瓨/鏁伴噺鏄剧ず锛氫繚鐣欐渶澶�6浣嶅皬鏁帮紝鍘绘帀鏈熬澶氫綑鐨�0锛堜笉寮哄埗琛ラ浂锛� */
+export const formatQuantity = (value) => {
+ if (value == null || value === '') return '0';
+ const n = Number(value);
+ if (Number.isNaN(n)) return '0';
+ if (n < 0) return '0';
+ return n % 1 === 0 ? String(n) : n.toFixed(6).replace(/\.?0+$/, '');
+};
+
+/** 鏍¢獙鏈�澶� N 浣嶅皬鏁帮紝鐢ㄤ簬鏁伴噺绫诲瓧娈碉紱瓒呰繃鏃惰繑鍥為敊璇俊鎭苟闃绘鎻愪氦 */
+export const maxDecimalPlaces = (maxDecimals, message) => {
+ const factor = Math.pow(10, maxDecimals);
+ const msg = message || `鏈�澶�${maxDecimals}浣嶅皬鏁癭;
+ return (value) => {
+ if (value == null || value === '') return undefined;
+ const n = Number(value);
+ if (Number.isNaN(n)) return undefined;
+ const rounded = Math.round(n * factor) / factor;
+ if (Math.abs(n - rounded) > 1e-10) return msg;
+ return undefined;
+ };
+};
+
+/** 鍒ゆ柇鏁板�兼槸鍚﹁秴杩� 6 浣嶅皬鏁帮紙鐢ㄤ簬鎻愪氦鍓嶆牎楠岋級 */
+export const hasMoreThan6Decimals = (value) => {
+ if (value == null || value === '') return false;
+ const n = Number(value);
+ if (Number.isNaN(n)) return false;
+ const rounded = Math.round(n * 1e6) / 1e6;
+ return Math.abs(n - rounded) > 1e-10;
+};
+
export const extractNavMenus = (data) => {
if (!data) {
return;
diff --git a/rsf-open-api/src/main/java/com/vincent/rsf/openApi/entity/params/ReportParams.java b/rsf-open-api/src/main/java/com/vincent/rsf/openApi/entity/params/ReportParams.java
index ed961ab..cb7d581 100644
--- a/rsf-open-api/src/main/java/com/vincent/rsf/openApi/entity/params/ReportParams.java
+++ b/rsf-open-api/src/main/java/com/vincent/rsf/openApi/entity/params/ReportParams.java
@@ -10,7 +10,7 @@
@Data
@Accessors(chain = true)
-@ApiModel(value = "ReportParams", description = "甯屾棩ERP涓婃姤鍙傛暟")
+@ApiModel(value = "ReportParams", description = "ERP涓婃姤鍙傛暟")
public class ReportParams implements Serializable {
@ApiModelProperty("璁㈠崟绫诲瀷")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/ReportParams.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/ReportParams.java
index 6d1e661..01c5289 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/ReportParams.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/ReportParams.java
@@ -11,7 +11,7 @@
@Data
@Accessors(chain = true)
-@ApiModel(value = "ReportParams", description = "甯屾棩ERP涓婃姤鍙傛暟")
+@ApiModel(value = "ReportParams", description = "ERP涓婃姤鍙傛暟")
public class ReportParams implements Serializable {
@ApiModelProperty("璁㈠崟绫诲瀷")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaCheckOrderController.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaCheckOrderController.java
index dd91c71..912479a 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaCheckOrderController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/PdaCheckOrderController.java
@@ -46,7 +46,7 @@
return pdaCheckOrderService.getCheckTaskItemList2(map.get("barcode"));
}
- @ApiOperation("甯屾棩鏃犲崟鎹复鏃剁洏鐐�")
+ @ApiOperation("鏃犲崟鎹复鏃剁洏鐐�")
@PostMapping("/check/temp/items")
public R tempCheckItem(@RequestBody Map<String, String> map) {
if (Objects.isNull(map)) {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java
index a14ca64..9252455 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaCheckOrderServiceImpl.java
@@ -263,7 +263,7 @@
/**
* @author Ryan
* @date 2025/11/5
- * @description: 甯屾棩鏃犲崟鎹复鏃剁洏鐐�
+ * @description: 鏃犲崟鎹复鏃剁洏鐐�
* @version 1.0
*/
@Override
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java
index efc1a52..69b689b 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/PdaOutStockServiceImpl.java
@@ -79,7 +79,9 @@
@Override
public R getOutStockTaskItem(String barcode) {
LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<>();
- lambdaQueryWrapper.eq(Task::getBarcode, barcode);
+ lambdaQueryWrapper.eq(Task::getBarcode, barcode)
+ .orderByDesc(Task::getId)
+ .last("limit 1");
Task task = taskService.getOne(lambdaQueryWrapper);
if (null == task) {
return R.error("鏈煡璇㈠埌鐩稿叧浠诲姟");
@@ -97,12 +99,16 @@
@Synchronized
public R saveOutTaskSts(String barcode) {
LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<>();
- lambdaQueryWrapper.eq(Task::getBarcode, barcode);
+ lambdaQueryWrapper.eq(Task::getBarcode, barcode)
+ .orderByDesc(Task::getId)
+ .last("limit 1");
Task task = taskService.getOne(lambdaQueryWrapper);
if (null == task) {
throw new CoolException("鏈壘鍒板鍣ㄥ彿瀵瑰簲浠诲姟");
}
- if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) {
+ // 鍏佽 199锛圵AVE_SEED 鎾涓�/寰呯‘璁わ級鎴� 196锛圓WAIT 绛夊緟纭锛夛紝涓庣洏鐐� PDA 閫昏緫涓�鑷�
+ if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)
+ && !task.getTaskStatus().equals(TaskStsType.AWAIT.id)) {
return R.error("浠诲姟鐘舵�佷笉鏄瓑寰呯‘璁�");
}
@@ -153,7 +159,9 @@
if (Cools.isEmpty(barcode)) {
throw new CoolException("鍙傛暟鏈夎");
}
- Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, barcode));
+ Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, barcode)
+ .orderByDesc(Task::getId)
+ .last("limit 1"));
if (null == task) {
throw new CoolException("鏈壘鍒板鍣ㄥ彿瀵瑰簲浠诲姟");
}
@@ -232,7 +240,9 @@
if (Objects.isNull(param.get("orderId"))) {
return R.error("璁㈠崟ID涓嶈兘涓虹┖锛侊紒");
}
- Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, param.get("barcode").toString()));
+ Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, param.get("barcode").toString())
+ .orderByDesc(Task::getId)
+ .last("limit 1"));
if (Objects.isNull(task)) {
throw new CoolException("鏁版嵁閿欒锛屼换鍔℃。宸蹭笉瀛樺湪锛侊紒");
}
@@ -280,7 +290,9 @@
if (Objects.isNull(params.getTaskItems()) || params.getTaskItems().isEmpty()) {
return R.error("鎷h揣鏄庣粏涓嶈兘涓虹┖锛�");
}
- Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.getBarcode()));
+ Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.getBarcode())
+ .orderByDesc(Task::getId)
+ .last("limit 1"));
if (null == task) {
return R.error("鏈壘鍒版墭鐩樺搴旂殑浠诲姟");
}
@@ -542,7 +554,9 @@
return R.error("鏁版嵁閿欒锛侊紒");
}
- Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, containerWaveParam.getContainer()));
+ Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, containerWaveParam.getContainer())
+ .orderByDesc(Task::getId)
+ .last("limit 1"));
if (null == task) {
return R.error("鏈壘鍒版墭鐩樺搴旂殑浠诲姟");
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/utils/QuantityUtils.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/utils/QuantityUtils.java
new file mode 100644
index 0000000..9f774f6
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/utils/QuantityUtils.java
@@ -0,0 +1,77 @@
+package com.vincent.rsf.server.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 鏁伴噺杩愮畻宸ュ叿锛氫娇鐢� BigDecimal 閬垮厤 Double 绮惧害闂銆�
+ * 瀹炰綋浠嶄负 Double 鏃讹紝杩愮畻鐢ㄦ湰宸ュ叿鍐嶈浆鍥� Double锛堜繚鐣� 6 浣嶅皬鏁帮級銆�
+ */
+public final class QuantityUtils {
+
+ private static final int SCALE = 6;
+ private static final RoundingMode ROUNDING = RoundingMode.HALF_UP;
+
+ private QuantityUtils() {
+ }
+
+ private static BigDecimal toBigDecimal(Double v) {
+ if (v == null) {
+ return BigDecimal.ZERO;
+ }
+ return BigDecimal.valueOf(v);
+ }
+
+ /**
+ * 鍔犳硶锛歛 + b锛岀粨鏋滀繚鐣� 6 浣嶅皬鏁拌浆 Double
+ */
+ public static Double add(Double a, Double b) {
+ return toBigDecimal(a).add(toBigDecimal(b)).setScale(SCALE, ROUNDING).doubleValue();
+ }
+
+ /**
+ * 鍑忔硶锛歛 - b锛岀粨鏋滀繚鐣� 6 浣嶅皬鏁拌浆 Double
+ */
+ public static Double subtract(Double a, Double b) {
+ return toBigDecimal(a).subtract(toBigDecimal(b)).setScale(SCALE, ROUNDING).doubleValue();
+ }
+
+ /**
+ * 姣旇緝锛歛 涓� b 澶у皬锛岄伩鍏嶇洿鎺ョ敤 Double 姣旇緝銆�
+ * 杩斿洖 a.compareTo(b)锛氳礋/0/姝�
+ */
+ public static int compare(Double a, Double b) {
+ return toBigDecimal(a).compareTo(toBigDecimal(b));
+ }
+
+ /**
+ * a > 0
+ */
+ public static boolean isPositive(Double a) {
+ return compare(a, 0.0) > 0;
+ }
+
+ /**
+ * a >= 0
+ */
+ public static boolean isNonNegative(Double a) {
+ return compare(a, 0.0) >= 0;
+ }
+
+ /**
+ * a <= 0
+ */
+ public static boolean isNonPositive(Double a) {
+ return compare(a, 0.0) <= 0;
+ }
+
+ /**
+ * 缁熶竴鑸嶅叆鍒� 6 浣嶅皬鏁板悗杞� Double锛堢敤浜庡瓨搴�/灞曠ず锛岄伩鍏嶆诞鐐瑰熬宸級
+ */
+ public static Double roundToScale(Double v) {
+ if (v == null) {
+ return 0.0;
+ }
+ return toBigDecimal(v).setScale(SCALE, ROUNDING).doubleValue();
+ }
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java
index 8ccb1bf..6ff6f2f 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderWorkType.java
@@ -15,7 +15,7 @@
ORDER_WORK_TYPE_SALE("4", "閿�鍞��鍥炲叆搴撳崟"),
ORDER_WORK_TYPE_OTHER_IN("5", "鍏跺畠鍏ュ簱鍗�"),
ORDER_WORK_TYPE_OTHER_TERANSFER_IN("6", "璋冩嫈鍏ュ簱鍗�"),
- ORDER_WORK_TYPE_OTHER_TERANSFER("8", "璋冩嫈鍏ュ簱鍗�"),//甯屾棩椤圭洰涓存椂淇敼
+ ORDER_WORK_TYPE_OTHER_TERANSFER("8", "璋冩嫈鍏ュ簱鍗�"),//椤圭洰涓存椂淇敼
ORDER_WORK_TYPE_STOCK_REVISE("7", "搴撳瓨璋冩暣鍗�"),
ORDER_WORK_TYPE_SUPPLIER("11", "閿�鍞嚭搴撳崟"),
ORDER_WORK_TYPE_RETURN_ORDER("12", "棰嗘枡鍑哄簱鍗�"),
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocItemMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocItemMapper.java
index 4c42b43..73fbada 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocItemMapper.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/LocItemMapper.java
@@ -23,5 +23,9 @@
* @param locUseStatus 搴撲綅鐘舵�侊紝涓虹┖鍒欎笉杩囨护
* @return 姣忚: matnrId, stockQty, locStatuses(閫楀彿鍒嗛殧鐨勫簱浣嶇姸鎬侊紝浠呭綋 locUseStatus 涓虹┖鏃惰繑鍥�)
*/
- List<Map<String, Object>> listStockByMatnrIds(@Param("matnrIds") List<Long> matnrIds, @Param("locUseStatus") String locUseStatus);
+ /**
+ * 鎸夌墿鏂�+鐘舵��+搴撲綅鍒嗙粍锛氭瘡琛� (matnrId, useStatus, locCode, locQty)銆�
+ * 姹囨�� stockQty 涓庢嫾鎺� "搴撲綅(鏁伴噺)" 鍦� Java 涓畬鎴愶紝鍑忚交鏁版嵁搴撳帇鍔涖��
+ */
+ List<Map<String, Object>> listStockByMatnrIdsGroupByStatusAndLoc(@Param("matnrIds") List<Long> matnrIds, @Param("locUseStatus") String locUseStatus);
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
index 4ad7c8f..1de8060 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/ScheduleJobs.java
@@ -193,7 +193,7 @@
WarehouseAreasItem warehousItem = warehouseAreasItemService.getOne(new LambdaQueryWrapper<WarehouseAreasItem>().eq(StringUtils.isNotBlank(orderItem.getFieldsIndex()), WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex()));
if (!Objects.isNull(warehousItem)) {
- //甯屾棩鐩稿悓绁ㄥ彿锛屾敹璐у尯涓嶅彲鏂板鐩稿悓绁ㄥ彿鏁版嵁
+ //鐩稿悓绁ㄥ彿锛屾敹璐у尯涓嶅彲鏂板鐩稿悓绁ㄥ彿鏁版嵁
FieldsItem fieldsItem = fieldsItemService.getOne(new LambdaQueryWrapper<FieldsItem>()
.eq(FieldsItem::getUuid, orderItem.getFieldsIndex()).last("LIMIT 1"));
if (!Objects.isNull(fieldsItem)) {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
index 666c054..61531c0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/LocItemServiceImpl.java
@@ -66,13 +66,11 @@
@Synchronized
@Transactional(rollbackFor = Exception.class)
public synchronized void generateTask(Short resouce, LocToTaskParams map, Long loginUserId) throws Exception {
- if (Objects.isNull(map.getSiteNo())) {
- throw new CoolException("绔欑偣涓嶈兘涓虹┖锛�");
- }
+ // 鍑哄簱鍙f湭浼犳椂榛樿 1001
+ String siteNo = StringUtils.isNotBlank(map.getSiteNo()) ? map.getSiteNo() : "1001";
if (Objects.isNull(map.getItems()) || map.getItems().isEmpty()) {
throw new CoolException("鏄庣粏涓嶈兘涓虹┖锛�");
}
- String siteNo = map.getSiteNo();
List<LocItem> items = map.getItems();
Map<Long, List<LocItem>> listMap = items.stream().collect(Collectors.groupingBy(LocItem::getLocId));
WkOrder order;
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
index a42985b..e2cf9c4 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -92,44 +92,96 @@
@Override
public PageParam<Matnr, BaseParam> pageMatnrForOutStock(PageParam<Matnr, BaseParam> pageParam, Map<String, Object> params) {
+ // 鍦� getMatnrPage 涔嬪墠鍙栧嚭 locUseStatus锛歡etMatnrPage 浼氫粠 where.map 涓� remove 鎺夎閿紙涓� params 鍚屽紩鐢級锛屽鑷村悗缁彇涓嶅埌
+ String locUseStatus = params.get("locUseStatus") != null ? params.get("locUseStatus").toString().trim() : null;
+ if (locUseStatus != null && locUseStatus.isEmpty()) locUseStatus = null;
+
PageParam<Matnr, BaseParam> page = matnrService.getMatnrPage(pageParam, params);
List<Matnr> records = page.getRecords();
if (records == null || records.isEmpty()) {
return page;
}
List<Long> matnrIds = records.stream().map(Matnr::getId).collect(Collectors.toList());
- String locUseStatus = params.get("locUseStatus") != null ? params.get("locUseStatus").toString() : null;
- List<Map<String, Object>> stockList = locItemMapper.listStockByMatnrIds(matnrIds, locUseStatus);
- Map<Long, Double> stockQtyMap = new HashMap<>();
- Map<Long, String> locStatusDescMap = new HashMap<>();
- Map<Long, String> locCodesMap = new HashMap<>();
- for (Map<String, Object> row : stockList) {
- Long matnrId = getLong(row, "matnrId", "matnrid");
- if (matnrId == null) continue;
- Object qty = getAny(row, "stockQty", "stockqty");
- double v = qty instanceof Number ? ((Number) qty).doubleValue() : 0d;
- stockQtyMap.put(matnrId, v);
- String locCodes = getStr(row, "locCodes", "loccodes");
- if (locCodes != null && !locCodes.isEmpty()) {
- locCodesMap.put(matnrId, locCodes);
- }
- String locStatuses = getStr(row, "locStatuses", "locstatuses");
- if (locStatuses != null && !locStatuses.isEmpty()) {
- String desc = Arrays.stream(locStatuses.split(","))
- .map(String::trim)
- .map(LocStsType::getDescByType)
- .collect(Collectors.joining(","));
- locStatusDescMap.put(matnrId, desc);
- } else if (locUseStatus != null && !locUseStatus.isEmpty()) {
- locStatusDescMap.put(matnrId, LocStsType.getDescByType(locUseStatus));
- }
- }
+ List<Map<String, Object>> stockByLocList = locItemMapper.listStockByMatnrIdsGroupByStatusAndLoc(matnrIds, locUseStatus);
+ Map<Long, List<Map<String, Object>>> rowsByMatnr = buildRowsByMatnrFromPerLoc(stockByLocList);
+ List<Matnr> expanded = new ArrayList<>();
for (Matnr record : records) {
- record.setStockQty(stockQtyMap.getOrDefault(record.getId(), 0d));
- record.setLocUseStatus$(locStatusDescMap.get(record.getId()));
- record.setLocCodes$(locCodesMap.get(record.getId()));
+ List<Map<String, Object>> statusRows = rowsByMatnr.get(record.getId());
+ if (statusRows == null || statusRows.isEmpty()) {
+ record.setStockQty(0d);
+ record.setLocUseStatus$(null);
+ record.setLocCodes$(null);
+ expanded.add(record);
+ continue;
+ }
+ for (Map<String, Object> row : statusRows) {
+ double v = row.get("stockQty") instanceof Number ? ((Number) row.get("stockQty")).doubleValue() : 0d;
+ String useStatus = getStr(row, "useStatus", "usestatus");
+ String statusDesc = useStatus != null ? LocStsType.getDescByType(useStatus) : null;
+ String locCodesWithQty = getStr(row, "locCodes$", "loccodes$");
+ Matnr copy = cloneMatnrForRow(record);
+ copy.setStockQty(v);
+ copy.setLocUseStatus$(statusDesc);
+ copy.setLocCodes$(locCodesWithQty);
+ expanded.add(copy);
+ }
}
+ page.setRecords(expanded);
return page;
+ }
+
+ /** 澶嶅埗鐗╂枡鐢ㄤ簬鎸夌姸鎬佸睍寮�琛岋紙浠呭鍒跺睍绀虹敤瀛楁锛宨d 淇濇寔鍘熸牱渚涘墠绔�夎鐢級 */
+ private static Matnr cloneMatnrForRow(Matnr source) {
+ Matnr copy = new Matnr();
+ BeanUtils.copyProperties(source, copy, "stockQty", "locUseStatus$", "locCodes$");
+ return copy;
+ }
+
+ /**
+ * 浠呯敤銆屾寜搴撲綅鏄庣粏銆嶆煡璇㈢粨鏋滃湪鍐呭瓨涓垎缁勬眹鎬伙細鎸� (matnrId, useStatus) 鑱氬悎锛�
+ * 寰楀埌 stockQty銆乴ocCodes$锛堝簱浣�(鏁伴噺),...锛夛紝鍑忚交鏁版嵁搴撳帇鍔涖��
+ */
+ private static Map<Long, List<Map<String, Object>>> buildRowsByMatnrFromPerLoc(List<Map<String, Object>> stockByLocList) {
+ Map<String, List<Map<String, Object>>> perLocByMatnrAndStatus = new HashMap<>();
+ for (Map<String, Object> locRow : stockByLocList) {
+ Long mid = getLong(locRow, "matnrId", "matnrid");
+ String us = getStr(locRow, "useStatus", "usestatus");
+ if (mid == null || us == null) continue;
+ String key = mid + ":" + us;
+ perLocByMatnrAndStatus.computeIfAbsent(key, k -> new ArrayList<>()).add(locRow);
+ }
+ Map<Long, List<Map<String, Object>>> rowsByMatnr = new HashMap<>();
+ for (Map.Entry<String, List<Map<String, Object>>> e : perLocByMatnrAndStatus.entrySet()) {
+ String[] parts = e.getKey().split(":", 2);
+ if (parts.length != 2) continue;
+ Long matnrId;
+ try { matnrId = Long.parseLong(parts[0]); } catch (NumberFormatException ex) { continue; }
+ String useStatus = parts[1];
+ List<Map<String, Object>> locs = e.getValue();
+ double stockQty = 0d;
+ StringBuilder sb = new StringBuilder();
+ for (Map<String, Object> locRow : locs) {
+ Object q = getAny(locRow, "locQty", "locqty");
+ double qty = q instanceof Number ? ((Number) q).doubleValue() : 0d;
+ stockQty += qty;
+ String code = getStr(locRow, "locCode", "loccode");
+ if (sb.length() > 0) sb.append(",");
+ sb.append(code != null ? code : "").append("(").append(formatQtyForLoc(qty)).append(")");
+ }
+ Map<String, Object> statusRow = new HashMap<>();
+ statusRow.put("matnrId", matnrId);
+ statusRow.put("useStatus", useStatus);
+ statusRow.put("stockQty", stockQty);
+ statusRow.put("locCodes$", sb.toString());
+ rowsByMatnr.computeIfAbsent(matnrId, k -> new ArrayList<>()).add(statusRow);
+ }
+ return rowsByMatnr;
+ }
+
+ private static String formatQtyForLoc(double qty) {
+ if (qty == (long) qty) return String.valueOf((long) qty);
+ String s = BigDecimal.valueOf(qty).setScale(6, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+ return s;
}
private static Long getLong(Map<String, Object> map, String... keys) {
@@ -748,11 +800,13 @@
locItems.add(locItem);
LocToTaskParams taskParams = new LocToTaskParams();
+ // 鍑哄簱鍗曚笅鍙戜换鍔℃椂锛屽嚭搴撳彛鏈紶鍒欓粯璁� 1001
+ String siteNo = StringUtils.isNotBlank(param.getSiteNo()) ? param.getSiteNo() : "1001";
taskParams.setType(Constants.TASK_TYPE_ORDER_OUT_STOCK)
.setOrgLoc(loc.getCode())
.setItems(locItems)
.setSourceId(outId)
- .setSiteNo(param.getSiteNo());
+ .setSiteNo(siteNo);
try {
//鐢熸垚鍑哄簱浠诲姟
locItemService.generateTask(TaskResouceType.TASK_RESOUCE_ORDER_TYPE.val, taskParams, loginUserId);
@@ -892,6 +946,14 @@
.eq(DeviceSite::getChannel, loc.getChannel())
.eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
);
+ // 鍑哄簱鍙e垪琛ㄦ帓搴忥細1001 鎺掔涓�锛屼綔涓洪粯璁�
+ deviceSites.sort((a, b) -> {
+ boolean a1001 = "1001".equals(a.getSite());
+ boolean b1001 = "1001".equals(b.getSite());
+ if (a1001 && !b1001) return -1;
+ if (!a1001 && b1001) return 1;
+ return 0;
+ });
if (!deviceSites.isEmpty()) {
List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
@@ -904,7 +966,7 @@
orderOutItemDto.setStaNos(maps);
//榛樿鑾峰彇绗竴绔欑偣
DeviceSite deviceSite = deviceSites.stream().findFirst().get();
- orderOutItemDto.setSiteNo(deviceSite.getSite());
+ orderOutItemDto.setSitesNo(deviceSite.getSite());
}
list.add(orderOutItemDto);
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
index 09ff644..476bf94 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -18,6 +18,7 @@
import com.vincent.rsf.server.api.entity.params.WcsTaskParams;
import com.vincent.rsf.server.api.service.WcsService;
import com.vincent.rsf.server.common.constant.Constants;
+import com.vincent.rsf.server.common.utils.QuantityUtils;
import com.vincent.rsf.server.manager.controller.params.LocToTaskParams;
import com.vincent.rsf.server.manager.controller.params.PakinItem;
import com.vincent.rsf.server.manager.enums.*;
@@ -860,33 +861,37 @@
throw new CoolException("浠诲姟鏄庣粏涓嶅瓨鍦紒锛�");
}
- List<LocItem> items = new ArrayList<>();
- for (TaskItem taskItem : taskItems) {
- LocItem locItem = new LocItem();
- LocItemWorking locWorking = locItemWorkingService.getOne(new LambdaQueryWrapper<LocItemWorking>()
- .eq(LocItemWorking::getTaskId, taskItem.getTaskId())
- .eq(StringUtils.isNotBlank(taskItem.getFieldsIndex()), LocItemWorking::getFieldsIndex, taskItem.getFieldsIndex())
- .eq(StringUtils.isNotEmpty(taskItem.getBatch()), LocItemWorking::getBatch, taskItem.getBatch())
- .eq(LocItemWorking::getMatnrId, taskItem.getMatnrId()));
- if (Objects.isNull(locWorking)) {
- continue;
+ if (TaskType.TASK_TYPE_PICK_IN.type.equals(task.getTaskType())) {
+ // 鎷f枡鍐嶅叆搴擄細鍑哄簱鏃跺凡鍦� pickOrCheckTask 涓墸鍑忓師搴撲綅锛�1100 -> 1089.899锛夛紝
+ // 鍏ュ簱瀹屾垚鏃朵笉鍐嶅洖鍐�/绱姞搴撲綅鏄庣粏锛屼繚鎸� 1 鏉� 1089.899锛岄伩鍏嶅嚭鐜颁袱鏉� 1100
+ // 浠呮洿鏂板簱浣嶇姸鎬併�佹竻鐞� LocItemWorking銆佷换鍔$姸鎬佸強娴佹按
+ } else {
+ // 鐩樼偣鍏ュ簱绛夛細娌跨敤鍘熼�昏緫锛屼粠 LocItemWorking 鍥炲啓骞� saveBatch
+ List<LocItem> items = new ArrayList<>();
+ for (TaskItem taskItem : taskItems) {
+ LocItem locItem = new LocItem();
+ LocItemWorking locWorking = locItemWorkingService.getOne(new LambdaQueryWrapper<LocItemWorking>()
+ .eq(LocItemWorking::getTaskId, taskItem.getTaskId())
+ .eq(StringUtils.isNotBlank(taskItem.getFieldsIndex()), LocItemWorking::getFieldsIndex, taskItem.getFieldsIndex())
+ .eq(StringUtils.isNotEmpty(taskItem.getBatch()), LocItemWorking::getBatch, taskItem.getBatch())
+ .eq(LocItemWorking::getMatnrId, taskItem.getMatnrId()));
+ if (Objects.isNull(locWorking)) {
+ continue;
+ }
+ if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
+ locWorking.setAnfme(taskItem.getAnfme());
+ }
+ BeanUtils.copyProperties(locWorking, locItem);
+ locItem.setWorkQty(0.0).setQty(0.0).setLocCode(loc.getCode()).setLocId(loc.getId()).setId(null).setUpdateBy(loginUserId).setUpdateTime(new Date());
+ //鏁伴噺涓洪浂鐨勪笉鍏ュ簱
+ if (locItem.getAnfme().compareTo(0.0) > 0) {
+ items.add(locItem);
+ }
}
- if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
- locWorking.setAnfme(taskItem.getAnfme());
- } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type) && taskItem.getQty() != null && taskItem.getQty().compareTo(0.0) > 0) {
- // 鎷f枡鍐嶅叆搴擄細鍏ュ簱鏁伴噺涓烘湰娆℃嫞鏂欐暟閲�(taskItem.qty)锛屼繚璇佷笌鍑哄簱鎵e噺涓�鑷�
- locWorking.setAnfme(taskItem.getQty());
- }
- BeanUtils.copyProperties(locWorking, locItem);
- locItem.setWorkQty(0.0).setQty(0.0).setLocCode(loc.getCode()).setLocId(loc.getId()).setId(null).setUpdateBy(loginUserId).setUpdateTime(new Date());
- //鏁伴噺涓洪浂鐨勪笉鍏ュ簱
- if (locItem.getAnfme().compareTo(0.0) > 0) {
- items.add(locItem);
- }
- }
- if (!locItemService.saveBatch(items)) {
+ if (!items.isEmpty() && !locItemService.saveBatch(items)) {
// throw new CoolException("浣滀笟搴撳瓨鍥炲啓澶辫触锛侊紒");
+ }
}
TaskItem taskItem = taskItems.stream().findFirst().get();
@@ -1290,7 +1295,7 @@
// if (Objects.isNull(locInfo)) {
// throw new CoolException("鑾峰彇搴撲綅澶辫触锛侊紒");
// }
- //甯屾棩涓婃姤鐗╂湁鎯呭喌锛屼笉闇�瑕佽幏鍙栨柊搴撲綅
+ //涓婃姤鐗╂湁鎯呭喌锛屼笉闇�瑕佽幏鍙栨柊搴撲綅
task.setTargLoc(task.getOrgLoc())
.setOrgSite(task.getTargSite());
@@ -1299,16 +1304,70 @@
}
//鑾峰彇鍥犲綋鍓嶄换鍔″嚭搴撶殑鎵�鏈夌墿鏂欎俊鎭�
List<LocItemWorking> tempLocs = locItemWorkingService.list(new LambdaQueryWrapper<LocItemWorking>().eq(LocItemWorking::getTaskId, task.getId()));
- if (tempLocs.isEmpty()) {
- throw new CoolException("鏁版嵁閿欒锛屼綔涓氫腑搴撳瓨鏁版嵁涓㈠け锛侊紒");
- }
List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId()));
if (taskItems.isEmpty()) {
throw new CoolException("鏁版嵁閿欒锛氫换鍔℃槑缁嗕负绌猴紒锛�");
}
+ // 涓庢煡璇竴鑷达細鑻ユ棤浣滀笟涓簱瀛樹絾瀛樺湪浠诲姟鏄庣粏锛岀敤浠诲姟鏄庣粏鍦ㄥ唴瀛樹腑鍏滃簳锛岄伩鍏嶁�滆兘鏌ュ埌鍗存棤娉曠‘璁も��
+ if (tempLocs.isEmpty()) {
+ tempLocs = taskItems.stream().map(ti -> {
+ LocItemWorking w = new LocItemWorking();
+ w.setTaskId(task.getId());
+ w.setFieldsIndex(ti.getFieldsIndex());
+ w.setAnfme(ti.getAnfme());
+ w.setMatnrId(ti.getMatnrId());
+ w.setMaktx(ti.getMaktx());
+ w.setMatnrCode(ti.getMatnrCode());
+ w.setSpec(ti.getSpec());
+ w.setBatch(ti.getBatch());
+ w.setUnit(ti.getUnit());
+ w.setModel(ti.getModel());
+ return w;
+ }).collect(Collectors.toList());
+ }
- // 鎷f枡鍏ュ簱锛氬湪鐢熸垚鎷f枡鍏ュ簱鍗曟椂鎵e噺鍘熷簱浣嶆暟閲忥紝涓嶄緷璧栧嚭搴撳畬鎴愭椂搴撲綅鐘舵�佷负R
+ // 鎷f枡鍏ュ簱锛氬厛绠楀墿浣欐暟閲忓苟鏇存柊 taskItem.anfme锛屽凡鎷f暟閲� taskItem.qty = 鍘熷簱浣� - 鍓╀綑锛堜繚璇� 鏁伴噺=100銆佸凡鎷f暟閲�=1銆佸簱瀛樻槑缁�=100锛�
if (TaskType.TASK_TYPE_PICK_IN.type.equals(type)) {
+ log.debug("[鎷f枡鍏ュ簱] 寮�濮嬪鐞� taskId={}, taskCode={}, orgLoc={}, tempLocs.size={}, taskItems.size={}",
+ task.getId(), task.getTaskCode(), task.getOrgLoc(), tempLocs.size(), taskItems.size());
+ tempLocs.forEach(working -> {
+ taskItems.forEach(taskItem -> {
+ if (Objects.equals(taskItem.getFieldsIndex(), working.getFieldsIndex())) {
+ // 宸叉嫞鏁伴噺锛氫紭鍏堢敤 taskItem.qty锛涗负 0 鏃朵粠鍑哄簱鍗曟槑缁嗗彇 鎵ц鏁�(workQty) 鎴� 璁㈠崟鏁伴噺(anfme)锛岄伩鍏嶆墜鍔ㄥ畬缁撴湭濉� qty 瀵艰嚧涓嶆墸鍑�
+ Double pickedQty = taskItem.getQty() != null && QuantityUtils.isPositive(taskItem.getQty())
+ ? taskItem.getQty()
+ : 0.0;
+ log.debug("[鎷f枡鍏ュ簱] taskItemId={}, fieldsIndex={}, working.anfme={}, taskItem.qty={}, taskItem.orderItemId={}, pickedQty(鍒�)={}",
+ taskItem.getId(), taskItem.getFieldsIndex(), working.getAnfme(), taskItem.getQty(), taskItem.getOrderItemId(), pickedQty);
+ if (pickedQty <= 0 && taskItem.getOrderItemId() != null) {
+ WkOrderItem orderItem = asnOrderItemService.getById(taskItem.getOrderItemId());
+ log.debug("[鎷f枡鍏ュ簱] 鏌ュ嚭搴撳崟鏄庣粏 orderItemId={}, orderItem={}, workQty={}, anfme={}",
+ taskItem.getOrderItemId(), orderItem != null ? "瀛樺湪" : "null",
+ orderItem != null ? orderItem.getWorkQty() : null, orderItem != null ? orderItem.getAnfme() : null);
+ if (orderItem != null) {
+ if (orderItem.getWorkQty() != null && QuantityUtils.isPositive(orderItem.getWorkQty())) {
+ pickedQty = orderItem.getWorkQty();
+ } else if (orderItem.getAnfme() != null && QuantityUtils.isPositive(orderItem.getAnfme())) {
+ pickedQty = orderItem.getAnfme();
+ }
+ }
+ }
+ Double minQty = QuantityUtils.subtract(working.getAnfme(), pickedQty);
+ log.debug("[鎷f枡鍏ュ簱] 璁$畻鍚� pickedQty={}, minQty(鍓╀綑)={}, 灏嗘洿鏂� taskItem.anfme={}, taskItem.qty={}",
+ pickedQty, minQty, minQty, pickedQty);
+ if (QuantityUtils.isNonNegative(minQty)) {
+ taskItem.setAnfme(minQty);
+ taskItem.setQty(pickedQty);
+ if (!taskItemService.updateById(taskItem)) {
+ throw new CoolException("浠诲姟鏄庣粏淇敼澶辫触锛侊紒");
+ }
+ } else {
+ log.warn("[鎷f枡鍏ュ簱] minQty<0 鏈洿鏂� taskItem, taskItemId={}", taskItem.getId());
+ }
+ }
+ });
+ });
+ log.debug("[鎷f枡鍏ュ簱] 鍗冲皢鎵e噺搴撲綅 locId={}, locCode={}", loc.getId(), loc.getCode());
subtractLocItemByTaskItems(loc, taskItems, SystemAuthUtils.getLoginUserId());
}
@@ -1317,19 +1376,19 @@
if (Objects.equals(taskItem.getFieldsIndex(), working.getFieldsIndex())) {
Double minQty = taskItem.getAnfme();
if (!task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
- // 璁$畻鍓╀綑鏁伴噺锛氫粠LocItemWorking涓噺鍘籘askItem鐨勬嫞鏂欐暟閲�
- minQty = Math.round((working.getAnfme() - taskItem.getQty()) * 1000000) / 1000000.0;
+ // 璁$畻鍓╀綑鏁伴噺
+ minQty = QuantityUtils.subtract(working.getAnfme(), taskItem.getQty());
}
- if (minQty.compareTo(0.0) >= 0) {
+ if (QuantityUtils.isNonNegative(minQty)) {
// 鏇存柊TaskItem鐨勫墿浣欐暟閲�
taskItem.setAnfme(minQty);
if (!taskItemService.updateById(taskItem)) {
throw new CoolException("浠诲姟鏄庣粏淇敼澶辫触锛侊紒");
}
- // 鏇存柊LocItemWorking鐨勫墿浣欐暟閲忥紙闈炵洏鐐瑰叆搴撴椂闇�瑕佹洿鏂帮級
+ // 鏇存柊LocItemWorking鐨勫墿浣欐暟閲忥紙闈炵洏鐐瑰叆搴撴椂闇�瑕佹洿鏂帮級锛涗粎鎸佷箙鍖栬褰曟墠鍐欏簱
if (!task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) {
working.setAnfme(minQty);
- if (!locItemWorkingService.updateById(working)) {
+ if (working.getId() != null && !locItemWorkingService.updateById(working)) {
throw new CoolException("浣滀笟搴撳瓨鏁伴噺鏇存柊澶辫触锛侊紒");
}
}
@@ -1384,9 +1443,9 @@
.setQty(0.0)
.setLocId(loc1.getId())
.setLocCode(loc1.getCode());
- // 鎷f枡鍐嶅叆搴擄細鐩爣搴撲綅鏁伴噺搴斾负鏈鎷f枡鏁伴噺(taskItem.qty)锛屼笉鏄師搴撲綅鍓╀綑鏁伴噺(taskItem.anfme)
- if (TaskType.TASK_TYPE_PICK_IN.type.equals(task.getTaskType()) && taskItem.getQty() != null && taskItem.getQty().compareTo(0.0) > 0) {
- itemWorking.setAnfme(taskItem.getQty());
+ // 鎷f枡鍐嶅叆搴擄細鐩爣搴撲綅鏁伴噺搴斾负鍥炲簱鐨勫墿浣欐暟閲�(taskItem.anfme)锛屽嵆鍘熷簱浣嶅噺鎺夋湰娆℃嫞鍑哄悗鐨勬暟閲忥紙濡� 1000 鍑哄簱 10 鈫� 990锛�
+ if (TaskType.TASK_TYPE_PICK_IN.type.equals(task.getTaskType()) && taskItem.getAnfme() != null && taskItem.getAnfme().compareTo(0.0) > 0) {
+ itemWorking.setAnfme(taskItem.getAnfme());
}
workings.add(itemWorking);
});
@@ -2066,18 +2125,37 @@
@Transactional(rollbackFor = Exception.class)
public void subtractLocItemByTaskItems(Loc loc, List<TaskItem> taskItems, Long loginUserId) {
for (TaskItem taskItem : taskItems) {
- // 鏌ヨ瀵瑰簲鐨勫簱浣嶆槑缁�
- LocItem locItem = locItemService.getOne(new LambdaQueryWrapper<LocItem>()
+ LambdaQueryWrapper<LocItem> locItemWrapper = new LambdaQueryWrapper<LocItem>()
.eq(LocItem::getLocId, loc.getId())
- .eq(LocItem::getMatnrId, taskItem.getMatnrId())
- .eq(StringUtils.isNotBlank(taskItem.getBatch()), LocItem::getBatch, taskItem.getBatch())
- .eq(StringUtils.isNotBlank(taskItem.getFieldsIndex()), LocItem::getFieldsIndex, taskItem.getFieldsIndex()));
+ .eq(LocItem::getMatnrId, taskItem.getMatnrId());
+ if (StringUtils.isNotBlank(taskItem.getBatch())) {
+ locItemWrapper.eq(LocItem::getBatch, taskItem.getBatch());
+ } else {
+ locItemWrapper.and(w -> w.isNull(LocItem::getBatch).or().eq(LocItem::getBatch, ""));
+ }
+ if (StringUtils.isNotBlank(taskItem.getFieldsIndex())) {
+ locItemWrapper.eq(LocItem::getFieldsIndex, taskItem.getFieldsIndex());
+ } else {
+ locItemWrapper.and(w -> w.isNull(LocItem::getFieldsIndex).or().eq(LocItem::getFieldsIndex, ""));
+ }
+ LocItem locItem = locItemService.getOne(locItemWrapper);
+
+ log.info("[鎷f枡鍏ュ簱-鎵e噺搴撲綅] taskItemId={}, locId={}, matnrId={}, batch={}, fieldsIndex={}, locItem={}, locItem.anfme={}, taskItem.qty={}, taskItem.anfme={}",
+ taskItem.getId(), loc.getId(), taskItem.getMatnrId(), taskItem.getBatch(), taskItem.getFieldsIndex(),
+ locItem != null ? "瀛樺湪" : "null", locItem != null ? locItem.getAnfme() : null, taskItem.getQty(), taskItem.getAnfme());
if (Objects.nonNull(locItem)) {
- // 璁$畻鎵e噺鍚庣殑鏁伴噺
- Double newAnfme = Math.round((locItem.getAnfme() - taskItem.getQty()) * 1000000) / 1000000.0;
-
- if (newAnfme.compareTo(0.0) <= 0) {
+ // 鎵e噺閲忥細浼樺厛鐢ㄦ湰娆℃嫞鏂欐暟閲� taskItem.getQty()锛涜嫢涓� 0 涓� taskItem.anfme 宸蹭负鍓╀綑鏁伴噺锛屽垯鎵e噺 = 鍘熷簱浣� - 鍓╀綑锛堢敤 BigDecimal 閬垮厤 Double 绮惧害闂锛�
+ Double deductQty = QuantityUtils.isPositive(taskItem.getQty())
+ ? taskItem.getQty()
+ : (taskItem.getAnfme() != null && QuantityUtils.compare(taskItem.getAnfme(), locItem.getAnfme()) < 0
+ ? QuantityUtils.subtract(locItem.getAnfme(), taskItem.getAnfme())
+ : 0.0);
+ Double newAnfme = QuantityUtils.subtract(locItem.getAnfme(), deductQty);
+ log.info("[鎷f枡鍏ュ簱-鎵e噺搴撲綅] locItemId={}, deductQty={}, 鍘焌nfme={}, newAnfme={}, 鎿嶄綔={}",
+ locItem.getId(), deductQty, locItem.getAnfme(), newAnfme, QuantityUtils.isNonPositive(newAnfme) ? "鍒犻櫎" : "鏇存柊");
+
+ if (QuantityUtils.isNonPositive(newAnfme)) {
// 鏁伴噺灏忎簬绛変簬0锛屽垹闄ゅ簱浣嶆槑缁�
locItemService.removeById(locItem.getId());
} else {
@@ -2089,6 +2167,9 @@
throw new CoolException("搴撲綅鏄庣粏鏁伴噺鎵e噺澶辫触锛侊紒");
}
}
+ } else {
+ log.warn("[鎷f枡鍏ュ簱-鎵e噺搴撲綅] 鏈煡鍒板簱浣嶆槑缁� locId={}, matnrId={}, batch={}, fieldsIndex={}锛屾湭鎵e噺",
+ loc.getId(), taskItem.getMatnrId(), taskItem.getBatch(), taskItem.getFieldsIndex());
}
}
}
diff --git a/rsf-server/src/main/resources/mapper/manager/LocItemMapper.xml b/rsf-server/src/main/resources/mapper/manager/LocItemMapper.xml
index 6db3133..e400a7a 100644
--- a/rsf-server/src/main/resources/mapper/manager/LocItemMapper.xml
+++ b/rsf-server/src/main/resources/mapper/manager/LocItemMapper.xml
@@ -55,4 +55,25 @@
</if>
GROUP BY li.matnr_id
</select>
+
+ <!-- 鎸夌墿鏂�+鐘舵��+搴撲綅鍒嗙粍锛氭瘡琛屼竴涓簱浣嶅強鍏舵暟閲忥紝姹囨�讳笌鎷兼帴鍦� Java 涓畬鎴愪互鍑忚交搴撳帇鍔� -->
+ <select id="listStockByMatnrIdsGroupByStatusAndLoc" resultType="java.util.HashMap">
+ SELECT
+ li.matnr_id AS matnrId,
+ l.use_status AS useStatus,
+ li.loc_code AS locCode,
+ COALESCE(SUM(li.anfme), 0) AS locQty
+ FROM man_loc_item li
+ INNER JOIN man_loc l ON l.id = li.loc_id AND (l.deleted = 0 OR l.deleted IS NULL)
+ WHERE li.deleted = 0
+ AND li.matnr_id IN
+ <foreach collection="matnrIds" item="id" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ <if test="locUseStatus != null and locUseStatus != ''">
+ AND l.use_status = #{locUseStatus}
+ </if>
+ GROUP BY li.matnr_id, l.use_status, li.loc_code
+ ORDER BY li.matnr_id, l.use_status, li.loc_code
+ </select>
</mapper>
--
Gitblit v1.9.1