飞书接口

This commit is contained in:
dxfeng 2025-07-16 14:31:52 +08:00
parent a7905171fa
commit f534fe2ef7
8 changed files with 458 additions and 0 deletions

View File

@ -2,4 +2,5 @@ description = "子模块demo项目"
dependencies {
//
implementation project(':secondev-chapanda-portal')
}

View File

@ -0,0 +1,41 @@
package com.weaver.seconddev.feishu.controller;
import com.weaver.common.authority.annotation.WeaPermission;
import com.weaver.seconddev.feishu.service.EmployeePanelService;
import lombok.extern.slf4j.Slf4j;
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.HashMap;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Slf4j
@RestController
@RequestMapping("/api/secondev/panel/employee")
@WeaPermission(publicPermission = true)
public class EmployeePanelController {
@Autowired
EmployeePanelService employeePanelService;
@GetMapping("/getAttendInfo")
public Object getAttendInfo(@RequestParam("beginDate") String beginDate,
@RequestParam("endDate") String endDate,
@RequestParam("jobNum") String jobNum) {
log.error("beginDate:{},endDate:{},jobNum:{}", beginDate, endDate, jobNum);
Map<String, Object> params = new HashMap<>();
params.put("beginDate", beginDate);
params.put("endDate", endDate);
params.put("jobNum", jobNum);
return employeePanelService.getAttendInfo(params);
}
}

View File

@ -0,0 +1,41 @@
package com.weaver.seconddev.feishu.controller;
import com.weaver.common.authority.annotation.WeaPermission;
import com.weaver.seconddev.feishu.service.EmployeePanelService;
import lombok.extern.slf4j.Slf4j;
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.HashMap;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Slf4j
@RestController
@RequestMapping("/sapi/secondev/panel/employee")
@WeaPermission(publicPermission = true)
public class OutEmployeePanelController {
@Autowired
EmployeePanelService employeePanelService;
@GetMapping("/getAttendInfo")
public Object getAttendInfo(@RequestParam("beginDate") String beginDate,
@RequestParam("endDate") String endDate,
@RequestParam("jobNum") String jobNum) {
log.error("beginDate:{},endDate:{},jobNum:{}", beginDate, endDate, jobNum);
Map<String, Object> params = new HashMap<>();
params.put("beginDate", beginDate);
params.put("endDate", endDate);
params.put("jobNum", jobNum);
return employeePanelService.getAttendInfo(params);
}
}

View File

@ -0,0 +1,26 @@
package com.weaver.seconddev.feishu.entity.po;
import lombok.Data;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Data
public class EmployeeAttendInfoPo {
/**
* 工号
*/
private String workCode;
/**
* 应出勤天数
*/
private String expectedAttendance;
/**
* 实际出勤
*/
private String actualAttendance;
}

View File

@ -0,0 +1,25 @@
package com.weaver.seconddev.feishu.mapper;
import com.weaver.seconddev.portal.entity.param.BaseParam;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Mapper
public interface EmployeePanelMapper {
@MapKey("employee")
Map<BigDecimal, Map<String, Object>> statsWorkTimeLength(@Param("param") BaseParam param, @Param(value = "empIds") List<Long> empIds, @Param(value = "beginDate") Date beginDate, @Param(value = "endDate") Date endDate,
@Param(value = "tenantKey") String tenantKey, @Param("extraAbsenteeism") boolean extraAbsenteeism, @Param("hasDetailExtend") boolean hasDetailExtend);
}

View File

@ -0,0 +1,22 @@
package com.weaver.seconddev.feishu.service;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.seconddev.feishu.entity.po.EmployeeAttendInfoPo;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
public interface EmployeePanelService {
/**
* 获取考勤信息
*
* @param params
* @return
*/
WeaResult<EmployeeAttendInfoPo> getAttendInfo(Map<String, Object> params);
}

View File

