| | |
| | | matnrName: "matnrName", |
| | | matnrCode: "matnrCode", |
| | | batch: "batch", |
| | | exceStatus: 'Exce Status', |
| | | splrBatch: "splrBatch", |
| | | orderCode: "orderCode", |
| | | orderItemId: "orderItemId", |
| | |
| | | orderCode: "源单号", |
| | | orderItemId: "源单明细ID", |
| | | unit: "单位", |
| | | exceStatus: '执行状态', |
| | | trackCode: "跟踪码", |
| | | fieldsIndex: "动态扩展", |
| | | anfme: "数量", |
| | |
| | | continue: '继续收货', |
| | | batch: '批量操作', |
| | | confirm: '确认', |
| | | start: '开始下发', |
| | | start: '自动下发', |
| | | pause: '暂停', |
| | | pick: '拣料', |
| | | check: '盘点', |
| | |
| | | //获取波次规则 |
| | | const closeDialog = async (value) => { |
| | | setWaveRule(false) |
| | | refresh() |
| | | console.log('=====>'); |
| | | console.log(value); |
| | | console.log(selectIds); |
| | | const res = await request.post(`/outStock/generate/wave`, { ids: selectIds, waveRuleId: value.id }); |
| | | if (res?.data?.code === 200) { |
| | | notify(res.data.msg); |
| | | } else { |
| | | notify(res.data.msg); |
| | | } |
| | | refresh() |
| | | } |
| | | |
| | | return ( |
New file |
| | |
| | | import { Box, Card, Grid, List, LinearProgress, Select, MenuItem, ListItemText, ListItemAvatar, Avatar, ListItemButton, Dialog, DialogTitle, ListItem, DialogContent, DialogActions, Button } from "@mui/material"; |
| | | import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE, DEFAULT_TYPE } from '@/config/setting'; |
| | | import { SimpleForm, TextInput, ReferenceInput, useTranslate, AutocompleteInput } from "react-admin"; |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { Delete, Edit, Add } from '@mui/icons-material'; |
| | | import SaveIcon from '@mui/icons-material/Save'; |
| | | import request from '@/utils/request'; |
| | | |
| | | const OutStockWaveDialog = (props) => { |
| | | const translate = useTranslate(); |
| | | const { onClose, selectedValue, open, setOpen } = props; |
| | | const [siteNos, setSiteNos] = useState([]); |
| | | const [formData, setFormData] = useState({ |
| | | id: DEFAULT_TYPE |
| | | }); |
| | | |
| | | const handleClose = () => { |
| | | onClose(null); |
| | | } |
| | | |
| | | const handleSelect = () => { |
| | | onClose(formData); |
| | | |
| | | } |
| | | |
| | | const handleListItemClick = (value) => { |
| | | onClose(value); |
| | | } |
| | | |
| | | const handleChange = (event) => { |
| | | console.log(event); |
| | | |
| | | setFormData({ id: event }) |
| | | }; |
| | | |
| | | return ( |
| | | <Dialog |
| | | onClose={handleClose} |
| | | open={open} |
| | | aria-labelledby="alert-dialog-title" |
| | | aria-describedby="alert-dialog-description" |
| | | > |
| | | <DialogTitle id="alert-dialog-title">{translate("toolbar.selectWave")}</DialogTitle> |
| | | <DialogContent sx={{ width: 600 }}> |
| | | <SimpleForm toolbar={false} defaultValue={formData}> |
| | | <ReferenceInput source="id" reference="waveRule" > |
| | | <AutocompleteInput |
| | | label={'toolbar.selectWave'} |
| | | defaultValue={DEFAULT_TYPE} |
| | | onChange={handleChange} |
| | | /> |
| | | </ReferenceInput> |
| | | </SimpleForm> |
| | | </DialogContent> |
| | | <DialogActions> |
| | | <Button onClick={handleClose} variant="outlined">{translate('toolbar.cancel')}</Button> |
| | | <Button onClick={handleSelect} autoFocus startIcon={<SaveIcon />} variant="contained"> |
| | | {translate('toolbar.confirm')} |
| | | </Button> |
| | | </DialogActions> |
| | | </Dialog> |
| | | ); |
| | | } |
| | | |
| | | export default OutStockWaveDialog; |
| | |
| | | > |
| | | <StyledDatagrid |
| | | preferenceKey='waveItem' |
| | | bulkActionButtons= { |
| | | bulkActionButtons={ |
| | | <> |
| | | <BulkStartButton /> |
| | | <BulkPauseButton /> |
| | |
| | | <TextField source="fieldsIndex" label="table.field.waveItem.fieldsIndex" /> |
| | | <NumberField source="workQty" label="table.field.waveItem.workQty" /> |
| | | <TextField source="unit" label="table.field.waveItem.unit" /> |
| | | <TextField source="exceStatus" label="table.field.waveItem.exceStatus" /> |
| | | <TextField source="updateBy$" label="common.field.updateBy" /> |
| | | <DateField source="updateTime" label="common.field.updateTime" showTime /> |
| | | <TextField source="createBy$" label="common.field.createBy" /> |
| | |
| | | const WaveList = () => { |
| | | const translate = useTranslate(); |
| | | const [createDialog, setCreateDialog] = useState(false); |
| | | const [autoExce, setAutoExce] = useState(false); |
| | | const [detailDialog, setDetailDialog] = useState(false); |
| | | const [select, setSelectIds] = useState({}); |
| | | const [drawerVal, setDrawerVal] = useState(false); |
| | |
| | | sort={{ field: "create_time", order: "desc" }} |
| | | actions={( |
| | | <TopToolbar> |
| | | <BulkStartButton /> |
| | | <BulkPauseButton /> |
| | | <BulkStartButton autoExce={autoExce} setAutoExce={setAutoExce} /> |
| | | <BulkPauseButton autoExce={autoExce} setAutoExce={setAutoExce} /> |
| | | <FilterButton /> |
| | | <SelectColumnsButton preferenceKey='wave' /> |
| | | </TopToolbar> |
| | |
| | | ); |
| | | } |
| | | |
| | | const BulkStartButton = () => { |
| | | const BulkStartButton = ({ autoExce, setAutoExce }) => { |
| | | const { data, selectedIds, onUnselectItems } = useListContext(); |
| | | |
| | | const startClick = () => { |
| | | onUnselectItems() |
| | | setAutoExce(true) |
| | | } |
| | | return ( |
| | | <Button label="toolbar.start" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} /> |
| | | !autoExce ? <Button label="toolbar.start" onClick={startClick} startIcon={<PlayArrowOutlinedIcon />} /> : <></> |
| | | ) |
| | | } |
| | | |
| | | const BulkPauseButton = () => { |
| | | const BulkPauseButton = ({ autoExce, setAutoExce }) => { |
| | | const { data, selectedIds, onUnselectItems } = useListContext(); |
| | | |
| | | const pauseClick = () => { |
| | | onUnselectItems() |
| | | setAutoExce(false) |
| | | } |
| | | return ( |
| | | <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseCircleOutlineIcon />} /> |
| | | autoExce ? <Button label="toolbar.pause" onClick={pauseClick} startIcon={<PauseCircleOutlineIcon />} /> : <></> |
| | | ) |
| | | } |
| | |
| | | public class FieldsUtils { |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @description 通过字段唯一标识获取动态字段对象key-value |
| | | * @param |
| | | * @return 扩展字段对象 |
| | | * @author Ryan |
| | | * @description 通过字段唯一标识获取动态字段对象key-value |
| | | * @time 2025/3/12 12:50 |
| | | */ |
| | | public static Map<String, String> getFields(String uuid) { |
| | |
| | | } |
| | | FieldsItemService fieldsItemService = SpringUtils.getBean(FieldsItemService.class); |
| | | List<FieldsItem> fieldsItems = fieldsItemService.list(new LambdaQueryWrapper<FieldsItem>().eq(FieldsItem::getUuid, uuid)); |
| | | for (Fields field : fields ) { |
| | | for (Fields field : fields) { |
| | | if (fieldsItems.isEmpty()) { |
| | | fieldsMap.put(field.getFields(), null); |
| | | continue; |
| | |
| | | }); |
| | | } |
| | | |
| | | return fieldsMap; |
| | | return fieldsMap; |
| | | } |
| | | |
| | | /** |
| | | * @param |
| | | * @return 包含扩展字段的集合对象 |
| | | * @author Ryan |
| | | * @description 获取集合扩展字段key-value值 |
| | | * @param |
| | | * @return 包含扩展字段的集合对象 |
| | | * @time 2025/3/15 15:05 |
| | | */ |
| | | public static List<Map<String, Object>> getExtendFields(List<Map<String, Object>> params) { |
| | |
| | | * @time 2025/3/18 15:00 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public static boolean saveFields(Map<String, ?> template, String uuid) throws Exception{ |
| | | public static boolean saveFields(Map<String, ?> template, String uuid) throws Exception { |
| | | List<Fields> fields = getFieldsSta(); |
| | | FieldsItemService fieldsItemService = SpringUtils.getBean(FieldsItemService.class); |
| | | List<FieldsItem> fieldsItems = new ArrayList<>(); |
| | |
| | | |
| | | /** |
| | | * 获取所有开启动态扩展字段 |
| | | * |
| | | * @return |
| | | */ |
| | | public static List<Fields> getFieldsSta() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @description 动态字段修改 |
| | | * @param |
| | | * @return |
| | | * @author Ryan |
| | | * @description 动态字段修改 |
| | | * @time 2025/4/7 15:28 |
| | | */ |
| | | @Synchronized |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public static void updateFieldsValue(Map<String, Object> params) throws Exception { |
| | | List<Fields> fields = getFieldsSta(); |
| | | if (fields.isEmpty()) { return; } |
| | | if (fields.isEmpty()) { |
| | | return; |
| | | } |
| | | Object fieldsIndex = params.get("fieldsIndex"); |
| | | if (!Objects.isNull(fieldsIndex) && StringUtils.isNotBlank(fieldsIndex.toString())) { |
| | | String index = fieldsIndex.toString(); |
| | | FieldsItemService fieldsItemService = SpringUtils.getBean(FieldsItemService.class); |
| | | for (Fields field : fields) { |
| | | if (!Objects.isNull(params.get(field.getFields()))) { |
| | | FieldsItem indexItem = fieldsItemService.getOne(new LambdaQueryWrapper<FieldsItem>() |
| | | .eq(FieldsItem::getUuid, index) |
| | | .eq(FieldsItem::getFieldsId, field.getId())); |
| | | //如果子表为空,执行插入操作,否则就执行修改操作 |
| | | if (Objects.isNull(indexItem)) { |
| | | FieldsItem item = new FieldsItem(); |
| | | item.setUuid(index) |
| | | .setFieldsId(field.getId()) |
| | | .setMatnrId(!Objects.isNull(params.get("matnrId")) ? Long.parseLong(params.get("matnrId").toString()) : null) |
| | | .setValue(params.get(field.getFields()).toString()); |
| | | if (!fieldsItemService.save(item)) { |
| | | throw new CoolException("扩展字段修改失败!!"); |
| | | } |
| | | } else { |
| | | indexItem.setValue(params.get(field.getFields()).toString()); |
| | | if (!fieldsItemService.updateById(indexItem)) { |
| | | throw new CoolException("扩展字段修改失败!!"); |
| | | } |
| | | if (!Objects.isNull(params.get(field.getFields()))) { |
| | | FieldsItem indexItem = fieldsItemService.getOne(new LambdaQueryWrapper<FieldsItem>() |
| | | .eq(FieldsItem::getUuid, index) |
| | | .eq(FieldsItem::getFieldsId, field.getId())); |
| | | //如果子表为空,执行插入操作,否则就执行修改操作 |
| | | if (Objects.isNull(indexItem)) { |
| | | FieldsItem item = new FieldsItem(); |
| | | item.setUuid(index) |
| | | .setFieldsId(field.getId()) |
| | | .setMatnrId(!Objects.isNull(params.get("matnrId")) ? Long.parseLong(params.get("matnrId").toString()) : null) |
| | | .setValue(params.get(field.getFields()).toString()); |
| | | if (!fieldsItemService.save(item)) { |
| | | throw new CoolException("扩展字段修改失败!!"); |
| | | } |
| | | } else { |
| | | indexItem.setValue(params.get(field.getFields()).toString()); |
| | | if (!fieldsItemService.updateById(indexItem)) { |
| | | throw new CoolException("扩展字段修改失败!!"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | saveFields(params, params.get("index").toString()); |
| | |
| | | Fields fields = fieldsService.getOne(new LambdaQueryWrapper<Fields>().eq(Fields::getFields, key)); |
| | | if (!Cools.isEmpty(fields)) { |
| | | String applySql = String.format( |
| | | "EXISTS (SELECT 1 FROM sys_fields_item fie " + |
| | | "WHERE %s.fields_index IS NOT NULL " + |
| | | "AND fie.uuid = %s.fields_index " + |
| | | "AND fie.fields_id = '%s' " + |
| | | "AND fie.value = '%s')", |
| | | tableName, tableName, fields.getId(), val |
| | | "EXISTS (SELECT 1 FROM sys_fields_item fie " + |
| | | "WHERE %s.fields_index IS NOT NULL " + |
| | | "AND fie.uuid = %s.fields_index " + |
| | | "AND fie.fields_id = '%s' " + |
| | | "AND fie.value = '%s')", |
| | | tableName, tableName, fields.getId(), val |
| | | ); |
| | | queryWrapper.apply(applySql); |
| | | } |
| | |
| | | private Integer status; |
| | | |
| | | /** |
| | | * 执行状态 0:未执行 1:待执行 2:执行中 3:已取消 |
| | | */ |
| | | @ApiModelProperty("执行状态") |
| | | private Short exceStatus; |
| | | |
| | | /** |
| | | * 是否删除 1: 是 0: 否 |
| | | */ |
| | | @ApiModelProperty(value= "是否删除 1: 是 0: 否 ") |
| | |
| | | * @return |
| | | * @time 2025/6/16 08:35 |
| | | */ |
| | | @Scheduled(cron = "0/30 * * * * ? ") |
| | | // @Scheduled(cron = "0/30 * * * * ? ") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void outStockComplete() { |
| | | List<AsnOrder> asnOrders = asnOrderService.list(new LambdaQueryWrapper<AsnOrder>() |
| | | .eq(AsnOrder::getType, OrderType.ORDER_OUT.type) |
| | | .apply("anfme=work_qty") |
| | | .apply("anfme = work_qty") |
| | | ); |
| | | if (asnOrders.isEmpty()) { |
| | | return; |
| | |
| | | import com.vincent.rsf.server.manager.service.CompanysService; |
| | | import com.vincent.rsf.server.manager.service.MatnrService; |
| | | import com.vincent.rsf.server.system.constant.SerialRuleCode; |
| | | import com.vincent.rsf.server.system.entity.Fields; |
| | | import com.vincent.rsf.server.system.service.DictDataService; |
| | | import com.vincent.rsf.server.system.service.FieldsItemService; |
| | | import com.vincent.rsf.server.system.service.FieldsService; |
| | |
| | | try { |
| | | StringBuffer sb = new StringBuffer(); |
| | | if (Objects.isNull(asnOrderItem.getFieldsIndex()) || StringUtils.isBlank(asnOrderItem.getFieldsIndex())) { |
| | | if (!Objects.isNull(asnOrderItem.getExtendFields()) && !asnOrderItem.getExtendFields().isEmpty()) { |
| | | Map<String, String> fields = asnOrderItem.getExtendFields(); |
| | | asnOrderItem.getExtendFields().keySet().forEach(key -> { |
| | | sb.append(fields.get(key)); |
| | | }); |
| | | } |
| | | sb.append(asnOrderItem.getAsnCode() + asnOrderItem.getMatnrId() + asnOrderItem.getSplrBatch() + asnOrderItem.getIsptResult$()); |
| | | sb.append(asnOrderItem.getMatnrId() + asnOrderItem.getSplrBatch() ); |
| | | //获取16位uuid |
| | | String uuid16 = Cools.md5Chinese(sb.toString()); |
| | | asnOrderItem.setFieldsIndex(uuid16); |
| | |
| | | if (!waveService.save(wave)) { |
| | | throw new CoolException("波次保存失败!!"); |
| | | } |
| | | |
| | | |
| | | |
| | | List<Long> list = orders.stream().map(AsnOrder::getId).collect(Collectors.toList()); |
| | | List<AsnOrderItem> orderItems = asnOrderItemService |
| | | .list(new LambdaQueryWrapper<AsnOrderItem>() |
| | | .in(AsnOrderItem::getAsnId, list)); |
| | | .in(AsnOrderItem::getAsnId, list).apply("anfme > work_qty")); |
| | | if (orderItems.isEmpty()) { |
| | | throw new CoolException("单据不存在!!"); |
| | | } |
| | |
| | | .set(AsnOrder::getWaveId, wave.getId()) |
| | | .set(AsnOrder::getWorkQty, wkQty) |
| | | .set(AsnOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val) |
| | | .in(AsnOrder::getId, params.getIds()))) { |
| | | .eq(AsnOrder::getId, order.getId()))) { |
| | | throw new CoolException("执行状态修改修改失败!!"); |
| | | } |
| | | } |
| | |
| | | throw new CoolException("主单信息不能为空"); |
| | | } |
| | | AsnOrder orders = params.getOrders(); |
| | | if (Objects.isNull(orders)) { |
| | | throw new CoolException("单据不能为空!!"); |
| | | } |
| | | if (StringUtils.isBlank(orders.getWkType())) { |
| | | throw new CoolException("业务类型不能为空!!"); |
| | | } |
| | | |
| | | String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_OUT_STOCK_CODE, orders); |
| | | if (Objects.isNull(ruleCode) || StringUtils.isBlank(ruleCode)) { |
| | | if (StringUtils.isBlank(ruleCode)) { |
| | | throw new CoolException("编码规则错误:请检查「SYS_OUT_STOCK_CODE」是否设置正确!!"); |
| | | } |
| | | orders.setCode(ruleCode) |
| | |
| | | p1.getUpdateBy(), |
| | | p1.getMemo() |
| | | ), |
| | | WaveItem::getSplrBatch, WaveItem::getMatnrId, WaveItem::getFieldsIndex |
| | | WaveItem::getSplrBatch, WaveItem::getMatnrCode, WaveItem::getFieldsIndex |
| | | ); |
| | | |
| | | return waveItems; |