| | |
| | | }, |
| | | button: { |
| | | edit: "Edit", |
| | | detail: "Details", |
| | | histories: "Histories", |
| | | }, |
| | | field: { |
| | | id: 'ID', |
| | |
| | | partners: 'Strategic Partners', |
| | | }, |
| | | list: { |
| | | titles: { |
| | | stockInfo: 'Stock Details', |
| | | }, |
| | | empty: { |
| | | tip: 'No data to display', |
| | | } |
| | |
| | | outStockItem: 'Out Stock Item', |
| | | inStockPoces: 'In Stock Pocess', |
| | | outStockPoces: 'Out Stock Pocess', |
| | | warehouseStock: 'Instant Inventory', |
| | | deviceBind: 'Device Bind', |
| | | tasks: 'Tasks', |
| | | wave: 'Wave Manage', |
| | |
| | | model: "model", |
| | | fieldsIndex: "fieldsIndex", |
| | | }, |
| | | warehouseStock: { |
| | | locId: "Loc ID", |
| | | locCode: "Code", |
| | | warehouse: 'Warehouse', |
| | | orderId: "Order Id", |
| | | type: "Type", |
| | | orderItemId: "Order Detail ID", |
| | | wkType: "Work Type", |
| | | matnrId: "Matnr Id", |
| | | maktx: "Mats Name", |
| | | unit: 'Unit', |
| | | anfme: 'Stock Qty', |
| | | matnrCode: "Matnr Code", |
| | | workQty: 'Work Qty', |
| | | qty: 'Non Stock Qty', |
| | | splrId: 'supplier', |
| | | batch: "Supplier Batch", |
| | | spec: "Spec", |
| | | model: "Model", |
| | | fieldsIndex: "Fields Index", |
| | | }, |
| | | deviceBind: { |
| | | currentRow: "currentRow", |
| | | startRow: "startRow", |
| | |
| | | }, |
| | | button: { |
| | | edit: "编辑", |
| | | detail: "库存明细", |
| | | histories: "流水记录", |
| | | }, |
| | | field: { |
| | | id: 'ID', |
| | |
| | | partners: '战略合作', |
| | | }, |
| | | list: { |
| | | titles: { |
| | | stockInfo: '库存明细', |
| | | }, |
| | | |
| | | empty: { |
| | | tip: '没有可显示数据', |
| | | } |
| | |
| | | outStockItem: '出库单明细', |
| | | inStockPoces: '入库管理', |
| | | outStockPoces: '出库管理', |
| | | warehouseStock: '即时库存', |
| | | deviceBind: '设备绑定', |
| | | tasks: '任务管理', |
| | | wave: '波次管理', |
| | |
| | | model: "型号", |
| | | fieldsIndex: "动态索引", |
| | | }, |
| | | warehouseStock: { |
| | | locId: "库位ID", |
| | | locCode: "库位", |
| | | warehouse: '仓库', |
| | | orderId: "订单ID", |
| | | type: "单据类型", |
| | | orderItemId: "单据明细ID", |
| | | wkType: "业务类型", |
| | | matnrId: "物料ID", |
| | | maktx: "物料名称", |
| | | unit: '单位', |
| | | anfme: '库存数量', |
| | | matnrCode: "物料编码", |
| | | workQty: '执行数', |
| | | qty: '不可用库存', |
| | | splrId: '供应商', |
| | | batch: "供应商批次", |
| | | splrBatch: "供应商批次", |
| | | spec: "规格", |
| | | model: "型号", |
| | | fieldsIndex: "动态索引", |
| | | }, |
| | | deviceBind: { |
| | | currentRow: "当前排号", |
| | | startRow: "起始排号", |
| | |
| | | import wave from './orders/wave'; |
| | | import locItem from './locItem' |
| | | import basStation from './basicInfo/basStation'; |
| | | import warehouseStock from './statistics/stockManage'; |
| | | |
| | | const ResourceContent = (node) => { |
| | | switch (node.component) { |
| | |
| | | return warehouseAreas; |
| | | case 'warehouseAreasItem': |
| | | return warehouseAreasItem; |
| | | case 'warehouseStock': |
| | | return warehouseStock; |
| | | case 'loc': |
| | | return loc; |
| | | case 'container': |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; |
| | | import request from '@/utils/request'; |
| | | import { |
| | | SavedQueriesList, |
| | | FilterLiveSearch, |
| | | useNotify, |
| | | useListContext, |
| | | SearchInput |
| | | } from 'react-admin'; |
| | | import BookmarkIcon from '@mui/icons-material/BookmarkBorder'; |
| | | import { Box, Typography, Card, CardContent, useTheme, Input } from '@mui/material'; |
| | | import { RichTreeView } from "@mui/x-tree-view/RichTreeView"; |
| | | import { TreeItem2 } from "@mui/x-tree-view/TreeItem2"; |
| | | |
| | | |
| | | const MatListAside = () => { |
| | | const theme = useTheme(); |
| | | const notify = useNotify(); |
| | | const { setFilters } = useListContext(); // 获取列表上下文 |
| | | const [selectedOption, setSelectedOption] = useState(null); |
| | | const [treeData, setTreeData] = useState([]); |
| | | const [defaultIds, setDefaultIds] = useState(['65']); |
| | | const [condition, setCondition] = useState(''); |
| | | |
| | | const haveChildren = (item) => { |
| | | if (Array.isArray(item)) { |
| | | return item.map((k) => haveChildren(k)); |
| | | } |
| | | |
| | | if (item && typeof item === 'object') { |
| | | if (item.id !== undefined) { |
| | | item.id = item.id.toString(); |
| | | } |
| | | |
| | | if (item.children && Array.isArray(item.children)) { |
| | | item.children = haveChildren(item.children); |
| | | } |
| | | } |
| | | |
| | | return item; |
| | | }; |
| | | useEffect(() => { |
| | | http() |
| | | }, [condition]); |
| | | |
| | | const http = () => { |
| | | request.post('/matnrGroup/tree', { condition }) |
| | | .then(res => { |
| | | if (res?.data?.code === 200) { |
| | | let data = res.data.data; |
| | | let items = haveChildren(data) |
| | | setTreeData(items) |
| | | setDefaultIds([items.at(0).id]) |
| | | |
| | | } else { |
| | | notify(res.data.msg); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | notify('Error fetching tree data'); |
| | | }); |
| | | |
| | | } |
| | | const handleNodeSelect = (event, nodeId) => { |
| | | setFilters({ groupId: nodeId }); |
| | | }; |
| | | const handleSearch = (e) => { |
| | | setCondition(e.target.value) |
| | | }; |
| | | |
| | | |
| | | const CustomCheckbox = React.forwardRef(function CustomCheckbox(props, ref) { |
| | | return <input type="checkbox" ref={ref} {...props} />; |
| | | }); |
| | | |
| | | const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { |
| | | return ( |
| | | <TreeItem2 |
| | | {...props} |
| | | ref={ref} |
| | | slots={{ |
| | | checkbox: CustomCheckbox, |
| | | }} |
| | | /> |
| | | ); |
| | | }); |
| | | |
| | | |
| | | return ( |
| | | <Card |
| | | sx={{ |
| | | order: -1, |
| | | mr: 2, |
| | | mt: 8, |
| | | alignSelf: 'flex-start', |
| | | border: theme.palette.mode === 'light' && '1px solid #e0e0e3', |
| | | width: 250, |
| | | minWidth: 150, |
| | | height: `100%`, |
| | | }} |
| | | > |
| | | <CardContent> |
| | | <Input |
| | | placeholder="搜索物料分组" |
| | | sx={{ '--Input-focused': 1, marginBottom: '10px' }} |
| | | onChange={handleSearch} |
| | | /> |
| | | <RichTreeView |
| | | defaultExpandedItems={defaultIds} |
| | | expansionTrigger="iconContainer" |
| | | items={treeData} |
| | | slots={CustomTreeItem} |
| | | onItemClick={handleNodeSelect} // 监听节点点击事件 |
| | | /> |
| | | |
| | | </CardContent> |
| | | </Card> |
| | | ) |
| | | } |
| | | |
| | | export default MatListAside; |
New file |
| | |
| | | import { Dialog, DialogActions, DialogContent, DialogTitle, Box } from "@mui/material"; |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { |
| | | List, |
| | | DatagridConfigurable, |
| | | SearchInput, |
| | | TopToolbar, |
| | | Button, |
| | | SelectColumnsButton, |
| | | EditButton, |
| | | FilterButton, |
| | | CreateButton, |
| | | ExportButton, |
| | | BulkDeleteButton, |
| | | WrapperField, |
| | | Toolbar, |
| | | useRecordContext, |
| | | useTranslate, |
| | | useNotify, |
| | | useListContext, |
| | | FunctionField, |
| | | TextField, |
| | | NumberField, |
| | | DateField, |
| | | BooleanField, |
| | | ReferenceField, |
| | | TextInput, |
| | | DateTimeInput, |
| | | DateInput, |
| | | SelectInput, |
| | | NumberInput, |
| | | ReferenceInput, |
| | | ReferenceArrayInput, |
| | | AutocompleteInput, |
| | | DeleteButton, |
| | | Form, |
| | | SaveButton, |
| | | useRefresh, |
| | | useGetList, |
| | | } from 'react-admin'; |
| | | import DialogCloseButton from "../../components/DialogCloseButton"; |
| | | import { styled } from '@mui/material/styles'; |
| | | import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; |
| | | import { Grid, Stack, width } from "@mui/system"; |
| | | import request from '@/utils/request'; |
| | | import SaveIcon from '@mui/icons-material/Save'; |
| | | import CheckCircleIcon from '@mui/icons-material/CheckCircle'; |
| | | |
| | | const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ |
| | | '& .css-1vooibu-MuiSvgIcon-root': { |
| | | height: '.9em' |
| | | }, |
| | | '& .RaDatagrid-row': { |
| | | cursor: 'auto' |
| | | }, |
| | | '& .status': { |
| | | width: 90 |
| | | }, |
| | | })); |
| | | |
| | | const WarehouseHistories = (props) => { |
| | | const { open, setOpen, record } = props; |
| | | const translate = useTranslate(); |
| | | const [params, setParams] = useState({}); |
| | | const [item, setItem] = useState({}); |
| | | const [poItemDialog, setPoItemDialog] = useState(false); |
| | | const [drawerVal, setDrawerVal] = useState(false); |
| | | const refresh = useRefresh(); |
| | | |
| | | const handleClose = (event, reason) => { |
| | | if (reason !== "backdropClick") { |
| | | setOpen(false); |
| | | } |
| | | }; |
| | | // const CustomFilter = () => { |
| | | // const { filterValues, setFilters, refetch } = useListContext('deliveryItem'); |
| | | // const [formValues, setFormValues] = useState(filterValues); |
| | | // const handleChange = (event) => { |
| | | // if (event.target == undefined || event.target == null) { return } |
| | | // setFormValues(formValues => ({ |
| | | // ...formValues, |
| | | // [event.target.name]: event.target.value |
| | | // })); |
| | | // }; |
| | | |
| | | // const handleSubmit = (event) => { |
| | | // setParams(formValues) |
| | | // }; |
| | | |
| | | // return ( |
| | | // <Box sx={{ width: '100%', margin: 1, marginBottom: 8, "& .MuiDialogActions-root": { padding: 0 } }}> |
| | | // <Form> |
| | | // <Grid container rowSpacing={2} columnSpacing={2} sx={{ padding: 2 }}> |
| | | // <Stack> |
| | | // <TextInput |
| | | // source="condition" |
| | | // label="common.action.search" |
| | | // resettable |
| | | // defaultValue={params?.condition} |
| | | // onChange={handleChange} /> |
| | | // </Stack> |
| | | // </Grid> |
| | | // <DialogActions> |
| | | // <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > |
| | | // <SaveButton onClick={handleSubmit} label={"toolbar.query"} /> |
| | | // </Toolbar> |
| | | // </DialogActions> |
| | | // </Form> |
| | | // </Box> |
| | | // ); |
| | | // }; |
| | | return ( |
| | | <Box> |
| | | <Dialog |
| | | open={open} |
| | | onClose={handleClose} |
| | | aria-labelledby="form-dialog-title" |
| | | aria-hidden |
| | | fullWidth |
| | | disableRestoreFocus |
| | | maxWidth="lg" |
| | | > |
| | | <DialogTitle id="form-dialog-title" sx={{ |
| | | position: 'sticky', |
| | | top: 0, |
| | | backgroundColor: 'background.paper', |
| | | zIndex: 1000 |
| | | }}> |
| | | <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> |
| | | <DialogCloseButton onClose={handleClose} /> |
| | | </Box> |
| | | </DialogTitle> |
| | | <Grid container rowSpacing={2} columnSpacing={2}> |
| | | <DialogContent> |
| | | <Grid item sx={24}> |
| | | <List |
| | | storeKey="selectPurchase" |
| | | resource="purchase/filters" |
| | | sx={{ |
| | | flexGrow: 1, |
| | | marginTop: 8, |
| | | height: 500, |
| | | transition: (theme) => |
| | | theme.transitions.create(['all'], { |
| | | duration: theme.transitions.duration.enteringScreen, |
| | | }), |
| | | marginRight: 0, |
| | | }} |
| | | // filters={<CustomFilter />} |
| | | queryOptions={{ meta: { ...params } }} |
| | | empty={false} |
| | | sort={{ field: "create_time", order: "desc" }} |
| | | actions={false} |
| | | perPage={DEFAULT_PAGE_SIZE} |
| | | > |
| | | <StyledDatagrid |
| | | preferenceKey='selectPurchase' |
| | | bulkActionButtons={ |
| | | <> |
| | | <ConfirmSelectButton |
| | | setOpen={setOpen} |
| | | setPoItemDialog={setPoItemDialog} |
| | | setItem={setItem} |
| | | mutationMode="pessimistic" /> |
| | | </> |
| | | } |
| | | rowClick={false} |
| | | expand={false} |
| | | expandSingle={true} |
| | | omit={['id', 'createTime', 'createBy', 'channel', 'platCode', 'memo', 'channel', 'startTime', 'workQty', 'endTime']} |
| | | > |
| | | <NumberField source="id" /> |
| | | <TextField source="code" label="table.field.purchase.code" /> |
| | | <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" /> |
| | | <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 /> |
| | | <DateField source="startTime" label="table.field.purchase.startTime" showTime /> |
| | | <DateField source="endTime" label="table.field.purchase.endTime" showTime /> |
| | | <TextField source="project" label="table.field.purchase.project" /> |
| | | <TextField source="memo" label="common.field.memo" sortable={false} /> |
| | | </StyledDatagrid> |
| | | </List> |
| | | </Grid> |
| | | </DialogContent> |
| | | </Grid> |
| | | </Dialog > |
| | | </Box> |
| | | ) |
| | | } |
| | | |
| | | export default WarehouseHistories; |
| | | |
| | | |
| | | const ConfirmSelectButton = ({ setOpen, setPoItemDialog, setItem }) => { |
| | | const { selectedIds, onUnselectItems } = useListContext(); |
| | | const confirmSelect = async (event) => { |
| | | setItem(selectedIds[0]) |
| | | onUnselectItems(); |
| | | setPoItemDialog(true) |
| | | setOpen(false); |
| | | } |
| | | |
| | | return ( |
| | | <Button label={"toolbar.confirm"} variant="contained" color="primary" size="medium" startIcon={<SaveIcon />} onClick={confirmSelect} /> |
| | | ) |
| | | } |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { |
| | | CreateBase, |
| | | useTranslate, |
| | | TextInput, |
| | | NumberInput, |
| | | BooleanInput, |
| | | DateInput, |
| | | SaveButton, |
| | | SelectInput, |
| | | ReferenceInput, |
| | | ReferenceArrayInput, |
| | | AutocompleteInput, |
| | | Toolbar, |
| | | required, |
| | | useDataProvider, |
| | | useNotify, |
| | | Form, |
| | | useCreateController, |
| | | } from 'react-admin'; |
| | | import { |
| | | Dialog, |
| | | DialogActions, |
| | | DialogContent, |
| | | DialogTitle, |
| | | Stack, |
| | | Grid, |
| | | Box, |
| | | } from '@mui/material'; |
| | | import DialogCloseButton from "../../components/DialogCloseButton"; |
| | | import StatusSelectInput from "../../components/StatusSelectInput"; |
| | | import MemoInput from "../../components/MemoInput"; |
| | | |
| | | const WarehouseStockCreate = (props) => { |
| | | const { open, setOpen } = props; |
| | | |
| | | const translate = useTranslate(); |
| | | const notify = useNotify(); |
| | | |
| | | const handleClose = (event, reason) => { |
| | | if (reason !== "backdropClick") { |
| | | setOpen(false); |
| | | } |
| | | }; |
| | | |
| | | const handleSuccess = async (data) => { |
| | | setOpen(false); |
| | | notify('common.response.success'); |
| | | }; |
| | | |
| | | const handleError = async (error) => { |
| | | notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } }); |
| | | }; |
| | | |
| | | return ( |
| | | <> |
| | | <CreateBase |
| | | record={{}} |
| | | transform={(data) => { |
| | | return data; |
| | | }} |
| | | mutationOptions={{ onSuccess: handleSuccess, onError: handleError }} |
| | | > |
| | | <Dialog |
| | | open={open} |
| | | onClose={handleClose} |
| | | aria-labelledby="form-dialog-title" |
| | | fullWidth |
| | | disableRestoreFocus |
| | | maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' |
| | | > |
| | | <Form> |
| | | <DialogTitle id="form-dialog-title" sx={{ |
| | | position: 'sticky', |
| | | top: 0, |
| | | backgroundColor: 'background.paper', |
| | | zIndex: 1000 |
| | | }} |
| | | > |
| | | {translate('create.title')} |
| | | <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> |
| | | <DialogCloseButton onClose={handleClose} /> |
| | | </Box> |
| | | </DialogTitle> |
| | | <DialogContent sx={{ mt: 2 }}> |
| | | <Grid container rowSpacing={2} columnSpacing={2}> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.locId" |
| | | source="locId" |
| | | autoFocus |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.locCode" |
| | | source="locCode" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.type" |
| | | source="type" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.orderItemId" |
| | | source="orderItemId" |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.wkType" |
| | | source="wkType" |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.matnrId" |
| | | source="matnrId" |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.maktx" |
| | | source="maktx" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.matnrCode" |
| | | source="matnrCode" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.unit" |
| | | source="unit" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.anfme" |
| | | source="anfme" |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.qty" |
| | | source="qty" |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <NumberInput |
| | | label="table.field.locItem.workQty" |
| | | source="workQty" |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.batch" |
| | | source="batch" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.spec" |
| | | source="spec" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.model" |
| | | source="model" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6} display="flex" gap={1}> |
| | | <TextInput |
| | | label="table.field.locItem.fieldsIndex" |
| | | source="fieldsIndex" |
| | | parse={v => v} |
| | | /> |
| | | </Grid> |
| | | </Grid> |
| | | </DialogContent> |
| | | <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> |
| | | <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > |
| | | <SaveButton /> |
| | | </Toolbar> |
| | | </DialogActions> |
| | | </Form> |
| | | </Dialog> |
| | | </CreateBase> |
| | | </> |
| | | ) |
| | | } |
| | | |
| | | export default WarehouseStockCreate; |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | 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 { Stack, Grid, Box, Typography } from '@mui/material'; |
| | | import * as Common from '@/utils/common'; |
| | | import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; |
| | | import EditBaseAside from "../../components/EditBaseAside"; |
| | | import CustomerTopToolBar from "../../components/EditTopToolBar"; |
| | | import MemoInput from "../../components/MemoInput"; |
| | | import StatusSelectInput from "../../components/StatusSelectInput"; |
| | | |
| | | const FormToolbar = () => { |
| | | const { getValues } = useFormContext(); |
| | | |
| | | return ( |
| | | <Toolbar sx={{ justifyContent: 'end' }}> |
| | | <SaveButton /> |
| | | {/* <DeleteButton mutationMode="optimistic" /> */} |
| | | </Toolbar> |
| | | ) |
| | | } |
| | | |
| | | const WarehouseStockEdit = () => { |
| | | const translate = useTranslate(); |
| | | |
| | | return ( |
| | | <Edit |
| | | redirect="list" |
| | | mutationMode={EDIT_MODE} |
| | | actions={<CustomerTopToolBar />} |
| | | aside={<EditBaseAside />} |
| | | > |
| | | <SimpleForm |
| | | shouldUnregister |
| | | warnWhenUnsavedChanges |
| | | toolbar={<FormToolbar />} |
| | | mode="onTouched" |
| | | defaultValues={{}} |
| | | // validate={(values) => { }} |
| | | > |
| | | <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}> |
| | | <Grid item xs={14} md={10}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.main')} |
| | | </Typography> |
| | | <Stack direction='row' gap={2}> |
| | | <NumberInput |
| | | label="table.field.locItem.locId" |
| | | source="locId" |
| | | autoFocus |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.locCode" |
| | | source="locCode" |
| | | parse={v => v} |
| | | /> |
| | | <NumberInput |
| | | label="table.field.locItem.orderId" |
| | | source="orderId" |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.type" |
| | | source="type$" |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <NumberInput |
| | | label="table.field.locItem.orderItemId" |
| | | source="orderItemId" |
| | | /> |
| | | <NumberInput |
| | | label="table.field.locItem.wkType" |
| | | source="wkType" |
| | | /> |
| | | <NumberInput |
| | | label="table.field.locItem.matnrId" |
| | | source="matnrId" |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.locItem.maktx" |
| | | source="maktx" |
| | | parse={v => v} |
| | | /> |
| | | |
| | | <TextInput |
| | | label="table.field.locItem.matnrCode" |
| | | source="matnrCode" |
| | | parse={v => v} |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.trackCode" |
| | | source="trackCode" |
| | | parse={v => v} |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.unit" |
| | | source="unit" |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <NumberInput |
| | | label="table.field.locItem.anfme" |
| | | source="anfme" |
| | | /> |
| | | <NumberInput |
| | | label="table.field.locItem.qty" |
| | | source="qty" |
| | | /> |
| | | <NumberInput |
| | | label="table.field.locItem.workQty" |
| | | source="workQty" |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.batch" |
| | | source="batch" |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.locItem.splrBatch" |
| | | source="splrBatch" |
| | | parse={v => v} |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.spec" |
| | | source="spec" |
| | | parse={v => v} |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.model" |
| | | source="model" |
| | | parse={v => v} |
| | | /> |
| | | <TextInput |
| | | label="table.field.locItem.fieldsIndex" |
| | | source="fieldsIndex" |
| | | parse={v => v} |
| | | /> |
| | | </Stack> |
| | | |
| | | </Grid> |
| | | <Grid item xs={10} md={2}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.common')} |
| | | </Typography> |
| | | <StatusSelectInput /> |
| | | <Box mt="2em" /> |
| | | <MemoInput /> |
| | | </Grid> |
| | | </Grid> |
| | | </SimpleForm> |
| | | </Edit > |
| | | ) |
| | | } |
| | | |
| | | export default WarehouseStockEdit; |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { |
| | | CreateBase, |
| | | useTranslate, |
| | | TextInput, |
| | | NumberInput, |
| | | BooleanInput, |
| | | DateInput, |
| | | SaveButton, |
| | | SelectInput, |
| | | ReferenceInput, |
| | | ReferenceArrayInput, |
| | | AutocompleteInput, |
| | | Toolbar, |
| | | required, |
| | | useDataProvider, |
| | | useNotify, |
| | | Form, |
| | | useCreateController, |
| | | useListContext, |
| | | useRefresh, |
| | | } from 'react-admin'; |
| | | import { |
| | | Dialog, |
| | | DialogActions, |
| | | DialogContent, |
| | | DialogTitle, |
| | | Stack, |
| | | Grid, |
| | | TextField, |
| | | Box, |
| | | Button, |
| | | Paper, |
| | | TableContainer, |
| | | Table, |
| | | TableHead, |
| | | TableBody, |
| | | TableRow, |
| | | TableCell, |
| | | Tooltip, |
| | | IconButton, |
| | | styled, |
| | | Select, |
| | | MenuItem |
| | | |
| | | } from '@mui/material'; |
| | | import DialogCloseButton from "../../components/DialogCloseButton"; |
| | | import StatusSelectInput from "../../components/StatusSelectInput"; |
| | | import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; |
| | | import SaveIcon from '@mui/icons-material/Save'; |
| | | import request from '@/utils/request'; |
| | | import { Add, Edit, Delete } from '@mui/icons-material'; |
| | | import _, { set } from 'lodash'; |
| | | import { DataGrid, useGridApiRef, GRID_DATE_COL_DEF, GRID_DATETIME_COL_DEF, getGridDateOperators, useGridApiContext } from '@mui/x-data-grid'; |
| | | import { LocalizationProvider, DatePicker, DateTimePicker } from '@mui/x-date-pickers'; |
| | | import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; |
| | | import DictionarySelect from "../../components/DictionarySelect"; |
| | | import DictSelect from "../../components/DictSelect"; |
| | | import { 'zhCN' as locale } from 'date-fns/locale'; |
| | | import { format, } from 'date-fns'; |
| | | import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; |
| | | |
| | | const WarehouseStockInfo = (props) => { |
| | | const { open, setOpen, billReload, record } = props; |
| | | const translate = useTranslate(); |
| | | const notify = useNotify(); |
| | | const refresh = useRefresh(); |
| | | const [disabled, setDisabled] = useState(false) |
| | | const [createDialog, setCreateDialog] = useState(false); |
| | | const tableRef = useRef(); |
| | | |
| | | useEffect(() => { |
| | | if (open && record !== 0) { |
| | | requestGetBody() |
| | | } |
| | | setDisabled(false) |
| | | }, [open]) |
| | | |
| | | const handleClose = (event, reason) => { |
| | | if (reason !== "backdropClick") { |
| | | setOpen(false); |
| | | refresh(); |
| | | setTableData([]) |
| | | } |
| | | }; |
| | | |
| | | |
| | | const [tabelData, setTableData] = useState([]); |
| | | |
| | | const resetData = () => { |
| | | setTableData([]) |
| | | } |
| | | |
| | | const setFinally = () => { |
| | | const rows = tableRef.current.state.editRows; |
| | | for (const key in rows) { |
| | | const find = tabelData.find(item => item.id === +key); |
| | | find.anfme = rows[key].anfme.value; |
| | | } |
| | | setTableData([...tabelData]); |
| | | } |
| | | |
| | | const handleSubmit = async () => { |
| | | setFinally() |
| | | setDisabled(true) |
| | | const parmas = { |
| | | "purchaseId": record, |
| | | "items": tabelData, |
| | | } |
| | | const res = await request.post(`/asnOrder/purchases/save`, parmas); |
| | | if (res?.data?.code === 200) { |
| | | notify(res.data.msg); |
| | | } else { |
| | | notify(res.data.msg); |
| | | } |
| | | setOpen(false); |
| | | refresh(); |
| | | resetData() |
| | | setDisabled(false) |
| | | }; |
| | | |
| | | const requestGetBody = async () => { |
| | | const res = await request.post(`warehouse/stock/page`, { matnrCode: record }); |
| | | if (res?.data?.code === 200) { |
| | | setTableData(res.data.data.records) |
| | | } else { |
| | | notify(res.data.msg); |
| | | } |
| | | } |
| | | |
| | | const [selectedRows, setSelectedRows] = useState([]); |
| | | |
| | | return ( |
| | | <> |
| | | <Dialog |
| | | open={open} |
| | | onClose={handleClose} |
| | | aria-labelledby="form-dialog-title" |
| | | aria-hidden |
| | | fullWidth |
| | | disableRestoreFocus |
| | | maxWidth="xl" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' |
| | | > |
| | | <DialogTitle id="form-dialog-title" sx={{ |
| | | position: 'sticky', |
| | | top: 0, |
| | | backgroundColor: 'background.paper', |
| | | zIndex: 1000 |
| | | }}> |
| | | {translate('common.list.titles.stockInfo')} |
| | | <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> |
| | | <DialogCloseButton onClose={handleClose} /> |
| | | </Box> |
| | | </DialogTitle> |
| | | <DialogContent sx={{ mt: 2 }}> |
| | | <Box></Box> |
| | | <Box sx={{ mt: 2 }}> |
| | | <AsnOrderModalTable tabelData={tabelData} |
| | | setTableData={setTableData} |
| | | record={record} |
| | | selectedRows={selectedRows} |
| | | setSelectedRows={setSelectedRows} |
| | | tableRef={tableRef} /> |
| | | </Box> |
| | | </DialogContent> |
| | | <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> |
| | | <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > |
| | | <Button disabled={disabled} onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> |
| | | {translate('toolbar.confirm')} |
| | | </Button> |
| | | </Toolbar> |
| | | </DialogActions> |
| | | </Dialog> |
| | | </> |
| | | ) |
| | | } |
| | | |
| | | export default WarehouseStockInfo; |
| | | |
| | | const SelectInputSplrNameEditCell = (params) => { |
| | | const [formData, setFormData] = useState([{}]) |
| | | useEffect(() => { |
| | | getOptions(); |
| | | }, []); |
| | | const getOptions = async () => { |
| | | const parmas = { |
| | | "type": "supplier" |
| | | } |
| | | const { |
| | | data: { code, data, msg }, |
| | | } = await request.post("companys/page", parmas); |
| | | if (code === 200) { |
| | | setFormData(data.records) |
| | | } else { |
| | | notify(msg); |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Select |
| | | value={params.value} |
| | | onChange={(e) => { |
| | | params.api.setEditCellValue({ |
| | | id: params.id, |
| | | field: params.field, |
| | | value: e.target.value, |
| | | }) |
| | | // 找到选中的供应商记录 |
| | | const selectedSupplier = formData.find(supplier => supplier.name === e.target.value); |
| | | |
| | | // 如果找到对应的供应商记录,同时更新splrCode字段 |
| | | if (selectedSupplier) { |
| | | params.api.setEditCellValue({ |
| | | id: params.id, |
| | | field: 'splrCode', |
| | | value: selectedSupplier.id, |
| | | }); |
| | | } |
| | | }} |
| | | fullWidth |
| | | > |
| | | {formData.map(e => { |
| | | return ( |
| | | <MenuItem value={e.name} children={e.name} key={e.id} /> |
| | | ); |
| | | |
| | | })} |
| | | |
| | | </Select> |
| | | ); |
| | | }; |
| | | |
| | | const AsnOrderModalTable = ({ tabelData, setTableData, record, selectedRows, setSelectedRows, tableRef }) => { |
| | | const translate = useTranslate(); |
| | | const notify = useNotify(); |
| | | |
| | | const [columns, setColumns] = useState([ |
| | | { |
| | | field: 'matnrCode', |
| | | headerName: translate('table.field.asnOrderItem.matnrCode'), |
| | | width: 130, |
| | | editable: false, |
| | | }, |
| | | { |
| | | field: 'matnrName', |
| | | headerName: translate('table.field.asnOrderItem.maktx'), |
| | | width: 250, |
| | | editable: false, |
| | | }, |
| | | { |
| | | field: 'splrName', |
| | | headerName: translate('table.field.asnOrderItem.splrName') + "*", |
| | | minWidth: 150, |
| | | flex: 1, |
| | | editable: false, |
| | | renderEditCell: (params) => ( |
| | | <SelectInputSplrNameEditCell {...params} /> |
| | | ), |
| | | }, |
| | | { |
| | | field: 'platItemId', |
| | | headerName: translate('table.field.asnOrderItem.platItemId') + "*", |
| | | minWidth: 100, |
| | | flex: 1, |
| | | editable: false, |
| | | }, |
| | | { |
| | | field: 'anfme', |
| | | headerName: translate('table.field.asnOrderItem.anfme') + "*", |
| | | type: 'number', |
| | | minWidth: 100, |
| | | flex: 1, |
| | | editable: false, |
| | | valueFormatter: (val) => val < 0 ? 0 : val, |
| | | }, |
| | | { |
| | | field: 'qty', |
| | | headerName: translate('table.field.asnOrderItem.qty') + "*", |
| | | type: 'number', |
| | | minWidth: 100, |
| | | flex: 1, |
| | | valueFormatter: (val) => val < 0 ? 0 : val, |
| | | }, |
| | | { |
| | | field: 'unit', |
| | | headerName: translate('table.field.asnOrderItem.stockUnit'), |
| | | minWidth: 100, |
| | | flex: 1, |
| | | editable: false, |
| | | }, |
| | | ]) |
| | | |
| | | let cdata = useRef([]); |
| | | |
| | | useEffect(() => { |
| | | getDynamicFields(); |
| | | }, []); |
| | | |
| | | useEffect(() => { |
| | | cdata.current = tabelData |
| | | }, [tabelData]); |
| | | |
| | | |
| | | const getDynamicFields = async () => { |
| | | const { |
| | | data: { code, data, msg }, |
| | | } = await request.get("/fields/enable/list"); |
| | | if (code === 200) { |
| | | const cols = data.map(el => ({ |
| | | field: el.fields, |
| | | valueGetter: (value, row) => { |
| | | if (value != null && value != undefined) { |
| | | return value; |
| | | } |
| | | if (row.extendFields == null || row.extendFields[el.fields] == null) { |
| | | return '' |
| | | } else { |
| | | return `${row.extendFields[el.fields] == null ? '' : row.extendFields[el.fields]}`; |
| | | } |
| | | }, |
| | | headerName: el.fieldsAlise, |
| | | minWidth: 100, |
| | | flex: 1, |
| | | editable: true |
| | | })) |
| | | setColumns([...columns, ...cols]) |
| | | } else { |
| | | notify(msg); |
| | | } |
| | | } |
| | | |
| | | const processRowUpdate = (newRow, oldRow) => { |
| | | const rows = tabelData.map((r) => |
| | | r.id === newRow.id ? { ...newRow } : r |
| | | ) |
| | | setTableData(rows) |
| | | |
| | | return newRow; |
| | | }; |
| | | |
| | | |
| | | const handleSelectionChange = (ids) => { |
| | | setSelectedRows(ids) |
| | | }; |
| | | |
| | | tableRef.current = useGridApiRef(); |
| | | |
| | | |
| | | return ( |
| | | <div style={{ height: 400, width: '100%' }}> |
| | | <DataGrid |
| | | apiRef={tableRef} |
| | | rows={tabelData} |
| | | columns={columns} |
| | | disableRowSelectionOnClick |
| | | getRowId={(row) => row.id} |
| | | disableColumnFilter |
| | | disableColumnSelector |
| | | disableColumnSorting |
| | | disableMultipleColumnsSorting |
| | | processRowUpdate={processRowUpdate} |
| | | initialState={{ |
| | | pagination: { |
| | | paginationModel: { |
| | | pageSize: 25, |
| | | }, |
| | | }, |
| | | }} |
| | | pageSizeOptions={[10, 25, 50, 100]} |
| | | editMode="row" |
| | | checkboxSelection |
| | | onRowSelectionModelChange={handleSelectionChange} |
| | | selectionModel={selectedRows} |
| | | sx={{ |
| | | '& .MuiDataGrid-cell input': { |
| | | border: '1px solid #ccc' |
| | | }, |
| | | }} |
| | | /> |
| | | </div> |
| | | ); |
| | | }; |
| | | |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; |
| | | import { useNavigate } from 'react-router-dom'; |
| | | 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, |
| | | useRefresh, |
| | | AutocompleteInput, |
| | | DeleteButton, |
| | | Button, |
| | | } from 'react-admin'; |
| | | import { Box, Typography, Card, Stack, LinearProgress } 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 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 request from '@/utils/request'; |
| | | import WarehouseStockCreate from "./WarehouseStockCreate"; |
| | | import WarehouseStockInfo from "./WarehouseStockInfo"; |
| | | import MatnrListAside from "./MatnrListAside"; |
| | | |
| | | const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ |
| | | '& .css-1vooibu-MuiSvgIcon-root': { |
| | | height: '.9em' |
| | | }, |
| | | '& .RaDatagrid-row': { |
| | | cursor: 'auto' |
| | | }, |
| | | '& .column-name': { |
| | | }, |
| | | '& .opt': { |
| | | width: 220 |
| | | }, |
| | | })); |
| | | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <NumberInput source="locId" label="table.field.locItem.locId" />, |
| | | <TextInput source="locCode" label="table.field.locItem.locCode" />, |
| | | <TextInput source="type" label="table.field.locItem.type" />, |
| | | <NumberInput source="orderItemId" label="table.field.locItem.orderItemId" />, |
| | | <NumberInput source="wkType" label="table.field.locItem.wkType" />, |
| | | <NumberInput source="matnrId" label="table.field.locItem.matnrId" />, |
| | | <TextInput source="maktx" label="table.field.locItem.maktx" />, |
| | | <TextInput source="unit" label="table.field.locItem.unit" />, |
| | | <NumberInput source="anfme" label="table.field.locItem.anfme" />, |
| | | <NumberInput source="workQty" label="table.field.locItem.workQty" />, |
| | | <TextInput source="batch" label="table.field.locItem.batch" />, |
| | | <TextInput source="spec" label="table.field.locItem.spec" />, |
| | | <TextInput source="model" label="table.field.locItem.model" />, |
| | | <TextInput source="fieldsIndex" label="table.field.locItem.fieldsIndex" />, |
| | | <TextInput label="common.field.memo" source="memo" />, |
| | | ] |
| | | |
| | | const WarehouseStockList = () => { |
| | | const translate = useTranslate(); |
| | | const [createDialog, setCreateDialog] = useState(false); |
| | | const [matnrCode, setMatnrCode] = useState(''); |
| | | const [drawerVal, setDrawerVal] = useState(false); |
| | | |
| | | return ( |
| | | <Box display="flex"> |
| | | <List |
| | | sx={{ |
| | | flexGrow: 1, |
| | | transition: (theme) => |
| | | theme.transitions.create(['all'], { |
| | | duration: theme.transitions.duration.enteringScreen, |
| | | }), |
| | | marginRight: 0, |
| | | }} |
| | | resource="warehouse/stock" |
| | | title={"common.button.detail"} |
| | | empty={false} |
| | | filters={filters} |
| | | sort={{ field: "create_time", order: "desc" }} |
| | | actions={( |
| | | <TopToolbar> |
| | | <FilterButton /> |
| | | <SelectColumnsButton preferenceKey='locItem' /> |
| | | </TopToolbar> |
| | | )} |
| | | perPage={DEFAULT_PAGE_SIZE} |
| | | > |
| | | <StyledDatagrid |
| | | preferenceKey='locItem' |
| | | bulkActionButtons={false} |
| | | rowClick={false} |
| | | expand={false} |
| | | expandSingle={true} |
| | | omit={['id', 'createTime', 'locId', 'spec', 'model', 'locCode', 'orderId', 'orderItemId', 'matnrId', 'splrBatch', 'createBy', 'memo', 'fieldsIndex']} |
| | | > |
| | | <NumberField source="id" /> |
| | | <NumberField source="locId" label="table.field.warehouseStock.locId" /> |
| | | <TextField source="locCode" label="table.field.warehouseStock.locCode" /> |
| | | <NumberField source="orderId" label="table.field.warehouseStock.orderId" /> |
| | | <NumberField source="orderItemId" label="table.field.warehouseStock.orderItemId" /> |
| | | <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" /> |
| | | <TextField source="spec" label="table.field.warehouseStock.spec" /> |
| | | <TextField source="model" label="table.field.warehouseStock.model" /> |
| | | {/* <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> |
| | | <TextField source="nickname" /> |
| | | </ReferenceField> */} |
| | | {/* <ReferenceField source="splrId" label="table.field.warehouseStock.splrId" reference="companys"> |
| | | <TextField source="name" filterToQuery={(val) => ({ name: val })} /> |
| | | </ReferenceField>, */} |
| | | <TextField source="batch" label="table.field.warehouseStock.batch" /> |
| | | <TextField source="unit" label="table.field.warehouseStock.unit" /> |
| | | <TextField source="fieldsIndex" label="table.field.warehouseStock.fieldsIndex" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | | <WrapperField cellClassName="opt" label="common.field.opt"> |
| | | <StockInfoButton /> |
| | | <HistoriesButton setCreateDialog={setCreateDialog} setMatnrCode={setMatnrCode} /> |
| | | </WrapperField> |
| | | </StyledDatagrid> |
| | | </List> |
| | | <WarehouseStockInfo |
| | | open={createDialog} |
| | | setOpen={setCreateDialog} |
| | | record={matnrCode} |
| | | /> |
| | | </Box> |
| | | ) |
| | | } |
| | | |
| | | export default WarehouseStockList; |
| | | |
| | | const HistoriesButton = ({ setCreateDialog , setMatnrCode}) => { |
| | | const record = useRecordContext(); |
| | | const historyClick = (event) => { |
| | | event.stopPropagation(); |
| | | setCreateDialog(true) |
| | | setMatnrCode(record?.matnrCode) |
| | | } |
| | | return ( |
| | | <Button label="common.button.histories" onClick={historyClick}></Button> |
| | | ) |
| | | } |
| | | |
| | | const StockInfoButton = () => { |
| | | const stockClick = (event) => { |
| | | event.stopPropagation(); |
| | | } |
| | | |
| | | return ( |
| | | <Button label="common.button.detail" onClick={stockClick}></Button> |
| | | ) |
| | | } |
| | | |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material'; |
| | | import { |
| | | useTranslate, |
| | | useRecordContext, |
| | | } from 'react-admin'; |
| | | import PanelTypography from "../../components/PanelTypography"; |
| | | import * as Common from '@/utils/common' |
| | | |
| | | const WarehouseStockPanel = () => { |
| | | const record = useRecordContext(); |
| | | if (!record) return null; |
| | | const translate = useTranslate(); |
| | | return ( |
| | | <> |
| | | <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}> |
| | | <CardContent> |
| | | <Grid container spacing={2}> |
| | | <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}> |
| | | <Typography variant="h6" gutterBottom align="left" sx={{ |
| | | maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' }, |
| | | whiteSpace: 'nowrap', |
| | | overflow: 'hidden', |
| | | textOverflow: 'ellipsis', |
| | | }}> |
| | | {Common.camelToPascalWithSpaces(translate('table.field.locItem.id'))}: {record.id} |
| | | </Typography> |
| | | {/* inherit, primary, secondary, textPrimary, textSecondary, error */} |
| | | <Typography variant="h6" gutterBottom align="right" > |
| | | ID: {record.id} |
| | | </Typography> |
| | | </Grid> |
| | | </Grid> |
| | | <Grid container spacing={2}> |
| | | <Grid item xs={12} container alignContent="flex-end"> |
| | | <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}> |
| | | {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo} |
| | | </Typography> |
| | | </Grid> |
| | | </Grid> |
| | | <Box height={20}> </Box> |
| | | <Grid container spacing={2}> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.locId" |
| | | property={record.locId} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.locCode" |
| | | property={record.locCode} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.orderId" |
| | | property={record.orderId} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.type" |
| | | property={record.type} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.orderItemId" |
| | | property={record.orderItemId} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.wkType" |
| | | property={record.wkType} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.matnrId" |
| | | property={record.matnrId} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.maktx" |
| | | property={record.maktx} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.matnrCode" |
| | | property={record.matnrCode} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.trackCode" |
| | | property={record.trackCode} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.unit" |
| | | property={record.unit} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.anfme" |
| | | property={record.anfme} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.qty" |
| | | property={record.qty} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.workQty" |
| | | property={record.workQty} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.batch" |
| | | property={record.batch} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.splrBatch" |
| | | property={record.splrBatch} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.spec" |
| | | property={record.spec} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.model" |
| | | property={record.model} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <PanelTypography |
| | | title="table.field.locItem.fieldsIndex" |
| | | property={record.fieldsIndex} |
| | | /> |
| | | </Grid> |
| | | |
| | | </Grid> |
| | | </CardContent> |
| | | </Card > |
| | | </> |
| | | ); |
| | | }; |
| | | |
| | | export default WarehouseStockPanel; |
New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { |
| | | ListGuesser, |
| | | EditGuesser, |
| | | ShowGuesser, |
| | | } from "react-admin"; |
| | | |
| | | import WarehouseStockList from "./WarehouseStockList"; |
| | | import WarehouseStockEdit from "./WarehouseStockEdit"; |
| | | |
| | | export default { |
| | | list: WarehouseStockList, |
| | | edit: WarehouseStockEdit, |
| | | show: ShowGuesser, |
| | | recordRepresentation: (record) => { |
| | | return `${record.id}` |
| | | } |
| | | }; |
New file |
| | |
| | | package com.vincent.rsf.server.manager.controller; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.vincent.rsf.framework.common.R; |
| | | 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.manager.entity.LocItem; |
| | | import com.vincent.rsf.server.manager.entity.WaitPakinItem; |
| | | import com.vincent.rsf.server.manager.service.WarehouseStockService; |
| | | import com.vincent.rsf.server.system.controller.BaseController; |
| | | import io.swagger.annotations.Api; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | @Api("库存管理") |
| | | @RestController |
| | | @RequestMapping("/warehouse/stock") |
| | | public class WarehouseStockController extends BaseController { |
| | | |
| | | @Autowired |
| | | private WarehouseStockService warehouseStockService; |
| | | |
| | | |
| | | @PreAuthorize("hasAuthority('manager:locItem:list')") |
| | | @PostMapping("/page") |
| | | public R page(@RequestBody Map<String, Object> param) { |
| | | BaseParam baseParam = buildParam(param, BaseParam.class); |
| | | PageParam<LocItem, BaseParam> pageParam = new PageParam<>(baseParam, LocItem.class); |
| | | QueryWrapper<LocItem> queryWrapper = pageParam.buildWrapper(true); |
| | | IPage<LocItem> pageResult = warehouseStockService.pageByStock(pageParam, queryWrapper); |
| | | List<LocItem> records = pageResult.getRecords(); |
| | | for (LocItem record : records) { |
| | | if (!Objects.isNull(record.getFieldsIndex())) { |
| | | Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex()); |
| | | record.setExtendFields(fields); |
| | | } |
| | | } |
| | | pageResult.setRecords(records); |
| | | return R.ok(pageResult); |
| | | } |
| | | |
| | | } |
| | |
| | | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime); |
| | | } |
| | | |
| | | |
| | | |
| | | public Boolean getStatusBool(){ |
| | | if (null == this.status){ return null; } |
| | | switch (this.status){ |
| | | case 1: |
| | | return true; |
| | | case 0: |
| | | return false; |
| | | default: |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | package com.vincent.rsf.server.manager.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | | import com.vincent.rsf.server.manager.entity.LocItem; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.springframework.stereotype.Repository; |
| | | |
| | | @Mapper |
| | | @Repository |
| | | public interface LocItemMapper extends BaseMapper<LocItem> { |
| | | |
| | | IPage<LocItem> pageByStock(PageParam<LocItem, BaseParam> pageParam, @Param(Constants.WRAPPER) QueryWrapper<LocItem> queryWrapper); |
| | | } |
New file |
| | |
| | | package com.vincent.rsf.server.manager.service; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | | import com.vincent.rsf.server.manager.entity.LocItem; |
| | | |
| | | public interface WarehouseStockService extends IService<LocItem> { |
| | | |
| | | IPage<LocItem> pageByStock(PageParam<LocItem, BaseParam> pageParam, QueryWrapper<LocItem> queryWrapper); |
| | | } |
New file |
| | |
| | | package com.vincent.rsf.server.manager.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | | import com.vincent.rsf.server.manager.entity.LocItem; |
| | | import com.vincent.rsf.server.manager.mapper.LocItemMapper; |
| | | import com.vincent.rsf.server.manager.service.WarehouseStockService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | @Service("warehouseStockService") |
| | | public class WarehouseStockServiceImpl extends ServiceImpl<LocItemMapper, LocItem> implements WarehouseStockService { |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/5/15 |
| | | * @description: 获取虚拟为存与物料库存并集 |
| | | * @version 1.0 |
| | | */ |
| | | @Override |
| | | public IPage<LocItem> pageByStock(PageParam<LocItem, BaseParam> pageParam, QueryWrapper<LocItem> queryWrapper) { |
| | | IPage<LocItem> results = this.baseMapper.pageByStock(pageParam, queryWrapper); |
| | | return results; |
| | | } |
| | | } |
| | |
| | | driver-class-name: com.mysql.jdbc.Driver |
| | | # url: jdbc:mysql://47.76.147.249:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai |
| | | username: root |
| | | url: jdbc:mysql://127.0.0.1:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai |
| | | url: jdbc:mysql://192.168.4.50:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai |
| | | # username: rsf |
| | | password: 34821015 |
| | | type: com.alibaba.druid.pool.DruidDataSource |
| | |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.vincent.rsf.server.manager.mapper.LocItemMapper"> |
| | | |
| | | <select id="pageByStock" resultType="com.vincent.rsf.server.manager.entity.LocItem"> |
| | | SELECT * |
| | | FROM (SELECT id, |
| | | loc_id, |
| | | loc_code, |
| | | type, |
| | | order_item_id, |
| | | wk_type, |
| | | matnr_id, |
| | | maktx, |
| | | matnr_code, |
| | | unit, |
| | | SUM(anfme) anfme, |
| | | SUM(qty) qty, |
| | | SUM(work_qty) work_qty, |
| | | batch, |
| | | spec, |
| | | model, |
| | | fields_index, |
| | | update_by, |
| | | create_by, |
| | | update_time, |
| | | create_time |
| | | FROM man_loc_item |
| | | GROUP BY matnr_id |
| | | UNION ALL |
| | | SELECT id, |
| | | '' AS loc_id, |
| | | '' AS loc_code, |
| | | type, |
| | | asn_item_id AS order_item_id, |
| | | wk_type, |
| | | matnr_id, |
| | | maktx, |
| | | matnr_code, |
| | | unit, |
| | | SUM(anfme) anfme, |
| | | SUM(qty) qty, |
| | | SUM(work_qty) work_qty, |
| | | batch, |
| | | spec, |
| | | model, |
| | | fields_index, |
| | | update_by, |
| | | create_by, |
| | | update_time, |
| | | create_time |
| | | FROM man_warehouse_areas_item |
| | | GROUP BY matnr_id) t |
| | | ${ew.customSqlSegment} |
| | | </select> |
| | | </mapper> |