package cn.iocoder.yudao.module.mes.service.wm.warehouse; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseImportExcelVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseImportRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehousePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse.MesWmWarehouseMapper; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 仓库 Service 实现类 */ @Service @Validated public class MesWmWarehouseServiceImpl implements MesWmWarehouseService { @Resource private MesWmWarehouseMapper warehouseMapper; @Resource private AdminUserApi adminUserApi; @Resource private MesWmWarehouseLocationService locationService; @Resource @Lazy private MesMdWorkstationService workstationService; @Resource private MesWmMaterialStockService materialStockService; @Resource private MesWmBarcodeService barcodeService; @Override public Long createWarehouse(MesWmWarehouseSaveReqVO createReqVO) { // 校验虚拟仓库不允许新增 validateNotVirtual(createReqVO.getCode()); // 校验数据 validateWarehouseSaveData(createReqVO); // 插入 MesWmWarehouseDO warehouse = BeanUtils.toBean(createReqVO, MesWmWarehouseDO.class); warehouseMapper.insert(warehouse); // 自动生成条码 barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WAREHOUSE.getValue(), warehouse.getId(), warehouse.getCode(), warehouse.getName()); return warehouse.getId(); } @Override public void updateWarehouse(MesWmWarehouseSaveReqVO updateReqVO) { // 校验存在 MesWmWarehouseDO warehouse = validateWarehouseExists(updateReqVO.getId()); // 校验虚拟仓库不允许修改 validateNotVirtual(warehouse.getCode()); // 校验数据 validateWarehouseSaveData(updateReqVO); // 更新 MesWmWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, MesWmWarehouseDO.class); warehouseMapper.updateById(updateObj); } private void validateWarehouseSaveData(MesWmWarehouseSaveReqVO reqVO) { // 校验编码唯一 validateWarehouseCodeUnique(reqVO.getId(), reqVO.getCode()); // 校验名称唯一 validateWarehouseNameUnique(reqVO.getId(), reqVO.getName()); } private void validateNotVirtual(String code) { if (MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE.equals(code)) { throw exception(WM_WAREHOUSE_IS_VIRTUAL); } } @Override public void deleteWarehouse(Long id) { // 校验存在 MesWmWarehouseDO warehouse = validateWarehouseExists(id); // 校验虚拟仓库不允许删除 validateNotVirtual(warehouse.getCode()); // 校验是否有库区 if (locationService.getWarehouseLocationCountByWarehouseId(id) > 0) { throw exception(WM_WAREHOUSE_HAS_LOCATION); } // 校验是否被工作站引用 if (workstationService.getWorkstationCountByWarehouseId(id) > 0) { throw exception(WM_WAREHOUSE_HAS_WORKSTATION); } // 校验是否有库存记录 if (materialStockService.getMaterialStockCountByWarehouseId(id) > 0) { throw exception(WM_WAREHOUSE_HAS_MATERIAL_STOCK); } // 删除 warehouseMapper.deleteById(id); } @Override public MesWmWarehouseDO validateWarehouseExists(Long id) { MesWmWarehouseDO warehouse = warehouseMapper.selectById(id); if (warehouse == null) { throw exception(WM_WAREHOUSE_NOT_EXISTS); } return warehouse; } private void validateWarehouseCodeUnique(Long id, String code) { MesWmWarehouseDO warehouse = warehouseMapper.selectByCode(code); if (warehouse == null) { return; } if (ObjUtil.notEqual(warehouse.getId(), id)) { throw exception(WM_WAREHOUSE_CODE_DUPLICATE); } } private void validateWarehouseNameUnique(Long id, String name) { MesWmWarehouseDO warehouse = warehouseMapper.selectByName(name); if (warehouse == null) { return; } if (ObjUtil.notEqual(warehouse.getId(), id)) { throw exception(WM_WAREHOUSE_NAME_DUPLICATE); } } @Override public MesWmWarehouseDO getWarehouse(Long id) { return warehouseMapper.selectById(id); } @Override public PageResult getWarehousePage(MesWmWarehousePageReqVO pageReqVO) { return warehouseMapper.selectPage(pageReqVO); } @Override public List getWarehouseList() { return warehouseMapper.selectSimpleList(); } @Override public List getWarehouseList(Collection ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } return warehouseMapper.selectListByIds(ids); } @Override public MesWmWarehouseDO getWarehouseByCode(String code) { // 1. 查询仓库,存在则直接返回 MesWmWarehouseDO warehouse = warehouseMapper.selectByCode(code); if (warehouse != null) { return warehouse; } // 2. 如果是虚拟线边库编码,则自动初始化 if (MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE.equals(code)) { MesWmWarehouseDO newWarehouse = MesWmWarehouseDO.builder() .code(code).name("虚拟线边仓库").frozen(false) .remark("系统自动初始化的虚拟线边仓库(用于生产报工与在制品管理解耦)") .build(); warehouseMapper.insert(newWarehouse); return newWarehouse; } return null; } @Override @Transactional(rollbackFor = Exception.class) public MesWmWarehouseImportRespVO importWarehouseList(List importList, boolean updateSupport) { // 校验导入数据不能为空 if (CollUtil.isEmpty(importList)) { throw exception(WM_WAREHOUSE_IMPORT_LIST_IS_EMPTY); } MesWmWarehouseImportRespVO respVO = MesWmWarehouseImportRespVO.builder() .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>()) .failureCodes(new LinkedHashMap<>()).build(); // 索引,用于错误提示 AtomicInteger index = new AtomicInteger(1); importList.forEach(importItem -> { int currentIndex = index.getAndIncrement(); String code = importItem.getCode(); String key = StrUtil.blankToDefault(code, "第 " + currentIndex + " 行"); // 校验编码必填 if (StrUtil.isBlank(code)) { respVO.getFailureCodes().put(key, "仓库编码不能为空"); return; } // 校验名称必填 if (StrUtil.isBlank(importItem.getName())) { respVO.getFailureCodes().put(key, "仓库名称不能为空"); return; } // 校验虚拟仓库不允许导入 if (MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE.equals(code)) { respVO.getFailureCodes().put(key, "虚拟仓库不允许导入"); return; } // 按名称解析负责人 Long chargeUserId = null; if (StrUtil.isNotBlank(importItem.getChargeUserName())) { chargeUserId = resolveChargeUserId(importItem.getChargeUserName()); if (chargeUserId == null) { respVO.getFailureCodes().put(key, "负责人不存在:" + importItem.getChargeUserName()); return; } } MesWmWarehouseDO existingByCode = warehouseMapper.selectByCode(code); MesWmWarehouseDO existingByName = warehouseMapper.selectByName(importItem.getName()); if (existingByCode != null && updateSupport) { // 名称唯一校验(排除自己) if (existingByName != null && !existingByCode.getId().equals(existingByName.getId())) { respVO.getFailureCodes().put(key, "仓库名称已存在:" + importItem.getName()); return; } // 更新 MesWmWarehouseDO updateObj = new MesWmWarehouseDO(); updateObj.setId(existingByCode.getId()); updateObj.setName(importItem.getName()); updateObj.setType(importItem.getType()); updateObj.setAddress(importItem.getAddress()); updateObj.setArea(importItem.getArea()); updateObj.setChargeUserId(chargeUserId); updateObj.setFrozen(importItem.getFrozen()); updateObj.setRemark(importItem.getRemark()); warehouseMapper.updateById(updateObj); respVO.getUpdateCodes().add(code); } else if (existingByCode != null) { respVO.getFailureCodes().put(key, "仓库编码已存在:" + code); } else { // 名称唯一校验 if (existingByName != null) { respVO.getFailureCodes().put(key, "仓库名称已存在:" + importItem.getName()); return; } // 创建 MesWmWarehouseDO createObj = new MesWmWarehouseDO(); createObj.setId(null); createObj.setCode(code); createObj.setName(importItem.getName()); createObj.setType(importItem.getType()); createObj.setAddress(importItem.getAddress()); createObj.setArea(importItem.getArea()); createObj.setChargeUserId(chargeUserId); createObj.setFrozen(ObjUtil.defaultIfNull(importItem.getFrozen(), Boolean.FALSE)); createObj.setRemark(importItem.getRemark()); warehouseMapper.insert(createObj); // 自动生成条码 barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WAREHOUSE.getValue(), createObj.getId(), createObj.getCode(), createObj.getName()); respVO.getCreateCodes().add(code); } }); return respVO; } private Long resolveChargeUserId(String chargeUserName) { List users = adminUserApi.getUserListByNickname(chargeUserName); for (AdminUserRespDTO user : users) { if (chargeUserName.equals(user.getNickname())) { return user.getId(); } } return null; } }