From 52feee3e55403d2858da59605173ec055f601bfa Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期六, 24 十月 2026 19:47:25 +0800
Subject: [PATCH] feat(hrm): 同步新疆中亿装配的人力资源模块到北方科技

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java |  194 +++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 182 insertions(+), 12 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
index f03a1c0..d32b4c5 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -6,7 +6,7 @@
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.framework.operatelog.core.util.OperateLogUtils;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeEducationSaveReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeEmergencyContactSaveReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportExcelVO;
@@ -17,10 +17,12 @@
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeSaveReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeSimpleRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeWorkHistorySaveReqVO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeContractDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeEducationDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeEmergencyContactDO;
 import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeWorkHistoryDO;
+import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeContractMapper;
 import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEducationMapper;
 import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEmergencyContactMapper;
 import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper;
@@ -32,18 +34,21 @@
 import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
 import cn.iocoder.yudao.module.system.api.permission.RoleApi;
 import cn.iocoder.yudao.module.system.api.permission.dto.RoleRespDTO;
+import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
+import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserUpdateReqDTO;
-import com.mzt.logapi.starter.annotation.LogRecord;
 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.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -56,7 +61,6 @@
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
 import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.module.hrm.enums.LogRecordConstants.*;
 
 /**
  * 鍛樺伐淇℃伅 Service 瀹炵幇绫�
@@ -69,6 +73,8 @@
 
     @Resource
     private HrmEmployeeMapper employeeMapper;
+    @Resource
+    private HrmEmployeeContractMapper contractMapper;
     @Resource
     private HrmEmployeeEducationMapper educationMapper;
     @Resource
@@ -85,6 +91,8 @@
     private AdminUserApi adminUserApi;
     @Resource
     private RoleApi roleApi;
+    @Resource
+    private StorageAttachmentApi storageAttachmentApi;
     @Resource
     @Lazy // 鑷敞鍏ラ渶寤惰繜鍔犺浇锛屽惁鍒� bean 琚唬鐞嗗寘瑁呭悗娉ㄥ叆鍘熷鐗堟湰瀵艰嚧鍚姩澶辫触
     private HrmEmployeeService self;
@@ -132,6 +140,8 @@
         }
         employeeMapper.insert(employee);
         Long employeeId = employee.getId();
+        // 缁戝畾闄勪欢
+        storageAttachmentApi.bindAttachments("file", "hrm_employee", employeeId, createReqVO.getBlobIds());
         // 7. 鍚屾娣诲姞鏁欒偛缁忓巻
         if (CollUtil.isNotEmpty(createReqVO.getEducations())) {
             createReqVO.getEducations().forEach(educationVO -> {
@@ -213,6 +223,8 @@
         syncWorkHistoryList(employeeId, updateReqVO.getWorkHistories());
         // 鍚屾绱ф�ヨ仈绯讳汉
         syncEmergencyContactList(employeeId, updateReqVO.getEmergencyContacts());
+        // 鏇存柊闄勪欢
+        storageAttachmentApi.updateAttachments("file", "hrm_employee", employeeId, updateReqVO.getBlobIds());
     }
 
     private void syncEducationList(Long employeeId, List<HrmEmployeeEducationSaveReqVO> newList) {
@@ -260,6 +272,8 @@
         educationMapper.deleteByEmployeeId(id);
         workHistoryMapper.deleteByEmployeeId(id);
         emergencyContactMapper.deleteByEmployeeId(id);
+        // 鍒犻櫎闄勪欢
+        storageAttachmentApi.deleteAttachmentsByRecord("hrm_employee", id);
         // 鍒犻櫎鍛樺伐
         employeeMapper.deleteById(id);
     }
@@ -314,6 +328,8 @@
                 respVO.setRoleNames(roles.stream().map(RoleRespDTO::getName).collect(Collectors.joining(",")));
             }
         }
+        // 濉厖闄勪欢
+        respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_employee", id));
         return respVO;
     }
 
@@ -355,18 +371,67 @@
                 .filter(Objects::nonNull)
                 .collect(Collectors.toSet());
         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(deptIds);
+        // 瑙f瀽宀椾綅ID锛坧ost_ids 瀛樼殑鏄� JSON 鏁扮粍瀛楃涓诧紝濡� [38]锛夛紝骞舵壒閲忓姞杞藉矖浣嶅悕绉�
+        Map<Long, List<Long>> empPostIdsMap = new LinkedHashMap<>();
+        Set<Long> allPostIds = new LinkedHashSet<>();
+        for (HrmEmployeeDO emp : list) {
+            List<Long> postIdList = parseEmployeePostIds(emp.getPostIds());
+            empPostIdsMap.put(emp.getId(), postIdList);
+            allPostIds.addAll(postIdList);
+        }
+        Map<Long, PostRespDTO> postMap = CollUtil.isEmpty(allPostIds)
+                ? Collections.emptyMap() : postApi.getPostMap(allPostIds);
         return list.stream().map(emp -> {
             HrmEmployeeSimpleRespVO vo = new HrmEmployeeSimpleRespVO();
             vo.setId(emp.getId());
             vo.setEmployeeNo(emp.getEmployeeNo());
             vo.setName(emp.getName());
             vo.setEmployeeStatus(emp.getEmployeeStatus());
+            vo.setDeptId(emp.getDeptId());
             if (emp.getDeptId() != null && deptMap.containsKey(emp.getDeptId())) {
                 vo.setDeptName(deptMap.get(emp.getDeptId()).getName());
+            }
+            // 宀椾綅淇℃伅锛堢敤浜庤皟宀楃瓑鍦烘櫙鑷姩甯﹀嚭鍘熷矖浣嶏級
+            List<Long> postIdList = empPostIdsMap.getOrDefault(emp.getId(), Collections.emptyList());
+            vo.setPostIds(postIdList);
+            if (CollUtil.isNotEmpty(postIdList)) {
+                vo.setPostName(postIdList.stream()
+                        .map(postMap::get)
+                        .filter(Objects::nonNull)
+                        .map(PostRespDTO::getName)
+                        .collect(Collectors.joining(",")));
             }
             return vo;
         }).collect(Collectors.toList());
     }
+
+    /**
+     * 瑙f瀽鍛樺伐鐨勫矖浣岻D瀛楃涓诧紙JSON 鏁扮粍鏍煎紡锛屽 [38] 鎴� [1,2]锛�
+     */
+
+    /**
+     * 瑙f瀽鍛樺伐宀椾綅ID瀛楃涓诧紙post_ids 瀛� JSON 鏁扮粍锛屽 [38] 鎴� [1,2]锛�
+     */
+    private java.util.List<Long> parseEmployeePostIds(String postIds) {
+        if (StrUtil.isBlank(postIds)) {
+            return Collections.emptyList();
+        }
+
+        // post_ids 褰㈠ "[38]" 鎴� "[1,2]"锛氬幓鎺変腑鎷彿鍚庢寜閫楀彿瑙f瀽
+        return Arrays.stream(postIds.replace("[", "").replace("]", "").split(","))
+                .map(String::trim)
+                .filter(StrUtil::isNotBlank)
+                .map(s -> {
+                    try {
+                        return Long.valueOf(s);
+                    } catch (NumberFormatException ex) {
+                        return null;
+                    }
+                })
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+
 
     @Override
     public HrmEmployeeDO getEmployeeByUserId(Long userId) {
@@ -384,8 +449,6 @@
     }
 
     @Override
-    @LogRecord(type = HRM_EMPLOYEE_TYPE, subType = HRM_EMPLOYEE_IMPORT_SUB_TYPE, bizNo = "0",
-            success = HRM_EMPLOYEE_IMPORT_SUCCESS)
     public HrmEmployeeImportRespVO importEmployeeList(List<HrmEmployeeImportExcelVO> importEmployees,
                                                       HrmEmployeeImportReqVO importReqVO) {
         // 1. 鏍¢獙闈炵┖
@@ -435,9 +498,6 @@
                 respVO.getFailureNames().put(name, ex.getMessage());
             }
         }
