| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemCreateReqDTO; |
| | | import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi; |
| | | import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO; |
| | | import cn.iocoder.yudao.module.mdm.enums.MdmItemTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.api.item.MesMdItemApi; |
| | | import cn.iocoder.yudao.module.mes.api.item.dto.MesMdItemSyncReqDTO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportExcelVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachinerySaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.dv.machinery.MesDvMachineryMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanMachineryService; |
| | | import cn.iocoder.yudao.module.mes.service.dv.checkrecord.MesDvCheckRecordService; |
| | | import cn.iocoder.yudao.module.mes.service.dv.maintenrecord.MesDvMaintenRecordService; |
| | | import cn.iocoder.yudao.module.mes.service.dv.repair.MesDvRepairService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | | import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; |
| | | import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkshopService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; |
| | | 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.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | |
| | | @Service |
| | | @Validated |
| | | public class MesDvMachineryServiceImpl implements MesDvMachineryService { |
| | | |
| | | /** |
| | | * 设备联动物料的类型编码(mes_md_item_type / mdm_item_category 中“设备”行的 code) |
| | | */ |
| | | private static final String EQUIPMENT_ITEM_TYPE_CODE = "EQUIPMENT"; |
| | | /** |
| | | * 设备联动物料的计量单位编码(mes_md_unit_measure / mdm_unit_measure 中“台”行的 code) |
| | | */ |
| | | private static final String EQUIPMENT_UNIT_CODE = "TAI"; |
| | | |
| | | @Resource |
| | | private MesDvMachineryMapper machineryMapper; |
| | |
| | | @Lazy |
| | | private MesDvRepairService repairService; |
| | | |
| | | // ========== 设备物料联动依赖 ========== |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | | @Resource |
| | | private MdmUnitMeasureApi mdmUnitMeasureApi; |
| | | @Resource |
| | | private MesMdItemApi mesMdItemApi; |
| | | @Resource |
| | | @Lazy |
| | | private MesMdItemTypeService mesMdItemTypeService; |
| | | @Resource |
| | | @Lazy |
| | | private MesMdUnitMeasureService mesMdUnitMeasureService; |
| | | @Resource |
| | | private MesWmTransactionService wmTransactionService; |
| | | @Resource |
| | | private MesWmWarehouseService wmWarehouseService; |
| | | @Resource |
| | | private MesWmWarehouseLocationService wmLocationService; |
| | | @Resource |
| | | private MesWmWarehouseAreaService wmAreaService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createMachinery(MesDvMachinerySaveReqVO createReqVO) { |
| | | // 校验设备类型存在 |
| | | machineryTypeService.getMachineryType(createReqVO.getMachineryTypeId()); |
| | |
| | | // 校验编码唯一 |
| | | validateMachineryCodeUnique(null, createReqVO.getCode()); |
| | | |
| | | // 插入 |
| | | // 创建对应 MDM 物料并同步 MES 物料(同一事务,失败整体回滚) |
| | | Long itemId = createEquipmentMaterial(createReqVO.getCode(), createReqVO.getName(), |
| | | createReqVO.getSpecification(), createReqVO.getRemark()); |
| | | |
| | | // 插入设备台账 |
| | | MesDvMachineryDO machinery = BeanUtils.toBean(createReqVO, MesDvMachineryDO.class); |
| | | machinery.setItemId(itemId); |
| | | machineryMapper.insert(machinery); |
| | | |
| | | // 自动生成条码 |
| | | barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.MACHINERY.getValue(), |
| | | machinery.getId(), machinery.getCode(), machinery.getName()); |
| | | // 自动入设备仓(库存 + 流水) |
| | | createEquipmentStock(itemId, machinery.getId(), machinery.getCode()); |
| | | return machinery.getId(); |
| | | } |
| | | |
| | |
| | | public void updateMachinery(MesDvMachinerySaveReqVO updateReqVO) { |
| | | // 校验存在 |
| | | validateMachineryExists(updateReqVO.getId()); |
| | | MesDvMachineryDO existMachinery = machineryMapper.selectById(updateReqVO.getId()); |
| | | // 校验设备类型存在 |
| | | machineryTypeService.getMachineryType(updateReqVO.getMachineryTypeId()); |
| | | // 校验车间存在 |
| | |
| | | |
| | | // 更新 |
| | | MesDvMachineryDO updateObj = BeanUtils.toBean(updateReqVO, MesDvMachineryDO.class); |
| | | // 物料关联由创建时自动生成,更新不允许清空(前端也不传入 itemId) |
| | | updateObj.setItemId(existMachinery.getItemId()); |
| | | machineryMapper.updateById(updateObj); |
| | | } |
| | | |
| | |
| | | public void deleteMachinery(Long id) { |
| | | // 校验存在 |
| | | validateMachineryExists(id); |
| | | // 校验已生成物料并入设备仓:避免库存/流水失去业务主体,禁止删除 |
| | | MesDvMachineryDO machinery = machineryMapper.selectById(id); |
| | | if (machinery.getItemId() != null) { |
| | | throw exception(DV_MACHINERY_HAS_ITEM); |
| | | } |
| | | // 校验关联数据 |
| | | if (checkPlanMachineryService.getCheckPlanMachineryCountByMachineryId(id) > 0) { |
| | | throw exception(DV_MACHINERY_HAS_CHECK_PLAN); |
| | |
| | | machinery.setMachineryTypeId(machineryType.getId()); |
| | | machinery.setWorkshopId(workshop.getId()); |
| | | machinery.setWorkstationId(workstationId); |
| | | // 创建对应 MDM 物料并同步 MES 物料(同一事务) |
| | | machinery.setItemId(createEquipmentMaterial(machinery.getCode(), machinery.getName(), |
| | | machinery.getSpecification(), machinery.getRemark())); |
| | | machineryMapper.insert(machinery); |
| | | // 自动生成条码 |
| | | barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.MACHINERY.getValue(), |
| | | machinery.getId(), machinery.getCode(), machinery.getName()); |
| | | // 自动入设备仓(库存 + 流水) |
| | | createEquipmentStock(machinery.getItemId(), machinery.getId(), machinery.getCode()); |
| | | respVO.getCreateCodes().add(importItem.getCode()); |
| | | } else if (updateSupport) { |
| | | // 3.5.2 更新 |
| | |
| | | updateObj.setMachineryTypeId(machineryType.getId()); |
| | | updateObj.setWorkshopId(workshop.getId()); |
| | | updateObj.setWorkstationId(workstationId); |
| | | // 物料关联由创建时自动生成,更新不允许清空 |
| | | updateObj.setItemId(existMachinery.getItemId()); |
| | | machineryMapper.updateById(updateObj); |
| | | respVO.getUpdateCodes().add(importItem.getCode()); |
| | | } else { |
| | |
| | | return respVO; |
| | | } |
| | | |
| | | /** |
| | | * 创建设备对应物料:先在 MDM 建主数据物料,再显式同步 MES 物料(两套主数据 id 对齐)。 |
| | | * |
| | | * @return MDM 物料编号(= MES 物料编号) |
| | | */ |
| | | private Long createEquipmentMaterial(String code, String name, String specification, String remark) { |
| | | // 1. 解析“设备”类型(MES 侧)与“台”单位(MDM 侧 + MES 侧),缺失则提示主数据未初始化 |
| | | MesMdItemTypeDO itemType = mesMdItemTypeService.getItemTypeByCode(EQUIPMENT_ITEM_TYPE_CODE); |
| | | if (itemType == null) { |
| | | throw exception(DV_MACHINERY_EQUIP_MASTER_MISSING); |
| | | } |
| | | if (mesMdUnitMeasureService.getUnitMeasureByCode(EQUIPMENT_UNIT_CODE) == null) { |
| | | throw exception(DV_MACHINERY_EQUIP_MASTER_MISSING); |
| | | } |
| | | CommonResult<MdmUnitMeasureRespDTO> unitResult = mdmUnitMeasureApi.getUnitMeasureByCode(EQUIPMENT_UNIT_CODE); |
| | | MdmUnitMeasureRespDTO mdmUnit = unitResult.isSuccess() ? unitResult.getData() : null; |
| | | if (mdmUnit == null) { |
| | | throw exception(DV_MACHINERY_EQUIP_MASTER_MISSING); |
| | | } |
| | | |
| | | // 2. 创建 MDM 物料;分类使用“设备”分类(其 id 与 MES 类型 id 对齐,由初始化脚本保证) |
| | | MdmItemCreateReqDTO createReqDTO = new MdmItemCreateReqDTO(); |
| | | createReqDTO.setCode(code); |
| | | createReqDTO.setName(name); |
| | | createReqDTO.setSpecification(specification); |
| | | createReqDTO.setRemark(remark); |
| | | createReqDTO.setCategoryId(itemType.getId()); |
| | | createReqDTO.setUnitMeasureId(mdmUnit.getId()); |
| | | createReqDTO.setItemType(MdmItemTypeEnum.EQUIPMENT.getType()); |
| | | createReqDTO.setStatus(0); |
| | | createReqDTO.setIsBatchManaged(false); |
| | | Long mdmItemId = mdmItemApi.createItem(createReqDTO).getCheckedData(); |
| | | |
| | | // 3. 显式同步 MES 物料(MdmItemCreateReqDTO 无 syncMes 开关,不会自动同步) |
| | | MesMdItemSyncReqDTO syncReqDTO = new MesMdItemSyncReqDTO(); |
| | | syncReqDTO.setCode(code); |
| | | syncReqDTO.setName(name); |
| | | syncReqDTO.setSpecification(specification); |
| | | syncReqDTO.setRemark(remark); |
| | | syncReqDTO.setUnitCode(EQUIPMENT_UNIT_CODE); |
| | | syncReqDTO.setItemTypeCode(EQUIPMENT_ITEM_TYPE_CODE); |
| | | syncReqDTO.setBatchFlag(false); |
| | | syncReqDTO.setSafeStockFlag(false); |
| | | syncReqDTO.setStatus(0); |
| | | syncReqDTO.setMdmItemId(mdmItemId); |
| | | mesMdItemApi.createItem(syncReqDTO); |
| | | return mdmItemId; |
| | | } |
| | | |
| | | /** |
| | | * 设备自动入设备仓:创建一条入库数量为 1 的库存事务,仓库/库区/库位取系统内置设备仓。 |
| | | * 库存行、数量与流水统一经 {@link MesWmTransactionService},禁止直接写库存表。 |
| | | */ |
| | | private void createEquipmentStock(Long itemId, Long machineryId, String machineryCode) { |
| | | MesWmWarehouseDO warehouse = wmWarehouseService.getWarehouseByCode(MesWmWarehouseDO.EQUIPMENT_WAREHOUSE); |
| | | MesWmWarehouseLocationDO location = wmLocationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.EQUIPMENT_LOCATION); |
| | | MesWmWarehouseAreaDO area = wmAreaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.EQUIPMENT_AREA); |
| | | if (warehouse == null || location == null || area == null) { |
| | | throw exception(DV_MACHINERY_EQUIP_MASTER_MISSING); |
| | | } |
| | | wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() |
| | | .setType(MesWmTransactionTypeEnum.IN.getType()) |
| | | .setItemId(itemId) |
| | | .setQuantity(BigDecimal.ONE) |
| | | .setWarehouseId(warehouse.getId()) |
| | | .setLocationId(location.getId()) |
| | | .setAreaId(area.getId()) |
| | | .setBizType(MesBizTypeConstants.DV_MACHINERY) |
| | | .setBizId(machineryId) |
| | | .setBizCode(machineryCode) |
| | | .setBizLineId(machineryId)); |
| | | } |
| | | |
| | | } |