From b852254d90e7d1955db31db154193ec8ee84d8b3 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 09 九月 2026 10:57:59 +0800
Subject: [PATCH] feat(hrm): 新增员工用工性质、班组归属字段及考勤异常处理优化

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java |  152 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 150 insertions(+), 2 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
index 35ded24..45568db 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
@@ -3,30 +3,51 @@
 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;
@@ -43,6 +64,15 @@
 @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;
@@ -71,7 +101,30 @@
     @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());
@@ -80,13 +133,20 @@
         // 鏍¢獙缂栫爜鍞竴
         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();
     }
 
@@ -94,6 +154,7 @@
     public void updateMachinery(MesDvMachinerySaveReqVO updateReqVO) {
         // 鏍¢獙瀛樺湪
         validateMachineryExists(updateReqVO.getId());
+        MesDvMachineryDO existMachinery = machineryMapper.selectById(updateReqVO.getId());
         // 鏍¢獙璁惧绫诲瀷瀛樺湪
         machineryTypeService.getMachineryType(updateReqVO.getMachineryTypeId());
         // 鏍¢獙杞﹂棿瀛樺湪
@@ -103,6 +164,8 @@
 
         // 鏇存柊
         MesDvMachineryDO updateObj = BeanUtils.toBean(updateReqVO, MesDvMachineryDO.class);
+        // 鐗╂枡鍏宠仈鐢卞垱寤烘椂鑷姩鐢熸垚锛屾洿鏂颁笉鍏佽娓呯┖锛堝墠绔篃涓嶄紶鍏� itemId锛�
+        updateObj.setItemId(existMachinery.getItemId());
         machineryMapper.updateById(updateObj);
     }
 
@@ -110,6 +173,11 @@
     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);
@@ -279,10 +347,15 @@
                 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 鏇存柊
@@ -291,6 +364,8 @@
                 updateObj.setMachineryTypeId(machineryType.getId());
                 updateObj.setWorkshopId(workshop.getId());
                 updateObj.setWorkstationId(workstationId);
+                // 鐗╂枡鍏宠仈鐢卞垱寤烘椂鑷姩鐢熸垚锛屾洿鏂颁笉鍏佽娓呯┖
+                updateObj.setItemId(existMachinery.getItemId());
                 machineryMapper.updateById(updateObj);
                 respVO.getUpdateCodes().add(importItem.getCode());
             } else {
@@ -301,4 +376,77 @@
         return respVO;
     }
 
+    /**
+     * 鍒涘缓璁惧瀵瑰簲鐗╂枡锛氬厛鍦� MDM 寤轰富鏁版嵁鐗╂枡锛屽啀鏄惧紡鍚屾 MES 鐗╂枡锛堜袱濂椾富鏁版嵁 id 瀵归綈锛夈��
+     *
+     * @return MDM 鐗╂枡缂栧彿锛�= MES 鐗╂枡缂栧彿锛�
+     */
+    private Long createEquipmentMaterial(String code, String name, String specification, String remark) {
+        // 1. 瑙f瀽鈥滆澶団�濈被鍨嬶紙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 鐗╂枡锛圡dmItemCreateReqDTO 鏃� 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));
+    }
+
 }

--
Gitblit v1.9.3