From b50b21e6a05bca4593ef3894a2e15a90706915d8 Mon Sep 17 00:00:00 2001 From: Administrator <704728292@qq.com> Date: Fri, 2 Jan 2026 18:57:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AttendanceReportController.java | 78 + .../entity/hldz/AttendanceRecord.java | 26 + .../organization/entity/hldz/Auxiliary.java | 34 + .../jcl/organization/entity/hldz/Person.java | 89 + .../entity/hldz/StandardOvertime.java | 24 + .../entity/hldz/VacationBalance.java | 42 + .../esb/SynEmployeeAgeGlSlInfoAction.java | 12 +- .../esb/cbd/SyncAttendConfigRangeEmp.java | 459 +++++ .../esb/cbd/SyncEmployeeAttaInfo.java | 283 +++ .../organization/esb/cbd/SyncMatrixInfo.java | 155 ++ .../cbd/SyncOrganizationPersonInfo_cbd.java | 2 +- .../esb/cbd/XmindDataFilterCmd.java | 514 ++++- .../organization/esb/zkd/SyncDsmlInfo.java | 231 +++ .../esb/zkd/SyncTermBasedPerson.java | 203 ++ .../zkd/controller/ZkdGetInfoController.java | 119 ++ .../esb/zkd/entity/ApiResponse.java | 28 + .../organization/esb/zkd/entity/Result.java | 40 + .../organization/esb/zkd/entity/UserData.java | 44 + .../esb/zkd/util/HttpCilentUtil.java | 892 +++++++++ .../organization/esb/zkd/util/HttpUtil.java | 83 + .../organization/esb/zkd/util/PapiUtil.java | 192 ++ .../service/AttendanceReportService.java | 16 + .../impl/AttendanceReportServiceImpl.java | 1690 +++++++++++++++++ .../service/impl/OrganaztionSeviceImpl.java | 21 +- .../service/impl/UploadServiceImpl.java | 578 +++--- 25 files changed, 5484 insertions(+), 371 deletions(-) create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/controller/AttendanceReportController.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/AttendanceRecord.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Auxiliary.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Person.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/StandardOvertime.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/VacationBalance.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncAttendConfigRangeEmp.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncEmployeeAttaInfo.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncMatrixInfo.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncDsmlInfo.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncTermBasedPerson.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/controller/ZkdGetInfoController.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/ApiResponse.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/Result.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/UserData.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpCilentUtil.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpUtil.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/PapiUtil.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/AttendanceReportService.java create mode 100644 jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/AttendanceReportServiceImpl.java diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/controller/AttendanceReportController.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/controller/AttendanceReportController.java new file mode 100644 index 0000000..3fa5c81 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/controller/AttendanceReportController.java @@ -0,0 +1,78 @@ +package com.weaver.seconddev.jcl.organization.controller; + +import com.weaver.common.authority.annotation.WeaPermission; +import com.weaver.seconddev.jcl.organization.entity.hldz.Person; +import com.weaver.seconddev.jcl.organization.service.AttendanceReportService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/secondev/jcl/attendanceReport") +public class AttendanceReportController { + + private static final Logger log = LoggerFactory.getLogger(AttendanceReportController.class); + + @Autowired + private AttendanceReportService attendanceReportService; + + /** + * 二开测试接口 + * @return + */ + @GetMapping("/test") + @WeaPermission(publicPermission = true) + public String secondTest(@RequestParam("name") String name){ + log.error("secondTest.name:{}",name); + return name ; + + } + + /** + * 考勤报表展示 + * @return + */ + @GetMapping("/getAttendanceReportInfo") + @WeaPermission(publicPermission = true) + public List saveQueryCondition( + @RequestParam("yearMonth") String yearMonth, + @RequestParam(value = "department", required = false) String department, + @RequestParam(value = "userName", required = false) String userName, + @RequestParam(value = "jobNum", required = false) String jobNum){ + log.error("getAttendanceReportInfo.yearMonth:{},department:{},userName:{},jobNum:{}",yearMonth,department,userName,jobNum); + return attendanceReportService.getAttendanceReportInfo(yearMonth,department,userName,jobNum); + + } + + /** + * 报表数据存为EB表数据 + * @return + */ + @GetMapping("/saveEBInfo") + @WeaPermission(publicPermission = true) + public Map saveEBInfo( + @RequestParam("yearMonth") String yearMonth, + @RequestParam("department") String department, + @RequestParam("userName") String userName, + @RequestParam("jobNum") String jobNum){ + log.error("saveEBInfo.yearMonth:{},department:{},userName:{},jobNum:{}",yearMonth,department,userName,jobNum); + return attendanceReportService.saveEBInfo(yearMonth,department,userName,jobNum); + + } + + @GetMapping("/getEmployeePreparationInfo") + @WeaPermission(publicPermission = true) + public Map getEmployeePreparationInfo( + @RequestParam(name = "department", required = false) String department, + @RequestParam(name = "year", required = false) String year, + @RequestParam(name = "month", required = false) String month) { + log.error("getEmployeePreparationInfo.department=={},year=={},month=={}", department, year,month); + return attendanceReportService.getEmployeePreparationInfo(department,year,month); + } + +} \ No newline at end of file diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/AttendanceRecord.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/AttendanceRecord.java new file mode 100644 index 0000000..0e98322 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/AttendanceRecord.java @@ -0,0 +1,26 @@ +package com.weaver.seconddev.jcl.organization.entity.hldz; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Optional; + +/** + * 原始打卡数据(人员打卡数据) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AttendanceRecord { + + private String personId; + // 标准加班类型小时数 + private LocalDateTime addTime; // 打卡时间 + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Auxiliary.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Auxiliary.java new file mode 100644 index 0000000..3cabd3f --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Auxiliary.java @@ -0,0 +1,34 @@ +package com.weaver.seconddev.jcl.organization.entity.hldz; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Auxiliary { + + private String ryxm; + private String gh; + private String bm; + private String rq; + // 补贴字段 + private String cfbt; // 厂房补贴 + private String hjbt1; // 环境补贴1 + private String hjbt2; //环境补贴2 + private String hjbt3; // 环境补贴3 + private String hjbt4; // 环境补贴4 + private String hjbt5; // 环境补贴5 + private String clbt; // 车辆补贴 + private String byf; // 搬运费 + private String zhts; // 在华天数 + private String bmnbt; // 部门内部贴 + private String wcbt; //误餐补贴(元) +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Person.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Person.java new file mode 100644 index 0000000..10cfe20 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/Person.java @@ -0,0 +1,89 @@ +package com.weaver.seconddev.jcl.organization.entity.hldz; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Person { + + private String id; + private String jobNum; + private String name; + private String deptId; + private String dept; + private String yearMonth; + private String totalShifts; + // 假期余额字段 + private String paidAnnualLeave; // 带薪年休假 + private String nursingLeave; // 哺乳假 + private String paidAnnualAndNursingLeave;//年休假天数+含哺乳假 + private String maternityLeave; // 产假 + private String marriageLeave; // 婚假 + private String familyVisitLeave; // 探亲假 1.父母1177292850110423040 + private String familyVisitLeaveSpouse; //2.配偶 1199278194791358465 + private String bereavementLeave; // 丧假 + private String personalLeave; // 事假 + private String commonSickLeave; // 普通病假 + private String hospitalSickLeave; // 住院病假 + private String officialLeave; // 因公休假 + private String workInjuryLeave; // 工伤假 + private String examLeave; // 考试假 + private String careLeave; // 护理假+陪产假+育儿假 + //private int paternityLeave; // 陪产假 + //private int parentalLeave; // 育儿假 + private String businessTrip; // 公出 + private String compensatoryLeave; // 加班换休(换休天数) + private String womanresting; // 孕妇工间休息 + private String OvertimeForCompensatoryleave; //加班换休技能职 + // 补贴字段 + private String cfbt; // 厂房补贴 + private String hjbt1; // 环境补贴1 + private String hjbt2; //环境补贴2 + private String hjbt3; // 环境补贴3 + private String hjbt4; // 环境补贴4 + private String hjbt5; // 环境补贴5 + private String clbt; // 车辆补贴 + private String byf; // 搬运费 + private String zhts; // 在华天数 + private String bmnbt; // 部门内部贴 + private String wcf; // 误餐费 + // 标准加班类型小时数 + private String day_type; // 加班类型 + private String workOverTime; // 平时加班小时数 + private String playDayOverTime; //周末加班小时数(休日加班:取系统中“加班换休假”+“加班换休假-技能职”中的加班时间转为可调休时间(本月数据))还是查加班换休之和 + private String holidayOverTime; //节假日加班小时数 + //中班/晚班数 + private String midShifts; // 中班数(排班上班) + private String nightShifts; // 夜班数(排班上班) + //中班/晚班(加班)数 + private String midShiftsOver; // 中班数(加班) + private String nightShiftsOver; // 夜班数(加班) + //中班(总数)/晚班数(总数) + private String midShiftsAll; + private String nightShiftsAll; + //休日加班小时数(计算后) + private String playDayOverTimeCal; + //平日加班小时数(计算后) + private String workOverTimeCal; + //合计加班时长(计算后) + private String standardOvertimeAll; + //矿工天数 + private String miner; + //福利假失效小时数 + private String welfareLeaveDays; + //实际出勤天数 + private String workLengthDay; + //加班余额兑换数 + private double overtimeExchangeRate; + + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/StandardOvertime.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/StandardOvertime.java new file mode 100644 index 0000000..55d1c5c --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/StandardOvertime.java @@ -0,0 +1,24 @@ +package com.weaver.seconddev.jcl.organization.entity.hldz; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class StandardOvertime { + + private String id; + // 标准加班类型小时数 + private String day_type; // 加班类型 + private String hour; // 小时数 + private String minute; //分钟数 + private String day; // 天数 +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/VacationBalance.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/VacationBalance.java new file mode 100644 index 0000000..3d6d89e --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/entity/hldz/VacationBalance.java @@ -0,0 +1,42 @@ +package com.weaver.seconddev.jcl.organization.entity.hldz; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class VacationBalance { + + private String id; + private String name; + // 假期字段 + private String paidAnnualLeave; // 带薪年休假 + private String nursingLeave; // 哺乳假 + //private int paidAnnualAndNursingLeave;//年休假天数+含哺乳假 + private String maternityLeave; // 产假 + private String marriageLeave; // 婚假 + private String familyVisitLeave; // 探亲假(父母) + private String familyVisitLeaveSpouse;// 探亲假(配偶) + private String bereavementLeave; // 丧假 + private String personalLeave; // 事假 + private String commonSickLeave; // 普通病假 + private String hospitalSickLeave; // 住院病假 + private String officialLeave; // 因公休假 + private String workInjuryLeave; // 工伤假 + private String examLeave; // 考试假 + private String careLeave; // 护理假+陪产假+育儿假 + private String paternityLeave; // 陪产假 + private String parentalLeave; // 育儿假 + private String businessTrip; // 公出 + private String compensatoryLeave; // 加班换休 + private String womanresting; // 孕妇工间休息 + private String OvertimeForCompensatoryleave; //加班换休技能职 +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/SynEmployeeAgeGlSlInfoAction.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/SynEmployeeAgeGlSlInfoAction.java index e568a16..ee8cb39 100644 --- a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/SynEmployeeAgeGlSlInfoAction.java +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/SynEmployeeAgeGlSlInfoAction.java @@ -166,10 +166,18 @@ public class SynEmployeeAgeGlSlInfoAction implements EsbServerlessRpcRemoteInter return Period.between(startDate, endDate).getYears(); } - private Double calculateYears(LocalDate startDate, LocalDate endDate) { +// private Double calculateYears(LocalDate startDate, LocalDate endDate) { +// Period period = Period.between(startDate, endDate); +// double years = period.getYears() + (period.getMonths() / 12.0) + (period.getDays() / 365.0); +// return Math.round(years * 100.0) / 100.0; // 保留两位小数 +// } + private Double calculateYears(LocalDate startDate, LocalDate endDate) { + // 计算日期间隔的年、月、天 Period period = Period.between(startDate, endDate); + // 转换为以年为单位的小数(年 + 月/12 + 天/365) double years = period.getYears() + (period.getMonths() / 12.0) + (period.getDays() / 365.0); - return Math.round(years * 100.0) / 100.0; // 保留两位小数 + // 保留一位小数并向下取整:放大10倍→向下取整→缩小10倍 + return Math.floor(years * 10.0) / 10.0; } // 检查是否是日期格式 yyyy-MM-dd diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncAttendConfigRangeEmp.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncAttendConfigRangeEmp.java new file mode 100644 index 0000000..b8f5053 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncAttendConfigRangeEmp.java @@ -0,0 +1,459 @@ +package com.weaver.seconddev.jcl.organization.esb.cbd; + +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.weaver.common.base.entity.result.WeaResult; +import com.weaver.common.distribution.genid.IdGenerator; +import com.weaver.esb.api.rpc.EsbServerlessRpcRemoteInterface; +import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @use:同步考勤规则-应用范围人员 + * @date 2025年12月27日 + * @author xuxy + */ +@Service("syncAttendConfigRangeEmp_kq") +public class SyncAttendConfigRangeEmp implements EsbServerlessRpcRemoteInterface { + + @Autowired + private DatabaseUtils databaseUtils; + private static final Logger log = LoggerFactory.getLogger(SyncAttendConfigRangeEmp.class); + + @Override + public WeaResult> execute(Map params) { + Map result = new HashMap<>(); + log.error("SyncAttendConfigrangeEmp.start"); + try { + //1.根据考勤规则eb表规则查询出每套考勤规则下对应的-应用范围人员 + List> kqgzEbInfo = getKqgzEbInfo(); + //2.遍历考勤规则eb表查询:1.范围人员 2.排除人员 + for (Map map : kqgzEbInfo) { + String form_data_id = String.valueOf(map.get("form_data_id")); + String bm = String.valueOf(map.get("bm")); + String rylb2 = String.valueOf(map.get("rylb2")); + String bmpc = String.valueOf(map.get("bmpc")); + String frgs = String.valueOf(map.get("frgs")); + String kqgz = String.valueOf(map.get("kqgz")); + //根据部门、人员类别查询add人员 + List> addEmployeeInfoAuto = getAddEmployeeInfoAuto(bm, rylb2); + //再查询手动新增人员/排除人员 + List> addEmployeeInfoManual = getAddEmployeeInfoManual(form_data_id); + //根据部门排除、法人公司排除 + List> deleteEmployeeInfoAuto = getDeleteEmployeeInfoAuto(bmpc, frgs); + //筛选之后的新增人员id集合 + List list = filterFinalAddEmployees(addEmployeeInfoAuto, addEmployeeInfoManual, deleteEmployeeInfoAuto); + //新增人员再跟原本的考勤规则-应用范围做比对:1.增量插入 2.缺量设置缺失人员失效日期为当前日期yyyy-MM-dd + filterResultList(list, kqgz); + } + log.error("SyncAttendConfigrangeEmp.kqgzEbInfo:{}", kqgzEbInfo); + }catch (Exception e) { + result.put("code","201"); + log.error("Exception_em:"+e); + } + return WeaResult.success(result); + } + + /** + * 根据考勤规则eb表规则查询出每套考勤规则下对应的-应用范围人员 + * @return + */ + public List> getKqgzEbInfo(){ + String sql = " select * from e10_common.uf_kqgz where kqgz is not null and delete_type=0 and TENANT_KEY = 't024j0gfn0' "; + log.error("getKqgzEbInfo.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getKqgzEbInfo.recordList:{}", recordList); + return recordList; + } + /** + * 根据部门、人员类别查询add人员 + * @return + */ + public List> getAddEmployeeInfoAuto(String bm,String rylb){ + String sql = " SELECT DISTINCT e.id,e.username\n" + + " FROM eteams.employee e\n" + + " left JOIN eteams.ft_1152026012537184302 f on f.FORM_DATA_ID=e.formdata\n" + + " WHERE \n" + + " f.rylb= '"+rylb+"' and \n" + + " e.personnel_status not in ('6','7') and\n" + + " e.DEPARTMENT in \n" + + " (WITH RECURSIVE SubDepartments AS (\n" + + " SELECT id,name\n" + + " FROM eteams.department\n" + + " WHERE id in ("+bm+")\n" + + " AND IS_DELETE = 0\n" + + " AND `type` = 'department'\n" + + " AND STATUS = 1 \n" + + " \n" + + " UNION ALL\n" + + " \n" + + " SELECT d.id,d.name\n" + + " FROM eteams.department d\n" + + " INNER JOIN SubDepartments sd ON d.parent = sd.id\n" + + " WHERE d.IS_DELETE = 0\n" + + " AND d.`type` = 'department'\n" + + " AND d.STATUS = 1\n" + + " )\n" + + " SELECT DISTINCT CAST(id AS CHAR)\n" + + " FROM SubDepartments) "; + log.error("getAddEmployeeInfoAuto.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getAddEmployeeInfoAuto.recordList:{}", recordList); + return recordList; + } + + /** + * 手动新增人员 + * @return + */ + public List> getAddEmployeeInfoManual(String form_data_id){ + String sql = " select xzpc,ry from e10_common.uf_kqgz_sddz where delete_type=0 and FORM_DATA_ID = '"+form_data_id+"' and TENANT_KEY = 't024j0gfn0' "; + log.error("getAddEmployeeInfoManual.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getAddEmployeeInfoManual.recordList:{}", recordList); + return recordList; + } + + + /** + * 根据部门排除、法人公司排除 + * @return + */ + public List> getDeleteEmployeeInfoAuto(String bmpc, String frgs){ + // 优化点1:前置判断 - bmpc和frgs都为空时,直接返回空列表 + if (StringUtils.isAllBlank(bmpc, frgs)) { + log.info("getDeleteEmployeeInfoAuto: bmpc和frgs均为空,返回空列表"); + return new ArrayList<>(); + } + + // ========== 1. 构建SQL固定部分 ========== + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append(" SELECT DISTINCT e.id,e.username ") + .append(" FROM eteams.employee e ") + .append(" left JOIN eteams.ft_1152026012537184302 f on f.FORM_DATA_ID=e.formdata ") + .append(" WHERE 1=1 "); // 占位符,方便后续拼接AND条件 + + // ========== 2. 动态拼接frgs相关条件 ========== + if (StringUtils.isNotBlank(frgs)) { + sqlBuilder.append(" AND f.gzdssyyzx = '").append(frgs).append("' "); // 参数化占位符,避免注入 + } + + // ========== 3. 动态拼接bmpc相关的部门递归查询 ========== + if (StringUtils.isNotBlank(bmpc)) { + sqlBuilder.append(" AND e.DEPARTMENT in ( ") + .append(" WITH RECURSIVE SubDepartments AS ( ") + .append(" SELECT id,name ") + .append(" FROM eteams.department ").append(" WHERE id in (").append(bmpc).append(") ") // 参数化占位符 + .append(" AND IS_DELETE = 0 ") + .append(" AND `type` = 'department' ") + .append(" AND STATUS = 1 ") + .append(" UNION ALL ") + .append(" SELECT d.id,d.name ") + .append(" FROM eteams.department d ") + .append(" INNER JOIN SubDepartments sd ON d.parent = sd.id ") + .append(" WHERE d.IS_DELETE = 0 ") + .append(" AND d.`type` = 'department' ") + .append(" AND d.STATUS = 1 ") + .append(" ) ") + .append(" SELECT DISTINCT CAST(id AS CHAR) FROM SubDepartments ") + .append(" ) "); + } + + // ========== 4. 拼接固定的人员状态条件 ========== + sqlBuilder.append(" AND e.personnel_status not in ('6','7') "); + log.error("getDeleteEmployeeInfoAuto.sql:{}", sqlBuilder.toString()); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sqlBuilder.toString()); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getDeleteEmployeeInfoAuto.recordList:{}", recordList); + return recordList; + } + + + /** + * 筛选最终剩余的新增人员ID集合(去重、排除后) + * @param addEmployeeInfoAuto 自动新增人员列表(含id、name字段) + * @param addEmployeeInfoManual 手动新增人员列表(含xzpc、ry字段:xzpc=0/1为标识,ry=人员ID) + * @param deleteEmployeeInfoAuto 自动排除人员列表(含id、name字段) + * @return 剩余新增人员ID集合(List,无重复) + */ + public static List filterFinalAddEmployees( + List> addEmployeeInfoAuto, + List> addEmployeeInfoManual, + List> deleteEmployeeInfoAuto) { + + // ========== 步骤1:构建新增人员池(id -> ry 映射,去重) ========== + Map addEmployeeMap = new HashMap<>(); + + // 1.1 处理自动新增列表:id=人员ID,name=ry + if (CollectionUtils.isNotEmpty(addEmployeeInfoAuto)) { + addEmployeeInfoAuto.stream() + .filter(map -> { + String id = getStringValue(map, "id"); + String name = getStringValue(map, "name"); + return StringUtils.isNotBlank(id) && StringUtils.isNotBlank(name); + }) + .forEach(map -> { + String id = getStringValue(map, "id"); + String ry = getStringValue(map, "name"); + addEmployeeMap.putIfAbsent(id, ry); + }); + } + + // 1.2 处理手动新增列表:筛选xzpc=0的人员,ry=人员ID + if (CollectionUtils.isNotEmpty(addEmployeeInfoManual)) { + addEmployeeInfoManual.stream() + .filter(map -> { + String xzpc = getStringValue(map, "xzpc"); + String empId = getStringValue(map, "ry"); + return "0".equals(xzpc) && StringUtils.isNotBlank(empId); + }) + .forEach(map -> { + String empId = getStringValue(map, "ry"); + String ry = empId; + addEmployeeMap.putIfAbsent(empId, ry); + }); + } + + // ========== 步骤2:构建排除人员ID集合 ========== + Set excludeIdSet = new HashSet<>(); + + // 2.1 处理自动排除列表:提取id(人员ID) + if (CollectionUtils.isNotEmpty(deleteEmployeeInfoAuto)) { + excludeIdSet.addAll( + deleteEmployeeInfoAuto.stream() + .map(map -> getStringValue(map, "id")) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toSet()) + ); + } + + // 2.2 处理手动新增列表:筛选xzpc=1的人员,提取ry(人员ID)作为排除ID + if (CollectionUtils.isNotEmpty(addEmployeeInfoManual)) { + excludeIdSet.addAll( + addEmployeeInfoManual.stream() + .filter(map -> { + String xzpc = getStringValue(map, "xzpc"); + String empId = getStringValue(map, "ry"); + return "1".equals(xzpc) && StringUtils.isNotBlank(empId); + }) + .map(map -> getStringValue(map, "ry")) + .collect(Collectors.toSet()) + ); + } + + // ========== 步骤3:筛选剩余新增人员ID(核心修改部分) ========== + // 排除需删除的人员ID + List finalAddEmployees = addEmployeeMap.keySet().stream() + .filter(s -> !excludeIdSet.contains(s)) // 直接提取人员ID(去掉Map构建) + .collect(Collectors.toList()); // 收集为List + log.error("filterFinalAddEmployees.finalAddEmployees:{}", finalAddEmployees); + return finalAddEmployees; + } + + /** + * 安全获取Map中的String类型值(处理null/空) + */ + private static String getStringValue(Map map, String key) { + if (map == null || key == null) { + return ""; + } + Object value = map.get(key); + return value == null ? "" : value.toString().trim(); + } + + /** + * 插入考勤规则--应用范围 + * @return + */ + public void insertAttendConfigRange(List list,String kqgz){ + /** + * 这里先查询一下:kqgz对应的应用范围人员最大序号 + */ + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + int sort_num = 0; + String sql = " select sort_num from e10_other_business.attend_config_range where attend_config='"+kqgz+"' and delete_type =0 and TENANT_KEY = 't024j0gfn0' order by sort_num desc "; + log.error("insertAttendConfigRange.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("insertAttendConfigRange.recordList:{}", recordList); + sort_num = Integer.parseInt(String.valueOf(recordList.get(0).get("sort_num"))); + log.error("insertAttendConfigRange.sort_num:{}", sort_num); + for (String s : list) { + sort_num+=1; + // 格式化时间 + String formattedDateTime = now.format(formatter); + // 生成随机 ID + long id = IdGenerator.generate(); + sql="insert into e10_other_business.attend_config_range(id,target_id,entry_type,tenant_key,create_time,update_time,delete_type,include_sub_dept,min_sec_level,max_sec_level,sort_num,creator) " + + " values('"+id+"','"+s+"','user','"+kqgz+"','t024j0gfn0','"+formattedDateTime+"','"+formattedDateTime+"','0','0','-999','999','"+sort_num+"','1167276462243069953') "; + log.error("insertAttendConfigRange.sql222:{}", sql); + Map rt = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + log.error("insertAttendConfigRange.sort_num22222:{}", sort_num); + log.error("insertAttendConfigRange.rs:{}", rt); + } + } + + + /** + * 更新考勤规则--应用范围失效时间 + * @return + */ + public void updateAttendConfigRangeExp(List list,String kqgz){ + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + for (String s : list) { + String sql = " select * from e10_other_business.attend_configrange_exp where CONFIG_RANGE_ID in(select id from e10_other_business.attend_config_range where attend_config='"+kqgz+"' \n" + + " and delete_type =0 and ENTRY_TYPE = 'user' and TENANT_KEY = 't024j0gfn0' and TARGET_ID = '"+s+"')"; + log.error("updateAttendConfigRangeExp.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("updateAttendConfigRangeExp.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + String id = String.valueOf(recordList.get(0).get("id")); + String formattedDateTime = now.format(formatter); + //根据id更新失效时间 + sql = "update e10_other_business.attend_configrange_exp set EXPIRY_DATE_END = '"+formattedDateTime+"' where id = '"+id+"' "; + log.error("updateAttendConfigRangeExp.sql222:{}", sql); + Map rt = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + log.error("updateAttendConfigRangeExp.rt222:{}", rt); + }else { + //新增失效时间表 + //生成随机 ID + long id = IdGenerator.generate(); + String formattedDateTime = now.format(formatter); + /** + * 这里查询一下CONFIG_RANGE_ID + */ + sql = " select id from e10_other_business.attend_config_range where attend_config='"+kqgz+"' and delete_type =0 and ENTRY_TYPE = 'user' and TENANT_KEY = 't024j0gfn0' and TARGET_ID = '"+s+"' "; + log.error("updateAttendConfigRangeExp.sql333:{}", sql); + Map rt2 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList2 = databaseUtils.getDataSourceList(rt2); + log.error("updateAttendConfigRangeExp.recordList2:{}", recordList2); + String config_range_id = String.valueOf(recordList2.get(0).get("id")); + + sql="insert into e10_other_business.attend_configrange_exp(id,create_time,update_time,delete_type,creator,tenant_key,EXPIRY_DATE_BEGIN,EXPIRY_DATE_END,CONFIG_RANGE_ID,CONFIG_ID) " + + " values('"+id+"','"+formattedDateTime+"','"+formattedDateTime+"','0','1167276462243069953','t024j0gfn0','2000-01-01','"+formattedDateTime+"','"+config_range_id+"','"+kqgz+"') "; + log.error("insertAttendConfigRange.sql444:{}", sql); + Map rt3 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList3 = databaseUtils.getDataSourceList(rt3); + log.error("updateAttendConfigRangeExp.recordList3:{}", recordList3); + } + } + } + + + public void filterResultList(List list,String kqgz){ + //1.查询原本的考勤规则对应的人员范围 + String sql = " select * from e10_other_business.attend_config_range where attend_config='"+kqgz+"' and delete_type =0 and ENTRY_TYPE = 'user' and TENANT_KEY = 't024j0gfn0' "; + log.error("filterResultList.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("filterResultList.recordList:{}", recordList); + List recordList2 = getTargetIdList(recordList); + //2.比对新老人员,筛选新增人员和失效人员 + List[] lists = compareStringListWithOrder(list, recordList2); + List addData = lists[0]; + List missingData = lists[1]; + //插入考勤规则--应用范围 + insertAttendConfigRange(addData,kqgz); + //缺失人员设置失效日期 + updateAttendConfigRangeExp(missingData,kqgz); + } + + public List getTargetIdList(List> recordList) { + if (Objects.isNull(recordList)) { + return new ArrayList<>(); + } + return recordList.stream() + .filter(Objects::nonNull) + .map(map -> Optional.ofNullable(map.get("target_id")).map(Object::toString).map(String::trim).orElse("")) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + } + + /** + * 对比两个String列表,返回新增数据、缺失数据(保留原顺序) + * @param baseList 基准列表(list) + * @param compareList 对比列表(recordList2) + * @return [新增数据List, 缺失数据List] + */ + public static List[] compareStringListWithOrder(List baseList, List compareList) { + // 空值兜底 + List safeBase = Optional.ofNullable(baseList).orElse(new ArrayList<>()); + List safeCompare = Optional.ofNullable(compareList).orElse(new ArrayList<>()); + + // 转LinkedHashSet:有序 + 去重 + 高效查找 + Set baseSet = new LinkedHashSet<>(safeBase); + Set compareSet = new LinkedHashSet<>(safeCompare); + + // 新增数据:compareList有,baseList无 + List addData = safeCompare.stream() + .filter(item -> !baseSet.contains(item)) + .collect(Collectors.toList()); + + // 缺失数据:baseList有,compareList无 + List missingData = safeBase.stream() + .filter(item -> !compareSet.contains(item)) + .collect(Collectors.toList()); + + return new List[]{addData, missingData}; + } + + + + + // 测试方法 +// public static void main(String[] args) { +// // 模拟测试数据(同之前) +// List> addAuto = new ArrayList<>(); +// Map auto1 = new HashMap<>(); +// auto1.put("id", "001"); +// auto1.put("name", "张三"); +// addAuto.add(auto1); +// Map auto2 = new HashMap<>(); +// auto2.put("id", "002"); +// auto2.put("name", "李四"); +// addAuto.add(auto2); +// +// List> addManual = new ArrayList<>(); +// Map manual1 = new HashMap<>(); +// manual1.put("xzpc", "0"); +// manual1.put("ry", "003"); +// addManual.add(manual1); +// Map manual2 = new HashMap<>(); +// manual2.put("xzpc", "1"); +// manual2.put("ry", "002"); +// addManual.add(manual2); +// +// List> deleteAuto = new ArrayList<>(); +// Map delete1 = new HashMap<>(); +// delete1.put("id", "001"); +// delete1.put("name", "张三"); +// deleteAuto.add(delete1); +// +// // 筛选最终新增人员ID +// List finalResult = filterFinalAddEmployees(addAuto, addManual, deleteAuto); +// +// // 输出结果 +// System.out.println("最终剩余新增人员ID:"); +// finalResult.forEach(id -> System.out.println(id)); +// } + + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncEmployeeAttaInfo.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncEmployeeAttaInfo.java new file mode 100644 index 0000000..d2c44ef --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncEmployeeAttaInfo.java @@ -0,0 +1,283 @@ +package com.weaver.seconddev.jcl.organization.esb.cbd; + +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.weaver.common.base.entity.result.WeaResult; +import com.weaver.common.distribution.genid.IdGenerator; +import com.weaver.esb.api.rpc.EsbServerlessRpcRemoteInterface; +import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.io.File; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * @use:同步人员附件信息 + * @date 2025年12月29日 + * @author xuxy + */ +@Service("syncEmployeeAttaInfo_jcl") +public class SyncEmployeeAttaInfo implements EsbServerlessRpcRemoteInterface { + + private static final Pattern JOB_NUM_PATTERN = Pattern.compile("_(\\d+)(\\(\\d+\\))?\\.[^.]+$"); + + @Autowired + private DatabaseUtils databaseUtils; + private static final Logger log = LoggerFactory.getLogger(SyncEmployeeAttaInfo.class); + + @Override + public WeaResult> execute(Map params) { + Map result = new HashMap<>(); + log.error("SyncEmployeeAttaInfo.start"); + String ml = null!=params.get("ml")?String.valueOf(params.get("ml").toString()):""; + String fieldName = null!=params.get("fieldName")?String.valueOf(params.get("fieldName").toString()):""; + log.error("SyncEmployeeAttaInfo.ml:{}", ml); + log.error("SyncEmployeeAttaInfo.fieldName:{}", fieldName); + try { + Map map = parseFileAndMatchJobNum(ml, fieldName); + result.put("map",map); + }catch (Exception e) { + result.put("code","201"); + log.error("Exception_em:"+e); + } + return WeaResult.success(result); + } + + + + // ===================== 2. 核心主方法:一站式完成「读文件+解析工号+工号匹配」===================== + /** + * 读取指定目录下所有文件,解析文件名中的工号,并匹配目标工号 + * @param targetDir 本地指定目录路径(必填) + */ + public Map parseFileAndMatchJobNum(String targetDir,String fieldName) { + Map map = new HashMap<>(); + // 1. 封装目录File对象 + File dir = new File(targetDir); + log.error("SyncEmployeeAttaInfo.dir:{}", dir); + // 校验目录合法性 + if (!dir.exists()) { + log.error("❌ 错误:指定的目录不存在 → " + targetDir); + map.put("targetDir",targetDir); + map.put("msg","指定的目录不存在"); + return map; + } + if (!dir.isDirectory()) { + log.error("❌ 错误:指定路径不是文件夹 → " + targetDir); + map.put("targetDir",targetDir); + map.put("msg","指定路径不是文件夹"); + return map; + } + + // 2. Java8 流式遍历目录下所有文件(自动过滤文件夹) + Optional.ofNullable(dir.listFiles()) + .ifPresent(files -> { + for (File file : files) { + if (file.isFile()) { // 只处理【文件】,跳过子文件夹 + String docName = file.getName(); // 获取完整文件名 + log.error("📄 读取到文件:" + docName); + + // 3. 解析文件名中的工号 + String jobNum = parseJobNumFromFileName(docName); + + if (Objects.nonNull(jobNum)) { + log.error("✅ 解析出工号:" + jobNum); + // 4. 根据工号执行匹配逻辑 + matchTargetJobNum(jobNum,docName,fieldName); + } else { + log.error("❌ 该文件名称不符合规则,未解析出工号 → " + fieldName); + } + } + } + }); + return map; + } + + // ===================== 3. 核心工具方法:从文件名解析工号(核心逻辑)===================== + /** + * 从指定文件名中提取工号,兼容两种格式:xxx_工号 / xxx_工号(数字) + * @param docName 完整文件名(如:黄小倩_身份证人像面_1000006711(1)) + * @return 解析后的纯工号,格式不匹配返回null + */ + public static String parseJobNumFromFileName(String docName) { + if (docName == null || docName.trim().isEmpty()) { + return null; + } + Matcher matcher = JOB_NUM_PATTERN.matcher(docName); + // 匹配成功则返回分组1的纯工号,失败返回null + return matcher.find() ? matcher.group(1) : null; + } + + // ===================== 4. 业务方法:工号匹配(可根据实际需求扩展)===================== + /** + * 工号匹配逻辑,可根据业务需求自定义实现(如:数据库查询、集合匹配等) + * @param fileJobNum 从文件解析出的工号 + * @param fileName 从文件解析出的名称 + */ + public void matchTargetJobNum(String fileJobNum,String docName,String fileName) { + //1.根据文件名称查询文件id + String docId = getFileId(docName); + if(StringUtils.isNotBlank(docId)){ + //2.更新eb表附件字段 + updateEmployeeInformationField(fileJobNum,docId,fileName); + //3.更新个人信息自定义表附件字段 + updateHruserInfoField(fileJobNum,docId,fileName); + } + + } + + /** + * 根据文件名称查询文件id + * @return + */ + public String getFileId(String docName){ + String docid = ""; + String sql = " select id from e10_core_business.fileobj where name = '"+docName+"' and DELETE_TYPE = 0 and TENANT_KEY = 't024j0gfn0' "; + log.error("getFileId.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getFileId.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + docid = String.valueOf(recordList.get(0).get("id")); + } + return docid; + } + + /** + * 根据文件名称查询员工信息表文件id + * @return + */ + public void updateEmployeeInformationField(String job_num,String docid,String fileName){ + String sql = " SELECT "+fileName+" from e10_common.uf_jcl_employee_information where job_num = '"+job_num+"' and DELETE_TYPE = 0 and TENANT_KEY = 't024j0gfn0'\n "; + log.error("checkEmployeeIsNotHave.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("checkEmployeeIsNotHave.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + String xxzbs = String.valueOf(recordList.get(0).get(fileName)); + //返回新拼接得附件id + String notContain = appendIfNotContain(xxzbs, docid); + //将新附件id更新到原来字段中 + updateEbField(notContain,job_num,fileName); + }else { + //为空直接更新docid到对应eb字段 + updateEbField(docid,job_num,fileName); + } + } + + /** + * 根据个人信息表附件字段 + * @return + */ + public void updateHruserInfoField(String job_num,String docid,String fileName){ + String sql = " select form_data_id,"+fileName+" from ft_1152116439014449153 where FORM_DATA_ID = (\n" + + "select FORM_DATA from e10_other_business.hr_userinfo where user = (\n" + + "select id from eteams.employee where job_num = '"+job_num+"')) and DELETE_TYPE = 0 and TENANT_KEY = 't024j0gfn0'\n "; + log.error("updateHruserInfoField.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("updateHruserInfoField.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + String xxzbs = String.valueOf(recordList.get(0).get(fileName)); + String form_data_id = String.valueOf(recordList.get(0).get("form_data_id")); + if(StringUtils.isNotBlank(xxzbs)){ + //返回新拼接得附件id + String notContain = appendIfNotContain(xxzbs, docid); + //将新附件id更新到原来字段中 + updateHrField(notContain,form_data_id,fileName); + }else { + //为空直接更新docid到对应eb字段 + updateHrField(docid,form_data_id,fileName); + } + } + } + + /** + * 逗号分隔字符串,若不包含目标str则追加,最终返回新的逗号分隔字符串 + * @param originalStr 原始逗号分隔字符串 (如:1000006711,1000006712) + * @param targetStr 待判断的目标字符串 (如:1000006713) + * @return 拼接后的新字符串 + */ + public static String appendIfNotContain(String originalStr, String targetStr) { + // 1. 逗号字符串 → List集合 + List strList = Arrays.stream(originalStr.split(",")) + .map(String::trim) // 去首尾空格 + .collect(Collectors.toList()); + + // 2. 判断是否包含,不包含则追加 + if (!strList.contains(targetStr.trim())) { + strList.add(targetStr.trim()); + } + + // 3. List → 逗号分隔的新字符串(核心:Java8流式拼接) + return strList.stream().collect(Collectors.joining(",")); + } + + /** + * 根据人员工号将新的附件id更新到原来eb字段 + * @return + */ + public void updateEbField(String fileid,String job_num,String fileName){ + String sql = " update e10_common.uf_jcl_employee_information set "+fileName+" = '"+fileid+"' where job_num = '"+job_num+"' and DELETE_TYPE = 0 and TENANT_KEY = 't024j0gfn0' "; + log.error("updateEbField.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("updateEbField.recordList:{}", recordList); + } + + /** + * 根据人员工号将新的附件id更新到原来hr字段 + * @return + */ + public void updateHrField(String fileid,String form_data_id,String fileName){ + String sql = " update e10_other_business.ft_1152116439014449153 set "+fileName+" = '"+fileid+"' where form_data_id = '"+form_data_id+"' and DELETE_TYPE = 0 and TENANT_KEY = 't024j0gfn0'\n "; + log.error("updateHrField.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("updateHrField.recordList:{}", recordList); + } + + + + /** + * 插入考勤规则--应用范围 + * @return + */ + public void insertAttendConfigRange(List list,String kqgz){ + /** + * 这里先查询一下:kqgz对应的应用范围人员最大序号 + */ + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + int sort_num = 0; + String sql = " select sort_num from e10_other_business.attend_config_range where attend_config='"+kqgz+"' and delete_type =0 and TENANT_KEY = 't024j0gfn0' order by sort_num desc "; + log.error("insertAttendConfigRange.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("insertAttendConfigRange.recordList:{}", recordList); + sort_num = Integer.parseInt(String.valueOf(recordList.get(0).get("sort_num"))); + log.error("insertAttendConfigRange.sort_num:{}", sort_num); + for (String s : list) { + sort_num+=1; + // 格式化时间 + String formattedDateTime = now.format(formatter); + // 生成随机 ID + long id = IdGenerator.generate(); + sql="insert into e10_other_business.attend_config_range(id,target_id,entry_type,tenant_key,create_time,update_time,delete_type,include_sub_dept,min_sec_level,max_sec_level,sort_num,creator) " + + " values('"+id+"','"+s+"','user','"+kqgz+"','t024j0gfn0','"+formattedDateTime+"','"+formattedDateTime+"','0','0','-999','999','"+sort_num+"','1167276462243069953') "; + log.error("insertAttendConfigRange.sql222:{}", sql); + Map rt = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + log.error("insertAttendConfigRange.sort_num22222:{}", sort_num); + log.error("insertAttendConfigRange.rs:{}", rt); + } + } +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncMatrixInfo.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncMatrixInfo.java new file mode 100644 index 0000000..3b323d6 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncMatrixInfo.java @@ -0,0 +1,155 @@ +package com.weaver.seconddev.jcl.organization.esb.cbd; + +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.weaver.common.base.entity.result.WeaResult; +import com.weaver.common.distribution.genid.IdGenerator; +import com.weaver.esb.api.rpc.EsbServerlessRpcRemoteInterface; +import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * @use:同步矩阵信息 + * @date 2025年12月31日 + * @author xuxy + */ +@Service("syncMatrixInfo_jcl") +public class SyncMatrixInfo implements EsbServerlessRpcRemoteInterface { + + @Autowired + private DatabaseUtils databaseUtils; + + private static final Logger log = LoggerFactory.getLogger(SyncMatrixInfo.class); + + @Override + public WeaResult> execute(Map params) { + Map result = new HashMap<>(); + try { + //1.查询数据源 + List> hrbpValues = getHrbpValues(); + //2.遍历查询是否存在,不存在插入矩阵信息 + for (Map hrbpValue : hrbpValues) { + //判断是否存在 + String empid = getValueOrDefaultEmpty(hrbpValue, "empid"); + String hrbp = getValueOrDefaultEmpty(hrbpValue, "hrbp"); + boolean b = checkIsNotHave(empid); + boolean b1 = checkIsNotHaveData(hrbp); + if(b&&b1){ + //插表 + insertMatrixInfo(empid,hrbp); + } + + } + log.error("syncDepartment.result:{}", result); + }catch (Exception e) { + result.put("status2","exception"); + log.error("Exception_em:"+e); + } + return WeaResult.success(result); + } + + /** + * 从Map中根据key取值,null则返回空字符串,非null返回原值(转为String) + * @param map 源Map + * @param key 要获取的key + * @return 处理后的字符串 + */ + private static String getValueOrDefaultEmpty(Map map, String key) { + // Optional.ofNullable处理null,orElse设置默认值为空字符串 + return Optional.ofNullable(map.get(key)) + .map(Object::toString) // 将非null的Object转为String + .orElse(""); + } + + /** + * 查询数据源 + * @return + */ + public List> getHrbpValues(){ + String sql = "select * from eteams.v_hrbp where hrbp is not null "; + log.error("getHrbpValues.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getHrbpValues.recordList:{}", recordList); + return recordList; + } + + /** + * 判断是否存在 + * @return + */ + public boolean checkIsNotHave(String relate_id){ + boolean flag = true; + String sql = " select id from eteams.hrm_matrix_condition_data where RELATE_ID = '"+relate_id+"' and DELETE_TYPE=0 and TENANT_KEY='t024j0gfn0' "; + log.error("checkIsNotHave.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("checkIsNotHave.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + flag = false; + } + return flag; + } + + /** + * 判断是否存在 + * @return + */ + public boolean checkIsNotHaveData(String relate_id){ + boolean flag = true; + String sql = " select id from eteams.hrm_matrix_value_data where RELATE_ID = '"+relate_id+"' and DELETE_TYPE=0 and TENANT_KEY='t024j0gfn0' "; + log.error("checkIsNotHaveData.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("checkIsNotHaveData.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + flag = false; + } + return flag; + } + + /** + * 插入考勤规则--应用范围 + * @return + */ + public void insertMatrixInfo(String empid,String hrbp){ + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 格式化时间 + String dateTime = now.format(formatter); + log.error("insertMatrixInfo.dateTime:{}", dateTime); + // 生成随机 ID + long id = IdGenerator.generate(); + log.error("insertMatrixInfo.id:{}", id); + //插入:eteams.hrm_matrix_data + String sql="insert into eteams.hrm_matrix_data(id,matrix_id,create_time,update_time,creator,delete_type,tenant_key,data_sort) " + + " values('"+id+"','1219550724007141382','"+dateTime+"','"+dateTime+"','1167276462243069953','0','t024j0gfn0','') "; + log.error("insertMatrixInfo.sql:{}", sql); + Map rt = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + log.error("insertMatrixInfo.rs:{}", rt); + //插入:eteams.hrm_matrix_condition_data + long id2 = IdGenerator.generate(); + sql="insert into eteams.hrm_matrix_condition_data(id,matrix_id,matrix_condition_config_id,matrix_data_id,relate_id,create_time,update_time,creator,delete_type,tenant_key) " + + " values('"+id2+"','1219550724007141382','1219550736933986305','"+ id +"','"+empid+"','"+dateTime+"','"+dateTime+"','1167276462243069953','0','t024j0gfn0') "; + log.error("insertMatrixInfo.sql222:{}", sql); + Map rt2 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + log.error("insertMatrixInfo.rs2:{}", rt2); + //插入:eteams.hrm_matrix_value_data + long id3 = IdGenerator.generate(); + sql="insert into eteams.hrm_matrix_value_data(id,matrix_id,matrix_condition_config_id,matrix_data_id,relate_id,create_time,update_time,creator,delete_type,tenant_key,sort) " + + " values('"+id3+"','1219550724007141382','1219550736933986305','"+ id +"','"+hrbp+"','"+dateTime+"','"+dateTime+"','1167276462243069953','0','t024j0gfn0','') "; + log.error("insertMatrixInfo.sql333:{}", sql); + Map rt3 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + log.error("insertMatrixInfo.rs3:{}", rt3); + } +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncOrganizationPersonInfo_cbd.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncOrganizationPersonInfo_cbd.java index 3b95e29..c954159 100644 --- a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncOrganizationPersonInfo_cbd.java +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/SyncOrganizationPersonInfo_cbd.java @@ -375,7 +375,7 @@ public class SyncOrganizationPersonInfo_cbd implements EsbServerlessRpcRemoteInt user_Info.put("employeeid",getIgnoreCase(employee_info, "id")); user_Info.put("password",containsKeyIgnoreCase(employee_info,"mm")?getIgnoreCase(employee_info, "mm"):""); user_Info.put("status","6"); - user_Info.put("TENANTKEY",getIgnoreCase(employee_info, "TENANTKEY")); + user_Info.put("TENANTKEY","t024j0gfn0"); user_Info.put("username",getIgnoreCase(employee_info, "username")); user_Info.put("email",containsKeyIgnoreCase(employee_info,"email")?getIgnoreCase(employee_info, "email"):""); user_Info.put("mobile",containsKeyIgnoreCase(employee_info,"mobile")?getIgnoreCase(employee_info, "mobile"):""); diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/XmindDataFilterCmd.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/XmindDataFilterCmd.java index 01f1184..4e9f337 100644 --- a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/XmindDataFilterCmd.java +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/cbd/XmindDataFilterCmd.java @@ -1,8 +1,6 @@ package com.weaver.seconddev.jcl.organization.esb.cbd; -import com.weaver.common.base.entity.result.WeaResult; import com.weaver.common.hrm.util.ImmutableMapUtil; -import com.weaver.framework.rpc.annotation.RpcReference; import com.weaver.loom.context.annotation.WeaHookReg; import com.weaver.loom.context.domain.AppInfo; import com.weaver.loom.context.domain.WeaHookRequest; @@ -14,10 +12,8 @@ import com.weaver.common.hrm.dto.xmind.Node; import com.weaver.common.hrm.dto.xmind.Sheet; import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; import com.weaver.seconddev.jcl.organization.util.RecruitModuleUtils; -import com.weaver.teams.hrapp.dto.est.HrComEstCfgInfoDto; -import com.weaver.teams.hrapp.dto.est.param.HrComEstCfgInfoParam; -import com.weaver.teams.hrapp.rest.HrRemoteApiService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +28,7 @@ public class XmindDataFilterCmd extends RegHookEvent { private static String tenant_key = RecruitModuleUtils.getCurrentTenantKey(); // 线程安全的全局岗位映射 private static final Map>> DEPT_POSITION_MAP = new ConcurrentHashMap<>(); + private static final Map>> POSITION_EMP_MAP = new ConcurrentHashMap<>(); private static final List> DEPT_POSITION_EST_MAP = new ArrayList<>(); private static final List> POSITION_EST_MAP = new ArrayList<>(); private static final Map DEPT_EMPLOYEE_COUNT_MAP = new ConcurrentHashMap<>(); @@ -84,6 +81,7 @@ public class XmindDataFilterCmd extends RegHookEvent { @Override public WeaHookResponse handle(WeaHookRequest request, WeaHookResponse response, AppInfo appInfo) throws Exception { + log.error("XmindDataFilterCmd.start11111111111111"); //入参,修改入参并不会影响到埋点的原始数据 Map param = request.getParams(); long start = System.nanoTime(); @@ -91,6 +89,8 @@ public class XmindDataFilterCmd extends RegHookEvent { initialize(); //初始化部门岗位数据 initializeDeptEmployeeCount(); + //初始化各岗位人员姓名 + initializePositionEmployee(); //初始化各岗位人数 initializePositionEmployeeCount(); //初始化人员信息 @@ -116,18 +116,20 @@ public class XmindDataFilterCmd extends RegHookEvent { for (Map allDepartment : allDepartments) { Deft deft = new Deft(); String id = String.valueOf(allDepartment.get("id")); - deft.setId(id); - deft.setName(String.valueOf(allDepartment.get("name"))); - deft.setParent_id(String.valueOf(allDepartment.get("parent"))); + String deptName = String.valueOf(allDepartment.get("name")); + /** + * 计算完部门人员和编制数之后再入值 + */ + //这里要根据部门id查询 List> bmBzList = getBzListByBmId(id); log.error("XmindDataFilterCmd.bmBzList:{}", bmBzList); // 处理数据(增加空列表校验) - //编制数 + //部门编制数 int estCount =0; - //缺编数 + //部门缺编数 int estLackCount =0; - //超编数 + //部门超编数 int estOverCount =0; if (bmBzList != null && !bmBzList.isEmpty()) { Map data = bmBzList.get(0); @@ -147,20 +149,27 @@ public class XmindDataFilterCmd extends RegHookEvent { estOverCount = Integer.parseInt(value3.trim()); } } - //查询部门在岗人数 + //查询部门在岗人数:positionCount // 在调用前添加日志检查 - log.error("DEPT_EMPLOYEE_COUNT_MAP size: {}", DEPT_EMPLOYEE_COUNT_MAP != null ? DEPT_EMPLOYEE_COUNT_MAP.size() : "null"); + log.error("DEPT_EMPLOYEE_COUNT_MAP size: {}", DEPT_EMPLOYEE_COUNT_MAP.size()); log.error("XmindDataFilterCmd.id8888:{}", id); - int positionCount = Optional.ofNullable(DEPT_EMPLOYEE_COUNT_MAP) + int positionCount = Optional.of(DEPT_EMPLOYEE_COUNT_MAP) .map(map -> map.getOrDefault(id, 0)) .orElse(0); //查询部门岗位名称 - List> positionByDept = getPositionsByDept(id); - log.error("XmindDataFilterCmd.positionByDept:{}", positionByDept); + /** + * 这里修改一下逻辑,改变原来的部门下岗位名称的展示 + */ + //List> positionByDept = DEPT_POSITION_MAP.get(id); + //log.error("XmindDataFilterCmd.positionByDept:{}", positionByDept); + /** + * 这里补充一个逻辑,增加部门对应的岗位+岗位对应的人员作为子节点 + */ + //遍历部门岗位,查询岗位编制等相关信息 StringJoiner joiner = new StringJoiner(","); - if(CollectionUtils.isNotEmpty(positionByDept)){ - for (Map map : positionByDept) { + if(CollectionUtils.isNotEmpty(DEPT_POSITION_MAP.get(id))){ + for (Map map : DEPT_POSITION_MAP.get(id)) { String gwId = String.valueOf(map.get("id")); String gwName = String.valueOf(map.get("name")); //查询岗位编制数/缺编数 @@ -174,7 +183,6 @@ public class XmindDataFilterCmd extends RegHookEvent { String value1 = String.valueOf(data.get("estLackCount")); String value2 = String.valueOf(data.get("estLackCount")); if (value1 == null || value1.trim().isEmpty()) { - estCountGw = 0; }else { estCountGw = Integer.parseInt(value1.trim()); } @@ -185,13 +193,45 @@ public class XmindDataFilterCmd extends RegHookEvent { } } //查询岗位人数 - int countGw = Optional.ofNullable(POSITION_EMPLOYEE_COUNT_MAP) + int countGw = Optional.of(POSITION_EMPLOYEE_COUNT_MAP) .map(map1 -> map1.getOrDefault(gwId, 0)) .orElse(0); log.error("XmindDataFilterCmd.countGw:{}", countGw); String gwInfo = String.format("\n岗位名称:%s、编制数:%d、在岗人数:%d、缺编数:%d", gwName, estCountGw, countGw, estLackCountGw); joiner.add(gwInfo); + /** + * 这里增加一个岗位信息展示: + * 岗位名称 + * 在岗人数/岗位编制数 + *人员姓名 + */ + //根据岗位id获取人员列表 + List> mapList = POSITION_EMP_MAP.get(gwId); + // 2. 处理mapList为null的情况,替换为空List + mapList = mapList == null ? Collections.emptyList() : mapList; + // 3. 提取姓名时增加空Map过滤 + 异常捕获 + List empNames = mapList.stream() + .filter(Objects::nonNull) // 过滤List中的null元素(关键!) + .map(map1 -> { + try { + Object nameObj = map1.get("name"); + // 处理nameObj为非字符串类型的情况(如数字、布尔值) + return nameObj == null ? null : nameObj.toString().trim(); + } catch (Exception e) { + // 捕获toString()异常,日志记录后返回null(后续被filter过滤) + log.error("提取姓名失败,map数据:{},异常:{}", map1, e.getMessage()); + return null; + } + }) + .filter(name -> name != null && !name.isEmpty()) + .collect(Collectors.toList()); + /** + * 拼接岗位参数(替换原来的岗位名称展示) + */ + String result2 = formatGwInfo(gwName, countGw, estCountGw, empNames); + map.put("name",result2); + } } //查询人员:姓名/职级/职位 @@ -204,12 +244,12 @@ public class XmindDataFilterCmd extends RegHookEvent { String jobset_level = String.valueOf(map.get("jobset_level")); //职级 //String jobsetLevel = USERINFO_Level_MAP.get(jobset_level); - String jobsetLevel = Optional.ofNullable(USERINFO_Level_MAP) + String jobsetLevel = Optional.of(USERINFO_Level_MAP) .map(map1 -> map1.getOrDefault(jobset_level, "")) .orElse(""); //职位 //String zw = USERINFO_ZW_MAP.get(userId); - String zw = Optional.ofNullable(USERINFO_ZW_MAP) + String zw = Optional.of(USERINFO_ZW_MAP) .map(map1 -> map1.getOrDefault(userId, "")) .orElse(""); // 格式化当前人员信息 @@ -223,6 +263,26 @@ public class XmindDataFilterCmd extends RegHookEvent { sb.append(personInfo); } } + /** + * 在这里拼接参数:包括部门的、岗位的 + */ + //1.部门参数 + // 步骤1:拼接下层字符串 + String lowerStr = positionCount + "/" + estCount; + // 步骤2:计算上层和下层的字符串长度 + int deptNameLen = deptName.length(); + int lowerStrLen = lowerStr.length(); + // 步骤3:计算居中缩进的空格数(向下取整,若长度差为奇数,会轻微偏左,可+1调整) + int indentSpace = (deptNameLen - lowerStrLen) / 2; + // 步骤4:生成缩进空格(Java 8可用String.join生成重复空格) + String indent = String.join("", java.util.Collections.nCopies(indentSpace, " ")); + // 步骤5:拼接最终结果 + String resultdept = String.format("%s%n%s%s", deptName, indent, lowerStr); + deft.setId(id); + deft.setName(resultdept); + deft.setParent_id(String.valueOf(allDepartment.get("parent"))); + + // 计算remark String remark = String.format("部门编制数:%d\n部门在岗人数:%d\n部门缺编数:%d\n岗位:%s\n人员:%s", estCount, @@ -239,16 +299,18 @@ public class XmindDataFilterCmd extends RegHookEvent { // } deft.setRemark(remark); if((estLackCount >0) || (estOverCount >0)){ - deft.setBgColor("#F1F1F1"); + deft.setBgColor("#B0E0E6");// 粉末蓝 } defts.add(deft); } - //3.组装 + //3.组装(这里构建富子结点:增加了部门子节点对应岗位++岗位子节点对应人员) Node root = buildDepartmentTree(defts); //4.塞入节点 allDataSheet.setNode(root); log.error("XmindDataFilterCmd.allDataSheet11:{}", allDataSheet); - //独立部门 + /** + * 独立部门 (独立sheet页面) + */ List> getsfdcdlzzjgBm = getsfdcdlzzjgBm(); if(CollectionUtils.isNotEmpty(getsfdcdlzzjgBm)){ //2.组装部门数据2 @@ -294,15 +356,15 @@ public class XmindDataFilterCmd extends RegHookEvent { } } //查询在岗人数 - int positionCount = Optional.ofNullable(DEPT_EMPLOYEE_COUNT_MAP) - .map(map -> map.getOrDefault(id, 0)) + int positionCount = Optional.of(DEPT_EMPLOYEE_COUNT_MAP) + .map(map -> map.getOrDefault(id2, 0)) .orElse(0); //查询部门岗位名称 - List> positionByDept = getPositionsByDept(id); + //List> positionByDept = getPositionsByDept(id); //遍历部门岗位,查询岗位编制等相关信息 StringJoiner joiner = new StringJoiner(","); - if(CollectionUtils.isNotEmpty(positionByDept)){ - for (Map map : positionByDept) { + if(CollectionUtils.isNotEmpty(DEPT_POSITION_MAP.get(id2))){ + for (Map map : DEPT_POSITION_MAP.get(id2)) { String gwId = String.valueOf(map.get("id")); String gwName = String.valueOf(map.get("name")); //查询岗位编制数/缺编数 @@ -315,7 +377,6 @@ public class XmindDataFilterCmd extends RegHookEvent { String value1 = String.valueOf(data.get("estLackCount")); String value2 = String.valueOf(data.get("estLackCount")); if (value1 == null || value1.trim().isEmpty()) { - estCountGw = 0; }else { estCountGw = Integer.parseInt(value1.trim()); } @@ -326,61 +387,112 @@ public class XmindDataFilterCmd extends RegHookEvent { } } //查询岗位人数 - int countGw = Optional.ofNullable(POSITION_EMPLOYEE_COUNT_MAP) + int countGw = Optional.of(POSITION_EMPLOYEE_COUNT_MAP) .map(map1 -> map1.getOrDefault(gwId, 0)) .orElse(0); String gwInfo = String.format("岗位名称:%s、编制数:%d、在岗人数:%d、缺编数:%d", gwName, estCountGw, countGw, estLackCountGw); joiner.add(gwInfo); + /** + * 这里增加一个岗位信息展示: + * 岗位名称 + * 在岗人数/岗位编制数 + *人员姓名 + */ + //根据岗位id获取人员列表 + // List> mapList = POSITION_EMP_MAP.get(gwId); + // 2. 处理mapList为null的情况,替换为空List + //mapList = mapList == null ? Collections.emptyList() : mapList; + // 3. 提取姓名时增加空Map过滤 + 异常捕获 +// List empNames = mapList.stream() +// .filter(Objects::nonNull) // 过滤List中的null元素(关键!) +// .map(map1 -> { +// try { +// Object nameObj = map1.get("name"); +// // 处理nameObj为非字符串类型的情况(如数字、布尔值) +// return nameObj == null ? null : nameObj.toString().trim(); +// } catch (Exception e) { +// // 捕获toString()异常,日志记录后返回null(后续被filter过滤) +// log.error("提取姓名失败,map数据:{},异常:{}", map1, e.getMessage()); +// return null; +// } +// }) +// .filter(name2 -> name2 != null && !name2.isEmpty()) +// .collect(Collectors.toList()); + /** + * 拼接岗位参数(替换原来的岗位名称展示) + */ + //log.error("XmindDataFilterCmd.gwName:{},countGw:{},estCountGw:{},empNames:{}", gwName,countGw,estCountGw,empNames); + //String result2 = formatGwInfo(gwName, countGw, estCountGw, empNames); + //map.put("name",result2); } } //查询人员:姓名/职级/职位 - StringBuilder sb = new StringBuilder(); - List> userNameByDept = getUserinfoByDept(id); - if(CollectionUtils.isNotEmpty(userNameByDept)){ - for (Map map : userNameByDept) { - String userId = String.valueOf(map.get("id")); - String userName = String.valueOf(map.get("username")); - String jobset_level = String.valueOf(map.get("jobset_level")); - //职级 - //String jobsetLevel = USERINFO_Level_MAP.get(jobset_level); - String jobsetLevel = Optional.ofNullable(USERINFO_Level_MAP) - .map(map1 -> map1.getOrDefault(jobset_level, "")) - .orElse(""); - //职位 - //String zw = USERINFO_ZW_MAP.get(userId); - String zw = Optional.ofNullable(USERINFO_ZW_MAP) - .map(map1 -> map1.getOrDefault(userId, "")) - .orElse(""); - // 格式化当前人员信息 - String personInfo = String.format("姓名:%s、职级:%s、职位:%s", - userName, jobsetLevel, zw); - - // 非首条数据添加分隔符 - if (sb.length() > 0) { - sb.append(","); - } - sb.append(personInfo); - } - } + //StringBuilder sb = new StringBuilder(); + //List> userNameByDept = getUserinfoByDept(id); +// if(CollectionUtils.isNotEmpty(userNameByDept)){ +// for (Map map : userNameByDept) { +// String userId = String.valueOf(map.get("id")); +// String userName = String.valueOf(map.get("username")); +// String jobset_level = String.valueOf(map.get("jobset_level")); +// //职级 +// //String jobsetLevel = USERINFO_Level_MAP.get(jobset_level); +// String jobsetLevel = Optional.ofNullable(USERINFO_Level_MAP) +// .map(map1 -> map1.getOrDefault(jobset_level, "")) +// .orElse(""); +// //职位 +// //String zw = USERINFO_ZW_MAP.get(userId); +// String zw = Optional.ofNullable(USERINFO_ZW_MAP) +// .map(map1 -> map1.getOrDefault(userId, "")) +// .orElse(""); +// // 格式化当前人员信息 +// String personInfo = String.format("姓名:%s、职级:%s、职位:%s", +// userName, jobsetLevel, zw); +// +// // 非首条数据添加分隔符 +// if (sb.length() > 0) { +// sb.append(","); +// } +// sb.append(personInfo); +// } +// } + /** + * 在这里拼接参数:包括部门的、岗位的222 + */ + //1.部门参数 + // 步骤1:拼接下层字符串 +// String lowerStr = positionCount + "/" + estCount; +// String name1 = String.valueOf(objectMap.get("name")); +// // 步骤2:计算上层和下层的字符串长度 +// int deptNameLen = name1.length(); +// int lowerStrLen = lowerStr.length(); +// // 步骤3:计算居中缩进的空格数(向下取整,若长度差为奇数,会轻微偏左,可+1调整) +// int indentSpace = (deptNameLen - lowerStrLen) / 2; +// // 步骤4:生成缩进空格(Java 8可用String.join生成重复空格) +// String indent = String.join("", java.util.Collections.nCopies(indentSpace, " ")); +// // 步骤5:拼接最终结果 +// String resultdept = String.format("%s%n%s%s", name1, indent, lowerStr); +// //deft.setId(id2); + //deft.setName(resultdept); + //deft.setParent_id(String.valueOf(objectMap.get("parent"))); // 计算remark - String remark = String.format("部门编制数:%d\n部门在岗人数:%d\n部门缺编数:%d\n岗位:%s\n人员:%s", - estCount, - positionCount, - estLackCount, - joiner.toString(), - sb.toString()); - log.error("XmindDataFilterCmd.remark222:{}", remark); +// String remark = String.format("部门编制数:%d\n部门在岗人数:%d\n部门缺编数:%d\n岗位:%s\n人员:%s", +// estCount, +// positionCount, +// estLackCount, +// joiner.toString(), +// sb.toString()); +// log.error("XmindDataFilterCmd.remark222:{}", remark); // if (estLackCount >0) { // remark += "\n缺编:" + (estLackCount); // } // if (estOverCount >0) { // remark += "\n超编:" + (estOverCount); // } - deft.setRemark(remark); - if((estLackCount >0) || (estOverCount >0)){ - deft.setBgColor("#F1F1F1"); - } + //deft.setRemark(remark); +// if((estLackCount >0) || (estOverCount >0)){ +// deft.setBgColor("#B0E0E6");// 粉末蓝 +// } defts2.add(deft); } //3.组装 @@ -405,11 +517,150 @@ public class XmindDataFilterCmd extends RegHookEvent { return response; } + + /** + * 拼接岗位信息为3层居中对齐的字符串 + * @param gwName 岗位名称(可为null,默认"未知岗位") + * @param countGw 岗位人数 + * @param estCountGw 编制数 + * @param empNames 人员姓名列表(可为null/空,无人员时不显示该层) + * @return 3层居中对齐的拼接字符串 + */ +// public static String formatGwInfo(String gwName, int countGw, int estCountGw, List empNames) { +// // 1. 处理岗位名称空值,兜底默认值 +// String safeGwName = Objects.isNull(gwName) || gwName.trim().isEmpty() ? "未知岗位" : gwName.trim(); +// // 2. 拼接第2层内容(人数/编制数) +// String layer2Str = countGw + "/" + estCountGw; +// // 3. 计算第1层(岗位名称)长度 +// int layer1Len = safeGwName.length(); +// +// // 4. 处理第2层:计算居中缩进 + 拼接内容 +// int layer2Len = layer2Str.length(); +// int layer2Indent = (layer1Len - layer2Len) / 2; // 第2层相对于第1层的居中缩进 +// String layer2IndentSpace = getIndentSpace(layer2Indent); +// String layer2Content = layer2IndentSpace + layer2Str; +// +// // 5. 处理第3层:人员姓名列表(每行一个,居中对齐) +// StringBuilder layer3Content = new StringBuilder(); +// if (Objects.nonNull(empNames) && !empNames.isEmpty()) { +// // 遍历姓名列表,每个姓名单独一行,相对于第1层居中 +// String layer3Lines = empNames.stream() +// .map(name -> { +// String safeName = Objects.isNull(name) ? "未知人员" : name.trim(); +// int nameLen = safeName.length(); +// int nameIndent = (layer1Len - nameLen) / 2; // 单个姓名的居中缩进 +// return getIndentSpace(nameIndent) + safeName; +// }) +// .collect(Collectors.joining("\n")); // 姓名间换行分隔 +// layer3Content.append("\n").append(layer3Lines); // 拼接第3层(先换行) +// } +// +// // 6. 拼接所有层(层间换行) +// return String.format("%s%n%s%s", safeGwName, layer2Content, layer3Content); +// } + + public static String formatGwInfo(String gwName, int countGw, int estCountGw, List empNames) { + // 1. 岗位名称空值兜底 + 去首尾空格,核心基准值 + String safeGwName = StringUtils.isBlank(gwName) ? "未知岗位" : gwName.trim(); + int layer1Len = safeGwName.length(); // 基准长度(所有层级对齐的核心) + if (layer1Len == 0) { // 极端边界兜底 + safeGwName = "未知岗位"; + layer1Len = 4; + } + + // 2. 拼接编制人数层(count/编制),核心修复:统一缩进计算逻辑 + String layer2Str = countGw + "/" + estCountGw; + int layer2Indent = (layer1Len - layer2Str.length()) / 2; + String layer2Content = getIndentSpace(Math.max(layer2Indent, 0)) + layer2Str; // 缩进≥0,避免负数 + + // 3. 拼接人员姓名层:统一换行符 + 可选去重 + 精准居中,核心修复换行/重复问题 + StringBuilder layer3Content = new StringBuilder(); + if (Objects.nonNull(empNames) && !empNames.isEmpty()) { + // 流式处理:空值兜底 + 去重 + 居中缩进,一步到位 + int finalLayer1Len = layer1Len; + String layer3Lines = empNames.stream() + .filter(StringUtils::isNotBlank) // 过滤空字符串/纯空格姓名 + .map(name -> StringUtils.isBlank(name) ? "未知人员" : name.trim()) // 姓名空值兜底 + .distinct() // ✅ 核心:自动去重(开启开关后生效) + .map(safeName -> { + int nameLen = safeName.length(); + int nameIndent = (finalLayer1Len - nameLen) / 2; + return getIndentSpace(Math.max(nameIndent, 0)) + safeName; // 缩进≥0 + }) + .collect(Collectors.joining(System.lineSeparator())); // ✅ 核心:统一用系统标准换行符 + + if (StringUtils.isNotBlank(layer3Lines)) { + // 仅在有人员数据时,拼接「单个标准换行」,杜绝多余换行导致的重复 + layer3Content.append(System.lineSeparator()).append(layer3Lines); + } + } + + // 4. 最终拼接:统一用系统标准换行符,三层内容严格分离,无重复拼接 + // ✅ 核心修复:用System.lineSeparator()替代%n和\n,全环境统一换行 + return safeGwName + + System.lineSeparator() + + layer2Content + + layer3Content; + } + +// // 工具方法:生成指定数量的空格(缩进专用),性能优化版 +// private String getIndentSpace(int indentNum) { +// if (indentNum <= 0) { +// return ""; +// } +// return StringUtils.repeat(" ", indentNum); +// } + + /** + * 生成指定数量的缩进空格(Java 8实现) + * @param indentCount 缩进空格数(负数时返回空字符串) + * @return 缩进空格字符串 + */ + private static String getIndentSpace(int indentCount) { + if (indentCount <= 0) { + return ""; + } + // Java 8生成重复空格:Collections.nCopies + String.join + return String.join("", Collections.nCopies(indentCount, " ")); + } @Override public void rollBack(WeaHookRequest request, WeaHookResponse response, AppInfo appInfo) throws Exception { } + // 部门岗位映射转换:String部门ID -> Long部门ID + public static Map>> convertDeptPositions( + Map>> deptPositionMap) { + + return deptPositionMap.entrySet().stream() + .filter(entry -> entry.getKey() != null && !entry.getKey().isEmpty()) + .collect(Collectors.toMap( + entry -> parseToLongSafely(entry.getKey(), "部门ID"), + Map.Entry::getValue + )); + } + + // 岗位人员映射转换:String岗位ID -> Long岗位ID + public static Map>> convertPositionPersons( + Map>> positionEmpMap) { + + return positionEmpMap.entrySet().stream() + .filter(entry -> entry.getKey() != null && !entry.getKey().isEmpty()) + .collect(Collectors.toMap( + entry -> parseToLongSafely(entry.getKey(), "岗位ID"), + Map.Entry::getValue + )); + } + // 安全类型转换方法(带错误日志) + private static Long parseToLongSafely(String idStr, String type) { + try { + return Long.parseLong(idStr); + } catch (NumberFormatException e) { + log.error("警告: 无法将%s(%s)转换为Long类型\n", type, idStr); + return null; // 转换失败返回null,后续collect方法会自动过滤 + } + } + /** * 塞入节点 * @param departments @@ -417,6 +668,13 @@ public class XmindDataFilterCmd extends RegHookEvent { */ public Node buildDepartmentTree(List departments) { log.error("XmindDataFilterCmd.departments:{}", departments); + Map>> deptPositions = convertDeptPositions(DEPT_POSITION_MAP); + /** + * 这里传一个空的岗位人员,不拼接岗位下级人员了 + */ + Map>> positionPersons = convertDeptPositions(POSITION_EMP_MAP); + log.error("XmindDataFilterCmd.deptPositions:{}", deptPositions); + log.error("XmindDataFilterCmd.positionPersons:{}", positionPersons); // 创建ID到Node的映射 Map nodeMap = new HashMap<>(); List rootCandidates = new ArrayList<>(); // 记录无父节点的节点 @@ -455,8 +713,79 @@ public class XmindDataFilterCmd extends RegHookEvent { // 处理最终根节点选择 Node node = resolveRootNode(rootCandidates); log.error("buildDepartmentTree.rootCandidates:{}", node); + + // 递归遍历部门树,为叶子部门节点添加岗位及人员 + traverseAndInjectPositions(node, deptPositions, positionPersons); return node; } + + // 岗位节点创建方法(适配Map数据) + public static Node createPositionNode(Map positionMap) { + return new Node() + .setId(getLongValue(positionMap, "id")) + .setName(getStringValue(positionMap, "name")) + .setType("position") + .setChildren(new ArrayList<>()); + } + + // 人员节点创建方法(适配Map数据) + public static Node createPersonNode(Map personMap) { + return new Node() + .setId(getLongValue(personMap, "id")) + .setName(getStringValue(personMap, "name")) + .setType("person"); + } + + // 辅助方法:安全获取Long值 + private static Long getLongValue(Map map, String key) { + return map.containsKey(key) ? + Long.parseLong(map.get(key).toString()) : null; + } + + // 辅助方法:安全获取String值 + private static String getStringValue(Map map, String key) { + return map.containsKey(key) ? + map.get(key).toString() : ""; + } + + private void traverseAndInjectPositions(Node node, + Map>> deptPositions, + Map>> positionPersons) { + // 处理叶子部门节点 + if ("department".equals(node.getType()) && (node.getChildren() == null || node.getChildren().isEmpty())) { + + // 获取该部门岗位列表(注意类型已变为List) + List> positions = deptPositions.get(node.getId()); + if (positions != null) { + for (Map posMap : positions) { + // 创建岗位节点 + Node posNode = createPositionNode(posMap); + + // 获取岗位下人员列表 +// List> persons = +// positionPersons.get(posNode.getId()); // 通过岗位ID获取人员 + +// if (persons != null) { +// for (Map perMap : persons) { +// // 创建人员节点并添加到岗位节点 +// posNode.getChildren().add( +// createPersonNode(perMap) +// ); +// } +// } + + // 将岗位节点添加到部门节点 + node.getChildren().add(posNode); + } + } + } + // 递归处理非叶子部门 + else if (node.getChildren() != null) { + for (Node child : node.getChildren()) { + traverseAndInjectPositions(child, deptPositions, positionPersons); + } + } + } // 判断是否为根节点 private boolean isRootNode(String parentId) { return parentId == null @@ -513,7 +842,7 @@ public class XmindDataFilterCmd extends RegHookEvent { * 查询所有部门 */ private List> getAllDepartments(){ - String sql="select id,name,parent from eteams.department where 1=1"; + String sql="select id,name,parent from eteams.department where 1=1 and virtualid = '1' "; log.error("getAllDept.sql:{}", sql); Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); List> recordList = databaseUtils.getDataSourceList(rs); @@ -606,7 +935,7 @@ public class XmindDataFilterCmd extends RegHookEvent { // 执行SQL查询 String sql = "SELECT p.id AS dept_id, COUNT(e.id) AS employee_count FROM eteams.department\n" + "p LEFT JOIN eteams.employee e ON p.id = e.department WHERE p.TENANT_KEY = 't024j0gfn0'\n" + - "AND p.is_delete = '0' GROUP BY p.id "; + "AND p.is_delete = '0' and e.PERSONNEL_STATUS = 3 GROUP BY p.id "; // 获取原始结果集 log.error("initializeDeptEmployeeCount.sql:{}", sql); @@ -657,6 +986,43 @@ public class XmindDataFilterCmd extends RegHookEvent { log.error("initializePositionEmployeeCount.POSITION_EMPLOYEE_COUNT_MAP:{}", POSITION_EMPLOYEE_COUNT_MAP); } + + /** + * 根据岗位获取岗位人员姓名 + * @return + */ + public void initializePositionEmployee() { + POSITION_EMP_MAP.clear(); + // 执行SQL查询 + String sql = "SELECT p.id AS position_id, e.id,e.username as name " + + "FROM eteams.position p " + + "LEFT JOIN eteams.employee e ON p.id = e.position " + + "WHERE p.TENANT_KEY = 't024j0gfn0' " + + "AND p.is_delete = '0' " + + "AND (p.delete_type = '0' OR p.delete_type IS NULL) " + + "AND p.is_canceled = '0' and e.username is not null and e.PERSONNEL_STATUS = 3 " + + "GROUP BY p.id"; + + // 获取原始结果集 + log.error("initializePositionEmployeeCount.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("initializePositionEmployeeCount.recordList:{}", recordList); + + // 按部门ID分组(Java 8 Stream) + Map>> tempMap = recordList.stream() + .filter(row -> row.get("position_id") != null) + .collect(Collectors.groupingBy( + row -> String.valueOf(row.get("position_id")), + ConcurrentHashMap::new, + Collectors.toList() + )); + + // 更新全局映射 + POSITION_EMP_MAP.putAll(tempMap); + log.error("initialize.POSITION_EMP_MAP:{}", POSITION_EMP_MAP); + } + /** * 初始化人员职级 * @return @@ -786,7 +1152,7 @@ public class XmindDataFilterCmd extends RegHookEvent { ")\n" + "AND p.is_canceled = '0'\n" + "and pdl.delete_type = 0\n" + - "and pdl.department_id in (select id from eteams.department where 1=1) "; + "and pdl.department_id in (select id from eteams.department where 1=1 and virtualid = '1') "; log.error("initialize.sql:{}", sql); Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); List> recordList = databaseUtils.getDataSourceList(rs); diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncDsmlInfo.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncDsmlInfo.java new file mode 100644 index 0000000..3c576d6 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncDsmlInfo.java @@ -0,0 +1,231 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd; + +import com.weaver.common.base.entity.result.WeaResult; +import com.weaver.common.distribution.genid.IdGenerator; +import com.weaver.esb.api.rpc.EsbServerlessRpcRemoteInterface; +import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +import com.weaver.seconddev.jcl.organization.util.RecruitModuleUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * @use:人员卡片数据同步到导师名录 + * @date 2025年10月31日 + * @author xuxy + */ +@Service("SyncDsmlInfo_zkd") +public class SyncDsmlInfo implements EsbServerlessRpcRemoteInterface { + + @Autowired + private DatabaseUtils databaseUtils; + @Autowired + RecruitModuleUtils recruitModuleUtils; + + private static final Logger log = LoggerFactory.getLogger(SyncDsmlInfo.class); + + // 定义常量分组(Java 8兼容写法) + private static final Set GROUP_2345 = new HashSet<>(Arrays.asList( + "1175819959708491776", + "1175819963869241516", + "1175819976972247465" + )); + + private static final Set GROUP_45 = new HashSet<>(Arrays.asList( + "1175819963869241349", + "1175819976972247549", + "1175819976972247717" + )); + + @Override + public WeaResult> execute(Map params) { + Map result = new HashMap<>(); + log.error("SyncDsmlInfo.start:"+"11111111"); + log.error("SyncDsmlInfo.GROUP_2345:"+GROUP_2345); + log.error("SyncDsmlInfo.GROUP_45:"+GROUP_45); + /** + * 1.查询到原数据 + */ + List> dsmlInfo = getDsmlInfo(); + //log.error("SyncDsmlInfo.dsmlInfoSize:"+dsmlInfo.size()); + /** + * 2.根据position增加zsfw + */ + processDsmlInfo(dsmlInfo); + log.error("processDsmlInfo.dsmlInfo222:"+dsmlInfo); + /** + * 3.将查询原数据插入到(导师名录eb表中)/写入表单引擎数据大表 + */ + insertDsml(dsmlInfo); + log.error("SyncDsmlInfo.result:"+result); + return WeaResult.success(result); + } + +// public static void main(String[] args) { +// List> dsmlInfo = new ArrayList<>(); +// Map map = new HashMap<>(); +// map.put("id","1130926169645793287"); +// map.put("position","111"); +// map.put("department","1127665787032453134"); +// map.put("email","linyue@ustc.edu.cn"); +// map.put("username","林岳"); +// +// Map map1 = new HashMap<>(); +// map1.put("id","1130926169645793306"); +// map1.put("position","222"); +// map1.put("department","1127665709882425381"); +// map1.put("email","linyue@ustc.edu.cn"); +// map1.put("username","郭昌"); +// +// Map map2 = new HashMap<>(); +// map2.put("id","1130926212830347514"); +// map2.put("position","333"); +// map2.put("department","1127665520794812442"); +// map2.put("email","linyue@ustc.edu.cn"); +// map2.put("username","葛亮"); +// dsmlInfo.add(map); +// dsmlInfo.add(map1); +// dsmlInfo.add(map2); +// processDsmlInfo(dsmlInfo); +// } + + public static void processDsmlInfo(List> dsmlInfo) { + log.error("processDsmlInfo.dsmlInfo000:"+dsmlInfo); + for (Map map : dsmlInfo) { + String position = Optional.ofNullable(map.get("position")) + .map(Object::toString) + .orElse(""); + if ("1175819959708491776".equals(position)|| + "1175819963869241516".equals(position)|| + "1175819976972247465".equals(position)) { + map.put("zsfw", "2,3,4,5"); + } else if ("1175819963869241349".equals(position)|| + "1175819976972247549".equals(position)|| + "1175819976972247717".equals(position)) { + map.put("zsfw", "4,5"); + } else { + map.put("zsfw", ""); + } + } + } + + /** + * 写入导师名录eb表 + * @return + */ + public void insertDsml(List> dsmlInfo){ + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 格式化时间 + String formattedDateTime = now.format(formatter); + /** + * 插入前先删除导师名录表数据 + */ + String str = "update uf_dsml set is_delete=1,delete_type=1 where sjly = 0 "; + Map rt = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", str); + List> recordList = databaseUtils.getDataSourceList(rt); + log.error("insertDsml.recordList:{}", recordList); + for (Map map : dsmlInfo) { + // 生成随机 ID + long formuserdataid = IdGenerator.generate(); + log.error("insertDsml.formuserdataid:"+formuserdataid); + // 使用Optional进行空值安全处理 + String id = Optional.ofNullable(map.get("id")) + .map(Object::toString) + .orElse(""); + String username = Optional.ofNullable(map.get("username")) + .map(Object::toString) + .orElse(""); + String department = Optional.ofNullable(map.get("department")) + .map(Object::toString) + .orElse(""); + String email = Optional.ofNullable(map. get("email")) + .map(Object::toString) + .orElse(""); + String position = Optional.ofNullable(map.get("position")) + .map(Object::toString) + .orElse(""); + String zsfw = Optional.ofNullable(map.get("zsfw")) + .map(Object::toString) + .orElse(""); + String sql="insert into uf_dsml(id,form_data_id,data_index,create_time,creator,updater,TENANT_KEY,is_flow,data_status,xm,glry,xy,yx,gw,zsfw,sjly) " + + " values('"+formuserdataid+"','"+formuserdataid+"',0.0,'"+formattedDateTime+"','1103415980721364998','1103415980721364998','txk4srsbcd',0,1," + + " '"+username+"','"+id+"','"+department+"','"+email+"','"+position+"','"+zsfw+"','0') "; + log.error("insertDsml.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + /** + * 写入表单引擎数据大表 + */ + String stf="insert into formdata(id, form_id, layout_id, data_status, tenant_key, operator, create_time, update_time, " + + " module, client, is_delete, creator, delete_type)" + + " values('" + formuserdataid + "','1177631276257845249','1177631276257845321','submit','txk4srsbcd','1103415980721364998','" + formattedDateTime + "'," + + " '" + formattedDateTime + "','ebuilderform','pc','0','1103415980721364998','0')"; + log.error("insertFormdata.sql:{}", stf); + Map ry = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", stf); + + //List> recordList = databaseUtils.getDataSourceList(rs); + //log.error("insertDsml.recordList:{}", recordList); + } + } + + /** + * 写入表单引擎数据大表 + * @return + */ + public void insertFormdata(List> dsmlInfo){ + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 格式化时间 + String formattedDateTime = now.format(formatter); + log.error("insertFormdata.formattedDateTime:{}", formattedDateTime); + for (Map map : dsmlInfo) { + String sql="insert into formdata(id, form_id, layout_id, data_status, tenant_key, operator, create_time, update_time, " + + " module, client, is_delete, creator, delete_type)" + + " values('" + map.get("id") + "','1177631276257845249','1177631276257845321','submit','txk4srsbcd','1103415980721364998','" + formattedDateTime + "'," + + " '" + formattedDateTime + "','ebuilderform','pc','0','1103415980721364998','0')"; + log.error("insertFormdata.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + } + //List> recordList = databaseUtils.getDataSourceList(rs); + //log.error("insertFormdata.recordList:{}", recordList); + } + + /** + * 写入EB表单数据大表 + * @return + */ + public void insertPhysical(Map map,String obj_id){ + String sql="insert into ebdf_physical_data(id, tenant_key, obj_id, name, form_data_id, form_table_id, is_flow, data_status, creator, create_time)" + + " values('" + map.get("id") + "','" + map.get("tenant_key") + "','" + obj_id + "','" + map.get("name") + "','" + map.get("id") + "'," + + " '" + map.get("id") + "','" + map.get("is_flow") + "','" + map.get("data_status") + "','" + map.get("creator") + "','" + map.get("create_time") + "')"; + log.error("insertPhysical.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("insertPhysical.recordList:{}", recordList); + } + + + + /** + * 全量人员信息中筛选出符合条件的岗位人员数据 + * @return + */ + public List> getDsmlInfo(){ + //String sql = "select * from eteams.position where name in('教授','研究员','特任教授','副教授','特任研究员','特任正高级工程师')"; + String sql = " select id,username,department,email,position from eteams.employee where position \n" + + " in(1175819959708491776,1175819963869241349,1175819963869241516,1175819976972247465,1175819976972247549,1175819976972247717)"; + log.error("getDsmlInfo.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getDsmlInfo.recordList:{}", recordList); + return recordList; + } +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncTermBasedPerson.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncTermBasedPerson.java new file mode 100644 index 0000000..f209934 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/SyncTermBasedPerson.java @@ -0,0 +1,203 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.weaver.common.base.entity.result.WeaResult; +import com.weaver.common.distribution.genid.IdGenerator; +import com.weaver.common.ei.utils.Util; +import com.weaver.common.mybatis.sqlinjection.interceptor.StringUtil; +import com.weaver.ebuilder.common.exception.BusinessException; +import com.weaver.esb.api.rpc.EsbServerlessRpcRemoteInterface; +import com.weaver.seconddev.jcl.organization.esb.zkd.entity.ApiResponse; +import com.weaver.seconddev.jcl.organization.esb.zkd.entity.UserData; +import com.weaver.seconddev.jcl.organization.esb.zkd.util.HttpUtil; +import com.weaver.seconddev.jcl.organization.esb.zkd.util.PapiUtil; +import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * @use:同步聘期制人员 + * @date 2025年11月12日 + * @author xuxy + */ +@Service("SyncTermBasedPerson_zkd") +public class SyncTermBasedPerson implements EsbServerlessRpcRemoteInterface { + + @Autowired + private DatabaseUtils databaseUtils; + @Autowired + private HttpUtil httpUtil; + + private static final Logger log = LoggerFactory.getLogger(SyncTermBasedPerson.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + private static String baseUrl = "https://dcm.ustc.edu.cn"; + private static String tokenPath = "/open_api/authentication/get_access_token"; + private static String employeeInfoPath = "/open_api/customization/tgxggfwdzzcyhxx/full"; + + @Override + public WeaResult> execute(Map params) { + Map result = new HashMap<>(); + log.error("SyncTermBasedPerson.start:"+"11111111"); + /** + * 1。获取token + */ + try { + String json11 = httpUtil.callGetApi(baseUrl, tokenPath, "20250421259519141525246261411841844", "f3603149693d172fc2e0de6b6818a2a2ddc9048c"); + log.error("ZkdGetInfoController.json:"+json11); + log.debug("Token响应: {}", json11); + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(json11); + String accessToken = ""; + // 校验业务状态码 + if (root.get("code").asInt() != 10000) { + String errMsg = String.format("三方接口错误 [%d]: %s", + root.get("code").asInt(), + root.get("message").asText() + ); + log.error(errMsg); + throw new BusinessException(errMsg); + } + // 3. 提取access_token(带空值校验) + JsonNode resultNode = root.get("result"); + if (resultNode == null || resultNode.isEmpty()) { + log.error("三方接口响应结构异常: result节点为空"); + throw new BusinessException("三方接口返回无效的result结构"); + } + accessToken = resultNode.get("access_token").asText(); + log.info("获取Token成功: {}", accessToken); + /** + * 2.根据accessToken获取:电子注册用户信息 + */ + String resultInfo = httpUtil.callPostApi(baseUrl, employeeInfoPath, "", accessToken); + log.error("ZkdGetInfoController.resultInfo:"+resultInfo); + List users = parseUserData(resultInfo); + log.error("ZkdGetInfoController.users:"+users); + result.put("users",users); + /** + * 3.根据返回的电子注册用户信息,在自身系统创建人员账号 + */ + syncEmployeeInfo(users); + } catch (Exception e) { + e.printStackTrace(); + } + log.error("SyncDsmlInfo.result:"+result); + return WeaResult.success(result); + } + + + // 直接解析JSON获取用户数据列表 + public static List parseUserData(String jsonResponse) throws Exception { + ApiResponse response = mapper.readValue(jsonResponse, ApiResponse.class); + + // 验证业务状态码(可选) + if (!"10000".equals(response.getCode())) { + throw new IllegalStateException("业务错误: " + response.getMessage()); + } + + return response.getResult().getData(); // 直接返回data列表 + } + + /** + * 同步员工信息 + */ + private void syncEmployeeInfo(List users) { + log.error("syncEmployeeInfo runnint"); + String e10code = PapiUtil.getCode(); + String e10accessToken = PapiUtil.getAccessToken(e10code); + //同步人员数据结构 + JSONArray datalist = new JSONArray(); + for (UserData user : users) { + JSONObject obj = new JSONObject(); + + //姓名 + String username = Util.null2String(user.getYhxm()); + //邮箱 + String email = Util.null2String(user.getDzyx()); + //主要邮箱 + String mainMmail = Util.null2String(user.getZyyx()); + if(StringUtils.isNotBlank(mainMmail)){ + email = mainMmail; + } + //人员分类码 + String ryfl = Util.null2String(user.getRyflm()); + if(("180030000".equals(ryfl)||"180040000".equals(ryfl))&&StringUtils.isNotBlank(email)){ + //手机号 + //String mobile = Util.null2String(dataobj.get("sjh")); + //办公电话 + // telephone = Util.null2String(dataobj.get("bgdh")); + //性别(male、female) +// String sex = Util.null2String(dataobj.get("xbm")); +// if ("1".equals(sex)) { +// sex = "male"; +// } else { +// sex = "female"; +// } + //工号 + String job_num = Util.null2String(user.getXgh()); + //入职日期 +// String hiredate = Util.null2String(dataobj.get("jxrq")); + //部门(所属组织) + //String department = Util.null2String(dataobj.get("dwbm")); + //状态(1:试用;2:试用延期;3:正式;4:临时;5:实习;6:离职;7:退休) + //String personnel_status = "3"; + //身份证 + //String id_no = Util.null2String(dataobj.get("sfzjh")); + //籍贯 + // String jg = Util.null2String(dataobj.get("jg")); + //账号 +// String account = ""; +// if(StringUtils.isNotBlank(mobile)){ +// account = mobile; +// }else if(StringUtils.isNotBlank(email)){ +// account = email; +// }else{ +// continue; +// } +// String loginid = Util.null2String(dataobj.get("gid")); +// +// String password = "1"; + + obj.put("username", username);//必须 todo + obj.put("email", email); + //obj.put("mobile", mobile); + //obj.put("telephone", telephone); + //obj.put("sex", sex); + obj.put("job_num", job_num); + //obj.put("department", department);//必须 todo + obj.put("personnel_status", "1");//必须 todo + //obj.put("id_no", id_no); +// obj.put("account", account); +// obj.put("loginid", loginid); +// obj.put("password", password); + //obj.put("userInfoExtend", userInfoExtend); + // obj.put("employeeExtend", employeeExtend); + datalist.add(obj); + } + + } + + //调用接口平台 标准接口 + Map params = new HashMap<>(10); + + JSONObject dataRule = new JSONObject(10);//规则必须 todo + dataRule.put("department", "code"); + dataRule.put("employee", "job_num"); + + params.put("data", datalist); + params.put("dataRule", dataRule); + + PapiUtil.syncEmployee(e10accessToken, params); + } + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/controller/ZkdGetInfoController.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/controller/ZkdGetInfoController.java new file mode 100644 index 0000000..83e8d58 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/controller/ZkdGetInfoController.java @@ -0,0 +1,119 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.controller; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.weaver.common.authority.annotation.WeaPermission; +import com.weaver.ebuilder.common.exception.BusinessException; +import com.weaver.seconddev.jcl.organization.esb.zkd.entity.ApiResponse; +import com.weaver.seconddev.jcl.organization.esb.zkd.entity.UserData; +import com.weaver.seconddev.jcl.organization.esb.zkd.util.HttpUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import java.util.ArrayList; +import java.util.List; + +@RestController +@RequestMapping("/api/secondev/jcl/zkdGetInfo") +public class ZkdGetInfoController { + + @Autowired + private HttpUtil httpUtil; + + private static final Logger log = LoggerFactory.getLogger(ZkdGetInfoController.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + private static String baseUrl = "https://dcm.ustc.edu.cn"; + private static String tokenPath = "/open_api/authentication/get_access_token"; + private static String employeeInfoPath = "/open_api/customization/tgxggfwdzzcyhxx/full"; + + /** + * 二开测试接口 + * @return + */ + @GetMapping("/test") + @WeaPermission(publicPermission = true) + public String secondTest(@RequestParam("name") String name){ + log.error("secondTest.name:{}",name); + return name ; + + } + + /** + * 获取三方接口信息 + * @return + */ + @GetMapping("/syncTermBasedPerson") + @WeaPermission(publicPermission = true) + public List syncTermBasedPerson(){ + log.error("ZkdGetInfoController.start:"+"11111111"); + log.error("ZkdGetInfoController.httpUtil:"+httpUtil); + List users = new ArrayList<>(); + /** + * 1。获取token + */ + try { + log.error("ZkdGetInfoController.baseUrl:"+baseUrl); + log.error("ZkdGetInfoController.tokenPath:"+tokenPath); + log.error("ZkdGetInfoController.clientId:"+"20250421259519141525246261411841844"); + log.error("ZkdGetInfoController.clientSecret:"+"f3603149693d172fc2e0de6b6818a2a2ddc9048c"); + + String json11 = httpUtil.callGetApi(baseUrl, tokenPath, "20250421259519141525246261411841844", "f3603149693d172fc2e0de6b6818a2a2ddc9048c"); + log.error("ZkdGetInfoController.json:"+json11); + log.debug("Token响应: {}", json11); + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(json11); + String accessToken = ""; + // 校验业务状态码 + if (root.get("code").asInt() != 10000) { + String errMsg = String.format("三方接口错误 [%d]: %s", + root.get("code").asInt(), + root.get("message").asText() + ); + log.error(errMsg); + throw new BusinessException(errMsg); + } + // 3. 提取access_token(带空值校验) + JsonNode resultNode = root.get("result"); + if (resultNode == null || resultNode.isEmpty()) { + log.error("三方接口响应结构异常: result节点为空"); + throw new BusinessException("三方接口返回无效的result结构"); + } + accessToken = resultNode.get("access_token").asText(); + log.info("获取Token成功: {}", accessToken); + /** + * 2.根据accessToken获取:电子注册用户信息 + */ + String resultInfo = httpUtil.callPostApi(baseUrl, employeeInfoPath, "", accessToken); + log.error("ZkdGetInfoController.resultInfo:"+resultInfo); + users = parseUserData(resultInfo); + log.error("ZkdGetInfoController.users:"+users); + /** + * 3.根据返回的电子注册用户信息,在自身系统创建人员账号 + */ + } catch (Exception e) { + log.error("接口调用异常 - URL: {} PATH: {}", baseUrl, tokenPath, e); // 记录完整堆栈到日志 + // 可选:抛出封装后的业务异常 + throw new BusinessException("三方接口调用失败", e); + } + return users; + + } + + // 直接解析JSON获取用户数据列表 + public static List parseUserData(String jsonResponse) throws Exception { + ApiResponse response = mapper.readValue(jsonResponse, ApiResponse.class); + log.error("parseUserData.response:"+response); + // 验证业务状态码(可选) + if (!"10000".equals(response.getCode())) { + throw new IllegalStateException("业务错误: " + response.getMessage()); + } + + return response.getResult().getData(); // 直接返回data列表 + } + +} \ No newline at end of file diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/ApiResponse.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/ApiResponse.java new file mode 100644 index 0000000..661180a --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/ApiResponse.java @@ -0,0 +1,28 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.entity; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ApiResponse { + @JsonProperty("code") + private String code; + @JsonProperty("description") + private String description; + @JsonProperty("message") + private String message; + @JsonProperty("result") + private Result result; + @JsonProperty("uuid") + private String uuid; +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/Result.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/Result.java new file mode 100644 index 0000000..d9bb38f --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/Result.java @@ -0,0 +1,40 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.entity; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Result { + @JsonProperty("data") + private List data; // 核心数据列表 + @JsonProperty("data_struct") + private Map data_struct; + @JsonProperty("encrypted_field") + private String encrypted_field; + @JsonProperty("max_page") + private int max_page; + @JsonProperty("page") + private int page; + @JsonProperty("per") + private int per; + @JsonProperty("per_page") + private int per_page; + @JsonProperty("total") + private int total; + @JsonProperty("water_mark") + private int water_mark; + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/UserData.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/UserData.java new file mode 100644 index 0000000..1aa7a2a --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/entity/UserData.java @@ -0,0 +1,44 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.entity; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * uf_jcl_employee_information + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserData { + @JsonProperty("wybs") + private String wybs; // 唯一标识 + @JsonProperty("yhgid") + private String yhgid; // 用户GID + @JsonProperty("xgh") + private String xgh; // 学工号 + @JsonProperty("yhxm") + private String yhxm; // 用户姓名 + @JsonProperty("zsfid") + private String zsfid; // 主身份ID + @JsonProperty("dzyx") + private String dzyx; // 电子邮箱 + @JsonProperty("dzyxqrzt") + private String dzyxqrzt;// 邮箱确认状态 + @JsonProperty("zyyx") + private String zyyx; // 主要邮箱 + @JsonProperty("cjsj") + private String cjsj; // 创建时间 + @JsonProperty("gxsj") + private String gxsj; // 更新时间 + @JsonProperty("tstamp") + private String tstamp; // 时间戳 + @JsonProperty("ryglflm") + private String ryglflm; // 人员管理分类码 + @JsonProperty("ryflm") + private String ryflm; // 人员分类码 +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpCilentUtil.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpCilentUtil.java new file mode 100644 index 0000000..410af2f --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpCilentUtil.java @@ -0,0 +1,892 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.util; + +import okhttp3.*; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.*; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.TrustAllStrategy; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * http请求工具类 + * + * @author wangj + * @version 1.00版本 + * @Date 2025-4-24 + */ + +public class HttpCilentUtil { + private static final Logger logger = LoggerFactory.getLogger(HttpCilentUtil.class); + + /** + * post请求 xml格式,带请求头 + * + * @param httpurl + * @param header + * @param xmlPayload + * @return + */ + public static String postXmlRequestHeader(String httpurl, Map header, String xmlPayload) { + String result = ""; + try { + // 接口的 URL + URL url = new URL(httpurl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + // 设置请求方法为 POST + connection.setRequestMethod("POST"); + + // 设置请求头 + connection.setRequestProperty("Content-Type", "application/xml"); + if (header != null) { + for (String key : header.keySet()) { + connection.setRequestProperty(key, header.get(key)); + } + } + // 允许输出 + connection.setDoOutput(true); + + byte[] input = xmlPayload.getBytes(StandardCharsets.UTF_8); + + // 写入 XML 数据 + try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { + outputStream.write(input); + } + + // 获取响应码 + int responseCode = connection.getResponseCode(); + + // 读取响应 + try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String line; + StringBuilder response = new StringBuilder(); + while ((line = reader.readLine()) != null) { + response.append(line); + } + result = response.toString(); + } + } catch (Exception e) { + logger.error("postXmlRequestHeader Exception:" + e.getMessage()); + } + return result; + } + + /** + * 带参数的get请求 + * + * @param url + * @param param + * @return String + */ + public static String doGet(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + // 执行请求 + response = httpclient.execute(httpGet); + // 判断返回状态是否为200 +// if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); +// } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 不带参数的get请求 + * + * @param url + * @return String + */ + public static String doGet(String url) { + return doGet(url, null); + } + + public static String doPostFile(String url, File file, String fileName, String token) { + String resultString = ""; + // 创建 HttpClient 实例 + HttpClient httpClient = HttpClients.createDefault(); + // 创建 HttpPost 请求 + HttpPost httpPost = new HttpPost(url); + try { + // 在请求头中添加 token + httpPost.addHeader("Authorization", "bearer " + token); + + // 创建 MultipartEntityBuilder 用于构建 multipart/form-data 请求体 + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + + // 添加文件参数 + FileBody fileBody = new FileBody(file); + builder.addPart("file", fileBody); + + // 添加普通文本参数 + builder.addTextBody("fileName", fileName, ContentType.TEXT_PLAIN.withCharset("UTF-8")); + // 构建请求实体 + HttpEntity multipart = builder.build(); + httpPost.setEntity(multipart); + // 执行请求 + HttpResponse response = httpClient.execute(httpPost); + // 获取响应实体 + HttpEntity responseEntity = response.getEntity(); + if (responseEntity != null) { + // 打印响应内容 + resultString = EntityUtils.toString(responseEntity); + } + } catch (IOException e) { + System.out.println("IOException:" + e.getMessage()); + e.printStackTrace(); + } finally { + // 释放连接 + httpPost.releaseConnection(); + } + return resultString; + } + + /** + * 带参数的post请求 + * + * @param url + * @param param + * @return String + */ + public static String doPost(String url, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 带参数,带请求头的post请求 + * + * @param url + * @param param + * @return String + */ + public static String doParamHeaderPost(String url, Map header, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + // 创建请求头 + if (header != null) { + for (String key : header.keySet()) { + httpPost.addHeader(key, header.get(key)); + } + } + // 创建参数列表 + if (param != null) { + List paramList = new ArrayList<>(); + for (String key : param.keySet()) { + paramList.add(new BasicNameValuePair(key, param.get(key))); + } + // 模拟表单 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList); + httpPost.setEntity(entity); + } + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 不带参数的post请求 + * + * @param url + * @return String + */ + public static String doPost(String url) { + return doPost(url, null); + } + + /** + * 传送json类型的post请求 + * + * @param url + * @param json + * @return String + */ + public static String doPostJson(String url, String json) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("accept", "application/json;charset=utf-8"); + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 传送json类型的post请求带header + * + * @param url + * @param json + * @param header + * @return String + */ + public static String doPostJsonHeader(String url, String json, Map header) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("accept", "application/json;charset=utf-8"); + if (header != null) { + for (String key : header.keySet()) { + httpPost.addHeader(key, header.get(key)); + } + } + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * post请求带header + * + * @param url + * @param header + * @return String + */ + public static String doPostHeader(String url, Map header) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("accept", "application/json;charset=utf-8"); + if (header != null) { + for (String key : header.keySet()) { + httpPost.addHeader(key, header.get(key)); + } + } + // 创建请求内容 + + // 执行http请求 + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 传送json类型的post请求带header + * + * @param url + * @param header + * @return String + */ + public static String doPostJsonHeader(String url, Map header, String json) { + // 创建Httpclient对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + String resultString = ""; + try { + // 创建Http Post请求 + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("accept", "application/json;charset=utf-8"); + if (header != null) { + for (String key : header.keySet()) { + httpPost.addHeader(key, header.get(key)); + } + } + // 创建请求内容 + StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); + httpPost.setEntity(entity); + + response = httpClient.execute(httpPost); + resultString = EntityUtils.toString(response.getEntity(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * 带参数的get请求带header + * + * @param url + * @param param + * @return String + */ + public static String doGetHeader(String url, Map header, Map param) { + // 创建Httpclient对象 + CloseableHttpClient httpclient = HttpClients.createDefault(); + + String resultString = ""; + CloseableHttpResponse response = null; + try { + // 创建uri + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + // 创建http GET请求 + HttpGet httpGet = new HttpGet(uri); + + httpGet.addHeader("accept", "application/json;charset=utf-8"); + if (header != null) { + for (String key : header.keySet()) { + httpGet.addHeader(key, header.get(key)); + } + } + // 执行请求 + response = httpclient.execute(httpGet); +// // 判断返回状态是否为200 +// if (response.getStatusLine().getStatusCode() == 200) { + resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); +// } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultString; + } + + /** + * POST请求接口,跳过ssl证书 + * + * @param url + * @param params + * @return + */ + public static String doPostNoSSL(String url, String params) { + String result = ""; + try { + // 创建信任所有证书的 SSL 上下文 + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, TrustAllStrategy.INSTANCE) + .build(); + + // 创建 HttpClient 实例,使用自定义的 SSL 上下文和主机名验证器 + HttpClient httpClient = HttpClients.custom() + .setSslcontext(sslContext) + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + + // 创建 HttpPost 请求 + HttpPost httpPost = new HttpPost(url); + + // 设置请求体 + StringEntity entity = new StringEntity(params); + httpPost.setEntity(entity); + httpPost.setHeader("Content-Type", "application/json"); + + // 执行请求 + HttpResponse response = httpClient.execute(httpPost); + + // 处理响应 + int statusCode = response.getStatusLine().getStatusCode(); + result = EntityUtils.toString(response.getEntity()); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + + /** + * 带参数的get请求 跳过ssl证书 + * + * @param url + * @return String + */ + public static String doGetNoSSL(String url, Map params) { + String result = ""; + try { + + // 创建信任所有证书的 SSL 上下文 + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, TrustAllStrategy.INSTANCE) + .build(); + + // 创建 HttpClient 实例,使用自定义的 SSL 上下文和主机名验证器 + HttpClient httpClient = HttpClients.custom() + .setSslcontext(sslContext) + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + + + // 构建带参数的 URL + String fullUrl = buildUrlWithParams(url, params); + + // 创建 HttpGet 请求 + HttpGet httpGet = new HttpGet(fullUrl); + httpGet.setHeader("User-Agent", "Apache HttpClient"); + + + // 执行请求并获取响应 + HttpResponse response = httpClient.execute(httpGet); + + // 检查响应状态码 + int statusCode = response.getStatusLine().getStatusCode(); + // 成功响应,获取响应内容 + result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + + + } catch (Exception e) { + e.printStackTrace(); + } + + + return result; + } + + + /** + * 构建带查询参数的 URL + */ + private static String buildUrlWithParams(String url, Map params) throws UnsupportedEncodingException { + if (params == null || params.isEmpty()) { + return url; + } + + StringBuilder queryString = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (queryString.length() > 0) { + queryString.append("&"); + } + queryString.append(URLEncoder.encode(entry.getKey(), "UTF-8")) + .append("=") + .append(URLEncoder.encode(entry.getValue(), "UTF-8")); + } + + // 处理 URL 中是否已有查询参数 + if (url.contains("?")) { + return url + "&" + queryString; + } else { + return url + "?" + queryString; + } + } + + + + /** + * POST请求接口,跳过ssl证书 + * + * @param url + * @param params + * @return + */ + public static String doPostHeaderNoSSL(String url, Map headers,String params) { + String result = ""; + try { + // 创建信任所有证书的 SSL 上下文 + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, TrustAllStrategy.INSTANCE) + .build(); + + // 创建 HttpClient 实例,使用自定义的 SSL 上下文和主机名验证器 + HttpClient httpClient = HttpClients.custom() + .setSslcontext(sslContext) + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + + // 创建 HttpPost 请求 + HttpPost httpPost = new HttpPost(url); + httpPost.setHeader("Content-Type", "application/json"); + + // 添加自定义请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue()); + } + } + + // 设置请求体 + if (params != null && !params.isEmpty()) { + StringEntity entity = new StringEntity(params, "UTF-8"); // 指定编码,避免中文乱码 + httpPost.setEntity(entity); + } + + // 执行请求 + HttpResponse response = httpClient.execute(httpPost); + + // 处理响应 + int statusCode = response.getStatusLine().getStatusCode(); + result = EntityUtils.toString(response.getEntity()); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + + /** + * 带参数的get请求 跳过ssl证书 + * + * @param url + * @return String + */ + public static String doGetHeaderNoSSL(String url, Map headers,Map params) { + String result = ""; + try { + + // 创建信任所有证书的 SSL 上下文 + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, TrustAllStrategy.INSTANCE) + .build(); + + // 创建 HttpClient 实例,使用自定义的 SSL 上下文和主机名验证器 + HttpClient httpClient = HttpClients.custom() + .setSslcontext(sslContext) + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + + + // 构建带参数的 URL + String fullUrl = buildUrlWithParams(url, params); + + // 创建 HttpGet 请求 + HttpGet httpGet = new HttpGet(fullUrl); + httpGet.setHeader("User-Agent", "Apache HttpClient"); + + + // 添加自定义请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpGet.setHeader(entry.getKey(), entry.getValue()); + } + } + + + // 执行请求并获取响应 + HttpResponse response = httpClient.execute(httpGet); + + // 检查响应状态码 + int statusCode = response.getStatusLine().getStatusCode(); + // 成功响应,获取响应内容 + result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + + + } catch (Exception e) { + e.printStackTrace(); + } + + + return result; + } + + + /** + * DELETE请求接口,跳过ssl证书 + * + * @param url 请求地址 + * @param headers 请求头信息 + * @param params 请求参数 + * @return 响应结果 + */ + public static String doDeleteHeaderNoSSL(String url, Map headers, String params) { + String result = ""; + try { + // 创建信任所有证书的 SSL 上下文 + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, TrustAllStrategy.INSTANCE) + .build(); + + // 创建 HttpClient 实例,使用自定义的 SSL 上下文和主机名验证器 + HttpClient httpClient = HttpClients.custom() + .setSslcontext(sslContext) + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + + // 创建 HttpDelete 请求 + HttpDelete httpDelete = new HttpDelete(url); + httpDelete.setHeader("Content-Type", "application/json"); + + // 添加自定义请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpDelete.setHeader(entry.getKey(), entry.getValue()); + } + } + + // 设置请求体(某些DELETE请求可能需要传递参数) + if (params != null && !params.isEmpty()) { + // 对于需要在请求体中传递参数的DELETE请求,使用HttpEntityEnclosingRequestBase + HttpEntityEnclosingRequestBase httpDeleteWithBody = new HttpEntityEnclosingRequestBase() { + @Override + public String getMethod() { + return "DELETE"; + } + }; + httpDeleteWithBody.setURI(new URI(url)); + httpDeleteWithBody.setHeader("Content-Type", "application/json"); + + // 复制请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpDeleteWithBody.setHeader(entry.getKey(), entry.getValue()); + } + } + + StringEntity entity = new StringEntity(params, "UTF-8"); + httpDeleteWithBody.setEntity(entity); + + // 执行请求 + HttpResponse response = httpClient.execute(httpDeleteWithBody); + result = EntityUtils.toString(response.getEntity()); + } else { + // 执行没有请求体的DELETE请求 + HttpResponse response = httpClient.execute(httpDelete); + result = EntityUtils.toString(response.getEntity()); + } + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + + /** + * PUT请求接口,跳过ssl证书 + * + * @param url 请求地址 + * @param headers 请求头信息 + * @param params 请求参数 + * @return 响应结果 + */ + public static String doPutHeaderNoSSL(String url, Map headers, String params) { + String result = ""; + try { + // 创建信任所有证书的 SSL 上下文 + SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(null, TrustAllStrategy.INSTANCE) + .build(); + + // 创建 HttpClient 实例,使用自定义的 SSL 上下文和主机名验证器 + HttpClient httpClient = HttpClients.custom() + .setSslcontext(sslContext) + .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + + // 创建 HttpPut 请求 + HttpPut httpPut = new HttpPut(url); + httpPut.setHeader("Content-Type", "application/json"); + + // 添加自定义请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpPut.setHeader(entry.getKey(), entry.getValue()); + } + } + + // 设置请求体(某些PUT请求可能需要传递参数) + if (params != null && !params.isEmpty()) { + // 对于需要在请求体中传递参数的PUT请求,使用HttpEntityEnclosingRequestBase + HttpEntityEnclosingRequestBase httpDeleteWithBody = new HttpEntityEnclosingRequestBase() { + @Override + public String getMethod() { + return "PUT"; + } + }; + httpDeleteWithBody.setURI(new URI(url)); + httpDeleteWithBody.setHeader("Content-Type", "application/json"); + + // 复制请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpDeleteWithBody.setHeader(entry.getKey(), entry.getValue()); + } + } + + StringEntity entity = new StringEntity(params, "UTF-8"); + httpDeleteWithBody.setEntity(entity); + + // 执行请求 + HttpResponse response = httpClient.execute(httpDeleteWithBody); + result = EntityUtils.toString(response.getEntity()); + } else { + // 执行没有请求体的PUT请求 + HttpResponse response = httpClient.execute(httpPut); + result = EntityUtils.toString(response.getEntity()); + } + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + + public static String okhttp3doPost(String url,String app_key,String app_security,String account,String authType) { + String resultString = ""; + Response response = null; + try { + + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + MediaType mediaType = MediaType.parse("text/plain"); + RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) + .addFormDataPart("app_key", app_key) + .addFormDataPart("app_security", app_security) + .addFormDataPart("account", account) + .addFormDataPart("authType", authType) + .build(); + Request request = new Request.Builder() + .url(url) + .method("POST", body) + .build(); + response = client.newCall(request).execute(); + resultString = response.body().string(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + response.close(); + } + } + return resultString; + } + + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpUtil.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpUtil.java new file mode 100644 index 0000000..87279e1 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/HttpUtil.java @@ -0,0 +1,83 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.util; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; + +import java.net.URI; +@Slf4j +@Component +public class HttpUtil { + private static final int TIMEOUT = 5000; // 5秒超时 + + public String callGetApi(String baseUrl, String apiPath,String clientId, String clientSecret) throws Exception { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + // 构建完整URL + URI uri = new URIBuilder(baseUrl + apiPath) + .addParameter("key", clientId) + .addParameter("secret", clientSecret) + .build(); + log.error("HttpUtil.url"+uri); + HttpGet request = new HttpGet(uri); + request.setConfig(RequestConfig.custom() + .setConnectTimeout(TIMEOUT) + .setSocketTimeout(30000) + .build()); + request.setHeader("Content-Type", "application/json"); + log.error("HttpUtil.request"+request); + try (CloseableHttpResponse response = httpClient.execute(request)) { + log.error("HttpUtil.response"+response); + int statusCode = response.getStatusLine().getStatusCode(); + log.error("HttpUtil.statusCode"+statusCode); + if (statusCode < 200 || statusCode >= 300) { + throw new RuntimeException("HTTP error: " + statusCode); + } + HttpEntity entity = response.getEntity(); + log.error("HttpUtil.entity"+entity); + return EntityUtils.toString(entity); + } + } + } + + // POST请求方法 + public String callPostApi(String baseUrl, String apiPath,String jsonBody, String token) throws Exception { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + URI uri = new URIBuilder(baseUrl + apiPath).build(); + HttpPost request = new HttpPost(uri); + + // 设置请求头 + request.setHeader("Content-Type", "application/json"); + if (token != null) { + request.setHeader("Authorization", "Bearer " + token); + } + + // 设置请求体 + request.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8)); + + // 设置超时配置 + request.setConfig(RequestConfig.custom() + .setConnectTimeout(TIMEOUT) + .setSocketTimeout(TIMEOUT) + .build()); + log.error("callPostApi.request"+request); + try (CloseableHttpResponse response = httpClient.execute(request)) { + log.error("callPostApi.response"+request); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode < 200 || statusCode >= 300) { + throw new RuntimeException("HTTP error: " + statusCode); + } + return EntityUtils.toString(response.getEntity()); + } + } + } +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/PapiUtil.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/PapiUtil.java new file mode 100644 index 0000000..6bfc2ee --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/esb/zkd/util/PapiUtil.java @@ -0,0 +1,192 @@ +package com.weaver.seconddev.jcl.organization.esb.zkd.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.weaver.signcenter.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * 接口平台调用工具类 + * + * @author wangj + * @version 1.00版本 + * @Date 2025-4-27 + */ + +public class PapiUtil { + private final static Logger log = LoggerFactory.getLogger(PapiUtil.class); + + private static String host = "https://hr.ustc.edu.cn/pqz"; + private static String corpid = "c4e15b4733f463615c4d78d09a52d732"; + private static String app_key = "ae7959882729017d7919b33b8b1735d1"; + private static String app_secret = "26456dcd33506b68a656c057b68bf6f"; + + + /** + * 获取CODE + * + * @return + */ + public static String getCode() { + String url = "/papi/openapi/oauth2/authorize"; + Map params = new HashMap<>(10); + params.put("corpid", corpid); + params.put("response_type", "code"); + params.put("state", ""); + String code = ""; + String result = HttpCilentUtil.doPost(host + url, params); + JSONObject resObj = JSON.parseObject(result); + String errcode = Util.null2String(resObj.get("errcode")); + if ("0".equals(errcode)) { + code = Util.null2String(resObj.get("code")); + } + return code; + } + + + /** + * 获取AccessToken + * + * @param code + * @return + */ + public static String getAccessToken(String code) { + String url = "/papi/openapi/oauth2/access_token"; + Map params = new HashMap<>(10); + params.put("app_key", app_key); + params.put("app_secret", app_secret); + params.put("grant_type", "authorization_code"); + params.put("code", code); + String accessToken = ""; + String result = HttpCilentUtil.doPost(host + url, params); + JSONObject resObj = JSON.parseObject(result); + String errcode = Util.null2String(resObj.get("errcode")); + if ("0".equals(errcode)) { + accessToken = Util.null2String(resObj.get("accessToken")); + } + return accessToken; + } + + /** + * 同步人员 + */ + public static boolean syncEmployee(String accessToken, Map params) { + boolean flag = true; + String url = "/papi/openapi/api/hrm/restful/syncEmployee?access_token=" + accessToken; + String result = HttpCilentUtil.doPostJson(host + url, JSONObject.toJSONString(params)); + JSONObject resObj = JSON.parseObject(result); + JSONObject message = (JSONObject) resObj.get("message"); + String errcode = Util.null2String(message.get("errcode")); + if ("0".equals(errcode)) { + JSONArray data = (JSONArray) resObj.get("data"); + JSONObject dataObj = (JSONObject) data.get(0); + String status = (String) dataObj.get("status"); + if (!"SUCCESS".equals(status)) { + flag = false; + log.error("syncEmployee params:" + JSONObject.toJSONString(params)); + log.error("syncEmployee result:" + result); + } + } + log.error("syncEmployee result:" + result); + + return flag; + } + + /** + * 同步部门 + */ + public static boolean syncDepartment(String accessToken, Map params) { + boolean flag = true; + String url = "/papi/openapi/api/hrm/restful/syncDepartment?access_token=" + accessToken; + String result = HttpCilentUtil.doPostJson(host + url, JSONObject.toJSONString(params)); + JSONObject resObj = JSON.parseObject(result); + JSONObject message = (JSONObject) resObj.get("message"); + String errcode = Util.null2String(message.get("errcode")); + if ("0".equals(errcode)) { + JSONArray data = (JSONArray) resObj.get("data"); + for (int i = 0; i < data.size(); i++) { + JSONObject dataObj = (JSONObject) data.get(i); + String status = (String) dataObj.get("status"); + if (!"SUCCESS".equals(status)) { + flag = false; + } + } + } + if (!flag) { + log.error("syncDepartment params:" + JSONObject.toJSONString(params)); + log.error("syncDepartment result:" + result); + } + return flag; + } + + + /** + * 同步岗位 + */ + public static boolean syncPosition(String accessToken, Map params) { + boolean flag = true; + String url = "/papi/openapi/api/hrm/restful/syncPosition?access_token=" + accessToken; + String result = HttpCilentUtil.doPostJson(host + url, JSONObject.toJSONString(params)); + JSONObject resObj = JSON.parseObject(result); + JSONObject message = (JSONObject) resObj.get("message"); + String errcode = Util.null2String(message.get("errcode")); + if ("0".equals(errcode)) { + JSONArray data = (JSONArray) resObj.get("data"); + for (int i = 0; i < data.size(); i++) { + JSONObject dataObj = (JSONObject) data.get(i); + String status = (String) dataObj.get("status"); + if (!"SUCCESS".equals(status)) { + flag = false; + } + } + } + if (!flag) { + log.error("syncPosition params:" + JSONObject.toJSONString(params)); + log.error("syncPosition result:" + result); + } + return flag; + } + + + /** + * 同步建模数据信息 + */ + public static boolean updateFormData(String jkbs, String accessToken, Map params) { + String url = "/papi/openapi/api/ebuilder/form/formdata/v2/updateFormData/" + jkbs + "?access_token=" + accessToken; + String result = HttpCilentUtil.doPostJson(host + url, JSONObject.toJSONString(params)); + JSONObject resObj = JSON.parseObject(result); + JSONObject datajson = (JSONObject) resObj.get("datajson"); + boolean status = (boolean) datajson.get("status"); + if (!status) { + log.error("updateFormData jkbs:" + jkbs); + log.error("updateFormData params:" + JSONObject.toJSONString(params)); + log.error("updateFormData result:" + result); + } + return status; + } + + + /** + * 同步建模数据信息(新建) + */ + public static boolean insertFormData(String jkbs, String accessToken, Map params) { + String url = "/papi/openapi/api/ebuilder/form/formdata/v2/saveFormData/" + jkbs + "?access_token=" + accessToken; + String result = HttpCilentUtil.doPostJson(host + url, JSONObject.toJSONString(params)); + JSONObject resObj = JSON.parseObject(result); + JSONObject datajson = (JSONObject) resObj.get("datajson"); + boolean status = (boolean) datajson.get("status"); + if (!status) { + log.error("saveFormData jkbs:" + jkbs); + log.error("saveFormData params:" + JSONObject.toJSONString(params)); + log.error("saveFormData result:" + result); + } + return status; + } + + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/AttendanceReportService.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/AttendanceReportService.java new file mode 100644 index 0000000..7e769a7 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/AttendanceReportService.java @@ -0,0 +1,16 @@ +package com.weaver.seconddev.jcl.organization.service; + +import com.weaver.seconddev.jcl.organization.entity.hldz.Person; + +import java.util.List; +import java.util.Map; + +public interface AttendanceReportService { + + List getAttendanceReportInfo(String yearMonth, String department, String userName, String jobNum); + + Map saveEBInfo(String yearMonth, String department, String userName, String jobNum); + + Map getEmployeePreparationInfo(String department, String year, String month); + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/AttendanceReportServiceImpl.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/AttendanceReportServiceImpl.java new file mode 100644 index 0000000..7379961 --- /dev/null +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/AttendanceReportServiceImpl.java @@ -0,0 +1,1690 @@ +package com.weaver.seconddev.jcl.organization.service.impl; + +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.weaver.common.distribution.genid.IdGenerator; +import com.weaver.seconddev.jcl.organization.entity.hldz.*; +import com.weaver.seconddev.jcl.organization.service.AttendanceReportService; +import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +@Service +public class AttendanceReportServiceImpl implements AttendanceReportService { + + private static final Logger log = LoggerFactory.getLogger(AttendanceReportServiceImpl.class); + private static final ObjectMapper mapper = new ObjectMapper(); + private List StandardOvertimeList = new ArrayList<>(); + private Map dynamicLeaveMap = new HashMap<>(); + + @Autowired + private DatabaseUtils databaseUtils; + + @Override + public List getAttendanceReportInfo(String yearMonth, String department, String userName, String jobNum) { + /** + * 这里弄一个最终返回结果集 + */ + List mergedList = new ArrayList<>(); + //1.查询人员部门工号姓名总排班等 + List employeeInfo = getPersonInfo(yearMonth,department, userName, jobNum); + log.error("getAttendanceReportInfo.employeeInfo:{}", employeeInfo); + //人员信息不为空则做后续筛选 + if(CollectionUtils.isNotEmpty(employeeInfo)){ + //1.1.实际出勤天数 + Map workLengthDay = getWorkLengthDay(yearMonth); + log.error("getAttendanceReportInfo.workLengthDay:{}", workLengthDay); + //2.查询人员对应的各个假期类型余额 + List vacationBalanceInfo = getVacationBalanceInfo(); + log.error("getAttendanceReportInfo.vacationBalanceInfo:{}", vacationBalanceInfo); + //整合各假期类型余额到人员信息中 + Map balanceMap = new HashMap<>(); + // 核心操作:将listb转为Map<人员ID, VacationBalance对象> + if(CollectionUtils.isNotEmpty(vacationBalanceInfo)){ + balanceMap = vacationBalanceInfo.stream() + .collect(Collectors.toMap( + VacationBalance::getId, // Key: 人员ID + vac -> vac, // Value: 整个对象 + (oldVal, newVal) -> oldVal // 冲突解决(保留旧值) + )); + log.error("getAttendanceReportInfo.balanceMap:{}", balanceMap); + } + //3.查询辅助表信息 + List auxiliaryInfo = getAttendanceAuxiliaryInfo(yearMonth); + Map auxiliaryMap = new HashMap<>(); + if(CollectionUtils.isNotEmpty(auxiliaryInfo)){ + auxiliaryMap = auxiliaryInfo.stream() + .collect(Collectors.toMap( + Auxiliary::getRyxm, // Key: 人员ID + vac -> vac, // Value: 整个对象 + (oldVal, newVal) -> oldVal // 冲突解决(保留旧值) + )); + } + log.error("getAttendanceReportInfo.auxiliaryMap:{}", auxiliaryMap); + //4.查询系统标准加班小时数:WORK:工作日,PLAYDAY:休息日,HOLIDAY:节假日(注:取系统中本月加班关联调休+本月不关联调休 不关联调休暂时没有) + List standardOvertimeHours = getStandardOvertimeHours(yearMonth); + Map StandardOvertimeMaps = new HashMap<>(); + if(CollectionUtils.isNotEmpty(standardOvertimeHours)){ + StandardOvertimeMaps = standardOvertimeHours.stream() + .collect(Collectors.toMap( + StandardOvertime::getId, // Key: 人员ID + vac -> vac, // Value: 整个对象 + (oldVal, newVal) -> oldVal // 冲突解决(保留旧值) + )); + log.error("getAttendanceReportInfo.StandardOvertimeMaps:{}", StandardOvertimeMaps); + } + //5.员工原始打卡数据集合 + List records =getEmployeeTimecardInfo(yearMonth); // 假设已有数据 + log.error("getAttendanceReportInfo.records:{}", records); + // 统计结果容器 + Map midShiftCount = new HashMap<>(); + Map nightShiftCount = new HashMap<>(); + //统计中班数(加班)/夜班数(加班) + // 统计结果容器 + Map midOvertime = new HashMap<>(); + Map nightOvertime = new HashMap<>(); + if(CollectionUtils.isNotEmpty(records)){ + // 按人员和日期分组 + Map>> grouped = records.stream() + .filter(r -> r.getAddTime() != null) // 显式过滤空值 + .collect(Collectors.groupingBy( + AttendanceRecord::getPersonId, + Collectors.groupingBy(r -> getSafeLocalDate(r.getAddTime())) + )); + log.error("getAttendanceReportInfo.grouped:{}", grouped); + grouped.forEach((personId, dateMap) -> { + dateMap.forEach((date, dailyRecords) -> { + // 排序获取上下班卡 + List sorted = dailyRecords.stream() + .sorted(Comparator.comparing(AttendanceRecord::getAddTime)) + .collect(Collectors.toList()); + + if(sorted.size() < 2) return; + + LocalDateTime inTime = sorted.get(0).getAddTime(); + LocalDateTime outTime = sorted.get(sorted.size()-1).getAddTime(); + + // 中班判断逻辑 + if(isMidShift(inTime, outTime)) { + midShiftCount.put(personId, midShiftCount.getOrDefault(personId, 0)+1); + } + + // 夜班判断逻辑 + if(isNightShift(inTime, outTime)) { + nightShiftCount.put(personId, nightShiftCount.getOrDefault(personId, 0)+1); + } + }); + }); + + grouped.forEach((personId, dateMap) -> { + dateMap.forEach((date, dailyRecords) -> { + // 排序获取上下班卡 + List sorted = dailyRecords.stream() + .sorted(Comparator.comparing(AttendanceRecord::getAddTime)) + .collect(Collectors.toList()); + + if(sorted.size() < 2) return; + + LocalDateTime inOverTime = sorted.get(0).getAddTime(); + LocalDateTime outOverTime = sorted.get(sorted.size()-1).getAddTime(); + + // 场景1:白班加班到22点后 + if(isDayShift(inOverTime) && outOverTime.isAfter(date.atTime(22,0))) { + midOvertime.merge(personId, 1, Integer::sum); + } + + // 场景2:夜班22点前上班 + if(isNightShiftOver(inOverTime) && inOverTime.isBefore(date.atTime(22,0))) { + midOvertime.merge(personId, 1, Integer::sum); + } + + // 场景3:中班加班到3点后 + if(isMidShiftOver(inOverTime) && outOverTime.isAfter(date.plusDays(1).atTime(3,0))) { + nightOvertime.merge(personId, 1, Integer::sum); + } + + // 场景4:夜班加班超过23点 + if(isNightShiftOver(inOverTime) && outOverTime.isAfter(date.atTime(23,0))) { + nightOvertime.merge(personId, 1, Integer::sum); + } + }); + }); + } + log.error("getAttendanceReportInfo.midShiftCount:{}", midShiftCount); + log.error("getAttendanceReportInfo.nightShiftCount:{}", nightShiftCount); + + log.error("getAttendanceReportInfo.midOvertime:{}", midOvertime); + log.error("getAttendanceReportInfo.nightOvertime:{}", nightOvertime); + //统计本月休假时长:年休假+哺乳+换休假+孕妇工间休息 + Map> leaveDurationThisMonth = leaveDurationThisMonth(yearMonth); + log.error("getAttendanceReportInfo.leaveDurationThisMonth:{}", leaveDurationThisMonth); + //应出勤和实际出勤 + Map> attendanceDuration = getAttendanceDuration(yearMonth); + log.error("getAttendanceReportInfo.attendanceDuration:{}", attendanceDuration); + //查询矿工天数 + Map> minerDays = getMinerDays(yearMonth); + log.error("getAttendanceReportInfo.minerDays:{}", minerDays); + //计算本月丧+婚+探亲+育儿假+陪产假+护理假合计 + Map> appeal_length_day_Map = leaveDurationMoreThisMonth(yearMonth); + log.error("getAttendanceReportInfo.appeal_length_day_Map:{}", appeal_length_day_Map); + // 合并操作 + Map finalStandardOvertimeMaps = StandardOvertimeMaps; + Map finalAuxiliaryMap = auxiliaryMap; + Map finalBalanceMap = balanceMap; + /** + * 获取加班余额兑换数 + */ + Map overtimeExchangeRate = getOvertimeExchangeRate(yearMonth); + /** + * 这里整合本月加班换休假 + */ + mergedList = employeeInfo.stream() + .peek(person -> { + // 1. 过滤id为空的员工,避免空指针 + if (person == null || person.getId() == null) { + return; + } + /** + * 先整合实际出勤天数 + */ + // 2. 根据id获取实际出勤天数(无对应值则为0.0) + double workLengthDays = workLengthDay.getOrDefault(person.getId(), 0.0); + // 3. 转换为String类型(保留2位小数,符合业务展示习惯) + String workLengthDaysStr = String.format("%.2f", workLengthDays); + // 4. 去除末尾的.00(可选,根据业务需求调整) + if (workLengthDaysStr.endsWith(".00")) { + workLengthDaysStr = workLengthDaysStr.replace(".00", ""); + } + // 5. 赋值给workLengthDay字段 + person.setWorkLengthDay(workLengthDaysStr); + /** + * 申请的非本月加班换休假 + */ + // 2. 根据id获取换休假天数(无对应值则为0.0) + double leaveDays = dynamicLeaveMap.getOrDefault(person.getId(), 0.0); + // 3. 转换为String类型(保留2位小数,符合业务展示习惯) + String leaveDaysStr = String.format("%.2f", leaveDays); + // 4. 去除末尾的.00(可选,根据业务需求调整) + if (leaveDaysStr.endsWith(".00")) { + leaveDaysStr = leaveDaysStr.replace(".00", ""); + } + // 5. 赋值给compensatoryLeave字段 + person.setCompensatoryLeave(leaveDaysStr); + + VacationBalance balance = new VacationBalance(); + if(!finalBalanceMap.isEmpty()){ + balance = finalBalanceMap.get(person.getId()); + } + if (balance != null) { + person.setPaidAnnualLeave(Optional.ofNullable(balance.getPaidAnnualLeave()).orElse("0"));//带薪年休假 + person.setNursingLeave(Optional.ofNullable(balance.getNursingLeave()).orElse("0"));//哺乳假 + double paid = Double.parseDouble(Optional.ofNullable(balance.getPaidAnnualLeave()).orElse("0")); + double nursing = Double.parseDouble(Optional.ofNullable(balance.getNursingLeave()).orElse("0")); + //person.setPaidAnnualAndNursingLeave(String.valueOf(paid + nursing)); + person.setMaternityLeave(Optional.ofNullable(balance.getMaternityLeave()).orElse("0"));//产假 + person.setMarriageLeave(Optional.ofNullable(balance.getMarriageLeave()).orElse("0"));//婚嫁 + person.setFamilyVisitLeave(Optional.ofNullable(balance.getFamilyVisitLeave()).orElse("0"));//探亲假(父母) + person.setFamilyVisitLeaveSpouse(Optional.ofNullable(balance.getFamilyVisitLeaveSpouse()).orElse("0"));//探亲假(配偶) + person.setBereavementLeave(Optional.ofNullable(balance.getBereavementLeave()).orElse("0"));//丧假 + person.setPersonalLeave(Optional.ofNullable(balance.getPersonalLeave()).orElse("0"));//事假 + person.setCommonSickLeave(Optional.ofNullable(balance.getCommonSickLeave()).orElse("0"));//普通病假 + person.setHospitalSickLeave(Optional.ofNullable(balance.getHospitalSickLeave()).orElse("0"));//住院病假 + person.setOfficialLeave(Optional.ofNullable(balance.getOfficialLeave()).orElse("0"));//因工休假 + person.setWorkInjuryLeave(Optional.ofNullable(balance.getWorkInjuryLeave()).orElse("0"));//工伤假 + person.setExamLeave(Optional.ofNullable(balance.getExamLeave()).orElse("0"));//考试假 + + double careLeave = Double.parseDouble(Optional.ofNullable(balance.getCareLeave()).orElse("0")); + double paternityLeave = Double.parseDouble(Optional.ofNullable(balance.getPaternityLeave()).orElse("0")); + double parentalLeave = Double.parseDouble(Optional.ofNullable(balance.getParentalLeave()).orElse("0")); + person.setCareLeave(String.valueOf(careLeave + paternityLeave + parentalLeave)); + person.setBusinessTrip(Optional.ofNullable(balance.getBusinessTrip()).orElse("0"));//公出 + //person.setCompensatoryLeave(Optional.ofNullable(balance.getCompensatoryLeave()).orElse("0"));//加班换休(逻辑修改了:申请的非本月加班换休假 ) + person.setWomanresting(Optional.ofNullable(balance.getWomanresting()).orElse("0"));//孕妇工间休息 + person.setOvertimeForCompensatoryleave(Optional.ofNullable(balance.getOvertimeForCompensatoryleave()).orElse("0"));//加班换休技能职 + + } + Auxiliary auxiliary = new Auxiliary(); + if(!finalAuxiliaryMap.isEmpty()){ + auxiliary = finalAuxiliaryMap.get(person.getId()); + } + if(auxiliary !=null){ + person.setCfbt(Optional.ofNullable(auxiliary.getCfbt()).orElse("0"));//厂房补贴 + person.setWcf(Optional.ofNullable(auxiliary.getWcbt()).orElse("0"));//误餐补贴 + person.setBmnbt(Optional.ofNullable(auxiliary.getBmnbt()).orElse("0"));//部门被补贴 + person.setZhts(Optional.ofNullable(auxiliary.getZhts()).orElse("0"));//在华天数 + person.setHjbt1(Optional.ofNullable(auxiliary.getHjbt1()).orElse("0"));//环境补贴1 + person.setHjbt2(Optional.ofNullable(auxiliary.getHjbt2()).orElse("0"));//环境补贴2 + person.setHjbt3(Optional.ofNullable(auxiliary.getHjbt3()).orElse("0"));//环境补贴3 + person.setHjbt4(Optional.ofNullable(auxiliary.getHjbt4()).orElse("0"));//环境补贴4 + person.setHjbt5(Optional.ofNullable(auxiliary.getHjbt5()).orElse("0"));//环境补贴5 + }else { + person.setCfbt("0");//厂房补贴 + person.setWcf("0");//搬运费 + person.setBmnbt("0");//部门被补贴 + person.setZhts("0");//在华天数 + person.setHjbt1("0");//环境补贴1 + person.setHjbt2("0");//环境补贴2 + person.setHjbt3("0");//环境补贴3 + person.setHjbt4("0");//环境补贴4 + person.setHjbt5("0");//环境补贴5 + } + StandardOvertime standardOvertime = new StandardOvertime(); + if(!finalStandardOvertimeMaps.isEmpty()){ + standardOvertime = finalStandardOvertimeMaps.get(person.getId()); + } + if(standardOvertime !=null){ + if("WORK".equals(standardOvertime.getDay_type())){ + person.setWorkOverTime(Optional.ofNullable(standardOvertime.getHour()).orElse("0")); + }else if("PLAYDAY".equals(standardOvertime.getDay_type())){ + person.setPlayDayOverTime(Optional.ofNullable(standardOvertime.getHour()).orElse("0")); + }else if("HOLIDAY".equals(standardOvertime.getDay_type())){ + person.setHolidayOverTime(Optional.ofNullable(standardOvertime.getHour()).orElse("0")); + }else { + person.setWorkOverTime("0"); + person.setPlayDayOverTime("0"); + person.setHolidayOverTime("0"); + } + }else{ + person.setWorkOverTime("0"); + person.setPlayDayOverTime("0"); + person.setHolidayOverTime("0"); + } + //中班/夜班次数 + person.setMidShifts(Optional.of(midShiftCount) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0) + .toString()); + person.setNightShifts(Optional.of(nightShiftCount) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0) + .toString()); + //中班/夜班(加班)次数 + person.setMidShiftsOver(Optional.of(midOvertime) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0) + .toString()); + person.setNightShiftsOver(Optional.of(nightOvertime) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0) + .toString()); + //中班/夜班次数(总数) + person.setMidShiftsAll(String.valueOf(Optional.of(midShiftCount) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0) + Optional.of(midOvertime) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0))); + person.setNightShiftsAll(String.valueOf(Optional.of(nightShiftCount) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0) + Optional.of(nightOvertime) + .map(map -> map.getOrDefault(person.getId(), 0)) + .orElse(0))); + + //计算得出:休日加班小时数(计算后)修正后逻辑:实际出勤天数-应出勤天数(日历排班)>=0,则为本值,否则为0. + double playDayOverTimeCal = subtractStringNumbers(person.getWorkLengthDay(), person.getTotalShifts()); + double v = playDayOverTimeCal >= 0 ? playDayOverTimeCal*8 : 0.0; + person.setPlayDayOverTimeCal(String.format("%.2f", v)); + /** + *平日加班小时数(计算后) + * + * 若休日加班小时数(计算后)>=0, + * 则为平日加班小时数(系统标准)。 + * 若休日加班小时数(计算后)<0, + * 则为实际上班天数(实际工作时长数(取出勤报表中-出勤汇总-出勤工时) + * +产生的本月加班换休假+申请的非本月加班换休假+年休假+哺乳+孕妇工间休息(对应实出勤字段)) -应出勤天数>=0(结果*8转为小时)为本值,小于0为0) + */ + if(playDayOverTimeCal>=0){ + person.setWorkOverTimeCal(person.getWorkOverTime()); + }else { + person.setWorkOverTimeCal(String.format("%.2f", v)); + } + +// String period_length_days = "0"; +// String actual_work_length_day = "0"; +// String playDayOverTime = "0"; +// String total_leave_days = "0"; +// Map map = new HashMap<>(); +// if(!attendanceDuration.isEmpty()){ +// map = attendanceDuration.get(person.getId()); +// } +// //应出勤/实际出勤 +// if(null!=map&&!map.isEmpty()){ +// period_length_days = map.get("period_length_day"); +// actual_work_length_day = map.get("actual_work_length_day"); +// } +// //假期累计 +// Map map2 = new HashMap<>(); +// if(!leaveDurationThisMonth.isEmpty()){ +// map2 = leaveDurationThisMonth.get(person.getId()); +// } +// if(null!=map2&&!map2.isEmpty()){ +// total_leave_days = map2.get("total_leave_days"); +// } +// //休息日加班 +// if(standardOvertime !=null){ +// if("PLAYDAY".equals(standardOvertime.getDay_type())){ +// playDayOverTime = standardOvertime.getDay(); +// } +// } +// //计算实际上班 +// BigDecimal multiply = new BigDecimal(0); +// BigDecimal multiply1 = new BigDecimal(0); +// BigDecimal bigDecimal1 = actual_work_length_day.trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(actual_work_length_day.trim()); +// BigDecimal bigDecimal2 = playDayOverTime.trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(playDayOverTime.trim()); +// BigDecimal bigDecimal3 = total_leave_days.trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(total_leave_days.trim()); +// BigDecimal bigDecimal4 = period_length_days.trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(period_length_days.trim()); +// BigDecimal subtract = bigDecimal1.add(bigDecimal2).add(bigDecimal3).subtract(bigDecimal4); +// multiply = subtract.multiply(new BigDecimal(24)); +// log.error("getAttendanceReportInfo.personid:{}", person.getId()); +// log.error("getAttendanceReportInfo.multiply:{}", multiply); +// log.error("getAttendanceReportInfo.bigDecimal1:{}", bigDecimal1); +// log.error("getAttendanceReportInfo.bigDecimal2:{}", bigDecimal2); +// log.error("getAttendanceReportInfo.bigDecimal3:{}", bigDecimal3); +// log.error("getAttendanceReportInfo.bigDecimal4:{}", bigDecimal4); +// log.error("getAttendanceReportInfo.subtract:{}", subtract); +// //设置:休日加班小时数(计算后) +// if(multiply.compareTo(BigDecimal.ZERO) > 0){ +// person.setPlayDayOverTimeCal(String.valueOf(subtract)); +// //这里设置:平日加班小时数(计算后)为:为平日加班小时数(系统标准) +// if(null!=standardOvertime&&"WORK".equals(standardOvertime.getDay_type())){ +// person.setWorkOverTimeCal(standardOvertime.getHour()); +// } +// }else { +// person.setPlayDayOverTimeCal("0"); +// //计算平日加班小时数(计算后)另一种设置场景 +// String workOverTime = "0"; +// if(standardOvertime !=null){ +// if("WORK".equals(standardOvertime.getDay_type())){ +// workOverTime = standardOvertime.getDay(); +// } +// } +// BigDecimal bigDecimal5 = workOverTime.trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(workOverTime.trim()); +// multiply1 = subtract.add(bigDecimal5).multiply(new BigDecimal(24)); +// if(multiply1.compareTo(BigDecimal.ZERO) > 0){ +// //设置:平日加班小时数(计算后) +// person.setWorkOverTimeCal(String.valueOf(multiply1)); +// }else { +// person.setWorkOverTimeCal("0"); +// } +// } + //合计加班时长(计算后) + BigDecimal hour = new BigDecimal(0); + if(null!=standardOvertime){ + if("HOLIDAY".equals(standardOvertime.getDay_type())){ + hour = standardOvertime.getHour().trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(standardOvertime.getHour().trim()); + } + } + //平时加班/工日加班计算后 + BigDecimal multiply = new BigDecimal(person.getWorkOverTimeCal()); + BigDecimal multiply1 = new BigDecimal(person.getPlayDayOverTimeCal()); + BigDecimal add = multiply.add(multiply1).add(hour).divide(new BigDecimal(2),5, RoundingMode.HALF_UP); + person.setStandardOvertimeAll(String.valueOf(add.compareTo(BigDecimal.ZERO)>0?add:0)); + log.error("getAttendanceReportInfo.multiply000:{}", multiply); + log.error("getAttendanceReportInfo.multiply111:{}", multiply1); + log.error("getAttendanceReportInfo.hour111:{}", hour); + //设置矿工天数 + String miner = "0"; + if(!minerDays.isEmpty()){ + miner = minerDays.get(person.getId()).get("miner"); + } + person.setMiner(miner); + /** + * 福利假失效小时数 + */ + + /** + * 加班余额兑换数 + */ + // 2. 根据id获取实际出勤天数(无对应值则为0.0) + double overtimeExchangeRates = overtimeExchangeRate.getOrDefault(person.getId(), 0.0); + // 5. 赋值给overtimeExchangeRate字段 + person.setOvertimeExchangeRate(overtimeExchangeRates); +// //福利假结算天数(取消) +// //1.实际出勤 +// //actual_work_length_day:bigDecimal1 +// //2.加班天数 +// BigDecimal addDays = multiply.add(multiply1).add(hour.divide(new BigDecimal(24),5, RoundingMode.HALF_UP)); +// log.error("getAttendanceReportInfo.addDays:{}", addDays); +// //3.假期累计 +// //total_leave_days:bigDecimal3 +// //4.本月工作日 +// //bigDecimal4 +// String leaveDays = "0"; +// if(!appeal_length_day_Map.isEmpty()){ +// leaveDays = null==appeal_length_day_Map.get(person.getId()).get("total_leave_days")?"0":appeal_length_day_Map.get(person.getId()).get("total_leave_days"); +// } +// log.error("getAttendanceReportInfo.leaveDays:{}", leaveDays); +// if(bigDecimal1.add(addDays).add(bigDecimal3).compareTo(bigDecimal4)>=0){ +// //设置福利假期天数为:丧+婚+探亲+育儿假+陪产假+护理假 +// log.error("getAttendanceReportInfo.leaveDays22222:{}", leaveDays); +// person.setWelfareLeaveDays(leaveDays); +// }else{ +// //减去缺勤天数,剩余的设置为福利假期 +// // 计算假期 +// BigDecimal decimal = leaveDays.trim().isEmpty() ? BigDecimal.ZERO : new BigDecimal(leaveDays.trim()); +// log.error("getAttendanceReportInfo.leaveDays33333:{}", decimal); +// BigDecimal subtract1 = decimal.subtract((bigDecimal4.subtract(bigDecimal1))); +// log.error("getAttendanceReportInfo.leaveDays44444:{}", subtract1); +// person.setWelfareLeaveDays(String.valueOf(subtract1.compareTo(BigDecimal.ZERO)>0?subtract1:0)); +// } +// log.error("getAttendanceReportInfo.person888:{}", person); + }) + .collect(Collectors.toList()); + log.error("getAttendanceReportInfo.mergedList:{}", mergedList); + } + return mergedList; + } + + /** + * 核心方法:将两个String类型数值转为double并执行减法运算(num1 - num2) + * @param num1Str 被减数(String类型,如"5.23") + * @param num2Str 减数(String类型,如"22.5") + * @return 计算结果(double) + */ + public static double subtractStringNumbers(String num1Str, String num2Str) { + // 1. 安全转换String为double(空值/非数字默认0.0) + double num1 = parseStringToDouble(num1Str, 0.0); + double num2 = parseStringToDouble(num2Str, 0.0); + + // 2. 执行减法计算 + return num1 - num2; + } + private static double parseStringToDouble(String str, double defaultValue) { + if (str == null || str.trim().isEmpty()) { + return defaultValue; + } + try { + return Double.parseDouble(str.trim()); + } catch (NumberFormatException e) { + // 非数字字符串返回默认值 + return defaultValue; + } + } + + // 方法1:通过年月字符串计算(推荐) + public static int getDaysInMonth(String yearMonth) { + // 补全日期格式为"yyyy-MM-dd" + LocalDate date = LocalDate.parse(yearMonth + "-01", + DateTimeFormatter.ofPattern("yyyy-MM-dd")); + return date.lengthOfMonth(); + } + + public static LocalDate getSafeLocalDate(LocalDateTime dateTime) { + return Optional.ofNullable(dateTime) + .map(LocalDateTime::toLocalDate) + .orElse(LocalDate.MIN); // 或自定义默认日期 + } + + /** + * 计算本月丧+婚+探亲+育儿假+陪产假+护理假合计 + * @return + */ + private Map> leaveDurationMoreThisMonth(String yearMonth) { + String sql = " SELECT\n" + + " ATTEND_DATE,\n" + + " employee,\n" + + " SUM(appeal_length_day) AS total_leave_days\n" + + " FROM \n" + + " attend_status_detail_link\n" + + " WHERE \n" + + " APPEAL_TYPE = 'leave'\n" + + " AND delete_type = 0\n" + + " AND VACATION_TYPE IN (select id from attend_vacation_setting where delete_type=0 and name in('丧假','婚假','育儿假','陪产假','护理假'))\n" + + " AND DATE_FORMAT(ATTEND_DATE, '%Y-%m') = '"+yearMonth+"'\n" + + " GROUP BY \n" + + " EMPLOYEE "; + log.error("leaveDurationMoreThisMonth.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("leaveDurationMoreThisMonth.recordList:{}", recordList); + Map> recordMap = new HashMap<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + // 1.上述查询的本月休假时长 + recordMap = recordList.stream() + .collect(Collectors.toMap( + // 键提取:处理id为null的情况 + m -> Objects.toString(m.get("employee"), "unknown_id"), + // 值转换:增强null值处理 + m -> m.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> { + Object value = e.getValue(); + // 自定义null处理逻辑(此处保留为"NULL_VALUE",可根据需要修改) + return value == null ? "0" : value.toString(); + } + )), + + // 合并策略:处理重复键 + (oldVal, newVal) -> { + // 合并时保留最新值,并打印冲突信息 + //System.out.println("重复键合并: " + oldVal.get("id") + " -> " + newVal.get("id")); + return newVal; + } + )); + } + return recordMap; + } + + /** + * 计算本月休假天数合计(本月年休假+本月哺乳+本月孕妇工间休息) + * @return + */ + private Map> leaveDurationThisMonth(String yearMonth) { + String sql = "SELECT \n" + + " ATTEND_DATE,\n" + + " EMPLOYEE,\n" + + " SUM(appeal_length_day) AS total_leave_days\n" + + " FROM \n" + + " attend_status_detail_link\n" + + " WHERE \n" + + " APPEAL_TYPE = 'leave'\n" + + " AND delete_type = 0\n" + + " AND VACATION_TYPE IN (1196642326248554497, 7045514828338071524, 7045514828343471545,1177293262259511296)\n" + + " AND DATE_FORMAT(ATTEND_DATE, '%Y-%m') = '"+yearMonth+"'\n" + + " GROUP BY \n" + + " EMPLOYEE "; + log.error("leaveDurationThisMonth.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("leaveDurationThisMonth.recordList:{}", recordList); + Map> recordMap = new HashMap<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + // 1.上述查询的本月休假时长 + recordMap = recordList.stream() + .collect(Collectors.toMap( + // 键提取:处理id为null的情况 + m -> Objects.toString(m.get("employee"), "unknown_id"), + // 值转换:增强null值处理 + m -> m.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> { + Object value = e.getValue(); + // 自定义null处理逻辑(此处保留为"NULL_VALUE",可根据需要修改) + return value == null ? "0" : value.toString(); + } + )), + + // 合并策略:处理重复键 + (oldVal, newVal) -> { + // 合并时保留最新值,并打印冲突信息 + //System.out.println("重复键合并: " + oldVal.get("id") + " -> " + newVal.get("id")); + return newVal; + } + )); + } + return recordMap; + } + /** + * 查询矿工天数 + * @return + */ + private Map> getMinerDays(String yearMonth){ + //2.查询应出勤和实际出勤 + String str = " SELECT\n" + + " ASD.employee,\n" + + " DATE_FORMAT(ASD.ATTEND_DATE, '%Y-%m') as ATTEND_DATE,\n" + + " SUM(CASE DAY_TYPE WHEN 'WORK' THEN AAD.ABSENTEEISM_LENGTH_DAY ELSE 0 END) AS miner \n" + + " from ATTEND_STATUS_DETAIL ASD \n" + + " LEFT JOIN attend_absence_detail AAD ON ASD.ID = AAD.ID and ASD.delete_type=AAD.delete_type\n" + + " where DATE_FORMAT(ASD.ATTEND_DATE, '%Y-%m') = '"+yearMonth+"' and ASD.delete_type = 0\n" + + " GROUP BY ASD.employee "; + log.error("getMinerDays.sql:{}", str); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", str); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getMinerDays.recordList:{}", recordList); + Map> recordMap = new HashMap<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + recordMap = recordList.stream() + .collect(Collectors.toMap( + // 键提取:处理id为null的情况 + m -> Objects.toString(m.get("employee"), "unknown_id"), + // 值转换:增强null值处理 + m -> m.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> { + Object value = e.getValue(); + // 自定义null处理逻辑(此处保留为"NULL_VALUE",可根据需要修改) + return value == null ? "0" : value.toString(); + } + )), + + // 合并策略:处理重复键 + (oldVal, newVal) -> { + // 合并时保留最新值,并打印冲突信息 + return newVal; + } + )); + } + return recordMap; + } + /** + * 查询应出勤和实际出勤 + * @return + */ + private Map> getAttendanceDuration(String yearMonth){ + //2.查询应出勤和实际出勤 + String str = " SELECT \n" + + " employee,\n" + + " SUM(PERIOD_LENGTH_DAY) AS PERIOD_LENGTH_DAY,\n" + + " SUM(ACTUAL_WORK_LENGTH_DAY) AS ACTUAL_WORK_LENGTH_DAY\n" + + " FROM \n" + + " ATTEND_STATUS_DETAIL\n" + + " WHERE \n" + + " DATE_FORMAT(ATTEND_DATE, '%Y-%m') = '"+yearMonth+"'\n" + + " AND delete_type = 0\n" + + " GROUP BY \n" + + " employee "; + log.error("leaveDurationThisMonth.sql:{}", str); + Map rs2 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", str); + List> recordList2 = databaseUtils.getDataSourceList(rs2); + log.error("leaveDurationThisMonth.recordList2:{}", recordList2); + Map> recordMap2 = new HashMap<>(); + if(CollectionUtils.isNotEmpty(recordList2)){ + recordMap2 = recordList2.stream() + .collect(Collectors.toMap( + // 键提取:处理id为null的情况 + m -> Objects.toString(m.get("employee"), "unknown_id"), + // 值转换:增强null值处理 + m -> m.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> { + Object value = e.getValue(); + // 自定义null处理逻辑(此处保留为"NULL_VALUE",可根据需要修改) + return value == null ? "0" : value.toString(); + } + )), + + // 合并策略:处理重复键 + (oldVal, newVal) -> { + // 合并时保留最新值,并打印冲突信息 + //System.out.println("重复键合并: " + oldVal.get("id") + " -> " + newVal.get("id")); + return newVal; + } + )); + } + return recordMap2; + } + + // 白班判断(8:00-17:00) + private static boolean isDayShift(LocalDateTime time) { + LocalTime t = time.toLocalTime(); + return !time.toLocalDate().equals(LocalDate.now().plusDays(1)) + && t.isAfter(LocalTime.of(8,0)) + && t.isBefore(LocalTime.of(17,0)); + } + + // 夜班判断(01:00-08:00等) + private static boolean isNightShiftOver(LocalDateTime time) { + LocalTime t = time.toLocalTime(); + return t.isAfter(LocalTime.MIDNIGHT) && t.isBefore(LocalTime.of(1,0)) + || t.isAfter(LocalTime.of(0,55)) && t.isBefore(LocalTime.of(7,55)) + || t.isAfter(LocalTime.of(1,0)) && t.isBefore(LocalTime.of(8,0)); + } + + // 中班判断(17:00-01:00等) + private static boolean isMidShiftOver(LocalDateTime time) { + LocalTime t = time.toLocalTime(); + return t.isAfter(LocalTime.of(16,0)) && t.isBefore(LocalTime.of(17,0)) + || t.isAfter(LocalTime.of(16,55)) && t.isBefore(LocalTime.MIDNIGHT) + || t.isAfter(LocalTime.MIDNIGHT) && t.isBefore(LocalTime.of(1,0)); + } + + + /** + * 中班判断逻辑实现 + */ + private boolean isMidShift(LocalDateTime in, LocalDateTime out) { + // 时间段定义(简化版) + LocalTime inTime = in.toLocalTime(); + LocalTime outTime = out.toLocalTime(); + + // 下班时间必须≥22:00 + if(out.toLocalDate().equals(in.toLocalDate()) && outTime.isBefore(LocalTime.of(22,0))) + return false; + + // 中班时间段判断 + return (inTime.isAfter(LocalTime.of(16,0)) && inTime.isBefore(LocalTime.of(17,0))) || + (inTime.isAfter(LocalTime.of(16,55)) && inTime.isBefore(LocalTime.of(0,0))) || + (inTime.isAfter(LocalTime.of(0,0)) && inTime.isBefore(LocalTime.of(1,0))); + } + + /** + * 夜班判断逻辑实现 + */ + private boolean isNightShift(LocalDateTime in, LocalDateTime out) { + // 时间段定义(简化版) + LocalTime inTime = in.toLocalTime(); + + // 夜班时间段判断 + boolean inRange = + (inTime.isAfter(LocalTime.of(0,0)) && inTime.isBefore(LocalTime.of(1,0))) || + (inTime.isAfter(LocalTime.of(0,55)) && inTime.isBefore(LocalTime.of(7,55))) || + (inTime.isAfter(LocalTime.of(1,0)) && inTime.isBefore(LocalTime.of(8,0))); + + // 时长判断 + long hours = ChronoUnit.MINUTES.between(in, out); + return inRange && hours >= 120; // 120分钟=2小时 + } + /** + * 查询员工总班次信息 + * @param yearMonth + * @param department + * @param userName + * @param jobNum + * @return + */ + private List getPersonInfo(String yearMonth,String department, String userName, String jobNum){ + String sql = " SELECT \n" + + " count(a.RANGE_ID) AS zpb,\n" + + " a.RANGE_ID,\n" + + " a.ATTEND_DATE,\n" + + " c.id AS employee,\n" + + " c.username,\n" + + " c.job_num,\n" + + " d.id AS did,\n" + + " d.name AS departmentname\n" + + " FROM eteams.employee c\n" + + " JOIN eteams.department d ON d.id = c.department\n" + + " JOIN attend_scheduling a ON a.RANGE_ID = c.id\n" + + " JOIN attend_shift b ON b.id = a.SHIFT_ID\n" + + " where\n" + + " a.DELETE_TYPE = 0 and c.id is not null and c.PERSONNEL_STATUS in(1,2,3,4,5) and a.shift_id !=10000 \n" + + " AND DATE_FORMAT(a.ATTEND_DATE, '%Y-%m') = '"+yearMonth+"' "; + String str = " SELECT \n" + + " count(a.RANGE_ID) AS zpb,\n" + + " a.RANGE_ID,\n" + + " a.ATTEND_DATE,\n" + + " b.target_id AS employee,\n" + + " e.username,\n" + + " e.job_num,\n" + + " d.id AS did,\n" + + " d.name AS departmentname\n" + + " from attend_scheduling a \n" + + " left join attend_config_range b on a.RANGE_ID = b.id\n" + + " left join eteams.employee e on e.id = b.target_id\n" + + " left JOIN eteams.department d ON d.id = e.department\n" + + " left JOIN attend_shift c ON c.id = a.SHIFT_ID\n" + + " where\n" + + " a.DELETE_TYPE = 0 and e.id is not null and e.PERSONNEL_STATUS in(1,2,3,4,5) and a.shift_id !=10000 \n" + + " AND DATE_FORMAT(a.ATTEND_DATE, '%Y-%m') = '"+yearMonth+"' "; + if (StringUtils.isNotBlank(department)) { + String s = splitStr(department); + sql += " and d.id in (" + s + ") "; + str += " and d.id in (" + s + ") "; + } + if (StringUtils.isNotBlank(userName)) { + sql += " and c.username like '%" + userName + "%' "; + str += " and e.username like '%" + userName + "%' "; + } + if (StringUtils.isNotBlank(jobNum)) { + sql += " and c.job_Num like '%" + jobNum + "%' "; + str += " and e.job_Num like '%" + jobNum + "%' "; + } + sql += " group by c.id "; + str += " group by b.target_id "; + //sql +=str; + log.error("getPersonInfo.sql:{}", sql); + log.error("getPersonInfo.str:{}", str); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getPersonInfo.recordList:{}", recordList); + Map rs2 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", str); + List> recordList2 = databaseUtils.getDataSourceList(rs2); + log.error("getPersonInfo.recordList2:{}", recordList2); + /** + * 这里获取当月天数 + */ + int daysInMonth = getDaysInMonth(yearMonth); + /** + * 再查询当月节假日天数(当月天数-节假日天数 = 出勤日天数) + */ + String stt = "select count(DISTINCT DATE_FORMAT(day, '%Y-%m-%d')) as daynum \n" + + "from attend_day where config_id=7046396505926807067 and delete_type =0 and DATE_FORMAT(day, '%Y-%m') = '"+yearMonth+"'"; + Map rs3 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", stt); + List> recordList3 = databaseUtils.getDataSourceList(rs3); + log.error("getPersonInfo.recordList3:{}", recordList3); + /** + * 计算当月工作日 + */ + int totalShifts = Math.max(daysInMonth - recordList3.size(), 0); + log.error("getPersonInfo.totalShifts:{}", totalShifts); + //不为空则转换 + List persons = new ArrayList<>(); + Set existingEmployees = new HashSet<>(); + if(CollectionUtils.isNotEmpty(recordList2)){ + // 核心转换逻辑 + persons = recordList2.stream() + .map(map -> { + Person person = new Person(); + person.setId(getMapValue(map, "employee")); + person.setJobNum(getMapValue(map, "job_num")); + person.setName(getMapValue(map, "username")); + person.setDeptId(getMapValue(map, "did")); + person.setDept(getMapValue(map, "departmentname")); + person.setYearMonth(yearMonth); + person.setTotalShifts(String.valueOf(totalShifts)); + return person; + }) + .peek(person -> existingEmployees.add(person.getId())) // 记录已存在的employee + .collect(Collectors.toList()); + } + // 处理第二个记录列表 + if (CollectionUtils.isNotEmpty(recordList)) { + List additionalPersons = recordList.stream() + .filter(map -> { + String employeeId = getMapValue(map, "employee"); + return !existingEmployees.contains(employeeId); // 过滤已存在的employee + }) + .map(map -> { + Person person = new Person(); + person.setId(getMapValue(map, "employee")); + person.setJobNum(getMapValue(map, "job_num")); + person.setName(getMapValue(map, "username")); + person.setDeptId(getMapValue(map, "did")); + person.setDept(getMapValue(map, "departmentname")); + person.setYearMonth(yearMonth); + person.setTotalShifts(getMapValue(map, "zpb")); + return person; + }) + .collect(Collectors.toList()); + + persons.addAll(additionalPersons); // 合并到主列表 + } + return persons; + } + + /** + * 字符串转化 + */ + private String splitStr(String str){ + // 使用 split 方法将字符串分割为数组 + String[] parts = str.split(","); + // 使用 StringBuilder 构建结果字符串 + StringBuilder result = new StringBuilder(); + for (String part : parts) { + // 在每个部分前后添加单引号 + result.append("'").append(part).append("',"); + } + // 移除最后一个多余的逗号 + if (result.length() > 0) { + result.setLength(result.length() - 1); + } + return result.toString(); + } + + /** + * 查询员工各类型假期余额信息 + * @return + */ + private List getVacationBalanceInfo(){ + String sql = "select c.id as cid,c.username,b.name,a.year,a.current_year,\n" + + "a.base,a.used,a.delete_type\n" + + " from attend_vacation_info_v2 a\n" + + "left join attend_vacation_setting b on a.VACATION = b.id \n" + + "left join eteams.employee c on a.employee = c.id\n" + + "Where a.vacation in(\n" + + "select id from attend_vacation_setting where name in('带薪年休假','哺乳假','婚假','探亲假(父母)','探亲假(配偶)','丧假','事假','普通病假',\n" + + " '住院病假','产假','因公休假','工伤假','考试假','护理假','陪产假','育儿假','公出','加班换休','孕妇工间休息','加班换休-技能职')\n" + + ")\n" + + "and a.CURRENT_YEAR !=0\n" + + " and a.delete_type = 0"; + log.error("getVacationBalanceInfo.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getVacationBalanceInfo.recordList:{}", recordList); + List VacationBalances = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + // 核心转换逻辑 + VacationBalances = recordList.stream() + .map(map -> { + VacationBalance vacationBalance = new VacationBalance(); + vacationBalance.setId(getMapValue(map, "cid")); + vacationBalance.setName(getMapValue(map, "username")); + // 处理假期余额等特殊字段 + String name = getMapValue(map, "name"); + if(name.equals("带薪年休假")) { + vacationBalance.setPaidAnnualLeave(getMapValue(map, "current_year")); + }else if(name.equals("哺乳假")) { + vacationBalance.setNursingLeave(getMapValue(map, "current_year")); + }else if(name.equals("产假")) { + vacationBalance.setMaternityLeave(getMapValue(map, "current_year")); + }else if(name.equals("婚假")) { + vacationBalance.setMarriageLeave(getMapValue(map, "current_year")); + }else if(name.equals("探亲假(父母)")) { + vacationBalance.setFamilyVisitLeave(getMapValue(map, "current_year")); + }else if(name.equals("探亲假(配偶)")) { + vacationBalance.setFamilyVisitLeaveSpouse(getMapValue(map, "current_year")); + }else if(name.equals("丧假")) { + vacationBalance.setBereavementLeave(getMapValue(map, "current_year")); + }else if(name.equals("事假")) { + vacationBalance.setPersonalLeave(getMapValue(map, "current_year")); + }else if(name.equals("普通病假")) { + vacationBalance.setCommonSickLeave(getMapValue(map, "current_year")); + }else if(name.equals("住院病假")) { + vacationBalance.setHospitalSickLeave(getMapValue(map, "current_year")); + }else if(name.equals("因公休假")) { + vacationBalance.setOfficialLeave(getMapValue(map, "current_year")); + }else if(name.equals("工伤假")) { + vacationBalance.setWorkInjuryLeave(getMapValue(map, "current_year")); + }else if(name.equals("考试假")) { + vacationBalance.setExamLeave(getMapValue(map, "current_year")); + }else if(name.equals("护理假")) { + vacationBalance.setCareLeave(getMapValue(map, "current_year")); + }else if(name.equals("陪产假")) { + vacationBalance.setPaternityLeave(getMapValue(map, "current_year")); + }else if(name.equals("育儿假")) { + vacationBalance.setParentalLeave(getMapValue(map, "current_year")); + }else if(name.equals("公出")) { + vacationBalance.setBusinessTrip(getMapValue(map, "current_year")); + }else if(name.equals("加班换休")) { + vacationBalance.setCompensatoryLeave(getMapValue(map, "current_year")); + }else if(name.equals("孕妇工间休息")) { + vacationBalance.setWomanresting(getMapValue(map, "current_year")); + }else if(name.equals("加班换休-技能职")) { + vacationBalance.setOvertimeForCompensatoryleave(getMapValue(map, "current_year")); + } + return vacationBalance; + }) + .collect(Collectors.toList()); + } + return VacationBalances; + } + + + /** + * 查询实际出勤天数 + * @return + */ + private Map getWorkLengthDay (String yearMonth){ + String[] parts = yearMonth.split("-"); + // 转换为整数类型(年份和月份) + int year = Integer.parseInt(parts[0]); + int month = Integer.parseInt(parts[1]); + //1.出勤天数 + String sql = "select employee,sum(WORK_LENGTH_DAY) as worklengthday from attend_status_detail where\n" + + " DATE_FORMAT(ATTEND_DATE, '%Y-%m') = '"+yearMonth+"' and delete_type = 0 GROUP BY employee "; + log.error("getWorkLengthDay.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getWorkLengthDay.recordList:{}", recordList); + //2.本月不关联调休的加班时长:day_type=WORK时,取day值 + List overtimeHours = getStandardOvertimeHours(yearMonth); + log.error("getWorkLengthDay.overtimeHours:{}", overtimeHours); + //3.产生的本月加班换休假(由于跟关联调休假一样且关联调休和不关联调休一样,所以这里*2就行) +// List overtimeHours2 = getStandardOvertimeHours(yearMonth); +// log.error("getWorkLengthDay.overtimeHours2:{}", overtimeHours2); + //4.非本月换休天数(本月申请的非本月加班换休假=本月之前的加班换休小时数之和-之前月份休息之和:和本月使用的换休假对比:1.大于等于直接加上本月使用换休假 2.小于加上之前剩余,这个月的不加) + //4.1.先查询出本月之前的加班换休小时数 + List standardOvertimeHoursPreviousMonth = getStandardOvertimeHoursPreviousMonth(yearMonth); + //4.2.之前月份换休假使用之和 + String sql3 = " select employee,sum(used)/8 as usedDay from attend_vacation_info_detail_v2 WHERE \n" + + " VACATION_TYPE = 7045514828342871535 and year = '"+year+"' and month < '"+month+"' and delete_type=0 and used !=0 GROUP BY employee "; + Map rs3 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql3); + List> recordList3 = databaseUtils.getDataSourceList(rs3); + log.error("getWorkLengthDay.recordList3:{}", recordList3); + String sql2 = " select employee,sum(used)/8 as usedDay from attend_vacation_info_detail_v2 WHERE \n" + + " VACATION_TYPE = 7045514828342871535 and year = '"+year+"' and month = '"+month+"' and delete_type=0 and used !=0 GROUP BY employee "; + Map rs2 = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql2); + List> recordList2 = databaseUtils.getDataSourceList(rs2); + log.error("getWorkLengthDay.recordList2:{}", recordList2); + //5.获取本月年休假+本月哺乳+本月孕妇工间休息 + Map> leaveDurationThisMonth = leaveDurationThisMonth(yearMonth); + /** + * 这里插入一个计算非本月加班换休假方法 + */ + // 调用独立方法计算动态usedDay + dynamicLeaveMap = calculateDynamicOvertimeLeave(standardOvertimeHoursPreviousMonth, recordList3, recordList2); + log.error("getWorkLengthDay.dynamicLeaveMap:{}", dynamicLeaveMap); + + // ========== 核心计算逻辑 ========== + return calculateActualAttendance(recordList, overtimeHours, recordList2, leaveDurationThisMonth, standardOvertimeHoursPreviousMonth, recordList3); + } + + /** + * 单独计算每个员工的非本月加班换休假(动态usedDay值) + * 核心规则: + * 1. 上月剩余加班换休 = 上月加班换休总和(WORK类型) - 上月已用休假总和 + * 2. 若上月剩余 > 当月休息天数 → 动态usedDay = 当月休息天数 + * 3. 若上月剩余 ≤ 当月休息天数 → 动态usedDay = 上月剩余(最小为0) + * + * @param standardOvertimeHoursPreviousMonth 上月加班换休小时数(day_type=WORK的day值) + * @param recordList3 上月已用休假总和(employee + usedDay) + * @param recordList2 当月休息天数(employee + usedDay) + * @return Map<员工编号, 动态usedDay值> + */ + public static Map calculateDynamicOvertimeLeave( + List standardOvertimeHoursPreviousMonth, + List> recordList3, + List> recordList2) { + + // ========== 1. 预处理:转换数据源为以employee为key的Map(空值/类型兼容) ========== + // 1.1 上月加班换休总和(仅WORK类型) + Map previousOvertimeMap = new HashMap<>(); + if (standardOvertimeHoursPreviousMonth != null && !standardOvertimeHoursPreviousMonth.isEmpty()) { + previousOvertimeMap = standardOvertimeHoursPreviousMonth.stream() + .filter(Objects::nonNull) // 过滤null元素 + .filter(ot -> ot.getId() != null) // 过滤员工编号为空 + .filter(ot -> "WORK".equals(ot.getDay_type())) // 仅WORK类型计入 + .collect(Collectors.groupingBy( + StandardOvertime::getId, + Collectors.summingDouble(ot -> parseToDouble(ot.getDay(), 0.0)) // String转Double + )); + } + + // 1.2 上月已用休假总和 + Map previousUsedDayMap = new HashMap<>(); + if (recordList3 != null && !recordList3.isEmpty()) { + previousUsedDayMap = recordList3.stream() + .filter(Objects::nonNull) + .filter(item -> item.get("employee") != null) + .collect(Collectors.toMap( + item -> item.get("employee").toString(), + item -> parseToDouble(item.get("usedDay"), 0.0), + (v1, v2) -> v1 // 重复员工取第一个值 + )); + } + + // 1.3 当月休息天数 + Map currentUsedDayMap = new HashMap<>(); + if (recordList2 != null && !recordList2.isEmpty()) { + currentUsedDayMap = recordList2.stream() + .filter(Objects::nonNull) + .filter(item -> item.get("employee") != null) + .collect(Collectors.toMap( + item -> item.get("employee").toString(), + item -> parseToDouble(item.get("usedDay"), 0.0), + (v1, v2) -> v1 + )); + } + + // ========== 2. 汇总所有员工,避免遗漏 ========== + Set allEmployees = new HashSet<>(); + allEmployees.addAll(previousOvertimeMap.keySet()); + allEmployees.addAll(previousUsedDayMap.keySet()); + allEmployees.addAll(currentUsedDayMap.keySet()); + + // ========== 3. 核心计算:动态usedDay值 ========== + Map dynamicUsedDayMap = new HashMap<>(); + for (String employee : allEmployees) { + // 3.1 计算上月剩余加班换休(小于0则取0) + double previousOvertime = previousOvertimeMap.getOrDefault(employee, 0.0); + double previousUsedDay = previousUsedDayMap.getOrDefault(employee, 0.0); + double previousRemaining = Math.max(0.0, previousOvertime - previousUsedDay); + + // 3.2 获取当月休息天数 + double currentUsedDay = currentUsedDayMap.getOrDefault(employee, 0.0); + + // 3.3 按规则计算动态usedDay + double dynamicUsedDay = Math.min(previousRemaining, currentUsedDay); + dynamicUsedDayMap.put(employee, dynamicUsedDay); + } + + return dynamicUsedDayMap; + } + + /** + * 计算每个员工的实际出勤天数(新增上月加班换休/已用休假逻辑) + * 公式调整:worklengthday + (WORK加班day*2) + 动态usedDay + total_leave_days + * 动态usedDay规则: + * 1. 计算上月剩余加班换休 = 上月加班换休总和 - 上月已用休假总和(<0则取0) + * 2. 若上月剩余 > 当月usedDay → 动态usedDay = 当月usedDay + * 3. 若上月剩余 ≤ 当月usedDay → 动态usedDay = 上月剩余 + */ + public static Map calculateActualAttendance( + List> recordList, + List overtimeHours, + List> recordList2, // 当月休息天数 + Map> leaveDurationThisMonth, + List standardOvertimeHoursPreviousMonth, // 上月加班换休 + List> recordList3) { // 上月已用休假 + + // ========== 原有数据源预处理(保持不变) ========== + // 1. recordList -> workLengthDayMap + Map workLengthDayMap = new HashMap<>(); + if (recordList != null && !recordList.isEmpty()) { + workLengthDayMap = recordList.stream() + .filter(Objects::nonNull) + .filter(item -> item.get("employee") != null) + .collect(Collectors.toMap( + item -> item.get("employee").toString(), + item -> parseToDouble(item.get("worklengthday"), 0.0), + (v1, v2) -> v1 + )); + } + + // 2. overtimeHours -> overtimeWorkDayMap + Map overtimeWorkDayMap = new HashMap<>(); + if (overtimeHours != null && !overtimeHours.isEmpty()) { + overtimeWorkDayMap = overtimeHours.stream() + .filter(Objects::nonNull) + .filter(ot -> ot.getId() != null) + .filter(ot -> "WORK".equals(ot.getDay_type())) + .collect(Collectors.groupingBy( + StandardOvertime::getId, + Collectors.summingDouble(ot -> parseToDouble(ot.getDay(), 0.0)) + )) + .entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue,//不用*2了 + (v1, v2) -> v1 + )); + } + + // 3. leaveDurationThisMonth -> totalLeaveDaysMap + Map totalLeaveDaysMap = new HashMap<>(); + if (leaveDurationThisMonth != null && !leaveDurationThisMonth.isEmpty()) { + totalLeaveDaysMap = leaveDurationThisMonth.entrySet().stream() + .filter(entry -> entry.getKey() != null) + .filter(entry -> entry.getValue() != null) + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> parseToDouble(entry.getValue().get("total_leave_days"), 0.0), + (v1, v2) -> v1 + )); + } + + // ========== 新增数据源预处理 ========== + // 4. 上月加班换休总和(standardOvertimeHoursPreviousMonth)-> previousOvertimeMap + Map previousOvertimeMap = new HashMap<>(); + if (standardOvertimeHoursPreviousMonth != null && !standardOvertimeHoursPreviousMonth.isEmpty()) { + previousOvertimeMap = standardOvertimeHoursPreviousMonth.stream() + .filter(Objects::nonNull) + .filter(ot -> ot.getId() != null) + .filter(ot -> "WORK".equals(ot.getDay_type())) // 仅WORK类型计入 + .collect(Collectors.groupingBy( + StandardOvertime::getId, + Collectors.summingDouble(ot -> parseToDouble(ot.getDay(), 0.0)) + )); + } + + // 5. 上月已用休假总和(recordList3)-> previousUsedDayMap + Map previousUsedDayMap = new HashMap<>(); + if (recordList3 != null && !recordList3.isEmpty()) { + previousUsedDayMap = recordList3.stream() + .filter(Objects::nonNull) + .filter(item -> item.get("employee") != null) + .collect(Collectors.toMap( + item -> item.get("employee").toString(), + item -> parseToDouble(item.get("usedDay"), 0.0), + (v1, v2) -> v1 + )); + } + + // 6. 当月休息天数(recordList2)-> currentUsedDayMap + Map currentUsedDayMap = new HashMap<>(); + if (recordList2 != null && !recordList2.isEmpty()) { + currentUsedDayMap = recordList2.stream() + .filter(Objects::nonNull) + .filter(item -> item.get("employee") != null) + .collect(Collectors.toMap( + item -> item.get("employee").toString(), + item -> parseToDouble(item.get("usedDay"), 0.0), + (v1, v2) -> v1 + )); + } + + // ========== 计算动态usedDay(核心新逻辑) ========== + Map dynamicUsedDayMap = new HashMap<>(); + // 汇总所有涉及的员工 + Set allEmployees = new HashSet<>(); + allEmployees.addAll(workLengthDayMap.keySet()); + allEmployees.addAll(overtimeWorkDayMap.keySet()); + allEmployees.addAll(totalLeaveDaysMap.keySet()); + allEmployees.addAll(previousOvertimeMap.keySet()); + allEmployees.addAll(previousUsedDayMap.keySet()); + allEmployees.addAll(currentUsedDayMap.keySet()); + + // 遍历每个员工计算动态usedDay + for (String employee : allEmployees) { + // 1. 计算上月剩余加班换休(<0则取0) + double previousOvertime = previousOvertimeMap.getOrDefault(employee, 0.0); + double previousUsedDay = previousUsedDayMap.getOrDefault(employee, 0.0); + double previousRemaining = Math.max(0.0, previousOvertime - previousUsedDay); + + // 2. 获取当月休息天数 + double currentUsedDay = currentUsedDayMap.getOrDefault(employee, 0.0); + + // 3. 按规则确定动态usedDay + double dynamicUsedDay; + if (previousRemaining > currentUsedDay) { + // 上月剩余 > 当月usedDay → 加当月usedDay + dynamicUsedDay = currentUsedDay; + } else { + // 上月剩余 ≤ 当月usedDay → 加上月剩余 + dynamicUsedDay = previousRemaining; + } + dynamicUsedDayMap.put(employee, dynamicUsedDay); + } + + // ========== 最终计算实际出勤天数 ========== + Map resultMap = new HashMap<>(); + for (String employee : allEmployees) { + double workLengthDay = workLengthDayMap.getOrDefault(employee, 0.0); + double overtimeWorkDay = overtimeWorkDayMap.getOrDefault(employee, 0.0); + double dynamicUsedDay = dynamicUsedDayMap.getOrDefault(employee, 0.0); + double totalLeaveDays = totalLeaveDaysMap.getOrDefault(employee, 0.0); + + // 最终公式:原有公式中usedDay替换为动态计算的值 + double actualAttendance = workLengthDay + overtimeWorkDay + dynamicUsedDay + totalLeaveDays; + resultMap.put(employee, actualAttendance); + } + + return resultMap; + } + + /** + * 安全转换对象为Double类型(核心工具方法) + * @param obj 待转换的对象(可能是String/Number/null/非数字) + * @param defaultValue 转换失败时的默认值 + * @return 转换后的Double值 + */ + private static double parseToDouble(Object obj, double defaultValue) { + if (obj == null) { + return defaultValue; + } + try { + // 兼容String/Integer/Double等类型 + return Double.parseDouble(obj.toString().trim()); + } catch (NumberFormatException e) { + // 非数字类型返回默认值,不抛异常 + return defaultValue; + } + } + + + + /** + * 获取人员原始打卡数据 + * @return + */ + private List getEmployeeTimecardInfo(String yearMonth){ + String sql = " select a.id,a.employee,b.username,DATE_FORMAT(a.ADD_TIME, '%Y-%m-%d %H:%i:%s') as ADD_TIME,a.type\n" + + " from TIMECARD a \n" + + " left join eteams.employee b on a.employee = b.id\n" + + " where a.delete_type = 0\n" + + " and DATE_FORMAT(a.ADD_TIME, '%Y-%m') = '"+yearMonth+"'\n" + + " order by a.ADD_TIME desc "; + log.error("getEmployeeTimecardInfo.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getEmployeeTimecardInfo.recordList:{}", recordList); + List records = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + records = recordList.stream() + .map(map -> { + AttendanceRecord attendanceRecord = new AttendanceRecord(); + attendanceRecord.setPersonId(getMapValue(map, "employee")); + attendanceRecord.setAddTime(parseStrict(getMapValue(map, "add_time"),"yyyy-MM-dd HH:mm:ss")); + return attendanceRecord; + }) + .collect(Collectors.toList()); + } + // 核心转换逻辑 + return records; + } + + + /** + * 获取人员加班余额兑换数 + * @return + */ + private Map getOvertimeExchangeRate(String yearMonth) { + String sql = " select sqr,bcdhzsz from ft_3916736841579 WHERE DELETE_TYPE=0 GROUP BY sqr "; + log.error("getOvertimeExchangeRate.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getOvertimeExchangeRate.recordList:{}", recordList); + return recordList.stream().filter(Objects::nonNull).filter(map -> map.get("sqr") != null && !map.get("sqr").toString().trim().isEmpty()) + .map(map -> { + String sqr = map.get("sqr").toString().trim(); + double bcdhzsz = parseToDouble(map.get("bcdhzsz"), 0.0); + return new AbstractMap.SimpleEntry<>(sqr, bcdhzsz); + }).collect(Collectors.toMap( + AbstractMap.SimpleEntry::getKey, + AbstractMap.SimpleEntry::getValue, + (v1, v2) -> v1 + )); + } + + // 指定格式转换(线程安全) + public static LocalDateTime parseStrict(String dateStr, String pattern) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + try { + return LocalDateTime.parse(dateStr, formatter); + } catch (DateTimeParseException e) { + //System.err.println("解析失败: " + dateStr + " | 格式: " + pattern); + return null; + } + } + + /** + * 查询考勤辅助表信息 + * @return + */ + private List getAttendanceAuxiliaryInfo(String yearMonth){ + String sql = "select * from uf_rybtlbb where delete_type = 0 and DATA_STATUS =1 \n" + + " and rq = '"+yearMonth+"' group by ryxm "; + + log.error("getAttendanceAuxiliaryInfo.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getAttendanceAuxiliaryInfo.recordList:{}", recordList); + List auxiliaries = new ArrayList<>(); + // 核心转换逻辑 + if(CollectionUtils.isNotEmpty(recordList)){ + auxiliaries = recordList.stream() + .map(map -> { + Auxiliary auxiliary = new Auxiliary(); + auxiliary.setRyxm(getMapValue(map, "ryxm")); + auxiliary.setGh(getMapValue(map, "gh")); + auxiliary.setBm(getMapValue(map, "bm")); + auxiliary.setRq(getMapValue(map, "rq")); + auxiliary.setWcbt(getMapValue(map, "wcbt")); + auxiliary.setBmnbt(getMapValue(map, "bmnbt")); + auxiliary.setZhts(getMapValue(map, "zhts")); + auxiliary.setCfbt(getMapValue(map, "cfbt")); + auxiliary.setHjbt1(getMapValue(map, "hjbt1")); + auxiliary.setHjbt2(getMapValue(map, "hjbt2")); + auxiliary.setHjbt3(getMapValue(map, "hjbt3")); + auxiliary.setHjbt4(getMapValue(map, "hjbt4")); + auxiliary.setHjbt5(getMapValue(map, "hjbt5")); + return auxiliary; + }) + .collect(Collectors.toList()); + } + return auxiliaries; + } + + /** + * 查询本月之前的加班小时数 WORK:工作日,PLAYDAY:休息日,HOLIDAY:节假日 + * @return + */ + private List getStandardOvertimeHoursPreviousMonth(String yearMonth){ + String sql = "select employee,day_type,sum(OVER_LENGTH_MSEC) / (1000 * 60 * 60) as hour,\n" + + " sum(OVER_LENGTH_MSEC) / (1000 * 60) as minute,\n" + + " sum(OVER_LENGTH_DAY) as day\n" + + " from attend_overtime_detail\n" + + " where DATE_FORMAT(ATTEND_DATE, '%Y-%m') < '"+yearMonth+"' \n" + + " and delete_type = 0\n" + + " group by EMPLOYEE "; + + log.error("getStandardOvertimeHoursPreviousMonth.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getStandardOvertimeHoursPreviousMonth.recordList:{}", recordList); + List list = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + list = recordList.stream() + .map(map -> { + StandardOvertime standardOvertime = new StandardOvertime(); + standardOvertime.setId(getMapValue(map, "employee")); + standardOvertime.setDay_type(getMapValue(map, "day_type")); + standardOvertime.setHour(getMapValue(map, "hour")); + standardOvertime.setMinute(getMapValue(map, "minute")); + standardOvertime.setDay(getMapValue(map, "day")); + return standardOvertime; + }) + .collect(Collectors.toList()); + //放到全局变量方便之后使用 + StandardOvertimeList.addAll(list); + } + // 核心转换逻辑 + return list; + } + + /** + * 查询系统标准加班小时数 WORK:工作日,PLAYDAY:休息日,HOLIDAY:节假日 + * @return + */ + private List getStandardOvertimeHours(String yearMonth){ + String sql = "select employee,day_type,sum(OVER_LENGTH_MSEC) / (1000 * 60 * 60) as hour,\n" + + " sum(OVER_LENGTH_MSEC) / (1000 * 60) as minute,\n" + + " sum(OVER_LENGTH_DAY) as day\n" + + " from attend_overtime_detail\n" + + " where DATE_FORMAT(ATTEND_DATE, '%Y-%m') = '"+yearMonth+"' \n" + + " and delete_type = 0\n" + + " group by EMPLOYEE "; + + log.error("getStandardOvertimeHours.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("getStandardOvertimeHours.recordList:{}", recordList); + List list = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(recordList)){ + list = recordList.stream() + .map(map -> { + StandardOvertime standardOvertime = new StandardOvertime(); + standardOvertime.setId(getMapValue(map, "employee")); + standardOvertime.setDay_type(getMapValue(map, "day_type")); + standardOvertime.setHour(getMapValue(map, "hour")); + standardOvertime.setMinute(getMapValue(map, "minute")); + standardOvertime.setDay(getMapValue(map, "day")); + return standardOvertime; + }) + .collect(Collectors.toList()); + //放到全局变量方便之后使用 + StandardOvertimeList.addAll(list); + } + // 核心转换逻辑 + return list; + } + + // 类型安全取值工具方法 +// private static T getMapValue(Map map, String key, Class type) { +// if(map.containsKey(key)) { +// Object value = map.get(key); +// if(type.isInstance(value)) { +// return type.cast(value); +// } +// throw new ClassCastException("字段 " + key + " 类型不匹配,期望:" + type.getSimpleName()); +// } +// throw new NoSuchElementException("缺失必填字段: " + key); +// } + // 优化后的getMapValue方法 + public static String convertToSafeString(Object value) { + if (value == null) return null; + Class clazz = value.getClass(); + + // 基础类型直接转换 + if (clazz == Integer.class || clazz == Long.class) { + return value.toString(); + } + // 复杂类型调用其toString() + else if (clazz == LocalDate.class) { + return ((LocalDate) value).format(DateTimeFormatter.ISO_DATE); + } + // 其他类型递归处理 + else if (value instanceof Map) { + return convertMapToJson((Map) value); + } + // 默认调用toString() + return value.toString(); + } + public static String convertMapToJson(Map map) { + try { + return mapper.writeValueAsString(map); + } catch (JsonProcessingException e) { + throw new RuntimeException("JSON序列化失败: " + e.getMessage(), e); + } + } + + // 在getMapValue中应用 + public static String getMapValue(Map map, String key) { + Object value = map.get(key); + return convertToSafeString(value); + } + + @Override + public Map saveEBInfo(String yearMonth, String department, String userName, String jobNum) { + List personList = this.getAttendanceReportInfo(yearMonth, department, userName, jobNum); + log.error("saveEBInfo.personList:{}", personList); + return insertEB(personList); + } + + + @Override + public Map getEmployeePreparationInfo(String department, String year, String month) { + Map result = new HashMap<>(); + String sql = " SELECT org_id,cfg_year,est_count_with_sub ,cfg_month\n" + + " FROM e10_other_business.hr_est_cfg\n" + + " where org_plan_status=1 and DELETE_TYPE = 0 and org_id = '"+department+"' and cfg_year = '"+year+"' and cfg_month ='"+month+"' "; + log.error("queryEmployeePreparationInfo.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + List> recordList = databaseUtils.getDataSourceList(rs); + log.error("queryEmployeePreparationInfo.recordList:{}", recordList); + if(CollectionUtils.isNotEmpty(recordList)){ + String org_id = getValueOrDefaultEmpty(recordList.get(0),"org_id"); + String cfg_year = getValueOrDefaultEmpty(recordList.get(0),"cfg_year"); + String cfg_month = getValueOrDefaultEmpty(recordList.get(0),"cfg_month"); + String est_count_with_sub = getValueOrDefaultEmpty(recordList.get(0),"est_count_with_sub"); + result.put("org_id",org_id); + result.put("cfg_year",cfg_year); + result.put("cfg_month",cfg_month); + result.put("est_count_with_sub",est_count_with_sub); + log.error("getOvertimeExchangeRate.result:{}", result); + } + return result; + } + + /** + * 从Map中根据key取值,null则返回空字符串,非null返回原值(转为String) + * @param map 源Map + * @param key 要获取的key + * @return 处理后的字符串 + */ + private static String getValueOrDefaultEmpty(Map map, String key) { + // Optional.ofNullable处理null,orElse设置默认值为空字符串 + return Optional.ofNullable(map.get(key)) + .map(Object::toString) // 将非null的Object转为String + .orElse(""); + } + + + /** + * 写入导师名录eb表 + * @return + */ + public Map insertEB(List personList){ + Map resultMap = new HashMap<>(); + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 定义格式化器,格式为:yyyy-MM-dd HH:mm:ss + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 格式化时间 + String formattedDateTime = now.format(formatter); + /** + * 插入前先删除导师名录表数据 + */ + String yearMonth = personList.get(0).getYearMonth(); + String str = "update uf_kqsxbb set is_delete=1,delete_type=1 where ny = '"+yearMonth+"' "; + Map rt = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", str); + List> recordList = databaseUtils.getDataSourceList(rt); + log.error("insertEB.recordList:{}", recordList); + for (Person person : personList) { + // 生成随机 ID + long formuserdataid = IdGenerator.generate(); + log.error("insertEB.formuserdataid:"+formuserdataid); + // 使用Optional进行空值安全处理 + String employeeid = Optional.ofNullable(person.getId()).map(Object::toString).orElse(""); + String jobNum = Optional.ofNullable(person.getJobNum()).map(Object::toString).orElse(""); + String username = Optional.ofNullable(person.getName()).map(Object::toString).orElse(""); + String departmentId = Optional.ofNullable(person.getDeptId()).map(Object::toString).orElse(""); + String department = Optional.ofNullable(person.getDept()).map(Object::toString).orElse(""); + //String yearMonth = Optional.ofNullable(person.getYearMonth()).map(Object::toString).orElse(""); + String totalShifts = Optional.ofNullable(person.getTotalShifts()).map(Object::toString).orElse("0"); + String paidAnnualLeave = Optional.ofNullable(person.getPaidAnnualLeave()).map(Object::toString).orElse("0"); + String nursingLeave = Optional.ofNullable(person.getNursingLeave()).map(Object::toString).orElse("0"); + //String paidAnnualAndNursingLeave = Optional.ofNullable(person.getPaidAnnualAndNursingLeave()).map(Object::toString).orElse("0"); + String maternityLeave = Optional.ofNullable(person.getMaternityLeave()).map(Object::toString).orElse("0"); + String marriageLeave = Optional.ofNullable(person.getMarriageLeave()).map(Object::toString).orElse("0"); + String familyVisitLeave = Optional.ofNullable(person.getFamilyVisitLeave()).map(Object::toString).orElse("0"); + String bereavementLeave = Optional.ofNullable(person.getBereavementLeave()).map(Object::toString).orElse("0"); + String personalLeave = Optional.ofNullable(person.getPersonalLeave()).map(Object::toString).orElse("0"); + String commonSickLeave = Optional.ofNullable(person.getCommonSickLeave()).map(Object::toString).orElse("0"); + String hospitalSickLeave = Optional.ofNullable(person.getHospitalSickLeave()).map(Object::toString).orElse("0"); + String officialLeave = Optional.ofNullable(person.getOfficialLeave()).map(Object::toString).orElse("0"); + String workInjuryLeave = Optional.ofNullable(person.getWorkInjuryLeave()).map(Object::toString).orElse("0"); + String examLeave = Optional.ofNullable(person.getExamLeave()).map(Object::toString).orElse("0"); + String careLeave = Optional.ofNullable(person.getCareLeave()).map(Object::toString).orElse("0"); + String businessTrip = Optional.ofNullable(person.getBusinessTrip()).map(Object::toString).orElse("0"); + String compensatoryLeave = Optional.ofNullable(person.getCompensatoryLeave()).map(Object::toString).orElse("0"); + String cfbt = Optional.ofNullable(person.getCfbt()).map(Object::toString).orElse("0"); + String hjbt1 = Optional.ofNullable(person.getHjbt1()).map(Object::toString).orElse("0"); + String hjbt2 = Optional.ofNullable(person.getHjbt2()).map(Object::toString).orElse("0"); + String hjbt3 = Optional.ofNullable(person.getHjbt3()).map(Object::toString).orElse("0"); + String hjbt4 = Optional.ofNullable(person.getHjbt4()).map(Object::toString).orElse("0"); + String hjbt5 = Optional.ofNullable(person.getHjbt5()).map(Object::toString).orElse("0"); + String clbt = Optional.ofNullable(person.getClbt()).map(Object::toString).orElse("0"); + String byf = Optional.ofNullable(person.getByf()).map(Object::toString).orElse("0"); + String zhts = Optional.ofNullable(person.getZhts()).map(Object::toString).orElse("0"); + String bmnbt = Optional.ofNullable(person.getBmnbt()).map(Object::toString).orElse("0"); + String wcf = Optional.ofNullable(person.getWcf()).map(Object::toString).orElse("0"); + String day_type = Optional.ofNullable(person.getDay_type()).map(Object::toString).orElse(""); + String workOverTime = Optional.ofNullable(person.getWorkOverTime()).map(Object::toString).orElse("0"); + String playDayOverTime = Optional.ofNullable(person.getPlayDayOverTime()).map(Object::toString).orElse("0"); + String holidayOverTime = Optional.ofNullable(person.getHolidayOverTime()).map(Object::toString).orElse("0"); + String midShifts = Optional.ofNullable(person.getMidShifts()).map(Object::toString).orElse("0"); + String nightShifts = Optional.ofNullable(person.getNightShifts()).map(Object::toString).orElse("0"); + String midShiftsOver = Optional.ofNullable(person.getMidShiftsOver()).map(Object::toString).orElse("0"); + String nightShiftsOver = Optional.ofNullable(person.getNightShiftsOver()).map(Object::toString).orElse("0"); + String midShiftsAll = Optional.ofNullable(person.getMidShiftsAll()).map(Object::toString).orElse("0"); + String nightShiftsAll = Optional.ofNullable(person.getNightShiftsAll()).map(Object::toString).orElse("0"); + String playDayOverTimeCal = Optional.ofNullable(person.getPlayDayOverTimeCal()).map(Object::toString).orElse("0"); + String workOverTimeCal = Optional.ofNullable(person.getWorkOverTimeCal()).map(Object::toString).orElse("0"); + String standardOvertimeAll = Optional.ofNullable(person.getStandardOvertimeAll()).map(Object::toString).orElse("0"); + String miner = Optional.ofNullable(person.getMiner()).map(Object::toString).orElse("0"); + String welfareLeaveDays = Optional.ofNullable(person.getWelfareLeaveDays()).map(Object::toString).orElse("0"); + + String sql="insert into uf_kqsxbb(id,form_data_id,data_index,create_time,creator,updater,TENANT_KEY,is_flow,data_status," + + "rybh,xm,bm,ny,bygr,zbspbsb,ybspbsb,zbsjb,ybsjb,zbzs,ybzs,prjbxssxtbz," + + "prjbxssjsh,xrjbxssxtbz,xrjbxssjsh,jrjbxss,hjjbszjsh,nxjts,brj," + + "hjts,tqjts,sjts,ssjts,ptbjts,zybjts,cjts,ygxjts,gsjts,ksjts,hljtshpcjyej," + + "gcts,hxts,fljjsts,wcf,kg,bmnbt,wfryzhts,cfbt,hjbt1,hjbt2,hjbt3,hjbt4,hjbt5) " + + " values('"+formuserdataid+"','"+formuserdataid+"',0.0,'"+formattedDateTime+"','1168008887430455296','1168008887430455296','tfira5j3pi',0,1," + + " '"+jobNum+"','"+employeeid+"','"+departmentId+"','"+yearMonth+"','"+totalShifts+"','"+midShifts+"','"+nightShifts+"','"+midShiftsOver+"','"+nightShiftsOver+"','"+midShiftsAll+"','"+nightShiftsAll+"','"+workOverTime+"'," + + " '"+workOverTimeCal+"','"+playDayOverTime+"','"+playDayOverTimeCal+"','"+holidayOverTime+"','"+standardOvertimeAll+"','"+paidAnnualLeave+"','"+nursingLeave+"'," + + " '"+marriageLeave+"','"+familyVisitLeave+"','"+bereavementLeave+"','"+personalLeave+"','"+commonSickLeave+"','"+hospitalSickLeave+"','"+maternityLeave+"','"+officialLeave+"','"+workInjuryLeave+"','"+examLeave+"','"+careLeave+"'," + + " '"+businessTrip+"','"+compensatoryLeave+"','"+welfareLeaveDays+"','"+wcf+"','"+miner+"','"+bmnbt+"','"+zhts+"','"+cfbt+"','"+hjbt1+"','"+hjbt2+"','"+hjbt3+"','"+hjbt4+"','"+hjbt5+"')"; + log.error("insertEB.sql:{}", sql); + Map rs = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", sql); + int code = Integer.parseInt(String.valueOf(rs.get("code"))); + log.error("insertFormdata.code:{}", code); + /** + * 写入表单引擎数据大表 + */ + String stf="insert into formdata(id, form_id, layout_id, data_status, tenant_key, operator, create_time, update_time, " + + " module, client, is_delete, creator, delete_type)" + + " values('" + formuserdataid + "','1198764177559724040','1198764177559724111','submit','tfira5j3pi','1168008887430455296','" + formattedDateTime + "'," + + " '" + formattedDateTime + "','ebuilderform','pc','0','1168008887430455296','0')"; + log.error("insertFormdata.sql:{}", stf); + Map ry = databaseUtils.execute("LOGIC", "weaver-ebuilder-form-service", stf); + int code1 = Integer.parseInt(String.valueOf(ry.get("code"))); + log.error("insertFormdata.code1:{}", code1); + if(200==code&&200==code1){ + resultMap.put("code","200"); + resultMap.put("msg","考勤报表导入EB表成功!"); + } + log.error("insertFormdata.resultMap:{}", resultMap); + } + return resultMap; + } + +} diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/OrganaztionSeviceImpl.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/OrganaztionSeviceImpl.java index ca7732c..3323b9e 100644 --- a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/OrganaztionSeviceImpl.java +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/OrganaztionSeviceImpl.java @@ -43,6 +43,7 @@ public class OrganaztionSeviceImpl implements OrganaztionService { @Override public void addOrganaztionDepartment(Department department, SimpleEmployee employee) { Map insertParam = CommonUtils.convertEntityToMap(department); + log.error("addOrganaztionDepartment.insertParam0000:{}",insertParam); String id= idGeneratorService.generatorIds(1)[0]; insertParam.put("id",id); insertParam.put("data_index","0.0"); @@ -54,6 +55,7 @@ public class OrganaztionSeviceImpl implements OrganaztionService { insertParam.put("updater",String.valueOf(employee.getId())); insertParam.put("delete_type","0"); insertParam.put("ft_status","0"); + log.error("addOrganaztionDepartment.insertParam1111:{}",insertParam); Map param = Maps.newHashMap(); param.put("dataMap",insertParam); param.put("tableName","uf_organization_bghzzsj"); @@ -118,12 +120,13 @@ public class OrganaztionSeviceImpl implements OrganaztionService { @Override public void splitOrganzationDepartment(Map param, SimpleEmployee employee) { Gson gson = new Gson(); - log.error("param : "+param); + log.error("splitOrganzationDepartment.param000: "+param); log.error(gson.toJson(param)); String splitDepartment = String.valueOf(param.get("departmentId")); String splitDepartmentCode = String.valueOf(param.get("departmentCode")); String fgldId = String.valueOf(param.get("fgldId")); String sscb = String.valueOf(param.get("sscb")); + log.error("splitOrganzationDepartment.splitDepartment:{},splitDepartmentCode:{},fgldId:{},sscb:{}"+splitDepartment,splitDepartmentCode,fgldId,sscb); List> dataList = gson.fromJson(param.get("data").toString(),List.class); String sql = "select * from eteams.department where parent=? and delete_type='0'"; @@ -136,16 +139,24 @@ public class OrganaztionSeviceImpl implements OrganaztionService { throw new EmployeeJclRunTimeException("被拆分组织下存在人员"); } for (Map data:dataList){ - log.error("splitOrganzationDepartment data"+data); + log.error("splitOrganzationDepartment.data"+data); String bmfzr = ((List>)data.get("bmfzr")).get(0).get("id").toString(); String sjzz = ((List>)data.get("sjzz")).get(0).get("id").toString(); String sjzzName = ((List>)data.get("sjzz")).get(0).get("name").toString(); - Department department = Department.builder().form_data_id(String.valueOf(param.get("id"))).bh(data.get("bh").toString()).czlx("4").bcfzzid(splitDepartmentCode).bz(data.get("bz").toString()) - .sscb(sscb).fgld(fgldId).sjzzmc(sjzzName).bmsqcj(data.get("bmsqcj").toString()).bmfzr(bmfzr).zzmc(data.get("zzmc").toString()).sjzz(sjzz).sjzzbh(data.get("sjzzbh").toString()).build(); + log.error("splitOrganzationDepartment.bmfzr:{},sjzz:{},sjzzName:{}"+bmfzr,sjzz,sjzzName); + /** + * 这里补充一个逻辑:根据上级组织id查询上级组织编号 + */ + String code = String.valueOf(getDepartmentCodeById(sjzz).get(0).get("code")); + log.error("splitOrganzationDepartment.code"+code); + Department department = Department.builder().form_data_id(String.valueOf(param.get("id"))).bh(data.get("bh").toString()).czlx("4").bcfzzid(splitDepartmentCode) + .sscb(sscb).fgld(fgldId).sjzzmc(sjzzName).bmsqcj(data.get("bmsqcj").toString()).bmfzr(bmfzr).zzmc(data.get("zzmc").toString()).sjzz(sjzz).sjzzbh(code).build(); + log.error("splitOrganzationDepartment.department"+department); addOrganaztionDepartment(department,employee); } sql = "update uf_organization_bghzzsj set delete_type='3',is_delete='1' where bh=?"; - databaseUtils.execute(sql,CommonUtils.getParamList(splitDepartmentCode)); + Map execute = databaseUtils.execute(sql, CommonUtils.getParamList(splitDepartmentCode)); + log.error("splitOrganzationDepartment.execute111:{}",execute); } diff --git a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/UploadServiceImpl.java b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/UploadServiceImpl.java index cc3b9cc..41d449e 100644 --- a/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/UploadServiceImpl.java +++ b/jcl-hrmorganization/secondev-jcl-hrmorganization/src/main/java/com/weaver/seconddev/jcl/organization/service/impl/UploadServiceImpl.java @@ -1,289 +1,289 @@ -package com.weaver.seconddev.jcl.organization.service.impl; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.weaver.common.form.data.FormDataService; -import com.weaver.common.form.metadata.ModuleSource; -import com.weaver.common.util.MimeTypeUtil; -import com.weaver.eteams.file.client.file.FileData; -import com.weaver.eteams.file.client.file.FileObj; -import com.weaver.eteams.file.client.remote.FileClientService; -import com.weaver.eteams.file.client.remote.RemoteUploadService; -import com.weaver.file.ud.api.FileDownloadService; -import com.weaver.framework.rpc.annotation.RpcReference; -import com.weaver.seconddev.jcl.common.service.CommonService; -import com.weaver.seconddev.jcl.enums.ContractStatusEnum; -import com.weaver.seconddev.jcl.organization.service.UploadService; -import com.weaver.seconddev.jcl.organization.util.CommonUtils; -import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; -import com.weaver.seconddev.jcl.organization.util.excel.ExcelParseHelper; -import com.weaver.seconddev.jcl.organization.util.excel.ExcelSupport; -import com.weaver.seconddev.jcl.organization.util.excel.ExcelUtil; -import com.weaver.teams.client.doc.remote.DocClientService; -import com.weaver.teams.crm.property.PropertyType; -import com.weaver.teams.domain.EntityType; -import com.weaver.teams.domain.crm.RemoteCustomerProperty; -import com.weaver.teams.domain.crm.RemoteCustomerPropertyService; -import com.weaver.teams.domain.user.SimpleEmployee; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import java.io.*; -import java.nio.file.Files; -import java.util.*; -import java.util.stream.Collectors; - -@Slf4j -@Service -public class UploadServiceImpl implements UploadService { - - @RpcReference - private RemoteUploadService remoteUploadService; - @RpcReference - private DocClientService docClientService; - @RpcReference - private FileClientService fileClientService; - @Autowired - private DatabaseUtils databaseUtils; - @RpcReference - private RemoteCustomerPropertyService remoteCustomerPropertyService; - @Autowired - private CommonService commonService; - @Autowired - private FileDownloadService fileDownloadService; - public static final String EXCEL_TYPE_XLSX = "xlsx"; - public static final String EXCEL_TYPE_XLS = "xls"; - - - @Override - public Map jcluploadFile(List> list,String tableName,String folderId,SimpleEmployee employee) throws Exception { - Map returnMap = Maps.newHashMap(); - List> importList = Lists.newArrayList(); - String sql = "select a.* from form_field a left join form_table b on a.form_id=b.form_id where b.table_name=? and a.delete_type='0'"; - List> fieldList = databaseUtils.getSqlList(sql,CommonUtils.getParamList(tableName)); - Map>> fieldGroupByTitle = fieldList.stream().collect(Collectors.groupingBy(e->e.get("title").toString())); - for (Map resultMap:list){ - FileData fileData = new FileData(); - fileData.setLoadUrl(fileDownloadService.getDownloadUrl(CommonUtils.null2String(resultMap.get("url")),CommonUtils.null2String(resultMap.get("tenant_key")),CommonUtils.null2String(resultMap.get("name")))); - - InputStream fileInputStream = fileData.getInputStream(); - - Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); - //标题 - List titles = ExcelSupport.getSheetHeader(sheet, 0); - returnMap.put("titles",titles); - log.error("title长度:{}",titles.get(0).length()); - String title = titles.get(0).replace(" ", ""); - log.error("处理前年月信息:{}",title); - - - // 处理数值 - List> data = ExcelParseHelper.parse2Map(sheet, 1, 0); - log.error("excel导入数据数量:[{}]", data.size()); - // 表头 - List headers = ExcelSupport.getSheetHeader(sheet, 0); - List> dataList = Lists.newArrayList(); - List> fileList = ExcelUtil.processEmbeddedObjects((XSSFSheet)sheet); - Map map = Maps.newHashMap(); - for (int i = 0; i < data.size(); i++) { - map = data.get(i); - Map singleCheck = new HashMap<>(); - for (int j = 0; j < headers.size(); j++) { - //组装单条数据基础数据 - String key = headers.get(j); - if (key == null) { - continue; - } - singleCheck.put(key.replace(" ", ""), Optional.ofNullable(map.get(key)).orElse("").toString().replace(" ", "")); - } - dataList.add(singleCheck); - } - //处理导入附件 - List> needUpdataList = Lists.newArrayList(); - for (Map fileMap:fileList){ - int rowNum = Integer.valueOf(fileMap.get("rowNum").toString()); - int colNum = Integer.valueOf(fileMap.get("colNum").toString()); - String fileName = dataList.get(rowNum-1).get(titles.get(colNum)); - fileMap.put("filename",fileName); - - Map fileUploadMap = uploadFile(fileMap,folderId,ModuleSource.ebuildercard,0L,employee,null); - long docId = ((FileObj)fileUploadMap.get("fileObj")).getDocId(); - long fileid = ((FileObj)fileUploadMap.get("fileObj")).getFileid(); - long id = ((FileObj)fileUploadMap.get("fileObj")).getId(); - log.error("docId : [{}],fileid:[{}],id:[{}]",docId,fileid,id); - dataList.get(rowNum-1).put(titles.get(colNum),String.valueOf(docId)); - Map updataMap = Maps.newHashMap(); - updataMap.put("id",dataList.get(rowNum-1).get("数据ID")); - if (fieldGroupByTitle.get(titles.get(colNum)).get(0).get("component_key").equals("FileComponent")){ - //附件 - log.error("附件字段"); - updataMap.put(titles.get(colNum),String.valueOf(fileid)); - }else{ - log.error("文档字段"); - log.error("字段key:"+fieldGroupByTitle.get(titles.get(colNum)).get(0).get("component_key")); - updataMap.put(titles.get(colNum),String.valueOf(docId)); - } - needUpdataList.add(updataMap); - } - - Map importResult = importData(needUpdataList,tableName,fieldGroupByTitle); - importList.add(importResult); - } - returnMap.put("importList",importList); - - return returnMap; - } - - public Map uploadFile(Map fileMap,String folderId, ModuleSource module, Long refId, SimpleEmployee employee, String chunks) { - File data = null; - try{ - data = File.createTempFile(UUID.randomUUID().toString(),null); - InputStream stream = (InputStream)fileMap.get("stream"); - String filename = CommonUtils.null2String(fileMap.get("filename")); - if (filename.endsWith(".pdf") || filename.endsWith(".bin")){ - PDDocument document = PDDocument.load(stream); - document.save(data); - if (filename.endsWith(".bin")){ - filename = filename.replace(".bin",".pdf"); - fileMap.put("filename",filename); - } - }else { - FileUtils.copyInputStreamToFile(stream, data); - } - stream.close(); - }catch (Exception e){ - log.error("error", e); - } - - Map result = new HashMap<>(); - if (refId == 0L) { - FileObj fileObj = new FileObj(); - String dataFileName = CommonUtils.null2String(fileMap.get("filename")); - - if(StringUtils.isEmpty(dataFileName)){ - return result; - } - String dataContentType = CommonUtils.null2String(fileMap.get("contentType")); - fileObj.setName(dataFileName); - fileObj.setRefId(refId); - fileObj.setModule(EntityType.valueOf(module.toString())); - String extensionName = dataFileName.lastIndexOf(".") > 0 ? dataFileName.substring(dataFileName.lastIndexOf(".")) : ""; - String contentType = MimeTypeUtil.getMimeType(extensionName); - - fileObj.setType(contentType != null ? contentType : dataContentType); - fileObj.setSize(data.length()); - String tenantKey = employee.getTenantKey(); - fileObj.setTenantKey(tenantKey); - if(chunks != null) { - try { - InputStream input = new FileInputStream(data); - Map map = remoteUploadService.chunkUpload( - employee.getEmployeeId(), - chunks, - Integer.parseInt(chunks == null ? "0" : chunks), - Integer.parseInt(chunks == null ? "0" : chunks), - data.length(), - toByteArray(input), - String.valueOf(new Date().getTime()), - dataFileName, - data.length(), - module.toString(), - refId, - null, - "false", - tenantKey); - String success = (String) map.get("success"); - if(map.get("fileObj") != null) { - success = "true"; - fileObj = (FileObj) map.get("fileObj"); - } - result.put("success",success); - result.put("responseMap",map); - }catch (Exception e) { - log.error("error", e); - result.put("error",e); - } - }else{ - try{ - fileObj = remoteUploadService.saveFile(employee.getTenantKey(), fileObj, Files.readAllBytes(data.toPath())); - //生成附件文档 - fileObj.setDocId(docClientService.fileCreateDoc(fileObj.getFileid(),Long.valueOf(folderId),employee.getId(),EntityType.valueOf(module.toString()),employee.getTenantKey())); - //fileObj.setDocId(docClientService.postFileUploadReId(fileObj, employee, new Date(), EntityType.valueOf(module.toString()))); - fileClientService.update(fileObj); - } catch (Exception e) { - log.error("error", e); - } finally { - if(data != null){ - data.delete(); - } - } - } - result.put("fileObj",fileObj); - result.put("module",module); - result.put("refId",refId); - } - - return result; - } - - public Map importData(List> dataList,String tableName,Map>> fieldGroupByTitle) { - - Map resultMap = Maps.newHashMap(); - - List> updateData = Lists.newArrayList(); - - Map>> dataGroupById = dataList.stream().collect(Collectors.groupingBy(e->e.get("id").toString())); - for (Map.Entry>>entry : dataGroupById.entrySet()){ - Map updataMap = Maps.newHashMap(); - String id = entry.getKey(); - Map dataMap = Maps.newHashMap(); - for (Map map : entry.getValue()){ - for (Map.Entry data: map.entrySet()){ - String key = data.getKey(); - key = fieldGroupByTitle.get(key)==null?key:fieldGroupByTitle.get(key).get(0).get("data_key").toString(); - String value = data.getValue(); - if (dataMap.get(key) == null){ - dataMap.put(key,value); - }else { - String oldValue = CommonUtils.null2String(dataMap.get(key)); - dataMap.put(key,oldValue+","+value); - } - } - } - Map condition = Maps.newHashMap(); - condition.put("id",id); - updataMap.put("condition",condition); - updataMap.put("dataMap",dataMap); - updataMap.put("tableName",tableName); - commonService.updateCommon(updataMap); - updateData.add(updataMap); - } - - resultMap.put("updateData",updateData); - return resultMap; - } - - /** - * InputStream转化为byte数组 - * @param input 输入流 - * @return 字节 - * @throws IOException 异常 - */ - public static byte[] toByteArray(InputStream input) throws IOException { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - byte[] buffer = new byte[4096]; - int n = 0; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - } - return output.toByteArray(); - } -} +//package com.weaver.seconddev.jcl.organization.service.impl; +// +//import com.google.common.collect.Lists; +//import com.google.common.collect.Maps; +//import com.weaver.common.form.data.FormDataService; +//import com.weaver.common.form.metadata.ModuleSource; +//import com.weaver.common.util.MimeTypeUtil; +//import com.weaver.eteams.file.client.file.FileData; +//import com.weaver.eteams.file.client.file.FileObj; +//import com.weaver.eteams.file.client.remote.FileClientService; +//import com.weaver.eteams.file.client.remote.RemoteUploadService; +//import com.weaver.file.ud.api.FileDownloadService; +//import com.weaver.framework.rpc.annotation.RpcReference; +//import com.weaver.seconddev.jcl.common.service.CommonService; +//import com.weaver.seconddev.jcl.enums.ContractStatusEnum; +//import com.weaver.seconddev.jcl.organization.service.UploadService; +//import com.weaver.seconddev.jcl.organization.util.CommonUtils; +//import com.weaver.seconddev.jcl.organization.util.DatabaseUtils; +//import com.weaver.seconddev.jcl.organization.util.excel.ExcelParseHelper; +//import com.weaver.seconddev.jcl.organization.util.excel.ExcelSupport; +//import com.weaver.seconddev.jcl.organization.util.excel.ExcelUtil; +//import com.weaver.teams.client.doc.remote.DocClientService; +//import com.weaver.teams.crm.property.PropertyType; +//import com.weaver.teams.domain.EntityType; +//import com.weaver.teams.domain.crm.RemoteCustomerProperty; +//import com.weaver.teams.domain.crm.RemoteCustomerPropertyService; +//import com.weaver.teams.domain.user.SimpleEmployee; +//import lombok.extern.slf4j.Slf4j; +//import org.apache.commons.io.FileUtils; +//import org.apache.commons.io.IOUtils; +//import org.apache.commons.lang.StringUtils; +//import org.apache.pdfbox.pdmodel.PDDocument; +//import org.apache.poi.ss.usermodel.Sheet; +//import org.apache.poi.xssf.usermodel.XSSFSheet; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +//import org.springframework.web.multipart.MultipartFile; +// +//import java.io.*; +//import java.nio.file.Files; +//import java.util.*; +//import java.util.stream.Collectors; +// +//@Slf4j +//@Service +//public class UploadServiceImpl implements UploadService { +// +// @RpcReference +// private RemoteUploadService remoteUploadService; +// @RpcReference +// private DocClientService docClientService; +// @RpcReference +// private FileClientService fileClientService; +// @Autowired +// private DatabaseUtils databaseUtils; +// @RpcReference +// private RemoteCustomerPropertyService remoteCustomerPropertyService; +// @Autowired +// private CommonService commonService; +// @Autowired +// private FileDownloadService fileDownloadService; +// public static final String EXCEL_TYPE_XLSX = "xlsx"; +// public static final String EXCEL_TYPE_XLS = "xls"; +// +// +// @Override +// public Map jcluploadFile(List> list,String tableName,String folderId,SimpleEmployee employee) throws Exception { +// Map returnMap = Maps.newHashMap(); +// List> importList = Lists.newArrayList(); +// String sql = "select a.* from form_field a left join form_table b on a.form_id=b.form_id where b.table_name=? and a.delete_type='0'"; +// List> fieldList = databaseUtils.getSqlList(sql,CommonUtils.getParamList(tableName)); +// Map>> fieldGroupByTitle = fieldList.stream().collect(Collectors.groupingBy(e->e.get("title").toString())); +// for (Map resultMap:list){ +// FileData fileData = new FileData(); +// fileData.setLoadUrl(fileDownloadService.getDownloadUrl(CommonUtils.null2String(resultMap.get("url")),CommonUtils.null2String(resultMap.get("tenant_key")),CommonUtils.null2String(resultMap.get("name")))); +// +// InputStream fileInputStream = fileData.getInputStream(); +// +// Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); +// //标题 +// List titles = ExcelSupport.getSheetHeader(sheet, 0); +// returnMap.put("titles",titles); +// log.error("title长度:{}",titles.get(0).length()); +// String title = titles.get(0).replace(" ", ""); +// log.error("处理前年月信息:{}",title); +// +// +// // 处理数值 +// List> data = ExcelParseHelper.parse2Map(sheet, 1, 0); +// log.error("excel导入数据数量:[{}]", data.size()); +// // 表头 +// List headers = ExcelSupport.getSheetHeader(sheet, 0); +// List> dataList = Lists.newArrayList(); +// List> fileList = ExcelUtil.processEmbeddedObjects((XSSFSheet)sheet); +// Map map = Maps.newHashMap(); +// for (int i = 0; i < data.size(); i++) { +// map = data.get(i); +// Map singleCheck = new HashMap<>(); +// for (int j = 0; j < headers.size(); j++) { +// //组装单条数据基础数据 +// String key = headers.get(j); +// if (key == null) { +// continue; +// } +// singleCheck.put(key.replace(" ", ""), Optional.ofNullable(map.get(key)).orElse("").toString().replace(" ", "")); +// } +// dataList.add(singleCheck); +// } +// //处理导入附件 +// List> needUpdataList = Lists.newArrayList(); +// for (Map fileMap:fileList){ +// int rowNum = Integer.valueOf(fileMap.get("rowNum").toString()); +// int colNum = Integer.valueOf(fileMap.get("colNum").toString()); +// String fileName = dataList.get(rowNum-1).get(titles.get(colNum)); +// fileMap.put("filename",fileName); +// +// Map fileUploadMap = uploadFile(fileMap,folderId,ModuleSource.ebuildercard,0L,employee,null); +// long docId = ((FileObj)fileUploadMap.get("fileObj")).getDocId(); +// long fileid = ((FileObj)fileUploadMap.get("fileObj")).getFileid(); +// long id = ((FileObj)fileUploadMap.get("fileObj")).getId(); +// log.error("docId : [{}],fileid:[{}],id:[{}]",docId,fileid,id); +// dataList.get(rowNum-1).put(titles.get(colNum),String.valueOf(docId)); +// Map updataMap = Maps.newHashMap(); +// updataMap.put("id",dataList.get(rowNum-1).get("数据ID")); +// if (fieldGroupByTitle.get(titles.get(colNum)).get(0).get("component_key").equals("FileComponent")){ +// //附件 +// log.error("附件字段"); +// updataMap.put(titles.get(colNum),String.valueOf(fileid)); +// }else{ +// log.error("文档字段"); +// log.error("字段key:"+fieldGroupByTitle.get(titles.get(colNum)).get(0).get("component_key")); +// updataMap.put(titles.get(colNum),String.valueOf(docId)); +// } +// needUpdataList.add(updataMap); +// } +// +// Map importResult = importData(needUpdataList,tableName,fieldGroupByTitle); +// importList.add(importResult); +// } +// returnMap.put("importList",importList); +// +// return returnMap; +// } +// +// public Map uploadFile(Map fileMap,String folderId, ModuleSource module, Long refId, SimpleEmployee employee, String chunks) { +// File data = null; +// try{ +// data = File.createTempFile(UUID.randomUUID().toString(),null); +// InputStream stream = (InputStream)fileMap.get("stream"); +// String filename = CommonUtils.null2String(fileMap.get("filename")); +// if (filename.endsWith(".pdf") || filename.endsWith(".bin")){ +// PDDocument document = PDDocument.load(stream); +// document.save(data); +// if (filename.endsWith(".bin")){ +// filename = filename.replace(".bin",".pdf"); +// fileMap.put("filename",filename); +// } +// }else { +// FileUtils.copyInputStreamToFile(stream, data); +// } +// stream.close(); +// }catch (Exception e){ +// log.error("error", e); +// } +// +// Map result = new HashMap<>(); +// if (refId == 0L) { +// FileObj fileObj = new FileObj(); +// String dataFileName = CommonUtils.null2String(fileMap.get("filename")); +// +// if(StringUtils.isEmpty(dataFileName)){ +// return result; +// } +// String dataContentType = CommonUtils.null2String(fileMap.get("contentType")); +// fileObj.setName(dataFileName); +// fileObj.setRefId(refId); +// fileObj.setModule(EntityType.valueOf(module.toString())); +// String extensionName = dataFileName.lastIndexOf(".") > 0 ? dataFileName.substring(dataFileName.lastIndexOf(".")) : ""; +// String contentType = MimeTypeUtil.getMimeType(extensionName); +// +// fileObj.setType(contentType != null ? contentType : dataContentType); +// fileObj.setSize(data.length()); +// String tenantKey = employee.getTenantKey(); +// fileObj.setTenantKey(tenantKey); +// if(chunks != null) { +// try { +// InputStream input = new FileInputStream(data); +// Map map = remoteUploadService.chunkUpload( +// employee.getEmployeeId(), +// chunks, +// Integer.parseInt(chunks == null ? "0" : chunks), +// Integer.parseInt(chunks == null ? "0" : chunks), +// data.length(), +// toByteArray(input), +// String.valueOf(new Date().getTime()), +// dataFileName, +// data.length(), +// module.toString(), +// refId, +// null, +// "false", +// tenantKey); +// String success = (String) map.get("success"); +// if(map.get("fileObj") != null) { +// success = "true"; +// fileObj = (FileObj) map.get("fileObj"); +// } +// result.put("success",success); +// result.put("responseMap",map); +// }catch (Exception e) { +// log.error("error", e); +// result.put("error",e); +// } +// }else{ +// try{ +// fileObj = remoteUploadService.saveFile(employee.getTenantKey(), fileObj, Files.readAllBytes(data.toPath())); +// //生成附件文档 +// fileObj.setDocId(docClientService.fileCreateDoc(fileObj.getFileid(),Long.valueOf(folderId),employee.getId(),EntityType.valueOf(module.toString()),employee.getTenantKey())); +// //fileObj.setDocId(docClientService.postFileUploadReId(fileObj, employee, new Date(), EntityType.valueOf(module.toString()))); +// fileClientService.update(fileObj); +// } catch (Exception e) { +// log.error("error", e); +// } finally { +// if(data != null){ +// data.delete(); +// } +// } +// } +// result.put("fileObj",fileObj); +// result.put("module",module); +// result.put("refId",refId); +// } +// +// return result; +// } +// +// public Map importData(List> dataList,String tableName,Map>> fieldGroupByTitle) { +// +// Map resultMap = Maps.newHashMap(); +// +// List> updateData = Lists.newArrayList(); +// +// Map>> dataGroupById = dataList.stream().collect(Collectors.groupingBy(e->e.get("id").toString())); +// for (Map.Entry>>entry : dataGroupById.entrySet()){ +// Map updataMap = Maps.newHashMap(); +// String id = entry.getKey(); +// Map dataMap = Maps.newHashMap(); +// for (Map map : entry.getValue()){ +// for (Map.Entry data: map.entrySet()){ +// String key = data.getKey(); +// key = fieldGroupByTitle.get(key)==null?key:fieldGroupByTitle.get(key).get(0).get("data_key").toString(); +// String value = data.getValue(); +// if (dataMap.get(key) == null){ +// dataMap.put(key,value); +// }else { +// String oldValue = CommonUtils.null2String(dataMap.get(key)); +// dataMap.put(key,oldValue+","+value); +// } +// } +// } +// Map condition = Maps.newHashMap(); +// condition.put("id",id); +// updataMap.put("condition",condition); +// updataMap.put("dataMap",dataMap); +// updataMap.put("tableName",tableName); +// commonService.updateCommon(updataMap); +// updateData.add(updataMap); +// } +// +// resultMap.put("updateData",updateData); +// return resultMap; +// } +// +// /** +// * InputStream转化为byte数组 +// * @param input 输入流 +// * @return 字节 +// * @throws IOException 异常 +// */ +// public static byte[] toByteArray(InputStream input) throws IOException { +// ByteArrayOutputStream output = new ByteArrayOutputStream(); +// byte[] buffer = new byte[4096]; +// int n = 0; +// while (-1 != (n = input.read(buffer))) { +// output.write(buffer, 0, n); +// } +// return output.toByteArray(); +// } +//}