@ -0,0 +1,116 @@
package com.weaver.seconddev.feishu.service.impl;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.common.hr.util.Util;
import com.weaver.seconddev.feishu.entity.po.EmployeeAttendInfoPo;
import com.weaver.seconddev.feishu.mapper.EmployeePanelMapper;
import com.weaver.seconddev.feishu.service.EmployeePanelService;
import com.weaver.seconddev.portal.entity.param.BaseParam;
import com.weaver.workflow.common.cfg.org.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Slf4j
@Service
public class EmployeePanelServiceImpl implements EmployeePanelService {
private static final String TENANT_KEY = "t024j0gfn0";
@Autowired
EmployeePanelMapper employeePanelMapper;
@Autowired
UserService userService;
@Override
public WeaResult<EmployeeAttendInfoPo> getAttendInfo(Map<String, Object> params) {
String jobNum = Util.null2String(params.get("jobNum"));
String beginDateStr = Util.null2String(params.get("beginDate"));
String endDateStr = Util.null2String(params.get("endDate"));
BaseParam baseParam = new BaseParam();
List<Long> userIdsByJobNum = userService.getUserIdsByJobNum(jobNum, TENANT_KEY);
if (CollectionUtils.isEmpty(userIdsByJobNum)) {
return WeaResult.fail("未匹配到人员", true);
}
Long employeeId = userIdsByJobNum.get(0);
//
List<Long> empIds = new ArrayList<>();
empIds.add(employeeId);
Date beginDate = parseDate(beginDateStr);
Date endDate = parseDate(endDateStr);
Map<BigDecimal, Map<String, Object>> mapMap = employeePanelMapper.statsWorkTimeLength(baseParam, empIds, beginDate, endDate, TENANT_KEY, false, false);
Map<String, Object> map = mapMap.get(BigDecimal.valueOf(employeeId));
log.error("map===>{}", map);
EmployeeAttendInfoPo employeeAttendInfoPo = new EmployeeAttendInfoPo();
employeeAttendInfoPo.setExpectedAttendance(formatNumber(map.get("period_length_day").toString()));
//employeeAttendInfoPo.setActualAttendance(formatNumber(map.get("actual_work_length_day").toString()));
employeeAttendInfoPo.setActualAttendance(formatNumber(map.get("work_length_day").toString()));
return WeaResult.success(employeeAttendInfoPo);
}
/**
* 日期类型转换
*
* @param dateStr
* @return
*/
private Date parseDate(String dateStr) {
if (dateStr == null) {
return null;
}
// 定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 将字符串解析为LocalDate
LocalDate localDate = LocalDate.parse(dateStr, formatter);
// 将LocalDate转换为java.util.Date
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
/**
* 格式化数字
*
* @param numberStr
* @return
*/
public static String formatNumber(String numberStr) {
if (numberStr == null || numberStr.isEmpty()) {
return numberStr;
}
BigDecimal bd = new BigDecimal(numberStr);
// 向上取整最多保留两位小数
bd = bd.setScale(2, RoundingMode.HALF_UP);
String formatted = bd.stripTrailingZeros().toPlainString();
// 如果结果为整数则去掉小数点
if (formatted.contains(".") && formatted.substring(formatted.indexOf('.') + 1).matches("0+")) {
return formatted.substring(0, formatted.indexOf('.'));
}
return formatted;
}
}

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weaver.seconddev.feishu.mapper.EmployeePanelMapper">
<sql id="lostAbsenteeismLengthHourSql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(abs.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(EARLY_OUT_LENGTH_MESC,0) -
IFNULL(SERIOUS_EARLY_LENGTH_MESC, 0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(abs.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(LATE_LENGTH_MESC,0)
-IFNULL(SERIOUS_LATE_LENGTH_MESC,0) ELSE 0 END
ELSE 0 END
ELSE 0 END)*1.00/3600000 AS lost_length_hour
</sql>
<sql id="lostAbsenteeismLengthDaySql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(abs.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(EARLY_OUT_LENGTH_DAY,0)-IFNULL(SERIOUS_EARLY_LENGTH_DAY,0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(abs.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(LATE_LENGTH_DAY,0)-IFNULL(SERIOUS_LATE_LENGTH_DAY,0)
ELSE 0 END
ELSE 0 END
ELSE 0 END) AS lost_length_day
</sql>
<sql id="lostLengthHourSql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(AAD.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(EARLY_OUT_LENGTH_MESC,0) -
IFNULL(SERIOUS_EARLY_LENGTH_MESC, 0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(AAD.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(LATE_LENGTH_MESC,0)
-IFNULL(SERIOUS_LATE_LENGTH_MESC,0) ELSE 0 END
ELSE 0 END
ELSE 0 END)*1.00/3600000 AS lost_length_hour
</sql>
<sql id="lateEarlyCountLengthSql">
sum(case when month_late_length_mesc = 1 then 1 else 0 end) AS month_late_in_count,
sum(case when month_late_length_mesc = 1 then AAD.LATE_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_late_in_hour,
sum(case when month_late_length_mesc = 1 then AAD.LATE_LENGTH_DAY else 0 end) AS month_late_in_day,
sum(case when month_late_length_mesc = 2 then 1 else 0 end) AS month_late_out_count,
sum(case when month_late_length_mesc = 2 then AAD.LATE_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_late_out_hour,
sum(case when month_late_length_mesc = 2 then AAD.LATE_LENGTH_DAY else 0 end) AS month_late_out_day,
sum(case when month_early_length_mesc = 1 then 1 else 0 end) AS month_early_in_count,
sum(case when month_early_length_mesc = 1 then AAD.EARLY_OUT_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_early_in_hour,
sum(case when month_early_length_mesc = 1 then AAD.EARLY_OUT_LENGTH_DAY else 0 end) AS month_early_in_day,
sum(case when month_early_length_mesc = 2 then 1 else 0 end) AS month_early_out_count,
sum(case when month_early_length_mesc = 2 then AAD.EARLY_OUT_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_early_out_hour,
sum(case when month_early_length_mesc = 2 then AAD.EARLY_OUT_LENGTH_DAY else 0 end) AS month_early_out_day
</sql>
<sql id="lostLengthDaySql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(AAD.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(EARLY_OUT_LENGTH_DAY,0)-IFNULL(SERIOUS_EARLY_LENGTH_DAY,0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(AAD.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(LATE_LENGTH_DAY,0)-IFNULL(SERIOUS_LATE_LENGTH_DAY,0)
ELSE 0 END
ELSE 0 END
ELSE 0 END) AS lost_length_day
</sql>
<select id="statsWorkTimeLength" resultType="java.util.Map">
SELECT
ASD.employee,
COUNT(CASE WHEN SIGN_IN_RECORD IS NOT NULL THEN 1 END) AS sign_in_num,
COUNT(CASE FINAL_SIGN_IN_STATUS WHEN 'SIGN_IN_LATE' THEN 1 END) AS late_num,
COUNT(CASE WHEN SIGN_OUT_RECORD IS NOT NULL THEN 1 END) AS sign_out_num,
COUNT(CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_EARLY' THEN 1 END) AS early_num,
COUNT(CASE FINAL_SIGN_IN_STATUS WHEN 'SERIOUSLY_LATE' THEN 1 END) AS seriously_late_num,
COUNT(CASE FINAL_SIGN_OUT_STATUS WHEN 'SERIOUSLY_EARLY' THEN 1 END) AS seriously_early_num,
<choose>
<when test="extraAbsenteeism == true">
COUNT(CASE WHEN abs.sign_in_absenteeism_status is not null AND (abs.sign_in_absenteeism_status !=
'SIGN_IN_NORMAL') THEN 1 END) AS absent_num_of_sign_in,
sum(abs.month_absent_countous) AS month_absent_countous,
</when>
<otherwise>
COUNT(CASE FINAL_SIGN_IN_STATUS WHEN 'SIGN_IN_ABSENTEEISM' THEN 1 END) AS absent_num_of_sign_in,
</otherwise>
</choose>
<choose>
<when test="extraAbsenteeism == true">
COUNT(CASE WHEN abs.sign_out_absenteeism_status is not null AND (abs.sign_out_absenteeism_status !=
'SIGN_OUT_NORMAL') AND (SIGN_IN_RECORD IS NOT NULL OR SIGN_OUT_RECORD IS NOT NULL) THEN 1 END) AS
absent_num_of_sign_out,
</when>
<otherwise>
COUNT(CASE WHEN FINAL_SIGN_OUT_STATUS = 'SIGN_OUT_ABSENTEEISM' AND SIGN_IN_RECORD IS NOT NULL THEN 1
END) AS absent_num_of_sign_out,
</otherwise>
</choose>
SUM(CASE DAY_TYPE WHEN 'WORK' THEN PERIOD_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS period_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN PERIOD_LENGTH_DAY ELSE 0 END) AS period_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN WORK_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS work_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN WORK_LENGTH_DAY ELSE 0 END) AS work_length_day,
SUM(CASE DAY_TYPE WHEN 'HOLIDAY' THEN WORK_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS holiday_work_length_hour,
SUM(CASE DAY_TYPE WHEN 'HOLIDAY' THEN WORK_LENGTH_DAY ELSE 0 END) AS holiday_work_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ACTUAL_WORK_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS actual_work_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ACTUAL_WORK_LENGTH_DAY ELSE 0 END) AS actual_work_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ABSENCE_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS absence_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ABSENCE_LENGTH_DAY ELSE 0 END) AS absence_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN LATE_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS late_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN LATE_LENGTH_DAY ELSE 0 END) AS late_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_LATE_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
seriously_late_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_LATE_LENGTH_DAY ELSE 0 END) AS seriously_late_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN EARLY_OUT_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS early_out_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN EARLY_OUT_LENGTH_DAY ELSE 0 END) AS early_out_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_EARLY_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
seriously_early_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_EARLY_LENGTH_DAY ELSE 0 END) AS seriously_early_length_day,
<choose>
<when test="extraAbsenteeism == true">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN abs.ABSENTEEISM_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
absenteeism_length_hour,
</when>
<otherwise>
SUM(CASE DAY_TYPE WHEN 'WORK' THEN AAD.ABSENTEEISM_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
absenteeism_length_hour,
</otherwise>
</choose>
<choose>
<when test="extraAbsenteeism == true">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN abs.ABSENTEEISM_LENGTH_DAY ELSE 0 END) AS absenteeism_length_day,
</when>
<otherwise>
SUM(CASE DAY_TYPE WHEN 'WORK' THEN AAD.ABSENTEEISM_LENGTH_DAY ELSE 0 END) AS absenteeism_length_day,
</otherwise>
</choose>
<choose>
<when test="extraAbsenteeism == true">
<include refid="lostAbsenteeismLengthHourSql"/>,
<include refid="lostAbsenteeismLengthDaySql"/>,
</when>
<otherwise>
<include refid="lostLengthHourSql"/>,
<include refid="lostLengthDaySql"/>,
</otherwise>
</choose>
<include refid="lateEarlyCountLengthSql"/>,
<if test="hasDetailExtend == true">
SUM(ADE.salary_length_day) as salary_length_day,
SUM(ADE.salary_length_mesc)*1.00/3600000 as salary_length_hour,
SUM(ADE.meal_length_day) as meal_length_day,
SUM(ADE.meal_length_mesc)*1.00/3600000 as meal_length_hour,
SUM(ADE.out_sign_length_day) as out_sign_length_day,
SUM(ADE.out_sign_length_mesc)*1.00/3600000 as out_sign_length_hour,
COUNT(CASE WHEN ADE.osign_in_record is not null THEN 1 END) as osign_in_num,
COUNT(CASE WHEN ADE.osign_out_record is not null THEN 1 END) as osign_out_num,
</if>
COUNT(CASE WHEN FINAL_SIGN_IN_STATUS = 'SIGN_IN_ABSENCE' AND SIGN_OUT_RECORD IS NOT NULL THEN 1 END) AS
un_sign_in_num,
COUNT(CASE WHEN FINAL_SIGN_OUT_STATUS = 'SIGN_OUT_ABSENCE' AND SIGN_IN_RECORD IS NOT NULL THEN 1 END) AS
un_sign_out_num,
COUNT(CASE WHEN FINAL_SIGN_IN_STATUS = 'SIGN_IN_ABSENCE' AND SIGN_OUT_RECORD IS NULL THEN 1 END) AS un_sign_num
FROM ${param.e10_other_business}.ATTEND_STATUS_DETAIL ASD
LEFT JOIN ${param.e10_other_business}.attend_absence_detail AAD ON ASD.ID = AAD.ID and
ASD.delete_type=AAD.delete_type
<if test="extraAbsenteeism == true">
LEFT JOIN ${param.e10_other_business}.attend_absenteeism_detail abs on abs.id = ASD.id and abs.delete_type=0
</if>
<if test="hasDetailExtend == true">
LEFT JOIN ${param.e10_other_business}.attend_status_detail_extend ADE on ADE.id = ASD.id
</if>
WHERE ASD.TENANT_KEY = #{tenantKey} AND ASD.ATTEND_DATE BETWEEN #{beginDate} AND #{endDate} and
ASD.delete_type=0
<if test="empIds != null">
AND ASD.EMPLOYEE IN
<foreach collection="empIds" item="empId" index="index" separator="," open="(" close=")">#{empId}</foreach>
</if>
GROUP BY ASD.EMPLOYEE
</select>
</mapper>