-        // 璁板綍瀵煎叆缁撴灉姹囨�伙紝渚� @LogRecord 鐨� success 鏂囨寮曠敤
-        OperateLogUtils.putImportSummary(respVO.getCreateNames(), respVO.getUpdateNames(),
-                respVO.getFailureNames());
         return respVO;
     }
 
@@ -449,8 +509,9 @@
         if (StrUtil.isBlank(importEmployee.getPhone())) {
             throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鎵嬫満鍙�");
         }
-        if (importEmployee.getHireDate() == null) {
-            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鍏ヨ亴鏃ユ湡");
+        LocalDate hireDate = parseImportDate(importEmployee.getHireDate());
+        if (hireDate == null) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鍏ヨ亴鏃ユ湡(鏍煎紡锛�2015 鎴� 2015-01-01)");
         }
         HrmEmployeeSaveReqVO reqVO = new HrmEmployeeSaveReqVO();
         reqVO.setName(importEmployee.getName());
@@ -459,11 +520,11 @@
         reqVO.setDeptId(deptId);
         reqVO.setPostIds(CollUtil.isEmpty(postIds) ? null : new ArrayList<>(postIds));
         reqVO.setRoleIds(CollUtil.isEmpty(roleIds) ? null : new ArrayList<>(roleIds));
