| | |
| | | }, |
| | | asnOrder: { |
| | | code: "Code", |
| | | poCode: "poCode", |
| | | poCode: "Internal Code", |
| | | poId: "poId", |
| | | type: "Type", |
| | | wkType: "wkType", |
| | |
| | | }, |
| | | asnOrderLog: { |
| | | code: "code", |
| | | poCode: "poCode", |
| | | poCode: "Internal Code", |
| | | poId: "poId", |
| | | type: "type", |
| | | wkType: "wkType", |
| | |
| | | asnCode: "asnCode", |
| | | platItemId: "platItemId", |
| | | poDetlId: "poDetlId", |
| | | poCode: "poCode", |
| | | poCode: "Internal Code", |
| | | fieldsIndex: "fieldsIndex", |
| | | matnrId: "matnrId", |
| | | matnrCode: "matnrCode", |
| | |
| | | }, |
| | | waitPakin: { |
| | | code: "code", |
| | | asnCodes: "Inbound Order No.", |
| | | ansId: "ansId", |
| | | asnCode: "asnCode", |
| | | barcode: "barcode", |
| | |
| | | name: "名称", |
| | | flagLogic: "虚拟库位", |
| | | fucAtrrs: "功能属性", |
| | | barcode: "容器码", |
| | | barcode: "料箱码", |
| | | startChannel: "起始巷道", |
| | | unit: "单位", |
| | | size: "长/宽/高", |
| | |
| | | }, |
| | | asnOrder: { |
| | | code: "WMS单号", |
| | | poCode: "PO编码", |
| | | poCode: "单据内码", |
| | | poId: "PO标识", |
| | | type: "单据类型", |
| | | wkType: "业务类型", |
| | |
| | | }, |
| | | outStock: { |
| | | code: "出库单号", |
| | | poCode: "DO单号", |
| | | poCode: "单据内码", |
| | | poId: "DO标识", |
| | | type: "类型", |
| | | wkType: "业务类型", |
| | |
| | | }, |
| | | checkOrder: { |
| | | code: "盘点单号", |
| | | poCode: "DO单号", |
| | | poCode: "单据内码", |
| | | poId: "DO标识", |
| | | type: "单据类型", |
| | | checkType: '盘点类型', |
| | |
| | | |
| | | transferOrder: { |
| | | code: '单号', |
| | | poCode: '调拔单', |
| | | poCode: '单据内码', |
| | | type: '单据类型', |
| | | wkType: '调拔类型', |
| | | anfme: '调拔数量', |
| | |
| | | outStockItem: { |
| | | orderId: "主单标识", |
| | | orderCode: "单号", |
| | | poCode: 'DO单号', |
| | | poCode: '单据内码', |
| | | poDetlId: "平台明细ID", |
| | | poDetlCode: "DO单", |
| | | matnrId: "物料标识", |
| | |
| | | }, |
| | | asnOrderLog: { |
| | | code: "编码", |
| | | poCode: "PO编码", |
| | | poCode: "单据内码", |
| | | poId: "PO标识", |
| | | type: "单据类型", |
| | | wkType: "业务类型", |
| | |
| | | asnOrderItemLog: { |
| | | orderId: "主单标识", |
| | | orderCode: "主单编码", |
| | | poCode: "单据内码", |
| | | platItemId: "erp标识", |
| | | poDetlId: "PO单标识", |
| | | poDetlCode: "PO单编码", |
| | |
| | | }, |
| | | waitPakin: { |
| | | code: "编码", |
| | | asnCodes: "入库通知单号", |
| | | ansId: "收货通知单号", |
| | | asnCode: "收货通知单编码", |
| | | barcode: "容器码", |
| | | barcode: "料箱码", |
| | | flagDefect: "不良品", |
| | | anfme: "数量", |
| | | ioStatus: "状态", |
| | |
| | | matnrId: "物料id", |
| | | matnrCode: "物料编码", |
| | | asnId: "收货通知单号", |
| | | asnCode: "收货通知单编码", |
| | | asnCode: "入库通知单号", |
| | | asnItemId: "收货通知单明细id", |
| | | trackCode: "条形码", |
| | | isptResult: '质检状态', |
| | |
| | | waitPakinLog: { |
| | | pakinId: "组托Id", |
| | | code: "编码", |
| | | barcode: "容器码", |
| | | barcode: "料箱码", |
| | | anfme: "数量", |
| | | ioStatus: "状态", |
| | | }, |
| | |
| | | true: '正常', |
| | | false: '禁用', |
| | | }, |
| | | notification: { |
| | | deleted: '删除成功 |||| %{smart_count} 项 删除成功', |
| | | }, |
| | | message: { |
| | | delete_title: '删除 %{name} #%{id}', |
| | | delete_content: '您确定要删除此项吗?', |
| | | loading: '请稍候', |
| | | }, |
| | | action: { |
| | | search: '搜索', |
| | |
| | | }, |
| | | page: { |
| | | empty_with_filters: '使用当前过滤条件未找到结果。', |
| | | loading: '加载中', |
| | | }, |
| | | navigation: { |
| | | no_results: '没有找到数据', |
| | |
| | | autoFocus |
| | | /> |
| | | </Grid> |
| | | {/* 现品票号已注释 |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.deliveryItem.platItemId" |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | */} |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.deliveryItem.matnrCode" |
| | |
| | | autoFocus |
| | | /> |
| | | </Stack> |
| | | {/* 现品票号已注释 |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.deliveryItem.platItemId" |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | */} |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.deliveryItem.matnrCode" |
| | |
| | | <DateInput label='common.time.before' source="timeEnd" alwaysOn />, |
| | | |
| | | <NumberInput source="deliveryId" label="table.field.deliveryItem.deliveryId" />, |
| | | <TextInput source="platItemId" label="table.field.deliveryItem.platItemId" />, |
| | | // 现品票号已注释 <TextInput source="platItemId" label="table.field.deliveryItem.platItemId" />, |
| | | <TextInput source="matnrCode" label="table.field.deliveryItem.matnrCode" />, |
| | | <TextInput source="matnrName" label="table.field.deliveryItem.matnrName" />, |
| | | <TextInput source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" />, |
| | |
| | | > |
| | | <NumberField source="id" /> |
| | | <NumberField source="deliveryId" label="table.field.deliveryItem.deliveryId" /> |
| | | <TextField source="platItemId" label="table.field.deliveryItem.platItemId" /> |
| | | {/* 现品票号已注释 <TextField source="platItemId" label="table.field.deliveryItem.platItemId" /> */} |
| | | <TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" /> |
| | | <TextField source="matnrName" label="table.field.deliveryItem.matnrName" /> |
| | | <TextField source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" /> |
| | | <TextField source="unit" label="table.field.deliveryItem.unit" /> |
| | | <NumberField source="anfme" label="table.field.deliveryItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.deliveryItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.deliveryItem.qty" /> |
| | | <NumberField source="nromQty" label="table.field.deliveryItem.nromQty" /> |
| | | <NumberField source="printQty" label="table.field.deliveryItem.printQty" /> |
| | |
| | | property={record.deliveryId} |
| | | /> |
| | | </Grid> |
| | | {/* 现品票号已注释 |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.deliveryItem.platItemId" |
| | | property={record.platItemId} |
| | | /> |
| | | </Grid> |
| | | */} |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.deliveryItem.matnrCode" |
| | |
| | | import * as Common from '@/utils/common'; |
| | | |
| | | const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ |
| | | width: '100%', |
| | | '& .RaDatagrid-tableWrapper': { width: '100%' }, |
| | | '& .MuiTable-root': { width: '100%' }, |
| | | '& .css-1vooibu-MuiSvgIcon-root': { |
| | | height: '.9em' |
| | | }, |
| | |
| | | |
| | | <NumberInput source="orderId" label="table.field.asnOrderItemLog.orderId" />, |
| | | <TextInput source="orderCode" label="table.field.asnOrderItemLog.orderCode" />, |
| | | <TextInput source="platItemId" label="table.field.asnOrderItemLog.platItemId" />, |
| | | // 现品票号已注释 <TextInput source="platItemId" label="table.field.asnOrderItemLog.platItemId" />, |
| | | <NumberInput source="poDetlId" label="table.field.asnOrderItemLog.poDetlId" />, |
| | | <TextInput source="poCode" label="table.field.asnOrderItemLog.poCode" />, |
| | | <TextInput source="fieldsIndex" label="table.field.asnOrderItemLog.fieldsIndex" />, |
| | |
| | | resource="asnOrderItemLog" |
| | | sx={{ |
| | | flexGrow: 1, |
| | | width: '100%', |
| | | minWidth: 0, |
| | | transition: (theme) => |
| | | theme.transitions.create(['all'], { |
| | | duration: theme.transitions.duration.enteringScreen, |
| | | }), |
| | | marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, |
| | | }} |
| | | title={"menu.asnOrderItemLog"} |
| | | title={"menu.asnOrderItem"} |
| | | empty={false} |
| | | filters={filters} |
| | | filter={{ logId }} |
| | |
| | | preferenceKey='asnOrderItemLog' |
| | | bulkActionButtons={false} |
| | | rowClick={(id, resource, record) => false} |
| | | omit={['id', 'orderId', 'poDetlId', 'poCode', 'qrcode', 'packName', 'createTime', 'memo', 'fieldsIndex', 'matnrId', 'splrCode', 'status', 'createBy$']} |
| | | omit={['id', 'asnId', 'orderId', 'poDetlId', 'poCode', 'qrcode', 'packName', 'createTime', 'memo', 'fieldsIndex', 'matnrId', 'splrCode', 'status', 'createBy$', 'platItemId', 'trackCode']} |
| | | > |
| | | <NumberField source="id" /> |
| | | <NumberField source="asnId" label="table.field.asnOrderItemLog.orderId" /> |
| | | <TextField source="asnCode" label="table.field.asnOrderItemLog.orderCode" /> |
| | | <TextField source="platItemId" label="table.field.asnOrderItemLog.platItemId" /> |
| | | <NumberField source="poDetlId" label="table.field.asnOrderItemLog.poDetlId" /> |
| | | <TextField source="poCode" label="table.field.asnOrderItemLog.poCode" /> |
| | | <TextField source="fieldsIndex" label="table.field.asnOrderItemLog.fieldsIndex" /> |
| | | <TextField source="matnrId" label="table.field.asnOrderItemLog.matnrId" /> |
| | | <TextField source="matnrCode" label="table.field.asnOrderItemLog.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.asnOrderItemLog.maktx" /> |
| | | <NumberField source="anfme" label="table.field.asnOrderItemLog.anfme" /> |
| | | <NumberField source="purQty" label="table.field.asnOrderItemLog.purQty" /> |
| | | <TextField source="purUnit" label="table.field.asnOrderItemLog.purUnit" /> |
| | | <NumberField source="qty" label="table.field.asnOrderItemLog.qty" /> |
| | | <TextField source="splrCode" label="table.field.asnOrderItemLog.splrCode" /> |
| | | <TextField source="splrBatch" label="table.field.asnOrderItemLog.splrBatch" /> |
| | | <TextField source="splrName" label="table.field.asnOrderItemLog.splrName" /> |
| | | <TextField source="qrcode" label="table.field.asnOrderItemLog.qrcode" /> |
| | | <TextField source="trackCode" label="table.field.asnOrderItemLog.trackCode" /> |
| | | <TextField source="packName" label="table.field.asnOrderItemLog.packName" /> |
| | | {/*<TextField source="ntyStatus$" label="table.field.asnOrderItemLog.ntyStatus" sortable={false} />*/} |
| | | <NumberField source="asnId" label="table.field.asnOrderItem.orderId" /> |
| | | <TextField source="asnCode" label="table.field.asnOrderItem.orderCode" /> |
| | | <NumberField source="poDetlId" label="table.field.asnOrderItem.poDetlId" /> |
| | | <TextField source="poCode" label="table.field.asnOrderItem.poCode" /> |
| | | <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" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="stockUnit" label="table.field.asnOrderItem.stockUnit" /> |
| | | <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="purUnit" label="table.field.asnOrderItem.purUnit" /> |
| | | <TextField source="splrCode" label="table.field.asnOrderItem.splrCode" /> |
| | | <TextField source="splrName" label="table.field.asnOrderItem.splrName" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | | <TextField source="createBy$" label="common.field.createBy" /> |
| | | <DateField source="createTime" label="common.field.createTime" showTime /> |
| | | <TextField source="memo" label="common.field.memo" sortable={false} /> |
| | |
| | | })); |
| | | |
| | | /** |
| | | * 入库/出库历史单列表共用骨架,仅 type 与标题由外部传入。 |
| | | * 入库历史单:typeFilter="in", listTitle="menu.asnOrderLog" |
| | | * 出库历史单:typeFilter="out", listTitle="menu.outStockOrderLog" |
| | | * 后端接口均为 asnOrderLog(出库由 dataProvider 映射),参数 filter.type 不同。 |
| | | */ |
| | | export default function AsnOrderLogListBase({ typeFilter, listTitle }) { |
| | | const [createDialog, setCreateDialog] = useState(false); |
| | |
| | | <NumberField source="poId" label="table.field.asnOrderLog.poId" /> |
| | | <TextField source="type$" label="table.field.asnOrderLog.type" /> |
| | | <TextField source="wkType$" label="table.field.asnOrderLog.wkType" /> |
| | | <NumberField source="anfme" label="table.field.asnOrderLog.anfme" /> |
| | | <NumberField source="qty" label="table.field.asnOrderLog.qty" /> |
| | | <NumberField source="anfme" label="table.field.asnOrderLog.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.asnOrderLog.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="logisNo" label="table.field.asnOrderLog.logisNo" /> |
| | | <DateField source="arrTime" label="table.field.asnOrderLog.arrTime" showTime /> |
| | | <TextField source="rleStatus$" label="table.field.asnOrderLog.rleStatus" sortable={false} /> |
| | |
| | | import { BooleanField, DateField, NumberField, ReferenceField, Show, SimpleShowLayout, TextField ,DateInput, |
| | | SelectInput,required,useTranslate, |
| | | useRecordContext,} from 'react-admin'; |
| | | import { Stack, Grid, Box, Typography, Card } from '@mui/material'; |
| | | import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; |
| | | import EditBaseAside from "../../components/EditBaseAside"; |
| | | import React from "react"; |
| | | import { Show, useTranslate, useRecordContext, DateField } from 'react-admin'; |
| | | import { Stack, Grid, Box, Typography, TextField as MuiTextField, Card, CardContent } from '@mui/material'; |
| | | import AccessTimeIcon from '@mui/icons-material/AccessTime'; |
| | | import CustomerTopToolBar from "../../components/EditTopToolBar"; |
| | | import AsnOrderItemLogList from "./AsnOrderItemLogList"; |
| | | |
| | | const AsnOrderLogDetailWithItems = () => { |
| | | const record = useRecordContext(); |
| | | /** 只读输入框样式,与 Edit 页 Filled 白底一致,用于 Show 头部 */ |
| | | const readOnlyInputSx = { |
| | | "& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled": { |
| | | bgcolor: 'white', |
| | | WebkitTextFillColor: "rgba(0, 0, 0)" |
| | | }, |
| | | "& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled": { |
| | | bgcolor: 'white', |
| | | WebkitTextFillColor: "rgba(0, 0, 0)" |
| | | }, |
| | | "& .MuiFilledInput-root.MuiInputBase-sizeSmall": { |
| | | bgcolor: 'white', |
| | | } |
| | | }; |
| | | |
| | | const ShowField = ({ source, labelKey, value }) => { |
| | | const translate = useTranslate(); |
| | | if (!record?.id) return null; |
| | | return ( |
| | | <> |
| | | <Grid item xs={24} md={16} sx={{ marginTop: '1em', width: '100%' }}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.common')} |
| | | </Typography> |
| | | </Grid> |
| | | <AsnOrderItemLogList logId={record.id} /> |
| | | </> |
| | | <MuiTextField |
| | | size="small" |
| | | variant="filled" |
| | | label={translate(labelKey)} |
| | | value={value ?? ''} |
| | | disabled |
| | | sx={{ width: 130, minWidth: 110, flexShrink: 0, ...readOnlyInputSx }} |
| | | InputProps={{ readOnly: true }} |
| | | /> |
| | | ); |
| | | }; |
| | | |
| | | const Aa = () =>{ |
| | | /** |
| | | * 入库/出库历史单查看详情:单列平铺(主要 → 更多 → 物料详情),无右侧 aside,占满整页宽度。 |
| | | * Show 页无 Form 上下文,用 MUI TextField 只读样式复刻 Edit 头部视觉效果。 |
| | | */ |
| | | const AsnOrderLogShow = () => { |
| | | const translate = useTranslate(); |
| | | |
| | | return( |
| | | <> |
| | | <Show |
| | | redirect="list" |
| | | mutationMode={EDIT_MODE} |
| | | actions={<CustomerTopToolBar />} |
| | | aside={<EditBaseAside />} |
| | | title="入库历史单详情" |
| | | sx={{ |
| | | width: '100% !important', |
| | | maxWidth: 'none !important', |
| | | '& > div': { maxWidth: 'none !important', width: '100% !important' }, |
| | | '& .RaShow-main': { maxWidth: 'none !important', width: '100% !important', minWidth: 0 }, |
| | | '& .RaShow-card': { maxWidth: 'none !important', width: '100% !important' }, |
| | | '& .MuiPaper-root': { maxWidth: 'none !important', width: '100% !important' }, |
| | | '& [class*="RaShow"]': { maxWidth: 'none !important', width: '100% !important' }, |
| | | }} |
| | | > |
| | | <SimpleShowLayout |
| | | shouldUnregister |
| | | warnWhenUnsavedChanges |
| | | mode="onTouched" |
| | | defaultValues={{}} |
| | | > |
| | | <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1, width: '100%', minWidth: 0 }}> |
| | | <Grid container spacing={2}> |
| | | <Grid item xs={12} md> |
| | | <Card variant="outlined" sx={{ height: '100%' }}> |
| | | <CardContent sx={{ py: 1, '&:last-child': { pb: 1.5 } }}> |
| | | <MainSection /> |
| | | </CardContent> |
| | | </Card> |
| | | </Grid> |
| | | <Grid item xs={12} md="auto"> |
| | | <Card variant="outlined" sx={{ height: '100%' }}> |
| | | <CardContent> |
| | | <MoreSection /> |
| | | </CardContent> |
| | | </Card> |
| | | </Grid> |
| | | </Grid> |
| | | <Card variant="outlined" sx={{ flex: '1 1 auto', minHeight: 0, display: 'flex', flexDirection: 'column' }}> |
| | | <CardContent sx={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, '&:last-child': { pb: 2 } }}> |
| | | <Box sx={{ width: '100%', minWidth: 0, overflowX: 'auto', flex: 1 }}> |
| | | <AsnOrderItemLogList /> |
| | | </Box> |
| | | </CardContent> |
| | | </Card> |
| | | </Box> |
| | | </Show> |
| | | ); |
| | | }; |
| | | |
| | | <Grid sx={{ |
| | | "& .MuiInputBase-input": { |
| | | bgcolor: "white" |
| | | } |
| | | }} container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> |
| | | |
| | | <Grid item xs={24} md={12}> |
| | | /** 更多:创建时间、修改时间,与 EditBaseAside 内容一致,放在主内容区单列展示 */ |
| | | const MoreSection = () => { |
| | | const translate = useTranslate(); |
| | | const record = useRecordContext(); |
| | | if (!record) return null; |
| | | return ( |
| | | <Box> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.side.title')} |
| | | </Typography> |
| | | <Grid container rowSpacing={2} columnSpacing={1}> |
| | | <Grid item xs={12} display="flex" gap={1}> |
| | | <AccessTimeIcon fontSize="small" color="disabled" /> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2">{translate('common.field.createTime')}</Typography> |
| | | <DateField record={record} source="createTime" showTime /> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item xs={12} display="flex" gap={1}> |
| | | <AccessTimeIcon fontSize="small" color="disabled" /> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2">{translate('common.field.updateTime')}</Typography> |
| | | <DateField record={record} source="updateTime" showTime /> |
| | | </Box> |
| | | </Grid> |
| | | </Grid> |
| | | </Box> |
| | | ); |
| | | }; |
| | | |
| | | const MainSection = () => { |
| | | const translate = useTranslate(); |
| | | const record = useRecordContext(); |
| | | if (!record) return null; |
| | | const rleStatusText = record.rleStatus === 1 ? '已释放' : (record.rleStatus === 0 ? '正常' : (record.rleStatus$ ?? '')); |
| | | const arrTime = record.arrTime ? (typeof record.arrTime === 'string' ? record.arrTime : new Date(record.arrTime).toLocaleString('zh-CN')) : ''; |
| | | const numOpt = { minimumFractionDigits: 2, maximumFractionDigits: 2 }; |
| | | return ( |
| | | <Box sx={{ pt: 0.3, width: '100%' }}> |
| | | <Grid container sx={{ width: '100%', maxWidth: '100%' }} rowSpacing={1} columnSpacing={1}> |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6" gutterBottom sx={{ mb: 1 }}> |
| | | {translate('common.edit.title.main')} |
| | | </Typography> |
| | | <Stack display="flax" justifyContent="space-between" flexWrap="wrap" direction='row' gap={2} > |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" > |
| | | {translate('table.field.asnOrderLog.code')} |
| | | </Typography> |
| | | <TextField source="code" label="id"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.poCode')} |
| | | </Typography> |
| | | <TextField source="poCode" label="poCode"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.poId')} |
| | | </Typography> |
| | | <NumberField source="poId" label="poId"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.type')} |
| | | </Typography> |
| | | <TextField source="type$" label="type"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.wkType')} |
| | | </Typography> |
| | | <TextField source="wkType$" label="type"/> |
| | | </Box> |
| | | </Grid> |
| | | |
| | | </Stack> |
| | | <Stack display="flax" justifyContent="space-between" flexWrap="wrap" direction='row' gap={2} sx={{mt:5 }}> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.anfme')} |
| | | </Typography> |
| | | <TextField source="anfme" label="id"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.qty')} |
| | | </Typography> |
| | | <TextField source="qty" label="poCode"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.logisNo')} |
| | | </Typography> |
| | | <NumberField source="logisNo" label="poId"/> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.arrTime')} |
| | | </Typography> |
| | | <DateField source="arrTime" label="type" showTime/> |
| | | </Box> |
| | | </Grid> |
| | | {/* 质检上报状态 |
| | | <Grid item display="flex" gap={1} minWidth={150}> |
| | | <Box flexGrow={1}> |
| | | <Typography variant="body2" sx={{fontSize: 20}}> |
| | | {translate('table.field.asnOrderLog.ntyStatus')} |
| | | </Typography> |
| | | <TextField source="ntyStatus$" label="type"/> |
| | | </Box> |
| | | </Grid> |
| | | */} |
| | | <Stack direction="row" gap={1} flexWrap="wrap" useFlexGap> |
| | | <ShowField source="code" labelKey="table.field.asnOrder.code" value={record.code} /> |
| | | <ShowField source="poCode" labelKey="table.field.asnOrder.poCode" value={record.poCode} /> |
| | | <ShowField source="type" labelKey="table.field.asnOrder.type" value={record.type$ ?? record.type} /> |
| | | <ShowField source="wkType" labelKey="table.field.asnOrder.wkType" value={record.wkType$ ?? record.wkType} /> |
| | | {/*</Stack>*/} |
| | | {/*<Stack direction="row" gap={1} flexWrap="wrap" useFlexGap sx={{ mt: 1 }}>*/} |
| | | <ShowField source="logisNo" labelKey="table.field.asnOrder.logisNo" value={record.logisNo} /> |
| | | <ShowField source="anfme" labelKey="table.field.asnOrder.anfme" value={record.anfme != null ? Number(record.anfme).toLocaleString('zh-CN', numOpt) : ''} /> |
| | | <ShowField source="qty" labelKey="table.field.asnOrder.qty" value={record.qty != null ? Number(record.qty).toLocaleString('zh-CN', numOpt) : ''} /> |
| | | <ShowField source="arrTime" labelKey="table.field.asnOrder.arrTime" value={arrTime} /> |
| | | <ShowField source="rleStatus" labelKey="table.field.asnOrder.rleStatus" value={rleStatusText} /> |
| | | </Stack> |
| | | </Grid> |
| | | </Grid> |
| | | <AsnOrderLogDetailWithItems /> |
| | | </SimpleShowLayout> |
| | | </Show> |
| | | </> |
| | | </Box> |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | const AsnorderlogShow = () => ( |
| | | |
| | | <Aa /> |
| | | |
| | | |
| | | |
| | | ); |
| | | |
| | | export default AsnorderlogShow |
| | | export default AsnOrderLogShow; |
| | |
| | | |
| | | import AsnOrderLogList from "./AsnOrderLogList"; |
| | | import AsnOrderLogEdit from "./AsnOrderLogEdit"; |
| | | import AsnorderlogShow from "./AsnOrderLogShow"; |
| | | import AsnOrderLogShow from "./AsnOrderLogShow"; |
| | | |
| | | export default { |
| | | list: AsnOrderLogList, |
| | | edit: AsnOrderLogEdit, |
| | | show: AsnorderlogShow, |
| | | show: AsnOrderLogShow, |
| | | recordRepresentation: (record) => { |
| | | return `${record.id}` |
| | | } |
| | |
| | | <TextField source="maktx" label="table.field.taskItemLog.maktx" />, |
| | | <TextField source="matnrCode" label="table.field.taskItemLog.matnrCode" />, |
| | | <TextField source="unit" label="table.field.taskItemLog.unit" />, |
| | | <NumberField source="anfme" label="table.field.taskItemLog.anfme" />, |
| | | <NumberField source="anfme" label="table.field.taskItemLog.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="batch" label="table.field.taskItemLog.batch" />, |
| | | <TextField source="spec" label="table.field.taskItemLog.spec" />, |
| | | <TextField source="model" label="table.field.taskItemLog.model" />, |
| | |
| | | import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; |
| | | import { useNavigate } from 'react-router-dom'; |
| | | import React, { useState } from "react"; |
| | | import { |
| | | List, |
| | | DatagridConfigurable, |
| | | SearchInput, |
| | | TopToolbar, |
| | | SelectColumnsButton, |
| | | EditButton, |
| | | FilterButton, |
| | | CreateButton, |
| | | ExportButton, |
| | | BulkDeleteButton, |
| | | WrapperField, |
| | | useRecordContext, |
| | | useTranslate, |
| | | useNotify, |
| | | useListContext, |
| | | FunctionField, |
| | | TextField, |
| | | NumberField, |
| | | DateField, |
| | | BooleanField, |
| | | ReferenceField, |
| | | TextInput, |
| | | DateTimeInput, |
| | | DateInput, |
| | | SelectInput, |
| | | NumberInput, |
| | | ReferenceInput, |
| | | ReferenceArrayInput, |
| | | AutocompleteInput, |
| | | DeleteButton, |
| | | useGetRecordId, |
| | | } from 'react-admin'; |
| | | import { Box, Typography, Card, Stack } from '@mui/material'; |
| | | import { styled } from '@mui/material/styles'; import EmptyData from "../../components/EmptyData"; |
| | | import MyCreateButton from "../../components/MyCreateButton"; |
| | | import MyExportButton from '../../components/MyExportButton'; |
| | | import { Box } from '@mui/material'; |
| | | import { styled } from '@mui/material/styles'; |
| | | import PageDrawer from "../../components/PageDrawer"; |
| | | import MyField from "../../components/MyField"; |
| | | import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; |
| | | import * as Common from '@/utils/common'; |
| | | import { PAGE_DRAWER_WIDTH, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting'; |
| | | |
| | | const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ |
| | | '& .css-1vooibu-MuiSvgIcon-root': { |
| | |
| | | '& .RaDatagrid-row': { |
| | | cursor: 'auto' |
| | | }, |
| | | '& .column-name': { |
| | | }, |
| | | '& .opt': { |
| | | width: 200 |
| | | }, |
| | |
| | | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <ReferenceInput source="pakinId" label="table.field.waitPakinItemLog.pakinId" reference="waitPakin"> |
| | | <AutocompleteInput label="table.field.waitPakinItemLog.pakinId" optionText="id" filterToQuery={(val) => ({ id: val })} /> |
| | | </ReferenceInput>, |
| | | <NumberInput source="pakinItemId" label="table.field.waitPakinItemLog.pakinItemId" />, |
| | | <NumberInput source="asnId" label="table.field.waitPakinItemLog.asnId" />, |
| | | <TextInput source="asnCode" label="table.field.waitPakinItemLog.asnCode" />, |
| | | <NumberInput source="asnItemId" label="table.field.waitPakinItemLog.asnItemId" />, |
| | | <TextInput source="trackCode" label="table.field.waitPakinItemLog.trackCode" />, |
| | | <NumberInput source="pakinId" label="table.field.waitPakinItemLog.pakinId" />, |
| | | <TextInput source="maktx" label="table.field.waitPakinItemLog.maktx" />, |
| | | <ReferenceInput source="matnrId" label="table.field.waitPakinItemLog.matnrId" reference="matnr"> |
| | | <AutocompleteInput label="table.field.waitPakinItemLog.matnrId" optionText="unit" filterToQuery={(val) => ({ unit: val })} /> |
| | | </ReferenceInput>, |
| | | <NumberInput source="matnrId" label="table.field.waitPakinItemLog.matnrId" />, |
| | | <TextInput source="matnrCode" label="table.field.waitPakinItemLog.matnrCode" />, |
| | | <TextInput source="asnCode" label="table.field.waitPakinItem.asnCode" />, |
| | | <NumberInput source="anfme" label="table.field.waitPakinItemLog.anfme" />, |
| | | <NumberInput source="workQty" label="table.field.waitPakinItemLog.workQty" />, |
| | | <TextInput source="unit" label="table.field.waitPakinItemLog.unit" />, |
| | | <TextInput source="fieldsIndex" label="table.field.waitPakinItemLog.fieldsIndex" />, |
| | | <NumberInput source="qty" label="table.field.waitPakinItemLog.qty" />, |
| | | <TextInput source="batch" label="table.field.waitPakinItemLog.batch" />, |
| | | <TextInput label="common.field.memo" source="memo" />, |
| | |
| | | ]} |
| | | resettable |
| | | />, |
| | | ] |
| | | ]; |
| | | |
| | | const WaitPakinItemLogList = () => { |
| | | const translate = useTranslate(); |
| | | const [createDialog, setCreateDialog] = useState(false); |
| | | const [drawerVal, setDrawerVal] = useState(false); |
| | | const recordId = useGetRecordId(); |
| | | |
| | |
| | | }), |
| | | marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, |
| | | }} |
| | | title={"menu.waitPakinItemLog"} |
| | | title={"menu.waitPakinItem"} |
| | | empty={false} |
| | | filters={filters} |
| | | filter={{ logId: recordId }} |
| | |
| | | <TopToolbar> |
| | | <FilterButton /> |
| | | <SelectColumnsButton preferenceKey='waitPakinItemLog' /> |
| | | <MyExportButton /> |
| | | {/* <MyExportButton /> 与组托通知档保持一致,不展示导出 */} |
| | | </TopToolbar> |
| | | )} |
| | | perPage={DEFAULT_PAGE_SIZE} |
| | | perPage={DEFAULT_ITEM_PAGE_SIZE} |
| | | > |
| | | <StyledDatagrid |
| | | preferenceKey='waitPakinItemLog' |
| | | bulkActionButtons={false} |
| | | rowClick={ false} |
| | | omit={['id', 'createTime', 'createBy', 'memo', 'pakinId', 'pakinItemId', 'asnId' ,'asnItemId', 'createBy$', 'fieldsIndex']} |
| | | omit={['id', 'logId', 'pakinId', 'pakinItemId', 'asnId', 'asnItemId', 'createTime', 'matnrId', 'createBy', 'memo', 'fieldsIndex']} |
| | | > |
| | | <NumberField source="id" /> |
| | | <ReferenceField source="pakinId" label="table.field.waitPakinItemLog.pakinId" reference="waitPakin" link={false} sortable={false}> |
| | | <TextField source="id" /> |
| | | </ReferenceField> |
| | | <NumberField source="pakinItemId" label="table.field.waitPakinItemLog.pakinItemId" /> |
| | | <NumberField source="asnId" label="table.field.waitPakinItemLog.asnId" /> |
| | | <TextField source="asnCode" label="table.field.waitPakinItemLog.asnCode" /> |
| | | <NumberField source="asnItemId" label="table.field.waitPakinItemLog.asnItemId" /> |
| | | <TextField source="trackCode" label="table.field.waitPakinItemLog.trackCode" /> |
| | | <TextField source="maktx" label="table.field.waitPakinItemLog.maktx" /> |
| | | <ReferenceField source="matnrId" label="table.field.waitPakinItemLog.matnrId" reference="matnr" link={false} sortable={false}> |
| | | <TextField source="unit" /> |
| | | </ReferenceField> |
| | | <TextField source="matnrCode" label="table.field.waitPakinItemLog.matnrCode" /> |
| | | <NumberField source="anfme" label="table.field.waitPakinItemLog.anfme" /> |
| | | <NumberField source="workQty" label="table.field.waitPakinItemLog.workQty" /> |
| | | <TextField source="unit" label="table.field.waitPakinItemLog.unit" /> |
| | | <TextField source="fieldsIndex" label="table.field.waitPakinItemLog.fieldsIndex" /> |
| | | <NumberField source="qty" label="table.field.waitPakinItemLog.qty" /> |
| | | <TextField source="batch" label="table.field.waitPakinItemLog.batch" /> |
| | | <TextField source="matnrCode" label="table.field.waitPakinItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.waitPakinItem.maktx" /> |
| | | <TextField source="batch" label="table.field.waitPakinItem.batch" /> |
| | | <NumberField source="matnrId" label="table.field.waitPakinItem.matnrId" /> |
| | | <NumberField source="anfme" label="table.field.waitPakinItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="unit" label="table.field.waitPakinItem.unit" /> |
| | | <TextField source="asnCode" label="table.field.waitPakinItem.asnCode" /> |
| | | <NumberField source="workQty" label="table.field.waitPakinItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.waitPakinItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="fieldsIndex" label="table.field.waitPakinItem.fieldsIndex" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | | <TextField source="createBy$" label="common.field.createBy" /> |
| | | <DateField source="createTime" label="common.field.createTime" showTime /> |
| | | <BooleanField source="statusBool" label="common.field.status" sortable={false} /> |
| | | <TextField source="memo" label="common.field.memo" sortable={false} /> |
| | | </StyledDatagrid> |
| | | </List> |
| | |
| | | import { |
| | | Edit, |
| | | SimpleForm, |
| | | FormDataConsumer, |
| | | useTranslate, |
| | | TextInput, |
| | | NumberInput, |
| | | BooleanInput, |
| | | DateInput, |
| | | SelectInput, |
| | | ReferenceInput, |
| | | ReferenceArrayInput, |
| | | AutocompleteInput, |
| | | SaveButton, |
| | | Toolbar, |
| | | Labeled, |
| | | NumberField, |
| | | required, |
| | | useRecordContext, |
| | | DeleteButton, |
| | | } from 'react-admin'; |
| | | import { useWatch, useFormContext } from "react-hook-form"; |
| | | import { useFormContext } from "react-hook-form"; |
| | | import { Stack, Grid, Box, Typography } from '@mui/material'; |
| | | import * as Common from '@/utils/common'; |
| | | import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; |
| | | import { EDIT_MODE } from '@/config/setting'; |
| | | import EditBaseAside from "../../components/EditBaseAside"; |
| | | import CustomerTopToolBar from "../../components/EditTopToolBar"; |
| | | import MemoInput from "../../components/MemoInput"; |
| | | import StatusSelectInput from "../../components/StatusSelectInput"; |
| | | import WaitPakinItemLogList from "./WaitPakinItemLogList"; |
| | | |
| | | const FormToolbar = () => { |
| | | const { getValues } = useFormContext(); |
| | | |
| | | return ( |
| | | <Toolbar sx={{ justifyContent: 'end' }}> |
| | | <></> |
| | | {/* <SaveButton /> |
| | | <DeleteButton mutationMode="optimistic" /> */} |
| | | </Toolbar> |
| | | ) |
| | | } |
| | | |
| | | const WaitPakinLogEdit = () => { |
| | | const translate = useTranslate(); |
| | |
| | | aside={<EditBaseAside />} |
| | | > |
| | | <SimpleForm |
| | | sx={{ |
| | | '& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled': { |
| | | bgcolor: "white", |
| | | color: "black", |
| | | '-webkit-text-fill-color': "rgba(0, 0, 0)" |
| | | }, |
| | | '& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled': { |
| | | color: 'rgba(0, 0, 0, 0.77)' |
| | | } |
| | | }} |
| | | shouldUnregister |
| | | warnWhenUnsavedChanges |
| | | toolbar={<FormToolbar />} |
| | | toolbar={<></>} |
| | | mode="onTouched" |
| | | defaultValues={{}} |
| | | > |
| | | <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> |
| | | <Grid item xs={24} md={12} sx={{ |
| | | "& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled": { |
| | | bgcolor: 'white', |
| | | WebkitTextFillColor: "rgba(0, 0, 0)" |
| | | }, |
| | | |
| | | "& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled": { |
| | | bgcolor: 'white', |
| | | WebkitTextFillColor: "rgba(0, 0, 0)" |
| | | } |
| | | }}> |
| | | <Grid container width={{ xs: '100%', xl: '100%' }}> |
| | | <Grid item xs={24} md={12}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.main')} |
| | | </Typography> |
| | | <Stack direction='row' gap={2}> |
| | | <NumberInput |
| | | label="table.field.waitPakinLog.pakinId" |
| | | source="pakinId" |
| | | readOnly |
| | | autoFocus |
| | | /> |
| | | <TextInput |
| | | label="table.field.waitPakinLog.code" |
| | | source="code" |
| | | readOnly |
| | | parse={v => v} |
| | | autoFocus |
| | | /> |
| | | <TextInput |
| | | label="table.field.waitPakin.asnCodes" |
| | | source="asnCodes" |
| | | readOnly |
| | | parse={v => v} |
| | | /> |
| | | <TextInput |
| | | label="table.field.waitPakinLog.barcode" |
| | | source="barcode" |
| | | readOnly |
| | | source="barcode" |
| | | parse={v => v} |
| | | /> |
| | | <NumberInput |
| | |
| | | /> |
| | | <SelectInput |
| | | label="table.field.waitPakinLog.ioStatus" |
| | | source="ioStatus" |
| | | readOnly |
| | | source="ioStatus" |
| | | choices={[ |
| | | { id: 0, name: '待入库' }, |
| | | { id: 1, name: ' 入库中' }, |
| | | ]} |
| | | validate={required()} |
| | | /> |
| | | </Stack> |
| | | </Grid> |
| | |
| | | TopToolbar, |
| | | SelectColumnsButton, |
| | | EditButton, |
| | | ShowButton, |
| | | FilterButton, |
| | | CreateButton, |
| | | ExportButton, |
| | |
| | | width: 200 |
| | | }, |
| | | })); |
| | | |
| | | const ViewDetailButton = () => ( |
| | | <ShowButton label="查看详情" /> |
| | | ); |
| | | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | |
| | | <StyledDatagrid |
| | | preferenceKey='waitPakinLog' |
| | | bulkActionButtons={false} |
| | | rowClick={'edit'} |
| | | rowClick={false} |
| | | expand={false} |
| | | expandSingle={true} |
| | | omit={['id', 'createTime', 'createBy', 'memo','statusBool']} |
| | |
| | | <NumberField source="pakinId" label="table.field.waitPakinLog.pakinId" /> |
| | | <TextField source="code" label="table.field.waitPakinLog.code" /> |
| | | <TextField source="barcode" label="table.field.waitPakinLog.barcode" /> |
| | | <NumberField source="anfme" label="table.field.waitPakinLog.anfme" /> |
| | | <NumberField source="anfme" label="table.field.waitPakinLog.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="ioStatus$" label="table.field.waitPakinLog.ioStatus" sortable={false} /> |
| | | <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> |
| | | <TextField source="nickname" /> |
| | |
| | | <DateField source="createTime" label="common.field.createTime" showTime /> |
| | | <BooleanField source="statusBool" label="common.field.status" sortable={false} /> |
| | | <TextField source="memo" label="common.field.memo" sortable={false} /> |
| | | <WrapperField cellClassName="opt" label="common.field.opt"> |
| | | <ViewDetailButton /> |
| | | </WrapperField> |
| | | </StyledDatagrid> |
| | | </List> |
| | | <PageDrawer |
| New file |
| | |
| | | import React from "react"; |
| | | import { |
| | | Show, |
| | | TextField, |
| | | NumberField, |
| | | } from 'react-admin'; |
| | | import { Box, Typography, Stack, Grid } from '@mui/material'; |
| | | import { useTranslate } from 'react-admin'; |
| | | import WaitPakinItemLogList from "./WaitPakinItemLogList"; |
| | | |
| | | /** |
| | | * 组托历史档查看详情:与组托通知档查看详情保持一致(主信息布局 + 明细列/omit 一致),仅展示无编辑。 |
| | | */ |
| | | const WaitPakinLogShow = () => { |
| | | const translate = useTranslate(); |
| | | return ( |
| | | <Show actions={false} title="组托历史档详情"> |
| | | <Box sx={{ pt: 1 }}> |
| | | <Grid container width={{ xs: '100%', xl: '100%' }}> |
| | | <Grid item xs={24} md={12}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.main')} |
| | | </Typography> |
| | | <Stack direction="row" gap={2} flexWrap="wrap" useFlexGap> |
| | | <TextField source="code" label="table.field.waitPakinLog.code" /> |
| | | <TextField source="asnCodes" label="table.field.waitPakin.asnCodes" /> |
| | | <TextField source="barcode" label="table.field.waitPakinLog.barcode" /> |
| | | <NumberField source="anfme" label="table.field.waitPakinLog.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="ioStatus$" label="table.field.waitPakinLog.ioStatus" /> |
| | | </Stack> |
| | | </Grid> |
| | | </Grid> |
| | | </Box> |
| | | <WaitPakinItemLogList /> |
| | | </Show> |
| | | ); |
| | | }; |
| | | |
| | | export default WaitPakinLogShow; |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { |
| | | ListGuesser, |
| | | EditGuesser, |
| | | ShowGuesser, |
| | | } from "react-admin"; |
| | | |
| | | import React from "react"; |
| | | import WaitPakinLogList from "./WaitPakinLogList"; |
| | | import WaitPakinLogEdit from "./WaitPakinLogEdit"; |
| | | import WaitPakinLogShow from "./WaitPakinLogShow"; |
| | | |
| | | export default { |
| | | list: WaitPakinLogList, |
| | | edit: WaitPakinLogEdit, |
| | | show: ShowGuesser, |
| | | show: WaitPakinLogShow, |
| | | recordRepresentation: (record) => { |
| | | return `${record.id}` |
| | | return record?.code != null ? record.code : `${record?.id ?? ''}`; |
| | | } |
| | | }; |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | {/* 现品票号已注释 |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.platItemId" |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | */} |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.platOrderCode" |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | {/* 现品票号已注释 |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.locItem.platItemId" |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | */} |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.locItem.platOrderCode" |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} />, |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="batch" label="table.field.locItem.batch" />, |
| | | <NumberField source="splrId" label="table.field.locItem.splrId" />, |
| | | <TextField source="spec" label="table.field.locItem.spec" />, |
| | |
| | | property={record.maktx} |
| | | /> |
| | | </Grid> |
| | | {/* 现品票号已注释 |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.platItemId" |
| | | property={record.platItemId} |
| | | /> |
| | | </Grid> |
| | | */} |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.platOrderCode" |
| | |
| | | <TextField source="batch" label="table.field.locItem.batch" />, |
| | | <TextField source="trackCode" label="table.field.locItem.trackCode" />, |
| | | <TextField source="unit" label="table.field.locItem.unit" />, |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" />, |
| | | <NumberField source="workQty" label="table.field.locItem.workQty" />, |
| | | <NumberField source="qty" label="table.field.locItem.qty" />, |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="workQty" label="table.field.locItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.locItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="splrBatch" label="table.field.locItem.splrBatch" />, |
| | | <TextField source="fieldsIndex" label="table.field.locItem.fieldsIndex" />, |
| | | ] |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="qty" label="table.field.purchase.qty" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="anfme" label="table.field.purchase.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.purchase.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <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 /> |
| | |
| | | source="barcode" |
| | | parse={v => v} |
| | | /> |
| | | {/* 包装已注释 |
| | | <TextInput |
| | | label="table.field.asnOrderItem.packName" |
| | | source="packName" |
| | | parse={v => v} |
| | | /> |
| | | */} |
| | | </Grid> |
| | | |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | |
| | | parse={v => v} |
| | | readOnly |
| | | /> |
| | | {/* 包装已注释 |
| | | <TextInput |
| | | label="table.field.asnOrderItem.packName" |
| | | source="packName" |
| | | parse={v => v} |
| | | /> |
| | | */} |
| | | </Stack> |
| | | </Grid> |
| | | </Grid> |
| | |
| | | <TextInput source="splrName" label="table.field.asnOrderItem.splrName" />, |
| | | <TextInput source="qrcode" label="table.field.asnOrderItem.qrcode" />, |
| | | <TextInput source="trackCode" label="table.field.asnOrderItem.barcode" />, |
| | | <TextInput source="packName" label="table.field.asnOrderItem.packName" />, |
| | | // <TextInput source="packName" label="table.field.asnOrderItem.packName" />, // 包装已注释 |
| | | <TextInput label="common.field.memo" source="memo" />, |
| | | <SelectInput |
| | | label="common.field.status" |
| | |
| | | <TextField source="orderCode" label="table.field.asnOrderItem.orderCode" />, |
| | | <TextField source="poDetlId" label="table.field.asnOrderItem.poDetlId" />, |
| | | <TextField source="poDetlCode" label="table.field.asnOrderItem.poDetlCode" />, |
| | | <TextField source="platItemId" label="table.field.asnOrderItem.platItemId" />, |
| | | // <TextField source="platItemId" label="table.field.asnOrderItem.platItemId" />, // 现品票号已注释 |
| | | <TextField source="matnrId" label="table.field.asnOrderItem.matnrId" />, |
| | | <TextField source="matnrCode" label="table.field.asnOrderItem.matnrCode" />, |
| | | <TextField source="maktx" label="table.field.asnOrderItem.maktx" />, |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} />, |
| | | <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ maximumFractionDigits: 6 }} />, |
| | | <NumberField source="anfme" label="table.field.asnOrderItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="stockUnit" label="table.field.asnOrderItem.stockUnit" />, |
| | | <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ maximumFractionDigits: 6 }} />, |
| | | <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="purUnit" label="table.field.asnOrderItem.purUnit" />, |
| | | <TextField source="splrCode" label="table.field.asnOrderItem.splrCode" />, |
| | | <TextField source="splrName" label="table.field.asnOrderItem.splrName" />, |
| | | <TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />, |
| | | // <TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />, // 质检已注释 |
| | | <TextField source="qrcode" label="table.field.asnOrderItem.qrcode" />, |
| | | <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />, |
| | | <TextField source="packName" label="table.field.asnOrderItem.packName" />, |
| | | // <TextField source="packName" label="table.field.asnOrderItem.packName" />, // 包装已注释 |
| | | ] |
| | | const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />) |
| | | const lastArr = [ |
| | |
| | | preferenceKey='asnOrderItem' |
| | | bulkActionButtons={false} |
| | | rowClick={(id, resource, record) => false} |
| | | omit={['id', 'orderId', 'orderCode', 'poDetlId', 'poDetlCode', 'matnrId', 'spec', 'model', 'purQty', 'purUnit', 'qrcode', 'trackCode', 'splrCode', 'platWorkCode', 'projectCode']} |
| | | omit={['id', 'orderId', 'orderCode', 'poDetlId', 'poDetlCode', 'matnrId', 'spec', 'model', 'purQty', 'purUnit', 'qrcode', 'trackCode', 'splrCode', 'platWorkCode', 'projectCode', 'platItemId', 'isptResult$', 'packName']} |
| | | > |
| | | {columns.map((column) => column)} |
| | | </StyledDatagrid>} |
| | |
| | | actions={( |
| | | <TopToolbar> |
| | | <FilterButton /> |
| | | <MyCreateButton onClick={() => { setCreateDialog(true); setmodalType(0) }} /> |
| | | <CreateByPoButton setPoCreate={setPoCreate} /> |
| | | {/* <MyCreateButton onClick={() => { setCreateDialog(true); setmodalType(0) }} /> 添加按钮暂不使用 */} |
| | | {/* <CreateByPoButton setPoCreate={setPoCreate} /> 通过PO单创建暂不使用 */} |
| | | <SelectColumnsButton preferenceKey='asnOrder' /> |
| | | <ImportButton value={'asnOrderItem'} /> |
| | | <MyExportButton /> |
| | |
| | | preferenceKey='asnOrder' |
| | | bulkActionButtons={ |
| | | <> |
| | | <InspectionsButton /> |
| | | {/* <InspectionsButton /> 报检按钮暂不使用 */} |
| | | <MyExportButton /> |
| | | {/* <BtnBulkExport></BtnBulkExport> */} |
| | | </>} |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="qty" label="table.field.asnOrder.qty" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="anfme" label="table.field.asnOrder.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.asnOrder.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <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" /> |
| | |
| | | <WrapperField cellClassName="opt" label="common.field.opt" > |
| | | <EditButton label="toolbar.detail"></EditButton> |
| | | <MyButton setCreateDialog={setCreateDialog} setmodalType={setmodalType} /> |
| | | <InspectionButton /> |
| | | {/* <InspectionButton /> 报检按钮暂不使用 */} |
| | | <CompleteButton /> |
| | | <ODeleteButton /> |
| | | <PrintButton setPrintOrder={setPrintOrder} setSelect={setSelect} /> |
| | |
| | | ), |
| | | headerClassName: "custom", |
| | | }, |
| | | { |
| | | field: 'platItemId', |
| | | headerName: translate('table.field.asnOrderItem.platItemId') + "*", |
| | | minWidth: 100, |
| | | flex: 1, |
| | | editable: true, |
| | | headerClassName: "custom", |
| | | }, |
| | | // 现品票号已注释 |
| | | // { |
| | | // field: 'platItemId', |
| | | // headerName: translate('table.field.asnOrderItem.platItemId') + "*", |
| | | // minWidth: 100, |
| | | // flex: 1, |
| | | // editable: true, |
| | | // headerClassName: "custom", |
| | | // }, |
| | | { |
| | | field: 'splrBatch', |
| | | headerName: translate('table.field.asnOrderItem.splrBatch'), |
| | |
| | | field: 'prodTime', |
| | | headerName: translate('table.field.asnOrderItem.prodTime') |
| | | }, |
| | | { |
| | | field: 'packName', |
| | | headerName: translate('table.field.asnOrderItem.packName') |
| | | }, |
| | | // { field: 'packName', headerName: translate('table.field.asnOrderItem.packName') }, // 包装已注释 |
| | | { |
| | | field: 'action', |
| | | headerName: '操作', |
| | |
| | | <Grid container spacing={2} sx={{ justifyContent: 'space-between', }}> |
| | | <Grid item md={2}> |
| | | <Box sx={{ display: 'flex', justifyContent: 'start' }}> |
| | | <Typography>ASN单:</Typography> |
| | | <Typography>单号:</Typography> |
| | | <Typography>{record?.code}</Typography> |
| | | </Box> |
| | | <Box sx={{ display: 'flex', justifyContent: 'start' }}> |
| | | <Typography>PO单:</Typography> |
| | | <Typography>单据内码:</Typography> |
| | | <Typography>{record?.poCode}</Typography> |
| | | </Box> |
| | | <Box sx={{ display: 'flex', justifyContent: 'start' }}> |
| | |
| | | <TextField source="orderCode" label="table.field.asnOrderItem.orderCode" />, |
| | | <TextField source="poDetlId" label="table.field.asnOrderItem.poDetlId" />, |
| | | <TextField source="poDetlCode" label="table.field.asnOrderItem.poDetlCode" />, |
| | | <TextField source="platItemId" label="table.field.asnOrderItem.platItemId" />, |
| | | // <TextField source="platItemId" label="table.field.asnOrderItem.platItemId" />, // 现品票号已注释 |
| | | <TextField source="matnrId" label="table.field.asnOrderItem.matnrId" />, |
| | | <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" 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 }} />, |
| | | <NumberField source="anfme" label="table.field.asnOrderItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.asnOrderItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="purQty" label="table.field.asnOrderItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | // <TextField source="splrName" label="table.field.asnOrderItem.splrName" />, |
| | | <TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />, |
| | | // <TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />, // 质检已注释 |
| | | // <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />, |
| | | <TextField source="packName" label="table.field.asnOrderItem.packName" />, |
| | | // <TextField source="packName" label="table.field.asnOrderItem.packName" />, // 包装已注释 |
| | | ] |
| | | const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />) |
| | | const lastArr = [ |
| | |
| | | ), |
| | | headerClassName: "custom", |
| | | }, |
| | | { |
| | | field: 'platItemId', |
| | | headerName: translate('table.field.asnOrderItem.platItemId') + "*", |
| | | minWidth: 100, |
| | | flex: 1, |
| | | editable: true, |
| | | headerClassName: "custom", |
| | | }, |
| | | // 现品票号已注释 |
| | | // { |
| | | // field: 'platItemId', |
| | | // headerName: translate('table.field.asnOrderItem.platItemId') + "*", |
| | | // minWidth: 100, |
| | | // flex: 1, |
| | | // editable: true, |
| | | // headerClassName: "custom", |
| | | // }, |
| | | { |
| | | field: 'anfme', |
| | | headerName: translate('table.field.asnOrderItem.anfme') + "*", |
| | |
| | | <TextField source="matnrCode" label="table.field.checkOrderItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.checkOrderItem.maktx" /> |
| | | <TextField source="platOrderCode" label="table.field.checkOrderItem.platOrderCode" /> |
| | | <NumberField source="anfme" label="table.field.checkOrderItem.anfme" /> |
| | | <NumberField source="workQty" label="table.field.checkOrderItem.workQty" /> |
| | | <NumberField source="qty" label="table.field.checkOrderItem.qty" /> |
| | | <NumberField source="anfme" label="table.field.checkOrderItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.checkOrderItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.checkOrderItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="stockUnit" label="table.field.checkOrderItem.stockUnit" /> |
| | | <TextField source="splrBatch" label="table.field.checkOrderItem.splrBatch" /> |
| | | <TextField source="splrCode" label="table.field.checkOrderItem.splrCode" /> |
| | |
| | | {/* <TextField source="type$" label="table.field.checkOrder.type" /> */} |
| | | <TextField cellClassName="wkType" source="wkType$" label="table.field.checkOrder.type" /> |
| | | <TextField source="checkType$" label="table.field.checkOrder.checkType" /> |
| | | <NumberField source="anfme" label="table.field.checkOrder.anfme" /> |
| | | <NumberField source="workQty" label="table.field.checkOrder.workQty" /> |
| | | <NumberField source="qty" label="table.field.checkOrder.qty" /> |
| | | <NumberField source="anfme" label="table.field.checkOrder.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.checkOrder.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.checkOrder.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <DateField source="arrTime" label="table.field.checkOrder.arrTime" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | |
| | | <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={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="splrName" label="table.field.deliveryItem.splrName" /> |
| | | <TextField source="splrBatch" label="table.field.deliveryItem.splrBatch" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | |
| | | <TextField source="orderCode" label="table.field.checkOrderItem.orderCode" /> |
| | | <TextField source="matnrCode" label="table.field.checkOrderItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.checkOrderItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.checkOrderItem.anfme" /> |
| | | <NumberField source="workQty" label="table.field.checkOrderItem.workQty" /> |
| | | <NumberField source="qty" label="table.field.checkOrderItem.qty" /> |
| | | <NumberField source="anfme" label="table.field.checkOrderItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.checkOrderItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.checkOrderItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="stockUnit" label="table.field.checkOrderItem.stockUnit" /> |
| | | <TextField source="splrName" label="table.field.checkOrderItem.splrName" /> |
| | | </StyledDatagrid> |
| | |
| | | |
| | | const baseColumns = [ |
| | | { field: 'locCode', headerName: '库位', width: 110 }, |
| | | { field: 'barcode', headerName: '容器', width: 120 }, |
| | | { field: 'barcode', headerName: '料箱码', width: 120 }, |
| | | { field: 'matnrCode', headerName: '物料编码', width: 120 }, |
| | | { field: 'batch', headerName: '批次', width: 90 }, |
| | | { field: 'unit', headerName: '单位', width: 60 }, |
| | |
| | | <TextField source="checkType$" label="table.field.checkDiff.checkType" sortable={false} /> |
| | | <NumberField source="areaId" label="table.field.checkDiff.areaId" /> |
| | | <TextField source="areaName" label="table.field.checkDiff.areaName" /> |
| | | <NumberField source="anfme" label="table.field.checkDiff.anfme" /> |
| | | <NumberField source="anfme" label="table.field.checkDiff.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="checkQty" label="table.field.checkDiff.checkQty" /> |
| | | {/* <NumberField source="exceStatus" label="table.field.checkDiff.exceStatus" /> */} |
| | | <NumberField source="updateBy$" label="common.field.updateBy" /> |
| | |
| | | <TextField source="model" label="table.field.checkDiffItem.model" /> |
| | | <TextField source="barcode" label="table.field.checkDiffItem.barcode" /> |
| | | <TextField source="batch" label="table.field.checkDiffItem.batch" /> |
| | | <NumberField source="anfme" label="table.field.checkDiffItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.checkDiffItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="checkQty" label="table.field.checkDiffItem.checkQty" /> |
| | | <CheckDiffField source="diffQty" label="table.field.checkDiffItem.diffQty" /> |
| | | <TextField source="reason" label="table.field.checkDiffItem.reason" /> |
| | |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={12} display="flex" gap={1}> |
| | | {/* 现品票号已注释 |
| | | <TextInput |
| | | label="table.field.deliveryItem.platItemId" |
| | | source="platItemId" |
| | | parse={v => v} |
| | | /> |
| | | */} |
| | | <TextInput |
| | | label="table.field.deliveryItem.matnrCode" |
| | | source="matnrCode" |
| | |
| | | source="deliveryId" |
| | | readOnly |
| | | /> |
| | | {/* 现品票号已注释 |
| | | <TextInput |
| | | label="table.field.deliveryItem.platItemId" |
| | | source="platItemId" |
| | | parse={v => v} |
| | | /> |
| | | */} |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <DateInput label='common.time.after' source="timeStart" />, |
| | | <DateInput label='common.time.before' source="timeEnd" />, |
| | | <TextInput source="platItemId" label="table.field.deliveryItem.platItemId" />, |
| | | // 现品票号已注释 <TextInput source="platItemId" label="table.field.deliveryItem.platItemId" />, |
| | | <TextInput source="matnrCode" label="table.field.deliveryItem.matnrCode" />, |
| | | <TextInput source="matnrName" label="table.field.deliveryItem.matnrName" />, |
| | | <TextInput source="splrName" label="table.field.deliveryItem.splrName" />, |
| | |
| | | > |
| | | <NumberField source="id" /> |
| | | <NumberField source="deliveryId" label="table.field.deliveryItem.deliveryId" /> |
| | | <TextField source="platItemId" label="table.field.deliveryItem.platItemId" /> |
| | | {/* 现品票号已注释 <TextField source="platItemId" label="table.field.deliveryItem.platItemId" /> */} |
| | | <TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.deliveryItem.matnrName" /> |
| | | <TextField source="fieldsIndex" label="table.field.deliveryItem.fieldsIndex" /> |
| | | <NumberField source="anfme" label="table.field.deliveryItem.anfme" /> |
| | | <NumberField source="workQty" label="table.field.deliveryItem.workQty" /> |
| | | <NumberField source="qty" label="table.field.deliveryItem.qty" /> |
| | | <NumberField source="anfme" label="table.field.deliveryItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.deliveryItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.deliveryItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="nromQty" label="table.field.deliveryItem.nromQty" /> |
| | | <TextField source="unit" label="table.field.deliveryItem.unit" /> |
| | | <TextField source="splrName" label="table.field.deliveryItem.splrName" /> |
| | |
| | | <TextField source="type$" label="table.field.delivery.type" /> |
| | | <TextField source="wkType$" label="table.field.delivery.wkType" /> |
| | | <TextField source="source" label="table.field.delivery.source" /> |
| | | <NumberField source="anfme" label="table.field.delivery.anfme" /> |
| | | <NumberField source="workQty" label="table.field.delivery.workQty" /> |
| | | <NumberField source="qty" label="table.field.delivery.qty" /> |
| | | <NumberField source="anfme" label="table.field.delivery.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.delivery.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.delivery.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="platCode" label="table.field.delivery.platCode" /> |
| | | <DateField source="startTime" label="table.field.delivery.startTime" showTime /> |
| | | <DateField source="endTime" label="table.field.delivery.endTime" showTime /> |
| | |
| | | <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" 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 }} />, |
| | | <NumberField source="anfme" label="table.field.outStockItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="purQty" label="table.field.outStockItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.outStockItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="stockUnit" label="table.field.outStockItem.stockUnit" />, |
| | | <TextField source="splrBatch" label="table.field.outStockItem.splrBatch" />, |
| | | <TextField source="purUnit" label="table.field.outStockItem.purUnit" />, |
| | |
| | | actions={( |
| | | <TopToolbar> |
| | | <FilterButton /> |
| | | <CreateByOrderButton setCreateDialog={setCreateDialog} /> |
| | | <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} /> |
| | | {/* <CreateByOrderButton setCreateDialog={setCreateDialog} /> 通过单据创建暂不使用 */} |
| | | {/* <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} /> 添加按钮暂不使用 */} |
| | | <SelectColumnsButton preferenceKey='outStock' /> |
| | | <ImportButton value={'outStockItem'} /> |
| | | </TopToolbar> |
| | |
| | | <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" 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 }} /> |
| | | <NumberField source="anfme" label="table.field.outStock.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.outStock.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.outStock.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <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" /> |
| | |
| | | ) |
| | | } |
| | | |
| | | /** 出库单执行状态:10=初始化(仅此状态显示编辑/详情) */ |
| | | /** 出库单执行状态:10=初始化(仅此状态显示编辑);详情任意状态可查看 */ |
| | | const OUT_STOCK_EXCE_STATUS_INIT = 10; |
| | | |
| | | const OutOrderRowActions = ({ setCreateDialog, setmodalType, setDrawerVal, drawerVal, setSelect }) => { |
| | |
| | | const isInit = record?.exceStatus === OUT_STOCK_EXCE_STATUS_INIT || record?.exceStatus === '10'; |
| | | return ( |
| | | <> |
| | | {isInit && ( |
| | | <> |
| | | <MyButton setCreateDialog={setCreateDialog} setmodalType={setmodalType} /> |
| | | {isInit && <MyButton setCreateDialog={setCreateDialog} setmodalType={setmodalType} />} |
| | | <EditButton label="toolbar.detail" icon={(<DetailsIcon />)} /> |
| | | </> |
| | | )} |
| | | <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} /> |
| | | </> |
| | | ); |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="anfme" label="table.field.deliveryItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="splrName" label="table.field.deliveryItem.splrName" /> |
| | | <TextField source="splrBatch" label="table.field.deliveryItem.splrBatch" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | |
| | | <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" 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 }} /> |
| | | <NumberField source="anfme" label="table.field.outStockItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.outStockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.outStockItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="stockUnit" label="table.field.outStockItem.stockUnit" /> |
| | | <TextField source="splrName" label="table.field.outStockItem.splrName" /> |
| | | </StyledDatagrid> |
| | |
| | | const baseColumns = [ |
| | | // { field: 'id', headerName: 'ID', width: 40 }, |
| | | { field: 'locCode', headerName: '库位', width: 110 }, |
| | | { field: 'barcode', headerName: '容器', width: 120 }, |
| | | { field: 'barcode', headerName: '料箱码', width: 120 }, |
| | | { field: 'matnrCode', headerName: '物料编码', width: 120 }, |
| | | { field: 'batch', headerName: '批次', width: 90 }, |
| | | { field: 'unit', headerName: '单位', width: 60 }, |
| | |
| | | defaultValue={row.poId} |
| | | /> |
| | | </Grid> |
| | | {/* 现品票号已注释 |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.purchaseItem.platItemId" |
| | |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | */} |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.purchaseItem.matnrCode" |
| | |
| | | source="purchaseId" |
| | | defaultValue={record?.id} |
| | | /> |
| | | {/* 现品票号已注释 |
| | | <TextInput |
| | | label="table.field.purchaseItem.platItemId" |
| | | source="platItemId" |
| | | parse={v => v} |
| | | /> |
| | | */} |
| | | <TextInput |
| | | label="table.field.purchaseItem.matnrCode" |
| | | source="matnrCode" |
| | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <NumberInput source="purchaseId" label="table.field.purchaseItem.purchaseId" />, |
| | | <TextInput source="platItemId" label="table.field.purchaseItem.platItemId" />, |
| | | // 现品票号已注释 <TextInput source="platItemId" label="table.field.purchaseItem.platItemId" />, |
| | | <TextInput source="matnrCode" label="table.field.purchaseItem.matnrCode" />, |
| | | <TextInput source="matnrName" label="table.field.purchaseItem.matnrName" />, |
| | | <TextInput source="unit" label="table.field.purchaseItem.unit" />, |
| | |
| | | > |
| | | <NumberField source="id" /> |
| | | <NumberField source="purchaseId" label="table.field.purchaseItem.purchaseId" /> |
| | | <TextField source="platItemId" label="table.field.purchaseItem.platItemId" /> |
| | | {/* 现品票号已注释 <TextField source="platItemId" label="table.field.purchaseItem.platItemId" /> */} |
| | | <TextField source="matnrCode" label="table.field.purchaseItem.matnrCode" /> |
| | | <TextField source="matnrName" label="table.field.purchaseItem.matnrName" /> |
| | | <TextField source="unit" label="table.field.purchaseItem.unit" /> |
| | | <NumberField source="anfme" label="table.field.purchaseItem.anfme" /> |
| | | <NumberField source="qty" label="table.field.purchaseItem.qty" /> |
| | | <NumberField source="anfme" label="table.field.purchaseItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.purchaseItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="nromQty" label="table.field.purchaseItem.nromQty" /> |
| | | <NumberField source="asnQty" label="table.field.purchaseItem.asnQty" /> |
| | | <NumberField source="printQty" label="table.field.purchaseItem.printQty" /> |
| | |
| | | <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={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.purchase.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | {/* <NumberField source="workQty" label="table.field.purchase.workQty" /> */} |
| | | <TextField source="channel" label="table.field.purchase.channel" /> |
| | | <TextField source="platCode" label="table.field.purchase.platCode" /> |
| | |
| | | label: 'table.field.purchaseItem.purchaseId', |
| | | minWidth: 100 |
| | | }, |
| | | { |
| | | id: 'platItemId', |
| | | label: 'table.field.purchaseItem.platItemId', |
| | | minWidth: 100 |
| | | }, |
| | | // 现品票号已注释 |
| | | // { |
| | | // id: 'platItemId', |
| | | // label: 'table.field.purchaseItem.platItemId', |
| | | // minWidth: 100 |
| | | // }, |
| | | { |
| | | id: 'matnrCode', |
| | | label: 'table.field.purchaseItem.matnrCode', |
| | |
| | | <TextField source="label" label="table.field.qlyIsptItem.label" /> |
| | | <TextField source="splrBatch" label="table.field.qlyIsptItem.splrBatch" /> |
| | | <NumberField source="dlyQty" label="table.field.qlyIsptItem.dlyQty" /> |
| | | <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="splrName" label="table.field.qlyIsptItem.splrName" /> |
| | | <NumberField source="isptResult$" label="table.field.qlyIsptItem.isptResult" /> |
| | | </StyledDatagrid> |
| | |
| | | <TextField source="matnrId" label="table.field.stockItem.matnrId" />, |
| | | <TextField source="matnrCode" label="table.field.stockItem.matnrCode" />, |
| | | <TextField source="maktx" label="table.field.stockItem.maktx" />, |
| | | <NumberField source="anfme" label="table.field.stockItem.anfme" />, |
| | | <NumberField source="anfme" label="table.field.stockItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="stockUnit" label="table.field.stockItem.stockUnit" />, |
| | | <NumberField source="workQty" label="table.field.stockItem.workQty" />, |
| | | <NumberField source="workQty" label="table.field.stockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="locCode" label="table.field.loc.code" />, |
| | | <TextField source="barcode" label="table.field.task.barcode" />, |
| | | <NumberField source="purQty" label="table.field.stockItem.purQty" />, |
| | | <NumberField source="purQty" label="table.field.stockItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="purUnit" label="table.field.stockItem.purUnit" />, |
| | | <NumberField source="qty" label="table.field.stockItem.qty" />, |
| | | <NumberField source="qty" label="table.field.stockItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="splrCode" label="table.field.stockItem.splrCode" />, |
| | | <TextField source="batch" label="table.field.stockItem.batch" />, |
| | | <TextField source="splrBatch" label="table.field.stockItem.splrBatch" />, |
| | |
| | | <TextField source="barcode" label="table.field.task.barcode" />, |
| | | <TextField source="type$" label="table.field.stock.type" /> |
| | | <TextField source="wkType$" label="table.field.stock.wkType" /> |
| | | <NumberField source="anfme" label="table.field.stock.anfme" /> |
| | | <NumberField source="anfme" label="table.field.stock.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | | <TextField source="createBy$" label="common.field.createBy" /> |
| | |
| | | <TextInput source="spec" label="table.field.transferItem.spec" />, |
| | | <TextInput source="model" label="table.field.transferItem.model" />, |
| | | <TextInput source="fieldsIndex" label="table.field.transferItem.fieldsIndex" />, |
| | | <TextInput source="platItemId" label="table.field.transferItem.platItemId" />, |
| | | // 现品票号已注释 <TextInput source="platItemId" label="table.field.transferItem.platItemId" />, |
| | | <TextInput source="platOrderCode" label="table.field.transferItem.platOrderCode" />, |
| | | <TextInput source="platWorkCode" label="table.field.transferItem.platWorkCode" />, |
| | | <TextInput source="projectCode" label="table.field.transferItem.projectCode" />, |
| | |
| | | <TextField source="model" label="table.field.transferItem.model" /> |
| | | <TextField source="batch" label="table.field.transferItem.batch" /> |
| | | <TextField source="unit" label="table.field.transferItem.unit" /> |
| | | <NumberField source="anfme" label="table.field.transferItem.anfme" /> |
| | | <NumberField source="workQty" label="table.field.transferItem.workQty" /> |
| | | <NumberField source="qty" label="table.field.transferItem.qty" /> |
| | | <NumberField source="anfme" label="table.field.transferItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.transferItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.transferItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="splrId" label="table.field.transferItem.splrId" /> |
| | | <TextField source="fieldsIndex" label="table.field.transferItem.fieldsIndex" /> |
| | | <TextField source="platItemId" label="table.field.transferItem.platItemId" /> |
| | | {/* 现品票号已注释 <TextField source="platItemId" label="table.field.transferItem.platItemId" /> */} |
| | | <TextField source="platOrderCode" label="table.field.transferItem.platOrderCode" /> |
| | | <TextField source="platWorkCode" label="table.field.transferItem.platWorkCode" /> |
| | | <TextField source="projectCode" label="table.field.transferItem.projectCode" /> |
| | |
| | | <TextField source="poCode" label="table.field.transferOrder.poCode" /> |
| | | <TextField source="type$" label="table.field.transferOrder.type" /> |
| | | <TextField cellClassName="wkType" source="wkType$" label="table.field.transferOrder.wkType" /> |
| | | <NumberField source="anfme" label="table.field.transferOrder.anfme" /> |
| | | <NumberField source="workQty" label="table.field.transferOrder.workQty" /> |
| | | <NumberField source="qty" label="table.field.transferOrder.qty" /> |
| | | <NumberField source="anfme" label="table.field.transferOrder.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.transferOrder.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.transferOrder.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="createBy$" label="common.field.createBy" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="createTime" label="common.field.createTime" showTime /> |
| | |
| | | <TextField source="unit" label="table.field.waveItem.unit" /> |
| | | <TextField source="trackCode" label="table.field.waveItem.trackCode" /> |
| | | <TextField source="fieldsIndex" label="table.field.waveItem.fieldsIndex" /> |
| | | <NumberField source="anfme" label="table.field.waveItem.anfme" /> |
| | | <NumberField source="workQty" label="table.field.waveItem.workQty" /> |
| | | <NumberField source="qty" label="table.field.waveItem.qty" /> |
| | | <NumberField source="anfme" label="table.field.waveItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="workQty" label="table.field.waveItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="qty" label="table.field.waveItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="stockQty" label="table.field.waveItem.stockQty" /> |
| | | <WrapperField cellClassName="opt" label="table.field.waveItem.stockLocs"> |
| | | <TagsField /> |
| | |
| | | <TextField source="maktx" label="table.field.waveItem.matnrName" /> |
| | | <TextField source="batch" label="table.field.waveItem.batch" /> |
| | | <TextField source="splrBatch" label="table.field.waveItem.splrBatch" /> |
| | | <NumberField source="anfme" label="table.field.waveItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.waveItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="fieldsIndex" label="table.field.waveItem.fieldsIndex" /> |
| | | <NumberField source="workQty" label="table.field.waveItem.workQty" /> |
| | | <NumberField source="workQty" label="table.field.waveItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="unit" label="table.field.waveItem.unit" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | |
| | | <NumberField source="id" /> |
| | | <TextField source="code" label="table.field.wave.code" /> |
| | | <TextField source="type$" label="table.field.wave.type" sortable={false} /> |
| | | <NumberField source="anfme" label="table.field.wave.anfme" /> |
| | | <NumberField source="anfme" label="table.field.wave.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="groupQty" label="table.field.wave.groupQty" /> |
| | | <NumberField source="workQty" label="table.field.wave.qty" /> |
| | | <NumberField source="workQty" label="table.field.wave.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="orderNum" label="table.field.wave.orderNum" /> |
| | | <DateField source="createTime" label="common.field.createTime" showTime /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | |
| | | <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" /> |
| | | <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="anfme" label="table.field.asnOrderItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="stockUnit" label="table.field.asnOrderItem.stockUnit" /> |
| | | <TextField source="splrName" label="table.field.asnOrderItem.splrName" /> |
| | | </StyledDatagrid> |
| | |
| | | <NumberField source="matnrId" label="table.field.locItem.matnrId" /> |
| | | <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.locItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="batch" label="table.field.locItem.batch" /> |
| | | <TextField source="trackCode" label="table.field.locItem.trackCode" /> |
| | | <TextField source="unit" label="table.field.locItem.unit" /> |
| | |
| | | <TextField source="locCode" label="table.field.stockStatistic.locCode" /> |
| | | <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.locItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="batch" label="table.field.locItem.batch" /> |
| | | <TextField source="unit" label="table.field.locItem.unit" /> |
| | | <TextField source="barcode" label="table.field.stockStatistic.barcode" /> |
| | |
| | | <TextField source="dayTime" label="table.field.stockStatistic.dayTime" /> |
| | | <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.locItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="batch" label="table.field.locItem.batch" /> |
| | | <TextField source="unit" label="table.field.locItem.unit" /> |
| | | </StyledDatagrid> |
| | |
| | | <TextField source="locCode" label="table.field.stockStatistic.locCode" /> |
| | | <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.locItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="batch" label="table.field.locItem.batch" /> |
| | | <TextField source="unit" label="table.field.locItem.unit" /> |
| | | <TextField source="barcode" label="table.field.stockStatistic.barcode" /> |
| | |
| | | <TextField source="dayTime" label="table.field.stockStatistic.dayTime" /> |
| | | <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.locItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="batch" label="table.field.locItem.batch" /> |
| | | <TextField source="unit" label="table.field.locItem.unit" /> |
| | | </StyledDatagrid> |
| | |
| | | <TextField source="matnrId" label="table.field.stockItem.matnrId" />, |
| | | <TextField source="matnrCode" label="table.field.stockItem.matnrCode" />, |
| | | <TextField source="maktx" label="table.field.stockItem.maktx" />, |
| | | <NumberField source="anfme" label="table.field.stockItem.anfme" />, |
| | | <NumberField source="anfme" label="table.field.stockItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="stockUnit" label="table.field.stockItem.stockUnit" />, |
| | | <NumberField source="workQty" label="table.field.stockItem.workQty" />, |
| | | <NumberField source="qty" label="table.field.stockItem.qty" />, |
| | | <NumberField source="workQty" label="table.field.stockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.stockItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="splrCode" label="table.field.stockItem.splrCode" />, |
| | | <TextField source="batch" label="table.field.stockItem.batch" />, |
| | | <TextField source="splrBatch" label="table.field.stockItem.splrBatch" />, |
| | |
| | | <NumberField source="matnrId" label="table.field.warehouseStock.matnrId" />, |
| | | <TextField source="matnrCode" label="table.field.warehouseStock.matnrCode" />, |
| | | <TextField source="maktx" label="table.field.warehouseStock.maktx" />, |
| | | <NumberField source="anfme" label="table.field.warehouseStock.anfme" />, |
| | | <NumberField source="workQty" label="table.field.warehouseStock.qty" />, |
| | | <NumberField source="anfme" label="table.field.warehouseStock.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="workQty" label="table.field.warehouseStock.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="spec" label="table.field.warehouseStock.spec" />, |
| | | <TextField source="model" label="table.field.warehouseStock.model" />, |
| | | <TextField source="warehouse$" label="table.field.warehouseStock.warehouse" />, |
| | |
| | | <NumberField source="count" label="table.field.stockStatistic.count" /> |
| | | <TextField source="inAnfmeCount" label="table.field.stockStatistic.inAnfmeCount" /> |
| | | <TextField source="outAnfmeCount" label="table.field.stockStatistic.outAnfmeCount" /> |
| | | <NumberField source="anfme" label="table.field.stockStatistic.anfme" /> |
| | | <NumberField source="anfme" label="table.field.stockStatistic.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="inAnfme" label="table.field.stockStatistic.inAnfme" /> |
| | | <TextField source="outAnfme" label="table.field.stockStatistic.outAnfme" /> |
| | | </StyledDatagrid> |
| | |
| | | <NumberField source="matnrId" label="table.field.stockItem.matnrId" /> |
| | | <TextField source="matnrCode" label="table.field.stockItem.matnrCode" /> |
| | | <TextField source="maktx" label="table.field.stockItem.maktx" /> |
| | | <NumberField source="anfme" label="table.field.stockItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.stockItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="stockUnit" label="table.field.stockItem.stockUnit" /> |
| | | <NumberField source="workQty" label="table.field.stockItem.workQty" /> |
| | | <NumberField source="purQty" label="table.field.stockItem.purQty" /> |
| | | <NumberField source="workQty" label="table.field.stockItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="purQty" label="table.field.stockItem.purQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="purUnit" label="table.field.stockItem.purUnit" /> |
| | | <NumberField source="qty" label="table.field.stockItem.qty" /> |
| | | <NumberField source="qty" label="table.field.stockItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="splrCode" label="table.field.stockItem.splrCode" /> |
| | | <TextField source="batch" label="table.field.stockItem.batch" /> |
| | | <TextField source="splrBatch" label="table.field.stockItem.splrBatch" /> |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="reviseQty" label="table.field.locItem.reviseQty" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="anfme" label="table.field.locItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <NumberField source="reviseQty" label="table.field.locItem.reviseQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <CheckDiffField source="diffQty" label="table.field.locItem.diffQty" /> |
| | | <TextField source="batch" label="table.field.locItem.batch" /> |
| | | <TextField source="spec" label="table.field.locItem.spec" /> |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} />, |
| | | <NumberField source="qty" label="table.field.taskItem.qty" options={{ maximumFractionDigits: 6 }} />, |
| | | <NumberField source="anfme" label="table.field.taskItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.taskItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | <TextField source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | |
| | | <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" options={{ maximumFractionDigits: 6 }} /> |
| | | <NumberField source="anfme" label="table.field.taskItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="batch" label="table.field.taskItem.batch" /> |
| | | <TextField source="spec" label="table.field.taskItem.spec" /> |
| | | <TextField source="model" label="table.field.taskItem.model" /> |
| | |
| | | parse={v => v} |
| | | autoFocus |
| | | /> |
| | | <TextInput |
| | | label="table.field.waitPakin.asnCodes" |
| | | source="asnCodes" |
| | | readOnly |
| | | parse={v => v} |
| | | /> |
| | | <SelectInput |
| | | label="table.field.waitPakin.flagDefect" |
| | | readOnly |
| | |
| | | <TextInput source="maktx" label="table.field.waitPakinItem.maktx" />, |
| | | <NumberInput source="matnrId" label="table.field.waitPakinItem.matnrId" />, |
| | | <TextInput source="matnrCode" label="table.field.waitPakinItem.matnrCode" />, |
| | | <TextInput source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | // <TextInput source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, // 客户单号已注释 |
| | | <TextInput source="asnCode" label="table.field.waitPakinItem.asnCode" />, |
| | | <TextInput source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextInput source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | | <NumberInput source="anfme" label="table.field.waitPakinItem.anfme" />, |
| | |
| | | <TextField source="maktx" label="table.field.waitPakinItem.maktx" />, |
| | | <TextField source="batch" label="table.field.waitPakinItem.batch" />, |
| | | <NumberField source="matnrId" label="table.field.waitPakinItem.matnrId" />, |
| | | <NumberField source="anfme" label="table.field.waitPakinItem.anfme" />, |
| | | <NumberField source="anfme" label="table.field.waitPakinItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="unit" label="table.field.waitPakinItem.unit" />, |
| | | <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | // <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, // 客户单号已注释 |
| | | <TextField source="asnCode" label="table.field.waitPakinItem.asnCode" />, |
| | | <TextField source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | | <NumberField source="workQty" label="table.field.waitPakinItem.workQty" />, |
| | | <NumberField source="qty" label="table.field.waitPakinItem.qty" />, |
| | | <NumberField source="workQty" label="table.field.waitPakinItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField source="qty" label="table.field.waitPakinItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="fieldsIndex" label="table.field.waitPakinItem.fieldsIndex" />, |
| | | <TextField source="isptResult$" label="table.field.waitPakinItem.isptResult" />, |
| | | // <TextField source="isptResult$" label="table.field.waitPakinItem.isptResult" />, // 质检票号已注释 |
| | | // <TextField source="platItemId" label="table.field.waitPakinItem.platItemId" />, // 现品票号已注释 |
| | | ] |
| | | const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />) |
| | | // 现品票号已注释:过滤掉 extendFields 中的现品票号(crushNo) 及别名为现品票号的字段 |
| | | const fields = data |
| | | .filter(el => el.fields !== 'crushNo' && el.fieldsAlise !== '现品票号') |
| | | .map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />) |
| | | const lastArr = [ |
| | | <TextField source="updateBy$" label="common.field.updateBy" />, |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime />, |
| | |
| | | preferenceKey='waitPakinItem' |
| | | bulkActionButtons={false} |
| | | rowClick={(id, resource, record) => false} |
| | | omit={['id', 'pakinId', 'createTime', 'matnrId', 'createBy', 'memo', 'fieldsIndex', 'platWorkCode', 'projectCode']} |
| | | omit={['id', 'pakinId', 'createTime', 'matnrId', 'createBy', 'memo', 'fieldsIndex', 'platWorkCode', 'projectCode', 'platOrderCode', 'isptResult$', 'platItemId']} |
| | | > |
| | | {columns.map((column) => column)} |
| | | </StyledDatagrid>} |
| | |
| | | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <TextInput source="asnCode" label="table.field.waitPakin.asnCode" />, |
| | | <TextInput source="code" label="table.field.waitPakin.code" />, |
| | | <TextInput source="barcode" label="table.field.waitPakin.barcode" />, |
| | | <NumberInput source="anfme" label="table.field.waitPakin.anfme" />, |
| | |
| | | preferenceKey='waitPakin' |
| | | bulkActionButtons={ |
| | | <> |
| | | <CreateTaskButton /> |
| | | {/* <CreateTaskButton /> 下发任务按钮暂不使用 */} |
| | | {/* <BulkDeleteButton mutationMode={OPERATE_MODE} /> */} |
| | | </>} |
| | | rowClick={false} |
| | |
| | | > |
| | | <NumberField source="id" /> |
| | | <TextField source="code" label="table.field.waitPakin.code" /> |
| | | <TextField source="asnCodes" label="table.field.waitPakin.asnCodes" sortable={false} /> |
| | | <TextField source="barcode" label="table.field.waitPakin.barcode" /> |
| | | <NumberField source="anfme" label="table.field.waitPakin.anfme" /> |
| | | <NumberField source="anfme" label="table.field.waitPakin.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="ioStatus$" label="table.field.waitPakin.ioStatus" sortable={false} /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | |
| | | <TextField source="memo" label="common.field.memo" sortable={false} /> |
| | | <WrapperField cellClassName="opt" label="common.field.opt"> |
| | | <EditButton label="toolbar.detail" sx={{ padding: '1px', fontSize: '.75rem' }} /> |
| | | <CreateTaskRowButton /> |
| | | {/* <CreateTaskRowButton /> 下发任务按钮暂不使用 */} |
| | | <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} /> |
| | | </WrapperField> |
| | | </StyledDatagrid> |
| | |
| | | <TextField key="maktx" source="maktx" label="table.field.warehouseAreasItem.matnrName" />, |
| | | <TextField key="matnrCode" source="matnrCode" label="table.field.warehouseAreasItem.matnrCode" />, |
| | | <TextField key="trackCode" source="trackCode" label="table.field.warehouseAreasItem.barcode" />, |
| | | <NumberField key="anfme" source="anfme" label="table.field.warehouseAreasItem.anfme" />, |
| | | <NumberField key="workQty" source="workQty" label="table.field.warehouseAreasItem.workQty" />, |
| | | <NumberField key="qty" source="qty" label="table.field.warehouseAreasItem.qty" />, |
| | | <NumberField key="anfme" source="anfme" label="table.field.warehouseAreasItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField key="workQty" source="workQty" label="table.field.warehouseAreasItem.workQty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <NumberField key="qty" source="qty" label="table.field.warehouseAreasItem.qty" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} />, |
| | | <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | <TextField source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | |
| | | <TextField source="label" label="table.field.qlyIsptItem.label" /> |
| | | <TextField source="splrBatch" label="table.field.qlyIsptItem.splrBatch" /> |
| | | <NumberField source="dlyQty" label="table.field.qlyIsptItem.dlyQty" /> |
| | | <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" /> |
| | | <NumberField source="anfme" label="table.field.qlyIsptItem.anfme" options={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} /> |
| | | <TextField source="splrName" label="table.field.qlyIsptItem.splrName" /> |
| | | <NumberField source="isptResult$" label="table.field.qlyIsptItem.isptResult" /> |
| | | </StyledDatagrid> |
| | |
| | | |
| | | /** 库存/数量显示:保留最多6位小数,去掉末尾多余的0(不强制补零) */ |
| | | /** 前端数量显示:统一保留2位小数(仅展示,后端不变) */ |
| | | export const formatQuantity = (value) => { |
| | | if (value == null || value === '') return '0'; |
| | | if (value == null || value === '') return '0.00'; |
| | | 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+$/, ''); |
| | | if (Number.isNaN(n)) return '0.00'; |
| | | if (n < 0) return '0.00'; |
| | | return n.toFixed(2); |
| | | }; |
| | | |
| | | /** 用于 react-admin NumberField 的数量展示 options(2位小数) */ |
| | | export const QTY_NUMBER_OPTIONS = { minimumFractionDigits: 2, maximumFractionDigits: 2 }; |
| | | |
| | | /** 校验最多 N 位小数,用于数量类字段;超过时返回错误信息并阻止提交 */ |
| | | export const maxDecimalPlaces = (maxDecimals, message) => { |
| | | const factor = Math.pow(10, maxDecimals); |
| | |
| | | @ExceptionHandler(Exception.class) |
| | | public ResponseEntity<CommonResponse> handleException(Exception e) { |
| | | log.error("系统异常", e); |
| | | String msg = e.getMessage() != null ? e.getMessage() : "系统异常"; |
| | | CommonResponse r = new CommonResponse(); |
| | | r.setCode(500); |
| | | r.setMsg(msg); |
| | | r.setMsg("系统异常"); |
| | | r.setData(ResultData.fail()); |
| | | return ResponseEntity.status(HttpStatus.OK).body(r); |
| | | } |
| | |
| | | private String orderNo; |
| | | |
| | | /** |
| | | * PO单号 |
| | | * 单据内码 |
| | | */ |
| | | @ApiModelProperty(value = "PO单号") |
| | | @ApiModelProperty(value = "单据内码") |
| | | private String poCode; |
| | | |
| | | /** |
| | |
| | | package com.vincent.rsf.openApi.entity.params; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonAlias; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.AccessLevel; |
| | | import lombok.Data; |
| | | import lombok.Setter; |
| | | import lombok.experimental.Accessors; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @ApiModelProperty(value = "业务类型,如:采购入库单、销售出库单、调拨申请单等", required = true) |
| | | private String wkType; |
| | | |
| | | @ApiModelProperty(value = "业务日期,时间戳精确到秒", required = true) |
| | | private Long businessTime; |
| | | @ApiModelProperty(value = "添加时间,支持 yyyy-MM-dd HH:mm:ss 或时间戳(秒/毫秒)") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @Setter(AccessLevel.NONE) |
| | | private Date businessTime; |
| | | |
| | | @ApiModelProperty(value = "创建日期,时间戳精确到秒", required = true) |
| | | private Long createTime; |
| | | @ApiModelProperty(value = "创建时间,支持 yyyy-MM-dd HH:mm:ss 或时间戳(秒/毫秒)") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @Setter(AccessLevel.NONE) |
| | | private Date createTime; |
| | | |
| | | @JsonDeserialize(using = FlexibleDateDeserializer.class) |
| | | public void setBusinessTime(Date businessTime) { |
| | | this.businessTime = businessTime; |
| | | } |
| | | |
| | | @JsonDeserialize(using = FlexibleDateDeserializer.class) |
| | | public void setCreateTime(Date createTime) { |
| | | this.createTime = createTime; |
| | | } |
| | | |
| | | @ApiModelProperty(value = "订单明细", required = true) |
| | | private List<WmsOrderItemParam> orderItems; |
| | |
| | | @ApiModelProperty("机器人编码") |
| | | private String robotCode; |
| | | |
| | | @ApiModelProperty("容器码") |
| | | @ApiModelProperty("料箱码") |
| | | private String zpallet; |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.openApi.entity.params; |
| | | |
| | | import com.fasterxml.jackson.core.JsonParser; |
| | | import com.fasterxml.jackson.core.JsonToken; |
| | | import com.fasterxml.jackson.databind.DeserializationContext; |
| | | import com.fasterxml.jackson.databind.JsonDeserializer; |
| | | |
| | | import java.io.IOException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.TimeZone; |
| | | |
| | | /** |
| | | * 支持时间戳(秒/毫秒)与字符串 "yyyy-MM-dd HH:mm:ss" 的 Date 反序列化,与 @JsonFormat 配合使用。 |
| | | */ |
| | | public class FlexibleDateDeserializer extends JsonDeserializer<Date> { |
| | | |
| | | private static final long MS_THRESHOLD = 10_000_000_000L; // 大于此为毫秒 |
| | | private static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; |
| | | private static final TimeZone DEFAULT_TZ = TimeZone.getTimeZone("GMT+8"); |
| | | |
| | | @Override |
| | | public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { |
| | | JsonToken t = p.getCurrentToken(); |
| | | if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { |
| | | long v = p.getLongValue(); |
| | | long ms = v >= MS_THRESHOLD ? v : v * 1000; |
| | | return new Date(ms); |
| | | } |
| | | if (t == JsonToken.VALUE_STRING) { |
| | | String s = p.getText().trim(); |
| | | if (s.isEmpty()) return null; |
| | | try { |
| | | long v = Long.parseLong(s); |
| | | long ms = v >= MS_THRESHOLD ? v : v * 1000; |
| | | return new Date(ms); |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | try { |
| | | SimpleDateFormat sdf = new SimpleDateFormat(PATTERN); |
| | | sdf.setTimeZone(DEFAULT_TZ); |
| | | sdf.setLenient(false); |
| | | return sdf.parse(s); |
| | | } catch (Exception ignored) { |
| | | } |
| | | if (s.length() >= 10 && s.charAt(4) == '-' && s.charAt(7) == '-') { |
| | | try { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | sdf.setTimeZone(DEFAULT_TZ); |
| | | sdf.setLenient(false); |
| | | return sdf.parse(s.substring(0, 10)); |
| | | } catch (Exception ignored) { |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | if (t == JsonToken.VALUE_NULL) return null; |
| | | return (Date) ctxt.handleUnexpectedToken(Date.class, p); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.openApi.entity.params; |
| | | |
| | | import com.fasterxml.jackson.core.JsonParser; |
| | | import com.fasterxml.jackson.core.JsonToken; |
| | | import com.fasterxml.jackson.databind.DeserializationContext; |
| | | import com.fasterxml.jackson.databind.JsonDeserializer; |
| | | |
| | | import java.io.IOException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.TimeZone; |
| | | |
| | | /** |
| | | * 将 JSON 反序列化为 Unix 时间戳(秒,Long)。 |
| | | * 支持:数字(秒或毫秒)、字符串 "yyyy-MM-dd HH:mm:ss" 或 "yyyy-MM-dd"。 |
| | | */ |
| | | public class FlexibleTimestampDeserializer extends JsonDeserializer<Long> { |
| | | |
| | | private static final long MS_THRESHOLD = 10_000_000_000L; // 大于此为毫秒 |
| | | private static final TimeZone DEFAULT_TZ = TimeZone.getTimeZone("GMT+8"); |
| | | |
| | | @Override |
| | | public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { |
| | | JsonToken t = p.getCurrentToken(); |
| | | if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { |
| | | long v = p.getLongValue(); |
| | | return v >= MS_THRESHOLD ? v / 1000 : v; |
| | | } |
| | | if (t == JsonToken.VALUE_STRING) { |
| | | String s = p.getText().trim(); |
| | | if (s.isEmpty()) { |
| | | return null; |
| | | } |
| | | try { |
| | | long v = Long.parseLong(s); |
| | | return v >= MS_THRESHOLD ? v / 1000 : v; |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | try { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | sdf.setTimeZone(DEFAULT_TZ); |
| | | sdf.setLenient(false); |
| | | Date d = sdf.parse(s); |
| | | return d != null ? d.getTime() / 1000 : null; |
| | | } catch (Exception ignored) { |
| | | } |
| | | if (s.length() >= 10 && s.charAt(4) == '-' && s.charAt(7) == '-') { |
| | | try { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | sdf.setTimeZone(DEFAULT_TZ); |
| | | sdf.setLenient(false); |
| | | Date d = sdf.parse(s.substring(0, 10)); |
| | | return d != null ? d.getTime() / 1000 : null; |
| | | } catch (Exception ignored) { |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | if (t == JsonToken.VALUE_NULL) { |
| | | return null; |
| | | } |
| | | return (Long) ctxt.handleUnexpectedToken(Long.class, p); |
| | | } |
| | | } |
| | |
| | | @ApiModelProperty("采购退货单号/生产单号/") |
| | | private String OrderNO; |
| | | |
| | | @ApiModelProperty("现品票号") |
| | | @ApiModelProperty("现品票号(已废弃)") |
| | | private String GoodsNO; |
| | | |
| | | @ApiModelProperty("盘点数量") |
| | |
| | | log.info("order/add 收到 operateType=3,走统一取消逻辑: {}", params.getOrderNo()); |
| | | return doCancel(params); |
| | | } |
| | | if (params.getOrderInternalCode() == null || params.getOrderInternalCode().trim().isEmpty()) { |
| | | throw new CoolException("单据内码不能为空!!"); |
| | | } |
| | | Map<String, Object> mapParams = toServerOrderMap(params); |
| | | List<Map<String, Object>> maps = Collections.singletonList(mapParams); |
| | | log.info("新增/修改单据,请求参数: {}", JSONArray.toJSONString(maps)); |
| | |
| | | private Map<String, Object> toServerOrderMap(ErpOpParams params) { |
| | | Map<String, Object> m = new HashMap<>(); |
| | | m.put("orderNo", params.getOrderNo()); |
| | | m.put("orderInternalCode", params.getOrderInternalCode()); |
| | | m.put("stationId", params.getStationId()); |
| | | m.put("wkType", params.getWkType()); |
| | | m.put("type", params.getOrderType() != null ? String.valueOf(params.getOrderType()) : null); |
| | | m.put("orderId", params.getOrderId()); |
| | | m.put("operateType", params.getOperateType()); |
| | | double anfmeSum = 0; |
| | | if (params.getOrderItems() != null) { |
| | | List<Map<String, Object>> items = params.getOrderItems().stream() |
| | |
| | | } |
| | | m.put("anfme", anfmeSum); |
| | | if (params.getBusinessTime() != null) { |
| | | m.put("arrTime", new Date(params.getBusinessTime() * 1000)); |
| | | m.put("arrTime", params.getBusinessTime()); |
| | | } else if (params.getCreateTime() != null) { |
| | | m.put("arrTime", new Date(params.getCreateTime() * 1000)); |
| | | m.put("arrTime", params.getCreateTime()); |
| | | } |
| | | return m; |
| | | } |
| | |
| | | m.put("model", item.getModel()); |
| | | m.put("unit", item.getUnit()); |
| | | m.put("batch", item.getBatch()); |
| | | m.put("planNo", item.getPlanNo()); |
| | | m.put("palletId", item.getPalletId()); |
| | | m.put("targetWareHouseId", item.getTargetWareHouseId()); |
| | | m.put("sourceWareHouseId", item.getSourceWareHouseId()); |
| | | return m; |
| | | } |
| | | |
| | |
| | | @ApiModelProperty("采购退货单号/生产单号/") |
| | | private String OrderNO; |
| | | |
| | | @ApiModelProperty("现品票号") |
| | | @ApiModelProperty("现品票号(已废弃)") |
| | | private String GoodsNO; |
| | | |
| | | @ApiModelProperty("盘点数量") |
| | |
| | | @ApiModelProperty("单号") |
| | | private String orderNo; |
| | | |
| | | @ApiModelProperty("单据内码,唯一标识") |
| | | private String orderInternalCode; |
| | | |
| | | @ApiModelProperty("入/出库接驳站点") |
| | | private String stationId; |
| | | |
| | | @ApiModelProperty("原库位") |
| | | private String orgLoc; |
| | | |
| | | @ApiModelProperty("订单ID") |
| | | private Long orderId; |
| | | |
| | | @ApiModelProperty("操作类型:1 新增;2 修改;3 取消") |
| | | private Integer operateType; |
| | | |
| | | @ApiModelProperty("数量") |
| | | private Double anfme; |
| | | |
| | |
| | | @ApiModelProperty("库存批次") |
| | | private String batch; |
| | | |
| | | @ApiModelProperty("计划跟踪号") |
| | | private String planNo; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | private String palletId; |
| | | |
| | | @ApiModelProperty("建议入库仓库") |
| | | private String targetWareHouseId; |
| | | |
| | | @ApiModelProperty("建议出库仓库") |
| | | private String sourceWareHouseId; |
| | | |
| | | @ApiModelProperty("已收数量") |
| | | private Double qty; |
| | | |
| | |
| | | @ApiModelProperty("作业站点 or 来源站点") |
| | | private String sourceStaNo; //作业站点 or 来源站点 |
| | | |
| | | @ApiModelProperty("容器条码") |
| | | private String barcode; //容器条码 |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; //料箱码 |
| | | |
| | | @ApiModelProperty("库位类型") |
| | | private Integer locType1; //库位类型 |
| | |
| | | |
| | | @PreAuthorize("hasAuthority('manager:task:list')") |
| | | @PostMapping("/getCheckTaskItemList2") |
| | | @ApiOperation("查询盘点任务列表,直接扫容器码") |
| | | @ApiOperation("查询盘点任务列表,直接扫料箱码") |
| | | public R getCheckTaskItemList2(@RequestBody Map<String, String> map) { |
| | | |
| | | return pdaCheckOrderService.getCheckTaskItemList2(map.get("barcode")); |
| | |
| | | |
| | | @PreAuthorize("hasAuthority('manager:task:list')") |
| | | @PostMapping("/getContainerWaveList") |
| | | @ApiOperation("根据容器码查询波次及出库单") |
| | | @ApiOperation("根据料箱码查询波次及出库单") |
| | | public R getContainerWaveList(@RequestBody Map<String, String> map) { |
| | | return pdaOutStockService.getContainerWaveList(map); |
| | | } |
| | |
| | | |
| | | @PreAuthorize("hasAuthority('manager:task:list')") |
| | | @PostMapping("/saveWavePick") |
| | | @ApiOperation("根据容器码查询波次及出库单") |
| | | @ApiOperation("根据料箱码查询波次及出库单") |
| | | public R saveWavePick(@RequestBody ContainerWaveParam containerWaveParam) { |
| | | |
| | | return pdaOutStockService.saveWavePick(containerWaveParam,getLoginUserId()); |
| | |
| | | private String code; |
| | | @ApiModelProperty("单号ID") |
| | | private Long id; |
| | | @ApiModelProperty("PO单号") |
| | | @ApiModelProperty("单据内码") |
| | | private String poCode; |
| | | @ApiModelProperty("明细") |
| | | private List<InspectItemDto> items; |
| | |
| | | @ApiModelProperty("小车编号 ") |
| | | private String robotCode; |
| | | |
| | | @ApiModelProperty("容器码") |
| | | @ApiModelProperty("料箱码") |
| | | private String zpallet; |
| | | } |
| | |
| | | |
| | | private BasStation checkStaStatus(String barcode, String sta) { |
| | | if (Cools.isEmpty(barcode)) { |
| | | throw new CoolException("容器码不能为空"); |
| | | throw new CoolException("料箱码不能为空"); |
| | | } |
| | | if (Cools.isEmpty(sta)) { |
| | | throw new CoolException("接驳位条码不能为空"); |
| | |
| | | .eq(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val) |
| | | ); |
| | | if (Cools.isEmpty(waitPakin)) { |
| | | throw new CoolException("容器码未找到组托信息,请检查组托状态"); |
| | | throw new CoolException("料箱码未找到组托信息,请检查组托状态"); |
| | | } |
| | | BasStation isBarcodeSta = basStationService.getOne(new LambdaQueryWrapper<BasStation>() |
| | | .eq(BasStation::getBarcode, barcode) |
| | |
| | | import com.vincent.rsf.server.common.security.JwtSubject; |
| | | import com.vincent.rsf.server.common.utils.FieldsUtils; |
| | | import com.vincent.rsf.server.common.utils.JwtUtil; |
| | | import com.vincent.rsf.server.common.utils.QuantityUtils; |
| | | import com.vincent.rsf.server.manager.controller.params.GenerateTaskParams; |
| | | import com.vincent.rsf.server.manager.controller.params.IsptItemsParams; |
| | | import com.vincent.rsf.server.manager.controller.params.WaitPakinParam; |
| | |
| | | throw new CoolException("数据错误:主单不存在!!"); |
| | | } |
| | | //TODO /**收货数量累加,1. 会出超收情况 2. 会有收货不足情况*/ |
| | | Double rcptedQty = Math.round((wkOrder.getQty() + receiptQty) * 1000000) / 1000000.0; |
| | | wkOrder.setQty(rcptedQty).setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val); |
| | | Double rcptedQty = QuantityUtils.add(wkOrder.getQty(), receiptQty); |
| | | // 新顺序:未执行(组托)→任务执行中→已完成,不再设置执行中/收货完成 |
| | | wkOrder.setQty(rcptedQty); // .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val) |
| | | if (!asnOrderMapper.updateById(wkOrder)) { |
| | | throw new CoolException("已收货数量修改失败!!"); |
| | | } |
| | |
| | | throw new CoolException("请输入正确的时间格式!!"); |
| | | } |
| | | |
| | | Double itemRcptQty = Math.round((dto.getReceiptQty() + orderItem.getQty()) * 1000000) / 1000000.0; |
| | | Double itemRcptQty = QuantityUtils.add(dto.getReceiptQty(), orderItem.getQty()); |
| | | Boolean allowOver = false; |
| | | if (!Objects.isNull(config)) { |
| | | if (Boolean.parseBoolean(config.getVal())) { |
| | | allowOver = true; |
| | | } |
| | | } |
| | | if (itemRcptQty.compareTo(orderItem.getAnfme()) > 0 && !allowOver) { |
| | | if (QuantityUtils.compare(itemRcptQty, orderItem.getAnfme()) > 0 && !allowOver) { |
| | | throw new CoolException("收货数量不能大于计划数量!!"); |
| | | } |
| | | |
| | |
| | | if (asnOrderItemMapper.updateById(orderItem) < 1) { |
| | | throw new CoolException("通知单明细数量修改失败!!"); |
| | | } |
| | | /**保存明细至收货区**/ |
| | | extracted(loginUserId, dto, areasItem, orderItem, wkOrder, matnr); |
| | | |
| | | // 收货区已停用,不再保存至收货区 |
| | | // extracted(loginUserId, dto, areasItem, orderItem, wkOrder, matnr); |
| | | } |
| | | |
| | | WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode)); |
| | | if (order.getQty().compareTo(order.getAnfme()) >= 0.00) { |
| | | order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val).setRleStatus(Short.valueOf("1")); |
| | | if (!asnOrderMapper.updateById(order)) { |
| | | throw new CoolException("订单状态修改失败!!"); |
| | | } |
| | | } |
| | | // 新顺序:未执行(组托)→任务执行中→已完成,不再设置收货完成 |
| | | // WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode)); |
| | | // if (order.getQty().compareTo(order.getAnfme()) >= 0.00) { |
| | | // order.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val).setRleStatus(Short.valueOf("1")); |
| | | // if (!asnOrderMapper.updateById(order)) { |
| | | // throw new CoolException("订单状态修改失败!!"); |
| | | // } |
| | | // } |
| | | |
| | | return R.ok("收货成功!!"); |
| | | } |
| | |
| | | .setUnit(orderItem.getStockUnit()) |
| | | .setStockUnit(orderItem.getStockUnit()) |
| | | .setBatch(StringUtils.isBlank(orderItem.getBatch()) ? SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_RECEIPT_BATCH, dto) : orderItem.getBatch()) |
| | | .setAnfme(dto.getReceiptQty()) |
| | | .setAnfme(QuantityUtils.roundToScale(dto.getReceiptQty())) |
| | | .setSplrBatch(dto.getSplrBatch()) |
| | | .setMatnrCode(matnr.getCode()) |
| | | .setUpdateBy(loginUserId) |
| | |
| | | |
| | | if (!Objects.isNull(serviceOne)) { |
| | | item.setId(serviceOne.getId()); |
| | | Double anfme = Math.round((item.getAnfme() + serviceOne.getAnfme()) * 1000000) / 1000000.0; |
| | | item.setAnfme(anfme); |
| | | item.setAnfme(QuantityUtils.add(item.getAnfme(), serviceOne.getAnfme())); |
| | | } |
| | | |
| | | //未质检 |
| | |
| | | * @description 获取收货区 |
| | | * @time 2025/3/11 10:12 |
| | | */ |
| | | /** 收货区已停用,返回空列表 */ |
| | | @Override |
| | | public R getReceiptAreas() { |
| | | List<WarehouseAreas> areas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>() |
| | | .eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type)); |
| | | return R.ok(areas); |
| | | // List<WarehouseAreas> areas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>() |
| | | // .eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type)); |
| | | // return R.ok(areas); |
| | | return R.ok(Collections.emptyList()); |
| | | } |
| | | |
| | | /** |
| | |
| | | // throw new CoolException("票号不能为空!!"); |
| | | // } |
| | | // if (Objects.isNull(code)) { |
| | | // throw new CoolException("容器号不能为空!!"); |
| | | // throw new CoolException("料箱码不能为空!!"); |
| | | // } |
| | | // BasContainer container = basContainerService.getOne(new LambdaQueryWrapper<BasContainer>().eq(BasContainer::getCode, barcode)); |
| | | // if (Objects.isNull(container)) { |
| | |
| | | return R.ok(resultList); |
| | | } |
| | | |
| | | //TODO 后续需根据策略配置,获取组拖数据。如:混装,按批次混装等 |
| | | LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<>(); |
| | | |
| | | // 如果有ASN单号,则只查询该单号下的物料(ASN单号作为必须条件) |
| | | // 收货区已停用:有ASN单号时从订单明细查可组托物料;可组盘数量 = 计划数量 - 已组托数量 - 已上架数量 |
| | | if (!Cools.isEmpty(asnCode)) { |
| | | // ASN单号作为必须条件 |
| | | queryWrapper.eq(WarehouseAreasItem::getAsnCode, asnCode); |
| | | |
| | | // 如果同时有物料编码,则查询该ASN单号下的该物料 |
| | | if (!Cools.isEmpty(matnrCode)) { |
| | | queryWrapper.eq(WarehouseAreasItem::getMatnrCode, matnrCode); |
| | | WkOrder order = asnOrderMapper.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, asnCode)); |
| | | if (order == null) { |
| | | logger.info("未找到ASN单号: {}", asnCode); |
| | | return R.ok(Collections.emptyList()); |
| | | } |
| | | // 按明细汇总已组托数量(组托数量不会因改单而变) |
| | | List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId())); |
| | | Map<Long, Double> palletizedByItemId = pakinItems.stream() |
| | | .collect(Collectors.groupingBy(WaitPakinItem::getAsnItemId, Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0))); |
| | | palletizedByItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v)); |
| | | LambdaQueryWrapper<WkOrderItem> itemWrapper = new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId()); |
| | | if (!Cools.isEmpty(matnrCode)) itemWrapper.eq(WkOrderItem::getMatnrCode, matnrCode); |
| | | if (!Cools.isEmpty(batch)) itemWrapper.eq(WkOrderItem::getSplrBatch, batch); |
| | | if (!Objects.isNull(fieldIndex)) itemWrapper.eq(WkOrderItem::getFieldsIndex, fieldIndex); |
| | | if (!Cools.isEmpty(code)) itemWrapper.eq(WkOrderItem::getTrackCode, code); |
| | | List<WkOrderItem> orderItems = asnOrderItemMapper.selectList(itemWrapper); |
| | | List<WarehouseAreasItem> list = new ArrayList<>(); |
| | | for (WkOrderItem oi : orderItems) { |
| | | Double anfme = QuantityUtils.roundToScale(oi.getAnfme() != null ? oi.getAnfme() : 0.0); |
| | | Double qty = QuantityUtils.roundToScale(oi.getQty() != null ? oi.getQty() : 0.0); |
| | | Double workQty = palletizedByItemId.getOrDefault(oi.getId(), 0.0); // 已组托数量 |
| | | if (QuantityUtils.compare(QuantityUtils.subtract(QuantityUtils.subtract(anfme, workQty), qty), 0.0) <= 0) continue; // 可组盘数量<=0 不返回 |
| | | WarehouseAreasItem v = new WarehouseAreasItem(); |
| | | v.setId(oi.getId()); |
| | | v.setAsnItemId(oi.getId()); |
| | | v.setAsnId(order.getId()); |
| | | v.setAsnCode(order.getCode()); |
| | | v.setAnfme(anfme); |
| | | v.setQty(qty); |
| | | v.setWorkQty(QuantityUtils.roundToScale(workQty)); |
| | | v.setMatnrCode(oi.getMatnrCode()); |
| | | v.setMaktx(oi.getMaktx()); |
| | | v.setSplrBatch(oi.getSplrBatch()); |
| | | v.setPlatItemId(oi.getPlatItemId()); |
| | | v.setStockUnit(oi.getStockUnit()); |
| | | v.setUnit(oi.getStockUnit()); |
| | | v.setMatnrId(oi.getMatnrId()); |
| | | v.setFieldsIndex(oi.getFieldsIndex()); |
| | | v.setTrackCode(oi.getTrackCode()); |
| | | if (oi.getFieldsIndex() != null) { |
| | | v.setExtendFields(FieldsUtils.getFields(oi.getFieldsIndex())); |
| | | } |
| | | list.add(v); |
| | | } |
| | | logger.info("=== 从订单明细查询可组托物料(收货区已停用)asnCode: {} 返回 {} 条", asnCode, list.size()); |
| | | return R.ok(list); |
| | | } |
| | | |
| | | // 如果同时有批次,则查询该ASN单号下的该批次 |
| | | if (!Cools.isEmpty(batch)) { |
| | | queryWrapper.eq(WarehouseAreasItem::getSplrBatch, batch); |
| | | } |
| | | |
| | | // 如果同时有票号,则查询该ASN单号下的该票号 |
| | | if (!Objects.isNull(fieldIndex)) { |
| | | queryWrapper.eq(WarehouseAreasItem::getFieldsIndex, fieldIndex); |
| | | } |
| | | |
| | | // 如果同时有跟踪码,则查询该ASN单号下的该跟踪码 |
| | | if (!Cools.isEmpty(code)) { |
| | | queryWrapper.eq(WarehouseAreasItem::getTrackCode, code); |
| | | } |
| | | } else { |
| | | // 无ASN单号时按其他条件查(收货区已停用,此处仅保留兼容,通常无数据) |
| | | LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<>(); |
| | | { |
| | | // 没有ASN单号时,可以扫描任意物料组托,使用OR连接多个条件 |
| | | // 统计有效条件数量 |
| | | int conditionCount = 0; |
| | |
| | | throw new CoolException("当前业务:" + SerialRuleCode.SYS_STOCK_CODE + ",编码规则不存在!!"); |
| | | } |
| | | List<WkOrderItem> itemList = params.getItemList(); |
| | | double sum = itemList.stream().mapToDouble(WkOrderItem::getAnfme).sum(); |
| | | Double sum = QuantityUtils.roundToScale(itemList.stream().mapToDouble(WkOrderItem::getAnfme).sum()); |
| | | stock.setAnfme(sum) |
| | | .setSourceId(order.getId()) |
| | | .setType(order.getType()) |
| | |
| | | @Override |
| | | public R getUnItemByContainer(Map<String, Object> params) { |
| | | if (Cools.isEmpty(params.get("barcode")) && Cools.isEmpty(params.get("code"))) { |
| | | throw new CoolException("容器号与组托档编码不能全为空"); |
| | | throw new CoolException("料箱码与组托档编码不能全为空"); |
| | | } |
| | | WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>() |
| | | .eq(!Cools.isEmpty(params.get("barcode")), WaitPakin::getBarcode, params.get("barcode")) |
| | | .eq(!Cools.isEmpty(params.get("code")), WaitPakin::getCode, params.get("code")) |
| | | .eq(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val)); |
| | | if (Objects.isNull(waitPakin)) { |
| | | return R.error("未找到该容器码的组托明细,请检查组托状态"); |
| | | return R.error("未找到该料箱码的组托明细,请检查组托状态"); |
| | | } |
| | | List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>() |
| | | .eq(WaitPakinItem::getPakinId, waitPakin.getId())); |
| | |
| | | .setMaktx(asnOrderItem.getMaktx()) |
| | | .setFieldsIndex(asnOrderItem.getFieldsIndex()) |
| | | .setBarcode(asnOrderItem.getTrackCode()) |
| | | .setQty(asnOrderItem.getQty()) |
| | | .setQty(QuantityUtils.roundToScale(asnOrderItem.getQty())) |
| | | .setStockUnit(asnOrderItem.getStockUnit()) |
| | | .setPurUnit(asnOrderItem.getPurUnit()) |
| | | .setPoCode(asnOrderItem.getPoCode()) |
| | | .setAnfme(asnOrderItem.getAnfme()) |
| | | .setAnfme(QuantityUtils.roundToScale(asnOrderItem.getAnfme())) |
| | | .setPurQty(asnOrderItem.getPurQty()) |
| | | .setSplrBatch(asnOrderItem.getSplrBatch()) |
| | | .setExtendFields(asnOrderItem.getExtendFields()) |
| | |
| | | if (Objects.isNull(stockItem)) { |
| | | detlsDto.setStockQty(0.0); |
| | | } else { |
| | | Double anfme = Math.round((stockItem.getAnfme() + stockItem.getWorkQty()) * 1000000) / 1000000.0; |
| | | Double anfme = QuantityUtils.add(stockItem.getAnfme(), stockItem.getWorkQty()); |
| | | detlsDto.setStockQty(anfme); |
| | | } |
| | | |
| | |
| | | lambdaQueryWrapper.eq(Task::getBarcode, barcode); |
| | | Task task = taskService.getOne(lambdaQueryWrapper); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | if (!task.getTaskStatus().equals(TaskStsType.AWAIT.id)) { |
| | | return R.error("任务状态不是等待确认"); |
| | |
| | | } |
| | | Task task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.getContainer())); |
| | | if (null == task) { |
| | | throw new CoolException("数据错误,未找到容器码对应盘点任务"); |
| | | throw new CoolException("数据错误,未找到料箱码对应盘点任务"); |
| | | } |
| | | for (CheckDiffItem ckDiffItem : params.getCheckDiffItems()) { |
| | | CheckDiffItem diffItem = new CheckDiffItem(); |
| | |
| | | lambdaQueryWrapper.eq(Task::getBarcode, barcode); |
| | | Task task = taskService.getOne(lambdaQueryWrapper); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | if (!task.getTaskStatus().equals(TaskStsType.AWAIT.id)) { |
| | | return R.error("任务状态不是等待确认"); |
| | | } |
| | | List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | if (Cools.isEmpty(taskItems)) { |
| | | throw new CoolException("未找到该容器码对应的任务明细"); |
| | | throw new CoolException("未找到该料箱码对应的任务明细"); |
| | | } |
| | | String sourceCode = taskItems.stream().findFirst().map(TaskItem::getSourceCode).orElse(null); |
| | | CheckDiff checkDiff = checkDiffService.getOne(new LambdaQueryWrapper<CheckDiff>().eq(CheckDiff::getOrderCode, sourceCode)); |
| | |
| | | lambdaQueryWrapper.eq(Task::getBarcode, barcode); |
| | | Task task = taskService.getOne(lambdaQueryWrapper); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | // 允许WAVE_SEED(199,等待确认/盘点中)和AWAIT(196,等待确认)两种状态 |
| | | if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id) |
| | |
| | | } |
| | | List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | if (Cools.isEmpty(taskItems)) { |
| | | throw new CoolException("未找到该容器码对应的任务明细"); |
| | | throw new CoolException("未找到该料箱码对应的任务明细"); |
| | | } |
| | | taskItems.forEach(taskItem -> { |
| | | if (!Objects.isNull(taskItem.getFieldsIndex())) { |
| | |
| | | lambdaQueryWrapper.eq(Task::getBarcode, barcode); |
| | | Task task = taskService.getOne(lambdaQueryWrapper); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | if (!task.getTaskStatus().equals(TaskStsType.AWAIT.id)) { |
| | | return R.error("任务状态不是等待确认"); |
| | |
| | | lambdaQueryWrapper.eq(Task::getBarcode, barcode); |
| | | Task task = taskService.getOne(lambdaQueryWrapper); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | // 允许WAVE_SEED(199,等待确认/盘点中)和AWAIT(196,等待确认)两种状态 |
| | | if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id) |
| | |
| | | .last("limit 1"); |
| | | Task task = taskService.getOne(lambdaQueryWrapper); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | // 允许 199(WAVE_SEED 播种中/待确认)或 196(AWAIT 等待确认),与盘点 PDA 逻辑一致 |
| | | if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id) |
| | |
| | | .orderByDesc(Task::getId) |
| | | .last("limit 1")); |
| | | if (null == task) { |
| | | throw new CoolException("未找到容器号对应任务"); |
| | | throw new CoolException("未找到料箱码对应任务"); |
| | | } |
| | | if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) { |
| | | return R.error("任务状态不是揀料狀態"); |
| | |
| | | // containerWaveDto.setTaskItem(taskItem); |
| | | // Wave wave = waveService.getById(taskItem.getSourceId()); |
| | | // if (null == wave) { |
| | | // throw new CoolException("未找到容器号对应波次"); |
| | | // throw new CoolException("未找到料箱码对应波次"); |
| | | // } |
| | | // List<WaveOrderRela> waveOrderRelas = waveOrderRelaService.list(new LambdaQueryWrapper<WaveOrderRela>() |
| | | // .eq(WaveOrderRela::getWaveId, wave.getId())); |
| | |
| | | return R.error("票号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(param.get("barcode"))) { |
| | | return R.error("容器号不能为空!!"); |
| | | return R.error("料箱码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(param.get("orderId"))) { |
| | | return R.error("订单ID不能为空!!"); |
| | |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | | import com.vincent.rsf.server.common.utils.FieldsUtils; |
| | | import com.vincent.rsf.server.common.utils.QuantityUtils; |
| | | import com.vincent.rsf.server.manager.controller.dto.LocStockDto; |
| | | import com.vincent.rsf.server.manager.entity.*; |
| | | import com.vincent.rsf.server.manager.enums.*; |
| | |
| | | @Autowired |
| | | private LocService locService; |
| | | @Autowired |
| | | private OrderWorkTypeService orderWorkTypeService; |
| | | @Autowired |
| | | private OrderTypeDictService orderTypeDictService; |
| | | @Autowired |
| | | private WarehouseAreasService warehouseAreasService; |
| | | @Autowired |
| | | private WarehouseService warehouseService; |
| | |
| | | private DictTypeService dictTypeService; |
| | | @Autowired |
| | | private LocItemService locItemService; |
| | | @Autowired |
| | | private WaitPakinItemService waitPakinItemService; |
| | | @Autowired |
| | | private WarehouseAreasItemService warehouseAreasItemService; |
| | | |
| | | |
| | | /** |
| | |
| | | public R syncCheckOrder(List<SyncOrderParams> syncOrders, Long loginUserId) { |
| | | if (!syncOrders.isEmpty()) { |
| | | syncOrders.forEach(syncOrder -> { |
| | | if (StringUtils.isBlank(syncOrder.getOrderInternalCode())) { |
| | | throw new CoolException("单据内码不能为空!!"); |
| | | } |
| | | // 明细 lineId(对应 platItemId)不能为空,且同一订单内不能重复 |
| | | if (syncOrder.getOrderItems() != null) { |
| | | Set<String> lineIds = new HashSet<>(); |
| | | for (SyncOrdersItem item : syncOrder.getOrderItems()) { |
| | | if (StringUtils.isBlank(item.getPlatItemId())) { |
| | | throw new CoolException("明细 lineId 不能为空!!"); |
| | | } |
| | | String lineId = item.getPlatItemId().trim(); |
| | | if (!lineIds.add(lineId)) { |
| | | throw new CoolException("同一订单内明细 lineId 不能重复:" + lineId); |
| | | } |
| | | } |
| | | } |
| | | WkOrder wkOrder = new WkOrder(); |
| | | DictData one = dictDataService.getOne(new LambdaQueryWrapper<DictData>().eq(DictData::getDictTypeCode, DictTypeCode.DICT_SYS_BUSINESS_TYPE) |
| | | .eq(DictData::getValue, syncOrder.getWkType()), false); |
| | | if (Objects.isNull(one)) { |
| | | // 兼容 wkType 传数字(类型码)或中文(显示名):先按 label 反查 type,否则按原值当 type |
| | | String wkTypeInput = syncOrder.getWkType(); |
| | | String typeCode = StringUtils.isBlank(wkTypeInput) ? null : orderWorkTypeService.getTypeByLabel(wkTypeInput); |
| | | if (typeCode == null) { |
| | | typeCode = wkTypeInput; |
| | | } |
| | | if (StringUtils.isBlank(typeCode) || orderWorkTypeService.getLabelByType(typeCode) == null) { |
| | | throw new CoolException("单据:" + syncOrder.getOrderNo() + ", 业务类型不存在!!"); |
| | | } |
| | | // 订单类型:支持数字 1/2/3、中文「出库单」/「入库单」/「调拨单」或内部码 out/in/transfer(来自字典) |
| | | String typeInput = syncOrder.getType(); |
| | | String resolvedOrderType = orderTypeDictService.resolveType(typeInput); |
| | | if (typeInput != null && !typeInput.trim().isEmpty() && resolvedOrderType == null) { |
| | | throw new CoolException("单据:" + syncOrder.getOrderNo() + ", 订单类型不存在!!"); |
| | | } |
| | | Loc serviceOne = null; |
| | | if (!Objects.isNull(syncOrder.getOrgLoc())) { |
| | |
| | | if (!Objects.isNull(serviceOne)) { |
| | | //TODO 添加调拔移库单功能 |
| | | } else { |
| | | // operateType=2 存在则修改、不存在则报错;operateType=1 存在则修改、不存在则新增 |
| | | WkOrder order = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(!Objects.isNull(syncOrder.getOrderId()), WkOrder::getPoId, syncOrder.getOrderId()) |
| | | .eq(WkOrder::getPoCode, syncOrder.getOrderNo())); |
| | | .eq(WkOrder::getPoCode, syncOrder.getOrderInternalCode())); |
| | | if (!Objects.isNull(order)) { |
| | | if (order.getExceStatus().equals(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val) || |
| | | order.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val)) { |
| | | /**删除单据明细*/ |
| | | asnOrderItemService.remove(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())); |
| | | /**删除主单*/ |
| | | asnOrderService.removeById(order.getId()); |
| | | } else { |
| | | throw new CoolException("单据已添加,不可执行修改或添加操作!!"); |
| | | // 仅未执行状态可被 order/add 修改(入库未执行、出库任务初始) |
| | | List<Short> editableStatus = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val, AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val); |
| | | if (!editableStatus.contains(order.getExceStatus())) { |
| | | throw new CoolException("仅未执行状态的单据可修改!!"); |
| | | } |
| | | // 存在则修改(1 和 2 均走此处),组托校验在 mergeOrderWithPakin/updateOrderNoPakin 内 |
| | | long pakinCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>() |
| | | .eq(WaitPakinItem::getAsnId, order.getId())); |
| | | if (pakinCount > 0) { |
| | | // 已组托:按 lineId(platItemId)合并,校验数量与删除 |
| | | mergeOrderWithPakin(order, syncOrder, resolvedOrderType, typeCode, loginUserId); |
| | | // 收货区已停用 // syncReceiptAreaByOrder(order.getId()); |
| | | return; // 本单已处理,跳过下方“新建主单+明细” |
| | | } |
| | | // 未组托:在原单上更新主单+明细,保留 exceStatus/qty/workQty,避免再次触发定时任务导致重复收货 |
| | | updateOrderNoPakin(order, syncOrder, loginUserId); |
| | | // 收货区已停用 // syncReceiptAreaByOrder(order.getId()); |
| | | return; |
| | | } else if (Integer.valueOf(2).equals(syncOrder.getOperateType())) { |
| | | // 仅 operateType=2 时要求单据必须存在 |
| | | throw new CoolException("单据不存在,无法修改!!"); |
| | | } |
| | | String rule = SerialRuleCode.SYS_ASN_ORDER; |
| | | if (syncOrder.getType().equals(OrderType.ORDER_OUT.type)) { |
| | | if (resolvedOrderType != null && resolvedOrderType.equals(OrderType.ORDER_OUT.type)) { |
| | | rule = SerialRuleCode.SYS_OUT_STOCK_CODE; |
| | | } |
| | | |
| | | String ruleCode = SerialRuleUtils.generateRuleCode(rule, null); |
| | | wkOrder.setType(syncOrder.getType()) |
| | | .setWkType(one.getValue()) |
| | | .setAnfme(syncOrder.getAnfme()) |
| | | .setPoCode(syncOrder.getOrderNo()) |
| | | // 有 orderNo 则直接作为 WMS 单号 code,否则按规则生成;po_code 存单据内码(orderInternalCode 已校验非空) |
| | | String wmsCode = StringUtils.isNotBlank(syncOrder.getOrderNo()) ? syncOrder.getOrderNo() : SerialRuleUtils.generateRuleCode(rule, null); |
| | | String poCodeVal = syncOrder.getOrderInternalCode(); |
| | | wkOrder.setType(resolvedOrderType != null ? resolvedOrderType : syncOrder.getType()) |
| | | .setWkType(typeCode) |
| | | .setAnfme(QuantityUtils.roundToScale(syncOrder.getAnfme())) |
| | | .setPoCode(poCodeVal) |
| | | .setWorkQty(0.0) |
| | | .setQty(0.0) |
| | | .setPoId(syncOrder.getOrderId()) |
| | | .setCode(ruleCode) |
| | | .setCode(wmsCode) |
| | | .setArrTime(syncOrder.getArrTime()) |
| | | .setStationId(syncOrder.getStationId()) |
| | | .setId(null) |
| | | .setCreateTime(new Date()) |
| | | .setUpdateTime(new Date()) |
| | | .setCreateBy(loginUserId) |
| | | .setUpdateBy(loginUserId); |
| | | |
| | | if (syncOrder.getType().equals(OrderType.ORDER_OUT.type)){ |
| | | if (resolvedOrderType != null && resolvedOrderType.equals(OrderType.ORDER_OUT.type)) { |
| | | wkOrder.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val); |
| | | } |
| | | |
| | |
| | | }); |
| | | List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>() |
| | | .eq(WkOrderItem::getOrderId, wkOrder.getId())); |
| | | double sum = orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum(); |
| | | Double sum = QuantityUtils.roundToScale(orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum()); |
| | | wkOrder.setAnfme(sum); |
| | | if (!asnOrderService.updateById(wkOrder)) { |
| | | throw new CoolException("计划收货数量修改失败!!"); |
| | |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * 已组托单据的修改合并:按 lineId(platItemId)匹配。 |
| | | * 规则:组托数量不会因改单而变;已组托 100 时,修改为 99 会报错,修改为 101 允许且多出的 1 可再组托。 |
| | | */ |
| | | private void mergeOrderWithPakin(WkOrder order, SyncOrderParams syncOrder, String resolvedOrderType, String typeCode, Long loginUserId) { |
| | | if (syncOrder.getOrderItems() != null) { |
| | | for (SyncOrdersItem it : syncOrder.getOrderItems()) { |
| | | if (StringUtils.isBlank(it.getPlatItemId())) { |
| | | throw new CoolException("明细 lineId 不能为空!!"); |
| | | } |
| | | } |
| | | } |
| | | List<WkOrderItem> existingItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())); |
| | | List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getAsnId, order.getId())); |
| | | Map<Long, Double> palletizedByItemId = pakinItems.stream() |
| | | .collect(Collectors.groupingBy(WaitPakinItem::getAsnItemId, Collectors.summingDouble(w -> w.getAnfme() != null ? w.getAnfme() : 0.0))); |
| | | palletizedByItemId.replaceAll((k, v) -> QuantityUtils.roundToScale(v)); |
| | | |
| | | Map<String, SyncOrdersItem> incomingByLineId = new HashMap<>(); |
| | | if (syncOrder.getOrderItems() != null) { |
| | | for (SyncOrdersItem it : syncOrder.getOrderItems()) { |
| | | incomingByLineId.put(it.getPlatItemId().trim(), it); |
| | | } |
| | | } |
| | | |
| | | Set<String> existingLineIds = existingItems.stream() |
| | | .map(e -> StringUtils.isNotBlank(e.getPlatItemId()) ? e.getPlatItemId().trim() : null) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | for (WkOrderItem existing : existingItems) { |
| | | String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null; |
| | | double palletized = palletizedByItemId.getOrDefault(existing.getId(), 0.0); |
| | | if (lineId == null || !incomingByLineId.containsKey(lineId)) { |
| | | if (palletized > 0) { |
| | | throw new CoolException("该明细已组托,需解除组托后才能删除!!"); |
| | | } |
| | | } else { |
| | | SyncOrdersItem inc = incomingByLineId.get(lineId); |
| | | Double newAnfme = QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : 0.0); |
| | | // 已组托数量不变:改小(如 100 改为 99)报错;改大(如 100 改为 101)允许,多出的可再组托 |
| | | if (QuantityUtils.compare(newAnfme, palletized) < 0) { |
| | | throw new CoolException("该明细数量不能小于已组托数量(已组托 " + palletized + "),需解除组托后才能修改!!"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | order.setAnfme(QuantityUtils.roundToScale(syncOrder.getAnfme() != null ? syncOrder.getAnfme() : 0.0)); |
| | | if (syncOrder.getArrTime() != null) { |
| | | order.setArrTime(syncOrder.getArrTime()); |
| | | } |
| | | if (StringUtils.isNotBlank(syncOrder.getStationId())) { |
| | | order.setStationId(syncOrder.getStationId()); |
| | | } |
| | | order.setUpdateBy(loginUserId); |
| | | order.setUpdateTime(new Date()); |
| | | asnOrderService.updateById(order); |
| | | |
| | | for (WkOrderItem existing : existingItems) { |
| | | String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null; |
| | | if (lineId == null || !incomingByLineId.containsKey(lineId)) { |
| | | asnOrderItemService.removeById(existing.getId()); |
| | | continue; |
| | | } |
| | | SyncOrdersItem inc = incomingByLineId.get(lineId); |
| | | existing.setAnfme(QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme())); |
| | | existing.setMaktx(inc.getMaktx()); |
| | | existing.setSpec(inc.getSpec()); |
| | | existing.setModel(inc.getModel()); |
| | | existing.setStockUnit(inc.getUnit()); |
| | | existing.setBatch(inc.getBatch()); |
| | | existing.setPlanNo(inc.getPlanNo()); |
| | | existing.setPalletId(inc.getPalletId()); |
| | | existing.setUpdateBy(loginUserId); |
| | | existing.setUpdateTime(new Date()); |
| | | asnOrderItemService.updateById(existing); |
| | | } |
| | | |
| | | for (Map.Entry<String, SyncOrdersItem> e : incomingByLineId.entrySet()) { |
| | | String key = e.getKey(); |
| | | if (!existingLineIds.contains(key)) { |
| | | Map<String, Object> map = new ObjectMapper().convertValue(e.getValue(), Map.class); |
| | | map.put("orderId", order.getId()); |
| | | map.put("poId", order.getPoId()); |
| | | map.put("poCode", order.getPoCode()); |
| | | map.put("order_code", order.getCode()); |
| | | map.put("matnrCode", e.getValue().getMatnr()); |
| | | map.put("platItemId", key); |
| | | if (!asnOrderItemService.fieldsSave(map, loginUserId)) { |
| | | throw new CoolException("明细保存失败!!"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Double sum = QuantityUtils.roundToScale(asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())) |
| | | .stream().mapToDouble(WkOrderItem::getAnfme).sum()); |
| | | order.setAnfme(sum); |
| | | asnOrderService.updateById(order); |
| | | } |
| | | |
| | | /** |
| | | * 未组托单据的修改:在原单上更新主单+明细(按 lineId 匹配),保留 exceStatus、qty、workQty,避免删单重建导致定时任务再次执行。 |
| | | */ |
| | | private void updateOrderNoPakin(WkOrder order, SyncOrderParams syncOrder, Long loginUserId) { |
| | | if (syncOrder.getOrderItems() == null || syncOrder.getOrderItems().isEmpty()) { |
| | | throw new CoolException("修改时明细不能为空!!"); |
| | | } |
| | | Map<String, SyncOrdersItem> incomingByLineId = new HashMap<>(); |
| | | for (SyncOrdersItem it : syncOrder.getOrderItems()) { |
| | | if (StringUtils.isBlank(it.getPlatItemId())) { |
| | | throw new CoolException("明细 lineId 不能为空!!"); |
| | | } |
| | | incomingByLineId.put(it.getPlatItemId().trim(), it); |
| | | } |
| | | List<WkOrderItem> existingItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())); |
| | | Set<String> existingLineIds = existingItems.stream() |
| | | .map(e -> StringUtils.isNotBlank(e.getPlatItemId()) ? e.getPlatItemId().trim() : null) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | order.setAnfme(QuantityUtils.roundToScale(syncOrder.getAnfme() != null ? syncOrder.getAnfme() : 0.0)); |
| | | if (syncOrder.getArrTime() != null) { |
| | | order.setArrTime(syncOrder.getArrTime()); |
| | | } |
| | | if (StringUtils.isNotBlank(syncOrder.getStationId())) { |
| | | order.setStationId(syncOrder.getStationId()); |
| | | } |
| | | order.setUpdateBy(loginUserId); |
| | | order.setUpdateTime(new Date()); |
| | | asnOrderService.updateById(order); |
| | | |
| | | for (WkOrderItem existing : existingItems) { |
| | | String lineId = StringUtils.isNotBlank(existing.getPlatItemId()) ? existing.getPlatItemId().trim() : null; |
| | | if (lineId == null || !incomingByLineId.containsKey(lineId)) { |
| | | // 收货区已停用 // warehouseAreasItemService.remove(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnItemId, existing.getId())); |
| | | asnOrderItemService.removeById(existing.getId()); |
| | | continue; |
| | | } |
| | | SyncOrdersItem inc = incomingByLineId.get(lineId); |
| | | existing.setAnfme(QuantityUtils.roundToScale(inc.getAnfme() != null ? inc.getAnfme() : existing.getAnfme())); |
| | | existing.setMaktx(inc.getMaktx()); |
| | | existing.setSpec(inc.getSpec()); |
| | | existing.setModel(inc.getModel()); |
| | | existing.setStockUnit(inc.getUnit()); |
| | | existing.setBatch(inc.getBatch()); |
| | | existing.setPlanNo(inc.getPlanNo()); |
| | | existing.setPalletId(inc.getPalletId()); |
| | | existing.setUpdateBy(loginUserId); |
| | | existing.setUpdateTime(new Date()); |
| | | asnOrderItemService.updateById(existing); |
| | | } |
| | | |
| | | for (Map.Entry<String, SyncOrdersItem> e : incomingByLineId.entrySet()) { |
| | | if (existingLineIds.contains(e.getKey())) { |
| | | continue; |
| | | } |
| | | Map<String, Object> map = new ObjectMapper().convertValue(e.getValue(), Map.class); |
| | | map.put("orderId", order.getId()); |
| | | map.put("poId", order.getPoId()); |
| | | map.put("poCode", order.getPoCode()); |
| | | map.put("order_code", order.getCode()); |
| | | map.put("matnrCode", e.getValue().getMatnr()); |
| | | map.put("platItemId", e.getKey()); |
| | | if (!asnOrderItemService.fieldsSave(map, loginUserId)) { |
| | | throw new CoolException("明细保存失败!!"); |
| | | } |
| | | } |
| | | |
| | | Double sum = QuantityUtils.roundToScale(asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())) |
| | | .stream().mapToDouble(WkOrderItem::getAnfme).sum()); |
| | | order.setAnfme(sum); |
| | | asnOrderService.updateById(order); |
| | | } |
| | | |
| | | /** 收货区已停用,方法整体注释 |
| | | * 订单修改后同步收货区:按 asnItemId 将收货区记录的 anfme 更新为订单明细的 anfme。 |
| | | */ |
| | | // private void syncReceiptAreaByOrder(Long orderId) { |
| | | // List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, orderId)); |
| | | // if (orderItems.isEmpty()) { |
| | | // return; |
| | | // } |
| | | // List<WarehouseAreasItem> areaItems = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getAsnId, orderId)); |
| | | // Map<Long, Double> itemAnfme = orderItems.stream().collect(Collectors.toMap(WkOrderItem::getId, i -> i.getAnfme() != null ? i.getAnfme() : 0.0, (a, b) -> b)); |
| | | // for (WarehouseAreasItem area : areaItems) { |
| | | // if (area.getAsnItemId() == null || !itemAnfme.containsKey(area.getAsnItemId())) { |
| | | // continue; |
| | | // } |
| | | // Double anfme = itemAnfme.get(area.getAsnItemId()); |
| | | // if (area.getAnfme() != null && area.getAnfme().equals(anfme)) { |
| | | // continue; |
| | | // } |
| | | // area.setAnfme(anfme); |
| | | // warehouseAreasItemService.updateById(area); |
| | | // } |
| | | // } |
| | | |
| | | /** |
| | | * @author Ryan |
| | |
| | | .eq(WkOrderItem::getMatnrCode, orderItem.getMatnr()) |
| | | .eq(StringUtils.isNotEmpty(orderItem.getBatch()), WkOrderItem::getSplrBatch, orderItem.getBatch()) |
| | | .eq(StringUtils.isNotEmpty(orderItem.getPlatItemId()), WkOrderItem::getPlatItemId, orderItem.getPlatItemId()) |
| | | .set(WkOrderItem::getAnfme, orderItem.getAnfme()))) { |
| | | .set(WkOrderItem::getAnfme, QuantityUtils.roundToScale(orderItem.getAnfme())))) { |
| | | throw new CoolException("单据修改失败!!"); |
| | | } |
| | | } else { |
| | |
| | | } |
| | | } |
| | | }); |
| | | wkOrder.setAnfme(order.getAnfme()); |
| | | wkOrder.setAnfme(QuantityUtils.roundToScale(order.getAnfme())); |
| | | if (!asnOrderService.updateById(wkOrder)) { |
| | | throw new CoolException("主单据修改失败!!"); |
| | | } |
| | |
| | | @Transactional(timeout = 60, rollbackFor = Exception.class) |
| | | public R syncOrderDelete(List<SyncOrderParams> orders) { |
| | | orders.forEach(order -> { |
| | | // operateType=3:存在则判断是否可以取消;主要校验单据内码(orderInternalCode),orderNo 查到 1 条继续,查到多条则报错强调使用 orderInternalCode |
| | | WkOrder wkOrder = null; |
| | | if (StringUtils.isNotEmpty(order.getOrderInternalCode())) { |
| | | wkOrder = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(WkOrder::getPoCode, order.getOrderInternalCode())); |
| | | } |
| | | if (wkOrder == null && StringUtils.isNotEmpty(order.getOrderNo())) { |
| | | List<WkOrder> list = asnOrderService.list(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(WkOrder::getCode, order.getOrderNo())); |
| | | if (list.isEmpty()) { |
| | | throw new CoolException("单据不存在,无法取消!!"); |
| | | } |
| | | if (list.size() > 1) { |
| | | throw new CoolException("单号对应多条单据,请使用单据内码(orderInternalCode)唯一指定后再取消!!"); |
| | | } |
| | | wkOrder = list.get(0); |
| | | } |
| | | if (wkOrder == null) { |
| | | throw new CoolException("单据不存在,无法取消!!请提供单据内码(orderInternalCode)或单号(orderNo)。"); |
| | | } |
| | | final WkOrder finalWkOrder = wkOrder; |
| | | // 已组托不可取消 |
| | | long pakinCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>() |
| | | .eq(WaitPakinItem::getAsnId, finalWkOrder.getId())); |
| | | if (pakinCount > 0) { |
| | | throw new CoolException("单据已组托,仅未组托状态可取消,请先解除组托!!"); |
| | | } |
| | | // 仅未执行状态可取消(入库未执行、出库任务初始) |
| | | List<Short> list = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val, |
| | | AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val); |
| | | WkOrder wkOrder = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>() |
| | | .in(WkOrder::getExceStatus, list) |
| | | .eq(WkOrder::getCode, order.getOrderNo())); |
| | | if (Objects.isNull(wkOrder)) { |
| | | throw new CoolException("订单:" + wkOrder.getCode() + ",当前状态,不可执行删除操作!!"); |
| | | if (!list.contains(finalWkOrder.getExceStatus())) { |
| | | throw new CoolException("仅未执行状态的单据可取消!!"); |
| | | } |
| | | order.getOrderItems().forEach(orderItem -> { |
| | | if (!asnOrderItemService.remove(new LambdaQueryWrapper<WkOrderItem>() |
| | | .eq(WkOrderItem::getMatnrCode, orderItem.getMatnr()) |
| | | .eq(StringUtils.isNotEmpty(orderItem.getBatch()), WkOrderItem::getSplrBatch, orderItem.getBatch()) |
| | | .eq(StringUtils.isNotEmpty(orderItem.getPlatItemId()), WkOrderItem::getPlatItemId, orderItem.getPlatItemId()) |
| | | .eq(WkOrderItem::getOrderCode, wkOrder.getCode()))) { |
| | | .eq(WkOrderItem::getOrderCode, finalWkOrder.getCode()))) { |
| | | throw new CoolException("单据明细删除失败!!"); |
| | | } |
| | | List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, wkOrder.getId())); |
| | | List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, finalWkOrder.getId())); |
| | | if (orderItems.isEmpty()) { |
| | | if (!asnOrderService.removeById(wkOrder.getId())) { |
| | | if (!asnOrderService.removeById(finalWkOrder.getId())) { |
| | | throw new CoolException("单据删除失败!!"); |
| | | } |
| | | } else { |
| | | Double sum = orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum(); |
| | | Double sum = QuantityUtils.roundToScale(orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum()); |
| | | if (!asnOrderService.update(new LambdaUpdateWrapper<WkOrder>() |
| | | .eq(WkOrder::getId, wkOrder.getId()) |
| | | .eq(WkOrder::getId, finalWkOrder.getId()) |
| | | .set(WkOrder::getAnfme, sum))) { |
| | | throw new CoolException("主单数量修改失败!!"); |
| | | } |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | |
| | | throw new CoolException("任务状态修改失败!!当前任务状态:" + task.getTaskStatus() + ",目标状态:" + TaskStsType.COMPLETE_IN.id); |
| | | } |
| | | log.info("入库任务状态更新成功 - 任务编码:{}", task.getTaskCode()); |
| | | // 入库完整闭环由定时任务完成:TaskSchedules.completeInStock 扫描 COMPLETE_IN,执行库位/组托/上报云仓 |
| | | } |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type) |
| | | || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type) |
| | |
| | | throw new CoolException("任务状态修改失败!!当前任务状态:" + task.getTaskStatus() + ",目标状态:" + TaskStsType.COMPLETE_OUT.id); |
| | | } |
| | | log.info("出库任务状态更新成功 - 任务编码:{}", task.getTaskCode()); |
| | | |
| | | // 全版出库在RCS回调后处理库存并设置为199,等待PDA快速拣货确认后更新为200 |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) { |
| | | log.info("全版出库任务,开始处理库存并更新状态为199 - 任务编码:{}", task.getTaskCode()); |
| | | try { |
| | | // 重新查询任务以获取最新状态(198) |
| | | task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, task.getTaskCode())); |
| | | |
| | | // 调用completeTask处理库存(会设置为199) |
| | | List<Task> taskList = new ArrayList<>(); |
| | | taskList.add(task); |
| | | taskService.completeTask(taskList); |
| | | |
| | | // 重新查询任务以获取最新状态(199) |
| | | task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, task.getTaskCode())); |
| | | |
| | | if (task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) { |
| | | log.info("全版出库任务状态已更新为199(等待PDA快速拣货确认后更新为200) - 任务编码:{}", task.getTaskCode()); |
| | | } else { |
| | | log.warn("全版出库任务状态更新为199失败 - 任务编码:{},当前状态:{}", |
| | | task.getTaskCode(), task.getTaskStatus()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("全版出库任务处理失败 - 任务编码:{},错误:{}", task.getTaskCode(), e.getMessage(), e); |
| | | // 不抛出异常,避免影响RCS回调的正常返回 |
| | | } |
| | | } |
| | | // 出库完整闭环(库存、出库单、9.1 上报云仓)由定时任务 TaskSchedules.complateOutStock 统一执行 |
| | | } |
| | | } |
| | | } else { |
| New file |
| | |
| | | package com.vincent.rsf.server.common.event; |
| | | |
| | | import org.springframework.context.ApplicationEvent; |
| | | |
| | | /** |
| | | * 字典数据变更事件,用于通知依赖该字典的缓存刷新(如订单业务类型)。 |
| | | */ |
| | | public class DictDataChangedEvent extends ApplicationEvent { |
| | | |
| | | private final String dictTypeCode; |
| | | |
| | | public DictDataChangedEvent(Object source, String dictTypeCode) { |
| | | super(source); |
| | | this.dictTypeCode = dictTypeCode; |
| | | } |
| | | |
| | | public String getDictTypeCode() { |
| | | return dictTypeCode; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 统一舍入到 6 位小数后转 Double(用于存库/展示,避免浮点尾差) |
| | | * 乘法:a * b,结果保留 6 位小数转 Double |
| | | */ |
| | | public static Double multiply(Double a, Double b) { |
| | | return toBigDecimal(a).multiply(toBigDecimal(b)).setScale(SCALE, ROUNDING).doubleValue(); |
| | | } |
| | | |
| | | /** |
| | | * 除法:a / b,结果保留 6 位小数转 Double(b=0 时返回 0) |
| | | */ |
| | | public static Double divide(Double a, Double b) { |
| | | if (b == null || toBigDecimal(b).compareTo(BigDecimal.ZERO) == 0) { |
| | | return 0.0; |
| | | } |
| | | return toBigDecimal(a).divide(toBigDecimal(b), SCALE, ROUNDING).doubleValue(); |
| | | } |
| | | |
| | | /** |
| | | * 统一舍入到 6 位小数后转 Double(用于存库/展示、入参校验,避免浮点尾差)。 |
| | | * 所有 Double 写入实体或参与比较前建议经此方法或 add/subtract 做精度控制。 |
| | | */ |
| | | public static Double roundToScale(Double v) { |
| | | if (v == null) { |
| | |
| | | @PostMapping("/waitPakin/page") |
| | | public R page(@RequestBody Map<String, Object> map) { |
| | | BaseParam baseParam = buildParam(map, BaseParam.class); |
| | | // 单据组托按单号查询:单号在明细表 asn_code,从 map 取出并移除,避免主表无此字段报错 |
| | | String asnCode = null; |
| | | if (baseParam.getMap() != null && baseParam.getMap().containsKey("asnCode")) { |
| | | Object v = baseParam.getMap().get("asnCode"); |
| | | if (v != null && StringUtils.isNotBlank(v.toString())) { |
| | | asnCode = v.toString().trim(); |
| | | } |
| | | baseParam.getMap().remove("asnCode"); |
| | | } |
| | | PageParam<WaitPakin, BaseParam> pageParam = new PageParam<>(baseParam, WaitPakin.class); |
| | | return R.ok().add(waitPakinService.page(pageParam, pageParam.buildWrapper(true))); |
| | | com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<WaitPakin> qw = pageParam.buildWrapper(true); |
| | | if (StringUtils.isNotBlank(asnCode)) { |
| | | List<Long> pakinIds = waitPakinItemService.list( |
| | | new LambdaQueryWrapper<WaitPakinItem>() |
| | | .select(WaitPakinItem::getPakinId) |
| | | .like(WaitPakinItem::getAsnCode, asnCode)) |
| | | .stream().map(WaitPakinItem::getPakinId).distinct().collect(Collectors.toList()); |
| | | if (pakinIds.isEmpty()) { |
| | | qw.and(w -> w.apply("1 = 0")); |
| | | } else { |
| | | qw.in("id", pakinIds); |
| | | } |
| | | } |
| | | Page<WaitPakin> page = waitPakinService.page(pageParam, qw); |
| | | fillAsnCodes(page.getRecords()); |
| | | return R.ok().add(page); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakin:list')") |
| | | @PostMapping("/waitPakin/list") |
| | | public R list(@RequestBody Map<String, Object> map) { |
| | | return R.ok().add(waitPakinService.list()); |
| | | List<WaitPakin> list = waitPakinService.list(); |
| | | fillAsnCodes(list); |
| | | return R.ok().add(list); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakin:list')") |
| | | @PostMapping({"/waitPakin/many/{ids}", "/waitPakins/many/{ids}"}) |
| | | public R many(@PathVariable Long[] ids) { |
| | | return R.ok().add(waitPakinService.listByIds(Arrays.asList(ids))); |
| | | List<WaitPakin> list = waitPakinService.listByIds(Arrays.asList(ids)); |
| | | fillAsnCodes(list); |
| | | return R.ok().add(list); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakin:list')") |
| | | @GetMapping("/waitPakin/{id}") |
| | | public R get(@PathVariable("id") Long id) { |
| | | return R.ok().add(waitPakinService.getById(id)); |
| | | WaitPakin one = waitPakinService.getById(id); |
| | | if (one != null) { |
| | | fillAsnCodes(Collections.singletonList(one)); |
| | | } |
| | | return R.ok().add(one); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakin:save')") |
| | |
| | | @PreAuthorize("hasAuthority('manager:waitPakin:list')") |
| | | @PostMapping("/waitPakin/export") |
| | | public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception { |
| | | ExcelUtil.build(ExcelUtil.create(waitPakinService.list(), WaitPakin.class), response); |
| | | List<WaitPakin> list = waitPakinService.list(); |
| | | fillAsnCodes(list); |
| | | ExcelUtil.build(ExcelUtil.create(list, WaitPakin.class), response); |
| | | } |
| | | |
| | | |
| | |
| | | return taskService.generateTasks(taskParams, getLoginUserId()); |
| | | } |
| | | |
| | | /** |
| | | * 根据组托明细填充主档的关联入库通知单号(asnCodes),多个单号逗号分隔 |
| | | */ |
| | | private void fillAsnCodes(List<WaitPakin> list) { |
| | | if (list == null || list.isEmpty()) { |
| | | return; |
| | | } |
| | | List<Long> pakinIds = list.stream().map(WaitPakin::getId).collect(Collectors.toList()); |
| | | List<WaitPakinItem> items = waitPakinItemService.list( |
| | | new LambdaQueryWrapper<WaitPakinItem>() |
| | | .in(WaitPakinItem::getPakinId, pakinIds) |
| | | .select(WaitPakinItem::getPakinId, WaitPakinItem::getAsnCode)); |
| | | Map<Long, String> asnCodesByPakinId = pakinIds.stream().collect(Collectors.toMap( |
| | | pid -> pid, |
| | | pid -> items.stream() |
| | | .filter(i -> pid.equals(i.getPakinId()) && i.getAsnCode() != null && !i.getAsnCode().trim().isEmpty()) |
| | | .map(WaitPakinItem::getAsnCode) |
| | | .distinct() |
| | | .collect(Collectors.joining(",")))); |
| | | for (WaitPakin p : list) { |
| | | p.setAsnCodes(asnCodesByPakinId.get(p.getId())); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.KeyValVo; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | | import com.vincent.rsf.server.manager.entity.WaitPakinItemLog; |
| | | import com.vincent.rsf.server.manager.entity.WaitPakinLog; |
| | | import com.vincent.rsf.server.manager.service.WaitPakinItemLogService; |
| | | import com.vincent.rsf.server.manager.service.WaitPakinLogService; |
| | | import com.vincent.rsf.server.system.controller.BaseController; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @RestController |
| | | public class WaitPakinLogController extends BaseController { |
| | | |
| | | @Autowired |
| | | private WaitPakinLogService waitPakinLogService; |
| | | @Autowired |
| | | private WaitPakinItemLogService waitPakinItemLogService; |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakinLog:list')") |
| | | @PostMapping("/waitPakinLog/page") |
| | | public R page(@RequestBody Map<String, Object> map) { |
| | | BaseParam baseParam = buildParam(map, BaseParam.class); |
| | | PageParam<WaitPakinLog, BaseParam> pageParam = new PageParam<>(baseParam, WaitPakinLog.class); |
| | | return R.ok().add(waitPakinLogService.page(pageParam, pageParam.buildWrapper(true))); |
| | | Page<WaitPakinLog> page = waitPakinLogService.page(pageParam, pageParam.buildWrapper(true)); |
| | | fillAsnCodesForLog(page.getRecords()); |
| | | return R.ok().add(page); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakinLog:list')") |
| | | @PostMapping("/waitPakinLog/list") |
| | | public R list(@RequestBody Map<String, Object> map) { |
| | | return R.ok().add(waitPakinLogService.list()); |
| | | List<WaitPakinLog> list = waitPakinLogService.list(); |
| | | fillAsnCodesForLog(list); |
| | | return R.ok().add(list); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakinLog:list')") |
| | | @PostMapping({"/waitPakinLog/many/{ids}", "/waitPakinLogs/many/{ids}"}) |
| | | public R many(@PathVariable Long[] ids) { |
| | | return R.ok().add(waitPakinLogService.listByIds(Arrays.asList(ids))); |
| | | List<WaitPakinLog> list = waitPakinLogService.listByIds(Arrays.asList(ids)); |
| | | fillAsnCodesForLog(list); |
| | | return R.ok().add(list); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakinLog:list')") |
| | | @GetMapping("/waitPakinLog/{id}") |
| | | public R get(@PathVariable("id") Long id) { |
| | | return R.ok().add(waitPakinLogService.getById(id)); |
| | | WaitPakinLog one = waitPakinLogService.getById(id); |
| | | if (one != null) { |
| | | fillAsnCodesForLog(Collections.singletonList(one)); |
| | | } |
| | | return R.ok().add(one); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:waitPakinLog:save')") |
| | |
| | | @PreAuthorize("hasAuthority('manager:waitPakinLog:list')") |
| | | @PostMapping("/waitPakinLog/export") |
| | | public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception { |
| | | ExcelUtil.build(ExcelUtil.create(waitPakinLogService.list(), WaitPakinLog.class), response); |
| | | List<WaitPakinLog> list = waitPakinLogService.list(); |
| | | fillAsnCodesForLog(list); |
| | | ExcelUtil.build(ExcelUtil.create(list, WaitPakinLog.class), response); |
| | | } |
| | | |
| | | /** |
| | | * 根据组托历史明细填充主档的关联入库通知单号(asnCodes),与组托通知档保持一致 |
| | | */ |
| | | private void fillAsnCodesForLog(List<WaitPakinLog> list) { |
| | | if (list == null || list.isEmpty()) { |
| | | return; |
| | | } |
| | | List<Long> logIds = list.stream().map(WaitPakinLog::getId).collect(Collectors.toList()); |
| | | List<WaitPakinItemLog> items = waitPakinItemLogService.list( |
| | | new LambdaQueryWrapper<WaitPakinItemLog>() |
| | | .in(WaitPakinItemLog::getLogId, logIds) |
| | | .select(WaitPakinItemLog::getLogId, WaitPakinItemLog::getAsnCode)); |
| | | Map<Long, String> asnCodesByLogId = logIds.stream().collect(Collectors.toMap( |
| | | logId -> logId, |
| | | logId -> items.stream() |
| | | .filter(i -> logId.equals(i.getLogId()) && i.getAsnCode() != null && !i.getAsnCode().trim().isEmpty()) |
| | | .map(WaitPakinItemLog::getAsnCode) |
| | | .distinct() |
| | | .collect(Collectors.joining(",")))); |
| | | for (WaitPakinLog p : list) { |
| | | p.setAsnCodes(asnCodesByLogId.get(p.getId())); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * PO单号 |
| | | * 单据内码 |
| | | */ |
| | | @ApiModelProperty(value= "PO单号") |
| | | @ApiModelProperty(value= "单据内码") |
| | | private String poCode; |
| | | |
| | | /** |
| | |
| | | |
| | | // AsnOrderLog asnOrderLog = new AsnOrderLog( |
| | | // null, // 编号 |
| | | // null, // PO单号 |
| | | // null, // 单据内码 |
| | | // null, // PO单据标识 |
| | | // null, // 单据类型[非空] |
| | | // null, // 业务类型[非空] |
| | |
| | | private Long containerType; |
| | | |
| | | /** |
| | | * 容器条码类型 |
| | | * 料箱条码类型 |
| | | */ |
| | | @ApiModelProperty(value= "容器条码类型") |
| | | @ApiModelProperty(value= "料箱条码类型") |
| | | private String codeType; |
| | | |
| | | @ApiModelProperty("是否满箱") |
| | |
| | | |
| | | // BasContainer basContainer = new BasContainer( |
| | | // null, // 容器类型 |
| | | // null, // 容器条码类型 |
| | | // null, // 料箱条码类型 |
| | | // null, // 可入库区 |
| | | // null, // 是否删除 |
| | | // null, // 状态 |
| | |
| | | private Integer type; |
| | | |
| | | /** |
| | | * 容器码 |
| | | * 料箱码 |
| | | */ |
| | | @ApiModelProperty(value= "容器码") |
| | | @ApiModelProperty(value= "料箱码") |
| | | private String barcode; |
| | | |
| | | /** |
| | |
| | | // null, // 仓库ID |
| | | // null, // 库区ID |
| | | // null, // 类型 |
| | | // null, // 容器码 |
| | | // null, // 料箱码 |
| | | // null, // 库位状态 |
| | | // null, // 巷道 |
| | | // null, // 排 |
| | |
| | | @ApiModelProperty(value= "添加人员") |
| | | private Long createBy; |
| | | |
| | | /**现品票号*/ |
| | | /** 现品票号(已废弃,无此概念) */ |
| | | @TableField(exist = false) |
| | | private String crushNo; |
| | | |
| | |
| | | import java.util.Date; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * 容器码 |
| | | * 料箱码 |
| | | */ |
| | | @ApiModelProperty(value= "容器码") |
| | | @ApiModelProperty(value= "料箱码") |
| | | private String barcode; |
| | | |
| | | /** |
| | |
| | | @ApiModelProperty(value= "备注") |
| | | private String memo; |
| | | |
| | | /** |
| | | * 关联的入库通知单号(多个用逗号分隔),仅查询展示用,不落库 |
| | | */ |
| | | @ApiModelProperty(value = "关联的入库通知单号,多个用逗号分隔") |
| | | @TableField(exist = false) |
| | | private String asnCodes; |
| | | |
| | | public WaitPakin() {} |
| | | |
| | | public WaitPakin(String code,String barcode,Double anfme,Short ioStatus,Integer status,Integer deleted,Integer tenantId,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) { |
| | |
| | | // null, // 编码 |
| | | // null, // 订单ID |
| | | // null, // 订单编码 |
| | | // null, // 容器码 |
| | | // null, // 料箱码 |
| | | // null, // 组拖数量 |
| | | // null, // 组拖状态 |
| | | // null, // 状态[非空] |
| | |
| | | import java.util.Date; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * 容器码 |
| | | * 料箱码 |
| | | */ |
| | | @ApiModelProperty(value= "容器码") |
| | | @ApiModelProperty(value= "料箱码") |
| | | private String barcode; |
| | | |
| | | /** |
| | |
| | | */ |
| | | @ApiModelProperty(value= "组拖状态 0: 待入库 1: 入库中 ") |
| | | private Short ioStatus; |
| | | |
| | | /** |
| | | * 关联的入库通知单号(多个用逗号分隔),仅查询展示用,不落库 |
| | | */ |
| | | @ApiModelProperty(value = "关联的入库通知单号,多个用逗号分隔") |
| | | @TableField(exist = false) |
| | | private String asnCodes; |
| | | |
| | | /** |
| | | * 状态 1: 正常 0: 冻结 |
| | |
| | | // WaitPakinLog waitPakinLog = new WaitPakinLog( |
| | | // null, // 主单ID |
| | | // null, // 编码 |
| | | // null, // 容器码 |
| | | // null, // 料箱码 |
| | | // null, // 组拖数量 |
| | | // null, // 组拖状态[非空] |
| | | // null, // 状态[非空] |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * PO单号 |
| | | * 单据内码 |
| | | */ |
| | | @ApiModelProperty(value = "PO单号") |
| | | @ApiModelProperty(value = "单据内码") |
| | | private String poCode; |
| | | |
| | | /** |
| | |
| | | @ApiModelProperty(value = "PO单据标识") |
| | | private Long poId; |
| | | |
| | | /** 入/出库接驳站点(8.3 stationId) */ |
| | | @ApiModelProperty(value = "接驳站点") |
| | | @com.baomidou.mybatisplus.annotation.TableField("station_id") |
| | | private String stationId; |
| | | |
| | | /** |
| | | * 单据类型 |
| | | */ |
| | |
| | | */ |
| | | @ApiModelProperty("库存批次") |
| | | private String batch; |
| | | |
| | | @ApiModelProperty("计划跟踪号(8.3 planNo)") |
| | | @com.baomidou.mybatisplus.annotation.TableField("plan_no") |
| | | private String planNo; |
| | | |
| | | @ApiModelProperty("托盘码(8.3 palletId)") |
| | | @com.baomidou.mybatisplus.annotation.TableField("pallet_id") |
| | | private String palletId; |
| | | |
| | | @ApiModelProperty("建议入库仓库(8.3 targetWareHouseId)") |
| | | @com.baomidou.mybatisplus.annotation.TableField("target_ware_house_id") |
| | | private String targetWareHouseId; |
| | | |
| | | @ApiModelProperty("建议出库仓库(8.3 sourceWareHouseId)") |
| | | @com.baomidou.mybatisplus.annotation.TableField("source_ware_house_id") |
| | | private String sourceWareHouseId; |
| | | |
| | | /** |
| | | * 采购单位 |
| | | */ |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * PO单号 |
| | | * 单据内码 |
| | | */ |
| | | @Excel(name = "PO单号") |
| | | @ApiModelProperty(value = "PO单号") |
| | | @Excel(name = "单据内码") |
| | | @ApiModelProperty(value = "单据内码") |
| | | @ExcelComment(value = "poCode", example = "PO59755695") |
| | | private String poCode; |
| | | |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * PO单号 |
| | | * 单据内码 |
| | | */ |
| | | @Excel(name = "DO单号") |
| | | @ApiModelProperty(value = "DO单号") |
| | |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Excel(name = "*PO单号") |
| | | @ApiModelProperty(value= "*PO单号") |
| | | @Excel(name = "*单据内码") |
| | | @ApiModelProperty(value= "*单据内码") |
| | | @ExcelComment(value = "poCode", example = "PO25413975") |
| | | private String poCode; |
| | | |
| | |
| | | private String code; |
| | | |
| | | /** |
| | | * PO单号 |
| | | * 单据内码 |
| | | */ |
| | | @Excel(name = "PO单号") |
| | | @ApiModelProperty(value = "PO单号") |
| | | @Excel(name = "单据内码") |
| | | @ApiModelProperty(value = "单据内码") |
| | | @ExcelComment(value = "poCode", example = "PO59755695") |
| | | private String poCode; |
| | | |
| | |
| | | */ |
| | | public enum AsnExceStatus { |
| | | |
| | | //ASN执行状态状态 |
| | | // ASN/入库单执行状态(新顺序):未执行(组托) → 任务执行中 → 已完成 |
| | | ASN_EXCE_STATUS_UN_EXCE("0", "未执行"), |
| | | /** @deprecated 已停用,新流程不再使用 */ |
| | | ASN_EXCE_STATUS_EXCE_ING("1", "执行中"), |
| | | /** @deprecated 已停用,新流程不再使用 */ |
| | | ASN_EXCE_STATUS_RECEIPT_DONE("2", "收货完成"), |
| | | ASN_EXCE_STATUS_TASK_EXCE("3", "任务执行中"), |
| | | /** 已完成:整单全流程结束(收货+组托+上架/入库任务等),可归档历史、上报 ERP;由组托/任务定时或移历史时设置 */ |
| | | ASN_EXCE_STATUS_TASK_DONE("4", "已完成"), |
| | | ASN_EXCE_STATUS_TASK_CANCEL("8", "取消"), |
| | | ASN_EXCE_STATUS_TASK_CLOSE("9", "已关闭"), |
| New file |
| | |
| | | package com.vincent.rsf.server.manager.listener; |
| | | |
| | | import com.vincent.rsf.server.common.event.DictDataChangedEvent; |
| | | import com.vincent.rsf.server.manager.service.OrderTypeDictService; |
| | | import com.vincent.rsf.server.manager.service.OrderWorkTypeService; |
| | | import com.vincent.rsf.server.system.constant.DictTypeCode; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | /** |
| | | * 字典数据变更时刷新订单业务类型、订单类型缓存,使配置改完立刻生效。 |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class OrderWorkTypeRefreshListener { |
| | | |
| | | @Resource |
| | | private OrderWorkTypeService orderWorkTypeService; |
| | | @Resource |
| | | private OrderTypeDictService orderTypeDictService; |
| | | |
| | | @EventListener |
| | | public void onDictDataChanged(DictDataChangedEvent event) { |
| | | if (DictTypeCode.DICT_ORDER_WORK_TYPE.equals(event.getDictTypeCode())) { |
| | | orderWorkTypeService.refreshCache(); |
| | | log.debug("订单业务类型字典已变更,已刷新缓存"); |
| | | } |
| | | if (DictTypeCode.DICT_SYS_ORDER_TYPE.equals(event.getDictTypeCode())) { |
| | | orderTypeDictService.refreshCache(); |
| | | log.debug("订单类型字典已变更,已刷新缓存"); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | |
| | | @Autowired |
| | | private FieldsItemService fieldsItemService; |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/5/9 |
| | | * @description: 直接组托开关为true,将收货单直接加入临时库存 |
| | | * @version 1.0 |
| | | */ |
| | | @Scheduled(cron = "0/25 * * * * ?") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public synchronized void IgnoreReceipt() { |
| | | Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN)); |
| | | if (Objects.isNull(config)) { |
| | | return; |
| | | } |
| | | if (!Boolean.parseBoolean(config.getVal())) { |
| | | return; |
| | | } |
| | | //自动收货单 |
| | | List<WkOrder> orders = asnOrderService.list(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(WkOrder::getType, OrderType.ORDER_IN.type) |
| | | .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)); |
| | | if (!orders.isEmpty()) { |
| | | for (WkOrder order : orders) { |
| | | if (order.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) { |
| | | WkOrder one = outStockService.getOne(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(WkOrder::getPoCode, order.getPoCode()) |
| | | .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)); |
| | | if (Objects.isNull(one)) { |
| | | throw new CoolException("数据错误"); |
| | | } |
| | | if (!one.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val)) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())); |
| | | if (orderItems.isEmpty()) { |
| | | return; |
| | | } |
| | | List<WarehouseAreasItem> items = new ArrayList<>(); |
| | | for (WkOrderItem item : orderItems) { |
| | | WarehouseAreas one = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>() |
| | | .eq(WarehouseAreas::getType, WarehouseAreasType.WAREHOUSE_AREAS_TYPE_RECEIPT.type), false); |
| | | Long areaId = Objects.isNull(one) ? null : one.getId(); |
| | | String areaName = Objects.isNull(one) ? null : one.getName(); |
| | | |
| | | WarehouseAreasItem param = new WarehouseAreasItem(); |
| | | BeanUtils.copyProperties(item, param); |
| | | param.setAreaId(one.getId()) |
| | | .setAsnCode(order.getCode()) |
| | | .setAreaId(areaId) |
| | | .setAreaName(areaName) |
| | | .setAsnId(order.getId()); |
| | | items.add(param); |
| | | Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getId, item.getMatnrId())); |
| | | if (Objects.isNull(matnr)) { |
| | | throw new CoolException("物料不存在!!"); |
| | | } |
| | | //更新收货区库存 |
| | | try { |
| | | updateReceipt(one, item, order, matnr); |
| | | } catch (Exception e) { |
| | | throw new CoolException(e.getMessage()); |
| | | } |
| | | |
| | | if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>().set(WkOrderItem::getQty, item.getAnfme()).eq(WkOrderItem::getId, item.getId()))) { |
| | | throw new CoolException("收货单明细完成数量修改失败!!"); |
| | | } |
| | | } |
| | | // if (!warehouseAreasItemService.saveBatch(items)) { |
| | | // throw new CoolException("收货单保存至收货区执行失败!!"); |
| | | // /** |
| | | // * @author Ryan |
| | | // * @date 2025/5/9 |
| | | // * @description: 直接组托开关为true,将收货单直接加入临时库存 |
| | | // * @version 1.0 |
| | | // */ |
| | | // @Scheduled(cron = "0/25 * * * * ?") |
| | | // @Transactional(rollbackFor = Exception.class) |
| | | // public synchronized void IgnoreReceipt() { |
| | | // Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.DIRECT_WAIT_PAKIN)); |
| | | // if (Objects.isNull(config)) { |
| | | // return; |
| | | // } |
| | | // if (!Boolean.parseBoolean(config.getVal())) { |
| | | // return; |
| | | // } |
| | | // //自动收货单 |
| | | // List<WkOrder> orders = asnOrderService.list(new LambdaQueryWrapper<WkOrder>() |
| | | // .eq(WkOrder::getType, OrderType.ORDER_IN.type) |
| | | // .eq(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)); |
| | | // if (!orders.isEmpty()) { |
| | | // for (WkOrder order : orders) { |
| | | // if (order.getWkType().equals(OrderWorkType.ORDER_WORK_TYPE_OTHER_TERANSFER.type)) { |
| | | // WkOrder one = outStockService.getOne(new LambdaQueryWrapper<WkOrder>() |
| | | // .eq(WkOrder::getPoCode, order.getPoCode()) |
| | | // .eq(WkOrder::getWkType, OrderWorkType.ORDER_WORK_TYPE_STOCK_TERANSFER.type)); |
| | | // if (Objects.isNull(one)) { |
| | | // throw new CoolException("数据错误"); |
| | | // } |
| | | // if (!one.getExceStatus().equals(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val)) { |
| | | // continue; |
| | | // } |
| | | // } |
| | | // |
| | | // List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, order.getId())); |
| | | // if (orderItems.isEmpty()) { |
| | | // return; |
| | | // } |
| | | // // 收货区已停用:不再写入收货区,仅更新单据状态与数量 |
| | | //// List<WarehouseAreas> receiptAreas = warehouseAreasService.list(new LambdaQueryWrapper<WarehouseAreas>() |
| | | //// .eq(WarehouseAreas::getType, WarehouseAreasType.WAREHOUSE_AREAS_TYPE_RECEIPT.type)); |
| | | //// WarehouseAreas receiptArea = receiptAreas.isEmpty() ? null : receiptAreas.get(0); |
| | | //// List<WarehouseAreasItem> items = new ArrayList<>(); |
| | | // for (WkOrderItem item : orderItems) { |
| | | //// Long areaId = receiptArea == null ? null : receiptArea.getId(); |
| | | //// String areaName = receiptArea == null ? null : receiptArea.getName(); |
| | | //// WarehouseAreasItem param = new WarehouseAreasItem(); |
| | | //// BeanUtils.copyProperties(item, param); |
| | | //// param.setAsnCode(order.getCode()).setAsnId(order.getId()); |
| | | //// if (areaId != null) { |
| | | //// param.setAreaId(areaId).setAreaName(areaName); |
| | | //// } |
| | | //// items.add(param); |
| | | //// Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getId, item.getMatnrId())); |
| | | //// if (Objects.isNull(matnr)) { |
| | | //// throw new CoolException("物料不存在!!"); |
| | | //// } |
| | | //// if (receiptArea != null) { |
| | | //// try { |
| | | //// updateReceipt(receiptArea, item, order, matnr); |
| | | //// } catch (Exception e) { |
| | | //// throw new CoolException(e.getMessage()); |
| | | //// } |
| | | //// } |
| | | // if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>().set(WkOrderItem::getQty, item.getAnfme()).eq(WkOrderItem::getId, item.getId()))) { |
| | | // throw new CoolException("收货单明细完成数量修改失败!!"); |
| | | // } |
| | | // } |
| | | //// if (!warehouseAreasItemService.saveBatch(items)) { |
| | | //// throw new CoolException("收货单保存至收货区执行失败!!"); |
| | | //// } |
| | | // |
| | | // if (!asnOrderService.update(new LambdaUpdateWrapper<WkOrder>() |
| | | // .set(WkOrder::getQty, order.getAnfme()) |
| | | // .set(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val) |
| | | // .eq(WkOrder::getId, order.getId()))) { |
| | | // throw new CoolException("收货单状态修改失败!!"); |
| | | // } |
| | | // } |
| | | // } |
| | | // } |
| | | |
| | | if (!asnOrderService.update(new LambdaUpdateWrapper<WkOrder>() |
| | | .set(WkOrder::getQty, order.getAnfme()) |
| | | .set(WkOrder::getExceStatus, AsnExceStatus.ASN_EXCE_STATUS_RECEIPT_DONE.val) |
| | | .eq(WkOrder::getId, order.getId()))) { |
| | | throw new CoolException("收货单状态修改失败!!"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | /** 收货区已停用,方法整体注释 |
| | | * @author Ryan |
| | | * @date 2025/5/12 |
| | | * @description: 收货区库存更新 |
| | | * @version 1.0 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateReceipt(WarehouseAreas areasItem, WkOrderItem orderItem, WkOrder wkOrder, Matnr matnr) throws Exception { |
| | | Companys companys = new Companys(); |
| | | if (StringUtils.isNoneBlank(orderItem.getSplrCode())) { |
| | | companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode())); |
| | | } |
| | | |
| | | WarehouseAreasItem item = new WarehouseAreasItem(); |
| | | item.setTrackCode(orderItem.getBarcode()) |
| | | .setAreaName(areasItem.getName()) |
| | | .setAreaId(areasItem.getId()) |
| | | .setAsnItemId(orderItem.getId()) |
| | | .setAsnCode(wkOrder.getCode()) |
| | | .setAsnId(wkOrder.getId()) |
| | | .setProdTime(orderItem.getProdTime()) |
| | | .setPlatItemId(orderItem.getPlatItemId()) |
| | | .setPlatOrderCode(orderItem.getPlatOrderCode()) |
| | | .setPlatWorkCode(orderItem.getPlatWorkCode()) |
| | | .setProjectCode(orderItem.getProjectCode()) |
| | | .setSplrId(companys.getId()) |
| | | //库存单位为最小单位 |
| | | .setUnit(orderItem.getStockUnit()) |
| | | .setStockUnit(orderItem.getStockUnit()) |
| | | .setMatnrCode(matnr.getCode()) |
| | | .setAnfme(orderItem.getAnfme()) |
| | | .setMatnrId(matnr.getId()) |
| | | .setIsptResult(orderItem.getIsptResult()) |
| | | .setMaktx(matnr.getName()) |
| | | .setSplrBatch(orderItem.getSplrBatch()) |
| | | .setWeight(matnr.getWeight()) |
| | | .setFieldsIndex(orderItem.getFieldsIndex()) |
| | | .setShipperId(matnr.getShipperId()); |
| | | |
| | | |
| | | 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)) { |
| | | throw new CoolException("票号:" + fieldsItem.getValue() + "已在收货区,不可推送相当票号数据。请联系管理员!!" ); |
| | | } |
| | | } |
| | | |
| | | LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<WarehouseAreasItem>() |
| | | .eq(WarehouseAreasItem::getMatnrCode, orderItem.getMatnrCode()) |
| | | .eq(!Cools.isEmpty(orderItem.getFieldsIndex()), WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex()) |
| | | .eq(WarehouseAreasItem::getAsnCode, orderItem.getOrderCode()) |
| | | .eq(StringUtils.isNotBlank(orderItem.getSplrBatch()), WarehouseAreasItem::getSplrBatch, orderItem.getSplrBatch()); |
| | | if (Objects.isNull(orderItem.getIsptResult())) { |
| | | queryWrapper.isNull(WarehouseAreasItem::getIsptResult); |
| | | } else { |
| | | queryWrapper.eq(WarehouseAreasItem::getIsptResult, orderItem.getIsptResult()); |
| | | } |
| | | WarehouseAreasItem serviceOne = warehouseAreasItemService.getOne(queryWrapper); |
| | | if (!Objects.isNull(serviceOne)) { |
| | | item.setId(serviceOne.getId()); |
| | | Double anfme = Math.round((item.getAnfme() + serviceOne.getAnfme()) * 1000000) / 1000000.0; |
| | | item.setAnfme(anfme); |
| | | } |
| | | //未质检 |
| | | if (!warehouseAreasItemService.saveOrUpdate(item)) { |
| | | throw new CoolException("收货失败!!"); |
| | | } |
| | | } |
| | | // @Transactional(rollbackFor = Exception.class) |
| | | // public void updateReceipt(WarehouseAreas areasItem, WkOrderItem orderItem, WkOrder wkOrder, Matnr matnr) throws Exception { |
| | | // Companys companys = new Companys(); |
| | | // if (StringUtils.isNoneBlank(orderItem.getSplrCode())) { |
| | | // companys = companysService.getOne(new LambdaQueryWrapper<Companys>().eq(Companys::getCode, orderItem.getSplrCode())); |
| | | // } |
| | | // WarehouseAreasItem item = new WarehouseAreasItem(); |
| | | // item.setTrackCode(orderItem.getBarcode()) |
| | | // .setAreaName(areasItem.getName()) |
| | | // .setAreaId(areasItem.getId()) |
| | | // .setAsnItemId(orderItem.getId()) |
| | | // .setAsnCode(wkOrder.getCode()) |
| | | // .setAsnId(wkOrder.getId()) |
| | | // .setProdTime(orderItem.getProdTime()) |
| | | // .setPlatItemId(orderItem.getPlatItemId()) |
| | | // .setPlatOrderCode(orderItem.getPlatOrderCode()) |
| | | // .setPlatWorkCode(orderItem.getPlatWorkCode()) |
| | | // .setProjectCode(orderItem.getProjectCode()) |
| | | // .setSplrId(companys.getId()) |
| | | // .setUnit(orderItem.getStockUnit()) |
| | | // .setStockUnit(orderItem.getStockUnit()) |
| | | // .setMatnrCode(matnr.getCode()) |
| | | // .setAnfme(orderItem.getAnfme()) |
| | | // .setMatnrId(matnr.getId()) |
| | | // .setIsptResult(orderItem.getIsptResult()) |
| | | // .setMaktx(matnr.getName()) |
| | | // .setSplrBatch(orderItem.getSplrBatch()) |
| | | // .setWeight(matnr.getWeight()) |
| | | // .setFieldsIndex(orderItem.getFieldsIndex()) |
| | | // .setShipperId(matnr.getShipperId()); |
| | | // List<WarehouseAreasItem> warehousList = StringUtils.isNotBlank(orderItem.getFieldsIndex()) |
| | | // ? warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex())) |
| | | // : Collections.emptyList(); |
| | | // WarehouseAreasItem warehousItem = warehousList.isEmpty() ? null : warehousList.get(0); |
| | | // if (!Objects.isNull(warehousItem)) { |
| | | // List<FieldsItem> fieldsList = fieldsItemService.list(new LambdaQueryWrapper<FieldsItem>() |
| | | // .eq(FieldsItem::getUuid, orderItem.getFieldsIndex()).last("LIMIT 1")); |
| | | // FieldsItem fieldsItem = fieldsList.isEmpty() ? null : fieldsList.get(0); |
| | | // if (!Objects.isNull(fieldsItem)) { |
| | | // throw new CoolException("票号:" + fieldsItem.getValue() + "已在收货区,不可推送相当票号数据。请联系管理员!!" ); |
| | | // } |
| | | // } |
| | | // LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new LambdaQueryWrapper<WarehouseAreasItem>() |
| | | // .eq(WarehouseAreasItem::getMatnrCode, orderItem.getMatnrCode()) |
| | | // .eq(!Cools.isEmpty(orderItem.getFieldsIndex()), WarehouseAreasItem::getFieldsIndex, orderItem.getFieldsIndex()) |
| | | // .eq(WarehouseAreasItem::getAsnCode, orderItem.getOrderCode()) |
| | | // .eq(StringUtils.isNotBlank(orderItem.getSplrBatch()), WarehouseAreasItem::getSplrBatch, orderItem.getSplrBatch()); |
| | | // if (Objects.isNull(orderItem.getIsptResult())) { |
| | | // queryWrapper.isNull(WarehouseAreasItem::getIsptResult); |
| | | // } else { |
| | | // queryWrapper.eq(WarehouseAreasItem::getIsptResult, orderItem.getIsptResult()); |
| | | // } |
| | | // List<WarehouseAreasItem> serviceList = warehouseAreasItemService.list(queryWrapper); |
| | | // WarehouseAreasItem serviceOne = serviceList.isEmpty() ? null : serviceList.get(0); |
| | | // if (!Objects.isNull(serviceOne)) { |
| | | // item.setId(serviceOne.getId()); |
| | | // item.setAnfme(orderItem.getAnfme()); |
| | | // } |
| | | // if (!warehouseAreasItemService.saveOrUpdate(item)) { |
| | | // throw new CoolException("收货失败!!"); |
| | | // } |
| | | // } |
| | | |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | /** |
| | | * @param |
| | | * @return |
| | | * 完成入库,更新库位明细、组托状态,并在此统一执行 9.1 入/出库结果上报云仓。 |
| | | * 与 RCS 回调形成闭环:RCS 上报任务结束后仅将任务状态置为 COMPLETE_IN(见 WcsServiceImpl.receiveExMsg), |
| | | * 本定时任务扫描 COMPLETE_IN 并执行 complateInTask(库位、组托、9.1 上报云仓)。 |
| | | * |
| | | * @author Ryan |
| | | * @description 完成入库,更新库存 |
| | | * @time 2025/4/2 12:37 |
| | | */ |
| | | @Scheduled(cron = "0/3 * * * * ?") |
| | |
| | | } |
| | | |
| | | /** |
| | | * 完成出库任务,更新库位/出库单,并在此统一执行 9.1 入/出库结果上报云仓。 |
| | | * 与 RCS 回调形成闭环:RCS 上报 END 后仅将出库任务状态置为 COMPLETE_OUT(见 WcsServiceImpl.receiveExMsg), |
| | | * 本定时任务扫描 COMPLETE_OUT 并执行 completeTask(扣库位、更新出库单、9.1 上报云仓)。 |
| | | * |
| | | * @author Ryan |
| | | * @date 2025/5/20 |
| | | * @description: 完成出库任务,更新库存 |
| | | * @version 1.0 |
| | | */ |
| | | @Scheduled(cron = "0/5 * * * * ? ") |
| | | @Transactional(rollbackFor = Exception.class) |
| New file |
| | |
| | | package com.vincent.rsf.server.manager.service; |
| | | |
| | | import com.vincent.rsf.server.system.entity.DictData; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 订单类型字典:从字典表动态获取(出库单/入库单/调拨单等),兼容 API 的 1/2/3。 |
| | | */ |
| | | public interface OrderTypeDictService { |
| | | |
| | | /** |
| | | * 查询所有启用的订单类型(带缓存) |
| | | */ |
| | | List<DictData> listAll(); |
| | | |
| | | /** |
| | | * 根据显示名称取类型编码,如 "出库单" -> "out" |
| | | */ |
| | | String getTypeByLabel(String label); |
| | | |
| | | /** |
| | | * 根据类型编码取显示名称,如 "out" -> "出库单" |
| | | */ |
| | | String getLabelByType(String type); |
| | | |
| | | /** |
| | | * 解析入参为内部类型编码。支持:数字 1/2/3、中文 "出库单"/"入库单"/"调拨单"、内部码 "out"/"in"/"transfer" |
| | | */ |
| | | String resolveType(String input); |
| | | |
| | | /** |
| | | * 解析 Integer 类型的 orderType(API 约定 1=出库 2=入库 3=调拨) |
| | | */ |
| | | String resolveType(Integer orderType); |
| | | |
| | | void refreshCache(); |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.manager.service; |
| | | |
| | | import com.vincent.rsf.server.system.entity.DictData; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 订单业务类型:从字典表动态获取与配置,替代/补充 OrderWorkType 枚举。 |
| | | */ |
| | | public interface OrderWorkTypeService { |
| | | |
| | | /** |
| | | * 查询所有启用的订单业务类型(带缓存,字典变更后需调用 refreshCache) |
| | | */ |
| | | List<DictData> listAll(); |
| | | |
| | | /** |
| | | * 根据显示名称(label)取类型编码(value),如 "采购入库单" -> "1" |
| | | */ |
| | | String getTypeByLabel(String label); |
| | | |
| | | /** |
| | | * 根据类型编码(value)取显示名称(label),如 "1" -> "采购入库单" |
| | | */ |
| | | String getLabelByType(String type); |
| | | |
| | | /** |
| | | * 清除缓存,下次 listAll 时从数据库重新加载(字典数据变更后调用) |
| | | */ |
| | | void refreshCache(); |
| | | } |
| | |
| | | BeanUtils.copyProperties(orderLog, order); |
| | | order.setId(orderLog.getAsnId()) |
| | | .setDeleted(0) |
| | | .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val); |
| | | .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val); // 新顺序:不再使用执行中 |
| | | |
| | | WkOrder wkOrder = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>().eq(WkOrder::getCode, orderLog.getCode())); |
| | | if (!Objects.isNull(wkOrder)) { |
| | |
| | | private AsnOrderService asnOrderService; |
| | | @Autowired |
| | | private TaskService taskService; |
| | | @Autowired |
| | | private WaitPakinItemService waitPakinItemService; |
| | | |
| | | @Override |
| | | public boolean notifyInspect(List<WkOrder> orders) { |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R removeOrders(List<Long> ids) { |
| | | // 已组托不可删除,需先解除组托 |
| | | long palletizedCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>() |
| | | .in(WaitPakinItem::getAsnId, ids)); |
| | | if (palletizedCount > 0) { |
| | | throw new CoolException("单据已组托,请先解除组托后再删除!!"); |
| | | } |
| | | for (Long id : ids) { |
| | | List<WkOrderItem> list = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>() |
| | | .eq(WkOrderItem::getOrderId, id)); |
| New file |
| | |
| | | package com.vincent.rsf.server.manager.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.vincent.rsf.server.manager.enums.OrderType; |
| | | import com.vincent.rsf.server.manager.service.OrderTypeDictService; |
| | | import com.vincent.rsf.server.system.constant.DictTypeCode; |
| | | import com.vincent.rsf.server.system.entity.DictData; |
| | | import com.vincent.rsf.server.system.service.DictDataService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 订单类型:优先从字典表读取,兼容 API 数字 1/2/3 与枚举回退。 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class OrderTypeDictServiceImpl implements OrderTypeDictService { |
| | | |
| | | private static final Map<String, String> API_NUMERIC_MAP = new HashMap<>(); |
| | | static { |
| | | API_NUMERIC_MAP.put("1", OrderType.ORDER_OUT.type); // 出库单 |
| | | API_NUMERIC_MAP.put("2", OrderType.ORDER_IN.type); // 入库单 |
| | | API_NUMERIC_MAP.put("3", OrderType.ORDER_TRANSFER.type); // 调拨单 |
| | | } |
| | | |
| | | @Resource |
| | | private DictDataService dictDataService; |
| | | |
| | | private volatile List<DictData> cache; |
| | | private static final Object CACHE_LOCK = new Object(); |
| | | |
| | | @Override |
| | | public List<DictData> listAll() { |
| | | if (cache != null && !cache.isEmpty()) { |
| | | return cache; |
| | | } |
| | | synchronized (CACHE_LOCK) { |
| | | if (cache != null && !cache.isEmpty()) { |
| | | return cache; |
| | | } |
| | | List<DictData> list = dictDataService.list(new LambdaQueryWrapper<DictData>() |
| | | .eq(DictData::getDictTypeCode, DictTypeCode.DICT_SYS_ORDER_TYPE) |
| | | .eq(DictData::getStatus, 1) |
| | | .orderByAsc(DictData::getSort)); |
| | | cache = list; |
| | | return cache; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public String getTypeByLabel(String label) { |
| | | if (label == null || label.isEmpty()) return null; |
| | | for (DictData d : listAll()) { |
| | | if (label.equals(d.getLabel())) return d.getValue(); |
| | | } |
| | | return OrderType.getTypeVal(label); |
| | | } |
| | | |
| | | @Override |
| | | public String getLabelByType(String type) { |
| | | if (type == null || type.isEmpty()) return null; |
| | | for (DictData d : listAll()) { |
| | | if (type.equals(d.getValue())) return d.getLabel(); |
| | | } |
| | | return OrderType.getValType(type); |
| | | } |
| | | |
| | | @Override |
| | | public String resolveType(String input) { |
| | | if (input == null) return null; |
| | | String s = input.trim(); |
| | | if (s.isEmpty()) return null; |
| | | if (API_NUMERIC_MAP.containsKey(s)) return API_NUMERIC_MAP.get(s); |
| | | String byLabel = getTypeByLabel(s); |
| | | if (byLabel != null) return byLabel; |
| | | if (getLabelByType(s) != null) return s; |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public String resolveType(Integer orderType) { |
| | | if (orderType == null) return null; |
| | | return API_NUMERIC_MAP.get(String.valueOf(orderType)); |
| | | } |
| | | |
| | | @Override |
| | | public void refreshCache() { |
| | | synchronized (CACHE_LOCK) { |
| | | cache = null; |
| | | } |
| | | log.info("订单类型字典缓存已刷新"); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.manager.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.vincent.rsf.server.manager.enums.OrderWorkType; |
| | | import com.vincent.rsf.server.manager.service.OrderWorkTypeService; |
| | | import com.vincent.rsf.server.system.constant.DictTypeCode; |
| | | import com.vincent.rsf.server.system.entity.DictData; |
| | | import com.vincent.rsf.server.system.service.DictDataService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 订单业务类型:优先从字典表读取(可配置),无则回退到 OrderWorkType 枚举。 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class OrderWorkTypeServiceImpl implements OrderWorkTypeService { |
| | | |
| | | @Resource |
| | | private DictDataService dictDataService; |
| | | |
| | | private volatile List<DictData> cache; |
| | | private static final Object CACHE_LOCK = new Object(); |
| | | |
| | | @Override |
| | | public List<DictData> listAll() { |
| | | if (cache != null && !cache.isEmpty()) { |
| | | return cache; |
| | | } |
| | | synchronized (CACHE_LOCK) { |
| | | if (cache != null && !cache.isEmpty()) { |
| | | return cache; |
| | | } |
| | | List<DictData> list = dictDataService.list(new LambdaQueryWrapper<DictData>() |
| | | .eq(DictData::getDictTypeCode, DictTypeCode.DICT_ORDER_WORK_TYPE) |
| | | .eq(DictData::getStatus, 1) |
| | | .orderByAsc(DictData::getSort)); |
| | | cache = list; |
| | | return cache; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public String getTypeByLabel(String label) { |
| | | if (label == null || label.isEmpty()) { |
| | | return null; |
| | | } |
| | | for (DictData d : listAll()) { |
| | | if (label.equals(d.getLabel())) { |
| | | return d.getValue(); |
| | | } |
| | | } |
| | | // 回退到枚举 |
| | | return OrderWorkType.getWorkType(label); |
| | | } |
| | | |
| | | @Override |
| | | public String getLabelByType(String type) { |
| | | if (type == null || type.isEmpty()) { |
| | | return null; |
| | | } |
| | | for (DictData d : listAll()) { |
| | | if (type.equals(d.getValue())) { |
| | | return d.getLabel(); |
| | | } |
| | | } |
| | | // 回退到枚举 |
| | | return OrderWorkType.getWorkDesc(type); |
| | | } |
| | | |
| | | @Override |
| | | public void refreshCache() { |
| | | synchronized (CACHE_LOCK) { |
| | | cache = null; |
| | | } |
| | | log.info("订单业务类型字典缓存已刷新"); |
| | | } |
| | | } |
| | |
| | | if (success.compareAndSet(false, true)) { |
| | | Long loginUserId = SystemAuthUtils.getLoginUserId(); |
| | | for (Task task : tasks) { |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type)) { |
| | | //1.入库 |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type) || task.getTaskType().equals(TaskType.TASK_TYPE_MERGE_IN.type)) { |
| | | //1.入库、54.并板再入库 |
| | | complateInstock(task, loginUserId); |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type) || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { |
| | | //53.拣料再入库 |
| | | //57.盘点再入库 |
| | | //53.拣料再入库、57.盘点再入库 |
| | | pickComplateInStock(task, loginUserId); |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_LOC_MOVE.type)) { |
| | | //移库 |
| | | //11.库格移载 |
| | | moveInStock(task, loginUserId); |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_EMPITY_IN.type)) { |
| | | //10.空板入库:与普通入库共用一个完成逻辑(若有组托则更新组托/库位并上报云仓) |
| | | complateInstock(task, loginUserId); |
| | | } |
| | | } |
| | | } |
| | |
| | | .set(Task::getTaskStatus, TaskStsType.UPDATED_IN.id))) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | |
| | | // 9.1 入/出库结果上报:库格移载完成后通知云仓(与定时任务闭环一致) |
| | | List<TaskItem> moveTaskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | if (!moveTaskItems.isEmpty()) { |
| | | reportInOutResultToCloud(task, loc, moveTaskItems, null, true); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | if (!taskService.updateById(task)) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | |
| | | // 9.1 入/出库结果上报:拣料再入库/盘点再入库完成后通知云仓(与定时任务闭环一致) |
| | | reportInOutResultToCloud(task, loc, taskItems, null, true); |
| | | } |
| | | |
| | | /** |
| | |
| | | List<TaskItem> items = orderMap.get(key); |
| | | //保存入出库明细 |
| | | saveStockItems(items, task, pakinItem.getId(), pakinItem.getAsnCode(), pakinItem.getWkType(), pakinItem.getType(), loginUserId); |
| | | //移出收货区库存, 修改组托状态(只有当source不为null时才需要移除收货区库存) |
| | | if (Objects.nonNull(pakinItem.getSource())) { |
| | | removeReceiptStock(pakinItem, loginUserId); |
| | | } |
| | | // 收货区已停用,不再移出收货区库存 |
| | | // if (Objects.nonNull(pakinItem.getSource())) { |
| | | // removeReceiptStock(pakinItem, loginUserId); |
| | | // } |
| | | }); |
| | | |
| | | Set<Long> pkinItemIds = taskItems.stream().map(TaskItem::getSource).collect(Collectors.toSet()); |
| | |
| | | Date now = new Date(); |
| | | for (TaskItem item : taskItems) { |
| | | String orderNo = isInbound ? sourceToOrderNo.get(item.getSource()) : (item.getPlatOrderCode() != null ? item.getPlatOrderCode() : item.getPlatWorkCode()); |
| | | if (orderNo == null && isInbound) { |
| | | orderNo = item.getPlatOrderCode() != null ? item.getPlatOrderCode() : item.getPlatWorkCode(); |
| | | } |
| | | if (orderNo == null || item.getMatnrCode() == null) { |
| | | continue; |
| | | } |
| | |
| | | throw new CoolException("出库单明细保存失败!!"); |
| | | } |
| | | |
| | | transfer.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_EXCE_ING.val); |
| | | transfer.setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val); // 新顺序:不再使用执行中 |
| | | |
| | | if (!this.updateById(transfer)) { |
| | | throw new CoolException("调拔单更新失败!!"); |
| | |
| | | import com.vincent.rsf.server.manager.mapper.MatnrMapper; |
| | | import com.vincent.rsf.server.manager.service.*; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.vincent.rsf.server.common.utils.QuantityUtils; |
| | | import com.vincent.rsf.server.system.constant.SerialRuleCode; |
| | | import com.vincent.rsf.server.system.utils.SerialRuleUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | |
| | | WaitPakin pakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>() |
| | | .eq(WaitPakin::getBarcode, waitPakin.getBarcode())); |
| | | |
| | | // 如果容器号已经组托过,提示已组托,请更换容器条码 |
| | | // 如果料箱码已经组托过,提示已组托,请更换料箱码 |
| | | if (!Objects.isNull(pakin)) { |
| | | throw new CoolException("已组托,请更换容器条码"); |
| | | throw new CoolException("已组托,请更换料箱码"); |
| | | } |
| | | |
| | | List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, waitPakin.getBarcode())); |
| | |
| | | throw new CoolException("当前料箱已有任务档在执行,不能再次组托!!"); |
| | | } |
| | | |
| | | // 检查容器号是否在库存中存在(通过库位表查询) |
| | | // 检查料箱码是否在库存中存在(通过库位表查询) |
| | | List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, waitPakin.getBarcode())); |
| | | if (!locs.isEmpty()) { |
| | | throw new CoolException("在库,请更换容器条码"); |
| | | throw new CoolException("在库,请更换料箱码"); |
| | | } |
| | | |
| | | double sum = waitPakin.getItems().stream().mapToDouble(PakinItem::getReceiptQty).sum(); |
| | | Double sum = QuantityUtils.roundToScale(waitPakin.getItems().stream().mapToDouble(PakinItem::getReceiptQty).sum()); |
| | | |
| | | WaitPakin waitPakin1 = new WaitPakin(); |
| | | if (Objects.isNull(pakin)) { |
| | |
| | | if (pakinItem1.getReceiptQty() == null || pakinItem1.getReceiptQty().compareTo(0.0) <= 0) { |
| | | throw new CoolException("组托数量不能小于等于零!!"); |
| | | } |
| | | pakinItem.setAnfme(pakinItem1.getReceiptQty()) |
| | | pakinItem.setAnfme(QuantityUtils.roundToScale(pakinItem1.getReceiptQty())) |
| | | .setTrackCode(pakinItem1.getTrackCode()); |
| | | } else { |
| | | // 有ASN单号,从收货区获取物料信息 |
| | | WarehouseAreasItem warehouseAreasItems = warehouseAreasItemService.getById(pakinItem1.getId()); |
| | | if (null == warehouseAreasItems) { |
| | | throw new CoolException("物料未送至收货区!!"); |
| | | // 收货区已停用:有ASN单号时从订单明细获取物料信息 |
| | | WkOrderItem orderItem = asnOrderItemService.getById(pakinItem1.getId()); |
| | | if (null == orderItem) { |
| | | throw new CoolException("订单明细不存在!!"); |
| | | } |
| | | |
| | | pakinItem.setAnfme(warehouseAreasItems.getAnfme()) |
| | | WkOrder order = asnOrderService.getById(orderItem.getOrderId()); |
| | | if (null == order) { |
| | | throw new CoolException("订单不存在!!"); |
| | | } |
| | | pakinItem.setAnfme(QuantityUtils.roundToScale(orderItem.getAnfme())) |
| | | .setPakinId(waitPakin1.getId()) |
| | | .setSource(warehouseAreasItems.getId()) |
| | | .setAsnId(warehouseAreasItems.getAsnId()) |
| | | .setAsnCode(warehouseAreasItems.getAsnCode()) |
| | | .setAsnItemId(warehouseAreasItems.getAsnItemId()) |
| | | .setIsptResult(warehouseAreasItems.getIsptResult()) |
| | | .setPlatItemId(warehouseAreasItems.getPlatItemId()) |
| | | .setPlatOrderCode(warehouseAreasItems.getPlatOrderCode()) |
| | | .setPlatWorkCode(warehouseAreasItems.getPlatWorkCode()) |
| | | .setProjectCode(warehouseAreasItems.getProjectCode()) |
| | | .setBatch(warehouseAreasItems.getSplrBatch()) |
| | | .setUnit(warehouseAreasItems.getStockUnit()) |
| | | .setFieldsIndex(warehouseAreasItems.getFieldsIndex()) |
| | | .setMatnrId(warehouseAreasItems.getMatnrId()) |
| | | .setMaktx(warehouseAreasItems.getMaktx()) |
| | | .setSource(null) // 收货区已停用,不关联收货区 |
| | | .setAsnId(order.getId()) |
| | | .setAsnCode(order.getCode()) |
| | | .setAsnItemId(orderItem.getId()) |
| | | .setIsptResult(orderItem.getIsptResult()) |
| | | .setPlatItemId(orderItem.getPlatItemId()) |
| | | .setPlatOrderCode(orderItem.getPlatOrderCode()) |
| | | .setPlatWorkCode(orderItem.getPlatWorkCode()) |
| | | .setProjectCode(orderItem.getProjectCode()) |
| | | .setBatch(orderItem.getSplrBatch()) |
| | | .setUnit(orderItem.getStockUnit()) |
| | | .setFieldsIndex(orderItem.getFieldsIndex()) |
| | | .setMatnrId(orderItem.getMatnrId()) |
| | | .setMaktx(orderItem.getMaktx()) |
| | | .setUpdateBy(userId) |
| | | .setCreateBy(userId) |
| | | .setMatnrCode(warehouseAreasItems.getMatnrCode()); |
| | | |
| | | WkOrder order = asnOrderService.getById(warehouseAreasItems.getAsnId()); |
| | | if (!Objects.isNull(order)) { |
| | | .setMatnrCode(orderItem.getMatnrCode()); |
| | | pakinItem.setType(null == order.getType() ? null : order.getType()) |
| | | .setWkType(null == order.getWkType() ? null : Short.parseShort(order.getWkType())); |
| | | } |
| | | .setWkType(StringUtils.isNotBlank(order.getWkType()) ? Short.parseShort(order.getWkType()) : null); |
| | | |
| | | for (PakinItem waitPakinItem : waitPakin.getItems()) { |
| | | if (waitPakinItem.getId().equals(warehouseAreasItems.getId())) { |
| | | if (waitPakinItem.getReceiptQty() > warehouseAreasItems.getAnfme() || waitPakinItem.getReceiptQty().compareTo(0.0) <= 0) { |
| | | throw new CoolException("组托数量不能大于收货数量且不能小于零!!"); |
| | | if (waitPakinItem.getId().equals(orderItem.getId())) { |
| | | if (waitPakinItem.getReceiptQty() == null || waitPakinItem.getReceiptQty().compareTo(0.0) <= 0) { |
| | | throw new CoolException("组托数量不能小于等于零!!"); |
| | | } |
| | | pakinItem.setAnfme(waitPakinItem.getReceiptQty()) |
| | | if (QuantityUtils.compare(waitPakinItem.getReceiptQty(), orderItem.getAnfme()) > 0) { |
| | | throw new CoolException("组托数量不能大于计划数量!!"); |
| | | } |
| | | pakinItem.setAnfme(QuantityUtils.roundToScale(waitPakinItem.getReceiptQty())) |
| | | .setTrackCode(waitPakinItem.getTrackCode()); |
| | | } |
| | | } |
| | |
| | | List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin1.getId())); |
| | | Double waitSum = 0.0; |
| | | if (!pakinItems.isEmpty()) { |
| | | waitSum = pakinItems.stream().mapToDouble(WaitPakinItem::getAnfme).sum(); |
| | | waitSum = QuantityUtils.roundToScale(pakinItems.stream().mapToDouble(WaitPakinItem::getAnfme).sum()); |
| | | } |
| | | // Double total = Math.round((sum + waitSum) * 100) / 100.0; |
| | | |
| | | for (WaitPakinItem pakinItem : items) { |
| | | // 如果source为空(没有ASN单号,不在收货区),跳过收货区更新 |
| | | if (Objects.isNull(pakinItem.getSource())) { |
| | | continue; |
| | | } |
| | | |
| | | WarehouseAreasItem one = warehouseAreasItemService.getOne(new LambdaQueryWrapper<WarehouseAreasItem>() |
| | | .eq(WarehouseAreasItem::getId, pakinItem.getSource())); |
| | | if (Objects.isNull(one)) { |
| | | throw new CoolException("收货区数据错误!!"); |
| | | } |
| | | Double workQty = Math.round((one.getWorkQty() + pakinItem.getAnfme()) * 1000000) / 1000000.0; |
| | | Double qty = Math.round((workQty + one.getQty()) * 1000000) / 1000000.0; |
| | | one.setWorkQty(workQty); |
| | | if (qty.compareTo(one.getAnfme()) > 0) { |
| | | throw new CoolException("组托数量不能大于收货数量!!"); |
| | | } |
| | | if (!warehouseAreasItemService.saveOrUpdate(one)) { |
| | | throw new CoolException("收货区执行数量修改失败!!"); |
| | | } |
| | | } |
| | | // 收货区已停用,不再更新收货区 |
| | | // for (WaitPakinItem pakinItem : items) { |
| | | // if (Objects.isNull(pakinItem.getSource())) continue; |
| | | // WarehouseAreasItem one = warehouseAreasItemService.getOne(new LambdaQueryWrapper<WarehouseAreasItem>() |
| | | // .eq(WarehouseAreasItem::getId, pakinItem.getSource())); |
| | | // if (Objects.isNull(one)) throw new CoolException("收货区数据错误!!"); |
| | | // Double workQty = Math.round((one.getWorkQty() + pakinItem.getAnfme()) * 1000000) / 1000000.0; |
| | | // Double qty = Math.round((workQty + one.getQty()) * 1000000) / 1000000.0; |
| | | // one.setWorkQty(workQty); |
| | | // if (qty.compareTo(one.getAnfme()) > 0) throw new CoolException("组托数量不能大于收货数量!!"); |
| | | // if (!warehouseAreasItemService.saveOrUpdate(one)) throw new CoolException("收货区执行数量修改失败!!"); |
| | | // } |
| | | |
| | | waitPakin1.setAnfme(waitSum); |
| | | if (!this.updateById(waitPakin1)) { |
| | |
| | | // if (!waitPakinItemService.removeByIds(ids)) { |
| | | // throw new CoolException("组托明细解绑失败!!"); |
| | | // } |
| | | List<Long> list2 = pakinItems.stream().map(WaitPakinItem::getSource).collect(Collectors.toList()); |
| | | List<WarehouseAreasItem> warehouseAreasItems = warehouseAreasItemService.listByIds(list2); |
| | | // 收货区已停用:仅保留非空 source 用于兼容旧数据,不再更新收货区 |
| | | List<Long> list2 = pakinItems.stream().map(WaitPakinItem::getSource).filter(Objects::nonNull).collect(Collectors.toList()); |
| | | List<WarehouseAreasItem> warehouseAreasItems = list2.isEmpty() ? Collections.emptyList() : warehouseAreasItemService.listByIds(list2); |
| | | for (int i1 = 0; i1 < pakinItems.size(); i1++) { |
| | | for (PakinItem item : paramItems) { |
| | | if (item.getId().equals(pakinItems.get(i1).getId())) { |
| | | if (pakinItems.get(i1).getAnfme().compareTo(item.getReceiptQty()) > 0) { |
| | | if (item.getReceiptQty().compareTo(0.00) == 0) { |
| | | if (QuantityUtils.compare(pakinItems.get(i1).getAnfme(), item.getReceiptQty()) > 0) { |
| | | if (QuantityUtils.compare(item.getReceiptQty(), 0.00) == 0) { |
| | | throw new CoolException("解绑数量不能为零!!"); |
| | | } |
| | | Double reslt = Math.round((pakinItems.get(i1).getAnfme() - pakinItems.get(i1).getWorkQty() - pakinItems.get(i1).getQty()) * 1000000) / 1000000.0; |
| | | if (item.getReceiptQty().compareTo(reslt) > 0) { |
| | | Double reslt = QuantityUtils.subtract(QuantityUtils.subtract(pakinItems.get(i1).getAnfme(), pakinItems.get(i1).getWorkQty()), pakinItems.get(i1).getQty()); |
| | | if (QuantityUtils.compare(item.getReceiptQty(), reslt) > 0) { |
| | | throw new CoolException("解绑数量不能大于剩余可执行数!!"); |
| | | } |
| | | |
| | | Double anfme = Math.round((pakinItems.get(i1).getAnfme() - item.getReceiptQty()) * 1000000) / 1000000.0; |
| | | Double anfme = QuantityUtils.subtract(pakinItems.get(i1).getAnfme(), item.getReceiptQty()); |
| | | pakinItems.get(i1).setAnfme(anfme); |
| | | if (!waitPakinItemService.updateById(pakinItems.get(i1))) { |
| | | throw new CoolException("组托明细数量修改失败!!"); |
| | |
| | | throw new CoolException("组托明细删除失败!!"); |
| | | } |
| | | } |
| | | for (int i = 0; i < warehouseAreasItems.size(); i++) { |
| | | if (warehouseAreasItems.get(i).getId().equals(pakinItems.get(i1).getSource())) { |
| | | double v = Math.round((warehouseAreasItems.get(i).getWorkQty() - item.getReceiptQty()) * 1000000) / 1000000.0; |
| | | warehouseAreasItems.get(i).setWorkQty(v); |
| | | if (!warehouseAreasItemService.updateById(warehouseAreasItems.get(i))) { |
| | | throw new CoolException("收货区数量修改失败!!"); |
| | | } |
| | | } |
| | | } |
| | | // 收货区已停用,不再回写收货区 |
| | | // for (int i = 0; i < warehouseAreasItems.size(); i++) { |
| | | // if (warehouseAreasItems.get(i).getId().equals(pakinItems.get(i1).getSource())) { |
| | | // double v = Math.round((warehouseAreasItems.get(i).getWorkQty() - item.getReceiptQty()) * 1000000) / 1000000.0; |
| | | // warehouseAreasItems.get(i).setWorkQty(v); |
| | | // if (!warehouseAreasItemService.updateById(warehouseAreasItems.get(i))) { |
| | | // throw new CoolException("收货区数量修改失败!!"); |
| | | // } |
| | | // } |
| | | // } |
| | | } |
| | | } |
| | | } |
| | | |
| | | double anfmes = paramItems.stream().mapToDouble(PakinItem::getReceiptQty).sum(); |
| | | Double anfmes = QuantityUtils.roundToScale(paramItems.stream().mapToDouble(PakinItem::getReceiptQty).sum()); |
| | | // double anfmes = warehouseAreasItems.stream().mapToDouble(WarehouseAreasItem::getAnfme).sum(); |
| | | if (waitPakins.getAnfme().compareTo(anfmes) <= 0) { |
| | | if (QuantityUtils.compare(waitPakins.getAnfme(), anfmes) <= 0) { |
| | | if (!waitPakinService.removeById(waitPakins.getId())) { |
| | | throw new CoolException("组托删除失败!!"); |
| | | } |
| | | } else { |
| | | Double anfme = Math.round((waitPakins.getAnfme() - anfmes) * 1000000) / 1000000.0; |
| | | waitPakins.setAnfme(anfme); |
| | | waitPakins.setAnfme(QuantityUtils.subtract(waitPakins.getAnfme(), anfmes)); |
| | | if (!waitPakinService.updateById(waitPakins)) { |
| | | throw new CoolException("组托数据修改失败!!"); |
| | | } |
| | |
| | | return R.error("组拖档有明细任务"); |
| | | } |
| | | |
| | | Set<Long> sourceIds = pakinItems.stream().map(WaitPakinItem::getSource).collect(Collectors.toSet()); |
| | | Set<Long> sourceIds = pakinItems.stream().map(WaitPakinItem::getSource).filter(Objects::nonNull).collect(Collectors.toSet()); |
| | | |
| | | List<WarehouseAreasItem> areasItems = warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>() |
| | | .in(WarehouseAreasItem::getId, sourceIds)); |
| | | List<WarehouseAreasItem> areasItems = sourceIds.isEmpty() ? Collections.emptyList() : warehouseAreasItemService.list(new LambdaQueryWrapper<WarehouseAreasItem>().in(WarehouseAreasItem::getId, sourceIds)); |
| | | |
| | | if (areasItems.isEmpty()) { |
| | | return R.error("收货区数据不存在!!"); |
| | | } |
| | | |
| | | // 收货区已停用,仅兼容旧数据时回滚收货区数量 |
| | | if (!areasItems.isEmpty()) { |
| | | Map<Long, List<WaitPakinItem>> listMap = pakinItems.stream().collect(Collectors.groupingBy(WaitPakinItem::getSource)); |
| | | for (WarehouseAreasItem item : areasItems) { |
| | | List<WaitPakinItem> pakin = listMap.get(item.getId()); |
| | | if (Objects.isNull(pakin)) { |
| | | continue; |
| | | } |
| | | double sum = pakin.stream().mapToDouble(WaitPakinItem::getAnfme).sum(); |
| | | Double workQty = Math.round((item.getWorkQty() - sum) * 1000000) / 1000000.0; |
| | | item.setWorkQty(workQty); |
| | | Double sum = QuantityUtils.roundToScale(pakin.stream().mapToDouble(WaitPakinItem::getAnfme).sum()); |
| | | item.setWorkQty(QuantityUtils.subtract(item.getWorkQty(), sum)); |
| | | if (!warehouseAreasItemService.updateById(item)) { |
| | | throw new CoolException("收货区数据回滚失败!!"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Set<Long> pakinItemIds = pakinItems.stream().map(WaitPakinItem::getId).collect(Collectors.toSet()); |
| | | |
| | |
| | | public final static String SYS_TRANSFER_TYPE = "sys_transfer_type"; |
| | | /**库存调整*/ |
| | | public final static String SYS_STOCK_REVISE_TYPE = "sys_stock_revise_type"; |
| | | |
| | | /** 订单业务类型(可界面配置,与 OrderWorkType 枚举对应) */ |
| | | public final static String DICT_ORDER_WORK_TYPE = "sys_order_work_type"; |
| | | } |
| | |
| | | package com.vincent.rsf.server.system.service.impl; |
| | | |
| | | import com.vincent.rsf.server.system.mapper.DictDataMapper; |
| | | import com.vincent.rsf.server.system.entity.DictData; |
| | | import com.vincent.rsf.server.system.service.DictDataService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.vincent.rsf.server.common.event.DictDataChangedEvent; |
| | | import com.vincent.rsf.server.system.entity.DictData; |
| | | import com.vincent.rsf.server.system.mapper.DictDataMapper; |
| | | import com.vincent.rsf.server.system.service.DictDataService; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.Serializable; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service("dictDataService") |
| | | public class DictDataServiceImpl extends ServiceImpl<DictDataMapper, DictData> implements DictDataService { |
| | | |
| | | @Resource |
| | | private ApplicationEventPublisher applicationEventPublisher; |
| | | |
| | | @Override |
| | | public boolean save(DictData entity) { |
| | | boolean result = super.save(entity); |
| | | if (result && entity.getDictTypeCode() != null) { |
| | | applicationEventPublisher.publishEvent(new DictDataChangedEvent(this, entity.getDictTypeCode())); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateById(DictData entity) { |
| | | boolean result = super.updateById(entity); |
| | | if (result && entity.getDictTypeCode() != null) { |
| | | applicationEventPublisher.publishEvent(new DictDataChangedEvent(this, entity.getDictTypeCode())); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public boolean removeByIds(Collection<? extends Serializable> list) { |
| | | if (list == null || list.isEmpty()) { |
| | | return true; |
| | | } |
| | | List<DictData> before = listByIds(list); |
| | | boolean result = super.removeByIds(list); |
| | | if (result && before != null) { |
| | | for (String dictTypeCode : before.stream().map(DictData::getDictTypeCode).filter(c -> c != null).distinct().collect(Collectors.toList())) { |
| | | applicationEventPublisher.publishEvent(new DictDataChangedEvent(this, dictTypeCode)); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | } |
| New file |
| | |
| | | -- 8.3 接口未使用字段接入:主单 stationId;明细 planNo、palletId、targetWareHouseId、sourceWareHouseId |
| | | -- 单据内码用 po_code 存储(接口 orderInternalCode),不单独建 order_internal_code 字段 |
| | | -- 若之前已执行过添加 order_internal_code,可先执行:ALTER TABLE man_asn_order DROP COLUMN order_internal_code; |
| | | -- 执行前请确认表 man_asn_order、man_asn_order_item 已存在 |
| | | |
| | | -- 主单 man_asn_order |
| | | ALTER TABLE `man_asn_order` |
| | | ADD COLUMN `station_id` varchar(64) DEFAULT NULL COMMENT '入/出库接驳站点'; |
| | | |
| | | -- 明细 man_asn_order_item |
| | | ALTER TABLE `man_asn_order_item` |
| | | ADD COLUMN `plan_no` varchar(64) DEFAULT NULL COMMENT '计划跟踪号' AFTER `batch`, |
| | | ADD COLUMN `pallet_id` varchar(64) DEFAULT NULL COMMENT '托盘码' AFTER `plan_no`, |
| | | ADD COLUMN `target_ware_house_id` varchar(64) DEFAULT NULL COMMENT '建议入库仓库' AFTER `pallet_id`, |
| | | ADD COLUMN `source_ware_house_id` varchar(64) DEFAULT NULL COMMENT '建议出库仓库' AFTER `target_ware_house_id`; |
| | |
| | | -- 出库历史单菜单:与「入库历史单」同级,共用 asnOrderLog 接口,仅前端 resource=outStockOrderLog、固定 type=out |
| | | -- 出库历史单菜单:与「入库历史单」同级,共用 asnOrderLog 接口,图标与出库通知单一致(HorizontalRule) |
| | | -- 执行前需已存在 component='asnOrderLog' 的菜单,否则本 INSERT 不会插入任何行 |
| | | INSERT INTO `sys_menu` (`id`, `name`, `parent_id`, `parent_name`, `path`, `path_name`, `route`, `component`, `brief`, `code`, `type`, `authority`, `icon`, `sort`, `meta`, `tenant_id`, `status`, `deleted`, `create_time`, `create_by`, `update_time`, `update_by`, `memo`) |
| | | SELECT 52, 'menu.outStockOrderLog', m.parent_id, m.parent_name, CONCAT(IFNULL(m.path,''), ',52'), 'menu.outStockOrderLog', '/histories/outStockOrderLog', 'outStockOrderLog', NULL, NULL, 0, NULL, 'Outbox', 2, NULL, 1, 1, 0, NULL, NULL, NULL, NULL, NULL |
| | | SELECT 52, 'menu.outStockOrderLog', m.parent_id, m.parent_name, CONCAT(IFNULL(m.path,''), ',52'), 'menu.outStockOrderLog', '/histories/outStockOrderLog', 'outStockOrderLog', NULL, NULL, 0, NULL, 'HorizontalRule', 2, NULL, 1, 1, 0, NULL, NULL, NULL, NULL, NULL |
| | | FROM `sys_menu` m WHERE m.component = 'asnOrderLog' LIMIT 1; |
| | | |
| | | -- 出库历史单列表权限(与入库历史单共用 manager:asnOrderLog:list,有该权限即可访问两个菜单) |
| New file |
| | |
| | | -- 订单类型字典:1 出库单 2 入库单 3 调拨单 等,可在【系统-数据字典】中维护 |
| | | -- value = 内部编码(out/in/transfer),label = 显示名称;API 的 orderType 1/2/3 在代码中映射为 out/in/transfer |
| | | |
| | | INSERT INTO `sys_dict_type` (`code`, `name`, `description`, `status`, `deleted`, `tenant_id`, `create_by`, `create_time`, `update_by`, `update_time`, `memo`) |
| | | SELECT 'sys_order_type', '订单类型', '出库单/入库单/调拨单等,与 wk_order.type 对应', 1, 0, 1, NULL, NOW(), NULL, NOW(), NULL |
| | | FROM DUAL |
| | | WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE code = 'sys_order_type' LIMIT 1); |
| | | |
| | | INSERT INTO `sys_dict_data` (`dict_type_id`, `dict_type_code`, `value`, `label`, `sort`, `status`, `deleted`, `tenant_id`, `create_by`, `create_time`, `update_by`, `update_time`, `memo`) |
| | | SELECT t.id, 'sys_order_type', v.val, v.lbl, v.srt, 1, 0, 1, NULL, NOW(), NULL, NOW(), NULL |
| | | FROM sys_dict_type t |
| | | CROSS JOIN ( |
| | | SELECT 'out' AS val, '出库单' AS lbl, 1 AS srt |
| | | UNION ALL SELECT 'in', '入库单', 2 |
| | | UNION ALL SELECT 'transfer', '调拨单', 3 |
| | | UNION ALL SELECT 'revise', '库存调整', 4 |
| | | UNION ALL SELECT 'check', '盘点单', 5 |
| | | ) v |
| | | WHERE t.code = 'sys_order_type' |
| | | AND NOT EXISTS (SELECT 1 FROM sys_dict_data d WHERE d.dict_type_code = 'sys_order_type' AND d.value = v.val LIMIT 1); |
| New file |
| | |
| | | -- 订单业务类型字典:与 OrderWorkType 枚举对应,可在【系统-数据字典】中维护 |
| | | -- 执行前请确认 sys_dict_type、sys_dict_data 表存在;表结构需含 create_by/create_time 等(与实体一致) |
| | | -- value = 类型编码(如 1、2),label = 显示名称(如 采购入库单) |
| | | |
| | | -- 1. 字典类型(若已存在 sys_order_work_type 可跳过本段) |
| | | INSERT INTO `sys_dict_type` (`code`, `name`, `description`, `status`, `deleted`, `tenant_id`, `create_by`, `create_time`, `update_by`, `update_time`, `memo`) |
| | | SELECT 'sys_order_work_type', '订单业务类型', '入库/出库/调拨等业务类型,与 wk_order.wk_type 对应', 1, 0, 1, NULL, NOW(), NULL, NOW(), NULL |
| | | FROM DUAL |
| | | WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE code = 'sys_order_work_type' LIMIT 1); |
| | | |
| | | -- 2. 字典数据(dict_type_id 取上一步类型的 id;若表结构为 id 自增可去掉 id 列) |
| | | INSERT INTO `sys_dict_data` (`dict_type_id`, `dict_type_code`, `value`, `label`, `sort`, `status`, `deleted`, `tenant_id`, `create_by`, `create_time`, `update_by`, `update_time`, `memo`) |
| | | SELECT t.id, 'sys_order_work_type', v.val, v.lbl, v.srt, 1, 0, 1, NULL, NOW(), NULL, NOW(), NULL |
| | | FROM sys_dict_type t |
| | | CROSS JOIN ( |
| | | SELECT '1' AS val, '采购入库单' AS lbl, 1 AS srt UNION ALL SELECT '2','生产入库单',2 UNION ALL SELECT '3','领料退回入库单',3 UNION ALL SELECT '4','销售退回入库单',4 UNION ALL SELECT '5','其它入库单',5 |
| | | UNION ALL SELECT '6','调拔入库单',6 UNION ALL SELECT '7','库存调整单',7 UNION ALL SELECT '8','调拔入库单(项目)',8 UNION ALL SELECT '11','销售出库单',11 UNION ALL SELECT '12','领料出库单',12 |
| | | UNION ALL SELECT '13','采购退回出库单',13 UNION ALL SELECT '14','其它出库单',14 UNION ALL SELECT '15','库存出库',15 UNION ALL SELECT '16','盘点出库',16 UNION ALL SELECT '17','调拔出库单',17 |
| | | UNION ALL SELECT '18','生产补料',18 UNION ALL SELECT '19','外发加工',19 |
| | | ) v |
| | | WHERE t.code = 'sys_order_work_type' |
| | | AND NOT EXISTS (SELECT 1 FROM sys_dict_data d WHERE d.dict_type_code = 'sys_order_work_type' AND d.value = v.val LIMIT 1); |
| New file |
| | |
| | | -- 波次管理菜单:若 sys_menu 中已存在 component='wave' 的菜单则跳过 |
| | | -- 执行后需在【系统管理 -> 角色管理 -> 分配权限】中为对应角色勾选「波次管理」并保存,菜单才会在侧栏显示 |
| | | |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `parent_name`, `path`, `path_name`, `route`, `component`, `brief`, `code`, `type`, `authority`, `icon`, `sort`, `meta`, `tenant_id`, `status`, `deleted`, `create_time`, `create_by`, `update_time`, `update_by`, `memo`) |
| | | SELECT 'menu.wave', 0, NULL, '', '', '/orders/wave', 'wave', NULL, NULL, 0, NULL, 'Waves', 0, NULL, 1, 1, 0, NOW(), NULL, NOW(), NULL, '波次管理' |
| | | FROM DUAL |
| | | WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `component` = 'wave' AND `type` = 0 LIMIT 1); |
| | | |
| | | -- 波次管理-列表查询权限(访问波次列表页和接口需要) |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `path`, `path_name`, `route`, `component`, `type`, `authority`, `sort`, `tenant_id`, `status`, `deleted`) |
| | | SELECT 'Query 波次', m.id, CONCAT(IFNULL(m.path,''), ',', m.id), NULL, NULL, NULL, 1, 'manager:wave:list', 0, 1, 1, 0 |
| | | FROM `sys_menu` m WHERE m.component = 'wave' AND m.type = 0 LIMIT 1; |
| | | |
| | | -- 波次管理-保存权限 |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `path`, `type`, `authority`, `sort`, `tenant_id`, `status`, `deleted`) |
| | | SELECT 'Create 波次', m.id, CONCAT(IFNULL(m.path,''), ',', m.id), 1, 'manager:wave:save', 1, 1, 1, 0 |
| | | FROM `sys_menu` m WHERE m.component = 'wave' AND m.type = 0 LIMIT 1; |
| | | |
| | | -- 波次管理-更新权限 |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `path`, `type`, `authority`, `sort`, `tenant_id`, `status`, `deleted`) |
| | | SELECT 'Update 波次', m.id, CONCAT(IFNULL(m.path,''), ',', m.id), 1, 'manager:wave:update', 2, 1, 1, 0 |
| | | FROM `sys_menu` m WHERE m.component = 'wave' AND m.type = 0 LIMIT 1; |
| | | |
| | | -- 波次管理-删除权限 |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `path`, `type`, `authority`, `sort`, `tenant_id`, `status`, `deleted`) |
| | | SELECT 'Delete 波次', m.id, CONCAT(IFNULL(m.path,''), ',', m.id), 1, 'manager:wave:remove', 3, 1, 1, 0 |
| | | FROM `sys_menu` m WHERE m.component = 'wave' AND m.type = 0 LIMIT 1; |
| | | |
| | | -- 波次明细-列表权限(进入波次明细需 manager:waveItem:list,若接口有要求可再加) |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `path`, `type`, `authority`, `sort`, `tenant_id`, `status`, `deleted`) |
| | | SELECT 'Query 波次明细', m.id, CONCAT(IFNULL(m.path,''), ',', m.id), 1, 'manager:waveItem:list', 4, 1, 1, 0 |
| | | FROM `sys_menu` m WHERE m.component = 'wave' AND m.type = 0 LIMIT 1; |
| | | |
| | | -- 波次明细-更新权限(下发任务等操作) |
| | | INSERT INTO `sys_menu` (`name`, `parent_id`, `path`, `type`, `authority`, `sort`, `tenant_id`, `status`, `deleted`) |
| | | SELECT 'Update 波次明细', m.id, CONCAT(IFNULL(m.path,''), ',', m.id), 1, 'manager:waveItem:update', 5, 1, 1, 0 |
| | | FROM `sys_menu` m WHERE m.component = 'wave' AND m.type = 0 LIMIT 1; |