package com.ruoyi.staff.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.dto.WordDateDto; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysPost; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysPostMapper; import com.ruoyi.staff.dto.StaffOnJobDto; import com.ruoyi.staff.dto.StaffOnJobImportDto; import com.ruoyi.staff.mapper.StaffContractMapper; import com.ruoyi.staff.mapper.StaffLeaveMapper; import com.ruoyi.staff.mapper.StaffOnJobMapper; import com.ruoyi.staff.pojo.StaffContract; import com.ruoyi.staff.pojo.StaffLeave; import com.ruoyi.staff.pojo.StaffOnJob; import com.ruoyi.staff.service.IStaffOnJobService; import freemarker.template.Configuration; import freemarker.template.Template; import lombok.AllArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @AllArgsConstructor @Service public class StaffOnJobServiceImpl extends ServiceImpl implements IStaffOnJobService { @Autowired private StaffOnJobMapper staffOnJobMapper; @Autowired private SysPostMapper sysPostMapper; @Autowired private SysDeptMapper sysDeptMapper; @Autowired private StaffContractMapper staffContractMapper; @Autowired private StaffLeaveMapper staffLeaveMapper; @Override public IPage staffOnJobListPage(Page page, StaffOnJob staffOnJob) { IPage result = staffOnJobMapper.staffOnJobListPage(page, staffOnJob); fillNationFallback(result.getRecords()); return result; } @Override @Transactional(rollbackFor = Exception.class) public int add(StaffOnJobDto staffOnJobParams) { syncStaffBasicFields(staffOnJobParams); List existedStaffNo = staffOnJobMapper.selectList(Wrappers.lambdaQuery() .eq(StaffOnJob::getStaffNo, staffOnJobParams.getStaffNo())); if (!CollectionUtils.isEmpty(existedStaffNo)) { throw new BaseException("Duplicate staffNo: " + staffOnJobParams.getStaffNo()); } staffOnJobParams.setContractExpireTime(staffOnJobParams.getContractEndTime()); staffOnJobParams.setStaffState(1); staffOnJobMapper.insert(staffOnJobParams); StaffContract staffContract = new StaffContract(); staffContract.setStaffOnJobId(staffOnJobParams.getId()); staffContract.setContractTerm(staffOnJobParams.getContractTerm()); staffContract.setContractStartTime(staffOnJobParams.getContractStartTime()); staffContract.setContractEndTime(staffOnJobParams.getContractEndTime()); return staffContractMapper.insert(staffContract); } @Override @Transactional(rollbackFor = Exception.class) public int update(Long id, StaffOnJobDto staffOnJobParams) { syncStaffBasicFields(staffOnJobParams); staffOnJobParams.setId(id); StaffOnJob job = staffOnJobMapper.selectById(id); if (job == null) { throw new BaseException("Staff not found, id=" + id); } if (StringUtils.isNotBlank(staffOnJobParams.getStaffNo())) { List existedStaffNo = staffOnJobMapper.selectList(Wrappers.lambdaQuery() .eq(StaffOnJob::getStaffNo, staffOnJobParams.getStaffNo()) .ne(StaffOnJob::getId, id)); if (!CollectionUtils.isEmpty(existedStaffNo)) { throw new BaseException("Duplicate staffNo: " + staffOnJobParams.getStaffNo()); } } String[] ignoreProperties = {"id"}; StaffContract contract = staffContractMapper.selectOne(Wrappers.lambdaQuery() .eq(StaffContract::getStaffOnJobId, id) .orderByDesc(StaffContract::getId) .last("limit 1")); if (contract != null) { BeanUtils.copyProperties(staffOnJobParams, contract, ignoreProperties); staffContractMapper.updateById(contract); } staffOnJobParams.setContractExpireTime(staffOnJobParams.getContractEndTime()); return staffOnJobMapper.updateById(staffOnJobParams); } @Override @Transactional(rollbackFor = Exception.class) public int delStaffOnJobs(List ids) { staffOnJobMapper.deleteBatchIds(ids); staffLeaveMapper.delete(Wrappers.lambdaQuery().in(StaffLeave::getStaffOnJobId, ids)); return staffContractMapper.delete(Wrappers.lambdaQuery().in(StaffContract::getStaffOnJobId, ids)); } @Override @Transactional(rollbackFor = Exception.class) public int renewContract(Long id, StaffContract staffContract) { StaffOnJob job = staffOnJobMapper.selectById(id); if (job == null) { throw new BaseException("Staff not found, id=" + id); } StaffContract newStaffContract = new StaffContract(); newStaffContract.setStaffOnJobId(id); newStaffContract.setContractTerm(staffContract.getContractTerm()); newStaffContract.setContractStartTime(staffContract.getContractStartTime()); newStaffContract.setContractEndTime(staffContract.getContractEndTime()); staffContractMapper.insert(newStaffContract); job.setContractExpireTime(staffContract.getContractEndTime()); staffOnJobMapper.updateById(job); return 0; } @Override public StaffOnJobDto staffOnJobDetail(Long id) { StaffOnJob staffOnJob = staffOnJobMapper.selectById(id); if (staffOnJob == null) { throw new BaseException("Staff not found, id=" + id); } StaffOnJobDto staffOnJobDto = new StaffOnJobDto(); BeanUtils.copyProperties(staffOnJob, staffOnJobDto); if (staffOnJob.getSysPostId() != null) { SysPost post = sysPostMapper.selectPostById(staffOnJob.getSysPostId().longValue()); if (post != null) { staffOnJobDto.setPostName(post.getPostName()); } } StaffContract contract = staffContractMapper.selectOne(Wrappers.lambdaQuery() .eq(StaffContract::getStaffOnJobId, staffOnJob.getId()) .orderByDesc(StaffContract::getId) .last("limit 1")); if (contract != null) { staffOnJobDto.setContractTerm(contract.getContractTerm()); staffOnJobDto.setContractStartTime(contract.getContractStartTime()); staffOnJobDto.setContractEndTime(contract.getContractEndTime()); } fillNationFallback(staffOnJobDto); return staffOnJobDto; } @Override public void staffOnJobExport(HttpServletResponse response, StaffOnJob staffOnJob) { List staffOnJobs = staffOnJobMapper.staffOnJobList(staffOnJob); fillNationFallback(staffOnJobs); ExcelUtil util = new ExcelUtil<>(StaffOnJobDto.class); util.exportExcel(response, staffOnJobs, "在职员工台账导出"); } @Override public List staffOnJobList(StaffOnJob staffOnJob) { List staffOnJobs = staffOnJobMapper.staffOnJobList(staffOnJob); fillNationFallback(staffOnJobs); return staffOnJobs; } @Override @Transactional(rollbackFor = Exception.class) public Boolean importData(MultipartFile file) { try { ExcelUtil util = new ExcelUtil<>(StaffOnJobImportDto.class); List staffOnJobs = util.importExcel(file.getInputStream()); if (CollectionUtils.isEmpty(staffOnJobs)) { throw new BaseException("Import data is empty"); } Map postMap = buildPostMap(); Map deptMap = buildDeptMap(); Set importedStaffNos = new HashSet<>(); for (int i = 0; i < staffOnJobs.size(); i++) { StaffOnJobDto staffOnJobDto = buildImportStaff(staffOnJobs.get(i), i + 2, postMap, deptMap, importedStaffNos); add(staffOnJobDto); } return true; } catch (Exception e) { if (e instanceof BaseException) { throw (BaseException) e; } throw new BaseException("Import failed, please check template and data format"); } } private StaffOnJobDto buildImportStaff(StaffOnJobImportDto row, int rowNum, Map postMap, Map deptMap, Set importedStaffNos) { String staffNo = normalizeValue(row.getStaffNo()); String postName = normalizeValue(row.getPostName()); String deptName = normalizeValue(row.getDeptName()); if (StringUtils.isBlank(staffNo)) { throw new BaseException("Row " + rowNum + " staffNo cannot be blank"); } if (!importedStaffNos.add(staffNo)) { throw new BaseException("Row " + rowNum + " duplicated staffNo: " + staffNo); } if (StringUtils.isBlank(normalizeValue(row.getStaffName()))) { throw new BaseException("Row " + rowNum + " staffName cannot be blank"); } if (StringUtils.isBlank(postName)) { throw new BaseException("Row " + rowNum + " postName cannot be blank"); } if (StringUtils.isBlank(deptName)) { throw new BaseException("Row " + rowNum + " deptName cannot be blank"); } if (row.getContractStartTime() == null) { throw new BaseException("Row " + rowNum + " contractStartTime cannot be blank"); } if (row.getContractEndTime() == null) { throw new BaseException("Row " + rowNum + " contractEndTime cannot be blank"); } if (row.getEntryDate() == null) { throw new BaseException("Row " + rowNum + " entryDate cannot be blank"); } SysPost post = postMap.get(postName); if (post == null) { throw new BaseException("Row " + rowNum + " post not found or disabled: " + postName); } SysDept dept = deptMap.get(deptName); if (dept == null) { throw new BaseException("Row " + rowNum + " dept not found or disabled: " + deptName); } StaffOnJobDto staffOnJobDto = new StaffOnJobDto(); BeanUtils.copyProperties(row, staffOnJobDto); staffOnJobDto.setStaffNo(staffNo); staffOnJobDto.setStaffName(normalizeValue(row.getStaffName())); staffOnJobDto.setSex(normalizeValue(row.getSex())); staffOnJobDto.setNation(normalizeValue(row.getNation())); staffOnJobDto.setNativePlace(normalizeValue(row.getNation())); staffOnJobDto.setBirthDate(row.getBirthDate()); staffOnJobDto.setIdentityCard(normalizeValue(row.getIdentityCard())); staffOnJobDto.setAdress(normalizeValue(row.getAdress())); staffOnJobDto.setPhone(normalizeValue(row.getPhone())); staffOnJobDto.setEmergencyContactPhone(normalizeValue(row.getEmergencyContactPhone())); staffOnJobDto.setEntryDate(row.getEntryDate()); staffOnJobDto.setContractTerm(normalizeValue(row.getContractTerm())); staffOnJobDto.setSysPostId(post.getPostId().intValue()); staffOnJobDto.setSysDeptId(dept.getDeptId().intValue()); syncStaffBasicFields(staffOnJobDto); return staffOnJobDto; } private void syncStaffBasicFields(StaffOnJobDto staffOnJobDto) { if (staffOnJobDto == null) { return; } staffOnJobDto.setStaffNo(normalizeValue(staffOnJobDto.getStaffNo())); staffOnJobDto.setStaffName(normalizeValue(staffOnJobDto.getStaffName())); staffOnJobDto.setNation(normalizeValue(staffOnJobDto.getNation())); staffOnJobDto.setNativePlace(normalizeValue(staffOnJobDto.getNativePlace())); if (StringUtils.isBlank(staffOnJobDto.getNation())) { staffOnJobDto.setNation(staffOnJobDto.getNativePlace()); } if (StringUtils.isBlank(staffOnJobDto.getNativePlace())) { staffOnJobDto.setNativePlace(staffOnJobDto.getNation()); } if (staffOnJobDto.getEntryDate() == null) { staffOnJobDto.setEntryDate(staffOnJobDto.getContractStartTime()); } } private void fillNationFallback(StaffOnJob staffOnJob) { if (staffOnJob == null) { return; } if (StringUtils.isBlank(staffOnJob.getNation())) { staffOnJob.setNation(staffOnJob.getNativePlace()); } if (StringUtils.isBlank(staffOnJob.getNativePlace())) { staffOnJob.setNativePlace(staffOnJob.getNation()); } } private void fillNationFallback(List staffOnJobs) { if (CollectionUtils.isEmpty(staffOnJobs)) { return; } staffOnJobs.forEach(this::fillNationFallback); } private Map buildPostMap() { SysPost query = new SysPost(); query.setStatus("0"); return buildUniqueMap(sysPostMapper.selectPostList(query), SysPost::getPostName, "post"); } private Map buildDeptMap() { SysDept query = new SysDept(); query.setStatus("0"); return buildUniqueMap(sysDeptMapper.selectDeptList(query), SysDept::getDeptName, "dept"); } private Map buildUniqueMap(List dataList, Function nameGetter, String fieldName) { Map> groupedMap = dataList.stream() .filter(Objects::nonNull) .filter(item -> StringUtils.isNotBlank(normalizeValue(nameGetter.apply(item)))) .collect(Collectors.groupingBy(item -> normalizeValue(nameGetter.apply(item)))); List duplicateNames = groupedMap.entrySet().stream() .filter(entry -> entry.getValue().size() > 1) .map(Map.Entry::getKey) .sorted() .collect(Collectors.toList()); if (!duplicateNames.isEmpty()) { throw new BaseException("Duplicate " + fieldName + " names: " + String.join(", ", duplicateNames)); } return groupedMap.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get(0))); } private String normalizeValue(String value) { return value == null ? null : value.trim(); } @Override public String exportCopy(HttpServletResponse response, StaffOnJob staffOnJob) throws Exception { String url = "/javaWork/product-inventory-management/file/prod/" + staffOnJob.getStaffName() + "-劳动合同书.docx"; Configuration cfg = new Configuration(Configuration.VERSION_2_3_32); cfg.setClassForTemplateLoading(StaffOnJobServiceImpl.class, "/static"); cfg.setDefaultEncoding("UTF-8"); WordDateDto staff = new WordDateDto(); BeanUtils.copyProperties(staffOnJob, staff); Instant instant = staff.getContractExpireTime().toInstant(); LocalDate localDate = instant.atZone(ZoneId.of("Asia/Shanghai")).toLocalDate(); LocalDate localDate1 = localDate.minusYears(Integer.parseInt(staff.getContractTerm())); LocalDate localDate2 = staff.getSignDate().toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate(); LocalDate localDate3 = staff.getTrialStartDate().toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate(); LocalDate localDate4 = staff.getTrialEndDate().toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate(); staff.setQyear(localDate2.getYear() + ""); staff.setQmoth(localDate2.getMonthValue() + ""); staff.setQday(localDate2.getDayOfMonth() + ""); if (staff.getDateSelect().equals("A")) { staff.setSyear(localDate1.getYear() + ""); staff.setSmoth(localDate1.getMonthValue() + ""); staff.setSday(localDate1.getDayOfMonth() + ""); staff.setEyear(localDate.getDayOfMonth() + ""); staff.setEmoth(localDate.getDayOfMonth() + ""); staff.setEday(localDate.getDayOfMonth() + ""); staff.setStyear(localDate3.getYear() + ""); staff.setStmoth(localDate3.getMonthValue() + ""); staff.setStday(localDate3.getDayOfMonth() + ""); staff.setSeyear(localDate4.getYear() + ""); staff.setSemoth(localDate4.getMonthValue() + ""); staff.setSeday(localDate4.getDayOfMonth() + ""); } else if (staff.getDateSelect().equals("B")) { staff.setBsyear(localDate1.getYear() + ""); staff.setBsmoth(localDate1.getMonthValue() + ""); staff.setBsday(localDate1.getDayOfMonth() + ""); staff.setBstyear(localDate3.getYear() + ""); staff.setBstmoth(localDate3.getMonthValue() + ""); staff.setBstday(localDate3.getDayOfMonth() + ""); staff.setBseyear(localDate4.getYear() + ""); staff.setBsemoth(localDate4.getMonthValue() + ""); staff.setBseday(localDate4.getDayOfMonth() + ""); } else if (staff.getDateSelect().equals("C")) { staff.setCsyear(localDate1.getYear() + ""); staff.setCsmoth(localDate1.getMonthValue() + ""); staff.setCsday(localDate1.getDayOfMonth() + ""); } Map data = new HashMap<>(); data.put("item", staff); Template template = cfg.getTemplate("劳动合同书.xml"); StringWriter out = new StringWriter(); template.process(data, out); String filledXml = out.toString(); File outputFile = new File(url); try (FileOutputStream fos = new FileOutputStream(outputFile); OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) { osw.write(filledXml); } return url; } }