-        reqVO.setHireDate(importEmployee.getHireDate());
+        reqVO.setHireDate(hireDate);
         reqVO.setEmployeeStatus(importEmployee.getEmployeeStatus() != null
                 ? importEmployee.getEmployeeStatus() : 1); // 榛樿鍦ㄨ亴
         reqVO.setEmail(importEmployee.getEmail());
-        reqVO.setBirthday(importEmployee.getBirthday());
+        reqVO.setBirthday(parseImportDate(importEmployee.getBirthday()));
         reqVO.setIdCard(importEmployee.getIdCard());
         reqVO.setNation(importEmployee.getNation());
         reqVO.setMarriageStatus(importEmployee.getMarriageStatus());
@@ -471,6 +532,11 @@
         reqVO.setEducation(importEmployee.getEducation());
         reqVO.setPoliticalStatus(importEmployee.getPoliticalStatus());
         reqVO.setRemark(importEmployee.getRemark());
+        reqVO.setEmployeeCategory(importEmployee.getEmployeeCategory());
+        reqVO.setBaseSalary(importEmployee.getBaseSalary());
+        reqVO.setBankName(importEmployee.getBankName());
+        reqVO.setBankAccount(importEmployee.getBankAccount());
+        reqVO.setAddress(importEmployee.getAddress());
         return reqVO;
     }
 
@@ -526,4 +592,108 @@
         return roleIds;
     }
 
