package com.engine.salary.service.impl; import cn.hutool.core.util.NumberUtil; import com.alibaba.druid.support.json.JSONUtils; import com.alibaba.fastjson.JSONObject; import com.api.formmode.mybatis.util.SqlProxyHandle; import com.cloudstore.eccom.pc.table.WeaTable; import com.cloudstore.eccom.pc.table.WeaTableColumn; import com.cloudstore.eccom.result.WeaResultMsg; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.biz.AttendQuoteBiz; import com.engine.salary.biz.AttendQuoteDataBiz; import com.engine.salary.biz.AttendQuoteDataValueBiz; import com.engine.salary.biz.AttendQuoteFieldBiz; import com.engine.salary.common.LocalDateRange; import com.engine.salary.config.SalaryElogConfig; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.hrmelog.entity.dto.LoggerContext; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.datacollection.bo.AttendQuoteDataBO; import com.engine.salary.entity.datacollection.dto.*; import com.engine.salary.entity.datacollection.param.*; import com.engine.salary.entity.datacollection.po.AttendQuoteDataPO; import com.engine.salary.entity.datacollection.po.AttendQuoteDataValuePO; import com.engine.salary.entity.datacollection.po.AttendQuoteFieldPO; import com.engine.salary.entity.datacollection.po.AttendQuotePO; import com.engine.salary.entity.salarysob.bo.SalarySobRangeBO; import com.engine.salary.entity.salarysob.dto.SalarySobCycleDTO; import com.engine.salary.entity.salarysob.param.SalarySobRangeEmpQueryParam; import com.engine.salary.entity.salarysob.po.SalarySobPO; import com.engine.salary.entity.salarysob.po.SalarySobRangePO; import com.engine.salary.enums.OperateTypeEnum; import com.engine.salary.enums.UserStatusEnum; import com.engine.salary.enums.datacollection.AttendQuoteSourceTypeEnum; import com.engine.salary.enums.datacollection.UseEmployeeTypeEnum; import com.engine.salary.exception.SalaryRunTimeException; import com.engine.salary.mapper.datacollection.AttendQuoteDataMapper; import com.engine.salary.mapper.salarysob.SalarySobMapper; import com.engine.salary.mapper.salarysob.SalarySobRangeMapper; import com.engine.salary.mapper.sys.SalarySysConfMapper; import com.engine.salary.remote.attend.entity.Attend4Salary; import com.engine.salary.remote.attend.service.RemoteAttend4SalaryService; import com.engine.salary.remote.attend.service.impl.RemoteAttend4SalaryServiceImpl; import com.engine.salary.service.*; import com.engine.salary.sys.entity.po.SalarySysConfPO; import com.engine.salary.sys.entity.vo.OrderRuleVO; import com.engine.salary.sys.service.SalarySysConfService; import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl; import com.engine.salary.util.SalaryDateUtil; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.engine.salary.util.db.IdGenerator; import com.engine.salary.util.db.MapperProxyFactory; import com.engine.salary.util.excel.ExcelParseHelper; import com.engine.salary.util.excel.ExcelSupport; import com.engine.salary.util.excel.ExcelUtil; import com.engine.salary.util.page.PageInfo; import com.engine.salary.util.page.SalaryPageUtil; import com.engine.salary.util.valid.ValidUtil; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import weaver.file.ImageFileManager; import weaver.general.BaseBean; import weaver.hrm.User; import weaver.wechat.util.Utils; import java.io.InputStream; import java.math.BigDecimal; import java.time.YearMonth; import java.util.*; import java.util.stream.Collectors; import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX; /** * 数据采集-考勤引用数据 *

Copyright: Copyright (c) 2022

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ @Slf4j public class AttendQuoteDataServiceImpl extends Service implements AttendQuoteDataService { private final Boolean isLog = "true".equals(new BaseBean().getPropValue("hrmSalary", "log")); private AttendQuoteBiz quoteBiz = new AttendQuoteBiz(); private AttendQuoteDataBiz dataBiz = new AttendQuoteDataBiz(); private AttendQuoteDataValueBiz dataValueBiz = new AttendQuoteDataValueBiz(); private AttendQuoteFieldBiz fieldBiz = new AttendQuoteFieldBiz(); private AttendQuoteFieldSettingService getFieldSettingService(User user) { return ServiceUtil.getService(AttendQuoteFieldSettingServiceImpl.class, user); } private SalarySysConfService getSalarySysConfService(User user) { return ServiceUtil.getService(SalarySysConfServiceImpl.class, user); } private SalarySobService getSalarySobService(User user) { return ServiceUtil.getService(SalarySobServiceImpl.class, user); } private AttendQuoteService getAttendQuoteService(User user) { return ServiceUtil.getService(AttendQuoteServiceImpl.class, user); } private AttendQuoteDataMapper getAttendQuoteDataMapper() { return MapperProxyFactory.getProxy(AttendQuoteDataMapper.class); } private SalarySobMapper getSalarySobMapper() { return MapperProxyFactory.getProxy(SalarySobMapper.class); } private SalarySobRangeMapper getSalarySobRangeMapper() { return MapperProxyFactory.getProxy(SalarySobRangeMapper.class); } private RemoteAttend4SalaryService getRemoteAttend4SalaryService(User user) { return ServiceUtil.getService(RemoteAttend4SalaryServiceImpl.class, user); } private SalaryEmployeeService getSalaryEmployeeService(User user) { return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user); } private SalarySysConfMapper getSalarySysConfMapper() { return SqlProxyHandle.getProxy(SalarySysConfMapper.class); } @Override public PageInfo listPage(AttendQuoteDataQueryParam queryParam) { //排序配置 OrderRuleVO orderRule = getSalarySysConfService(user).orderRule(); queryParam.setOrderRule(orderRule); List list = getAttendQuoteDataMapper().list(queryParam); PageInfo page = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), list, AttendQuoteDataBaseDTO.class); return page; } /** * 获取所有考勤字段 * * @return */ private List getAllAttendQuoteFields() { return fieldBiz.listSome(AttendQuoteFieldPO.builder().build()); } /** * 获取考勤数据结果 * * @param attendQuoteDataBases * @return */ public List> getListMaps(List attendQuoteDataBases) { if (CollectionUtils.isEmpty(attendQuoteDataBases)) { return new ArrayList<>(); } // 考核数据值 List attendQuoteDataValues = dataValueBiz.listSome(AttendQuoteDataValuePO.builder().attendQuoteId(attendQuoteDataBases.get(0).getAttendQuoteId()).build()); return attendQuoteDataBases.stream().map(m -> { Map map = new LinkedHashMap<>(); map.put("id", m.getId()); map.put("username", m.getUsername()); map.put("departmentName", m.getDepartmentName()); map.put("mobile", m.getMobile()); map.put("jobNum", m.getJobNum()); map.put("idNo", m.getIdNo()); // 考勤数据 attendQuoteDataValues.stream().filter(a -> a.getAttendQuoteDataId().equals(m.getId())).collect(Collectors.toList()).forEach(e -> { map.put(e.getAttendQuoteFieldId() + "_attendQuoteData", e.getDataValue()); }); return map; }).collect(Collectors.toList()); } @Override public List getAttendQuoteData(YearMonth salaryYearMonth, Long salarySobId, List employeeIds) { if (salaryYearMonth == null || salarySobId == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100358, "参数有误:薪资所属月、薪资账套id")); } List list = new ArrayList<>(); Date salaryYearMonthDay = SalaryDateUtil.localDateToDate(salaryYearMonth.atDay(1)); //查询引用主表 List attendQuotes = quoteBiz.listSome(AttendQuotePO.builder().salaryYearMonth(salaryYearMonthDay).salarySobId(salarySobId).build()); if (CollectionUtils.isEmpty(attendQuotes)) { return Collections.emptyList(); } AttendQuotePO attendQuote = attendQuotes.get(0); //查询考勤数据值 List attendQuoteDataValues = dataValueBiz.listSome(AttendQuoteDataValuePO.builder().attendQuoteId(attendQuote.getId()).employeeIds(employeeIds).build()); if (CollectionUtils.isEmpty(employeeIds)) { employeeIds = attendQuoteDataValues.stream().map(AttendQuoteDataValuePO::getEmployeeId) .distinct().collect(Collectors.toList()); } employeeIds.forEach(e -> { AttendQuoteDataDTO attendQuoteData = new AttendQuoteDataDTO(); attendQuoteData.setEmployeeId(e); List dataValues = attendQuoteDataValues.stream().filter(v -> v.getEmployeeId().equals(e)).map(m -> AttendQuoteDataValueDTO.builder() .attendQuoteFieldId(m.getAttendQuoteFieldId()) .dataValue(m.getDataValue()) .build()).collect(Collectors.toList()); attendQuoteData.setDataValues(dataValues); list.add(attendQuoteData); }); return list; } @Override public XSSFWorkbook export(AttendQuoteDataQueryParam queryParam) { if (queryParam.getAttendQuoteId() == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100253, "考勤引用id不能为空")); } //排序配置 OrderRuleVO orderRule = getSalarySysConfService(user).orderRule(); queryParam.setOrderRule(orderRule); // 考勤数据分页主数据 List attendQuoteDataBases = dataBiz.list(queryParam); // 所有考勤字段 List attendQuoteFields = getAllAttendQuoteFields(); // 获取最终结果 List> listMaps = getListMaps(attendQuoteDataBases); // 1.工作簿名称 String sheetName = SalaryI18nUtil.getI18nLabel(93931, "考勤数据"); List header = new ArrayList<>(); header.add(SalaryI18nUtil.getI18nLabel(85429, "姓名")); header.add(SalaryI18nUtil.getI18nLabel(86185, "部门")); header.add(SalaryI18nUtil.getI18nLabel(86186, "手机号")); header.add(SalaryI18nUtil.getI18nLabel(86317, "工号")); // 动态列 if (CollectionUtils.isNotEmpty(listMaps)) { for (AttendQuoteFieldPO attendQuoteField : attendQuoteFields) { header.add(attendQuoteField.getFieldName()); } } List> rows = new ArrayList<>(); // 2.表头 rows.add(header); // 3.表数据 for (Map dto : listMaps) { List row = new ArrayList<>(); row.add(dto.get("username")); row.add(dto.get("departmentName")); row.add(dto.get("mobile")); row.add(dto.get("jobNum")); // 动态列 for (AttendQuoteFieldPO attendQuoteField : attendQuoteFields) { Object o = dto.get(attendQuoteField.getId().toString() + "_attendQuoteData"); try { if (o != null && NumberUtil.isNumber(o.toString())) { row.add(new BigDecimal(o.toString())); } else { row.add(o); } } catch (Exception e) { row.add(o); } } rows.add(row); } // 记录日志 AttendQuotePO attendQuotePO = getAttendQuoteService(user).getById(queryParam.getAttendQuoteId()); SalarySobPO salarySob = getSalarySobService(user).getById(attendQuotePO.getSalarySobId()); LoggerContext loggerContext = new LoggerContext(); loggerContext.setUser(user); loggerContext.setTargetId(String.valueOf(attendQuotePO.getId())); loggerContext.setTargetName(SalaryDateUtil.getFormatYearMonth(attendQuotePO.getSalaryYearMonth()) + " " + (salarySob != null ? salarySob.getName() : "")); loggerContext.setOperateType(OperateTypeEnum.EXCEL_EXPORT.getValue()); loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "导出考勤数据")); loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "考勤数据")); SalaryElogConfig.attendQuoteLoggerTemplate.write(loggerContext); return ExcelUtil.genWorkbookV2(rows, sheetName); } /** * 获取表头设置字段 * * @param sourceType * @return */ private List getAttendQuoteSetFields(AttendQuoteSourceTypeEnum sourceType) { List allAttendQuoteFields = getAllAttendQuoteFields(); List attendQuoteFieldSettingList = getFieldSettingService(user).listNoSync(AttendQuoteFieldSettingQueryParam.builder().sourceType(sourceType).isViewChecked(Boolean.TRUE).build()); List attendQuoteFields = new ArrayList<>(); attendQuoteFieldSettingList.forEach(s -> { List items = s.getItems(); if (CollectionUtils.isNotEmpty(items)) { items.forEach(i -> { Optional optional = allAttendQuoteFields.stream().filter(f -> f.getId().equals(i.getId())).findFirst(); optional.ifPresent(attendQuoteFields::add); }); } }); return attendQuoteFields; } @Override public String syncAttendQuoteData(AttendQuoteDataSyncParam syncParam) { AttendQuoteDataSyncParam.checkParam(syncParam); String salaryYearMonth = syncParam.getSalaryYearMonth(); int year = Integer.parseInt(salaryYearMonth.split("-")[0]); int month = Integer.parseInt(salaryYearMonth.split("-")[1]); if (!SalaryDateUtil.checkYearMonth(salaryYearMonth)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100365, "薪资所属月格式有误,正确格式示例为'2021-01'")); } // 1.获取已设置的可同步的考勤字段 List attendQuoteFields = getAttendQuoteSetFields(AttendQuoteSourceTypeEnum.QUOTE); if (CollectionUtils.isEmpty(attendQuoteFields)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100366, "请先设置同步字段")); } // 获取薪资账套 SalarySobCycleDTO salarySobCycle = getSalarySobService(user).getSalarySobCycle(syncParam.getSalarySobId(), YearMonth.of(year, month)); // 2.薪资账套人员 List employeeIds = new ArrayList<>(); // 获取薪资账套人员 List salarySobRanges = getSalarySobRangeMapper().listSome(SalarySobRangePO.builder().includeType(1).salarySobId(salarySobCycle.getSalarySobId()).build()); List salarySobRangeEmpQueryParams = SalarySobRangeBO.convert2EmployeeQueryParam(salarySobRanges); List> partition = Lists.partition(salarySobRangeEmpQueryParams, 100); List employeeSalarySobIds = new ArrayList<>(); partition.forEach(l -> employeeSalarySobIds.addAll(getSalarySobRangeMapper().listEmployeeIds(l))); if (CollectionUtils.isEmpty(employeeSalarySobIds) || CollectionUtils.isEmpty(salarySobRangeEmpQueryParams)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100367, "薪资账套还没有人员")); } // 账套外人员 List employeeOtherIds = (List) syncParam.getEmployeeIds(); employeeIds.addAll(employeeSalarySobIds); employeeIds.addAll(CollectionUtils.emptyIfNull(employeeOtherIds)); // 4.获取考勤模块数据 List> attendQuoteSyncData = getAttendQuoteDataFromRemoteAttend(salarySobCycle.getAttendCycle(), employeeIds, attendQuoteFields); List pos = new ArrayList<>(); List values = new ArrayList<>(); // 5.考勤引用数据处理 Date now = new Date(); if (CollectionUtils.isNotEmpty(attendQuoteSyncData)) { // 3.生成考勤引用 AttendQuotePO attendQuote = getAttendQuote(AttendQuoteSourceTypeEnum.QUOTE, syncParam.getSalarySobId(), year, month, syncParam.getDescription()); for (Long employeeId : employeeIds) { AttendQuoteDataPO po = new AttendQuoteDataPO(); po.setId(IdGenerator.generate()); po.setCreateTime(now); po.setUpdateTime(now); po.setCreator((long) user.getUID()); po.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY); // 考勤引用表的主键id po.setAttendQuoteId(attendQuote.getId()); po.setEmployeeId(employeeId); pos.add(po); for (Map attendQuoteData : attendQuoteSyncData) { if (!Objects.isNull(attendQuoteData.get("employeeId")) && !Objects.isNull(employeeId) && !Objects.isNull(attendQuoteData.get("attendQuoteFieldId")) && attendQuoteData.get("employeeId").toString().equals(employeeId.toString())) { values.add(AttendQuoteDataValuePO.builder() .createTime(now) .updateTime(now) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .employeeId(employeeId) .attendQuoteId(attendQuote.getId()) .attendQuoteDataId(po.getId()) .attendQuoteFieldId(Long.valueOf(attendQuoteData.get("attendQuoteFieldId").toString())) .dataValue(Utils.null2String(attendQuoteData.get("dataValue"))) .build()); } } } // 6.数据落库处理 handleDataToDB(attendQuote.getId(), pos, values); // 记录日志 recordLog(attendQuote); } else { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100368, "暂无考勤数据可以同步")); } return null; } private void recordLog(AttendQuotePO attendQuote) { SalarySobPO salarySob = getSalarySobService(user).getById(attendQuote.getSalarySobId()); String sourceType = AttendQuoteSourceTypeEnum.getDefaultLabelByValue(attendQuote.getSourceType()); LoggerContext loggerContext = new LoggerContext(); loggerContext.setUser(user); loggerContext.setTargetId(String.valueOf(attendQuote.getId())); loggerContext.setTargetName(SalaryDateUtil.getFormatYearMonth(attendQuote.getSalaryYearMonth()) + " " + (salarySob != null ? salarySob.getName() : "")); loggerContext.setOperateType(OperateTypeEnum.ADD.getValue()); loggerContext.setOperateTypeName(sourceType + SalaryI18nUtil.getI18nLabel(0, "考勤数据")); loggerContext.setOperatedesc(sourceType + SalaryI18nUtil.getI18nLabel(0, "考勤数据")); loggerContext.setNewValues(attendQuote); SalaryElogConfig.attendQuoteLoggerTemplate.write(loggerContext); } /** * 获取考勤引用 * * @param salarySobId * @param year * @param month * @return */ private AttendQuotePO getAttendQuote(AttendQuoteSourceTypeEnum sourceType, Long salarySobId, int year, int month, String description) { SalarySobCycleDTO salarySobCycle = getSalarySobService(user).getSalarySobCycle(salarySobId, YearMonth.of(year, month)); Date salaryYearMonthDayDate = SalaryDateUtil.localDateToDate(YearMonth.of(year, month).atDay(1)); List attendQuotes = quoteBiz.listSome(AttendQuotePO.builder().salarySobId(salarySobId).salaryYearMonth(salaryYearMonthDayDate).build()); // 考勤引用 AttendQuotePO attendQuote = new AttendQuotePO(); if (CollectionUtils.isNotEmpty(attendQuotes)) { attendQuote = attendQuotes.get(0); } attendQuote.setSalarySobId(salarySobCycle.getSalarySobId()); LocalDateRange salaryCycleRange = salarySobCycle.getSalaryCycle(); LocalDateRange attendCycleRange = salarySobCycle.getAttendCycle(); // 考勤周期 attendQuote.setAttendCycle(SalaryDateUtil.getFormatLocalDate(attendCycleRange.getFromDate()) + " ~ " + SalaryDateUtil.getFormatLocalDate(attendCycleRange.getEndDate())); // 薪资周期 attendQuote.setSalaryCycle(SalaryDateUtil.getFormatLocalDate(salaryCycleRange.getFromDate()) + " ~ " + SalaryDateUtil.getFormatLocalDate(salaryCycleRange.getEndDate())); attendQuote.setSalaryYearMonth(salaryYearMonthDayDate); // 来源:导入 attendQuote.setSourceType(sourceType.getValue()); attendQuote.setDescription(description); Date now = new Date(); attendQuote.setCreateTime(now); attendQuote.setUpdateTime(now); attendQuote.setCreator((long) user.getUID()); attendQuote.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY); // 新增或修改考勤引用 if (attendQuote.getId() != null) { quoteBiz.updateById(attendQuote); } else { attendQuote.setId(IdGenerator.generate()); quoteBiz.insert(attendQuote); } return attendQuote; } /** * 获取考勤模块数据 * * @param attendCycleRange * @param employeeIds * @param attendQuoteFields * @return */ private List> getAttendQuoteDataFromRemoteAttend(LocalDateRange attendCycleRange, List employeeIds, List attendQuoteFields) { List> attendQuoteSyncData = new ArrayList<>(); Attend4Salary attend4Salary = new Attend4Salary(); try { int partSize = 500; List> partition = Lists.partition(employeeIds, partSize); for (List part : partition) { attend4Salary.setBeginDate(attendCycleRange.getFromDate()); attend4Salary.setEndDate(attendCycleRange.getEndDate()); attend4Salary.setOnlyEmpIds(part); List> attendResult = getRemoteAttend4SalaryService(user).getDatas(attend4Salary); AttendQuoteDataBO.buildAttendDataFromRemote(attendResult, attendQuoteFields, attendQuoteSyncData); // attend4Salary.setUnit("day"); // attendResult = remoteAttend4SalaryService.getWorkTimeSummary(attend4Salary); // log.info("考勤数据[按天]:{}", JSONUtils.toJSONString(attendResult.getData())); // AttendQuoteDataBO.buildAttendDataFromRemote("day", attendResult.getData(), attendQuoteFields, attendQuoteSyncData); } } catch (Exception e) { log.error("salaryAttend获取考勤数据错误失败:{}", String.format("参数:%s,错误信息:%s", JSONObject.toJSONString(attend4Salary), e.getMessage()), e); return attendQuoteSyncData; } if (isLog) { log.info("salaryAttend同步的考勤数据:{}", JSONUtils.toJSONString(attendQuoteSyncData)); } return attendQuoteSyncData; } /** * 引用同步或导入落库处理 * * @param attendQuoteId * @param pos * @param values */ private void handleDataToDB(Long attendQuoteId, List pos, List values) { // 数据落库处理 if (CollectionUtils.isEmpty(pos)) { return; } // 多条相同人的则以第一条为准,如果逆序排列(用于重复的则以最后一条为准)Collections.reverse(pos); pos = pos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getEmployeeId()))), ArrayList::new)); // 删除考勤数据 ArrayList quoteIds = new ArrayList<>(); quoteIds.add(attendQuoteId); dataBiz.deleteByAttendQuoteIds(quoteIds); // 新增考勤数据 dataBiz.insertData(pos); // 删除考勤值数据 // dataValueBiz.deleteByAttendQuoteDataIds(pos.stream().map(AttendQuoteDataPO::getId).collect(Collectors.toList())); dataValueBiz.deleteByAttendQuoteIds(quoteIds); // 新增考勤值数据 if (CollectionUtils.isNotEmpty(values)) { //去除空值 values = values.stream().filter(po -> StringUtils.isNotBlank(po.getDataValue())).collect(Collectors.toList()); dataValueBiz.insertData(values); } } @Override public XSSFWorkbook downloadTemplate(AttendQuoteDataExportTemplateParam exportParam) { try { // 考勤主数据 Date salaryYearMonth = SalaryDateUtil.localDateToDate(exportParam.getSalaryYearMonth().atDay(1)); List attendQuotePOS = quoteBiz.listSome(AttendQuotePO.builder() .salarySobId(exportParam.getSalarySobId()) .salaryYearMonth(salaryYearMonth) .ids(exportParam.getIds()).build()); AttendQuotePO po = CollectionUtils.isNotEmpty(attendQuotePOS) ? attendQuotePOS.get(0) : null; AttendQuoteDataQueryParam queryParam = AttendQuoteDataQueryParam.builder().attendQuoteId(po == null ? 0L : po.getId()).build(); List attendQuoteDataBases = dataBiz.list(queryParam); // 获取已设置的可同步的字段 List attendQuoteFields = getAttendQuoteSetFields(AttendQuoteSourceTypeEnum.IMPORT); // 获取最终结果 List> listMaps = getListMaps(attendQuoteDataBases); // 1.工作簿名称 String sheetName = SalaryI18nUtil.getI18nLabel(101606, "考勤引用导入模板"); List header = new ArrayList<>(); header.add(SalaryI18nUtil.getI18nLabel(85429, "姓名")); header.add(SalaryI18nUtil.getI18nLabel(86185, "部门")); header.add(SalaryI18nUtil.getI18nLabel(86186, "手机号")); header.add(SalaryI18nUtil.getI18nLabel(86317, "工号")); header.add(SalaryI18nUtil.getI18nLabel(86317, "证件号码")); // 动态列 for (AttendQuoteFieldPO attendQuoteField : attendQuoteFields) { header.add(attendQuoteField.getFieldName()); } List> rows = new ArrayList<>(); rows.add(header); for (Map dto : listMaps) { List row = new ArrayList<>(); row.add(dto.get("username")); row.add(dto.get("departmentName")); row.add(dto.get("mobile")); row.add(dto.get("jobNum")); // // 动态列 // Map map = listMaps.get(0); // for (AttendQuoteFieldPO attendQuoteField : attendQuoteFields) { // row.add(map.containsKey(attendQuoteField.getId() + "_attendQuoteData") ? dto.get(attendQuoteField.getId() + "_attendQuoteData") : ""); // } rows.add(row); } return ExcelUtil.genWorkbookV2(rows, sheetName); } catch (Exception e) { log.error("salaryAttend下载模板失败", e); } return null; } /** * 导入的数据插入到数据库中 */ public Map preview(AttendQuoteDataImportParam param) { ValidUtil.doValidator(param); Long salarySobId = param.getSalarySobId(); SalarySobPO salarySobPO = getSalarySobService(user).getById(salarySobId); if (salarySobPO == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100537, "薪资账套不存在")); } String salaryYearMonth = param.getSalaryYearMonth(); if (!SalaryDateUtil.checkYearMonth(salaryYearMonth)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100365, "薪资所属月格式有误,正确格式示例为'2021-01'")); } InputStream fileInputStream = null; try { fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(param.getImageId())); Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); Map apidatas = new HashMap(); apidatas.put("headers", ExcelSupport.getSheetHeader(sheet, 0)); apidatas.put("list", ExcelParseHelper.parse2List(sheet, 1)); return apidatas; } finally { IOUtils.closeQuietly(fileInputStream); } } /** * 导入的数据插入到数据库中 */ public Map importAttendQuoteData(AttendQuoteDataImportParam param) { ValidUtil.doValidator(param); Long salarySobId = param.getSalarySobId(); SalarySobPO salarySobPO = getSalarySobService(user).getById(salarySobId); if (salarySobPO == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100537, "薪资账套不存在")); } String salaryYearMonth = param.getSalaryYearMonth(); if (!SalaryDateUtil.checkYearMonth(salaryYearMonth)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100365, "薪资所属月格式有误,正确格式示例为'2021-01'")); } int year = Integer.parseInt(salaryYearMonth.split("-")[0]); int month = Integer.parseInt(salaryYearMonth.split("-")[1]); //查询对于人员信息导入筛选的全局配置 SalarySysConfPO salarySysConfPO = getSalarySysConfMapper().getOneByCode("matchEmployeeMode"); String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0"; // 获取租户下所有的人员 List employees = getSalaryEmployeeService(user).listAll(UseEmployeeTypeEnum.ALL); // 获取已设置的可同步的考勤字段 List attendQuoteFields = getAttendQuoteSetFields(AttendQuoteSourceTypeEnum.IMPORT); // 生成获取考勤引用 AttendQuotePO attendQuote = getAttendQuote(AttendQuoteSourceTypeEnum.IMPORT, salarySobId, year, month, StringUtils.EMPTY); int total = 0; int index = 0; int successCount = 0; int errorCount = 0; // 待导入数据 List pos = new ArrayList<>(); List values = new ArrayList<>(); String valI18n = SalaryI18nUtil.getI18nLabel(100581, "请输入数字"); InputStream fileInputStream = null; try { fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(param.getImageId())); Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); // 表头 List headers = ExcelSupport.getSheetHeader(sheet, 0); // 错误sheet数据 List> errorData = new ArrayList<>(); // 错误提示 List> excelComments = new ArrayList<>(); //验证字段是否缺失 String isValidHeader = checkHeaders(headers, attendQuoteFields); if (StringUtils.isNotBlank(isValidHeader)) { Map apidatas = new HashMap(); apidatas.put("successCount", successCount); apidatas.put("errorCount", errorCount); Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", isValidHeader); excelComments.add(errorMessageMap); apidatas.put("errorData", excelComments); return apidatas; } // 处理数值 List> data = ExcelParseHelper.parse2Map(sheet, 1); total = data.size(); Map map; Date now = new Date(); AttendQuoteDataPO po; for (int i = 0; i < data.size(); i++) { index += 1; String rowIndex = "第" + index + "行"; map = data.get(i); po = new AttendQuoteDataPO(); po.setId(IdGenerator.generate()); po.setCreateTime(now); po.setUpdateTime(now); po.setCreator((long) user.getUID()); po.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY); // 考勤引用表的主键id po.setAttendQuoteId(attendQuote.getId()); int errorSum = 0; String userName = Optional.ofNullable(map.get(SalaryI18nUtil.getI18nLabel(85429, "姓名"))).orElse("").toString(); String deparmentName = Optional.ofNullable(map.get(SalaryI18nUtil.getI18nLabel(86185, "部门"))).orElse("").toString(); String mobile = Optional.ofNullable(map.get(SalaryI18nUtil.getI18nLabel(86186, "手机号"))).orElse("").toString(); String workcode = Optional.ofNullable(map.get(SalaryI18nUtil.getI18nLabel(86317, "工号"))).orElse("").toString(); String idNo = Optional.ofNullable(map.get(SalaryI18nUtil.getI18nLabel(86317, "证件号码"))).orElse("").toString(); List employeeSameIds = new ArrayList<>(); //筛选导入人员信息可以在人力资源池中匹配到的人员信息 List emps = getSalaryEmployeeService(user).matchImportEmployee(confValue, employees, userName, deparmentName, mobile, workcode, idNo, null); //含在职和离职,选在职数据 if (CollectionUtils.isNotEmpty(emps) && emps.size() > 1) { employeeSameIds = emps.stream() .filter(e -> UserStatusEnum.getNormalStatus().contains(e.getStatus())) .map(DataCollectionEmployee::getEmployeeId) .collect(Collectors.toList()); } if (CollectionUtils.isNotEmpty(emps) && emps.size() == 1) { employeeSameIds = emps.stream() .map(DataCollectionEmployee::getEmployeeId) .collect(Collectors.toList()); } for (int j = 0; j < headers.size(); j++) { String key = headers.get(j); if (key == null) { continue; } String cellVal = Optional.ofNullable(map.get(key.toString())).orElse("").toString(); if (SalaryI18nUtil.getI18nLabel(85429, "姓名").equals(key.toString())) { //当人员信息导入筛选的全局配置为"0"时,姓名才是必填项 if (StringUtils.isEmpty(cellVal) && "0".equals(confValue)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowIndex + SalaryI18nUtil.getI18nLabel(100579, "姓名不能为空")); excelComments.add(errorMessageMap); errorSum += 1; } else if (CollectionUtils.isEmpty(employeeSameIds) || employeeSameIds.size() > 1) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowIndex + SalaryI18nUtil.getI18nLabel(100579, "员工信息不存在或者存在多个员工")); excelComments.add(errorMessageMap); errorSum += 1; } else { Long employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 ? employeeSameIds.get(0) : null; if (employeeId != null && employeeId > 0) { po.setEmployeeId(employeeId); } else { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowIndex + SalaryI18nUtil.getI18nLabel(100579, "姓名错误,系统内不存在该姓名")); excelComments.add(errorMessageMap); errorSum += 1; } } } if (po.getEmployeeId() != null) { String bigDecimalValue; for (AttendQuoteFieldPO attendQuoteField : attendQuoteFields) { if (attendQuoteField.getFieldName().equals(key)) { if (1 == attendQuoteField.getFieldType()) { bigDecimalValue = bigDecimalVal(cellVal, excelComments, valI18n, errorCount + 1, j); errorSum += StringUtils.isEmpty(bigDecimalValue) ? 1 : 0; if (StringUtils.isNotEmpty(bigDecimalValue)) { values.add(AttendQuoteDataValuePO.builder() .createTime(now) .updateTime(now) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .employeeId(po.getEmployeeId()) .attendQuoteId(attendQuote.getId()) .attendQuoteDataId(po.getId()) .attendQuoteFieldId(attendQuoteField.getId()) .dataValue(Utils.null2String(bigDecimalValue)) .build()); } } else { values.add(AttendQuoteDataValuePO.builder() .createTime(now) .updateTime(now) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .employeeId(po.getEmployeeId()) .attendQuoteId(attendQuote.getId()) .attendQuoteDataId(po.getId()) .attendQuoteFieldId(attendQuoteField.getId()) .dataValue(Utils.null2String(cellVal)) .build()); } } } } } if (errorSum > 0) { errorCount += 1; // 添加错误数据 errorData.add(map); } else { successCount += 1; // 成功一条就添加一条记录 pos.add(po); } // 导入进度 // salaryBatchService.sendImportRate(message.getBizId(), total, index); } // 数据入库处理 handleDataToDB(attendQuote.getId(), pos, values); // 记录日志 recordLog(attendQuote); Map apidatas = new HashMap(); apidatas.put("successCount", successCount); apidatas.put("errorCount", errorCount); apidatas.put("errorData", excelComments); return apidatas; } finally { IOUtils.closeQuietly(fileInputStream); } } /** * @return null * @description 编辑数据 * @author Harryxzy * @date 2022/10/28 14:40 */ @Override public void editData(AttendQuoteDataEditParam attendQuoteDataEditParam) { Map attendQuoteData = attendQuoteDataEditParam.getAttendQuoteData(); AttendQuoteDataBiz dataBiz = new AttendQuoteDataBiz(); AttendQuoteDataValueBiz attendQuoteDataValueBiz = new AttendQuoteDataValueBiz(); ArrayList ids = new ArrayList<>(); ids.add(attendQuoteDataEditParam.getId()); AttendQuoteDataQueryParam build = AttendQuoteDataQueryParam.builder().ids(ids).build(); List list = dataBiz.list(build); if (list == null || list.size() == 0) { throw new SalaryRunTimeException("该数据不存在!"); } Map attendQuoteFieldData = new HashMap<>(); for (Map.Entry entrySet : attendQuoteData.entrySet()) { String[] s = entrySet.getKey().split("_"); attendQuoteFieldData.put(s[0], entrySet.getValue()); } for (Map.Entry entrySet : attendQuoteFieldData.entrySet()) { AttendQuoteDataValuePO updatePO = AttendQuoteDataValuePO.builder().employeeId(list.get(0).getEmployeeId()).attendQuoteFieldId(SalaryEntityUtil.string2Long(entrySet.getKey())).dataValue(entrySet.getValue()).build(); attendQuoteDataValueBiz.updateDataValue(updatePO); } } /** * @return void * @description 获取数据 * @author Harryxzy * @date 2022/10/31 14:12 */ @Override public Map getData(AttendQuoteDataEditParam attendQuoteDataEditParam) { ArrayList ids = new ArrayList<>(); ids.add(attendQuoteDataEditParam.getId()); AttendQuoteDataQueryParam build = AttendQuoteDataQueryParam.builder().ids(ids).build(); List list = dataBiz.list(build); if (list == null || list.size() == 0) { throw new SalaryRunTimeException("该数据不存在!"); } // 所有考勤字段 List attendQuoteFields = getAllAttendQuoteFields(); // 获取最终结果 List> listMaps = getListMaps(list); List columns = new ArrayList<>(); columns.add(new WeaTableColumn("150", SalaryI18nUtil.getI18nLabel(85429, "姓名"), "username")); columns.add(new WeaTableColumn("150", SalaryI18nUtil.getI18nLabel(86185, "部门"), "departmentName")); columns.add(new WeaTableColumn("150", SalaryI18nUtil.getI18nLabel(86186, "手机号"), "mobile")); columns.add(new WeaTableColumn("150", SalaryI18nUtil.getI18nLabel(86317, "工号"), "jobNum")); // 动态列 if (CollectionUtils.isNotEmpty(listMaps)) { Map map = listMaps.stream().max(Comparator.comparingInt(m -> m.keySet().size())).get(); for (AttendQuoteFieldPO attendQuoteField : attendQuoteFields) { if (map.containsKey(attendQuoteField.getId() + "_attendQuoteData")) { columns.add(new WeaTableColumn("150", attendQuoteField.getFieldName(), attendQuoteField.getId() + "_attendQuoteData")); } } } WeaTable weaTable = new WeaTable(); weaTable.setColumns(columns); WeaResultMsg result = new WeaResultMsg(false); result.putAll(weaTable.makeDataResult()); result.success(); Map datas = new HashMap<>(); datas.put("data", listMaps.get(0)); datas.put("dataKey", result.getResultMap()); return datas; } /** * 获取金额数字值 * * @param bigDecimalValStr * @param excelComments * @param i * @param j * @return */ private String bigDecimalVal(String bigDecimalValStr, List> excelComments, String valI18n, int i, int j) { if (StringUtils.isBlank(bigDecimalValStr)) { return BigDecimal.ZERO.toString(); } BigDecimal bigDecimalVal = null; try { bigDecimalVal = new BigDecimal(bigDecimalValStr); } catch (Exception e) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", valI18n); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, valI18n, i, i, j, j); } return bigDecimalVal == null ? "" : bigDecimalVal.toString(); } /** * 检查参数 * * @param message * @param params * @return */ // private boolean checkParams(BatchDocumentMessage message, Map params) { // boolean isValid = true; // String errorMsg = ""; // if (params == null) { // errorMsg = SalaryI18nUtil.getI18nLabel(message.getTenantKey(), message.getUserId(), 100582, "参数必传"); // } else { // if (!params.containsKey("salaryYearMonth") // || !params.containsKey("salarySobId") // || params.get("salaryYearMonth") == null // || params.get("salarySobId") == null) { // errorMsg = SalaryI18nUtil.getI18nLabel(message.getTenantKey(), message.getUserId(), 100588, "薪资所属月和薪资账套必传"); // } else { // String salaryYearMonth = params.get("salaryYearMonth").toString(); // if (!SalaryDateUtil.checkYearMonth(salaryYearMonth)) { // errorMsg = SalaryI18nUtil.getI18nLabel(message.getTenantKey(), message.getUserId(), 100365, "薪资所属月格式有误,正确格式示例为'2021-01'"); // } else { // List salarySobs = new LambdaQueryChainWrapper<>(getSalarySobMapper()) // .eq(SalarySobPO::getTenantKey, message.getTenantKey()) // .eq(SalarySobPO::getDeleteType, 0) // .eq(SalarySobPO::getId, Long.valueOf(params.get("salarySobId").toString())) // .list(); // if (CollectionUtils.isEmpty(salarySobs)) { // errorMsg = SalaryI18nUtil.getI18nLabel(message.getTenantKey(), message.getUserId(), 100537, "薪资账套不存在"); // } // } // } // } // // 有错误信息发送 // if (StringUtils.isNotEmpty(errorMsg)) { // // 发送导入回调信息 // salaryBatchService.sendImportCallBackInfo(message, errorMsg); // isValid = false; // } // return isValid; // } /** * 检查列头 * * @return */ private String checkHeaders(List headerList, List attendQuoteFields) { boolean isValid = true; String userNameI18n = SalaryI18nUtil.getI18nLabel(85429, "姓名"); List mustHeaders = attendQuoteFields.stream().map(AttendQuoteFieldPO::getFieldName).collect(Collectors.toList()); mustHeaders.add(userNameI18n); // 缺少的必须列 List lackHeaders = mustHeaders.stream().filter(item -> !headerList.contains(item)).collect(Collectors.toList()); String errorMsg = ""; String checkHeaderI18n = SalaryI18nUtil.getI18nLabel(101850, "缺少如下列,请检查:"); if (CollectionUtils.isEmpty(attendQuoteFields)) { errorMsg = SalaryI18nUtil.getI18nLabel(101849, "考勤字段列缺失,请补充"); } else if (CollectionUtils.isNotEmpty(lackHeaders)) { errorMsg = checkHeaderI18n + Joiner.on(",").join((Iterable) lackHeaders); } return errorMsg; } }