| | |
| | | locDeadReport: 'Locs Dead Report', |
| | | stockStatistic: 'Stock Statistic', |
| | | statisticCount: 'Statistic Count', |
| | | |
| | | preparation: "备料单", |
| | | }, |
| | | table: { |
| | | field: { |
| | |
| | | selectWave: 'Select Wave Rule', |
| | | |
| | | }, |
| | | placeholder: { |
| | | warehouseAreasCode: "use for warehouse areas code prefix", |
| | | }, |
| | | request: { |
| | | error: { |
| | | stock: "Insufficient inventory to deliver !!", |
| | |
| | | modiftySite: '修改库口', |
| | | selectWave: '波次规则', |
| | | }, |
| | | placeholder: { |
| | | warehouseAreasCode: "用于库位编码前缀占位符", |
| | | }, |
| | | request: { |
| | | error: { |
| | | stock: "库存不足,无法提交!!", |
| | |
| | | // </Button> : ) |
| | | record.exceStatus === 1 ? <ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskIcon />} onConfirm={requestComplete} /> : <></> |
| | | ) |
| | | |
| | | |
| | | } |
| | | |
| | | const CloseButton = () => { |
| | |
| | | import PublicIcon from '@mui/icons-material/Public'; |
| | | import SelectMatnrModal from "./SelectMatnrModal"; |
| | | import EditIcon from '@mui/icons-material/Edit'; |
| | | import TaskIcon from '@mui/icons-material/Task'; |
| | | import OutOrderPreview from "./OutOrderPreview"; |
| | | import AddIcon from '@mui/icons-material/Add'; |
| | | import OutStockPublic from "./OutStockPublic"; |
| | |
| | | <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} /> |
| | | <EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton> |
| | | <CancelButton /> |
| | | <CompleteButton /> |
| | | <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} /> |
| | | </WrapperField> |
| | | </StyledDatagrid> |
| | |
| | | ); |
| | | } |
| | | |
| | | //完成单据 |
| | | const CompleteButton = () => { |
| | | const record = useRecordContext(); |
| | | const notify = useNotify(); |
| | | const refresh = useRefresh(); |
| | | const requestComplete = async () => { |
| | | const { data: { code, data, msg } } = await request.get(`/outStock/complete/${record.id}`); |
| | | if (code === 200) { |
| | | notify(msg); |
| | | refresh() |
| | | } else { |
| | | notify(msg); |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | // record.exceStatus === 1 && (record.anfme === record.qty ? <Button onClick={requestComplete} label={"toolbar.complete"} color="secondary"> |
| | | // <TaskIcon /> |
| | | // </Button> : ) |
| | | record.exceStatus != 15 ? <ConfirmButton label={"toolbar.complete"} color="secondary" startIcon={<TaskIcon />} onConfirm={requestComplete} /> : <></> |
| | | ) |
| | | } |
| | | |
| | | const MyButton = ({ setCreateDialog, setmodalType }) => { |
| | | const record = useRecordContext(); |
| | | const handleEditClick = (btn) => { |
| | |
| | | textOverflow: 'ellipsis', |
| | | whiteSpace: 'nowrap', |
| | | maxWidth: 600, |
| | | // 确保所有单元格有基本的内边距 |
| | | padding: '8px 16px', |
| | | })); |
| | | |
| | | const TreeTableRow = (props) => { |
| | |
| | | |
| | | const isOpen = openNodes[row.id] || false; |
| | | |
| | | // 更明显的透明度渐变 |
| | | const getOpacity = (currentDepth) => { |
| | | // 第一级:100%,第二级:75%,第三级:50%,第四级:40% |
| | | const opacities = [1, 0.9, 0.8, 0.7]; |
| | | return opacities[currentDepth] || 0.4; |
| | | }; |
| | | |
| | | const opacity = getOpacity(depth); |
| | | |
| | | return ( |
| | | <React.Fragment> |
| | | <StyledTableRow hover tabIndex={-1} key={row.id}> |
| | | <StyledTableCell sx={{ padding: 0 }}> |
| | | {row.children && ( |
| | | <StyledTableRow |
| | | hover |
| | | tabIndex={-1} |
| | | key={row.id} |
| | | sx={{ |
| | | opacity: depth > 0 ? opacity : 1, |
| | | // 添加背景色渐变增强效果 |
| | | backgroundColor: depth > 0 ? `rgba(0, 0, 0, ${0.02 * (3 - depth)})` : 'inherit', |
| | | }} |
| | | > |
| | | <StyledTableCell sx={{ |
| | | padding: 0, |
| | | width: 60, |
| | | // 进一步减小缩进距离到12px |
| | | paddingLeft: depth * 4 |
| | | }}> |
| | | {row.children && row.children.length > 0 && ( |
| | | <IconButton |
| | | aria-label="expand row" |
| | | size="small" |
| | | onClick={() => toggleNode(row.id)} |
| | | sx={{ |
| | | opacity: depth > 0 ? opacity : 1, |
| | | }} |
| | | > |
| | | {isOpen ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />} |
| | | </IconButton> |
| | |
| | | key={column.id} |
| | | align={column.align || 'left'} |
| | | style={{ |
| | | paddingLeft: idx === 0 && (depth * 16 + 16), |
| | | opacity: column.id === 'icon' && .6 |
| | | // 名称列也使用12px缩进 |
| | | paddingLeft: idx === 0 ? (depth * 24 + 16) : 16, |
| | | // opacity: column.id === 'icon' && .6 |
| | | }} |
| | | onClick={() => toggleNode(row.id)} |
| | | onClick={() => column.id === 'name' && toggleNode(row.id)} |
| | | sx={{ |
| | | opacity: column.id === 'icon' ? 0.6 : (depth > 0 ? opacity : 1), |
| | | fontWeight: 400, |
| | | // 使用字体大小或颜色来区分层级 |
| | | fontSize: depth === 0 ? '0.95rem' : '0.9rem', |
| | | // 或者使用不同的颜色 |
| | | color: depth === 0 ? 'text.primary' : `rgba(0, 0, 0, ${opacity})`, |
| | | }} |
| | | > |
| | | {column.format ? column.format(value) : value} |
| | | </StyledTableCell> |
| | |
| | | })} |
| | | <StyledTableCell> |
| | | <Tooltip title="Edit"> |
| | | <IconButton onClick={() => onEdit(row)}> |
| | | <IconButton |
| | | onClick={() => onEdit(row)} |
| | | sx={{ |
| | | opacity: depth > 0 ? opacity : 1, |
| | | }} |
| | | size="small" |
| | | > |
| | | <Edit /> |
| | | </IconButton> |
| | | </Tooltip> |
| | | <Tooltip title="Delete"> |
| | | <IconButton onClick={() => onDelete(row)}> |
| | | <IconButton |
| | | onClick={() => onDelete(row)} |
| | | sx={{ |
| | | opacity: depth > 0 ? opacity : 1, |
| | | }} |
| | | size="small" |
| | | > |
| | | <Delete /> |
| | | </IconButton> |
| | | </Tooltip> |
| | | </StyledTableCell> |
| | | </StyledTableRow> |
| | | {row.children && isOpen && ( |
| | | {row.children && row.children.length > 0 && isOpen && ( |
| | | row.children.map((child) => ( |
| | | <TreeTableRow |
| | | key={child.id} |
| | |
| | | const [editRecord, setEditRecord] = React.useState(null); |
| | | const [openNodes, setOpenNodes] = React.useState({}); |
| | | const [expandAll, setExpandAll] = React.useState(false); |
| | | const notifyState = React.useRef({ last: '', at: 0 }); |
| | | const pushNotify = React.useCallback((type, msg) => { |
| | | const text = typeof msg === 'string' ? msg : (msg || ''); |
| | | const now = Date.now(); |
| | | if (notifyState.current.last === text && now - notifyState.current.at < 1500) return; |
| | | notifyState.current = { last: text, at: now }; |
| | | notify(text, { type, messageArgs: { _: text } }); |
| | | }, [notify]); |
| | | |
| | | const http = async () => { |
| | | const res = await request.post(RESOURCE + '/tree', { |
| | |
| | | if (res?.data?.code === 200) { |
| | | setTreeData(res.data.data); |
| | | } else { |
| | | notify(res.data.msg); |
| | | const msg = translate('ra.notification.http_error', { _: res?.data?.msg || 'Request failed' }); |
| | | pushNotify('warning', msg); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | onSuccess: () => { |
| | | handleRefresh(); |
| | | notify('Department deleted successfully', { type: 'info', messageArgs: { _: 'Department deleted successfully' } }); |
| | | const msg = translate('ra.message.delete_success', { _: 'Deleted successfully' }); |
| | | pushNotify('success', msg); |
| | | }, |
| | | onError: (error) => { |
| | | notify(`Error: ${error.message}`, { type: 'warning', messageArgs: { _: `Error: ${error.message}` } }); |
| | | const msg = translate('ra.notification.http_error', { _: error?.message || 'Network error' }); |
| | | pushNotify('error', msg); |
| | | }, |
| | | } |
| | | ); |
| | |
| | | const newExpandAll = !prevExpandAll; |
| | | const newOpenNodes = {}; |
| | | const updateOpenNodes = (nodes) => { |
| | | if (!nodes) return; |
| | | nodes.forEach(node => { |
| | | newOpenNodes[node.id] = newExpandAll; |
| | | if (node.children) { |
| | |
| | | ); |
| | | }; |
| | | |
| | | export default MenuList; |
| | | export default MenuList; |
| | |
| | | source="code" |
| | | validate={[required()]} |
| | | parse={(v) => v} |
| | | placeholder={translate("placeholder.warehouseAreasCode")} |
| | | /> |
| | | <AutocompleteInput |
| | | choices={dicts} |
| | | optionText="label" |
| | | label="table.field.asnOrder.type" |
| | | label="table.field.warehouseAreas.type" |
| | | source="type" |
| | | optionValue="value" |
| | | parse={v => v} |
| | |
| | | package com.vincent.rsf.server.manager.controller; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.vincent.rsf.framework.common.Cools; |
| | | import com.vincent.rsf.framework.common.R; |
| | |
| | | import com.vincent.rsf.server.manager.service.LocService; |
| | | import com.vincent.rsf.server.system.controller.BaseController; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import javax.validation.Valid; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | |
| | | public R update(@RequestBody Loc loc) { |
| | | loc.setUpdateBy(getLoginUserId()); |
| | | String join = StringUtils.join(loc.getTypeIds(), ","); |
| | | loc.setType(join); |
| | | if (Objects.isNull(loc.getTypeIds())) { |
| | | throw new CoolException("库位类型不能为空!!"); |
| | | if (!Objects.isNull(loc.getTypeIds())) { |
| | | loc.setType(join); |
| | | } |
| | | if (Objects.isNull(loc.getTypeIds()) && !Objects.isNull(loc.getType())) { |
| | | loc.setTypeIds(Arrays.asList(Long.valueOf(loc.getType()))); |
| | | } |
| | | |
| | | if (!locService.updateById(loc)) { |
| | | return R.error("Update Fail"); |
| | | } |
| | |
| | | } |
| | | if (Objects.isNull(param.getTypeIds()) && param.getTypeIds().isEmpty()) { |
| | | return R.error("库位类型不能为空!!"); |
| | | } |
| | | if (Objects.isNull(param.getWarehouseId())) { |
| | | return R.error("仓库ID不能为空!!"); |
| | | } |
| | | if (Objects.isNull(param.getAreaId())) { |
| | | return R.error("库区ID不能为空!!"); |
| | |
| | | return outStockService.saveOutStock(params, getLoginUserId()); |
| | | } |
| | | |
| | | @GetMapping("/outStock/complete/{id}") |
| | | @ApiOperation("完成出库单") |
| | | @PreAuthorize("hasAuthority('manager:outStock:update')") |
| | | public R complete(@PathVariable Long id) { |
| | | if (Objects.isNull(id)) { |
| | | return R.error("参数不能为空!!"); |
| | | } |
| | | return outStockService.completeOutOrderById(id); |
| | | } |
| | | |
| | | |
| | | @ApiOperation("单据信息修改") |
| | | @PostMapping("/outStock/items/update") |
| | | @PreAuthorize("hasAuthority('manager:outStock:update')") |
| | |
| | | |
| | | Warehouse warehouse1 = warehouseService.getById(warehouse.getId()); |
| | | if (!warehouse.getName().equals(warehouse1.getName())) { |
| | | List<Warehouse> areasList = warehouseService.list(new LambdaQueryWrapper<Warehouse>().eq(Warehouse::getName, warehouse1.getName())); |
| | | List<Warehouse> areasList = warehouseService.list(new LambdaQueryWrapper<Warehouse>().eq(Warehouse::getName, warehouse.getName())); |
| | | if (!areasList.isEmpty()) { |
| | | throw new CoolException("仓库名已存在!!"); |
| | | } |
| | | } |
| | | if (!warehouse.getCode().equals(warehouse1.getCode())) { |
| | | List<Warehouse> areasList = warehouseService.list(new LambdaQueryWrapper<Warehouse>().eq(Warehouse::getCode, warehouse1.getCode())); |
| | | List<Warehouse> areasList = warehouseService.list(new LambdaQueryWrapper<Warehouse>().eq(Warehouse::getCode, warehouse.getCode())); |
| | | if (!areasList.isEmpty()) { |
| | | throw new CoolException("仓库编码已存在!!"); |
| | | } |
| | | } |
| | | |
| | | |
| | | if (!warehouseService.updateById(warehouse)) { |
| | | return R.error("Update Fail"); |
| | |
| | | |
| | | R cancelOutOrderByItems(List<WkOrderItem> orderItems); |
| | | |
| | | R completeOutOrderById(Long id); |
| | | |
| | | } |
| | |
| | | |
| | | String join = loc.getType(); |
| | | if (!Objects.isNull(loc.getTypeIds()) && !loc.getTypeIds().isEmpty()) { |
| | | join = StringUtils.join(loc.getTypeIds(), ","); |
| | | join = StringUtils.join(loc.getTypeIds(), ","); |
| | | } |
| | | boolean update = this.update(new LambdaUpdateWrapper<Loc>() |
| | | .in(Loc::getId, locs.getId()) |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R initLocs(LocMastInitParam param, Long loginUserId) { |
| | | //清空表 |
| | | // this.baseMapper.deleteAll(); |
| | | //清空当前库区库位 |
| | | List<Loc> locs = this.list(new LambdaQueryWrapper<Loc>().eq(Loc::getWarehouseId, param.getWarehouseId()).eq(Loc::getAreaId, param.getAreaId())); |
| | | if (!locs.isEmpty()) { |
| | | if (!this.remove(new LambdaQueryWrapper<Loc>().eq(Loc::getWarehouseId, param.getWarehouseId()).eq(Loc::getAreaId, param.getAreaId()))) { |
| | | throw new CoolException("初始化失败:数据删除失败!!"); |
| | | } |
| | | } |
| | | |
| | | WarehouseAreas warehouseAreas = warehouseAreasService.getOne(new LambdaQueryWrapper<WarehouseAreas>() |
| | | .eq(WarehouseAreas::getWarehouseId, param.getWarehouseId()) |
| | | .eq(WarehouseAreas::getId, param.getAreaId())); |
| | | .eq(!Objects.isNull(param.getWarehouseId()), WarehouseAreas::getWarehouseId, param.getWarehouseId()) |
| | | .eq(!Objects.isNull(param.getAreaId()), WarehouseAreas::getId, param.getAreaId())); |
| | | if (Objects.isNull(warehouseAreas)) { |
| | | throw new CoolException("库区不存在!!"); |
| | | } |
| | | // 清空表 |
| | | // this.baseMapper.deleteAll(); |
| | | // 清空当前库区库位 |
| | | List<Loc> locs = this.list(new LambdaQueryWrapper<Loc>().eq(Loc::getWarehouseId, warehouseAreas.getWarehouseId()) |
| | | .eq(Loc::getAreaId, warehouseAreas.getId())); |
| | | if (!locs.isEmpty()) { |
| | | if (!this.remove(new LambdaQueryWrapper<Loc>().eq(Loc::getWarehouseId, warehouseAreas.getWarehouseId()) |
| | | .eq(Loc::getAreaId, warehouseAreas.getId()))) { |
| | | throw new CoolException("初始化失败:数据删除失败!!"); |
| | | } |
| | | } |
| | | |
| | | String join = StringUtils.join(param.getTypeIds(), ","); |
| | | |
| | | String[] split = warehouseAreas.getCode().split("\\."); |
| | | if (split.length == 0){ |
| | | if (split.length == 0) { |
| | | throw new CoolException("库区编码错误!!"); |
| | | } |
| | | StringBuilder locStar = new StringBuilder(); |
| | |
| | | } |
| | | |
| | | List<Loc> list = new ArrayList<>(); |
| | | Integer chanl = 0; //默认第一巷道 |
| | | Integer chanl = 0; // 默认第一巷道 |
| | | for (int r = param.getStartRow(); r <= param.getEndRow(); r++) { |
| | | try{ |
| | | Shelves shelves = new Shelves(param.getEndRow() - param.getStartRow() + 1, param.getChannel(),param.getStartRow()); |
| | | for (List<Integer> node : shelves.nodes){ |
| | | try { |
| | | Shelves shelves = new Shelves(param.getEndRow() - param.getStartRow() + 1, param.getChannel(), |
| | | param.getStartRow()); |
| | | for (List<Integer> node : shelves.nodes) { |
| | | if (node.contains(r)) { |
| | | if (!Cools.isEmpty(param.getStartChannel()) && param.getStartChannel() > 0){ |
| | | if (!Cools.isEmpty(param.getStartChannel()) && param.getStartChannel() > 0) { |
| | | chanl = shelves.nodes.indexOf(node) + param.getStartChannel(); |
| | | }else { |
| | | } else { |
| | | chanl = shelves.nodes.indexOf(node) + 1; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | }catch (Exception e){ |
| | | } catch (Exception e) { |
| | | throw new CoolException("解析巷道号失败"); |
| | | } |
| | | for (int b = param.getStartBay(); b <= param.getEndBay(); b++) { |
| | | for (int l = param.getStartLev(); l <= param.getEndLev(); l++) { |
| | | // 获取库位号 |
| | | String locNo = locStar + String.format("%d", r) + String.format("-%d", b) + String.format("-%d", l); |
| | | String locNo = locStar + String.format("%d", r) + String.format("-%d", b) + String.format("-%d", l); |
| | | Loc loc = new Loc(); |
| | | loc.setCode(locNo) |
| | | .setUseStatus("O") |
| | |
| | | |
| | | @Override |
| | | public boolean saveType(Loc loc) { |
| | | List<LocTypeRela> relas = new ArrayList<>(); |
| | | List<LocTypeRela> relas = new ArrayList<>(); |
| | | loc.getTypeIds().forEach(id -> { |
| | | LocTypeRela typeRela = new LocTypeRela(); |
| | | typeRela.setTypeId(id) |
| | |
| | | @Override |
| | | public boolean updateLoc(Loc loc) { |
| | | locTypeRelaMapper.delete(new LambdaQueryWrapper<LocTypeRela>().eq(LocTypeRela::getLocId, loc.getId())); |
| | | List<LocTypeRela> relas = new ArrayList<>(); |
| | | List<LocTypeRela> relas = new ArrayList<>(); |
| | | loc.getTypeIds().forEach(id -> { |
| | | LocTypeRela typeRela = new LocTypeRela(); |
| | | typeRela.setTypeId(id) |
| | |
| | | if (Objects.isNull(locs.getLocAreaId())) { |
| | | throw new CoolException("修改库位信息不能为空!!"); |
| | | } |
| | | List<LocArea> locAreas = locAreaService.list(new LambdaQueryWrapper<LocArea>().eq(LocArea::getId, locs.getLocAreaId())); |
| | | List<LocArea> locAreas = locAreaService |
| | | .list(new LambdaQueryWrapper<LocArea>().eq(LocArea::getId, locs.getLocAreaId())); |
| | | if (locAreas.isEmpty()) { |
| | | throw new CoolException("库位分区不存在!!"); |
| | | } |
| | |
| | | |
| | | /** |
| | | * 获取库位使用情况 |
| | | * |
| | | * @return |
| | | */ |
| | | @Override |
| | |
| | | |
| | | return waveItems; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @param id |
| | | * @return |
| | | * @author Ryan |
| | | * @description 完成出库单 |
| | | * @time 2025/4/25 10:07 |
| | | */ |
| | | @Override |
| | | public R completeOutOrderById(Long id) { |
| | | WkOrder order = this.getById(id); |
| | | if (Objects.isNull(order)) { |
| | | return R.error("出库单不存在!!"); |
| | | } |
| | | order.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val); |
| | | if (!this.updateById(order)) { |
| | | throw new CoolException("完成出库单失败!!"); |
| | | } |
| | | return R.ok("完成出库单成功!!"); |
| | | } |
| | | } |