+    /**
+     * 瀹归敊瑙f瀽瀵煎叆鏃ユ湡鏂囨湰锛屾敮鎸侊細2015 / 2015骞� / 2015-01 / 2015-01-02 / 2015/1/2 / 2015.1.2 /
+     * 2015-01-02 00:00:00 / 20150102锛屼互鍙� Excel 鏃ユ湡搴忓垪鍙凤紱瑙f瀽涓嶅嚭杩斿洖 null銆�
+     */
+    private static LocalDate parseImportDate(String raw) {
+        if (StrUtil.isBlank(raw)) {
+            return null;
+        }
+        String s = raw.trim();
+        // 鍘绘帀鏃堕棿閮ㄥ垎
+        int sp = s.indexOf(' ');
+        if (sp > 0) {
+            s = s.substring(0, sp);
+        }
+        // 涓枃骞存湀鏃� / 鏂滄潬 / 鐐� / 涓嬪垝绾� 缁熶竴鎴� - 鍒嗛殧
+        s = s.replace("骞�", "-").replace("鏈�", "-").replace("鏃�", "")
+                .replace("/", "-").replace(".", "-").replace("_", "-").trim();
+        s = s.replaceAll("^-+|-+$", "");
+        if (StrUtil.isBlank(s)) {
+            return null;
+        }
+        try {
+            if (s.matches("\\d+")) {
+                int len = s.length();
+                if (len == 4) { // 2015
+                    return LocalDate.of(Integer.parseInt(s), 1, 1);
+                }
+                if (len == 5) { // Excel 鏃ユ湡搴忓垪鍙凤紙1900 鏃ユ湡绯荤粺锛屽熀鍑� 1899-12-30锛�
+                    return LocalDate.of(1899, 12, 30).plusDays(Long.parseLong(s));
+                }
+                if (len == 6) { // 201506
+                    return LocalDate.of(Integer.parseInt(s.substring(0, 4)), Integer.parseInt(s.substring(4, 6)), 1);
+                }
+                if (len == 8) { // 20150601
+                    return LocalDate.of(Integer.parseInt(s.substring(0, 4)), Integer.parseInt(s.substring(4, 6)), Integer.parseInt(s.substring(6, 8)));
+                }
+                return null;
+            }
+            String[] parts = s.split("-");
+            if (parts.length == 2) { // 2015-06
+                return LocalDate.of(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), 1);
+            }
+            if (parts.length >= 3) { // 2015-06-01
+                return LocalDate.of(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
+            }
+        } catch (Exception e) {
+            return null;
+        }
+        return null;
+    }
+
+    // ========== 杞 ==========
+
+    @Override
+    public void regularizeEmployee(Long id) {
+        validateEmployee(id);
+        HrmEmployeeContractDO contract = findCurrentContract(id);
+        // 浠呫�屽姵鍔ㄥ悎鍚屻�嶅彲杞锛涘姵鍔″悎鍚屼笉杞
+        if (contract == null || !Integer.valueOf(1).equals(contract.getContractType())) {
+            throw exception(EMPLOYEE_REGULARIZE_NEED_LABOR_CONTRACT);
+        }
+        HrmEmployeeDO updateObj = new HrmEmployeeDO();
+        updateObj.setId(id);
+        updateObj.setEmployeeStatus(1); // 1-鍦ㄨ亴
+        updateObj.setRegularDate(LocalDate.now());
+        employeeMapper.updateById(updateObj);
+    }
+
+    @Override
+    public List<HrmEmployeeDO> getRegularizeReminderList(Integer days) {
+        int aheadDays = days == null ? 7 : days;
+        LocalDate limit = LocalDate.now().plusDays(aheadDays);
+        // 璇曠敤涓殑鍛樺伐
+        List<HrmEmployeeDO> trials = employeeMapper.selectList(
+                new LambdaQueryWrapperX<HrmEmployeeDO>().eq(HrmEmployeeDO::getEmployeeStatus, 2));
+        List<HrmEmployeeDO> result = new ArrayList<>();
+        for (HrmEmployeeDO employee : trials) {
+            HrmEmployeeContractDO contract = findCurrentContract(employee.getId());
+            // 浠呭姵鍔ㄥ悎鍚屻�佷笖璇曠敤鏈熷嵆灏嗗埌鏈�
+            if (contract == null || !Integer.valueOf(1).equals(contract.getContractType())) {
+                continue;
+            }
+            LocalDate probationEnd = contract.getProbationEndDate();
+            if (probationEnd != null && !probationEnd.isAfter(limit)) {
+                result.add(employee);
+            }
+        }
+        return result;
+    }
+
+    /** 鏌ヨ鍛樺伐褰撳墠鐢熸晥鍚堝悓 */
+    private HrmEmployeeContractDO findCurrentContract(Long employeeId) {
+        List<HrmEmployeeContractDO> list = contractMapper.selectListByEmployee(employeeId);
+        if (CollUtil.isEmpty(list)) {
+            return null;
+        }
+        for (HrmEmployeeContractDO contract : list) {
+            if (Boolean.TRUE.equals(contract.getIsCurrent())) {
+                return contract;
+            }
+        }
+        return null;
+    }
+
 }
\ No newline at end of file

--
Gitblit v1.9.3