Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39fee88bdd | ||
|
|
dd117937f0 | ||
|
|
2f88db00da | ||
|
|
ce60d0986f | ||
|
|
5f6fc4216b | ||
|
|
45da1138bf | ||
|
|
f07b0b7e16 | ||
|
|
8e7d331c65 | ||
|
|
0a87b28282 | ||
|
|
6b43aa02ae | ||
|
|
90622c0e0b |
@ -17,6 +17,26 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ulisesbocchio</groupId>
|
||||||
|
<artifactId>jasypt-spring-boot-starter</artifactId>
|
||||||
|
<version>3.0.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 新版 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>dingtalk</artifactId>
|
||||||
|
<version>2.2.43</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 旧版 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
@ -223,7 +243,6 @@
|
|||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${project.basedir}/src/main/resources/lib/k3cloud-webapi-sdk-java11-v8.2.0.jar</systemPath>
|
<systemPath>${project.basedir}/src/main/resources/lib/k3cloud-webapi-sdk-java11-v8.2.0.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
@ -241,6 +260,12 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-test</artifactId>
|
||||||
|
<version>3.3.3</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,6 +15,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@MapperScan({"com.evo.**.mapper.**.**"})
|
@MapperScan({"com.evo.**.mapper.**.**"})
|
||||||
|
@EnableAsync // 开启异步支持
|
||||||
public class EvoApplication
|
public class EvoApplication
|
||||||
{
|
{
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
|
|||||||
@ -125,4 +125,17 @@ public class RzAttendanceController extends BaseController
|
|||||||
{
|
{
|
||||||
return success(rzAttendanceDetailService.selectListByAttendanceId(id));
|
return success(rzAttendanceDetailService.selectListByAttendanceId(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Log(title = "考勤记录重新抓取", businessType = BusinessType.UPDATE)
|
||||||
|
@GetMapping(value = "/load/{id}")
|
||||||
|
public AjaxResult loadAttendance(@PathVariable("id") Long id){
|
||||||
|
return success(rzAttendanceService.loadAttendance(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Log(title = "考勤记录全部重新抓取", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping(value = "/load/all")
|
||||||
|
public AjaxResult loadAllAttendance(@RequestBody RzAttendance rzAttendance)
|
||||||
|
{
|
||||||
|
return rzAttendanceService.loadAllAttendance(rzAttendance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -120,5 +120,9 @@ public class RzAttendance extends BaseEntity {
|
|||||||
private Date startTime;
|
private Date startTime;
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private Date endTime;
|
private Date endTime;
|
||||||
|
/***
|
||||||
|
* 补卡扣款
|
||||||
|
*/
|
||||||
|
private BigDecimal debiting;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,8 @@ public class RzSalaryVo {
|
|||||||
|
|
||||||
@Excel(name = "姓名")
|
@Excel(name = "姓名")
|
||||||
private String name;
|
private String name;
|
||||||
|
@Excel(name = "身份证号")
|
||||||
|
private String idCard;
|
||||||
@Excel(name = "提成金额")
|
@Excel(name = "提成金额")
|
||||||
private BigDecimal sale;
|
private BigDecimal sale;
|
||||||
@Excel(name = "日期", width = 30, dateFormat = "yyyy-MM")
|
@Excel(name = "日期", width = 30, dateFormat = "yyyy-MM")
|
||||||
|
|||||||
@ -76,7 +76,14 @@ public interface PunchTheClockStrategyExchangeProcessor {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default String initMessage(Integer result, String meg){
|
default String initMessage(Integer result, String meg){
|
||||||
|
//需要返回的对象, 默认失败
|
||||||
|
return initStaticMessage(result, meg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String initStaticMessage(Integer result, String meg){
|
||||||
//需要返回的对象, 默认失败
|
//需要返回的对象, 默认失败
|
||||||
return JSONObject.toJSONString(new RzAttendanceVo(result, meg, null));
|
return JSONObject.toJSONString(new RzAttendanceVo(result, meg, null));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -101,11 +101,20 @@ public class KQDeviceExchangeProcessor implements PunchTheClockStrategyExchangeP
|
|||||||
//如果最后一条数据的卡类型为下班卡,则返回上班卡和加班卡权限 or 检查当前人员是否存在特殊加班中 或者 检查当前人员部门是否开启加班 or 暂时取消这个判定 当天打过加班卡 ( || rzAttendanceDetailMapper.checkOverTimeCard(sysStaff.getUserId(), new Date()) > 0)
|
//如果最后一条数据的卡类型为下班卡,则返回上班卡和加班卡权限 or 检查当前人员是否存在特殊加班中 或者 检查当前人员部门是否开启加班 or 暂时取消这个判定 当天打过加班卡 ( || rzAttendanceDetailMapper.checkOverTimeCard(sysStaff.getUserId(), new Date()) > 0)
|
||||||
if(ObjectUtils.isNotEmpty(eqOverStaffMapper.selectEqOverStaffByUserId(sysStaff.getUserId())) || ObjectUtils.isEmpty(sysDeptMapper.selectOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptId, sysStaff.getDeptId()).eq(SysDept::getIsOverTime,"1")))){
|
if(ObjectUtils.isNotEmpty(eqOverStaffMapper.selectEqOverStaffByUserId(sysStaff.getUserId())) || ObjectUtils.isEmpty(sysDeptMapper.selectOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptId, sysStaff.getDeptId()).eq(SysDept::getIsOverTime,"1")))){
|
||||||
//如果存在特殊加班, 或者当前部门没有开启加班 或者当天打过加班, 则无法打加班卡
|
//如果存在特殊加班, 或者当前部门没有开启加班 或者当天打过加班, 则无法打加班卡
|
||||||
return initMessage(0,"验证通过", "111000000");
|
// return initMessage(0,"验证通过", "111000000");
|
||||||
|
return initMessage(0,"验证通过", "000000000");
|
||||||
}
|
}
|
||||||
return initMessage(0,"验证通过", "111100000");
|
//检查最后一条打卡记录是否为钉钉的下班卡, 如果不存在禁止打加班卡
|
||||||
|
// return initMessage(0,"验证通过", "111100000");
|
||||||
|
return initMessage(0,"验证通过", "000100000");
|
||||||
}else{
|
}else{
|
||||||
|
//检查钉钉是否存在今天的下班卡, 和加班卡
|
||||||
|
if("加班卡".equals(rzAttendanceDetail.getButtonType())){
|
||||||
return initMessage(0,"验证通过", "000011000");
|
return initMessage(0,"验证通过", "000011000");
|
||||||
|
}else{
|
||||||
|
return initMessage(0,"验证通过", "000000000");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +159,6 @@ public class KQDeviceExchangeProcessor implements PunchTheClockStrategyExchangeP
|
|||||||
return initMessage(1, "当天已经打过加班卡");
|
return initMessage(1, "当天已经打过加班卡");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//员工考勤记录
|
//员工考勤记录
|
||||||
RzAttendance attendance = rzAttendanceMapper.queryNowDayAttendanceByStatisticalIdAndDate(Long.valueOf(userId),date);
|
RzAttendance attendance = rzAttendanceMapper.queryNowDayAttendanceByStatisticalIdAndDate(Long.valueOf(userId),date);
|
||||||
//如果当前打卡是下班卡, 并且当前员工考勤上班时间为空, 则判定为隔天打下班卡
|
//如果当前打卡是下班卡, 并且当前员工考勤上班时间为空, 则判定为隔天打下班卡
|
||||||
@ -212,11 +220,13 @@ public class KQDeviceExchangeProcessor implements PunchTheClockStrategyExchangeP
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Boolean checkToDayCard(String userId, String rules, Date date){
|
public Boolean checkToDayCard(String userId, String rules, Date date){
|
||||||
return ObjectUtils.isNotEmpty(rzAttendanceDetailService.getOne(new LambdaQueryWrapper<RzAttendanceDetail>()
|
//原位getOne, 修正钉钉打打卡后 会出现多条记录, 所以改为list
|
||||||
|
return ObjectUtils.isNotEmpty(rzAttendanceDetailService.list(new LambdaQueryWrapper<RzAttendanceDetail>()
|
||||||
.like(RzAttendanceDetail::getButtonType,"%"+rules+"%")
|
.like(RzAttendanceDetail::getButtonType,"%"+rules+"%")
|
||||||
.eq(RzAttendanceDetail::getStaffId, Long.valueOf(userId))
|
.eq(RzAttendanceDetail::getStaffId, Long.valueOf(userId))
|
||||||
.eq(RzAttendanceDetail::getDelFlag, Constants.DELETE_FLAG_0)
|
.eq(RzAttendanceDetail::getDelFlag, Constants.DELETE_FLAG_0)
|
||||||
.apply(" date_format(date_time,'%Y%m%d') = date_format({0},'%Y%m%d') ", date)));
|
.apply(" date_format(date_time,'%Y%m%d') = date_format({0},'%Y%m%d') ", date)
|
||||||
|
.orderByDesc(RzAttendanceDetail::getCreateTime)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
package com.evo.attendance.service;
|
package com.evo.attendance.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.evo.attendance.domain.RzAttendance;
|
||||||
import com.evo.attendance.domain.vo.RzAttendanceDetailVO;
|
import com.evo.attendance.domain.vo.RzAttendanceDetailVO;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.attendance.domain.RzAttendance;
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -62,4 +65,15 @@ public interface IRzAttendanceService extends IService<RzAttendance>
|
|||||||
RzAttendance selectRzAttendanceBySfIdAndNameAndTime(Long userId, String employeeName, String replacementTime,Boolean isAttendance);
|
RzAttendance selectRzAttendanceBySfIdAndNameAndTime(Long userId, String employeeName, String replacementTime,Boolean isAttendance);
|
||||||
|
|
||||||
public void sendAbnormalAttendance();
|
public void sendAbnormalAttendance();
|
||||||
|
|
||||||
|
public void dingDing(String dingUserId, String bizId, Long checkTime);
|
||||||
|
|
||||||
|
void addRzOverTime(String result, SysStaff sysStaff, DingShiftGroup dingsShiftGroup, String checkType, Date formatWorkDate, Date formatUserCheckTime, String timeResult, String remark, Double debiting, RzAttendance attendance);
|
||||||
|
|
||||||
|
public RzAttendance queryNowDayAttendanceByStatisticalIdAndDate(Long staffId, Date date);
|
||||||
|
|
||||||
|
public RzAttendance loadAttendance(Long id);
|
||||||
|
|
||||||
|
public AjaxResult loadAllAttendance(RzAttendance rzAttendance);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
package com.evo.attendance.service;
|
package com.evo.attendance.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.evo.attendance.domain.RzSpecialAttendance;
|
import com.evo.attendance.domain.RzSpecialAttendance;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,7 +13,7 @@ import java.util.List;
|
|||||||
* @author evo
|
* @author evo
|
||||||
* @date 2025-04-15
|
* @date 2025-04-15
|
||||||
*/
|
*/
|
||||||
public interface IRzSpecialAttendanceService
|
public interface IRzSpecialAttendanceService extends IService<RzSpecialAttendance>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 查询加班考勤记录
|
* 查询加班考勤记录
|
||||||
@ -51,4 +54,6 @@ public interface IRzSpecialAttendanceService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteRzSpecialAttendanceById(Long id);
|
public int deleteRzSpecialAttendanceById(Long id);
|
||||||
|
|
||||||
|
public RzSpecialAttendance selectRzSpecialAttendanceByUserIdAndDate(Long staffId, Date date);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ public class RzAttendanceDetailServiceImpl extends ServiceImpl<RzAttendanceDetai
|
|||||||
//.apply( " DATE_FORMAT(date_time,'%Y%m%d') = DATE_FORMAT({0},'%Y%m%d')", date)
|
//.apply( " DATE_FORMAT(date_time,'%Y%m%d') = DATE_FORMAT({0},'%Y%m%d')", date)
|
||||||
//以下为特殊规则, 只针对下班卡起作用
|
//以下为特殊规则, 只针对下班卡起作用
|
||||||
.orderByAsc("下班卡".equals(rules), RzAttendanceDetail::getDateTime)
|
.orderByAsc("下班卡".equals(rules), RzAttendanceDetail::getDateTime)
|
||||||
.last("下班卡".equals(rules)," limit 1 ")
|
.last(" limit 1 ")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,11 +141,6 @@ public class RzAttendanceDetailServiceImpl extends ServiceImpl<RzAttendanceDetai
|
|||||||
data.setIcon(timeLine.icon);
|
data.setIcon(timeLine.icon);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
//
|
|
||||||
// return getBaseMapper().selectListByAttendanceId(new LambdaQueryWrapper<RzAttendanceDetail>().eq(RzAttendanceDetail::getAttendanceId, attId)
|
|
||||||
// .select(RzAttendanceDetail::getButtonType, RzAttendanceDetail::getPhoto, RzAttendanceDetail::getDateTime,RzAttendanceDetail::getDelFlag)).stream().map(data ->{
|
|
||||||
// return new RzAttendanceDetailTimeLineVO(data.getButtonType(), data.getPhoto(), DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",data.getDateTime()), data.getDelFlag());
|
|
||||||
// }).collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");
|
SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package com.evo.attendance.service.impl;
|
package com.evo.attendance.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
@ -13,16 +16,23 @@ import com.evo.attendance.service.RzAttendanceDetailService;
|
|||||||
import com.evo.common.annotation.DataScope;
|
import com.evo.common.annotation.DataScope;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.common.core.domain.entity.SysDept;
|
import com.evo.common.core.domain.entity.SysDept;
|
||||||
import com.evo.common.utils.Collections;
|
import com.evo.common.handler.thread.RzAttendanceBatchHandler;
|
||||||
import com.evo.common.utils.DateUtils;
|
import com.evo.common.utils.*;
|
||||||
import com.evo.common.utils.SecurityUtils;
|
import com.evo.ding.DingUtils;
|
||||||
import com.evo.common.utils.StringUtils;
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.ding.mapper.DingShiftGroupMapper;
|
||||||
|
import com.evo.ding.mapper.DingShiftMapper;
|
||||||
import com.evo.equipment.service.IEqImagesService;
|
import com.evo.equipment.service.IEqImagesService;
|
||||||
|
import com.evo.personnelMatters.service.IRzOverTimeService;
|
||||||
import com.evo.system.domain.SysStaff;
|
import com.evo.system.domain.SysStaff;
|
||||||
import com.evo.system.mapper.SysDeptMapper;
|
import com.evo.system.mapper.SysDeptMapper;
|
||||||
import com.evo.system.mapper.SysStaffMapper;
|
import com.evo.system.mapper.SysStaffMapper;
|
||||||
import com.evo.system.service.ISysStaffService;
|
import com.evo.system.service.ISysStaffService;
|
||||||
import com.evo.wechat.service.SendClientService;
|
import com.evo.wechat.service.SendClientService;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
@ -31,6 +41,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -56,6 +67,13 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
|
|||||||
private SendClientService sendClientService;
|
private SendClientService sendClientService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysStaffMapper sysStaffMapper;
|
private SysStaffMapper sysStaffMapper;
|
||||||
|
@Autowired
|
||||||
|
private DingShiftGroupMapper dingsShiftGroupMapper;
|
||||||
|
@Autowired
|
||||||
|
private DingShiftMapper dingsShiftMapper;
|
||||||
|
@Resource
|
||||||
|
private RzAttendanceBatchHandler dataBatchHandler;
|
||||||
|
|
||||||
|
|
||||||
private static final String MORNING_CARD_SINGLE = "上班卡(单班制)";
|
private static final String MORNING_CARD_SINGLE = "上班卡(单班制)";
|
||||||
private static final String MORNING_CARD_DOUBLE = "上班卡(双班制)";
|
private static final String MORNING_CARD_DOUBLE = "上班卡(双班制)";
|
||||||
@ -131,6 +149,19 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int attendenceCount() {
|
public int attendenceCount() {
|
||||||
|
// Map<String, String> addressMap = ParamUtils.checkKqAddressCount();
|
||||||
|
// Map<String, Integer> resultMap = Collections.emptyMap();
|
||||||
|
// ObjectMapper mapper = new ObjectMapper();
|
||||||
|
// addressMap.keySet().stream().forEach(key -> {
|
||||||
|
// try {
|
||||||
|
// Map<String, String> limitMap = mapper.readValue(addressMap.get(key), new TypeReference<Map<String, String>>() {});
|
||||||
|
// limitMap.get()
|
||||||
|
// resultMap.put(key, getBaseMapper().attendenceCount())
|
||||||
|
// } catch (JsonProcessingException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
List<RzAttendance> list = getBaseMapper().attendenceCount();
|
List<RzAttendance> list = getBaseMapper().attendenceCount();
|
||||||
return list.size();
|
return list.size();
|
||||||
}
|
}
|
||||||
@ -479,7 +510,7 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
|
|||||||
try {
|
try {
|
||||||
for (SysStaff sysStaff : sysStaffService.selectSysStaffListAll()){
|
for (SysStaff sysStaff : sysStaffService.selectSysStaffListAll()){
|
||||||
Date date = DateUtils.addDays(new Date(), -1);
|
Date date = DateUtils.addDays(new Date(), -1);
|
||||||
RzAttendance beforeAttendance = getBaseMapper().queryNowDayAttendanceByStatisticalIdAndDate(sysStaff.getUserId(), date);
|
RzAttendance beforeAttendance = queryNowDayAttendanceByStatisticalIdAndDate(sysStaff.getUserId(), date);
|
||||||
if(beforeAttendance.getWorkStartTime() != null && beforeAttendance.getWorkEndTime() == null){
|
if(beforeAttendance.getWorkStartTime() != null && beforeAttendance.getWorkEndTime() == null){
|
||||||
sendAbnormalAttendance(sysStaff, beforeAttendance.getWorkStartTime());
|
sendAbnormalAttendance(sysStaff, beforeAttendance.getWorkStartTime());
|
||||||
|
|
||||||
@ -505,8 +536,202 @@ public class RzAttendanceServiceImpl extends ServiceImpl<RzAttendanceMapper, RzA
|
|||||||
log.error("查询前一天的打卡情况报错了");
|
log.error("查询前一天的打卡情况报错了");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
@Async("asyncExecutor")
|
||||||
|
public void dingDing(String dingUserId, String bizId, Long checkTime) {
|
||||||
|
//此处需要保证, 所有的员工必须存在dingUserId
|
||||||
|
SysStaff sysStaff = sysStaffMapper.selectSysStaffByDingUserId(dingUserId);//打卡记录信息
|
||||||
|
if(sysStaff != null){
|
||||||
|
String result = DingUtils.getListRecord(Collections.asList(dingUserId), DateUtils.parseDateToStr("yyyy-MM-dd", new Date(checkTime))+" 00:00:00", DateUtils.parseDateToStr("yyyy-MM-dd", new Date(checkTime))+" 23:59:59");
|
||||||
|
System.out.println("打卡结果===>"+result);
|
||||||
|
JSONObject resultJson = JSON.parseObject(result);
|
||||||
|
if(Integer.valueOf(0).equals(resultJson.getInteger("errcode")))
|
||||||
|
try {
|
||||||
|
{
|
||||||
|
JSONArray jsonArray = resultJson.getJSONArray("recordresult");
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JSONObject ob = jsonArray.getJSONObject(i);
|
||||||
|
if(bizId.equals(ob.getString("bizId"))){
|
||||||
|
calculationAddRzOverTime(result, sysStaff, ob, null);
|
||||||
|
// //打卡类型
|
||||||
|
// String checkType = ob.getString("checkType");
|
||||||
|
// //考勤组
|
||||||
|
// String groupId = ob.getString("groupId");
|
||||||
|
// //排班时间
|
||||||
|
// Long planCheckTime = ob.getLong("planCheckTime");
|
||||||
|
// // 格式化:先转Date对象,再格式化
|
||||||
|
// String formatPlanCheckTime = DateUtils.parseDateToStr("HH:mm:ss", new Date(planCheckTime));
|
||||||
|
// //用户打卡时间
|
||||||
|
// Long userCheckTime = ob.getLong("userCheckTime");
|
||||||
|
// //工作时间 (这里指的是哪一天的卡)
|
||||||
|
// Long workDate = ob.getLong("workDate");
|
||||||
|
// /***
|
||||||
|
// * 打卡结果
|
||||||
|
// * Normal:正常
|
||||||
|
// * Early:早退
|
||||||
|
// * Late:迟到
|
||||||
|
// * SeriousLate:严重迟到
|
||||||
|
// * Absenteeism:旷工迟到
|
||||||
|
// * NotSigned:未打卡
|
||||||
|
// */
|
||||||
|
// String timeResult = ob.getString("timeResult");
|
||||||
|
//
|
||||||
|
// Date formatWorkDate = Date.from(Instant.ofEpochMilli(workDate));
|
||||||
|
// Date formatUserCheckTime = Date.from(Instant.ofEpochMilli(userCheckTime));
|
||||||
|
// DingShiftGroup dingsShiftGroup = dingsShiftGroupMapper.selectByGroupIdAndTypeAndCheckTime(groupId, checkType, formatPlanCheckTime);
|
||||||
|
// addRzOverTime(result, sysStaff, dingsShiftGroup, checkType, formatWorkDate, formatUserCheckTime, timeResult, null, 0d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("处理钉钉打卡出现异常, 异常原因是==>>{}, 打卡结果是=====>>>>> {}", e.getMessage(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRzOverTime(String result, SysStaff sysStaff, DingShiftGroup dingsShiftGroup, String checkType, Date formatWorkDate, Date formatUserCheckTime, String timeResult, String remark, Double debiting,RzAttendance attendance){
|
||||||
|
if(dingsShiftGroup != null){
|
||||||
|
//通过打卡类型, classId, 和排班打卡时间, 获取工作时长
|
||||||
|
//通过班次id拿到工作时长
|
||||||
|
DingShift dingsShift = dingsShiftMapper.selectByDingId(dingsShiftGroup.getShiftId());
|
||||||
|
//通过workDate 获取哪一天的卡
|
||||||
|
if(attendance == null){
|
||||||
|
attendance = queryNowDayAttendanceByStatisticalIdAndDate(sysStaff.getUserId(),formatWorkDate);
|
||||||
|
}
|
||||||
|
//生成打卡记录
|
||||||
|
rzAttendanceDetailService.addDetail(attendance, ("OnDuty".equals(checkType) ? "上班卡" : "下班卡"), "/", formatUserCheckTime, StringUtils.isEmpty(remark) ? "钉钉打卡" : remark, "");
|
||||||
|
//上班
|
||||||
|
if("OnDuty".equals(checkType)){
|
||||||
|
attendance.setRules("上班卡");
|
||||||
|
attendance.setWorkStartTime(formatUserCheckTime);
|
||||||
|
if(!"Normal".equals(timeResult)){
|
||||||
|
attendance.setYcsFlag("1");
|
||||||
|
}
|
||||||
|
}else if("OffDuty".equals(checkType)){
|
||||||
|
attendance.setWorkEndTime(formatUserCheckTime);
|
||||||
|
if("Normal".equals(timeResult) && !"1".equals(attendance.getYcsFlag()) && attendance.getWorkStartTime() != null){
|
||||||
|
attendance.setWorkSum(BigDecimal.valueOf(dingsShift.getWorkHour()));
|
||||||
|
}else{
|
||||||
|
//早退需要计算工时
|
||||||
|
if(attendance.getWorkStartTime() != null){
|
||||||
|
Long hours = (attendance.getWorkEndTime().getTime() - attendance.getWorkStartTime().getTime())/1000/60/60;
|
||||||
|
attendance.setWorkSum((BigDecimal.valueOf(dingsShift.getWorkHour()).compareTo(BigDecimal.valueOf(hours)) < 0) ? BigDecimal.valueOf(dingsShift.getWorkHour()) : BigDecimal.valueOf(hours));
|
||||||
|
}else {
|
||||||
|
attendance.setWorkSum(DataUtils.DEFAULT_VALUE);
|
||||||
|
}
|
||||||
|
if(!"Normal".equals(timeResult)){
|
||||||
|
attendance.setYcxFlag("1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
log.error("钉钉打卡=====>>>>>>>>>>>>>>>>>> 出现未知打卡类型, 当前打卡类型");
|
||||||
|
//终止继续执行
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//判断打卡时间, 添加夜班次数 打卡时间在晚上7点以后
|
||||||
|
if(dingsShift.getWorkHour() == 12 && attendance.getWorkSum().intValue() >= 12 && attendance.getWorkStartTime()!= null && attendance.getWorkStartTime().getHours() > 12){
|
||||||
|
attendance.setNightNumber(1);
|
||||||
|
//必须是8小时倒班制or单班制, 并且工作时长>=8小时, 并且 上班打开时间在12点至21点 算作中班 -- 2026-02-04 因1月份张克龙中班考勤问题, 刘杰面谈
|
||||||
|
}else if(dingsShift.getWorkHour() == 8 && attendance.getWorkSum().intValue() >= 8 && attendance.getWorkStartTime() != null && attendance.getWorkStartTime().getHours() >= 12 && attendance.getWorkStartTime().getHours() < 21){
|
||||||
|
attendance.setMiddleShiftNumber(1);
|
||||||
|
}
|
||||||
|
//记录补卡扣款
|
||||||
|
attendance.setDebiting(DataUtils.findDefaultValue(attendance.getDebiting(), DataUtils.DEFAULT_VALUE).add(new BigDecimal(DataUtils.findDefaultValue(debiting, 0d))));
|
||||||
|
getBaseMapper().updateRzAttendance(attendance);
|
||||||
|
//检查是否开启加班, 所有的加班调整为, 扫脸打卡
|
||||||
|
// if(dingsShift.getOvertimeWork()){
|
||||||
|
// //使用排班下班时间作为加班开始时间
|
||||||
|
// rzOverTimeService.overTimeCard(sysStaff, DateUtils.parseDate(DateUtils.parseDateToStr("yyyy-MM-dd", formatWorkDate)+" "+ dingsShiftGroup.getCheckTime()));
|
||||||
|
// //员工打卡时间作为加班下班时间
|
||||||
|
// rzOverTimeService.overTimeOffDutyCard(sysStaff, formatUserCheckTime, "/");
|
||||||
|
// }
|
||||||
|
}else{
|
||||||
|
log.info("钉钉回调打卡信息=====>>>>> {}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzAttendance queryNowDayAttendanceByStatisticalIdAndDate(Long staffId, Date date) {
|
||||||
|
return getBaseMapper().queryNowDayAttendanceByStatisticalIdAndDate(staffId,date);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzAttendance loadAttendance(Long id) {
|
||||||
|
RzAttendance attendance = getById(id);
|
||||||
|
SysStaff sysStaff = sysStaffMapper.selectById(attendance.getStaffId());
|
||||||
|
if(StringUtils.isNotEmpty(sysStaff.getDingUserId())){
|
||||||
|
String result = DingUtils.getListRecord(Collections.asList(sysStaff.getDingUserId()), DateUtils.parseDateToStr("yyyy-MM-dd", attendance.getAttendanceDate())+" 00:00:00", DateUtils.parseDateToStr("yyyy-MM-dd", attendance.getAttendanceDate())+" 23:59:59");
|
||||||
|
JSONObject resultJson = JSON.parseObject(result);
|
||||||
|
if(Integer.valueOf(0).equals(resultJson.getInteger("errcode")))
|
||||||
|
try {
|
||||||
|
JSONArray jsonArray = resultJson.getJSONArray("recordresult");
|
||||||
|
JSONObject onDutyObject = (JSONObject) jsonArray.stream().filter(data -> "OnDuty".equals(((JSONObject)data).getString("checkType"))).findFirst().orElse(null);
|
||||||
|
if(onDutyObject != null){
|
||||||
|
calculationAddRzOverTime(result, sysStaff, onDutyObject, attendance);
|
||||||
|
}
|
||||||
|
JSONObject offDutyObject = (JSONObject) jsonArray.stream().filter(data -> "OffDuty".equals(((JSONObject)data).getString("checkType"))).findFirst().orElse(null);
|
||||||
|
if(offDutyObject != null){
|
||||||
|
calculationAddRzOverTime(result, sysStaff, offDutyObject, attendance);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("重新抓取钉钉考勤结果异常, 异常原因是==>>{}, 打卡结果是=====>>>>> {}", e.getMessage(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attendance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AjaxResult loadAllAttendance(RzAttendance rzAttendance) {
|
||||||
|
if (StringUtils.isNull(rzAttendance.getAttendanceDate())) {
|
||||||
|
return AjaxResult.error("请选择需要重新抓取的月份!!");
|
||||||
|
}
|
||||||
|
dataBatchHandler.batchProcess(rzAttendance.getAttendanceDate(), (result, sysStaff, ob, attendance) -> {
|
||||||
|
// 调用你当前 ServiceImpl 里的方法
|
||||||
|
try {
|
||||||
|
this.calculationAddRzOverTime(result, sysStaff, ob, attendance);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("刷新用户===>>{}, 出现异常, 异常原因为====>{}", JSONObject.toJSONString(sysStaff), e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculationAddRzOverTime(String result ,SysStaff sysStaff, JSONObject ob, RzAttendance attendance){
|
||||||
|
//打卡类型
|
||||||
|
String checkType = ob.getString("checkType");
|
||||||
|
//考勤组
|
||||||
|
String groupId = ob.getString("groupId");
|
||||||
|
//
|
||||||
|
String shiftId = ob.getString("classId");
|
||||||
|
//排班时间
|
||||||
|
Long planCheckTime = ob.getLong("planCheckTime");
|
||||||
|
// 格式化:先转Date对象,再格式化
|
||||||
|
String formatPlanCheckTime = DateUtils.parseDateToStr("HH:mm:ss", new Date(planCheckTime));
|
||||||
|
//用户打卡时间
|
||||||
|
Long userCheckTime = ob.getLong("userCheckTime");
|
||||||
|
//工作时间 (这里指的是哪一天的卡)
|
||||||
|
Long workDate = ob.getLong("workDate");
|
||||||
|
/***
|
||||||
|
* 打卡结果
|
||||||
|
* Normal:正常
|
||||||
|
* Early:早退
|
||||||
|
* Late:迟到
|
||||||
|
* SeriousLate:严重迟到
|
||||||
|
* Absenteeism:旷工迟到
|
||||||
|
* NotSigned:未打卡
|
||||||
|
*/
|
||||||
|
String timeResult = ob.getString("timeResult");
|
||||||
|
|
||||||
|
Date formatWorkDate = Date.from(Instant.ofEpochMilli(workDate));
|
||||||
|
Date formatUserCheckTime = Date.from(Instant.ofEpochMilli(userCheckTime));
|
||||||
|
DingShiftGroup dingsShiftGroup = dingsShiftGroupMapper.selectByGroupIdAndTypeAndCheckTime(groupId, shiftId, checkType, formatPlanCheckTime);
|
||||||
|
addRzOverTime(result, sysStaff, dingsShiftGroup, checkType, formatWorkDate, formatUserCheckTime, timeResult, null, 0d, attendance);
|
||||||
|
}
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
protected void sendAbnormalAttendance(SysStaff sysStaff, Date date){
|
protected void sendAbnormalAttendance(SysStaff sysStaff, Date date){
|
||||||
|
|||||||
@ -171,16 +171,21 @@ public class RzAttendanceStatisticalServiceImpl extends ServiceImpl<RzAttendance
|
|||||||
RzAttendanceStatistical rzAttendanceStatistical = getBaseMapper().getRzAttendanceStatisticalByDateAndName(sysStaff.getUserId(),date);
|
RzAttendanceStatistical rzAttendanceStatistical = getBaseMapper().getRzAttendanceStatisticalByDateAndName(sysStaff.getUserId(),date);
|
||||||
if(StringUtils.isNotNull(rzAttendanceStatistical)){
|
if(StringUtils.isNotNull(rzAttendanceStatistical)){
|
||||||
//判断名称和部门是否一样。不一样操作修改
|
//判断名称和部门是否一样。不一样操作修改
|
||||||
if(!rzAttendanceStatistical.getName().equals(sysStaff.getName()) || rzAttendanceStatistical.getDeptId() != sysStaff.getDeptId()){
|
//if(!rzAttendanceStatistical.getName().equals(sysStaff.getName()) || rzAttendanceStatistical.getDeptId() != sysStaff.getDeptId()){
|
||||||
|
if(!rzAttendanceStatistical.getName().equals(sysStaff.getName())){
|
||||||
//修改部门和姓名
|
//修改部门和姓名
|
||||||
rzAttendanceStatistical.setName(sysStaff.getName());
|
rzAttendanceStatistical.setName(sysStaff.getName());
|
||||||
|
if(rzAttendanceStatistical.getDeptId() == null){
|
||||||
rzAttendanceStatistical.setDeptId(sysStaff.getDeptId());
|
rzAttendanceStatistical.setDeptId(sysStaff.getDeptId());
|
||||||
|
}
|
||||||
getBaseMapper().updateRzAttendanceStatistical(rzAttendanceStatistical);
|
getBaseMapper().updateRzAttendanceStatistical(rzAttendanceStatistical);
|
||||||
//查询考勤详情修改
|
//查询考勤详情修改
|
||||||
List<RzAttendance> kq_list = rzAttendanceMapper.queryMonthAttendanceByStaffId(sysStaff.getUserId(),new Date());
|
List<RzAttendance> kq_list = rzAttendanceMapper.queryMonthAttendanceByStaffId(sysStaff.getUserId(),new Date());
|
||||||
//循环修改信息
|
//循环修改信息
|
||||||
for (RzAttendance rzAttendance : kq_list) {
|
for (RzAttendance rzAttendance : kq_list) {
|
||||||
|
if(rzAttendanceStatistical.getDeptId() == null){
|
||||||
rzAttendance.setDeptId(sysStaff.getDeptId());
|
rzAttendance.setDeptId(sysStaff.getDeptId());
|
||||||
|
}
|
||||||
rzAttendance.setName(sysStaff.getName());
|
rzAttendance.setName(sysStaff.getName());
|
||||||
rzAttendanceMapper.updateRzAttendance(rzAttendance);
|
rzAttendanceMapper.updateRzAttendance(rzAttendance);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.evo.attendance.domain.RzAttendanceStatistical;
|
import com.evo.attendance.domain.RzAttendanceStatistical;
|
||||||
import com.evo.attendance.domain.RzSpecialAttendance;
|
import com.evo.attendance.domain.RzSpecialAttendance;
|
||||||
import com.evo.attendance.domain.RzSpecialOverTime;
|
import com.evo.attendance.domain.RzSpecialOverTime;
|
||||||
@ -23,7 +24,7 @@ import javax.annotation.Resource;
|
|||||||
* @date 2025-04-15
|
* @date 2025-04-15
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class RzSpecialAttendanceServiceImpl implements IRzSpecialAttendanceService
|
public class RzSpecialAttendanceServiceImpl extends ServiceImpl<RzSpecialAttendanceMapper, RzSpecialAttendance> implements IRzSpecialAttendanceService
|
||||||
{
|
{
|
||||||
@Resource
|
@Resource
|
||||||
private RzSpecialAttendanceMapper rzSpecialAttendanceMapper;
|
private RzSpecialAttendanceMapper rzSpecialAttendanceMapper;
|
||||||
@ -131,4 +132,9 @@ public class RzSpecialAttendanceServiceImpl implements IRzSpecialAttendanceServi
|
|||||||
rzAttendanceStatistical.setOverTimeHours(rzAttendanceStatistical.getOverTimeHours().subtract(rzSpecialAttendance.getWorkHours()));
|
rzAttendanceStatistical.setOverTimeHours(rzAttendanceStatistical.getOverTimeHours().subtract(rzSpecialAttendance.getWorkHours()));
|
||||||
return rzAttendanceStatisticalMapper.updateRzAttendanceStatistical(rzAttendanceStatistical);
|
return rzAttendanceStatisticalMapper.updateRzAttendanceStatistical(rzAttendanceStatistical);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzSpecialAttendance selectRzSpecialAttendanceByUserIdAndDate(Long staffId, Date date) {
|
||||||
|
return getBaseMapper().selectRzSpecialAttendanceByUserIdAndDate(staffId, date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.evo.common.constant.CacheConstants;
|
||||||
import com.evo.common.utils.DateUtils;
|
import com.evo.common.utils.DateUtils;
|
||||||
import com.evo.common.utils.SecurityUtils;
|
import com.evo.common.utils.SecurityUtils;
|
||||||
import com.evo.equipment.constant.Constants;
|
import com.evo.equipment.constant.Constants;
|
||||||
@ -103,6 +104,7 @@ public class RzSysParamServiceImpl extends ServiceImpl<RzSysParamMapper, RzSysPa
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
// @Cacheable(cacheNames = Constants.SYS_RUNNING_PARAMS, key = "#code")
|
||||||
public RzSysParam getRzSysParam(String name, String code, String defVal, String des){
|
public RzSysParam getRzSysParam(String name, String code, String defVal, String des){
|
||||||
RzSysParam param = getRzSysParam(code);
|
RzSysParam param = getRzSysParam(code);
|
||||||
if(ObjectUtils.isEmpty(param)){
|
if(ObjectUtils.isEmpty(param)){
|
||||||
@ -116,7 +118,7 @@ public class RzSysParamServiceImpl extends ServiceImpl<RzSysParamMapper, RzSysPa
|
|||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@Cacheable(cacheNames = Constants.SYS_RUNNING_PARAMS, key = "#code")
|
// @Cacheable(cacheNames = Constants.SYS_RUNNING_PARAMS, key = "#code")
|
||||||
public RzSysParam getRzSysParam(String code){
|
public RzSysParam getRzSysParam(String code){
|
||||||
return getOne(new LambdaQueryWrapper<RzSysParam>().eq(RzSysParam::getParamCode, code));
|
return getOne(new LambdaQueryWrapper<RzSysParam>().eq(RzSysParam::getParamCode, code));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
package com.evo.common.async;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
/**
|
||||||
|
* AsyncConfig
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:AsyncConfig
|
||||||
|
* @date: 2026年03月05日 8:48
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
//@EnableAsync
|
||||||
|
public class AsyncConfig {
|
||||||
|
|
||||||
|
@Value("${yt.async.corePoolSize:'5'}")
|
||||||
|
private Integer corePoolSize;
|
||||||
|
@Value("${yt.async.maxPoolSize:'10'}")
|
||||||
|
private Integer maxPoolSize;
|
||||||
|
@Value("${yt.async.queueCapacity:'20'}")
|
||||||
|
private Integer queueCapacity;
|
||||||
|
@Value("${yt.async.keepAliveSeconds:'60'}")
|
||||||
|
private Integer keepAliveSeconds;
|
||||||
|
|
||||||
|
|
||||||
|
@Bean("asyncExecutor") // 自定义线程池名称
|
||||||
|
public Executor asyncExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
// 核心线程数
|
||||||
|
executor.setCorePoolSize(corePoolSize);
|
||||||
|
// 最大线程数
|
||||||
|
executor.setMaxPoolSize(maxPoolSize);
|
||||||
|
// 队列容量
|
||||||
|
executor.setQueueCapacity(queueCapacity);
|
||||||
|
// 线程空闲超时时间
|
||||||
|
executor.setKeepAliveSeconds(keepAliveSeconds);
|
||||||
|
// 线程名称前缀
|
||||||
|
executor.setThreadNamePrefix("async-thread-");
|
||||||
|
// 拒绝策略(队列满+最大线程数满时的处理方式)
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
// 初始化
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.evo.common.config.thread;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
/**
|
||||||
|
* SpringBoot 动态安全线程池(生产级)
|
||||||
|
* @ClassName:DynamicThreadPoolConfig
|
||||||
|
* @date: 2026年04月25日 15:00
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class DynamicThreadPoolConfig {
|
||||||
|
|
||||||
|
private final ThreadPoolProperties poolProperties;
|
||||||
|
|
||||||
|
public DynamicThreadPoolConfig(ThreadPoolProperties poolProperties) {
|
||||||
|
this.poolProperties = poolProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "dataBatchThreadPool")
|
||||||
|
public ThreadPoolTaskExecutor dataBatchThreadPool() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
|
||||||
|
// 基础配置
|
||||||
|
executor.setCorePoolSize(poolProperties.getCorePoolSize());
|
||||||
|
executor.setMaxPoolSize(poolProperties.getMaxPoolSize());
|
||||||
|
executor.setQueueCapacity(poolProperties.getQueueCapacity());
|
||||||
|
executor.setKeepAliveSeconds(poolProperties.getKeepAliveSeconds());
|
||||||
|
executor.setThreadNamePrefix(poolProperties.getThreadNamePrefix());
|
||||||
|
|
||||||
|
// 核心线程允许超时回收
|
||||||
|
executor.setAllowCoreThreadTimeOut(true);
|
||||||
|
|
||||||
|
// 自定义线程工厂(异常捕获)
|
||||||
|
executor.setThreadFactory(new ThreadFactory() {
|
||||||
|
private final AtomicLong num = new AtomicLong(1);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread thread = new Thread(r);
|
||||||
|
thread.setName(poolProperties.getThreadNamePrefix() + num.getAndIncrement());
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.setUncaughtExceptionHandler((t, e) ->
|
||||||
|
System.err.println("线程异常:" + t.getName() + "," + e.getMessage())
|
||||||
|
);
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 拒绝策略:阻塞入队,不丢任务
|
||||||
|
executor.setRejectedExecutionHandler((r, e) -> {
|
||||||
|
if (!e.isShutdown()) {
|
||||||
|
try {
|
||||||
|
e.getQueue().put(r);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 优雅关闭
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
executor.setAwaitTerminationSeconds(60);
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.evo.common.config.thread;
|
||||||
|
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
/**
|
||||||
|
* 线程池工具类(静态调用)
|
||||||
|
* @ClassName:ThreadPoolManager
|
||||||
|
* @date: 2026年04月25日 15:02
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ThreadPoolManager {
|
||||||
|
|
||||||
|
private static ThreadPoolTaskExecutor executor;
|
||||||
|
|
||||||
|
@Resource(name = "dataBatchThreadPool")
|
||||||
|
public void setExecutor(ThreadPoolTaskExecutor executor) {
|
||||||
|
ThreadPoolManager.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交任务
|
||||||
|
public static void execute(Runnable task) {
|
||||||
|
executor.execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态修改核心线程
|
||||||
|
public static void setCorePoolSize(int size) {
|
||||||
|
executor.setCorePoolSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态修改最大线程
|
||||||
|
public static void setMaxPoolSize(int size) {
|
||||||
|
executor.setMaxPoolSize(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.evo.common.config.thread;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc:
|
||||||
|
* @ClassName:ThreadPoolProperties
|
||||||
|
* @date: 2026年04月25日 14:57
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "thread.pool")
|
||||||
|
public class ThreadPoolProperties {
|
||||||
|
private Integer corePoolSize;
|
||||||
|
private Integer maxPoolSize;
|
||||||
|
private Integer keepAliveSeconds;
|
||||||
|
private Integer queueCapacity;
|
||||||
|
private String threadNamePrefix;
|
||||||
|
private Integer batchSize; // 每线程处理条数
|
||||||
|
}
|
||||||
@ -133,4 +133,9 @@ public class Constants
|
|||||||
|
|
||||||
public static final BigDecimal DAY_WORK_HOUR = new BigDecimal(8);
|
public static final BigDecimal DAY_WORK_HOUR = new BigDecimal(8);
|
||||||
|
|
||||||
|
|
||||||
|
public static final String SOURCE_PT = "1";
|
||||||
|
public static final String SOURCE_DING = "2";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,113 @@
|
|||||||
|
package com.evo.common.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.attendance.service.IRzAttendanceService;
|
||||||
|
import com.evo.common.core.controller.BaseController;
|
||||||
|
import com.evo.ding.DingGlobalParams;
|
||||||
|
import com.evo.ding.DingCallbackCrypto;
|
||||||
|
import com.evo.ding.processor.instance.InstanceChangeExchangeProcessor;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallbackController
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:CallbackController
|
||||||
|
* @date: 2026年03月04日 11:27
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/callback")
|
||||||
|
@Slf4j
|
||||||
|
public class CallbackController extends BaseController {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
IRzAttendanceService rzAttendanceService;
|
||||||
|
@Autowired
|
||||||
|
List<InstanceChangeExchangeProcessor> instanceChangeExchangeProcessorList;
|
||||||
|
@Autowired
|
||||||
|
List<DingCallBackExchangeProcessor> dingCallBackExchangeProcessorList;
|
||||||
|
@PostMapping("/ding/clock")
|
||||||
|
public Map<String, String> dingDingClock(@RequestBody Map<String, Object> params){
|
||||||
|
log.info(JSONObject.toJSONString(params));
|
||||||
|
try {
|
||||||
|
// 1. 从http请求中获取加解密参数
|
||||||
|
|
||||||
|
// 2. 使用加解密类型
|
||||||
|
// 2、调用订阅事件接口订阅的事件为企业级事件推送,此时OWNER_KEY为:开发者后台应用的Client ID(原企业内部应用 appKey )
|
||||||
|
DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(DingGlobalParams.getToken(), DingGlobalParams.getAesKey(), DingGlobalParams.getClientId());
|
||||||
|
String encryptMsg = String.valueOf(params.get("encrypt"));
|
||||||
|
String decryptMsg = callbackCrypto.getDecryptMsg(String.valueOf(params.get("msg_signature")), String.valueOf(params.get("timestamp")), String.valueOf(params.get("nonce")), encryptMsg);
|
||||||
|
|
||||||
|
log.info("==============>"+decryptMsg);
|
||||||
|
// 3. 反序列化回调事件json数据
|
||||||
|
JSONObject eventJson = JSON.parseObject(decryptMsg);
|
||||||
|
String eventType = eventJson.getString("EventType");
|
||||||
|
log.info("发生了:" + eventType + "事件");
|
||||||
|
for (DingCallBackExchangeProcessor processor : dingCallBackExchangeProcessorList) {
|
||||||
|
if (processor.accept(eventType)) {
|
||||||
|
processor.exchange(eventJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 根据EventType分类处理
|
||||||
|
// if ("check_url".equals(eventType)) {
|
||||||
|
// log.info("打卡回调");
|
||||||
|
// } else if ("attendance_check_record".equals(eventType)) { //打卡推送
|
||||||
|
// JSONArray dataList = eventJson.getJSONArray("DataList");
|
||||||
|
// if(dataList!= null && dataList.size() > 0){
|
||||||
|
// JSONObject jsonObject = dataList.getJSONObject(0);
|
||||||
|
// String userId = jsonObject.getString("userId");
|
||||||
|
// if(StringUtils.isNotEmpty(userId)){
|
||||||
|
// rzAttendanceService.dingDing(userId, jsonObject.getString("bizId"));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// //审批实例订阅
|
||||||
|
// }else if ("bpms_instance_change".equals(eventType)) {
|
||||||
|
// log.info("审批实例订阅回调");
|
||||||
|
// for (InstanceChangeExchangeProcessor processor : instanceChangeExchangeProcessorList) {
|
||||||
|
// if (processor.accept(eventJson.getString("processCode"))) {
|
||||||
|
// processor.exchange(eventJson);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // 审批任务订阅
|
||||||
|
// }else if ("bpms_task_change".equals(eventType)) {
|
||||||
|
// log.info("审批任务订阅回调");
|
||||||
|
// // 处理通讯录用户增加事件
|
||||||
|
// }else if ("attendance_approve_status_change".equals(eventType)) {
|
||||||
|
// log.info("请假、加班、出差、外出状态变更事件");
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 处理通讯录用户增加事件
|
||||||
|
// }else if ("user_add_org".equals(eventType)) {
|
||||||
|
// // 处理通讯录用户增加事件
|
||||||
|
// log.info("发生了:" + eventType + "事件");
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // 添加其他已注册的
|
||||||
|
// log.info("发生了:" + eventType + "事件");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 5. 返回success的加密数据
|
||||||
|
Map<String, String> successMap = callbackCrypto.getEncryptedMap("success");
|
||||||
|
return successMap;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package com.evo.common.controller;
|
|||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoResponseBody;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.evo.attendance.service.IRzAttendanceService;
|
import com.evo.attendance.service.IRzAttendanceService;
|
||||||
import com.evo.attendance.service.IRzAttendanceStatisticalService;
|
import com.evo.attendance.service.IRzAttendanceStatisticalService;
|
||||||
@ -11,6 +12,8 @@ import com.evo.common.config.Global;
|
|||||||
import com.evo.common.constant.Constants;
|
import com.evo.common.constant.Constants;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.common.utils.Collections;
|
import com.evo.common.utils.Collections;
|
||||||
|
import com.evo.common.utils.http.HttpUtils;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
import com.evo.personnelMatters.mapper.RzOverTimeDetailMapper;
|
import com.evo.personnelMatters.mapper.RzOverTimeDetailMapper;
|
||||||
import com.evo.personnelMatters.mapper.RzOverTimeMapper;
|
import com.evo.personnelMatters.mapper.RzOverTimeMapper;
|
||||||
import com.evo.restaurant.service.IRzRestaurantStatisticsService;
|
import com.evo.restaurant.service.IRzRestaurantStatisticsService;
|
||||||
@ -20,21 +23,27 @@ import com.evo.wechat.TemplateMessageUtil;
|
|||||||
import com.evo.wechat.dto.AbnormalAttendanceTemplate;
|
import com.evo.wechat.dto.AbnormalAttendanceTemplate;
|
||||||
import com.evo.wechat.dto.MessageTemplate;
|
import com.evo.wechat.dto.MessageTemplate;
|
||||||
import com.evo.wechat.service.GZHAccessTokenService;
|
import com.evo.wechat.service.GZHAccessTokenService;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.jasypt.encryption.StringEncryptor;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.File;
|
import java.net.HttpURLConnection;
|
||||||
import java.io.FileReader;
|
import java.net.URL;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -67,6 +76,208 @@ public class TestController {
|
|||||||
private RzAttendanceDetailService rzAttendanceDetailService;
|
private RzAttendanceDetailService rzAttendanceDetailService;
|
||||||
@Resource
|
@Resource
|
||||||
private GZHAccessTokenService gzhAccessTokenService;
|
private GZHAccessTokenService gzhAccessTokenService;
|
||||||
|
@Resource
|
||||||
|
private StringEncryptor stringEncryptor;
|
||||||
|
/**
|
||||||
|
* 清洗加班
|
||||||
|
*/
|
||||||
|
@GetMapping("/dept")
|
||||||
|
public AjaxResult dept(Long deptId) throws ParseException {
|
||||||
|
return AjaxResult.success("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清洗加班
|
||||||
|
*/
|
||||||
|
@GetMapping("/user")
|
||||||
|
public AjaxResult user(String phone) throws ParseException {
|
||||||
|
return AjaxResult.success(DingUtils.getUserIdByPhoto(phone));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清洗加班
|
||||||
|
*/
|
||||||
|
@GetMapping("/aes")
|
||||||
|
public void aes() throws ParseException {
|
||||||
|
// 1. 解密用户名(去掉ENC())
|
||||||
|
String usernameCipher = "QpRNGkSzaeihXTOqXCqXCdAgTTBTOD8M";
|
||||||
|
String usernamePlain = stringEncryptor.decrypt(usernameCipher);
|
||||||
|
System.out.println("解密后的用户名:" + usernamePlain);
|
||||||
|
|
||||||
|
// 2. 解密密码(去掉ENC())
|
||||||
|
String passwordCipher = "c5Sf+6DNzIgtVm2BoHLFmJqnsTJhqRQd721fQ5HXFEY=";
|
||||||
|
String passwordPlain = stringEncryptor.decrypt(passwordCipher);
|
||||||
|
System.out.println("解密后的密码:" + passwordPlain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/buildUser")
|
||||||
|
public AjaxResult buildUser() throws ParseException {
|
||||||
|
List<SysStaff> staffList = sysStaffService.list(new LambdaQueryWrapper<SysStaff>().ne(SysStaff::getStatus, -1).isNull(SysStaff::getDingUserId));
|
||||||
|
List<String> notDingDing = Collections.emptyList();
|
||||||
|
if(Collections.isNotEmpty(staffList)){
|
||||||
|
staffList.stream().forEach(data ->{
|
||||||
|
String result = DingUtils.getUserIdByPhoto(data.getPhone());
|
||||||
|
JSONObject resObject = JSON.parseObject(result);
|
||||||
|
if(Integer.valueOf(0).equals(resObject.getInteger("errcode"))){
|
||||||
|
JSONObject dingRes = resObject.getJSONObject("result");
|
||||||
|
String userId = dingRes.getString("userid");
|
||||||
|
data.setDingUserId(userId);
|
||||||
|
}else{
|
||||||
|
notDingDing.add(data.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
sysStaffService.updateBatchById(staffList);
|
||||||
|
if(Collections.isNotEmpty(notDingDing)){
|
||||||
|
return AjaxResult.success("部分更新失败, 未找到钉钉数据, 人员名单如下: "+ String.join(",", notDingDing));
|
||||||
|
}
|
||||||
|
return AjaxResult.success("更新完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传
|
||||||
|
*/
|
||||||
|
@GetMapping("/update")
|
||||||
|
public void testUpload(@Param("file") MultipartFile filePath) throws Exception {
|
||||||
|
GetFileUploadInfoResponseBody responseBody = DingUtils.resourceUrls();
|
||||||
|
// 从接口返回信息中拿到url
|
||||||
|
String resourceUrl = responseBody.getHeaderSignatureInfo().getResourceUrls().get(0);
|
||||||
|
// 从接口返回信息中拿到headers
|
||||||
|
Map<String, String> headers = responseBody.getHeaderSignatureInfo().getHeaders();
|
||||||
|
URL url = new URL(resourceUrl);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||||
|
if (headers != null) {
|
||||||
|
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||||
|
connection.setRequestProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
connection.setRequestMethod("PUT");
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setReadTimeout(10000);
|
||||||
|
connection.setConnectTimeout(10000);
|
||||||
|
connection.connect();
|
||||||
|
OutputStream out = connection.getOutputStream();
|
||||||
|
InputStream is = filePath.getInputStream();
|
||||||
|
byte[] b =new byte[1024];
|
||||||
|
int temp;
|
||||||
|
while ((temp=is.read(b))!=-1){
|
||||||
|
out.write(b,0,temp);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
connection.disconnect();
|
||||||
|
if (responseCode == 200) {
|
||||||
|
System.out.println("上传成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("上传失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清洗加班
|
||||||
|
*/
|
||||||
|
@GetMapping("/testAdapterSend")
|
||||||
|
public AjaxResult testSend() throws ParseException {
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
|
||||||
|
// // 文件
|
||||||
|
// File file = new File("D:\\andy\\车辆管理.png");
|
||||||
|
//// File file1 = new File("D:\\andy\\index.ts");
|
||||||
|
// FileSystemResource resource = new FileSystemResource(file);
|
||||||
|
//// FileSystemResource resource1 = new FileSystemResource(file1);
|
||||||
|
// params.add("files", resource);
|
||||||
|
//// params.add("files", resource1);
|
||||||
|
// StringBuilder markdownMsg = new StringBuilder();
|
||||||
|
// markdownMsg.append("### 🚀 安全库存提醒\n\n")
|
||||||
|
// .append("今日暂无安全库存预警数据。\n\n");
|
||||||
|
// // 只显示前三个安全库存数据
|
||||||
|
// markdownMsg.append("**物料编号: ").append("123321").append("**\n")
|
||||||
|
// .append("- 物料名称: ").append("测试测试567").append("\n")
|
||||||
|
// .append("- 预计可用量: ").append("200").append("\n")
|
||||||
|
// .append("- 即时库存: ").append("100").append("\n")
|
||||||
|
// .append("- 最大库存: ").append("50").append("\n")
|
||||||
|
// .append("- 创建时间: ").append(DateUtil.formatDateTime(new Date())).append("\n")
|
||||||
|
// .append("---\n"); // 添加分隔线
|
||||||
|
// // 添加总数汇总
|
||||||
|
// markdownMsg.append("**总数汇总**\n")
|
||||||
|
// .append("- 今日安全库存预警数据总数: **").append(50).append("**\n");
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// {"month":"sendMarkdownAndFileToUser","robotCode":"dinge794oclijuyxsyub","clientId":"dinge794oclijuyxsyub","clientSecret":"4ryzLl48I8ghhKqEMPCwablFqbs6PCmadqfDAPFWBNuIEBMJvPFQg-XHAe2oH2Fe","recipientType":"code","users":["00312","00150"],"title":"消息通知测试","content":"消息正文内容。。。。。。。。"}
|
||||||
|
|
||||||
|
Map<String,String> dataMap = Collections.emptyMap();
|
||||||
|
dataMap.put("month", "sendMarkdownAndFileToUser");
|
||||||
|
dataMap.put("robotCode","dinge794oclijuyxsyub");
|
||||||
|
dataMap.put("clientId", "dinge794oclijuyxsyub");
|
||||||
|
dataMap.put("clientSecret", "4ryzLl48I8ghhKqEMPCwablFqbs6PCmadqfDAPFWBNuIEBMJvPFQg-XHAe2oH2Fe");
|
||||||
|
dataMap.put("recipientType", "code");//00146
|
||||||
|
dataMap.put("users", JSON.toJSONString(Collections.asList("00312","00150")));
|
||||||
|
dataMap.put("title", "消息通知测试");
|
||||||
|
dataMap.put("content", "消息正文内容。。。。。。。。");
|
||||||
|
//
|
||||||
|
//// dataMap.put("parameterTypes", JSON.toJSONString(Collections.asList("java.lang.String","java.lang.String")));
|
||||||
|
//// dataMap.put("parameters", JSON.toJSONString(Collections.asList("test测试",markdownMsg.toString())));
|
||||||
|
// //推送数据类型
|
||||||
|
params.add("data", JSON.toJSONString(dataMap));
|
||||||
|
//
|
||||||
|
String url = "http://localhost:8089/ding/send";
|
||||||
|
return AjaxResult.success(restTemplate.postForObject(url, params, String.class));
|
||||||
|
//
|
||||||
|
|
||||||
|
//String data = "{\"FormId\":\"BD_Empinfo\",\"FieldKeys\":\"FID\",\"FilterString\":[{\"Left\":\"\",\"FieldName\":\"FStaffNumber\",\"Compare\":\"17\",\"Value\":\"00046\",\"Right\":\"\",\"Logic\":0}],\"OrderString\":\"\",\"TopRowCount\":0,\"StartRow\":0,\"Limit\":2000,\"SubSystemId\":\"\"}";
|
||||||
|
//
|
||||||
|
// String data = "{\n" +
|
||||||
|
// " \"FormId\" : \"PRD_MO\",\n" +
|
||||||
|
// " \"FieldKeys\" : \"F_HBYT_SCLH,FBillNo,FWorkShopID.FName,FMaterialId.FNumber,FMaterialName,FPlanStartDate,FPlanFinishDate,FPickMtrlStatus\",\n" +
|
||||||
|
// " \"FilterString\" : [ {\n" +
|
||||||
|
// " \"FieldName\" : \"FStatus\",\n" +
|
||||||
|
// " \"Compare\" : \"105\",\n" +
|
||||||
|
// " \"Value\" : \"4\",\n" +
|
||||||
|
// " \"Left\" : \"\",\n" +
|
||||||
|
// " \"Right\" : \"\",\n" +
|
||||||
|
// " \"Logic\" : 0\n" +
|
||||||
|
// " }, {\n" +
|
||||||
|
// " \"FieldName\" : \"FPickMtrlStatus\",\n" +
|
||||||
|
// " \"Compare\" : \"29\",\n" +
|
||||||
|
// " \"Value\" : \"1\",\n" +
|
||||||
|
// " \"Left\" : \"\",\n" +
|
||||||
|
// " \"Right\" : \"\",\n" +
|
||||||
|
// " \"Logic\" : 0\n" +
|
||||||
|
// " }, {\n" +
|
||||||
|
// " \"FieldName\" : \"F_HBYT_SCLH\",\n" +
|
||||||
|
// " \"Compare\" : \"67\",\n" +
|
||||||
|
// " \"Value\" : \"QB-26-163-XCL\",\n" +
|
||||||
|
// " \"Left\" : \"\",\n" +
|
||||||
|
// " \"Right\" : \"\",\n" +
|
||||||
|
// " \"Logic\" : 0\n" +
|
||||||
|
// " } ],\n" +
|
||||||
|
// " \"OrderString\" : \"\",\n" +
|
||||||
|
// " \"TopRowCount\" : 0,\n" +
|
||||||
|
// " \"StartRow\" : 0,\n" +
|
||||||
|
// " \"Limit\" : 10000,\n" +
|
||||||
|
// " \"SubSystemId\" : \"\"\n" +
|
||||||
|
// "}";
|
||||||
|
//
|
||||||
|
// return AjaxResult.success(HttpUtils.sendPost("http://localhost:8089/distribution/kingdee/send", JSONObject.toJSONString(
|
||||||
|
// Collections.asMap("fromId","PRD_MO", "month","billQuery", "parameterTypes",Collections.asList(String.class),"data",Collections.asMap("123",data)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清洗加班
|
* 清洗加班
|
||||||
|
|||||||
@ -57,6 +57,11 @@ public class SysDept extends BaseEntity
|
|||||||
/** 是否加班 */
|
/** 是否加班 */
|
||||||
private String isOverTime;
|
private String isOverTime;
|
||||||
|
|
||||||
|
/** 是否加班 */
|
||||||
|
private String isShowFinancial;
|
||||||
|
|
||||||
|
private String dingId;
|
||||||
|
|
||||||
/** 子部门 */
|
/** 子部门 */
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private List<SysDept> children = new ArrayList<SysDept>();
|
private List<SysDept> children = new ArrayList<SysDept>();
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.evo.common.function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc: 四参数
|
||||||
|
* @ClassName:FourParamFunction
|
||||||
|
* @date: 2026年04月27日 11:46
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FourParamFunction<A, B, C, D> {
|
||||||
|
void apply(A a, B b, C c, D d);
|
||||||
|
}
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
package com.evo.common.handler.thread;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.attendance.domain.RzAttendance;
|
||||||
|
import com.evo.common.config.thread.ThreadPoolManager;
|
||||||
|
import com.evo.common.config.thread.ThreadPoolProperties;
|
||||||
|
import com.evo.common.function.FourParamFunction;
|
||||||
|
import com.evo.common.utils.Collections;
|
||||||
|
import com.evo.common.utils.DateUtils;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import com.evo.system.service.ISysStaffService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 考勤 批量数据处理器 每个线程 固定处理 50 条数据
|
||||||
|
* @ClassName:DataBatchHandler
|
||||||
|
* @date: 2026年04月25日 15:01
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class RzAttendanceBatchHandler {
|
||||||
|
|
||||||
|
private final ThreadPoolProperties poolProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysStaffService sysStaffService;
|
||||||
|
|
||||||
|
public RzAttendanceBatchHandler(ThreadPoolProperties poolProperties) {
|
||||||
|
this.poolProperties = poolProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量处理任务(自动分片,每片50条)
|
||||||
|
*/
|
||||||
|
public void batchProcess(Date date, FourParamFunction<String, SysStaff, JSONObject, RzAttendance> calculationAddRzOverTime) {
|
||||||
|
int batchSize = poolProperties.getBatchSize(); // 50条/线程
|
||||||
|
AtomicInteger index = new AtomicInteger(0);
|
||||||
|
List<SysStaff> sysStaffList = sysStaffService.selectSysStaffListAll();
|
||||||
|
|
||||||
|
Date firstDate = DateUtils.getMonthFirst(date);
|
||||||
|
Date endDate = DateUtils.getMonthEnd(date);
|
||||||
|
// 获取有多少天
|
||||||
|
List<String> dateTimeList = new ArrayList<>();
|
||||||
|
|
||||||
|
while (firstDate.compareTo(endDate)<=0) {
|
||||||
|
dateTimeList.add(DateUtils.parseDateToStr("yyyy-MM-dd", firstDate));
|
||||||
|
firstDate = DateUtils.addDays(firstDate, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 循环分片提交任务
|
||||||
|
while (index.get() < sysStaffList.size()) {
|
||||||
|
int start = index.getAndAdd(batchSize);
|
||||||
|
int end = Math.min(start + batchSize, sysStaffList.size());
|
||||||
|
|
||||||
|
List<SysStaff> batchData = sysStaffList.subList(start, end);
|
||||||
|
|
||||||
|
// 提交到线程池,一个线程处理这 50 条
|
||||||
|
ThreadPoolManager.execute(() -> {
|
||||||
|
try {
|
||||||
|
handleBatchData(batchData, dateTimeList, calculationAddRzOverTime);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("批量处理异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 真正业务:单个线程处理 50 条数据
|
||||||
|
*/
|
||||||
|
private void handleBatchData(List<SysStaff> batchData, List<String> dateTimeList, FourParamFunction<String, SysStaff, JSONObject, RzAttendance> calculationAddRzOverTime) {
|
||||||
|
String threadName = Thread.currentThread().getName();
|
||||||
|
System.out.println("========================================");
|
||||||
|
System.out.println(threadName + " 开始处理,条数:" + batchData.size());
|
||||||
|
//将数据的钉钉钉钉list获取
|
||||||
|
Map<String, SysStaff> map = batchData.stream().filter(data -> StringUtils.isNotEmpty(data.getDingUserId())).collect(Collectors.toMap(SysStaff::getDingUserId, data -> data));
|
||||||
|
List<String> dingUserIds = map.keySet().stream().collect(Collectors.toList());
|
||||||
|
System.out.println("==================="+JSONObject.toJSONString(dingUserIds));
|
||||||
|
for (String date : dateTimeList){
|
||||||
|
String result = DingUtils.getListRecord(dingUserIds, date+" 00:00:00", date+" 23:59:59");
|
||||||
|
JSONObject resultJson = JSON.parseObject(result);
|
||||||
|
if(Integer.valueOf(0).equals(resultJson.getInteger("errcode"))){
|
||||||
|
try {
|
||||||
|
JSONArray jsonArray = resultJson.getJSONArray("recordresult");
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JSONObject object = jsonArray.getJSONObject(i);
|
||||||
|
calculationAddRzOverTime.apply(result, map.get(object.getString("userId")), object, null);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("重新抓取钉钉考勤结果异常, 抓取用户为====>>>{}, 异常原因是==>>{}, 打卡结果是=====>>>>> {}", JSONObject.toJSONString(dingUserIds), e.getMessage(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
System.out.println(threadName + " 处理完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -7,6 +7,9 @@ import com.evo.attendance.service.IRzSysParamService;
|
|||||||
import com.evo.personnelMatters.domain.RzHoliday;
|
import com.evo.personnelMatters.domain.RzHoliday;
|
||||||
import com.evo.personnelMatters.service.IRzHolidayService;
|
import com.evo.personnelMatters.service.IRzHolidayService;
|
||||||
import com.evo.system.service.ISysDictDataService;
|
import com.evo.system.service.ISysDictDataService;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -76,6 +79,17 @@ public class ParamUtils {
|
|||||||
return Double.valueOf(param.getParamValue());
|
return Double.valueOf(param.getParamValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取补卡单次扣款
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Double getDebiting(){
|
||||||
|
RzSysParam param= paramService.getRzSysParam("补卡单次扣款", "recharge_card_debiting","2","单次补卡扣款");
|
||||||
|
return Double.valueOf(param.getParamValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 获取餐厅的开放时间
|
* 获取餐厅的开放时间
|
||||||
* @return
|
* @return
|
||||||
@ -122,7 +136,7 @@ public class ParamUtils {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<String> getInternDailyWage(){
|
public static List<String> getInternDailyWage(){
|
||||||
RzSysParam param= paramService.getRzSysParam("实习生不住宿的日薪人员名单", "intern_not_accommodation","乔克俭","实习生不住宿的日薪人员名单");
|
RzSysParam param= paramService.getRzSysParam("实习生不住宿的日薪人员名单", "intern_daily_wage","乔克俭","实习生不住宿的日薪人员名单");
|
||||||
return Collections.asList(param.getParamValue().split(","));
|
return Collections.asList(param.getParamValue().split(","));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +201,16 @@ public class ParamUtils {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<String> getTsDevSn(){
|
public static List<String> getTsDevSn(){
|
||||||
RzSysParam param= paramService.getRzSysParam("获取特殊类型的打卡机型号", "ts_device_sn","ET74336,ET74335","获取特殊类型的打卡机型号, 多个参数使用,隔开");
|
RzSysParam param= paramService.getRzSysParam("获取特殊类型的打卡机型号", "ts_device_sn","T71474,RT64815","获取特殊类型的打卡机型号, 多个参数使用,隔开");
|
||||||
|
return Collections.asList(param.getParamValue().split(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取餐厅设备信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<String> getRestaurantDevSn(){
|
||||||
|
RzSysParam param= paramService.getRzSysParam("获取餐厅打卡机型号", "restaurant_device_sn","T71474,RT64815","获取餐厅打卡机型号, 多个参数使用,隔开");
|
||||||
return Collections.asList(param.getParamValue().split(","));
|
return Collections.asList(param.getParamValue().split(","));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,6 +229,24 @@ public class ParamUtils {
|
|||||||
if(StringUtils.isEmpty(rulesVal)) return false;
|
if(StringUtils.isEmpty(rulesVal)) return false;
|
||||||
return Collections.asList(rulesVal.split(",")).contains(rules);
|
return Collections.asList(rulesVal.split(",")).contains(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 检查各厂考勤人数
|
||||||
|
* sn 设备号
|
||||||
|
* rules 规则
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Map<String, String> checkKqAddressCount(){
|
||||||
|
try {
|
||||||
|
RzSysParam param= paramService.getRzSysParam("检查各厂考勤人数规则", "check_kq_address_count","{\"北厂\":\"{\"longScope\":\"123-456\",\"latScope\":\"123-456\"}\"}","特殊打卡机的打卡按钮规则, 使用json格式, 如果打卡机存在多个按钮规则用,分割");
|
||||||
|
String val = param.getParamValue();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
// 第一层:外层 Map<String, String>
|
||||||
|
return mapper.readValue(param.getParamValue(), new TypeReference<Map<String, String>>() {});
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
/***
|
/***
|
||||||
* 获取特殊加班的考勤规则
|
* 获取特殊加班的考勤规则
|
||||||
* sn 设备号
|
* sn 设备号
|
||||||
@ -215,6 +256,9 @@ public class ParamUtils {
|
|||||||
public static JSONObject getDeviceOverTimeRules(String sn){
|
public static JSONObject getDeviceOverTimeRules(String sn){
|
||||||
if(StringUtils.isEmpty(sn)) return null;
|
if(StringUtils.isEmpty(sn)) return null;
|
||||||
RzSysParam param= paramService.getRzSysParam("特殊加班的考勤规则", "device_over_time_rules","{\"ET74336\":{\"minHour\":2, \"maxHour\":3,\"endMealTime\":\"19:00\"}}","特殊加班的考勤规则, minHour:最小加班时长. maxHour: 最大加班时长, endMealTime: 餐厅闭厅时间");
|
RzSysParam param= paramService.getRzSysParam("特殊加班的考勤规则", "device_over_time_rules","{\"ET74336\":{\"minHour\":2, \"maxHour\":3,\"endMealTime\":\"19:00\"}}","特殊加班的考勤规则, minHour:最小加班时长. maxHour: 最大加班时长, endMealTime: 餐厅闭厅时间");
|
||||||
|
if(param == null){
|
||||||
|
return getDefaultMaxOverTime();
|
||||||
|
}
|
||||||
JSONObject jsonObject = JSONObject.parseObject(param.getParamValue());
|
JSONObject jsonObject = JSONObject.parseObject(param.getParamValue());
|
||||||
JSONObject rules = jsonObject.getJSONObject(sn);
|
JSONObject rules = jsonObject.getJSONObject(sn);
|
||||||
return (ObjectUtils.isEmpty(rules) ? getDefaultMaxOverTime(): rules);
|
return (ObjectUtils.isEmpty(rules) ? getDefaultMaxOverTime(): rules);
|
||||||
@ -299,14 +343,13 @@ public class ParamUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//检查格式, 如果格式不匹配, 输出日志, 直接返回true
|
//检查格式, 如果格式不匹配, 输出日志, 直接返回true
|
||||||
if(!Pattern.compile("").matcher(checkDate).matches()){
|
if(!Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$").matcher(checkDate).matches()){
|
||||||
log.error("当前检查日期{}, 不符合检查规则", checkDate);
|
log.error("当前检查日期{}, 不符合检查规则", checkDate);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//检查是否为假期
|
//检查是否为假期
|
||||||
return getHoliddayList(Integer.valueOf(checkDate.substring(0,4)), 0).contains(checkDate);
|
return getHoliddayList(Integer.valueOf(checkDate.substring(0,4)), 0).contains(checkDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 获取假期范围 0 全部 1法休 2 公休
|
* 获取假期范围 0 全部 1法休 2 公休
|
||||||
* @param year
|
* @param year
|
||||||
@ -332,11 +375,26 @@ public class ParamUtils {
|
|||||||
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).map(Long::valueOf).collect(Collectors.toList());
|
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).map(Long::valueOf).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取基本工资全新的假期
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<Long> getBasicFullPaidLeave(){
|
||||||
|
RzSysParam param= paramService.getRzSysParam("基本薪全薪发放的假期", "basic_full_paid_leave","58","基本薪全薪发放的假期; 58-陪产假");
|
||||||
|
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).map(Long::valueOf).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<String> getWebCompany(){
|
public static List<String> getWebCompany(){
|
||||||
RzSysParam param= paramService.getRzSysParam("外包公司名称", "web_company","WB,LWWB","外包公司, 不扣个税)");
|
RzSysParam param= paramService.getRzSysParam("外包公司名称", "web_company","WB,LWWB","外包公司, 不扣个税)");
|
||||||
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
|
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<String> getWeBaoTaxCompany(){
|
||||||
|
RzSysParam param= paramService.getRzSysParam("需要扣税的外包公司名称", "we_bao_tax_company","YTLW","需要扣税的外包公司名称)");
|
||||||
|
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 获取80%假期
|
* 获取80%假期
|
||||||
@ -348,7 +406,16 @@ public class ParamUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 获取80%假期
|
* 获取基本薪假期
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<Long> getBasicVacation(){
|
||||||
|
RzSysParam param= paramService.getRzSysParam("基本薪假期类型", "basic_vacation","58","80%的假期类型; 58-陪产假");
|
||||||
|
return Collections.asList(param.getParamValue().split(",")).stream().filter(StringUtils::isNotEmpty).map(Long::valueOf).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 特殊年度免征额计算
|
||||||
* @param nameAndIdCard 姓名-身份证
|
* @param nameAndIdCard 姓名-身份证
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package com.evo.common.utils;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
@ -18,6 +20,7 @@ import com.evo.common.exception.ServiceException;
|
|||||||
*
|
*
|
||||||
* @author evo
|
* @author evo
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class SecurityUtils
|
public class SecurityUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -62,7 +65,9 @@ public class SecurityUtils
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
|
log.error("获取用户账户异常", HttpStatus.UNAUTHORIZED);
|
||||||
|
return "system";
|
||||||
|
// throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -138,7 +138,74 @@ public class HttpUtils
|
|||||||
conn.setRequestProperty("connection", "Keep-Alive");
|
conn.setRequestProperty("connection", "Keep-Alive");
|
||||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||||
conn.setRequestProperty("Accept-Charset", "UTF-8");
|
conn.setRequestProperty("Accept-Charset", "UTF-8");
|
||||||
conn.setRequestProperty("contentType", "UTF-8");
|
//conn.setRequestProperty("contentType", "UTF-8");
|
||||||
|
conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
|
||||||
|
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
conn.setDoInput(true);
|
||||||
|
out = new PrintWriter(conn.getOutputStream());
|
||||||
|
out.print(param);
|
||||||
|
out.flush();
|
||||||
|
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null)
|
||||||
|
{
|
||||||
|
result.append(line);
|
||||||
|
}
|
||||||
|
log.info("recv - {}", result);
|
||||||
|
}
|
||||||
|
catch (ConnectException e)
|
||||||
|
{
|
||||||
|
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
||||||
|
}
|
||||||
|
catch (SocketTimeoutException e)
|
||||||
|
{
|
||||||
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (out != null)
|
||||||
|
{
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
if (in != null)
|
||||||
|
{
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendPost(String url, String param, String contentType) {
|
||||||
|
PrintWriter out = null;
|
||||||
|
BufferedReader in = null;
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
log.info("sendPost - {}", url);
|
||||||
|
URL realUrl = new URL(url);
|
||||||
|
URLConnection conn = realUrl.openConnection();
|
||||||
|
conn.setRequestProperty("accept", "*/*");
|
||||||
|
conn.setRequestProperty("connection", "Keep-Alive");
|
||||||
|
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||||
|
conn.setRequestProperty("Accept-Charset", "UTF-8");
|
||||||
|
conn.setRequestProperty("Content-Type", contentType);
|
||||||
|
|
||||||
conn.setDoOutput(true);
|
conn.setDoOutput(true);
|
||||||
conn.setDoInput(true);
|
conn.setDoInput(true);
|
||||||
out = new PrintWriter(conn.getOutputStream());
|
out = new PrintWriter(conn.getOutputStream());
|
||||||
|
|||||||
@ -35,6 +35,11 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
|
|||||||
SpringUtils.applicationContext = applicationContext;
|
SpringUtils.applicationContext = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ApplicationContext getApplicationContext() throws BeansException
|
||||||
|
{
|
||||||
|
return SpringUtils.applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取对象
|
* 获取对象
|
||||||
*
|
*
|
||||||
|
|||||||
400
evo-admin/src/main/java/com/evo/ding/DingCallbackCrypto.java
Normal file
400
evo-admin/src/main/java/com/evo/ding/DingCallbackCrypto.java
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
package com.evo.ding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingCallbackCrypto
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallbackCrypto
|
||||||
|
* @date: 2026年03月04日 11:55
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.security.PermissionCollection;
|
||||||
|
import java.security.Security;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class DingCallbackCrypto {
|
||||||
|
|
||||||
|
private static final Charset CHARSET = Charset.forName("utf-8");
|
||||||
|
private static final Base64 base64 = new Base64();
|
||||||
|
private byte[] aesKey;
|
||||||
|
private String token;
|
||||||
|
private String corpId;
|
||||||
|
/**
|
||||||
|
* ask getPaddingBytes key固定长度
|
||||||
|
**/
|
||||||
|
private static final Integer AES_ENCODE_KEY_LENGTH = 43;
|
||||||
|
/**
|
||||||
|
* 加密随机字符串字节长度
|
||||||
|
**/
|
||||||
|
private static final Integer RANDOM_LENGTH = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
*
|
||||||
|
* @param token 钉钉开放平台上,开发者设置的token
|
||||||
|
* @param encodingAesKey 钉钉开放台上,开发者设置的EncodingAESKey
|
||||||
|
* @param corpId 企业自建应用-事件订阅, 使用appKey
|
||||||
|
* 企业自建应用-注册回调地址, 使用corpId
|
||||||
|
* 第三方企业应用, 使用suiteKey
|
||||||
|
*
|
||||||
|
* @throws DingTalkEncryptException 执行失败,请查看该异常的错误码和具体的错误信息
|
||||||
|
*/
|
||||||
|
public DingCallbackCrypto(String token, String encodingAesKey, String corpId) throws DingTalkEncryptException {
|
||||||
|
if (null == encodingAesKey || encodingAesKey.length() != AES_ENCODE_KEY_LENGTH) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.AES_KEY_ILLEGAL);
|
||||||
|
}
|
||||||
|
this.token = token;
|
||||||
|
this.corpId = corpId;
|
||||||
|
aesKey = Base64.decodeBase64(encodingAesKey + "=");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getEncryptedMap(String plaintext) throws DingTalkEncryptException {
|
||||||
|
return getEncryptedMap(plaintext, System.currentTimeMillis(), Utils.getRandomStr(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将和钉钉开放平台同步的消息体加密,返回加密Map
|
||||||
|
*
|
||||||
|
* @param plaintext 传递的消息体明文
|
||||||
|
* @param timeStamp 时间戳
|
||||||
|
* @param nonce 随机字符串
|
||||||
|
* @return
|
||||||
|
* @throws DingTalkEncryptException
|
||||||
|
*/
|
||||||
|
public Map<String, String> getEncryptedMap(String plaintext, Long timeStamp, String nonce)
|
||||||
|
throws DingTalkEncryptException {
|
||||||
|
if (null == plaintext) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL);
|
||||||
|
}
|
||||||
|
if (null == timeStamp) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_TIMESTAMP_ILLEGAL);
|
||||||
|
}
|
||||||
|
if (null == nonce) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_NONCE_ILLEGAL);
|
||||||
|
}
|
||||||
|
// 加密
|
||||||
|
String encrypt = encrypt(Utils.getRandomStr(RANDOM_LENGTH), plaintext);
|
||||||
|
String signature = getSignature(token, String.valueOf(timeStamp), nonce, encrypt);
|
||||||
|
Map<String, String> resultMap = new HashMap<String, String>();
|
||||||
|
resultMap.put("msg_signature", signature);
|
||||||
|
resultMap.put("encrypt", encrypt);
|
||||||
|
resultMap.put("timeStamp", String.valueOf(timeStamp));
|
||||||
|
resultMap.put("nonce", nonce);
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密文解密
|
||||||
|
*
|
||||||
|
* @param msgSignature 签名串
|
||||||
|
* @param timeStamp 时间戳
|
||||||
|
* @param nonce 随机串
|
||||||
|
* @param encryptMsg 密文
|
||||||
|
* @return 解密后的原文
|
||||||
|
* @throws DingTalkEncryptException
|
||||||
|
*/
|
||||||
|
public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg)
|
||||||
|
throws DingTalkEncryptException {
|
||||||
|
//校验签名
|
||||||
|
String signature = getSignature(token, timeStamp, nonce, encryptMsg);
|
||||||
|
if (!signature.equals(msgSignature)) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
|
||||||
|
}
|
||||||
|
// 解密
|
||||||
|
String result = decrypt(encryptMsg);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 对明文加密.
|
||||||
|
* @param text 需要加密的明文
|
||||||
|
* @return 加密后base64编码的字符串
|
||||||
|
*/
|
||||||
|
private String encrypt(String random, String plaintext) throws DingTalkEncryptException {
|
||||||
|
try {
|
||||||
|
byte[] randomBytes = random.getBytes(CHARSET);
|
||||||
|
byte[] plainTextBytes = plaintext.getBytes(CHARSET);
|
||||||
|
byte[] lengthByte = Utils.int2Bytes(plainTextBytes.length);
|
||||||
|
byte[] corpidBytes = corpId.getBytes(CHARSET);
|
||||||
|
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||||
|
byteStream.write(randomBytes);
|
||||||
|
byteStream.write(lengthByte);
|
||||||
|
byteStream.write(plainTextBytes);
|
||||||
|
byteStream.write(corpidBytes);
|
||||||
|
byte[] padBytes = PKCS7Padding.getPaddingBytes(byteStream.size());
|
||||||
|
byteStream.write(padBytes);
|
||||||
|
byte[] unencrypted = byteStream.toByteArray();
|
||||||
|
byteStream.close();
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
|
||||||
|
IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
|
||||||
|
byte[] encrypted = cipher.doFinal(unencrypted);
|
||||||
|
String result = base64.encodeToString(encrypted);
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 对密文进行解密.
|
||||||
|
* @param text 需要解密的密文
|
||||||
|
* @return 解密得到的明文
|
||||||
|
*/
|
||||||
|
private String decrypt(String text) throws DingTalkEncryptException {
|
||||||
|
byte[] originalArr;
|
||||||
|
try {
|
||||||
|
// 设置解密模式为AES的CBC模式
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
|
||||||
|
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
|
||||||
|
// 使用BASE64对密文进行解码
|
||||||
|
byte[] encrypted = Base64.decodeBase64(text);
|
||||||
|
// 解密
|
||||||
|
originalArr = cipher.doFinal(encrypted);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
String plainText;
|
||||||
|
String fromCorpid;
|
||||||
|
try {
|
||||||
|
// 去除补位字符
|
||||||
|
byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
|
||||||
|
// 分离16位随机字符串,网络字节序和corpId
|
||||||
|
byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
|
||||||
|
int plainTextLegth = Utils.bytes2int(networkOrder);
|
||||||
|
plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
|
||||||
|
fromCorpid = new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// corpid不相同的情况
|
||||||
|
if (!fromCorpid.equals(corpId)) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);
|
||||||
|
}
|
||||||
|
return plainText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数字签名
|
||||||
|
*
|
||||||
|
* @param token isv token
|
||||||
|
* @param timestamp 时间戳
|
||||||
|
* @param nonce 随机串
|
||||||
|
* @param encrypt 加密文本
|
||||||
|
* @return
|
||||||
|
* @throws DingTalkEncryptException
|
||||||
|
*/
|
||||||
|
public String getSignature(String token, String timestamp, String nonce, String encrypt)
|
||||||
|
throws DingTalkEncryptException {
|
||||||
|
try {
|
||||||
|
String[] array = new String[] {token, timestamp, nonce, encrypt};
|
||||||
|
Arrays.sort(array);
|
||||||
|
System.out.println(JSON.toJSONString(array));
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
sb.append(array[i]);
|
||||||
|
}
|
||||||
|
String str = sb.toString();
|
||||||
|
System.out.println(str);
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||||
|
md.update(str.getBytes());
|
||||||
|
byte[] digest = md.digest();
|
||||||
|
|
||||||
|
StringBuffer hexstr = new StringBuffer();
|
||||||
|
String shaHex = "";
|
||||||
|
for (int i = 0; i < digest.length; i++) {
|
||||||
|
shaHex = Integer.toHexString(digest[i] & 0xFF);
|
||||||
|
if (shaHex.length() < 2) {
|
||||||
|
hexstr.append(0);
|
||||||
|
}
|
||||||
|
hexstr.append(shaHex);
|
||||||
|
}
|
||||||
|
return hexstr.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Utils {
|
||||||
|
public Utils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRandomStr(int count) {
|
||||||
|
String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
Random random = new Random();
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
int number = random.nextInt(base.length());
|
||||||
|
sb.append(base.charAt(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] int2Bytes(int count) {
|
||||||
|
byte[] byteArr = new byte[] {(byte)(count >> 24 & 255), (byte)(count >> 16 & 255), (byte)(count >> 8 & 255),
|
||||||
|
(byte)(count & 255)};
|
||||||
|
return byteArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int bytes2int(byte[] byteArr) {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
count <<= 8;
|
||||||
|
count |= byteArr[i] & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PKCS7Padding {
|
||||||
|
private static final Charset CHARSET = Charset.forName("utf-8");
|
||||||
|
private static final int BLOCK_SIZE = 32;
|
||||||
|
|
||||||
|
public PKCS7Padding() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] getPaddingBytes(int count) {
|
||||||
|
int amountToPad = 32 - count % 32;
|
||||||
|
if (amountToPad == 0) {
|
||||||
|
amountToPad = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
char padChr = chr(amountToPad);
|
||||||
|
String tmp = new String();
|
||||||
|
|
||||||
|
for (int index = 0; index < amountToPad; ++index) {
|
||||||
|
tmp = tmp + padChr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp.getBytes(CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] removePaddingBytes(byte[] decrypted) {
|
||||||
|
int pad = decrypted[decrypted.length - 1];
|
||||||
|
if (pad < 1 || pad > 32) {
|
||||||
|
pad = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char chr(int a) {
|
||||||
|
byte target = (byte)(a & 255);
|
||||||
|
return (char)target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DingTalkEncryptException extends Exception {
|
||||||
|
public static final int SUCCESS = 0;
|
||||||
|
public static final int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
|
||||||
|
public static final int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
|
||||||
|
public static final int ENCRYPTION_NONCE_ILLEGAL = 900003;
|
||||||
|
public static final int AES_KEY_ILLEGAL = 900004;
|
||||||
|
public static final int SIGNATURE_NOT_MATCH = 900005;
|
||||||
|
public static final int COMPUTE_SIGNATURE_ERROR = 900006;
|
||||||
|
public static final int COMPUTE_ENCRYPT_TEXT_ERROR = 900007;
|
||||||
|
public static final int COMPUTE_DECRYPT_TEXT_ERROR = 900008;
|
||||||
|
public static final int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009;
|
||||||
|
public static final int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010;
|
||||||
|
private static Map<Integer, String> msgMap = new HashMap();
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
static {
|
||||||
|
msgMap.put(0, "成功");
|
||||||
|
msgMap.put(900001, "加密明文文本非法");
|
||||||
|
msgMap.put(900002, "加密时间戳参数非法");
|
||||||
|
msgMap.put(900003, "加密随机字符串参数非法");
|
||||||
|
msgMap.put(900005, "签名不匹配");
|
||||||
|
msgMap.put(900006, "签名计算失败");
|
||||||
|
msgMap.put(900004, "不合法的aes key");
|
||||||
|
msgMap.put(900007, "计算加密文字错误");
|
||||||
|
msgMap.put(900008, "计算解密文字错误");
|
||||||
|
msgMap.put(900009, "计算解密文字长度不匹配");
|
||||||
|
msgMap.put(900010, "计算解密文字corpid不匹配");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DingTalkEncryptException(Integer exceptionCode) {
|
||||||
|
super((String)msgMap.get(exceptionCode));
|
||||||
|
this.code = exceptionCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Security.setProperty("crypto.policy", "limited");
|
||||||
|
RemoveCryptographyRestrictions();
|
||||||
|
} catch (Exception var1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
private static void RemoveCryptographyRestrictions() throws Exception {
|
||||||
|
Class<?> jceSecurity = getClazz("javax.crypto.JceSecurity");
|
||||||
|
Class<?> cryptoPermissions = getClazz("javax.crypto.CryptoPermissions");
|
||||||
|
Class<?> cryptoAllPermission = getClazz("javax.crypto.CryptoAllPermission");
|
||||||
|
if (jceSecurity != null) {
|
||||||
|
setFinalStaticValue(jceSecurity, "isRestricted", false);
|
||||||
|
PermissionCollection defaultPolicy = (PermissionCollection)getFieldValue(jceSecurity, "defaultPolicy", (Object)null, PermissionCollection.class);
|
||||||
|
if (cryptoPermissions != null) {
|
||||||
|
Map<?, ?> map = (Map)getFieldValue(cryptoPermissions, "perms", defaultPolicy, Map.class);
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cryptoAllPermission != null) {
|
||||||
|
Permission permission = (Permission)getFieldValue(cryptoAllPermission, "INSTANCE", (Object)null, Permission.class);
|
||||||
|
defaultPolicy.add(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
private static Class<?> getClazz(String className) {
|
||||||
|
Class clazz = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
clazz = Class.forName(className);
|
||||||
|
} catch (Exception var3) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
private static void setFinalStaticValue(Class<?> srcClazz, String fieldName, Object newValue) throws Exception {
|
||||||
|
Field field = srcClazz.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||||
|
modifiersField.setAccessible(true);
|
||||||
|
modifiersField.setInt(field, field.getModifiers() & -17);
|
||||||
|
field.set((Object)null, newValue);
|
||||||
|
}
|
||||||
|
private static <T> T getFieldValue(Class<?> srcClazz, String fieldName, Object owner, Class<T> dstClazz) throws Exception {
|
||||||
|
Field field = srcClazz.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
return dstClazz.cast(field.get(owner));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
91
evo-admin/src/main/java/com/evo/ding/DingGlobalParams.java
Normal file
91
evo-admin/src/main/java/com/evo/ding/DingGlobalParams.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package com.evo.ding;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingBase
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingBase
|
||||||
|
* @date: 2026年03月02日 8:48
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "ding")
|
||||||
|
public class DingGlobalParams {
|
||||||
|
|
||||||
|
public static String baseUrl;
|
||||||
|
|
||||||
|
public static String url;
|
||||||
|
|
||||||
|
public static String clientId;
|
||||||
|
|
||||||
|
public static String clientSecret;
|
||||||
|
|
||||||
|
public static String aesKey;
|
||||||
|
|
||||||
|
public static String token;
|
||||||
|
|
||||||
|
public static String corpId;
|
||||||
|
|
||||||
|
|
||||||
|
public static String getBaseUrl() {
|
||||||
|
return baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBaseUrl(String baseUrl) {
|
||||||
|
DingGlobalParams.baseUrl = baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCorpId() {
|
||||||
|
return corpId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCorpId(String corpId) {
|
||||||
|
DingGlobalParams.corpId = corpId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAesKey() {
|
||||||
|
return aesKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAesKey(String aesKey) {
|
||||||
|
DingGlobalParams.aesKey = aesKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
DingGlobalParams.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
DingGlobalParams.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getClientId() {
|
||||||
|
return DingGlobalParams.clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
DingGlobalParams.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getClientSecret() {
|
||||||
|
return clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setClientSecret(String clientSecret) {
|
||||||
|
DingGlobalParams.clientSecret = clientSecret;
|
||||||
|
}
|
||||||
|
}
|
||||||
316
evo-admin/src/main/java/com/evo/ding/DingUtils.java
Normal file
316
evo-admin/src/main/java/com/evo/ding/DingUtils.java
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
package com.evo.ding;
|
||||||
|
|
||||||
|
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
|
||||||
|
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
|
||||||
|
import com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoResponseBody;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.aliyun.tea.TeaException;
|
||||||
|
import com.dingtalk.api.DefaultDingTalkClient;
|
||||||
|
import com.dingtalk.api.DingTalkClient;
|
||||||
|
import com.dingtalk.api.request.*;
|
||||||
|
import com.dingtalk.api.response.*;
|
||||||
|
import com.evo.common.core.redis.RedisCache;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.taobao.api.ApiException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingUtils
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingUtils
|
||||||
|
* @date: 2026年03月02日 8:54
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class DingUtils {
|
||||||
|
|
||||||
|
private static RedisCache redisCache;
|
||||||
|
|
||||||
|
private static String ACCESS_TOKEN_KEY = "ding_access_token";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public DingUtils(RedisCache redisCache) {
|
||||||
|
this.redisCache = redisCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> com.aliyun.teaopenapi.Client client(Class<?> t) throws Exception {
|
||||||
|
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
|
||||||
|
config.protocol = "https";
|
||||||
|
config.regionId = "central";
|
||||||
|
if(t == com.aliyun.dingtalkoauth2_1_0.Client.class){
|
||||||
|
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
|
||||||
|
}else if(t == com.aliyun.dingtalkworkflow_1_0.Client.class){
|
||||||
|
return new com.aliyun.dingtalkworkflow_1_0.Client(config);
|
||||||
|
}else if(t == com.aliyun.dingtalkstorage_1_0.Client.class){
|
||||||
|
return new com.aliyun.dingtalkstorage_1_0.Client(config);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getAccessToken() throws Exception {
|
||||||
|
String token = redisCache.getCacheObject(ACCESS_TOKEN_KEY);
|
||||||
|
if(StringUtils.isEmpty(token)){
|
||||||
|
com.aliyun.dingtalkoauth2_1_0.Client client = (com.aliyun.dingtalkoauth2_1_0.Client) client(com.aliyun.dingtalkoauth2_1_0.Client.class);
|
||||||
|
GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest().setAppKey(DingGlobalParams.getClientId()).setAppSecret(DingGlobalParams.getClientSecret());
|
||||||
|
try {
|
||||||
|
GetAccessTokenResponse res = client.getAccessToken(getAccessTokenRequest);
|
||||||
|
token = res.getBody().getAccessToken();
|
||||||
|
//7200s- 10s,防止出现读取不超时, 请求超时
|
||||||
|
redisCache.setCacheObject(ACCESS_TOKEN_KEY, token, res.getBody().getExpireIn()-10);
|
||||||
|
} catch (TeaException err) {
|
||||||
|
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
|
||||||
|
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||||
|
log.error("获取token出现 TeaException 异常, 异常编码{}, 异常原因{}", err.getCode(), err.getMessage());
|
||||||
|
}
|
||||||
|
} catch (Exception _err) {
|
||||||
|
TeaException err = new TeaException(_err.getMessage(), _err);
|
||||||
|
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
|
||||||
|
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||||
|
log.error("获取token出现 Exception 异常, 异常编码{}, 异常原因{}", err.getCode(), err.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据手机号获取用户id
|
||||||
|
public static String getUserIdByPhoto(String photo){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getUrl()+"v2/user/getbymobile");
|
||||||
|
OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
|
||||||
|
req.setMobile(photo);
|
||||||
|
OapiV2UserGetbymobileResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据手机号获取用户id
|
||||||
|
public static String getUserInfoByUserId(String userId){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getUrl()+"v2/user/get");
|
||||||
|
OapiV2UserGetRequest req = new OapiV2UserGetRequest();
|
||||||
|
req.setUserid(userId);
|
||||||
|
OapiV2UserGetResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
/***
|
||||||
|
* 获取班次信息
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static String getShift(){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getUrl()+"attendance/shift/list");
|
||||||
|
OapiAttendanceShiftListRequest req = new OapiAttendanceShiftListRequest();
|
||||||
|
req.setOpUserId("03491015494921375480");
|
||||||
|
OapiAttendanceShiftListResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OapiAttendanceShiftQueryResponse.TopShiftVo getShiftDetail(Long id){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getBaseUrl()+"topapi/attendance/shift/query");
|
||||||
|
OapiAttendanceShiftQueryRequest req = new OapiAttendanceShiftQueryRequest();
|
||||||
|
req.setOpUserId("03491015494921375480");
|
||||||
|
req.setShiftId(id);
|
||||||
|
OapiAttendanceShiftQueryResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getResult();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OapiAttendanceGroupQueryResponse.TopSimpleGroupVO getGroupDetail(Long id){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getBaseUrl()+"topapi/attendance/group/query");
|
||||||
|
OapiAttendanceGroupQueryRequest req = new OapiAttendanceGroupQueryRequest();
|
||||||
|
req.setOpUserId("03491015494921375480");
|
||||||
|
req.setGroupId(id);
|
||||||
|
OapiAttendanceGroupQueryResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getResult();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取考勤组信息
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static String getAttendanceGroupList(){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getUrl()+"attendance/getsimplegroups");
|
||||||
|
OapiAttendanceGetsimplegroupsRequest req = new OapiAttendanceGetsimplegroupsRequest();
|
||||||
|
OapiAttendanceGetsimplegroupsResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取打卡详情
|
||||||
|
* @param dingUserIds 钉钉userId
|
||||||
|
* @param checkDateFrom 开始时间 yyyy-MM-dd HH:mm:ss
|
||||||
|
* @param checkDateTo 结束时间 yyyy-MM-dd HH:mm:ss
|
||||||
|
*/
|
||||||
|
public static String getListRecord(List<String> dingUserIds, String checkDateFrom, String checkDateTo){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getBaseUrl()+"attendance/listRecord");
|
||||||
|
OapiAttendanceListRecordRequest req = new OapiAttendanceListRecordRequest();
|
||||||
|
req.setUserIds(dingUserIds);
|
||||||
|
req.setCheckDateFrom(checkDateFrom);
|
||||||
|
req.setCheckDateTo(checkDateTo);
|
||||||
|
req.setIsI18n(false);
|
||||||
|
OapiAttendanceListRecordResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
System.out.println(rsp.getBody());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取审批详情
|
||||||
|
* @param processInstanceId 审批示例id
|
||||||
|
*/
|
||||||
|
public static GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult getProcessInstanceInfo(String processInstanceId){
|
||||||
|
try {
|
||||||
|
com.aliyun.dingtalkworkflow_1_0.Client client = (com.aliyun.dingtalkworkflow_1_0.Client) client(com.aliyun.dingtalkworkflow_1_0.Client.class);
|
||||||
|
com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders getProcessInstanceHeaders = new com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceHeaders();
|
||||||
|
getProcessInstanceHeaders.xAcsDingtalkAccessToken = getAccessToken();
|
||||||
|
com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest getProcessInstanceRequest = new com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceRequest();
|
||||||
|
getProcessInstanceRequest.setProcessInstanceId(processInstanceId);
|
||||||
|
try {
|
||||||
|
return client.getProcessInstanceWithOptions(getProcessInstanceRequest, getProcessInstanceHeaders, new com.aliyun.teautil.models.RuntimeOptions()).getBody().getResult();
|
||||||
|
} catch (TeaException err) {
|
||||||
|
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
|
||||||
|
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||||
|
log.error("获取token出现 TeaException 异常, 异常编码{}, 异常原因{}", err.getCode(), err.getMessage());
|
||||||
|
}
|
||||||
|
} catch (Exception _err) {
|
||||||
|
TeaException err = new TeaException(_err.getMessage(), _err);
|
||||||
|
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
|
||||||
|
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||||
|
log.error("获取token出现 Exception 异常, 异常编码{}, 异常原因{}", err.getCode(), err.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("=============>>> 获取审批实例出现异常, 异常原因为: {}", e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 获取排班详情
|
||||||
|
* @param userId
|
||||||
|
* @param planId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getPlanInfo(String userId, String planId){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getBaseUrl()+"attendance/schedule/result/listbyids");
|
||||||
|
OapiAttendanceScheduleResultListbyidsRequest req = new OapiAttendanceScheduleResultListbyidsRequest();
|
||||||
|
req.setOpUserId(userId);
|
||||||
|
req.setScheduleIds(planId);
|
||||||
|
OapiAttendanceScheduleResultListbyidsResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getDeptInfo(Long deptId){
|
||||||
|
try {
|
||||||
|
DingTalkClient client = new DefaultDingTalkClient(DingGlobalParams.getUrl()+"v2/department/get");
|
||||||
|
OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
|
||||||
|
req.setDeptId(deptId);
|
||||||
|
OapiV2DepartmentGetResponse rsp = client.execute(req, getAccessToken());
|
||||||
|
return rsp.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static GetFileUploadInfoResponseBody resourceUrls() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
com.aliyun.dingtalkstorage_1_0.Client client = (com.aliyun.dingtalkstorage_1_0.Client) client(com.aliyun.dingtalkstorage_1_0.Client.class);
|
||||||
|
com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoHeaders getFileUploadInfoHeaders = new com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoHeaders();
|
||||||
|
getFileUploadInfoHeaders.xAcsDingtalkAccessToken = getAccessToken();
|
||||||
|
com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoRequest getFileUploadInfoRequest = new com.aliyun.dingtalkstorage_1_0.models.GetFileUploadInfoRequest();
|
||||||
|
getFileUploadInfoRequest.setUnionId("IQ4KFIKVugR3UYfNOii5VzwiEiE");
|
||||||
|
getFileUploadInfoRequest.setProtocol("HEADER_SIGNATURE");
|
||||||
|
return client.getFileUploadInfoWithOptions("28629173113", getFileUploadInfoRequest, getFileUploadInfoHeaders, new com.aliyun.teautil.models.RuntimeOptions()).getBody();
|
||||||
|
} catch (TeaException err) {
|
||||||
|
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
|
||||||
|
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||||
|
log.error("获取resourceUrls出现 TeaException 异常, 异常编码{}, 异常原因{}", err.getCode(), err.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception _err) {
|
||||||
|
TeaException err = new TeaException(_err.getMessage(), _err);
|
||||||
|
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
|
||||||
|
// err 中含有 code 和 message 属性,可帮助开发定位问题
|
||||||
|
log.error("获取resourceUrls出现 Exception 异常, 异常编码{}, 异常原因{}", err.getCode(), err.getMessage());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
25
evo-admin/src/main/java/com/evo/ding/domain/DingGroup.java
Normal file
25
evo-admin/src/main/java/com/evo/ding/domain/DingGroup.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package com.evo.ding.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShift
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShift
|
||||||
|
* @date: 2026年03月04日 13:50
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DingGroup implements Serializable {
|
||||||
|
|
||||||
|
/** 主键 */
|
||||||
|
private Long id;
|
||||||
|
/** 班次名称 */
|
||||||
|
public String name;
|
||||||
|
/** 钉钉的班次id */
|
||||||
|
public String dingId;
|
||||||
|
|
||||||
|
}
|
||||||
33
evo-admin/src/main/java/com/evo/ding/domain/DingShift.java
Normal file
33
evo-admin/src/main/java/com/evo/ding/domain/DingShift.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package com.evo.ding.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShift
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShift
|
||||||
|
* @date: 2026年03月04日 13:50
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DingShift implements Serializable {
|
||||||
|
|
||||||
|
/** 主键 */
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/** 班次名称 */
|
||||||
|
public String name;
|
||||||
|
/** 钉钉的班次id */
|
||||||
|
public String dingId;
|
||||||
|
/** 工作时长 */
|
||||||
|
public Integer workHour;
|
||||||
|
/** 上班基准时间节点 */
|
||||||
|
public String onDutyCheckTime;
|
||||||
|
/** 下班基准时间节点 */
|
||||||
|
public String offDutyCheckTime;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.evo.ding.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShift
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShift
|
||||||
|
* @date: 2026年03月04日 13:50
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DingShiftGroup implements Serializable {
|
||||||
|
|
||||||
|
/** 主键 */
|
||||||
|
private Long id;
|
||||||
|
/** 钉钉的groupId */
|
||||||
|
public String groupId;
|
||||||
|
/** 钉钉的班次id */
|
||||||
|
public String shiftId;
|
||||||
|
/** type 打卡类型 */
|
||||||
|
public String type;
|
||||||
|
/** type 打卡类型 */
|
||||||
|
public String checkTime;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String shiftName;
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.evo.ding.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.evo.ding.domain.DingGroup;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingGroupMapper
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShiftGroupMapper
|
||||||
|
* @date: 2026年03月05日 14:47
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingGroupMapper extends BaseMapper<DingGroup> {
|
||||||
|
|
||||||
|
public DingGroup selectByDingId(@Param("dingId") String dingId);
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.evo.ding.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShiftGroupMapper
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShiftGroupMapper
|
||||||
|
* @date: 2026年03月05日 14:47
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingShiftGroupMapper extends BaseMapper<DingShiftGroup> {
|
||||||
|
|
||||||
|
DingShiftGroup selectByGroupIdAndTypeAndCheckTime(@Param("groupId") String groupId, @Param("shiftId")String shiftId, @Param("type") String type, @Param("checkTime") String checkTime);
|
||||||
|
|
||||||
|
int updateCheckTimeByShiftIdAndType(@Param("shiftId")String shiftId, @Param("type")String type, @Param("checkTime")String checkTime);
|
||||||
|
|
||||||
|
List<DingShiftGroup> selectListByShiftId(@Param("shiftId") String shiftId);
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.evo.ding.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShiftGroupMapper
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShiftGroupMapper
|
||||||
|
* @date: 2026年03月05日 14:47
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingShiftMapper extends BaseMapper<DingShift> {
|
||||||
|
|
||||||
|
public DingShift selectByDingId(@Param("dingId") String dingId);
|
||||||
|
|
||||||
|
public List<DingShift> selectList(DingShift dingShift);
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
package com.evo.ding.processor;
|
||||||
|
|
||||||
|
import com.evo.attendance.service.IRzAttendanceService;
|
||||||
|
import com.evo.attendance.service.RzAttendanceDetailService;
|
||||||
|
import com.evo.common.utils.Collections;
|
||||||
|
import com.evo.common.utils.spring.SpringUtils;
|
||||||
|
import com.evo.ding.service.DingShiftGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftService;
|
||||||
|
import com.evo.personnelMatters.service.IRzLeaveDetailService;
|
||||||
|
import com.evo.personnelMatters.service.IRzLeaveService;
|
||||||
|
import com.evo.personnelMatters.service.IRzOverTimeDetailService;
|
||||||
|
import com.evo.personnelMatters.service.IRzOverTimeService;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import com.evo.system.service.ISysStaffService;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉回调基础类型 DingBaseExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingBaseExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 11:05
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingBasicExchangeProcessor {
|
||||||
|
|
||||||
|
final Map<String, Object> p = Collections.emptyMap();
|
||||||
|
//审批状态
|
||||||
|
String APPROVE_STATUS = "COMPLETED";
|
||||||
|
|
||||||
|
String APPROVE_RESULT = "AGREE";
|
||||||
|
|
||||||
|
default ISysStaffService getISysStaffService(){
|
||||||
|
if(!p.containsKey("sysStaffService")){
|
||||||
|
p.put("sysStaffService", SpringUtils.getBean(ISysStaffService.class));
|
||||||
|
}
|
||||||
|
return (ISysStaffService)p.get("sysStaffService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default IRzAttendanceService getIRzAttendanceService(){
|
||||||
|
if(!p.containsKey("rzAttendanceService")){
|
||||||
|
p.put("rzAttendanceService", SpringUtils.getBean(IRzAttendanceService.class));
|
||||||
|
}
|
||||||
|
return (IRzAttendanceService)p.get("rzAttendanceService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default RzAttendanceDetailService getRzAttendanceDetailService(){
|
||||||
|
if(!p.containsKey("rzAttendanceDetailService")){
|
||||||
|
p.put("rzAttendanceDetailService", SpringUtils.getBean(RzAttendanceDetailService.class));
|
||||||
|
}
|
||||||
|
return (RzAttendanceDetailService)p.get("rzAttendanceDetailService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default IRzOverTimeService getIRzOverTimeService(){
|
||||||
|
if(!p.containsKey("rzOverTimeService")){
|
||||||
|
p.put("rzOverTimeService", SpringUtils.getBean(IRzOverTimeService.class));
|
||||||
|
}
|
||||||
|
return (IRzOverTimeService)p.get("rzOverTimeService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default IRzOverTimeDetailService getIRzOverTimeDetailService(){
|
||||||
|
if(!p.containsKey("rzOverTimeDetailService")){
|
||||||
|
p.put("rzOverTimeDetailService", SpringUtils.getBean(IRzOverTimeDetailService.class));
|
||||||
|
}
|
||||||
|
return (IRzOverTimeDetailService)p.get("rzOverTimeDetailService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default DingShiftService getDingShiftService(){
|
||||||
|
if(!p.containsKey("dingShiftService")){
|
||||||
|
p.put("dingShiftService", SpringUtils.getBean(DingShiftService.class));
|
||||||
|
}
|
||||||
|
return (DingShiftService)p.get("dingShiftService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default DingShiftGroupService getDingShiftGroupService(){
|
||||||
|
if(!p.containsKey("dingShiftGroupService")){
|
||||||
|
p.put("dingShiftGroupService", SpringUtils.getBean(DingShiftGroupService.class));
|
||||||
|
}
|
||||||
|
return (DingShiftGroupService)p.get("dingShiftGroupService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default IRzLeaveService getIRzLeaveService(){
|
||||||
|
if(!p.containsKey("rzLeaveService")){
|
||||||
|
p.put("rzLeaveService", SpringUtils.getBean(IRzLeaveService.class));
|
||||||
|
}
|
||||||
|
return (IRzLeaveService)p.get("rzLeaveService");
|
||||||
|
}
|
||||||
|
|
||||||
|
default IRzLeaveDetailService getIRzLeaveDetailService(){
|
||||||
|
if(!p.containsKey("rzLeaveDetailService")){
|
||||||
|
p.put("rzLeaveDetailService", SpringUtils.getBean(IRzLeaveDetailService.class));
|
||||||
|
}
|
||||||
|
return (IRzLeaveDetailService)p.get("rzLeaveDetailService");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
default SysStaff getSysStaffByDingUserId(String dingUserId){
|
||||||
|
SysStaff sysStaff = getISysStaffService().selectSysStaffByDingUserId(dingUserId);
|
||||||
|
if(sysStaff == null){
|
||||||
|
throw new RuntimeException("未查询到用户信息, 用户的DingUserId为:"+dingUserId);
|
||||||
|
}
|
||||||
|
return sysStaff;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.evo.ding.processor.approveStatus;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.evo.ding.processor.DingBasicExchangeProcessor;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请假、加班、出差、外出状态变更事件 回调 InstanceChangeExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:InstanceChangeExchangeProcessor
|
||||||
|
* @date: 2026年03月09日 15:25
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface AttendanceApproveStatusChangeExchangeProcessor extends DingBasicExchangeProcessor {
|
||||||
|
|
||||||
|
Logger logger = LoggerFactory.getLogger(AttendanceApproveStatusChangeExchangeProcessor.class);
|
||||||
|
//请假
|
||||||
|
String APPROVE_TYPE_LEAVE = "LEAVE";
|
||||||
|
//加班
|
||||||
|
String APPROVE_TYPE_OVERTIME = "OVERTIME";
|
||||||
|
//请假
|
||||||
|
String APPROVE_TYPE_OUT = "OUT";
|
||||||
|
//撤销
|
||||||
|
String BIZ_ACTION_REVOKE = "REVOKE";
|
||||||
|
|
||||||
|
boolean accept(String approveType, String result, String status);
|
||||||
|
|
||||||
|
void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json);
|
||||||
|
|
||||||
|
default JSONObject getExtValue(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json, String componentType) {
|
||||||
|
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValueList = json.getFormComponentValues();
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues formComponentValue = formComponentValueList.stream().filter(data -> componentType.equals(data.getComponentType())).findAny().orElse(null);
|
||||||
|
if(formComponentValue != null){
|
||||||
|
return JSON.parseObject(formComponentValue.getExtValue());
|
||||||
|
}
|
||||||
|
throw new RuntimeException("未查询到相关审批信息, 审批类型为:"+componentType+"; 参数信息为: "+ json.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
default JSONArray getValue(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json, String componentType) {
|
||||||
|
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValueList = json.getFormComponentValues();
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues formComponentValue = formComponentValueList.stream().filter(data -> componentType.equals(data.getComponentType())).findAny().orElse(null);
|
||||||
|
if(formComponentValue != null){
|
||||||
|
return JSON.parseArray(formComponentValue.getValue());
|
||||||
|
}
|
||||||
|
throw new RuntimeException("未查询到相关审批信息, 审批类型为:"+componentType+"; 参数信息为: "+ json.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package com.evo.ding.processor.approveStatus.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.evo.common.constant.Constants;
|
||||||
|
import com.evo.common.core.domain.entity.SysDictData;
|
||||||
|
import com.evo.common.utils.DataUtils;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.processor.approveStatus.AttendanceApproveStatusChangeExchangeProcessor;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeave;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import com.evo.system.service.ISysDictDataService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请假事件处理 ApproveStatusLeaveExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:ApproveStatusLeaveExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 13:32
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ApproveStatusLeaveExchangeProcessor implements AttendanceApproveStatusChangeExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ISysDictDataService sysDictDataService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String approveType, String result, String status) {
|
||||||
|
return APPROVE_TYPE_LEAVE.equals(approveType.toUpperCase()) && APPROVE_STATUS.equals(status.toUpperCase()) && APPROVE_RESULT.equals(result.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
//如果是撤销, 执行撤销
|
||||||
|
if(BIZ_ACTION_REVOKE.equals(json.getBizAction())){
|
||||||
|
revoke(processInstanceId);
|
||||||
|
}else{
|
||||||
|
leave(processInstanceId, getSysStaffByDingUserId(json.getOriginatorUserId()), json);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("执行钉钉 -["+(BIZ_ACTION_REVOKE.equals(json.getBizAction()) ? "撤销" : "请假")+"审批]-回调出现异常, 异常原因为:{}", e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 撤销假期
|
||||||
|
* @param processInstanceId 钉钉审批单详情
|
||||||
|
*/
|
||||||
|
public void revoke(String processInstanceId){
|
||||||
|
RzLeaveDetail rzLeaveDetail = getIRzLeaveDetailService().selectRzLeaveDetailByProcessInstanceId(processInstanceId);
|
||||||
|
if(rzLeaveDetail != null){
|
||||||
|
getIRzLeaveDetailService().deleteRzLeaveDetailById(rzLeaveDetail.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 请假
|
||||||
|
* @param processInstanceId 钉钉审批单详情
|
||||||
|
* @param sysStaff 平台用户
|
||||||
|
* @param json 请求数据信息
|
||||||
|
*/
|
||||||
|
public void leave(String processInstanceId, SysStaff sysStaff, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
|
||||||
|
|
||||||
|
JSONObject extValueJson = getExtValue(json, "DDHolidayField");
|
||||||
|
//解析假期类型
|
||||||
|
JSONObject extension = JSON.parseObject(extValueJson.getString("extension"));
|
||||||
|
//查询假期类型
|
||||||
|
String tag = extension.getString("tag");
|
||||||
|
SysDictData sysDictData = sysDictDataService.selectDictDataListByType("holidays_type").stream().filter(data-> StringUtils.equals(data.getDictLabel(),tag)).findFirst().orElse(null);
|
||||||
|
if(sysDictData != null){
|
||||||
|
//假期类型的code
|
||||||
|
Long dictCode = sysDictData.getDictCode();
|
||||||
|
JSONArray detailList = extValueJson.getJSONArray("detailList");
|
||||||
|
Date beginTime = null;
|
||||||
|
Date endTime = null;
|
||||||
|
//如果大于1 证明是多天请假, 需要排序
|
||||||
|
if(detailList.size() > 1){
|
||||||
|
detailList.sort((a,b)->{
|
||||||
|
return ((JSONObject) a).getLong("workDate").compareTo(((JSONObject) b).getLong("workDate"));
|
||||||
|
});
|
||||||
|
//获取第一天
|
||||||
|
beginTime = new Date(detailList.getJSONObject(0).getJSONObject("approveInfo").getLong("fromTime"));
|
||||||
|
//获取最后一天
|
||||||
|
endTime = new Date(detailList.getJSONObject(detailList.size()-1).getJSONObject("approveInfo").getLong("toTime"));
|
||||||
|
}else{
|
||||||
|
//只请一天假
|
||||||
|
JSONObject approveInfo = detailList.getJSONObject(0).getJSONObject("approveInfo");
|
||||||
|
beginTime = new Date(approveInfo.getLong("fromTime"));
|
||||||
|
//获取最后一天
|
||||||
|
endTime = new Date(approveInfo.getLong("toTime"));
|
||||||
|
}
|
||||||
|
|
||||||
|
RzLeave rzLeave = getIRzLeaveService().selectRzLeaveByUserId(sysStaff.getUserId());
|
||||||
|
RzLeaveDetail rzLeaveDetail = new RzLeaveDetail();
|
||||||
|
rzLeaveDetail.setName(sysStaff.getName());
|
||||||
|
rzLeaveDetail.setLeaveStartTime(beginTime);
|
||||||
|
rzLeaveDetail.setLeaveEndTime(endTime);
|
||||||
|
rzLeaveDetail.setLeaveId(rzLeave.getId());
|
||||||
|
rzLeaveDetail.setType(dictCode);
|
||||||
|
// if("调休".equals(tag)){
|
||||||
|
rzLeaveDetail.setLeaveHour(new BigDecimal(extValueJson.getDouble("durationInDay")).multiply(Constants.DAY_WORK_HOUR).intValue());
|
||||||
|
// }else{
|
||||||
|
// rzLeaveDetail.setLeaveHour(extValueJson.getInteger("durationInHour"));
|
||||||
|
// }
|
||||||
|
rzLeaveDetail.setRemarks("钉钉"+tag);
|
||||||
|
rzLeaveDetail.setProcessInstanceId(processInstanceId);
|
||||||
|
getIRzLeaveDetailService().insertRzLeaveDetail(rzLeaveDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package com.evo.ding.processor.approveStatus.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.evo.attendance.domain.RzAttendance;
|
||||||
|
import com.evo.attendance.domain.RzAttendanceDetail;
|
||||||
|
import com.evo.attendance.mapper.RzAttendanceMapper;
|
||||||
|
import com.evo.attendance.service.IRzAttendanceService;
|
||||||
|
import com.evo.attendance.service.RzAttendanceDetailService;
|
||||||
|
import com.evo.common.core.domain.entity.SysDictData;
|
||||||
|
import com.evo.common.utils.ParamUtils;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.processor.approveStatus.AttendanceApproveStatusChangeExchangeProcessor;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeave;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import com.evo.system.service.ISysDictDataService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出差事件处理 ApproveStatusOutExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:ApproveStatusLeaveExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 13:32
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ApproveStatusOutExchangeProcessor implements AttendanceApproveStatusChangeExchangeProcessor {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RzAttendanceMapper rzAttendanceMapper;
|
||||||
|
@Resource
|
||||||
|
private RzAttendanceDetailService rzAttendanceDetailService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String approveType, String result, String status) {
|
||||||
|
return APPROVE_TYPE_OUT.equals(approveType.toUpperCase()) && APPROVE_STATUS.equals(status.toUpperCase()) && APPROVE_RESULT.equals(result.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json) {
|
||||||
|
try {
|
||||||
|
rzAttendance(json, BIZ_ACTION_REVOKE.equals(json.getBizAction()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("执行钉钉 -[出差审批]-回调出现异常, 异常原因为:{}", e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/***
|
||||||
|
*
|
||||||
|
* @param json 审批单数据
|
||||||
|
* @param isRevoke 是否为撤回
|
||||||
|
*/
|
||||||
|
public void rzAttendance(GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult json, Boolean isRevoke){
|
||||||
|
SysStaff sysStaff = getSysStaffByDingUserId(json.getOriginatorUserId());
|
||||||
|
//出差
|
||||||
|
JSONArray valueJson = getValue(json, "TableField");
|
||||||
|
JSONObject jsonObject = valueJson.getJSONObject(0);
|
||||||
|
JSONArray rowValue = jsonObject.getJSONArray("rowValue");
|
||||||
|
for (int i = 0; i < rowValue.size(); i++) {
|
||||||
|
JSONObject rowValueObject = rowValue.getJSONObject(i);
|
||||||
|
if ("duration".equals(rowValueObject.getString("bizAlias"))) {
|
||||||
|
JSONObject extendValue = rowValueObject.getJSONObject("extendValue");
|
||||||
|
JSONArray detailList = extendValue.getJSONArray("detailList");
|
||||||
|
for (int j = 0; j < detailList.size(); j++) {
|
||||||
|
JSONObject detailObject = detailList.getJSONObject(j);
|
||||||
|
Date formatWorkDate = Date.from(Instant.ofEpochMilli(detailObject.getLong("workDate")));
|
||||||
|
//检查是否为假期, 如果为假期, 不做记录, 只记录不是假期的数据, 假期的外出, 需要提交加班审批
|
||||||
|
if (!ParamUtils.checkHoliday(formatWorkDate)) {
|
||||||
|
JSONObject classInfo = detailObject.getJSONObject("classInfo");
|
||||||
|
JSONObject section = classInfo.getJSONArray("sections").getJSONObject(0);
|
||||||
|
Long startTime = section.getLong("startTime");
|
||||||
|
Long endTime = section.getLong("endTime");
|
||||||
|
Integer durationInHour = detailObject.getJSONObject("approveInfo").getInteger("durationInHour");
|
||||||
|
Date formatStartTime = Date.from(Instant.ofEpochMilli(startTime));
|
||||||
|
Date formatEndTime = Date.from(Instant.ofEpochMilli(endTime));
|
||||||
|
//通过workDate 获取哪一天的卡
|
||||||
|
RzAttendance attendance = rzAttendanceMapper.queryNowDayAttendanceByStatisticalIdAndDate(sysStaff.getUserId(), formatStartTime);
|
||||||
|
if(isRevoke){
|
||||||
|
//清除打卡记录
|
||||||
|
rzAttendanceDetailService.remove(new LambdaQueryWrapper<RzAttendanceDetail>().eq(RzAttendanceDetail::getAttendanceId, attendance.getId()));
|
||||||
|
//重置打卡信息
|
||||||
|
attendance.setRules("");
|
||||||
|
attendance.setWorkStartTime(null);
|
||||||
|
attendance.setWorkEndTime(null);
|
||||||
|
attendance.setWorkSum(BigDecimal.valueOf(0));
|
||||||
|
attendance.setNightNumber(0);
|
||||||
|
attendance.setMiddleShiftNumber(0);
|
||||||
|
}else{
|
||||||
|
//生成打卡记录
|
||||||
|
rzAttendanceDetailService.addDetail(attendance, "上班卡", "/", formatStartTime, "出差自动打卡", "");
|
||||||
|
rzAttendanceDetailService.addDetail(attendance, "下班卡", "/", formatEndTime, "出差自动打卡", "");
|
||||||
|
//上班
|
||||||
|
attendance.setRules("上班卡");
|
||||||
|
attendance.setWorkStartTime(formatStartTime);
|
||||||
|
attendance.setWorkEndTime(formatEndTime);
|
||||||
|
attendance.setWorkSum(BigDecimal.valueOf(durationInHour));
|
||||||
|
if (attendance.getWorkSum().intValue() >= 12 && attendance.getWorkStartTime() != null && attendance.getWorkStartTime().getHours() > 12) {
|
||||||
|
attendance.setNightNumber(1);
|
||||||
|
} else if (attendance.getWorkSum().intValue() >= 8 && attendance.getWorkStartTime() != null && attendance.getWorkStartTime().getHours() >= 12 && attendance.getWorkStartTime().getHours() < 21) {
|
||||||
|
attendance.setMiddleShiftNumber(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rzAttendanceMapper.updateRzAttendance(attendance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
package com.evo.ding.processor.approveStatus.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.evo.attendance.domain.RzAttendanceStatistical;
|
||||||
|
import com.evo.attendance.domain.RzSpecialAttendance;
|
||||||
|
import com.evo.attendance.domain.RzSpecialOverTime;
|
||||||
|
import com.evo.attendance.mapper.RzAttendanceStatisticalMapper;
|
||||||
|
import com.evo.attendance.mapper.RzSpecialAttendanceMapper;
|
||||||
|
import com.evo.attendance.mapper.RzSpecialOverTimeMapper;
|
||||||
|
import com.evo.attendance.service.IRzAttendanceStatisticalService;
|
||||||
|
import com.evo.attendance.service.IRzSpecialAttendanceService;
|
||||||
|
import com.evo.common.core.domain.entity.SysDictData;
|
||||||
|
import com.evo.common.utils.DataUtils;
|
||||||
|
import com.evo.common.utils.DateUtils;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.processor.approveStatus.AttendanceApproveStatusChangeExchangeProcessor;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeave;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import com.evo.system.service.ISysDictDataService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*加班事件处理 ApproveStatusOvertimeExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:ApproveStatusLeaveExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 13:32
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ApproveStatusOvertimeExchangeProcessor implements AttendanceApproveStatusChangeExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
IRzSpecialAttendanceService rzSpecialAttendanceService;
|
||||||
|
@Resource
|
||||||
|
private RzSpecialOverTimeMapper rzSpecialOverTimeMapper;
|
||||||
|
@Resource
|
||||||
|
private RzAttendanceStatisticalMapper rzAttendanceStatisticalMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String approveType, String result, String status) {
|
||||||
|
//加班不在对接
|
||||||
|
return false; //APPROVE_TYPE_OVERTIME.equals(approveType.toUpperCase()) && APPROVE_STATUS.equals(status.toUpperCase()) && APPROVE_RESULT.equals(result.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void exchange(String processInstanceId, GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result) {
|
||||||
|
try {
|
||||||
|
SysStaff sysStaff = getSysStaffByDingUserId(result.getOriginatorUserId());
|
||||||
|
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> formComponentValueList = result.getFormComponentValues();
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues startComponentValue = formComponentValueList.stream().filter(data -> "开始时间".equals(data.getName())).findAny().orElse(null);
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues endValue = formComponentValueList.stream().filter(data -> "结束时间".equals(data.getName())).findAny().orElse(null);
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues durationValue = formComponentValueList.stream().filter(data -> "时长".equals(data.getName())).findAny().orElse(null);
|
||||||
|
if(startComponentValue != null && endValue != null && durationValue != null){
|
||||||
|
Date startDate = DateUtils.parseDate(startComponentValue.getValue(), "yyyy-MM-dd HH:mm");
|
||||||
|
Date endDate = DateUtils.parseDate(endValue.getValue(), "yyyy-MM-dd HH:mm");
|
||||||
|
BigDecimal duration = new BigDecimal(durationValue.getValue());
|
||||||
|
//获取加班详情数据
|
||||||
|
RzSpecialAttendance rzSpecialAttendance = rzSpecialAttendanceService.selectRzSpecialAttendanceByUserIdAndDate(sysStaff.getUserId(), startDate);
|
||||||
|
//如果没有, 则新增
|
||||||
|
if(rzSpecialAttendance == null){
|
||||||
|
rzSpecialAttendance = new RzSpecialAttendance();
|
||||||
|
rzSpecialAttendance.setAttendanceDate(startDate);
|
||||||
|
rzSpecialAttendance.setStaffId(sysStaff.getUserId());
|
||||||
|
rzSpecialAttendance.setName(sysStaff.getName());
|
||||||
|
rzSpecialAttendance.setDeptId(sysStaff.getDeptId());
|
||||||
|
rzSpecialAttendance.setDelFlag("0");
|
||||||
|
rzSpecialAttendance.setCreateBy("admin");
|
||||||
|
rzSpecialAttendance.setCreateTime(new Date());
|
||||||
|
}
|
||||||
|
rzSpecialAttendance.setWorkStartTime(startDate);
|
||||||
|
rzSpecialAttendance.setWorkEndTime(endDate);
|
||||||
|
rzSpecialAttendance.setWorkHours(duration);
|
||||||
|
rzSpecialAttendanceService.saveOrUpdate(rzSpecialAttendance);
|
||||||
|
|
||||||
|
//获取加班统计数据
|
||||||
|
RzSpecialOverTime rzSpecialOverTime = rzSpecialOverTimeMapper.selectRzSpecialOverTimeByUserIdAndDate(rzSpecialAttendance.getStaffId(),rzSpecialAttendance.getAttendanceDate());
|
||||||
|
if(ObjectUtils.isEmpty(rzSpecialOverTime)){
|
||||||
|
rzSpecialOverTime = new RzSpecialOverTime();
|
||||||
|
rzSpecialOverTime.setUserId(sysStaff.getUserId());
|
||||||
|
rzSpecialOverTime.setName(sysStaff.getName());
|
||||||
|
rzSpecialOverTime.setDeptId(sysStaff.getDeptId());
|
||||||
|
rzSpecialOverTime.setDelFlag("0");
|
||||||
|
rzSpecialOverTime.setOverDate(startDate);
|
||||||
|
rzSpecialOverTime.setCreateTime(new Date());
|
||||||
|
rzSpecialOverTime.setCreateBy("admin");
|
||||||
|
rzSpecialOverTimeMapper.insertRzSpecialOverTime(rzSpecialOverTime);
|
||||||
|
}
|
||||||
|
if(DataUtils.DEFAULT_VALUE.compareTo(rzSpecialAttendance.getWorkHours()) != 0){
|
||||||
|
rzSpecialOverTime.setSickHours(DataUtils.findDefaultValue(rzSpecialOverTime.getSickHours(), new BigDecimal(0)).add(rzSpecialAttendance.getWorkHours()));
|
||||||
|
rzSpecialOverTimeMapper.updateRzSpecialOverTime(rzSpecialOverTime);
|
||||||
|
//更新加班统计
|
||||||
|
RzAttendanceStatistical rzAttendanceStatistical = rzAttendanceStatisticalMapper.getRzAttendanceStatisticalByDateAndName(rzSpecialAttendance.getStaffId(),rzSpecialAttendance.getAttendanceDate());
|
||||||
|
rzAttendanceStatistical.setOverTimeHours(DataUtils.findDefaultValue(rzAttendanceStatistical.getOverTimeHours(), new BigDecimal(0)).add(rzSpecialAttendance.getWorkHours()));
|
||||||
|
rzAttendanceStatisticalMapper.updateRzAttendanceStatistical(rzAttendanceStatistical);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("执行钉钉 -[加班审批]-回调出现异常, 异常原因为:{}", e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.evo.ding.processor.callback;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉回调入口 DingCallBackExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackExchanageProcessor
|
||||||
|
* @date: 2026年03月12日 8:49
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
//入职
|
||||||
|
static final String EVENT_TYPE_USER_ADD_ORG = "user_add_org";
|
||||||
|
//离职
|
||||||
|
static final String EVENT_TYPE_USER_LEAVE_ORG = "user_leave_org";
|
||||||
|
//打卡
|
||||||
|
static final String EVENT_TYPE_CHECK_RECORD = "attendance_check_record";
|
||||||
|
//审批实例订阅-> 补卡
|
||||||
|
static final String EVENT_TYPE_INSTANCE_CHANGE = "bpms_instance_change";
|
||||||
|
//请假、加班、出差、外出状态变更事件
|
||||||
|
static final String EVENT_TYPE_APPROVE_STATUS_CHANGE = "attendance_approve_status_change";
|
||||||
|
//班制调整
|
||||||
|
static final String EVENT_TYPE_ATTEND_SHIFT_CHANGE = "attend_shift_change";
|
||||||
|
//考勤组调整
|
||||||
|
static final String EVENT_TYPE_ATTEND_GROUP_CHANGE = "attend_group_change";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
boolean accept(String eventType);
|
||||||
|
|
||||||
|
void exchange(JSONObject json);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
|
import com.evo.ding.processor.approveStatus.AttendanceApproveStatusChangeExchangeProcessor;
|
||||||
|
import com.evo.ding.processor.instance.InstanceChangeExchangeProcessor;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请假、加班、出差、外出状态变更事件 DingCallBackInstanceChangeExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackCheckRecordExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackApproveStatusChangeExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
List<AttendanceApproveStatusChangeExchangeProcessor> approveStatusChangeExchangeProcessorList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_APPROVE_STATUS_CHANGE.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("请假、加班、出差、外出状态变更事件 回调 ========================>>>{}", json.toString());
|
||||||
|
//获取审批示例id
|
||||||
|
String processInstanceId = json.getString("processInstanceId");
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result = DingUtils.getProcessInstanceInfo(processInstanceId);
|
||||||
|
System.out.println(JSONObject.toJSONString(result));
|
||||||
|
for (AttendanceApproveStatusChangeExchangeProcessor processor : approveStatusChangeExchangeProcessorList) {
|
||||||
|
if (processor.accept(json.getString("approveType"), result.getResult(), result.getStatus())) {
|
||||||
|
processor.exchange(processInstanceId, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.attendance.service.IRzAttendanceService;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工打开回调 DingCallBackCheckRecordExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackCheckRecordExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackCheckRecordExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
IRzAttendanceService rzAttendanceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_CHECK_RECORD.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("钉钉 打卡回调========================>>>{}", json.toString());
|
||||||
|
JSONArray dataList = json.getJSONArray("DataList");
|
||||||
|
if(dataList!= null && dataList.size() > 0){
|
||||||
|
JSONObject jsonObject = dataList.getJSONObject(0);
|
||||||
|
String userId = jsonObject.getString("userId");
|
||||||
|
if(StringUtils.isNotEmpty(userId)){
|
||||||
|
rzAttendanceService.dingDing(userId, jsonObject.getString("bizId"), jsonObject.getLong("checkTime"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.dingtalk.api.response.OapiAttendanceGroupQueryResponse;
|
||||||
|
import com.dingtalk.api.response.OapiAttendanceShiftQueryResponse;
|
||||||
|
import com.evo.common.utils.Collections;
|
||||||
|
import com.evo.common.utils.DateUtils;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
|
import com.evo.ding.domain.DingGroup;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import com.evo.ding.service.DingGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftService;
|
||||||
|
import io.swagger.models.auth.In;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 考勤组信息调整 DingCallBackGroupChangeExchangeProcessor
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackCheckRecordExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackGroupChangeExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DingGroupService dingGroupService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DingShiftService dingShiftService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DingShiftGroupService dingShiftGroupService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_ATTEND_GROUP_CHANGE.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("钉钉 班制调整回调========================>>>{}", json.toString());
|
||||||
|
OapiAttendanceGroupQueryResponse.TopSimpleGroupVO groupDetail = DingUtils.getGroupDetail(json.getLong("id"));
|
||||||
|
if(groupDetail != null){
|
||||||
|
String groupDingId = String.valueOf(groupDetail.getId());
|
||||||
|
DingGroup dingGroup = dingGroupService.selectByDingId(groupDingId);
|
||||||
|
if(dingGroup == null){
|
||||||
|
dingGroup = new DingGroup();
|
||||||
|
}
|
||||||
|
dingGroup.setName(groupDetail.getName());
|
||||||
|
dingGroup.setDingId(groupDingId);
|
||||||
|
dingGroupService.saveOrUpdate(dingGroup);
|
||||||
|
|
||||||
|
//获取现在所有的数据
|
||||||
|
List<DingShiftGroup> dingShiftGroupList = dingShiftGroupService.selectListByGroupId(groupDingId);
|
||||||
|
//如果返回为空, 旧数据不为空, 直接清除
|
||||||
|
if(Collections.isEmpty(groupDetail.getShiftIds()) && Collections.isNotEmpty(dingShiftGroupList)){
|
||||||
|
dingShiftGroupService.removeByIds(dingShiftGroupList);
|
||||||
|
}else if(Collections.isNotEmpty(groupDetail.getShiftIds()) && Collections.isEmpty(dingShiftGroupList)){
|
||||||
|
//更新绑定信息
|
||||||
|
for (Long shiftId : groupDetail.getShiftIds()) {
|
||||||
|
crateDingShiftGroup(groupDingId, String.valueOf(shiftId));
|
||||||
|
}
|
||||||
|
}else if(Collections.isNotEmpty(groupDetail.getShiftIds()) && Collections.isNotEmpty(dingShiftGroupList)){
|
||||||
|
Map<String, List<DingShiftGroup>> map = dingShiftGroupList.stream().collect(Collectors.groupingBy(DingShiftGroup::getShiftId));
|
||||||
|
for (Long shiftId : groupDetail.getShiftIds()) {
|
||||||
|
String strShiftId = String.valueOf(shiftId);
|
||||||
|
if(map.containsKey(strShiftId)){
|
||||||
|
DingShift dingShift = dingShiftService.selectByDingIdEmptyCreate(strShiftId);
|
||||||
|
for (DingShiftGroup dingShiftGroup : map.get(strShiftId)){
|
||||||
|
dingShiftGroup.setCheckTime(("OnDuty".equals(dingShiftGroup.getType()) ? dingShift.getOnDutyCheckTime() : dingShift.getOffDutyCheckTime()));
|
||||||
|
dingShiftGroupService.updateById(dingShiftGroup);
|
||||||
|
}
|
||||||
|
map.remove(strShiftId);
|
||||||
|
}else{
|
||||||
|
crateDingShiftGroup(groupDingId, String.valueOf(shiftId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果还存在, 需要删除
|
||||||
|
if(Collections.isNotEmpty(map)){
|
||||||
|
dingShiftGroupService.removeByIds(map.values().stream().filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void crateDingShiftGroup(String groupId, String shiftId){
|
||||||
|
DingShift dingShift = dingShiftService.selectByDingIdEmptyCreate(shiftId);
|
||||||
|
//直接更新上班, 下班
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
DingShiftGroup dingShiftGroup = new DingShiftGroup();
|
||||||
|
dingShiftGroup.setGroupId(groupId);
|
||||||
|
dingShiftGroup.setShiftId(String.valueOf(shiftId));
|
||||||
|
dingShiftGroup.setType(i == 0 ? "OnDuty" : "OffDuty");
|
||||||
|
if(dingShift != null){
|
||||||
|
dingShiftGroup.setCheckTime(i == 0 ? dingShift.getOnDutyCheckTime() : dingShift.getOffDutyCheckTime());
|
||||||
|
}
|
||||||
|
dingShiftGroupService.save(dingShiftGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.ding.processor.instance.InstanceChangeExchangeProcessor;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批实例订阅 DingCallBackInstanceChangeExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackCheckRecordExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackInstanceChangeExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
List<InstanceChangeExchangeProcessor> instanceChangeExchangeProcessorList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_INSTANCE_CHANGE.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("审批实例订阅回调========================>>>{}", json.toString());
|
||||||
|
for (InstanceChangeExchangeProcessor processor : instanceChangeExchangeProcessorList) {
|
||||||
|
if (processor.accept(json.getString("processCode"))) {
|
||||||
|
processor.exchange(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.dingtalk.api.response.OapiAttendanceShiftQueryResponse;
|
||||||
|
import com.evo.common.utils.DateUtils;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import com.evo.ding.service.DingShiftGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班制信息调整 DingCallBackShiftChangeExchangeProcessor
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackCheckRecordExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackShiftChangeExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DingShiftService dingShiftService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DingShiftGroupService dingShiftGroupService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_ATTEND_SHIFT_CHANGE.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("钉钉 班制调整回调========================>>>{}", json.toString());
|
||||||
|
OapiAttendanceShiftQueryResponse.TopShiftVo shiftDetail = DingUtils.getShiftDetail(json.getLong("id"));
|
||||||
|
if(shiftDetail != null){
|
||||||
|
String shiftDingId = String.valueOf(shiftDetail.getId());
|
||||||
|
DingShift dingShift = dingShiftService.selectByDingId(shiftDingId);
|
||||||
|
//获取工作时长
|
||||||
|
OapiAttendanceShiftQueryResponse.TopShiftSettingVo topShiftSettingVo = shiftDetail.getShiftSetting();
|
||||||
|
|
||||||
|
OapiAttendanceShiftQueryResponse.TopSectionVo topSectionVo = shiftDetail.getSections().get(0);
|
||||||
|
OapiAttendanceShiftQueryResponse.TopPunchVo newOnDutyTopPunchVo = topSectionVo.getPunches().stream().filter(data -> data.getCheckType().equals("OnDuty")).findAny().orElse(null);
|
||||||
|
OapiAttendanceShiftQueryResponse.TopPunchVo newOffDutyTopPunchVo = topSectionVo.getPunches().stream().filter(data -> data.getCheckType().equals("OffDuty")).findAny().orElse(null);
|
||||||
|
//如果不存在班制, 创建新的班制
|
||||||
|
if(dingShift == null){
|
||||||
|
//如果本地不存在, 直接创建新的
|
||||||
|
dingShift = new DingShift();
|
||||||
|
dingShift.setName(shiftDetail.getName());
|
||||||
|
dingShift.setDingId(shiftDingId);
|
||||||
|
}
|
||||||
|
dingShift.setWorkHour(new BigDecimal(topShiftSettingVo.getWorkTimeMinutes()).divide(new BigDecimal(60), 2, java.math.BigDecimal.ROUND_HALF_UP).intValue());
|
||||||
|
dingShift.setOnDutyCheckTime(DateUtils.parseDateToStr("HH:mm:ss",newOnDutyTopPunchVo.getCheckTime()));
|
||||||
|
dingShift.setOffDutyCheckTime(DateUtils.parseDateToStr("HH:mm:ss",newOffDutyTopPunchVo.getCheckTime()));
|
||||||
|
//通过三目判定, 如果id为空, 则走保存,如果存在id 则更新
|
||||||
|
if((dingShift.getId() == null ? dingShiftService.save(dingShift) : dingShiftService.updateById(dingShift))){
|
||||||
|
dingShiftGroupService.updateCheckTimeByShiftIdAndType(shiftDingId, newOnDutyTopPunchVo.getCheckType(), dingShift.getOnDutyCheckTime());
|
||||||
|
dingShiftGroupService.updateCheckTimeByShiftIdAndType(shiftDingId, newOffDutyTopPunchVo.getCheckType(), dingShift.getOffDutyCheckTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import com.evo.system.service.ISysStaffService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工离职 DingCallBackUseLeaveOrgExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackUseLeaveOrgExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackUseLeaveOrgExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ISysStaffService sysStaffService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_USER_LEAVE_ORG.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("钉钉 员工离职========================>>>{}", json.toString());
|
||||||
|
JSONArray dataList = json.getJSONArray("userId");
|
||||||
|
if(dataList!= null && dataList.size() > 0){
|
||||||
|
dataList.forEach(data->{
|
||||||
|
sysStaffService.sysStaffLeaveByDingUserId(String.valueOf(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.evo.ding.processor.callback.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.attendance.service.IRzAttendanceService;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
|
import com.evo.ding.processor.callback.DingCallBackExchangeProcessor;
|
||||||
|
import com.evo.system.service.ISysStaffService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工入职 DingCallBackUserAddOrgExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingCallBackUserAddOrgExchangeProcessor
|
||||||
|
* @date: 2026年03月12日 9:02
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DingCallBackUserAddOrgExchangeProcessor implements DingCallBackExchangeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ISysStaffService sysStaffService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String eventType) {
|
||||||
|
return EVENT_TYPE_USER_ADD_ORG.equals(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
log.info("钉钉 新增员工========================>>>{}", json.toString());
|
||||||
|
JSONArray dataList = json.getJSONArray("UserId");
|
||||||
|
if(dataList!= null && dataList.size() > 0){
|
||||||
|
dataList.forEach(data->{
|
||||||
|
sysStaffService.insertSysStaffByDingDing(DingUtils.getUserInfoByUserId(String.valueOf(data)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.evo.ding.processor.instance;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.evo.ding.processor.DingBasicExchangeProcessor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉审批实例回调处理接口 InstanceChangeExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:InstanceChangeExchangeProcessor
|
||||||
|
* @date: 2026年03月09日 15:25
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface InstanceChangeExchangeProcessor extends DingBasicExchangeProcessor {
|
||||||
|
|
||||||
|
Logger logger = LoggerFactory.getLogger(InstanceChangeExchangeProcessor.class);
|
||||||
|
|
||||||
|
//补卡
|
||||||
|
static final String PROCESS_CODE_RECHARGE_CARD = "PROC-19617D02-F632-402E-9ACD-134CC47E462F";
|
||||||
|
|
||||||
|
boolean accept(String processCode);
|
||||||
|
|
||||||
|
void exchange(JSONObject json);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
package com.evo.ding.processor.instance.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody;
|
||||||
|
import com.evo.common.utils.DateUtils;
|
||||||
|
import com.evo.common.utils.ParamUtils;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
|
import com.evo.ding.DingUtils;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.ding.processor.instance.InstanceChangeExchangeProcessor;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钉钉补卡接口回调 InstanceChangeRechargeCardExchangeProcessor
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:InstanceChangeRechargeCardExchangeProcessor
|
||||||
|
* @date: 2026年03月10日 10:24
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class InstanceChangeRechargeCardExchangeProcessor implements InstanceChangeExchangeProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(String processCode) {
|
||||||
|
return InstanceChangeExchangeProcessor.PROCESS_CODE_RECHARGE_CARD.equals(processCode);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void exchange(JSONObject json) {
|
||||||
|
//获取审批示例id
|
||||||
|
String processInstanceId = json.getString("processInstanceId");
|
||||||
|
GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResult result = DingUtils.getProcessInstanceInfo(processInstanceId);
|
||||||
|
//根据操作人id, 获取user
|
||||||
|
SysStaff sysStaff = getSysStaffByDingUserId(result.getOriginatorUserId());
|
||||||
|
if(sysStaff != null){
|
||||||
|
List<GetProcessInstanceResponseBody.GetProcessInstanceResponseBodyResultFormComponentValues> resultFormValues = result.getFormComponentValues();
|
||||||
|
//补卡时间
|
||||||
|
String bkTime = resultFormValues.stream().filter(data-> "补卡时间".equals(data.getName()) && StringUtils.isNotEmpty(data.getValue())).findFirst().get().getValue();
|
||||||
|
String extValue = resultFormValues.stream().filter(data-> "补卡时间".equals(data.getName()) && StringUtils.isNotEmpty(data.getExtValue())).findFirst().get().getExtValue();
|
||||||
|
//补卡类型
|
||||||
|
String bkType = resultFormValues.stream().filter(data-> "补卡类型".equals(data.getName()) && StringUtils.isNotEmpty(data.getValue())).findFirst().get().getValue();
|
||||||
|
//补卡原因
|
||||||
|
String bkYi = resultFormValues.stream().filter(data-> "补卡原因".equals(data.getName()) && StringUtils.isNotEmpty(data.getValue())).findFirst().get().getValue();
|
||||||
|
//获取补卡班次
|
||||||
|
String checkType = "上班卡".equals(bkType) ? "OnDuty" : "OffDuty";
|
||||||
|
DingShiftGroup dingsShiftGroup = null;
|
||||||
|
try {
|
||||||
|
if(StringUtils.isNotEmpty(extValue)){
|
||||||
|
JSONObject js = JSONObject.parseObject(extValue);
|
||||||
|
String planId = js.getString("planId");
|
||||||
|
String s = DingUtils.getPlanInfo(result.getOriginatorUserId(), planId);
|
||||||
|
JSONObject planResult = JSONObject.parseObject(s);
|
||||||
|
if(Integer.valueOf(0).equals(planResult.getInteger("errcode"))){
|
||||||
|
JSONObject planResultObject = planResult.getJSONArray("result").getJSONObject(0);
|
||||||
|
String formatPlanCheckTime = DateUtils.parseDateToStr("HH:mm:ss", new Date(planResultObject.getString("plan_check_time")));
|
||||||
|
dingsShiftGroup = getDingShiftGroupService().selectByGroupIdAndTypeAndCheckTime(planResultObject.getString("group_id"), planResultObject.getString("class_id"), checkType, formatPlanCheckTime);
|
||||||
|
Date date= DateUtils.parseDate(bkTime, "yyyy-MM-dd HH:mm");
|
||||||
|
//生成补卡记录信息
|
||||||
|
getIRzAttendanceService().addRzOverTime(json.toString(), sysStaff, dingsShiftGroup, checkType, date, date, "/", "钉钉补卡-"+bkYi, ParamUtils.getDebiting(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
log.info("补卡出现错误, 为在本地找到班次数据, 错误信息为:{}, 回调信息为: {}", e.getMessage(), json.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.evo.ding.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.evo.ding.domain.DingGroup;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShiftService
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShiftService
|
||||||
|
* @date: 2026年03月11日 15:55
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingGroupService extends IService<DingGroup> {
|
||||||
|
|
||||||
|
public DingGroup selectByDingId(String dingId);
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.evo.ding.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingShiftGroupService
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingShiftGroupService
|
||||||
|
* @date: 2026年03月11日 15:48
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingShiftGroupService extends IService<DingShiftGroup> {
|
||||||
|
|
||||||
|
DingShiftGroup selectByGroupIdAndTypeAndCheckTime(String groupId, String shiftId, String type, String checkTime);
|
||||||
|
|
||||||
|
int updateCheckTimeByShiftIdAndType(String shiftId, String type, String checkTime);
|
||||||
|
|
||||||
|
List<DingShiftGroup> selectListByGroupId(String groupId);
|
||||||
|
|
||||||
|
public List<DingShiftGroup> selectList(DingShiftGroup dingShiftGroup);
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.evo.ding.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingsShiftService
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingsShiftService
|
||||||
|
* @date: 2026年03月11日 15:55
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface DingShiftService extends IService<DingShift> {
|
||||||
|
|
||||||
|
public DingShift selectByDingId(String dingId);
|
||||||
|
|
||||||
|
public DingShift selectByDingIdEmptyCreate(String dingId);
|
||||||
|
|
||||||
|
public List<DingShift> selectList(DingShift dingShift);
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.evo.ding.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.evo.ding.domain.DingGroup;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.mapper.DingGroupMapper;
|
||||||
|
import com.evo.ding.mapper.DingShiftMapper;
|
||||||
|
import com.evo.ding.service.DingGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingShiftGroupServiceImpl
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingShiftGroupServiceImpl
|
||||||
|
* @date: 2026年03月11日 15:49
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DingGroupServiceImpl extends ServiceImpl<DingGroupMapper, DingGroup> implements DingGroupService {
|
||||||
|
@Override
|
||||||
|
public DingGroup selectByDingId(String dingId) {
|
||||||
|
return getBaseMapper().selectByDingId(dingId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.evo.ding.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.ding.mapper.DingShiftGroupMapper;
|
||||||
|
import com.evo.ding.service.DingShiftGroupService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingShiftGroupServiceImpl
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingShiftGroupServiceImpl
|
||||||
|
* @date: 2026年03月11日 15:49
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DingShiftGroupServiceImpl extends ServiceImpl<DingShiftGroupMapper, DingShiftGroup> implements DingShiftGroupService {
|
||||||
|
@Override
|
||||||
|
public DingShiftGroup selectByGroupIdAndTypeAndCheckTime(String groupId, String shiftId, String type, String checkTime) {
|
||||||
|
return getBaseMapper().selectByGroupIdAndTypeAndCheckTime(groupId, shiftId, type, checkTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int updateCheckTimeByShiftIdAndType(String shiftId, String type, String checkTime) {
|
||||||
|
return getBaseMapper().updateCheckTimeByShiftIdAndType(shiftId, type, checkTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DingShiftGroup> selectListByGroupId(String groupId) {
|
||||||
|
return list(new LambdaQueryWrapper<DingShiftGroup>().eq(DingShiftGroup::getGroupId, groupId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DingShiftGroup> selectList(DingShiftGroup dingShiftGroup) {
|
||||||
|
return getBaseMapper().selectListByShiftId(dingShiftGroup.getShiftId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package com.evo.ding.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.evo.common.utils.Collections;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.ding.mapper.DingShiftGroupMapper;
|
||||||
|
import com.evo.ding.mapper.DingShiftMapper;
|
||||||
|
import com.evo.ding.processor.callback.impl.DingCallBackShiftChangeExchangeProcessor;
|
||||||
|
import com.evo.ding.service.DingShiftGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DingShiftGroupServiceImpl
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:DingShiftGroupServiceImpl
|
||||||
|
* @date: 2026年03月11日 15:49
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DingShiftServiceImpl extends ServiceImpl<DingShiftMapper, DingShift> implements DingShiftService {
|
||||||
|
@Autowired
|
||||||
|
@Lazy
|
||||||
|
DingCallBackShiftChangeExchangeProcessor dingCallBackShiftChangeExchangeProcessor;
|
||||||
|
@Override
|
||||||
|
public DingShift selectByDingId(String dingId) {
|
||||||
|
return getBaseMapper().selectByDingId(dingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DingShift selectByDingIdEmptyCreate(String dingId) {
|
||||||
|
DingShift dingShift = getBaseMapper().selectByDingId(dingId);
|
||||||
|
if(dingShift == null){
|
||||||
|
dingCallBackShiftChangeExchangeProcessor.exchange(JSONObject.from(Collections.asMap("id", dingId)));
|
||||||
|
return selectByDingId(dingId);
|
||||||
|
}
|
||||||
|
return dingShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DingShift> selectList(DingShift dingShift) {
|
||||||
|
return getBaseMapper().selectList(dingShift);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package com.evo.equipment.service.impl;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.evo.common.utils.ParamUtils;
|
||||||
import com.evo.equipment.constant.Constants;
|
import com.evo.equipment.constant.Constants;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.common.utils.DateUtils;
|
import com.evo.common.utils.DateUtils;
|
||||||
@ -113,7 +114,7 @@ public class EqImagesServiceImpl implements IEqImagesService
|
|||||||
|
|
||||||
//定义公共打卡机
|
//定义公共打卡机
|
||||||
List<String> dkj_list = new ArrayList<String>();
|
List<String> dkj_list = new ArrayList<String>();
|
||||||
dkj_list.add(Constants.EQ_DEVICE_CODE); //食堂
|
dkj_list.addAll(ParamUtils.getRestaurantDevSn()); //食堂
|
||||||
// dkj_list.add(Constants.EQ_DEVICE_PUBLIC_CODE); //公共
|
// dkj_list.add(Constants.EQ_DEVICE_PUBLIC_CODE); //公共
|
||||||
dkj_list.add(eqImages.getTimeClock());
|
dkj_list.add(eqImages.getTimeClock());
|
||||||
|
|
||||||
@ -265,7 +266,7 @@ public class EqImagesServiceImpl implements IEqImagesService
|
|||||||
Row row = sheet.getRow(p);
|
Row row = sheet.getRow(p);
|
||||||
if(StringUtils.isNotNull(row)){
|
if(StringUtils.isNotNull(row)){
|
||||||
dkj_list = new ArrayList<String>();
|
dkj_list = new ArrayList<String>();
|
||||||
dkj_list.add(Constants.EQ_DEVICE_CODE); //食堂
|
dkj_list.addAll(ParamUtils.getRestaurantDevSn()); //食堂
|
||||||
// dkj_list.add(Constants.EQ_DEVICE_PUBLIC_CODE); //公共
|
// dkj_list.add(Constants.EQ_DEVICE_PUBLIC_CODE); //公共
|
||||||
dkj_list.add(row.getCell(4).getStringCellValue());
|
dkj_list.add(row.getCell(4).getStringCellValue());
|
||||||
cau = new StaffDto();
|
cau = new StaffDto();
|
||||||
|
|||||||
@ -46,7 +46,7 @@ import java.util.stream.Collectors;
|
|||||||
* @date 2024-08-07
|
* @date 2024-08-07
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDetail> implements IEqSnDetailService, ApplicationRunner
|
public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDetail> implements IEqSnDetailService
|
||||||
{
|
{
|
||||||
@Resource
|
@Resource
|
||||||
private SysStaffMapper sysStaffMapper;
|
private SysStaffMapper sysStaffMapper;
|
||||||
@ -118,8 +118,15 @@ public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDet
|
|||||||
public EqSnDetail selectEqSnDetailBySn(String sn){
|
public EqSnDetail selectEqSnDetailBySn(String sn){
|
||||||
return getBaseMapper().selectEqSnDetailBySn(sn);
|
return getBaseMapper().selectEqSnDetailBySn(sn);
|
||||||
}
|
}
|
||||||
//com.evo.equipment.constant.Constants.EQ_DEVICE_PUBLIC_CODE,
|
//com.evo.equipment.constant.Constants.EQ_DEVICE_PUBLIC_CODE, Collections.asList(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE)
|
||||||
static List<String> tsSn = Collections.asList(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE);
|
static List<String> tsSn = Collections.emptyList();
|
||||||
|
|
||||||
|
public List<String> getTsSn(){
|
||||||
|
tsSn.clear();
|
||||||
|
tsSn.addAll(ParamUtils.getTsDevSn());
|
||||||
|
tsSn.addAll(ParamUtils.getRestaurantDevSn());
|
||||||
|
return tsSn;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Map<String, String>> getPhoto(List<SysStaff> userList){
|
private List<Map<String, String>> getPhoto(List<SysStaff> userList){
|
||||||
List<Map<String, String>> userPhotoList = Collections.emptyList();
|
List<Map<String, String>> userPhotoList = Collections.emptyList();
|
||||||
@ -141,11 +148,12 @@ public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDet
|
|||||||
public Map<String, List<Map<String, String>>> initTsDkDevice(String deviceSn){
|
public Map<String, List<Map<String, String>>> initTsDkDevice(String deviceSn){
|
||||||
Map<String, List<Map<String, String>>> snUserPhotoList = Collections.emptyMap();
|
Map<String, List<Map<String, String>>> snUserPhotoList = Collections.emptyMap();
|
||||||
//如果有且只有一个设备信息, 并且设备信息为公共打卡机, 或者是 食堂打卡机
|
//如果有且只有一个设备信息, 并且设备信息为公共打卡机, 或者是 食堂打卡机
|
||||||
if(tsSn.contains(deviceSn)) {
|
if(getTsSn().contains(deviceSn)) {
|
||||||
List<Map<String, String>> userPhotoList = Collections.emptyList();
|
List<Map<String, String>> userPhotoList = Collections.emptyList();
|
||||||
List<SysStaff> userList = Collections.emptyList();
|
List<SysStaff> userList = Collections.emptyList();
|
||||||
//deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_PUBLIC_CODE) ||
|
//deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_PUBLIC_CODE) ||
|
||||||
if (deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE)) {
|
//deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE)
|
||||||
|
if (ParamUtils.getRestaurantDevSn().contains(deviceSn)) {
|
||||||
//获取所有未删除的, 没有离职的员工信息
|
//获取所有未删除的, 没有离职的员工信息
|
||||||
userList = sysStaffMapper.selectList(new LambdaQueryWrapper<SysStaff>().eq(SysStaff::getDelFlag, Constants.DELETE_FLAG_0).ne(SysStaff::getStatus, Constants.JOB_STATIS_11).select(SysStaff::getUserId, SysStaff::getDeptId, SysStaff::getName));
|
userList = sysStaffMapper.selectList(new LambdaQueryWrapper<SysStaff>().eq(SysStaff::getDelFlag, Constants.DELETE_FLAG_0).ne(SysStaff::getStatus, Constants.JOB_STATIS_11).select(SysStaff::getUserId, SysStaff::getDeptId, SysStaff::getName));
|
||||||
}
|
}
|
||||||
@ -154,8 +162,8 @@ public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDet
|
|||||||
List<Long> userIds = eqOverStaffMapper.selectList(new LambdaQueryWrapper<EqOverStaff>().eq(EqOverStaff::getDelFlag, Constants.DELETE_FLAG_0).select(EqOverStaff::getUserId)).stream().map(EqOverStaff::getUserId).collect(Collectors.toList());
|
List<Long> userIds = eqOverStaffMapper.selectList(new LambdaQueryWrapper<EqOverStaff>().eq(EqOverStaff::getDelFlag, Constants.DELETE_FLAG_0).select(EqOverStaff::getUserId)).stream().map(EqOverStaff::getUserId).collect(Collectors.toList());
|
||||||
userList = sysStaffMapper.selectList((new LambdaQueryWrapper<SysStaff>().in(SysStaff::getUserId, userIds).eq(SysStaff::getDelFlag, Constants.DELETE_FLAG_0).ne(SysStaff::getStatus, Constants.JOB_STATIS_11).select(SysStaff::getUserId, SysStaff::getDeptId, SysStaff::getName)));
|
userList = sysStaffMapper.selectList((new LambdaQueryWrapper<SysStaff>().in(SysStaff::getUserId, userIds).eq(SysStaff::getDelFlag, Constants.DELETE_FLAG_0).ne(SysStaff::getStatus, Constants.JOB_STATIS_11).select(SysStaff::getUserId, SysStaff::getDeptId, SysStaff::getName)));
|
||||||
}
|
}
|
||||||
//如果是下发的食堂打卡机, 则需要查找餐饮人员的数据
|
//如果是下发的食堂打卡机, 则需要查找餐饮人员的数据 deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE)deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE)
|
||||||
if (deviceSn.equals(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE)) {
|
if (ParamUtils.getRestaurantDevSn().contains(deviceSn)) {
|
||||||
List<RzRestaurantImages> list = rzRestaurantImagesMapper.selectList(new LambdaQueryWrapper<RzRestaurantImages>().eq(RzRestaurantImages::getDelFlag, Constants.DELETE_FLAG_0));
|
List<RzRestaurantImages> list = rzRestaurantImagesMapper.selectList(new LambdaQueryWrapper<RzRestaurantImages>().eq(RzRestaurantImages::getDelFlag, Constants.DELETE_FLAG_0));
|
||||||
for (RzRestaurantImages img : list) {
|
for (RzRestaurantImages img : list) {
|
||||||
userPhotoList.add(Collections.asMap("userId", String.valueOf(img.getId()), "name", img.getName(), "photoUrl", img.getImageUrl(), "deptName", "实习生"));
|
userPhotoList.add(Collections.asMap("userId", String.valueOf(img.getId()), "name", img.getName(), "photoUrl", img.getImageUrl(), "deptName", "实习生"));
|
||||||
@ -204,14 +212,14 @@ public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDet
|
|||||||
Map<String, List<Map<String, String>>> snUserPhotoList = Collections.emptyMap();
|
Map<String, List<Map<String, String>>> snUserPhotoList = Collections.emptyMap();
|
||||||
if(Collections.isEmpty(userPhotoList)){
|
if(Collections.isEmpty(userPhotoList)){
|
||||||
//如果有且只有一个设备信息, 并且设备信息为公共打卡机, 或者是 食堂打卡机
|
//如果有且只有一个设备信息, 并且设备信息为公共打卡机, 或者是 食堂打卡机
|
||||||
if(snList.size() ==1 && tsSn.contains(snList.get(0))){
|
if(snList.size() ==1 && getTsSn().contains(snList.get(0))){
|
||||||
snUserPhotoList.putAll(initTsDkDevice(snList.get(0)));
|
snUserPhotoList.putAll(initTsDkDevice(snList.get(0)));
|
||||||
}else{
|
}else{
|
||||||
List<String> allSnList = new ArrayList<String>(){{addAll(snList);}};
|
List<String> allSnList = new ArrayList<String>(){{addAll(snList);}};
|
||||||
List<String> tsDeviceSn = Collections.findDuplicatesList(allSnList, tsSn);
|
List<String> tsDeviceSn = Collections.findDuplicatesList(allSnList, getTsSn());
|
||||||
//所有所有不是特殊打卡机人员信息
|
//所有所有不是特殊打卡机人员信息
|
||||||
snList.remove(tsDeviceSn);
|
snList.remove(tsDeviceSn);
|
||||||
snList.stream().filter(sn-> !tsSn.contains(sn)).forEach(sn ->{
|
snList.stream().filter(sn-> !getTsSn().contains(sn)).forEach(sn ->{
|
||||||
//获取所有未删除的, 没有离职的员工信息
|
//获取所有未删除的, 没有离职的员工信息
|
||||||
List<SysStaff> userList = sysStaffMapper.selectList((new LambdaQueryWrapper<SysStaff>().like(SysStaff::getTimeClock, sn).eq(SysStaff::getDelFlag, Constants.DELETE_FLAG_0).ne(SysStaff::getStatus,Constants.JOB_STATIS_11).select(SysStaff::getUserId, SysStaff::getDeptId, SysStaff::getName)));
|
List<SysStaff> userList = sysStaffMapper.selectList((new LambdaQueryWrapper<SysStaff>().like(SysStaff::getTimeClock, sn).eq(SysStaff::getDelFlag, Constants.DELETE_FLAG_0).ne(SysStaff::getStatus,Constants.JOB_STATIS_11).select(SysStaff::getUserId, SysStaff::getDeptId, SysStaff::getName)));
|
||||||
snUserPhotoList.put(sn, getPhoto(userList));
|
snUserPhotoList.put(sn, getPhoto(userList));
|
||||||
@ -304,8 +312,10 @@ public class EqSnDetailServiceImpl extends ServiceImpl<EqSnDetailMapper, EqSnDet
|
|||||||
update(new UpdateWrapper<EqSnDetail>().set("type","连接已断开").set("session_id","").eq( "session_id", sessionId));
|
update(new UpdateWrapper<EqSnDetail>().set("type","连接已断开").set("session_id","").eq( "session_id", sessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
//
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
// @Override
|
||||||
tsSn.addAll(ParamUtils.getTsDevSn());
|
// public void run(ApplicationArguments args) throws Exception {
|
||||||
}
|
// tsSn.addAll(ParamUtils.getTsDevSn());
|
||||||
|
// tsSn.addAll(ParamUtils.getRestaurantDevSn());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,9 +42,6 @@ public class RzSalaryDetailController extends BaseController
|
|||||||
private IRzSalaryDetailService rzSalaryDetailService;
|
private IRzSalaryDetailService rzSalaryDetailService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysDeptService deptService; //部门
|
private ISysDeptService deptService; //部门
|
||||||
@Resource
|
|
||||||
private SysDictDataMapper sysDictDataMapper; //数据字典
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询工资详情列表
|
* 查询工资详情列表
|
||||||
*/
|
*/
|
||||||
@ -101,403 +98,6 @@ public class RzSalaryDetailController extends BaseController
|
|||||||
return toAjax(rzSalaryDetailService.deleteRzSalaryDetailById(id));
|
return toAjax(rzSalaryDetailService.deleteRzSalaryDetailById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出工资详情列表
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('finance:financeDetail:export')")
|
|
||||||
@Log(title = "工资详情", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export1")
|
|
||||||
public AjaxResult export1(RzSalaryDetail rzSalaryDetail)
|
|
||||||
{
|
|
||||||
ExcelUtilSs<SalaryVo> util = new ExcelUtilSs<SalaryVo>(SalaryVo.class);
|
|
||||||
//创建总表
|
|
||||||
List<SalaryVo> list = new ArrayList<SalaryVo>();
|
|
||||||
//创建各个公司的数据
|
|
||||||
List<List<SalaryVo>> lists = new ArrayList<>();
|
|
||||||
//创建各个部门sheetname集合
|
|
||||||
List<String> sheetNameList = new ArrayList<>();
|
|
||||||
//汇总表表头
|
|
||||||
String title = new SimpleDateFormat("yyyy-MM").format(rzSalaryDetail.getMonth())+"月工资汇总表";
|
|
||||||
//获取所有的最小独立部门
|
|
||||||
List<SysDept> dept_list = deptService.queryAllDeptForMin();
|
|
||||||
//员工工资信息
|
|
||||||
SalaryVo salaryVo = null;
|
|
||||||
//工资数据转化的保存
|
|
||||||
List<SalaryVo> list0 =new ArrayList<SalaryVo>();
|
|
||||||
for (SysDept sysDept : dept_list) {
|
|
||||||
sheetNameList.add(sysDept.getDeptName());
|
|
||||||
//部门小计
|
|
||||||
SalaryVo xj_salaryVo = new SalaryVo();
|
|
||||||
// xj_salaryVo.setBasicSalary(new BigDecimal("0.00"));
|
|
||||||
xj_salaryVo.setName("小计:");
|
|
||||||
//查询部门下的数据
|
|
||||||
List<RzSalaryDetail> pay_list = rzSalaryDetailService.selectSalaryDetailByDeptId(sysDept.getDeptId(),rzSalaryDetail.getMonth());
|
|
||||||
for (RzSalaryDetail salaryDetail : pay_list) {
|
|
||||||
salaryVo = new SalaryVo();
|
|
||||||
// xj_salaryVo.setBasicSalary(xj_salaryVo.getBasicSalary().add(salaryDetail.getBasicSalary()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getOvertimeSalary())){
|
|
||||||
// xj_salaryVo.setOvertimeSalary(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// xj_salaryVo.setOvertimeSalary(xj_salaryVo.getOvertimeSalary().add(salaryDetail.getOvertimeSalary()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getLevelSubsidies())){
|
|
||||||
// xj_salaryVo.setLevelSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
xj_salaryVo.setLevelSubsidies(xj_salaryVo.getLevelSubsidies().add(salaryDetail.getLevelSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getContractSubsidies())){
|
|
||||||
xj_salaryVo.setContractSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setContractSubsidies(xj_salaryVo.getContractSubsidies().add(salaryDetail.getContractSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSenioritySalary())){
|
|
||||||
xj_salaryVo.setSenioritySalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSenioritySalary(xj_salaryVo.getSenioritySalary().add(salaryDetail.getSenioritySalary()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSocialSubsidies())){
|
|
||||||
xj_salaryVo.setSocialSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
// xj_salaryVo.setSocialSubsidies(xj_salaryVo.getSocialSubsidies().add(salaryDetail.getSocialSubsidies()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getFullSubsidies())){
|
|
||||||
// xj_salaryVo.setFullSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// xj_salaryVo.setFullSubsidies(xj_salaryVo.getFullSubsidies().add(salaryDetail.getFullSubsidies()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getNightSubsidies())){
|
|
||||||
// xj_salaryVo.setNightSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
xj_salaryVo.setNightSubsidies(xj_salaryVo.getNightSubsidies().add(salaryDetail.getNightSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getDinnerSubsidies())){
|
|
||||||
xj_salaryVo.setDinnerSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setDinnerSubsidies(xj_salaryVo.getDinnerSubsidies().add(salaryDetail.getDinnerSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSubsidyOrBonus())){
|
|
||||||
xj_salaryVo.setSubsidyOrBonus(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSubsidyOrBonus(xj_salaryVo.getSubsidyOrBonus().add(salaryDetail.getSubsidyOrBonus()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAbsenteeismSalary())){
|
|
||||||
xj_salaryVo.setAbsenteeismSalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAbsenteeismSalary(xj_salaryVo.getAbsenteeismSalary().add(salaryDetail.getAbsenteeismSalary()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAbsenteeismSubsidies())){
|
|
||||||
xj_salaryVo.setAbsenteeismSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAbsenteeismSubsidies(xj_salaryVo.getAbsenteeismSubsidies().add(salaryDetail.getAbsenteeismSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getMealFee())){
|
|
||||||
xj_salaryVo.setMealFee(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setMealFee(xj_salaryVo.getMealFee().add(salaryDetail.getMealFee()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getDeductions())){
|
|
||||||
xj_salaryVo.setDeductions(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setDeductions(xj_salaryVo.getDeductions().add(salaryDetail.getDeductions()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSalary())){
|
|
||||||
xj_salaryVo.setSalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSalary(xj_salaryVo.getSalary().add(salaryDetail.getSalary()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getPayInsurance())){
|
|
||||||
xj_salaryVo.setPayInsurance(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setPayInsurance(xj_salaryVo.getPayInsurance().add(salaryDetail.getPayInsurance()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSalaryBeforeTax())){
|
|
||||||
xj_salaryVo.setSalaryBeforeTax(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSalaryBeforeTax(xj_salaryVo.getSalaryBeforeTax().add(salaryDetail.getSalaryBeforeTax()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getTotalWages())){
|
|
||||||
xj_salaryVo.setTotalWages(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setTotalWages(xj_salaryVo.getTotalWages().add(salaryDetail.getTotalWages()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAnnualExemptionAmount())){
|
|
||||||
xj_salaryVo.setAnnualExemptionAmount(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAnnualExemptionAmount(xj_salaryVo.getAnnualExemptionAmount().add(salaryDetail.getAnnualExemptionAmount()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSpecialDeduction())){
|
|
||||||
xj_salaryVo.setSpecialDeduction(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSpecialDeduction(xj_salaryVo.getSpecialDeduction().add(salaryDetail.getSpecialDeduction()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSlowDownTheDeduction())){
|
|
||||||
xj_salaryVo.setSlowDownTheDeduction(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSlowDownTheDeduction(xj_salaryVo.getSlowDownTheDeduction().add(salaryDetail.getSlowDownTheDeduction()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAggregatePersonalIncomeTax())){
|
|
||||||
xj_salaryVo.setAggregatePersonalIncomeTax(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAggregatePersonalIncomeTax(xj_salaryVo.getAggregatePersonalIncomeTax().add(salaryDetail.getAggregatePersonalIncomeTax()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getTaxPayable())){
|
|
||||||
xj_salaryVo.setTaxPayable(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setTaxPayable(xj_salaryVo.getTaxPayable().add(salaryDetail.getTaxPayable()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getNetPayroll())){
|
|
||||||
xj_salaryVo.setNetPayroll(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setNetPayroll(xj_salaryVo.getNetPayroll().add(salaryDetail.getNetPayroll()));
|
|
||||||
BeanUtils.copyProperties(salaryDetail, salaryVo);
|
|
||||||
salaryVo.setDeptName(sysDept.getDeptName());
|
|
||||||
list0.add(salaryVo);
|
|
||||||
}
|
|
||||||
list0.add(xj_salaryVo);
|
|
||||||
lists.add(list0);
|
|
||||||
list.add(xj_salaryVo);
|
|
||||||
}
|
|
||||||
//计算伊特总计数据
|
|
||||||
SalaryVo gj_salaryVo = new SalaryVo();
|
|
||||||
for (SalaryVo salaryVoz : list) {
|
|
||||||
// if(StringUtils.isNull(gj_salaryVo.getBasicSalary())){
|
|
||||||
// gj_salaryVo.setBasicSalary(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// gj_salaryVo.setBasicSalary(gj_salaryVo.getBasicSalary().add(salaryVoz.getBasicSalary()));
|
|
||||||
// if(StringUtils.isNull(gj_salaryVo.getOvertimeSalary())){
|
|
||||||
// gj_salaryVo.setOvertimeSalary(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// gj_salaryVo.setOvertimeSalary(gj_salaryVo.getOvertimeSalary().add(DataUtils.findDefaultValue(salaryVoz.getOvertimeSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
// if(StringUtils.isNull(gj_salaryVo.getLevelSubsidies())){
|
|
||||||
// gj_salaryVo.setLevelSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
gj_salaryVo.setLevelSubsidies(gj_salaryVo.getLevelSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getLevelSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getContractSubsidies())){
|
|
||||||
gj_salaryVo.setContractSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setContractSubsidies(gj_salaryVo.getContractSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getContractSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSenioritySalary())){
|
|
||||||
gj_salaryVo.setSenioritySalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setSenioritySalary(gj_salaryVo.getSenioritySalary().add(DataUtils.findDefaultValue(salaryVoz.getSenioritySalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSocialSubsidies())){
|
|
||||||
gj_salaryVo.setSocialSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
// gj_salaryVo.setSocialSubsidies(gj_salaryVo.getSocialSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getSocialSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
// if(StringUtils.isNull(gj_salaryVo.getFullSubsidies())){
|
|
||||||
// gj_salaryVo.setFullSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// gj_salaryVo.setFullSubsidies(gj_salaryVo.getFullSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getFullSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
// if(StringUtils.isNull(gj_salaryVo.getNightSubsidies())){
|
|
||||||
// gj_salaryVo.setNightSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
gj_salaryVo.setNightSubsidies(gj_salaryVo.getNightSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getNightSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getDinnerSubsidies())){
|
|
||||||
gj_salaryVo.setDinnerSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setDinnerSubsidies(gj_salaryVo.getDinnerSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getDinnerSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSubsidyOrBonus())){
|
|
||||||
gj_salaryVo.setSubsidyOrBonus(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setSubsidyOrBonus(gj_salaryVo.getSubsidyOrBonus().add(DataUtils.findDefaultValue(salaryVoz.getSubsidyOrBonus(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getAbsenteeismSalary())){
|
|
||||||
gj_salaryVo.setAbsenteeismSalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setAbsenteeismSalary(gj_salaryVo.getAbsenteeismSalary().add(DataUtils.findDefaultValue(salaryVoz.getAbsenteeismSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getAbsenteeismSubsidies())){
|
|
||||||
gj_salaryVo.setAbsenteeismSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setAbsenteeismSubsidies(gj_salaryVo.getAbsenteeismSubsidies().add(DataUtils.findDefaultValue(salaryVoz.getAbsenteeismSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getMealFee())){
|
|
||||||
gj_salaryVo.setMealFee(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setMealFee(gj_salaryVo.getMealFee().add(DataUtils.findDefaultValue(salaryVoz.getMealFee(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getDeductions())){
|
|
||||||
gj_salaryVo.setDeductions(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setDeductions(gj_salaryVo.getDeductions().add(DataUtils.findDefaultValue(salaryVoz.getDeductions(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSalary())){
|
|
||||||
gj_salaryVo.setSalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setSalary(gj_salaryVo.getSalary().add(DataUtils.findDefaultValue(salaryVoz.getSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getPayInsurance())){
|
|
||||||
gj_salaryVo.setPayInsurance(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setPayInsurance(gj_salaryVo.getPayInsurance().add(DataUtils.findDefaultValue(salaryVoz.getPayInsurance(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSalaryBeforeTax())){
|
|
||||||
gj_salaryVo.setSalaryBeforeTax(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setSalaryBeforeTax(gj_salaryVo.getSalaryBeforeTax().add(DataUtils.findDefaultValue(salaryVoz.getSalaryBeforeTax(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getTotalWages())){
|
|
||||||
gj_salaryVo.setTotalWages(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setTotalWages(gj_salaryVo.getTotalWages().add(DataUtils.findDefaultValue(salaryVoz.getTotalWages(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getAnnualExemptionAmount())){
|
|
||||||
gj_salaryVo.setAnnualExemptionAmount(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setAnnualExemptionAmount(gj_salaryVo.getAnnualExemptionAmount().add(DataUtils.findDefaultValue(salaryVoz.getAnnualExemptionAmount(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSpecialDeduction())){
|
|
||||||
gj_salaryVo.setSpecialDeduction(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setSpecialDeduction(gj_salaryVo.getSpecialDeduction().add(DataUtils.findDefaultValue(salaryVoz.getSpecialDeduction(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getSlowDownTheDeduction())){
|
|
||||||
gj_salaryVo.setSlowDownTheDeduction(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setSlowDownTheDeduction(gj_salaryVo.getSlowDownTheDeduction().add(DataUtils.findDefaultValue(salaryVoz.getSlowDownTheDeduction(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getAggregatePersonalIncomeTax())){
|
|
||||||
gj_salaryVo.setAggregatePersonalIncomeTax(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setAggregatePersonalIncomeTax(gj_salaryVo.getAggregatePersonalIncomeTax().add(DataUtils.findDefaultValue(salaryVoz.getAggregatePersonalIncomeTax(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getTaxPayable())){
|
|
||||||
gj_salaryVo.setTaxPayable(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setTaxPayable(gj_salaryVo.getTaxPayable().add(DataUtils.findDefaultValue(salaryVoz.getTaxPayable(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
if(StringUtils.isNull(gj_salaryVo.getNetPayroll())){
|
|
||||||
gj_salaryVo.setNetPayroll(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setNetPayroll(gj_salaryVo.getNetPayroll().add(DataUtils.findDefaultValue(salaryVoz.getNetPayroll(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
}
|
|
||||||
gj_salaryVo.setName("伊特总计:");
|
|
||||||
list.add(gj_salaryVo);
|
|
||||||
|
|
||||||
//创建总表的对象
|
|
||||||
SalaryVo payRollZong = new SalaryVo();
|
|
||||||
payRollZong.setName("总计:");
|
|
||||||
BeanUtils.copyProperties(gj_salaryVo, payRollZong);
|
|
||||||
//查询非伊特数据
|
|
||||||
List<SysDictData> cy_list = sysDictDataMapper.selectDictDataByType(Constants.SYS_COMPANY);
|
|
||||||
for (SysDictData sysDictData : cy_list) {
|
|
||||||
if(!"YT".equals(sysDictData.getDictValue())){
|
|
||||||
sheetNameList.add(sysDictData.getDictLabel());
|
|
||||||
//部门小计
|
|
||||||
SalaryVo xj_salaryVo = new SalaryVo();
|
|
||||||
xj_salaryVo.setName("小计:");
|
|
||||||
//查询非伊特下的数据
|
|
||||||
List<RzSalaryDetail> f_list = rzSalaryDetailService.selectSalaryDetailByWbFlag(sysDictData.getDictValue(),rzSalaryDetail.getMonth());
|
|
||||||
for (RzSalaryDetail salaryDetail : f_list) {
|
|
||||||
salaryVo = new SalaryVo();
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getBasicSalary())){
|
|
||||||
// xj_salaryVo.setBasicSalary(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// xj_salaryVo.setBasicSalary(xj_salaryVo.getBasicSalary().add(salaryDetail.getBasicSalary()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getOvertimeSalary())){
|
|
||||||
// xj_salaryVo.setOvertimeSalary(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// xj_salaryVo.setOvertimeSalary(xj_salaryVo.getOvertimeSalary().add(salaryDetail.getOvertimeSalary()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getLevelSubsidies())){
|
|
||||||
// xj_salaryVo.setLevelSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
xj_salaryVo.setLevelSubsidies(xj_salaryVo.getLevelSubsidies().add(salaryDetail.getLevelSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getContractSubsidies())){
|
|
||||||
xj_salaryVo.setContractSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setContractSubsidies(xj_salaryVo.getContractSubsidies().add(salaryDetail.getContractSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSenioritySalary())){
|
|
||||||
xj_salaryVo.setSenioritySalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSenioritySalary(xj_salaryVo.getSenioritySalary().add(salaryDetail.getSenioritySalary()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSocialSubsidies())){
|
|
||||||
xj_salaryVo.setSocialSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
// xj_salaryVo.setSocialSubsidies(xj_salaryVo.getSocialSubsidies().add(salaryDetail.getSocialSubsidies()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getFullSubsidies())){
|
|
||||||
// xj_salaryVo.setFullSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
// xj_salaryVo.setFullSubsidies(xj_salaryVo.getFullSubsidies().add(salaryDetail.getFullSubsidies()));
|
|
||||||
// if(StringUtils.isNull(xj_salaryVo.getNightSubsidies())){
|
|
||||||
// xj_salaryVo.setNightSubsidies(new BigDecimal("0.00"));
|
|
||||||
// }
|
|
||||||
xj_salaryVo.setNightSubsidies(xj_salaryVo.getNightSubsidies().add(salaryDetail.getNightSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getDinnerSubsidies())){
|
|
||||||
xj_salaryVo.setDinnerSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setDinnerSubsidies(xj_salaryVo.getDinnerSubsidies().add(salaryDetail.getDinnerSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSubsidyOrBonus())){
|
|
||||||
xj_salaryVo.setSubsidyOrBonus(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSubsidyOrBonus(xj_salaryVo.getSubsidyOrBonus().add(salaryDetail.getSubsidyOrBonus()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAbsenteeismSalary())){
|
|
||||||
xj_salaryVo.setAbsenteeismSalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAbsenteeismSalary(xj_salaryVo.getAbsenteeismSalary().add(salaryDetail.getAbsenteeismSalary()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAbsenteeismSubsidies())){
|
|
||||||
xj_salaryVo.setAbsenteeismSubsidies(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAbsenteeismSubsidies(xj_salaryVo.getAbsenteeismSubsidies().add(salaryDetail.getAbsenteeismSubsidies()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getMealFee())){
|
|
||||||
xj_salaryVo.setMealFee(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setMealFee(xj_salaryVo.getMealFee().add(salaryDetail.getMealFee()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getDeductions())){
|
|
||||||
xj_salaryVo.setDeductions(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setDeductions(xj_salaryVo.getDeductions().add(salaryDetail.getDeductions()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSalary())){
|
|
||||||
xj_salaryVo.setSalary(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSalary(xj_salaryVo.getSalary().add(salaryDetail.getSalary()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getPayInsurance())){
|
|
||||||
xj_salaryVo.setPayInsurance(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setPayInsurance(xj_salaryVo.getPayInsurance().add(salaryDetail.getPayInsurance()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSalaryBeforeTax())){
|
|
||||||
xj_salaryVo.setSalaryBeforeTax(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSalaryBeforeTax(xj_salaryVo.getSalaryBeforeTax().add(salaryDetail.getSalaryBeforeTax()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getTotalWages())){
|
|
||||||
xj_salaryVo.setTotalWages(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setTotalWages(xj_salaryVo.getTotalWages().add(salaryDetail.getTotalWages()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAnnualExemptionAmount())){
|
|
||||||
xj_salaryVo.setAnnualExemptionAmount(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAnnualExemptionAmount(xj_salaryVo.getAnnualExemptionAmount().add(salaryDetail.getAnnualExemptionAmount()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSpecialDeduction())){
|
|
||||||
xj_salaryVo.setSpecialDeduction(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSpecialDeduction(xj_salaryVo.getSpecialDeduction().add(salaryDetail.getSpecialDeduction()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getSlowDownTheDeduction())){
|
|
||||||
xj_salaryVo.setSlowDownTheDeduction(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setSlowDownTheDeduction(xj_salaryVo.getSlowDownTheDeduction().add(salaryDetail.getSlowDownTheDeduction()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getAggregatePersonalIncomeTax())){
|
|
||||||
xj_salaryVo.setAggregatePersonalIncomeTax(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setAggregatePersonalIncomeTax(xj_salaryVo.getAggregatePersonalIncomeTax().add(salaryDetail.getAggregatePersonalIncomeTax()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getTaxPayable())){
|
|
||||||
xj_salaryVo.setTaxPayable(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setTaxPayable(xj_salaryVo.getTaxPayable().add(salaryDetail.getTaxPayable()));
|
|
||||||
if(StringUtils.isNull(xj_salaryVo.getNetPayroll())){
|
|
||||||
xj_salaryVo.setNetPayroll(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
xj_salaryVo.setNetPayroll(xj_salaryVo.getNetPayroll().add(salaryDetail.getNetPayroll()));
|
|
||||||
BeanUtils.copyProperties(salaryDetail, salaryVo);
|
|
||||||
salaryVo.setDeptName(deptService.selectDeptById(salaryDetail.getDeptId()).getDeptName());
|
|
||||||
list0.add(salaryVo);
|
|
||||||
}
|
|
||||||
list.add(xj_salaryVo);
|
|
||||||
// payRollZong.setBasicSalary(DataUtils.findDefaultValue(xj_salaryVo.getBasicSalary(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getBasicSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
// payRollZong.setOvertimeSalary(DataUtils.findDefaultValue(xj_salaryVo.getOvertimeSalary(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getOvertimeSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setLevelSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getLevelSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getLevelSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setContractSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getContractSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getContractSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSenioritySalary(DataUtils.findDefaultValue(xj_salaryVo.getSenioritySalary(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSenioritySalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSocialSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getSocialSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSocialSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
// payRollZong.setFullSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getFullSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getFullSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setNightSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getNightSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getNightSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setDinnerSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getDinnerSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getDinnerSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSubsidyOrBonus(DataUtils.findDefaultValue(xj_salaryVo.getSubsidyOrBonus(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSubsidyOrBonus(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setAbsenteeismSalary(DataUtils.findDefaultValue(xj_salaryVo.getAbsenteeismSalary(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getAbsenteeismSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setAbsenteeismSubsidies(DataUtils.findDefaultValue(xj_salaryVo.getAbsenteeismSubsidies(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getAbsenteeismSubsidies(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setMealFee(DataUtils.findDefaultValue(xj_salaryVo.getMealFee(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getMealFee(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setDeductions(DataUtils.findDefaultValue(xj_salaryVo.getDeductions(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getDeductions(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSalary(DataUtils.findDefaultValue(xj_salaryVo.getSalary(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSalary(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setPayInsurance(DataUtils.findDefaultValue(xj_salaryVo.getPayInsurance(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getPayInsurance(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSalaryBeforeTax(DataUtils.findDefaultValue(xj_salaryVo.getSalaryBeforeTax(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSalaryBeforeTax(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setTotalWages(DataUtils.findDefaultValue(xj_salaryVo.getTotalWages(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getTotalWages(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setAnnualExemptionAmount(DataUtils.findDefaultValue(xj_salaryVo.getAnnualExemptionAmount(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getAnnualExemptionAmount(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSpecialDeduction(DataUtils.findDefaultValue(xj_salaryVo.getSpecialDeduction(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSpecialDeduction(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setSlowDownTheDeduction(DataUtils.findDefaultValue(xj_salaryVo.getSlowDownTheDeduction(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getSlowDownTheDeduction(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setAggregatePersonalIncomeTax(DataUtils.findDefaultValue(xj_salaryVo.getAggregatePersonalIncomeTax(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getAggregatePersonalIncomeTax(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setTaxPayable(DataUtils.findDefaultValue(xj_salaryVo.getTaxPayable(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getTaxPayable(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
payRollZong.setNetPayroll(DataUtils.findDefaultValue(xj_salaryVo.getNetPayroll(), DataUtils.DEFAULT_VALUE).add(DataUtils.findDefaultValue(payRollZong.getNetPayroll(), DataUtils.DEFAULT_VALUE)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list.add(payRollZong);
|
|
||||||
//表尾
|
|
||||||
String footer = "制表: "+"审核: "+"经理签字: "+"总经理签字: ";
|
|
||||||
return util.exportExcel(list,lists,"总表",sheetNameList,title,footer);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 导入销售提成
|
|
||||||
*/
|
|
||||||
// @PreAuthorize("@ss.hasPermi('finance:financeDetail:importSalesCommissions')")
|
|
||||||
// @Log(title = "导入销售提成", businessType = BusinessType.IMPORT)
|
|
||||||
// @PostMapping("/importSalesCommissions")
|
|
||||||
// public AjaxResult importSalesCommissions(MultipartFile file) throws Exception
|
|
||||||
// {
|
|
||||||
// ExcelUtil<RzSalaryVo> util = new ExcelUtil<>(RzSalaryVo.class);
|
|
||||||
// List<RzSalaryVo> attendanceList = util.importExcel(file.getInputStream());
|
|
||||||
// return success(rzSalaryDetailService.importSalesCommissions(attendanceList));
|
|
||||||
// }
|
|
||||||
/*
|
/*
|
||||||
* 导出工资详情列表
|
* 导出工资详情列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -3,11 +3,7 @@ package com.evo.finance.controller;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import com.evo.common.annotation.Log;
|
import com.evo.common.annotation.Log;
|
||||||
import com.evo.common.core.controller.BaseController;
|
import com.evo.common.core.controller.BaseController;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
@ -51,4 +47,15 @@ public class RzSalaryStatisticsController extends BaseController
|
|||||||
{
|
{
|
||||||
return rzSalaryStatisticsService.deleteRzSalaryStatisticsById(id);
|
return rzSalaryStatisticsService.deleteRzSalaryStatisticsById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认发放工资
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('finance:financeStatistics:confirm')")
|
||||||
|
@Log(title = "工资统计", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public AjaxResult confirm(@PathVariable Long id)
|
||||||
|
{
|
||||||
|
return rzSalaryStatisticsService.confirmRzSalaryStatisticsById(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -198,10 +198,28 @@ public class RzSalaryDetail extends BaseEntity
|
|||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private BigDecimal bjAmount;
|
private BigDecimal bjAmount;
|
||||||
|
/***
|
||||||
|
* 扣减费用,. 劳务税率计算
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private BigDecimal kjAmount;
|
||||||
|
//基本工资全薪
|
||||||
|
@TableField(exist = false)
|
||||||
|
private BigDecimal basicAmount;
|
||||||
|
|
||||||
/** 删除标识 */
|
/** 删除标识 */
|
||||||
private String delFlag;
|
private String delFlag;
|
||||||
|
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
public Integer getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(Integer type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getSalesCommission() {
|
public BigDecimal getSalesCommission() {
|
||||||
return salesCommission;
|
return salesCommission;
|
||||||
}
|
}
|
||||||
@ -630,6 +648,14 @@ public class RzSalaryDetail extends BaseEntity
|
|||||||
this.bjAmount = bjAmount;
|
this.bjAmount = bjAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getBasicAmount() {
|
||||||
|
return basicAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBasicAmount(BigDecimal basicAmount) {
|
||||||
|
this.basicAmount = basicAmount;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal getSocialSecurityDeduction() {
|
public BigDecimal getSocialSecurityDeduction() {
|
||||||
return socialSecurityDeduction;
|
return socialSecurityDeduction;
|
||||||
}
|
}
|
||||||
@ -638,6 +664,14 @@ public class RzSalaryDetail extends BaseEntity
|
|||||||
this.socialSecurityDeduction = socialSecurityDeduction;
|
this.socialSecurityDeduction = socialSecurityDeduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getKjAmount() {
|
||||||
|
return kjAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKjAmount(BigDecimal kjAmount) {
|
||||||
|
this.kjAmount = kjAmount;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "RzSalaryDetail{" +
|
return "RzSalaryDetail{" +
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import java.util.Date;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.evo.common.annotation.Excel;
|
import com.evo.common.annotation.Excel;
|
||||||
@ -16,6 +17,7 @@ import com.evo.common.core.domain.BaseEntity;
|
|||||||
* @author evo
|
* @author evo
|
||||||
* @date 2024-11-26
|
* @date 2024-11-26
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
public class RzSalaryStatistics extends BaseEntity
|
public class RzSalaryStatistics extends BaseEntity
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -43,61 +45,12 @@ public class RzSalaryStatistics extends BaseEntity
|
|||||||
|
|
||||||
/** 删除标识 */
|
/** 删除标识 */
|
||||||
private String delFlag;
|
private String delFlag;
|
||||||
|
/***
|
||||||
|
* 发放信息
|
||||||
|
*/
|
||||||
|
private String salaryInfo;
|
||||||
|
|
||||||
public void setId(Long id)
|
|
||||||
{
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getId()
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
public void setMonth(Date month)
|
|
||||||
{
|
|
||||||
this.month = month;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getMonth()
|
|
||||||
{
|
|
||||||
return month;
|
|
||||||
}
|
|
||||||
public void setNumber(int number)
|
|
||||||
{
|
|
||||||
this.number = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumber()
|
|
||||||
{
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
public void setStatus(String status)
|
|
||||||
{
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus()
|
|
||||||
{
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
public void setRemarks(String remarks)
|
|
||||||
{
|
|
||||||
this.remarks = remarks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRemarks()
|
|
||||||
{
|
|
||||||
return remarks;
|
|
||||||
}
|
|
||||||
public void setDelFlag(String delFlag)
|
|
||||||
{
|
|
||||||
this.delFlag = delFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDelFlag()
|
|
||||||
{
|
|
||||||
return delFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@ -3,10 +3,11 @@ package com.evo.finance.domain.vo;
|
|||||||
import com.evo.common.annotation.Excel;
|
import com.evo.common.annotation.Excel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SalaryVo {
|
public class SalaryVo implements Serializable {
|
||||||
|
|
||||||
@Excel(name = "序号")
|
@Excel(name = "序号")
|
||||||
private Integer seqNo;
|
private Integer seqNo;
|
||||||
|
|||||||
@ -62,6 +62,14 @@ public interface RzSalaryDetailMapper extends BaseMapper<RzSalaryDetail>
|
|||||||
* @return 工资详情集合
|
* @return 工资详情集合
|
||||||
*/
|
*/
|
||||||
public List<RzSalaryDetail> selectRzSalaryDetailByMonth(Date month);
|
public List<RzSalaryDetail> selectRzSalaryDetailByMonth(Date month);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据月份删除工资详情列表
|
||||||
|
*
|
||||||
|
* @param month 工资详情
|
||||||
|
* @return 工资详情集合
|
||||||
|
*/
|
||||||
|
public int deleteRzSalaryDetailByMonth(Date month);
|
||||||
/**
|
/**
|
||||||
* 根据部门查询工资单
|
* 根据部门查询工资单
|
||||||
* @return
|
* @return
|
||||||
@ -70,4 +78,8 @@ public interface RzSalaryDetailMapper extends BaseMapper<RzSalaryDetail>
|
|||||||
|
|
||||||
public List<RzSalaryDetail> selectSalaryDetailByWbFlag(@Param("wbFlag")String wbFlag,@Param("date")Date date);
|
public List<RzSalaryDetail> selectSalaryDetailByWbFlag(@Param("wbFlag")String wbFlag,@Param("date")Date date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public Date selectMaxMonthBySysStallId(Long id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.evo.finance.processor;
|
||||||
|
|
||||||
|
import com.evo.finance.domain.RzSalaryDetail;
|
||||||
|
import com.evo.system.domain.SysStaffDetail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc: 接口
|
||||||
|
* @ClassName:CalculationProcessor
|
||||||
|
* @date: 2026年05月04日 14:36
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
public interface CalculationProcessor {
|
||||||
|
|
||||||
|
boolean accept(String companyName);
|
||||||
|
|
||||||
|
RzSalaryDetail calculation(SysStaffDetail detail, RzSalaryDetail rzSalaryDetail);
|
||||||
|
}
|
||||||
@ -14,12 +14,15 @@ import com.evo.system.mapper.SysStaffDetailMapper;
|
|||||||
import com.evo.system.utils.SubsidyCalculationUtils;
|
import com.evo.system.utils.SubsidyCalculationUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,6 +42,9 @@ public interface SalaryCalculationStrategyExchangeProcessor {
|
|||||||
SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");
|
SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
SimpleDateFormat ym = new SimpleDateFormat("yyyy-MM");
|
SimpleDateFormat ym = new SimpleDateFormat("yyyy-MM");
|
||||||
SimpleDateFormat y = new SimpleDateFormat("yyyy");
|
SimpleDateFormat y = new SimpleDateFormat("yyyy");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
boolean accept(SysStaffDetail detail);
|
boolean accept(SysStaffDetail detail);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -74,7 +80,7 @@ public interface SalaryCalculationStrategyExchangeProcessor {
|
|||||||
* 计算新薪资
|
* 计算新薪资
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void exchangeSalaryCalculation(SysStaff sysStaff, SysStaffDetail detail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical, Map<Long, Boolean> overTimeMap);
|
void exchangeSalaryCalculation(SysStaff sysStaff, SysStaffDetail detail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical, Map<Long, Boolean> overTimeMap, List<Map<String,Object>> salaryInfoMapList);
|
||||||
|
|
||||||
void monthSalary(Date limitMonth, Date month, Date limitDate ,SysStaff sysStaff, SysStaffDetail sysStaffDetail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical);
|
void monthSalary(Date limitMonth, Date month, Date limitDate ,SysStaff sysStaff, SysStaffDetail sysStaffDetail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical);
|
||||||
|
|
||||||
@ -105,9 +111,10 @@ public interface SalaryCalculationStrategyExchangeProcessor {
|
|||||||
rzSalaryDetail.setSalary(rzSalaryDetail.getMonthSalary().add(isMonth ? rzSalaryDetail.getOvertimeSalary() : DataUtils.DEFAULT_VALUE).add(rzSalaryDetail.getNightSubsidies()).add(rzSalaryDetail.getMiddleSubsidies()).add(rzSalaryDetail.getDinnerSubsidies())
|
rzSalaryDetail.setSalary(rzSalaryDetail.getMonthSalary().add(isMonth ? rzSalaryDetail.getOvertimeSalary() : DataUtils.DEFAULT_VALUE).add(rzSalaryDetail.getNightSubsidies()).add(rzSalaryDetail.getMiddleSubsidies()).add(rzSalaryDetail.getDinnerSubsidies())
|
||||||
.add(DataUtils.findDefaultValue(rzSalaryDetail.getFullSubsidies(), DataUtils.DEFAULT_VALUE)).add(rzSalaryDetail.getLevelSubsidies()).add(rzSalaryDetail.getContractSubsidies()).add(rzSalaryDetail.getSocialSubsidies())
|
.add(DataUtils.findDefaultValue(rzSalaryDetail.getFullSubsidies(), DataUtils.DEFAULT_VALUE)).add(rzSalaryDetail.getLevelSubsidies()).add(rzSalaryDetail.getContractSubsidies()).add(rzSalaryDetail.getSocialSubsidies())
|
||||||
.add(rzSalaryDetail.getSenioritySalary()).add(rzSalaryDetail.getSubsidyOrBonus()).add(rzSalaryDetail.getSalesCommission())
|
.add(rzSalaryDetail.getSenioritySalary()).add(rzSalaryDetail.getSubsidyOrBonus()).add(rzSalaryDetail.getSalesCommission())
|
||||||
.subtract(rzSalaryDetail.getAbsenteeismSubsidies()).subtract(rzSalaryDetail.getDeductions()).subtract(rzSalaryDetail.getAbsenteeismSalary()).add(DataUtils.findDefaultValue(rzSalaryDetail.getBjAmount(), DataUtils.DEFAULT_VALUE)));
|
.subtract(rzSalaryDetail.getAbsenteeismSubsidies()).subtract(rzSalaryDetail.getDeductions()).subtract(rzSalaryDetail.getAbsenteeismSalary()).add(DataUtils.findDefaultValue(rzSalaryDetail.getBjAmount(), DataUtils.DEFAULT_VALUE))
|
||||||
|
.add(DataUtils.findDefaultValue(rzSalaryDetail.getBasicAmount(), DataUtils.DEFAULT_VALUE)));
|
||||||
//.subtract(rzSalaryDetail.getMealFee())
|
//.subtract(rzSalaryDetail.getMealFee())
|
||||||
//如果当前人员不打卡 则需要扣减缺勤工资
|
//如果当前人员不打卡 则需要扣减缺勤工资setBasicAmount
|
||||||
// if("否".equals(sysStaff.getClockIn())){
|
// if("否".equals(sysStaff.getClockIn())){
|
||||||
// rzSalaryDetail.setSalary(rzSalaryDetail.getSalary());
|
// rzSalaryDetail.setSalary(rzSalaryDetail.getSalary());
|
||||||
// }
|
// }
|
||||||
@ -218,7 +225,7 @@ public interface SalaryCalculationStrategyExchangeProcessor {
|
|||||||
* 开始计算薪资
|
* 开始计算薪资
|
||||||
*/
|
*/
|
||||||
|
|
||||||
default void calculation(SysStaff sysStaff, SysStaffDetail detail, RzSalaryDetail rzSalaryDetail){
|
default void calculation(SysStaff sysStaff, SysStaffDetail detail, RzSalaryDetail rzSalaryDetail, List<Map<String,Object>> salaryInfoMapList){
|
||||||
RzSalaryDetailMapper rzSalaryDetailMapper = SpringUtils.getBean(RzSalaryDetailMapper.class);
|
RzSalaryDetailMapper rzSalaryDetailMapper = SpringUtils.getBean(RzSalaryDetailMapper.class);
|
||||||
SysStaffDetailMapper sysStaffDetailMapper = SpringUtils.getBean(SysStaffDetailMapper.class);
|
SysStaffDetailMapper sysStaffDetailMapper = SpringUtils.getBean(SysStaffDetailMapper.class);
|
||||||
|
|
||||||
@ -258,109 +265,148 @@ public interface SalaryCalculationStrategyExchangeProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//判断是否外包,外包公司员工不做税(月薪50000不上税)
|
//判断是否外包,外包公司员工不做税(月薪50000不上税)
|
||||||
if(ParamUtils.getWebCompany().contains(sysStaff.getCompanyName().toUpperCase())){
|
Map<String, CalculationProcessor> calculationProcessorMap = SpringUtils.getApplicationContext().getBeansOfType(CalculationProcessor.class);
|
||||||
// 实发工资 = 税前工资
|
for (CalculationProcessor processor : calculationProcessorMap.values()) {
|
||||||
rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getMealFee()));
|
if (processor.accept(sysStaff.getCompanyName().toUpperCase())) {
|
||||||
// 此阶税率为百分之3,速减数为0
|
rzSalaryDetail = processor.calculation(detail, rzSalaryDetail);
|
||||||
rzSalaryDetail.setTaxRate(DataUtils.DEFAULT_VALUE);
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(DataUtils.DEFAULT_VALUE);
|
|
||||||
// 本年累计已缴税额
|
|
||||||
rzSalaryDetail.setAggregatePersonalIncomeTax(DataUtils.DEFAULT_VALUE);
|
|
||||||
rzSalaryDetail.setTaxPayable(DataUtils.DEFAULT_VALUE);
|
|
||||||
}else {
|
|
||||||
|
|
||||||
// 判断应纳税所得额额度(额度不一样税率不一样)
|
|
||||||
if (rzSalaryDetail.getTaxableIncome().doubleValue() > 0 && rzSalaryDetail.getTaxableIncome().doubleValue() <= 36000l) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.03"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
|
||||||
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 36000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 144000L) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.10"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("2520"));
|
|
||||||
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 144000L && rzSalaryDetail.getTaxableIncome().doubleValue() <= 300000l) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.20"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("16920"));
|
|
||||||
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 300000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 420000l) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.25"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("31920"));
|
|
||||||
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 420000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 660000l) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.30"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("52920"));
|
|
||||||
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 660000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 960000l) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.35"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("85920"));
|
|
||||||
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 960000l) {
|
|
||||||
// 此阶税率为百分之3,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.45"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("181920"));
|
|
||||||
} else {
|
|
||||||
// 应纳税所得额小于0(免征额+专项扣除>应发工资时)
|
|
||||||
// 此阶税率为百分之0,速减数为0
|
|
||||||
rzSalaryDetail.setTaxRate(new BigDecimal("0.00"));
|
|
||||||
// 速算扣除数(速算扣除数跟税率同步)
|
|
||||||
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 判断税前工资是否大于5000,如果小于,则不在计算个税
|
|
||||||
if (rzSalaryDetail.getSalaryBeforeTax().doubleValue() > 5000.00){
|
|
||||||
// 本月应缴税额(本月应纳税所得额*税率-速减数-本年累计已预缴个税)
|
|
||||||
rzSalaryDetail.setTaxPayable(rzSalaryDetail.getTaxableIncome().multiply(rzSalaryDetail.getTaxRate()).setScale(2, BigDecimal.ROUND_HALF_UP).subtract(rzSalaryDetail.getSlowDownTheDeduction()).subtract(detail.getAggregatePersonalIncomeTax()));
|
|
||||||
if (rzSalaryDetail.getTaxPayable().doubleValue() <= 0) {
|
|
||||||
rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 应纳税所得额
|
|
||||||
rzSalaryDetail.setTaxableIncome(new BigDecimal("0.00"));
|
|
||||||
rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
|
||||||
}
|
|
||||||
// 实发工资(税前工资-本月应缴个人所得税)
|
|
||||||
rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getTaxPayable()).subtract(rzSalaryDetail.getMealFee()));
|
|
||||||
// 本年累计已缴税额
|
|
||||||
rzSalaryDetail.setAggregatePersonalIncomeTax(detail.getAggregatePersonalIncomeTax().add(rzSalaryDetail.getTaxPayable()));
|
|
||||||
}
|
}
|
||||||
|
// if(ParamUtils.getWebCompany().contains(sysStaff.getCompanyName().toUpperCase())){
|
||||||
|
// // 实发工资 = 税前工资
|
||||||
|
// rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getMealFee()));
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(DataUtils.DEFAULT_VALUE);
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(DataUtils.DEFAULT_VALUE);
|
||||||
|
// // 本年累计已缴税额
|
||||||
|
// rzSalaryDetail.setAggregatePersonalIncomeTax(DataUtils.DEFAULT_VALUE);
|
||||||
|
// rzSalaryDetail.setTaxPayable(DataUtils.DEFAULT_VALUE);
|
||||||
|
// }else if (DataUtils.DEFAULT_VALUE.compareTo(ParamUtils.getWeBaoTaxCompany(sysStaff.getCompanyName().toUpperCase())) > 0){
|
||||||
|
// //劳务
|
||||||
|
// // 判断应纳税所得额额度(额度不一样税率不一样)
|
||||||
|
// rzSalaryDetail.setTaxRate(ParamUtils.getWeBaoTaxCompany(sysStaff.getCompanyName().toUpperCase()));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
||||||
|
// rzSalaryDetail.setTaxPayable(rzSalaryDetail.getTaxableIncome().multiply(rzSalaryDetail.getTaxRate()).setScale(2, BigDecimal.ROUND_HALF_UP).subtract(rzSalaryDetail.getSlowDownTheDeduction()).subtract(detail.getAggregatePersonalIncomeTax()));
|
||||||
|
// if (rzSalaryDetail.getTaxPayable().doubleValue() <= 0) {
|
||||||
|
// rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
||||||
|
// }
|
||||||
|
// rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getTaxPayable()).subtract(rzSalaryDetail.getMealFee()));
|
||||||
|
// // 本年累计已缴税额
|
||||||
|
// rzSalaryDetail.setAggregatePersonalIncomeTax(detail.getAggregatePersonalIncomeTax().add(rzSalaryDetail.getTaxPayable()));
|
||||||
|
// }else {
|
||||||
|
// // 判断应纳税所得额额度(额度不一样税率不一样)
|
||||||
|
// if (rzSalaryDetail.getTaxableIncome().doubleValue() > 0 && rzSalaryDetail.getTaxableIncome().doubleValue() <= 36000l) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.03"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
||||||
|
// } else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 36000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 144000L) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.10"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("2520"));
|
||||||
|
// } else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 144000L && rzSalaryDetail.getTaxableIncome().doubleValue() <= 300000l) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.20"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("16920"));
|
||||||
|
// } else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 300000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 420000l) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.25"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("31920"));
|
||||||
|
// } else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 420000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 660000l) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.30"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("52920"));
|
||||||
|
// } else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 660000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 960000l) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.35"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("85920"));
|
||||||
|
// } else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 960000l) {
|
||||||
|
// // 此阶税率为百分之3,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.45"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("181920"));
|
||||||
|
// } else {
|
||||||
|
// // 应纳税所得额小于0(免征额+专项扣除>应发工资时)
|
||||||
|
// // 此阶税率为百分之0,速减数为0
|
||||||
|
// rzSalaryDetail.setTaxRate(new BigDecimal("0.00"));
|
||||||
|
// // 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
// rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 判断税前工资是否大于5000,如果小于,则不在计算个税
|
||||||
|
// if (rzSalaryDetail.getSalaryBeforeTax().doubleValue() > 5000.00){
|
||||||
|
// // 本月应缴税额(本月应纳税所得额*税率-速减数-本年累计已预缴个税)
|
||||||
|
// rzSalaryDetail.setTaxPayable(rzSalaryDetail.getTaxableIncome().multiply(rzSalaryDetail.getTaxRate()).setScale(2, BigDecimal.ROUND_HALF_UP).subtract(rzSalaryDetail.getSlowDownTheDeduction()).subtract(detail.getAggregatePersonalIncomeTax()));
|
||||||
|
// if (rzSalaryDetail.getTaxPayable().doubleValue() <= 0) {
|
||||||
|
// rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // 应纳税所得额
|
||||||
|
// rzSalaryDetail.setTaxableIncome(new BigDecimal("0.00"));
|
||||||
|
// rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
||||||
|
// }
|
||||||
|
// // 实发工资(税前工资-本月应缴个人所得税)
|
||||||
|
// rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getTaxPayable()).subtract(rzSalaryDetail.getMealFee()));
|
||||||
|
// // 本年累计已缴税额
|
||||||
|
// rzSalaryDetail.setAggregatePersonalIncomeTax(detail.getAggregatePersonalIncomeTax().add(rzSalaryDetail.getTaxPayable()));
|
||||||
|
// }
|
||||||
rzSalaryDetail.setId(null);
|
rzSalaryDetail.setId(null);
|
||||||
//更新下全年累计
|
//更新下全年累计
|
||||||
rzSalaryDetail.setSpecialDeduction(detail.getSpecialDeduction().add(kouChu));
|
rzSalaryDetail.setSpecialDeduction(detail.getSpecialDeduction().add(kouChu));
|
||||||
if(rzSalaryDetailMapper.insert(rzSalaryDetail)< 0){
|
if(rzSalaryDetailMapper.insert(rzSalaryDetail)< 0){
|
||||||
throw new RuntimeException("生成员工考勤详情失败");
|
throw new RuntimeException("生成员工考勤详情失败");
|
||||||
}
|
}
|
||||||
//判断统计月缴费公司和上一次是否一个公司
|
Map<String, Object> salaryInfoMap = Collections.asMap("detailId", detail.getId());
|
||||||
if(StringUtils.isNull(old_rzSalary)
|
if(StringUtils.isNull(old_rzSalary)
|
||||||
|| !old_rzSalary.getWbFlag().equals(sysStaff.getCompanyName())
|
|| !old_rzSalary.getWbFlag().equals(sysStaff.getCompanyName())
|
||||||
//判断12月, 是个税系统, 每年12月更新, 开始累计次年1月数据
|
//判断12月, 是个税系统, 每年12月更新, 开始累计次年1月数据
|
||||||
|| curr_month == 12){
|
|| curr_month == 12){
|
||||||
// 把本年累计已缴个税保存到员工信息表中
|
// 把本年累计已缴个税保存到员工信息表中
|
||||||
detail.setAggregatePersonalIncomeTax(rzSalaryDetail.getTaxPayable());
|
salaryInfoMap.put("aggregatePersonalIncomeTax", rzSalaryDetail.getTaxPayable());
|
||||||
// 把本年累计专项扣除保存到员工信息表中
|
// 把本年累计专项扣除保存到员工信息表中
|
||||||
detail.setSpecialDeduction(kouChu);
|
salaryInfoMap.put("specialDeduction", kouChu);
|
||||||
// 把本年累计已发工资保存到员工信息表中
|
// 把本年累计已发工资保存到员工信息表中
|
||||||
detail.setTotalWages(rzSalaryDetail.getSalaryBeforeTax());
|
salaryInfoMap.put("totalWages", rzSalaryDetail.getSalaryBeforeTax());
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// 把本年累计个税
|
// 把本年累计已缴个税保存到员工信息表中
|
||||||
detail.setAggregatePersonalIncomeTax(rzSalaryDetail.getAggregatePersonalIncomeTax());
|
salaryInfoMap.put("aggregatePersonalIncomeTax", rzSalaryDetail.getAggregatePersonalIncomeTax());
|
||||||
// 把本年累计专项扣除保存到员工信息表中
|
// 把本年累计专项扣除保存到员工信息表中
|
||||||
detail.setSpecialDeduction(detail.getSpecialDeduction().add(kouChu));
|
salaryInfoMap.put("specialDeduction", detail.getSpecialDeduction().add(kouChu));
|
||||||
// 把本年累计已发工资保存到员工信息表中
|
// 把本年累计已发工资保存到员工信息表中
|
||||||
detail.setTotalWages(rzSalaryDetail.getTotalWages());
|
salaryInfoMap.put("totalWages", rzSalaryDetail.getTotalWages());
|
||||||
}
|
|
||||||
if(sysStaffDetailMapper.updateSysStaffDetail(detail)< 0){
|
|
||||||
throw new RuntimeException("更新员工详情信息异常");
|
|
||||||
}
|
}
|
||||||
|
salaryInfoMapList.add(salaryInfoMap);
|
||||||
|
|
||||||
|
//判断统计月缴费公司和上一次是否一个公司
|
||||||
|
// if(StringUtils.isNull(old_rzSalary)
|
||||||
|
// || !old_rzSalary.getWbFlag().equals(sysStaff.getCompanyName())
|
||||||
|
// //判断12月, 是个税系统, 每年12月更新, 开始累计次年1月数据
|
||||||
|
// || curr_month == 12){
|
||||||
|
// // 把本年累计已缴个税保存到员工信息表中
|
||||||
|
// detail.setAggregatePersonalIncomeTax(rzSalaryDetail.getTaxPayable());
|
||||||
|
// // 把本年累计专项扣除保存到员工信息表中
|
||||||
|
// detail.setSpecialDeduction(kouChu);
|
||||||
|
// // 把本年累计已发工资保存到员工信息表中
|
||||||
|
// detail.setTotalWages(rzSalaryDetail.getSalaryBeforeTax());
|
||||||
|
//
|
||||||
|
// }else{
|
||||||
|
// // 把本年累计个税
|
||||||
|
// detail.setAggregatePersonalIncomeTax(rzSalaryDetail.getAggregatePersonalIncomeTax());
|
||||||
|
// // 把本年累计专项扣除保存到员工信息表中
|
||||||
|
// detail.setSpecialDeduction(detail.getSpecialDeduction().add(kouChu));
|
||||||
|
// // 把本年累计已发工资保存到员工信息表中
|
||||||
|
// detail.setTotalWages(rzSalaryDetail.getTotalWages());
|
||||||
|
// }
|
||||||
|
// if(sysStaffDetailMapper.updateSysStaffDetail(detail)< 0){
|
||||||
|
// throw new RuntimeException("更新员工详情信息异常");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,11 +42,11 @@ public class DailyWageStrategyExchangeProcessor implements SalaryCalculationStra
|
|||||||
@Override
|
@Override
|
||||||
public boolean accept(SysStaffDetail detail) {
|
public boolean accept(SysStaffDetail detail) {
|
||||||
//日薪不为空, 并且大于0
|
//日薪不为空, 并且大于0
|
||||||
return detail.getDailyWage() != null && detail.getDailyWage().compareTo(new BigDecimal(0)) > 0;
|
return detail != null && detail.getDailyWage() != null && detail.getDailyWage().compareTo(new BigDecimal(0)) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exchangeSalaryCalculation(SysStaff sysStaff, SysStaffDetail sysStaffDetail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical, Map<Long, Boolean> overTimeMap) {
|
public void exchangeSalaryCalculation(SysStaff sysStaff, SysStaffDetail sysStaffDetail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical, Map<Long, Boolean> overTimeMap, List<Map<String,Object>> salaryInfoMapList) {
|
||||||
// //计算社保
|
// //计算社保
|
||||||
// socialSecurity(sysStaff,sysStaffDetail, attendanceStatistical);
|
// socialSecurity(sysStaff,sysStaffDetail, attendanceStatistical);
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public class DailyWageStrategyExchangeProcessor implements SalaryCalculationStra
|
|||||||
buildRzSalaryDetail(false, sysStaff, sysStaffDetail,rzSalaryDetail, attendanceStatistical);
|
buildRzSalaryDetail(false, sysStaff, sysStaffDetail,rzSalaryDetail, attendanceStatistical);
|
||||||
|
|
||||||
//计算薪资
|
//计算薪资
|
||||||
calculation(sysStaff, sysStaffDetail,rzSalaryDetail);
|
calculation(sysStaff, sysStaffDetail,rzSalaryDetail, salaryInfoMapList);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,71 @@
|
|||||||
|
package com.evo.finance.processor.impl;
|
||||||
|
|
||||||
|
import com.evo.common.utils.DataUtils;
|
||||||
|
import com.evo.common.utils.ParamUtils;
|
||||||
|
import com.evo.finance.domain.RzSalaryDetail;
|
||||||
|
import com.evo.finance.processor.CalculationProcessor;
|
||||||
|
import com.evo.system.domain.SysStaffDetail;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc:
|
||||||
|
* @ClassName:LWTaxCalculationProcessor
|
||||||
|
* @date: 2026年05月04日 14:42
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class LWTaxCalculationProcessor implements CalculationProcessor {
|
||||||
|
private String companyName;
|
||||||
|
@Override
|
||||||
|
public boolean accept(String companyName) {
|
||||||
|
this.companyName = companyName;;
|
||||||
|
return ParamUtils.getWeBaoTaxCompany().contains(companyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzSalaryDetail calculation(SysStaffDetail detail, RzSalaryDetail rzSalaryDetail) {
|
||||||
|
//年度免征额 强制归0
|
||||||
|
rzSalaryDetail.setAnnualExemptionAmount(DataUtils.DEFAULT_VALUE);
|
||||||
|
|
||||||
|
if (rzSalaryDetail.getSalaryBeforeTax().doubleValue() <= 4000) {
|
||||||
|
rzSalaryDetail.setTaxableIncome(rzSalaryDetail.getSalaryBeforeTax().subtract(BigDecimal.valueOf(800)));
|
||||||
|
if (rzSalaryDetail.getTaxableIncome().doubleValue() <= 0) {
|
||||||
|
rzSalaryDetail.setTaxableIncome(new BigDecimal("0.00"));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
rzSalaryDetail.setTaxableIncome(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getSalaryBeforeTax().multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_HALF_UP)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rzSalaryDetail.getTaxableIncome().doubleValue() <= 20000L) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.20"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(DataUtils.DEFAULT_VALUE);
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 20000L && rzSalaryDetail.getTaxableIncome().doubleValue() <= 50000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.3"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("2000"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 50000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.40"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("7000"));
|
||||||
|
}
|
||||||
|
rzSalaryDetail.setTaxPayable(rzSalaryDetail.getTaxableIncome().multiply(rzSalaryDetail.getTaxRate()).setScale(2, BigDecimal.ROUND_HALF_UP).subtract(rzSalaryDetail.getSlowDownTheDeduction()));
|
||||||
|
if (rzSalaryDetail.getTaxPayable().doubleValue() < 0) {
|
||||||
|
rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实发工资(税前工资-本月应缴个人所得税)
|
||||||
|
rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getTaxPayable()).subtract(rzSalaryDetail.getMealFee()));
|
||||||
|
// 本年累计已缴税额
|
||||||
|
rzSalaryDetail.setAggregatePersonalIncomeTax(rzSalaryDetail.getTaxPayable());
|
||||||
|
|
||||||
|
return rzSalaryDetail;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,8 @@ import com.evo.finance.processor.SalaryCalculationStrategyExchangeProcessor;
|
|||||||
import com.evo.personnelMatters.mapper.RzLeaveDetailMapper;
|
import com.evo.personnelMatters.mapper.RzLeaveDetailMapper;
|
||||||
import com.evo.system.domain.SysStaff;
|
import com.evo.system.domain.SysStaff;
|
||||||
import com.evo.system.domain.SysStaffDetail;
|
import com.evo.system.domain.SysStaffDetail;
|
||||||
|
import com.evo.utils.DateUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@ -36,12 +38,14 @@ public class MonthlySalaryStrategyExchangeProcessor implements SalaryCalculation
|
|||||||
private RzAttendanceMapper rzAttendanceMapper;
|
private RzAttendanceMapper rzAttendanceMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private RzLeaveDetailMapper rzLeaveDetailMapper;
|
private RzLeaveDetailMapper rzLeaveDetailMapper;
|
||||||
|
@Autowired
|
||||||
|
private DateUtil dateUtil1;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(SysStaffDetail detail) {
|
public boolean accept(SysStaffDetail detail) {
|
||||||
//基本工资不为空, 并且大于0 并且岗位工资不为空, 并且大于0
|
//基本工资不为空, 并且大于0 并且岗位工资不为空, 并且大于0
|
||||||
return (detail.getBasicSalary() != null && detail.getBasicSalary().compareTo(new BigDecimal(0)) > 0) && (detail.getJobsSalary() != null && detail.getJobsSalary().compareTo(new BigDecimal(0)) > 0);
|
return (detail != null && detail.getBasicSalary() != null && detail.getBasicSalary().compareTo(new BigDecimal(0)) > 0) && (detail.getJobsSalary() != null && detail.getJobsSalary().compareTo(new BigDecimal(0)) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -52,13 +56,13 @@ public class MonthlySalaryStrategyExchangeProcessor implements SalaryCalculation
|
|||||||
* @param overTimeMap
|
* @param overTimeMap
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void exchangeSalaryCalculation(SysStaff sysStaff, SysStaffDetail sysStaffDetail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical, Map<Long, Boolean> overTimeMap) {
|
public void exchangeSalaryCalculation(SysStaff sysStaff, SysStaffDetail sysStaffDetail, RzSalaryDetail rzSalaryDetail, RzAttendanceStatistical attendanceStatistical, Map<Long, Boolean> overTimeMap, List<Map<String,Object>> salaryInfoMapList) {
|
||||||
//计算社保
|
//计算社保
|
||||||
//socialSecurity(sysStaff,sysStaffDetail, attendanceStatistical);
|
//socialSecurity(sysStaff,sysStaffDetail, attendanceStatistical);
|
||||||
//组件基础数据
|
//组件基础数据
|
||||||
buildRzSalaryDetail(true, sysStaff, sysStaffDetail,rzSalaryDetail, attendanceStatistical);
|
buildRzSalaryDetail(true, sysStaff, sysStaffDetail,rzSalaryDetail, attendanceStatistical);
|
||||||
//计算薪资
|
//计算薪资
|
||||||
calculation(sysStaff, sysStaffDetail,rzSalaryDetail);
|
calculation(sysStaff, sysStaffDetail,rzSalaryDetail, salaryInfoMapList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -115,8 +119,29 @@ public class MonthlySalaryStrategyExchangeProcessor implements SalaryCalculation
|
|||||||
BigDecimal gs = rzSalaryDetail.getBasicSalary().multiply(new BigDecimal(Constants.SUBSIDY_PERIOD)).divide(new BigDecimal(ParamUtils.getMonthWorkDayNum(DateUtils.getYear(rzSalaryDetail.getMonth()), DateUtils.getMonth(rzSalaryDetail.getMonth()))),2, RoundingMode.HALF_UP).multiply(new BigDecimal(total8Hour).divide(Constants.DAY_WORK_HOUR,2,RoundingMode.HALF_UP));
|
BigDecimal gs = rzSalaryDetail.getBasicSalary().multiply(new BigDecimal(Constants.SUBSIDY_PERIOD)).divide(new BigDecimal(ParamUtils.getMonthWorkDayNum(DateUtils.getYear(rzSalaryDetail.getMonth()), DateUtils.getMonth(rzSalaryDetail.getMonth()))),2, RoundingMode.HALF_UP).multiply(new BigDecimal(total8Hour).divide(Constants.DAY_WORK_HOUR,2,RoundingMode.HALF_UP));
|
||||||
// rzSalaryDetail.setMonthSalary(rzSalaryDetail.getMonthSalary().add(gs));
|
// rzSalaryDetail.setMonthSalary(rzSalaryDetail.getMonthSalary().add(gs));
|
||||||
rzSalaryDetail.setBjAmount(gs);
|
rzSalaryDetail.setBjAmount(gs);
|
||||||
|
}
|
||||||
|
if(sysStaff.getName().equals("史国臣")){
|
||||||
|
System.out.println("11111");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal basic = new BigDecimal("0");
|
||||||
|
Long basicHour = 0l;
|
||||||
|
for (Long type: ParamUtils.getBasicVacation()) {
|
||||||
|
Long hour = rzLeaveDetailMapper.selectLeaveHourByUserIdAndDateAndType(sysStaff.getUserId(), rzSalaryDetail.getMonth(), type);
|
||||||
|
if(hour.compareTo(0l)> 0){
|
||||||
|
basicHour = basicHour+ hour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(basicHour.compareTo(0l)> 0){
|
||||||
|
//存在工伤假, 需要计算
|
||||||
|
basic = rzSalaryDetail.getBasicSalary().divide(new BigDecimal(ParamUtils.getMonthWorkDayNum(DateUtils.getYear(rzSalaryDetail.getMonth()), DateUtils.getMonth(rzSalaryDetail.getMonth()))),2, RoundingMode.HALF_UP).multiply(new BigDecimal(basicHour).divide(Constants.DAY_WORK_HOUR,2,RoundingMode.HALF_UP));
|
||||||
|
// rzSalaryDetail.setMonthSalary(rzSalaryDetail.getMonthSalary().add(gs));
|
||||||
|
// rzSalaryDetail.setBjAmount(DataUtils.findDefaultValue(rzSalaryDetail.getBjAmount(), DataUtils.DEFAULT_VALUE).add(basic));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BigDecimal gsj = new BigDecimal(0);
|
BigDecimal gsj = new BigDecimal(0);
|
||||||
Long totalAllHour = 0l;
|
Long totalAllHour = 0l;
|
||||||
for (Long type: ParamUtils.getFullPaidLeave()) {
|
for (Long type: ParamUtils.getFullPaidLeave()) {
|
||||||
@ -128,6 +153,20 @@ public class MonthlySalaryStrategyExchangeProcessor implements SalaryCalculation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//获取所有的基本薪资
|
||||||
|
Long totalBasicHour = 0l;
|
||||||
|
for (Long type: ParamUtils.getBasicFullPaidLeave()) {
|
||||||
|
Long hour = rzLeaveDetailMapper.selectLeaveHourByUserIdAndDateAndType(sysStaff.getUserId(), rzSalaryDetail.getMonth(), type);
|
||||||
|
if(hour.compareTo(0l)> 0){
|
||||||
|
totalBasicHour = totalBasicHour+hour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(totalBasicHour.compareTo(0l)> 0){
|
||||||
|
//存在工伤假, 需要计算
|
||||||
|
BigDecimal basicAmount = rzSalaryDetail.getBasicSalary().divide(new BigDecimal(ParamUtils.getMonthWorkDayNum(DateUtils.getYear(rzSalaryDetail.getMonth()), DateUtils.getMonth(rzSalaryDetail.getMonth()))),2, RoundingMode.HALF_UP).multiply(new BigDecimal(totalBasicHour).divide(Constants.DAY_WORK_HOUR,2,RoundingMode.HALF_UP));
|
||||||
|
rzSalaryDetail.setBasicAmount(basicAmount);
|
||||||
|
}
|
||||||
|
|
||||||
// if(totalAllHour.compareTo(0l)> 0){
|
// if(totalAllHour.compareTo(0l)> 0){
|
||||||
// //存在工伤假, 需要计算
|
// //存在工伤假, 需要计算
|
||||||
// rzSalaryDetail.setMonthSalary(rzSalaryDetail.getMonthSalary().add(workHourPrice.multiply(new BigDecimal(totalAllHour))));
|
// rzSalaryDetail.setMonthSalary(rzSalaryDetail.getMonthSalary().add(workHourPrice.multiply(new BigDecimal(totalAllHour))));
|
||||||
@ -144,7 +183,7 @@ public class MonthlySalaryStrategyExchangeProcessor implements SalaryCalculation
|
|||||||
//计算社保占比
|
//计算社保占比
|
||||||
socialSecurity(sysStaff, detail, gsj, attendanceStatistical);
|
socialSecurity(sysStaff, detail, gsj, attendanceStatistical);
|
||||||
|
|
||||||
//请假时长
|
//缺勤扣款
|
||||||
rzSalaryDetail.setAbsenteeismSalary(hourlyWage.multiply(attendanceStatistical.getAbsenteeism().subtract(new BigDecimal(totalAllHour))));
|
rzSalaryDetail.setAbsenteeismSalary(hourlyWage.multiply(attendanceStatistical.getAbsenteeism().subtract(new BigDecimal(totalAllHour))).subtract(basic));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.evo.finance.processor.impl;
|
||||||
|
|
||||||
|
import com.evo.common.utils.DataUtils;
|
||||||
|
import com.evo.common.utils.ParamUtils;
|
||||||
|
import com.evo.finance.domain.RzSalaryDetail;
|
||||||
|
import com.evo.finance.processor.CalculationProcessor;
|
||||||
|
import com.evo.system.domain.SysStaffDetail;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc:
|
||||||
|
* @ClassName:NotTaxCalculationProcessor
|
||||||
|
* @date: 2026年05月04日 14:40
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class NotTaxCalculationProcessor implements CalculationProcessor {
|
||||||
|
@Override
|
||||||
|
public boolean accept(String companyName) {
|
||||||
|
return ParamUtils.getWebCompany().contains(companyName.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzSalaryDetail calculation(SysStaffDetail detail, RzSalaryDetail rzSalaryDetail) {
|
||||||
|
// 实发工资 = 税前工资
|
||||||
|
rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getMealFee()));
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(DataUtils.DEFAULT_VALUE);
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(DataUtils.DEFAULT_VALUE);
|
||||||
|
// 本年累计已缴税额
|
||||||
|
rzSalaryDetail.setAggregatePersonalIncomeTax(DataUtils.DEFAULT_VALUE);
|
||||||
|
rzSalaryDetail.setTaxPayable(DataUtils.DEFAULT_VALUE);
|
||||||
|
|
||||||
|
return rzSalaryDetail;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
package com.evo.finance.processor.impl;
|
||||||
|
|
||||||
|
import com.evo.common.utils.DataUtils;
|
||||||
|
import com.evo.common.utils.ParamUtils;
|
||||||
|
import com.evo.finance.domain.RzSalaryDetail;
|
||||||
|
import com.evo.finance.processor.CalculationProcessor;
|
||||||
|
import com.evo.system.domain.SysStaffDetail;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc:
|
||||||
|
* @ClassName:TaxCalculationProcessor
|
||||||
|
* @date: 2026年05月04日 14:42
|
||||||
|
* @author: andy.shi
|
||||||
|
* @contact: 17330188597
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TaxCalculationProcessor implements CalculationProcessor {
|
||||||
|
@Override
|
||||||
|
public boolean accept(String companyName) {
|
||||||
|
return !ParamUtils.getWeBaoTaxCompany().contains(companyName) && !ParamUtils.getWebCompany().contains(companyName.toUpperCase()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzSalaryDetail calculation(SysStaffDetail detail, RzSalaryDetail rzSalaryDetail) {
|
||||||
|
// 判断应纳税所得额额度(额度不一样税率不一样)
|
||||||
|
if (rzSalaryDetail.getTaxableIncome().doubleValue() > 0 && rzSalaryDetail.getTaxableIncome().doubleValue() <= 36000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.03"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 36000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 144000L) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.10"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("2520"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 144000L && rzSalaryDetail.getTaxableIncome().doubleValue() <= 300000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.20"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("16920"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 300000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 420000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.25"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("31920"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 420000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 660000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.30"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("52920"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 660000l && rzSalaryDetail.getTaxableIncome().doubleValue() <= 960000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.35"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("85920"));
|
||||||
|
} else if (rzSalaryDetail.getTaxableIncome().doubleValue() > 960000l) {
|
||||||
|
// 此阶税率为百分之3,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.45"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("181920"));
|
||||||
|
} else {
|
||||||
|
// 应纳税所得额小于0(免征额+专项扣除>应发工资时)
|
||||||
|
// 此阶税率为百分之0,速减数为0
|
||||||
|
rzSalaryDetail.setTaxRate(new BigDecimal("0.00"));
|
||||||
|
// 速算扣除数(速算扣除数跟税率同步)
|
||||||
|
rzSalaryDetail.setSlowDownTheDeduction(new BigDecimal("0"));
|
||||||
|
}
|
||||||
|
// 判断税前工资是否大于5000,如果小于,则不在计算个税
|
||||||
|
if (rzSalaryDetail.getSalaryBeforeTax().doubleValue() > 5000.00){
|
||||||
|
// 本月应缴税额(本月应纳税所得额*税率-速减数-本年累计已预缴个税)
|
||||||
|
rzSalaryDetail.setTaxPayable(rzSalaryDetail.getTaxableIncome().multiply(rzSalaryDetail.getTaxRate()).setScale(2, BigDecimal.ROUND_HALF_UP).subtract(rzSalaryDetail.getSlowDownTheDeduction()).subtract(detail.getAggregatePersonalIncomeTax()));
|
||||||
|
if (rzSalaryDetail.getTaxPayable().doubleValue() <= 0) {
|
||||||
|
rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 应纳税所得额
|
||||||
|
rzSalaryDetail.setTaxableIncome(new BigDecimal("0.00"));
|
||||||
|
rzSalaryDetail.setTaxPayable(new BigDecimal("0.00"));
|
||||||
|
}
|
||||||
|
// 实发工资(税前工资-本月应缴个人所得税)
|
||||||
|
rzSalaryDetail.setNetPayroll(rzSalaryDetail.getSalaryBeforeTax().subtract(rzSalaryDetail.getTaxPayable()).subtract(rzSalaryDetail.getMealFee()));
|
||||||
|
// 本年累计已缴税额
|
||||||
|
rzSalaryDetail.setAggregatePersonalIncomeTax(detail.getAggregatePersonalIncomeTax().add(rzSalaryDetail.getTaxPayable()));
|
||||||
|
|
||||||
|
return rzSalaryDetail;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import java.util.List;
|
|||||||
import com.evo.attendance.domain.vo.RzSalaryVo;
|
import com.evo.attendance.domain.vo.RzSalaryVo;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.finance.domain.RzSalaryDetail;
|
import com.evo.finance.domain.RzSalaryDetail;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,4 +70,6 @@ public interface IRzSalaryDetailService
|
|||||||
public List<RzSalaryDetail> selectSalaryDetailByWbFlag(String wbFlag,Date date);
|
public List<RzSalaryDetail> selectSalaryDetailByWbFlag(String wbFlag,Date date);
|
||||||
|
|
||||||
AjaxResult export(RzSalaryDetail rzSalaryDetail);
|
AjaxResult export(RzSalaryDetail rzSalaryDetail);
|
||||||
|
|
||||||
|
void dimission(SysStaff sysStaff);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,4 +35,6 @@ public interface IRzSalaryStatisticsService extends IService<RzSalaryStatistics>
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public AjaxResult deleteRzSalaryStatisticsById(Long id);
|
public AjaxResult deleteRzSalaryStatisticsById(Long id);
|
||||||
|
|
||||||
|
public AjaxResult confirmRzSalaryStatisticsById(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.evo.finance.service.impl;
|
package com.evo.finance.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.evo.attendance.domain.RzAttendanceStatistical;
|
import com.evo.attendance.domain.RzAttendanceStatistical;
|
||||||
@ -139,33 +140,76 @@ public class RzSalaryDetailServiceImpl extends ServiceImpl<RzSalaryDetailMapper,
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
Map<Long, Boolean> overTimeMap = deptMapper.selectList(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDelFlag, Constants.DELETE_FLAG_0).select(SysDept::getIsOverTime, SysDept::getDeptId)).stream().collect(Collectors.toMap(SysDept::getDeptId,d->"0".equals(d.getIsOverTime())));
|
Map<Long, Boolean> overTimeMap = deptMapper.selectList(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDelFlag, Constants.DELETE_FLAG_0).select(SysDept::getIsOverTime, SysDept::getDeptId)).stream().collect(Collectors.toMap(SysDept::getDeptId,d->"0".equals(d.getIsOverTime())));
|
||||||
|
List<Map<String,Object>> salaryInfoMapList = Collections.emptyList();
|
||||||
for (SysStaff sysStaff : st_list) {
|
for (SysStaff sysStaff : st_list) {
|
||||||
RzSalaryDetail newRzSalaryDetail = new RzSalaryDetail();
|
//<<<<<<< HEAD
|
||||||
newRzSalaryDetail.setMonth(rzSalaryDetail.getMonth());
|
// RzSalaryDetail newRzSalaryDetail = new RzSalaryDetail();
|
||||||
newRzSalaryDetail.setStaffId(sysStaff.getUserId()); //员工ID
|
// newRzSalaryDetail.setMonth(rzSalaryDetail.getMonth());
|
||||||
newRzSalaryDetail.setDeptId(sysStaff.getDeptId()); //部门
|
// newRzSalaryDetail.setStaffId(sysStaff.getUserId()); //员工ID
|
||||||
newRzSalaryDetail.setName(sysStaff.getName()); //姓名
|
// newRzSalaryDetail.setDeptId(sysStaff.getDeptId()); //部门
|
||||||
newRzSalaryDetail.setWbFlag(sysStaff.getCompanyName()); //公司
|
// newRzSalaryDetail.setName(sysStaff.getName()); //姓名
|
||||||
newRzSalaryDetail.setDelFlag(Constants.DELETE_FLAG_0);
|
// newRzSalaryDetail.setWbFlag(sysStaff.getCompanyName()); //公司
|
||||||
//查询考勤统计
|
// newRzSalaryDetail.setDelFlag(Constants.DELETE_FLAG_0);
|
||||||
RzAttendanceStatistical attendanceStatistical = rzAttendanceStatisticalMapper.getRzAttendanceStatisticalByDateAndName(sysStaff.getUserId(), rzSalaryDetail.getMonth());
|
// //查询考勤统计
|
||||||
//查询员工详情
|
// RzAttendanceStatistical attendanceStatistical = rzAttendanceStatisticalMapper.getRzAttendanceStatisticalByDateAndName(sysStaff.getUserId(), rzSalaryDetail.getMonth());
|
||||||
SysStaffDetail sysStaffDetail = sysStaffDetailMapper.selectSysStaffDetailByStaffId(sysStaff.getUserId());
|
// //查询员工详情
|
||||||
|
// SysStaffDetail sysStaffDetail = sysStaffDetailMapper.selectSysStaffDetailByStaffId(sysStaff.getUserId());
|
||||||
Map<String, SalaryCalculationStrategyExchangeProcessor> salaryCalculationExchangeProcessorMap = applicationContext.getBeansOfType(SalaryCalculationStrategyExchangeProcessor.class);
|
// Map<String, SalaryCalculationStrategyExchangeProcessor> salaryCalculationExchangeProcessorMap = applicationContext.getBeansOfType(SalaryCalculationStrategyExchangeProcessor.class);
|
||||||
for (SalaryCalculationStrategyExchangeProcessor processor : salaryCalculationExchangeProcessorMap.values()) {
|
// for (SalaryCalculationStrategyExchangeProcessor processor : salaryCalculationExchangeProcessorMap.values()) {
|
||||||
if (processor.accept(sysStaffDetail)) {
|
// if (processor.accept(sysStaffDetail)) {
|
||||||
processor.exchangeSalaryCalculation(sysStaff, sysStaffDetail, newRzSalaryDetail, attendanceStatistical, overTimeMap);
|
// processor.exchangeSalaryCalculation(sysStaff, sysStaffDetail, newRzSalaryDetail, attendanceStatistical, overTimeMap, salaryInfoMapList);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//=======
|
||||||
|
calculation(sysStaff, rzSalaryDetail.getMonth(), overTimeMap, 1, salaryInfoMapList);
|
||||||
}
|
}
|
||||||
|
rzSalaryStatistics.setSalaryInfo(JSON.toJSONString(salaryInfoMapList));
|
||||||
|
rzSalaryStatisticsMapper.updateById(rzSalaryStatistics);
|
||||||
//关闭日志记录
|
//关闭日志记录
|
||||||
ParamUtils.updateLogOperation(false);
|
ParamUtils.updateLogOperation(false);
|
||||||
return AjaxResult.success();
|
return AjaxResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dimission(SysStaff sysStaff) {
|
||||||
|
Map<Long, Boolean> overTimeMap = deptMapper.selectList(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDelFlag, Constants.DELETE_FLAG_0).select(SysDept::getIsOverTime, SysDept::getDeptId)).stream().collect(Collectors.toMap(SysDept::getDeptId,d->"0".equals(d.getIsOverTime())));
|
||||||
|
Date date = getBaseMapper().selectMaxMonthBySysStallId(sysStaff.getUserId());
|
||||||
|
//如果为空, 入职时间-1个月 作为起始时间
|
||||||
|
if(date != null){
|
||||||
|
date = DateUtils.addMonths(date, 1);
|
||||||
|
}else{
|
||||||
|
date = sysStaff.getEmploymentDate();
|
||||||
|
}
|
||||||
|
List<Map<String,Object>> salaryInfoMapList = Collections.emptyList();
|
||||||
|
//进行离职工资计算操作
|
||||||
|
while (date.compareTo(sysStaff.getQuitDate()) < 1){
|
||||||
|
calculation(sysStaff, date, overTimeMap ,2, salaryInfoMapList);
|
||||||
|
date = DateUtils.addMonths(date, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculation(SysStaff sysStaff, Date date, Map<Long, Boolean> overTimeMap, Integer type,List<Map<String,Object>> salaryInfoMapList){
|
||||||
|
RzSalaryDetail newRzSalaryDetail = new RzSalaryDetail();
|
||||||
|
newRzSalaryDetail.setMonth(date);
|
||||||
|
newRzSalaryDetail.setStaffId(sysStaff.getUserId()); //员工ID
|
||||||
|
newRzSalaryDetail.setDeptId(sysStaff.getDeptId()); //部门
|
||||||
|
newRzSalaryDetail.setName(sysStaff.getName()); //姓名
|
||||||
|
newRzSalaryDetail.setWbFlag(sysStaff.getCompanyName()); //公司
|
||||||
|
newRzSalaryDetail.setDelFlag(Constants.DELETE_FLAG_0);
|
||||||
|
newRzSalaryDetail.setType(type);
|
||||||
|
//查询考勤统计
|
||||||
|
RzAttendanceStatistical attendanceStatistical = rzAttendanceStatisticalMapper.getRzAttendanceStatisticalByDateAndName(sysStaff.getUserId(), date);
|
||||||
|
//查询员工详情
|
||||||
|
SysStaffDetail sysStaffDetail = sysStaffDetailMapper.selectSysStaffDetailByStaffId(sysStaff.getUserId());
|
||||||
|
|
||||||
|
Map<String, SalaryCalculationStrategyExchangeProcessor> salaryCalculationExchangeProcessorMap = applicationContext.getBeansOfType(SalaryCalculationStrategyExchangeProcessor.class);
|
||||||
|
for (SalaryCalculationStrategyExchangeProcessor processor : salaryCalculationExchangeProcessorMap.values()) {
|
||||||
|
if (processor.accept(sysStaffDetail)) {
|
||||||
|
processor.exchangeSalaryCalculation(sysStaff, sysStaffDetail, newRzSalaryDetail, attendanceStatistical, overTimeMap, salaryInfoMapList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,7 +325,7 @@ public class RzSalaryDetailServiceImpl extends ServiceImpl<RzSalaryDetailMapper,
|
|||||||
deptLists.add(depts);
|
deptLists.add(depts);
|
||||||
}
|
}
|
||||||
SalaryVo result = sumSalaryVo(allList);
|
SalaryVo result = sumSalaryVo(allList);
|
||||||
result.setDeptName(sheetCompanyName+"总计");
|
result.setDeptName(sheetCompanyName+"合计");
|
||||||
result.setPeopleNum(dataList.size());
|
result.setPeopleNum(dataList.size());
|
||||||
allList.add(result);
|
allList.add(result);
|
||||||
|
|
||||||
@ -292,10 +336,16 @@ public class RzSalaryDetailServiceImpl extends ServiceImpl<RzSalaryDetailMapper,
|
|||||||
hjResult.setPeopleNum(dataList.size());
|
hjResult.setPeopleNum(dataList.size());
|
||||||
List<SalaryVo> sortList = dataList.stream().sorted((x,y) -> {return x.getDeptName().compareTo(y.getDeptName()); }).collect(Collectors.toList());
|
List<SalaryVo> sortList = dataList.stream().sorted((x,y) -> {return x.getDeptName().compareTo(y.getDeptName()); }).collect(Collectors.toList());
|
||||||
sortList.add(hjResult);
|
sortList.add(hjResult);
|
||||||
companyLists.add(sortList);
|
List<SalaryVo> ewSalaryVoList = Collections.emptyList();
|
||||||
|
for (SalaryVo salaryVo : sortList){
|
||||||
|
SalaryVo allResult = new SalaryVo();
|
||||||
|
BeanUtils.copyProperties(salaryVo,allResult);
|
||||||
|
ewSalaryVoList.add(allResult);
|
||||||
|
}
|
||||||
|
companyLists.add(ewSalaryVoList);
|
||||||
}else{
|
}else{
|
||||||
SalaryVo result = sumSalaryVo(dataList);
|
SalaryVo result = sumSalaryVo(dataList);
|
||||||
result.setDeptName(sheetCompanyName+"总计");
|
result.setDeptName(sheetCompanyName+"合计");
|
||||||
result.setPeopleNum(dataList.size());
|
result.setPeopleNum(dataList.size());
|
||||||
allList.add(result);
|
allList.add(result);
|
||||||
|
|
||||||
@ -320,13 +370,18 @@ public class RzSalaryDetailServiceImpl extends ServiceImpl<RzSalaryDetailMapper,
|
|||||||
// allSheetNames.remove("河北伊特");
|
// allSheetNames.remove("河北伊特");
|
||||||
companyLists.addAll(deptLists);
|
companyLists.addAll(deptLists);
|
||||||
|
|
||||||
companyLists.stream().forEach(dataList
|
for (List<SalaryVo> dataList : companyLists){
|
||||||
->{
|
|
||||||
int x = 1;
|
int x = 1;
|
||||||
for (SalaryVo salaryVo : dataList){
|
for (SalaryVo salaryVo : dataList){
|
||||||
salaryVo.setSeqNo(x++);
|
salaryVo.setSeqNo(x++);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
// companyLists.stream().forEach(dataList ->{
|
||||||
|
// int x = 1;
|
||||||
|
// for (SalaryVo salaryVo : dataList){
|
||||||
|
// salaryVo.setSeqNo(x++);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
return util.exportExcel(allList,companyLists,"总表", allSheetNames, new SimpleDateFormat("yyyy-MM").format(rzSalaryDetail.getMonth())+"月工资", "制表: "+"审核: "+"经理签字: "+"总经理签字:");
|
return util.exportExcel(allList,companyLists,"总表", allSheetNames, new SimpleDateFormat("yyyy-MM").format(rzSalaryDetail.getMonth())+"月工资", "制表: "+"审核: "+"经理签字: "+"总经理签字:");
|
||||||
|
|
||||||
@ -335,24 +390,28 @@ public class RzSalaryDetailServiceImpl extends ServiceImpl<RzSalaryDetailMapper,
|
|||||||
private List<SalaryVo> buildExportData(RzSalaryDetail rzSalaryDetail) {
|
private List<SalaryVo> buildExportData(RzSalaryDetail rzSalaryDetail) {
|
||||||
// 获取所有部门列表
|
// 获取所有部门列表
|
||||||
List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>());
|
List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>());
|
||||||
|
Map<Long, String> deptNameMap = Collections.emptyMap(); //deptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
|
||||||
|
for (SysDept dept : deptList) {
|
||||||
|
deptNameMap.put(dept.getDeptId(), buildDept(dept.getDeptId(), deptList, deptNameMap));
|
||||||
|
}
|
||||||
//部门列表转换为部门ID到部门名称的映射
|
//部门列表转换为部门ID到部门名称的映射
|
||||||
Map<Long, String> deptNameMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
|
// Map<Long, String> deptNameMap = deptList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
|
||||||
//键为部门ID,值为部门名称,用于快速查找父部门为根部门(ID为0)的部门名称
|
//键为部门ID,值为部门名称,用于快速查找父部门为根部门(ID为0)的部门名称
|
||||||
Map<String, String> nameAndDeptIdMap = deptList.stream().filter(d -> d.getParentId().equals(0l)).collect(Collectors.toMap(d->String.valueOf(d.getDeptId()), SysDept::getDeptName));
|
Map<String, String> topDeptNameAndDeptIdMap = deptList.stream().filter(d -> d.getParentId().equals(0l)).collect(Collectors.toMap(d->String.valueOf(d.getDeptId()), SysDept::getDeptName));
|
||||||
Map<Long, String> companyNameMap = Collections.emptyMap();
|
Map<Long, String> companyNameMap = Collections.emptyMap();
|
||||||
// 过滤出所有非根部门(即parentId不等于0的部门),并为每个部门执行以下操作
|
// 过滤出所有非根部门(即parentId不等于0的部门),并为每个部门执行以下操作
|
||||||
deptList.stream().filter(d -> !d.getParentId().equals(0l)).forEach(d ->{
|
deptList.stream().filter(d -> !d.getParentId().equals(0l)).forEach(d ->{
|
||||||
// 将当前部门的祖ID字符串拆分成List以便后续处理
|
// 将当前部门的祖ID字符串拆分成List以便后续处理
|
||||||
List<String> parentIdList = Collections.asList(d.getAncestors().split(","));
|
List<String> parentIdList = Collections.asList(d.getAncestors().split(","));
|
||||||
Iterator<String> it = nameAndDeptIdMap.keySet().iterator();
|
Iterator<String> it = topDeptNameAndDeptIdMap.keySet().iterator();
|
||||||
while (it.hasNext()){
|
while (it.hasNext()){
|
||||||
String pid = it.next();
|
String pid = it.next();
|
||||||
if(parentIdList.contains(pid)){
|
if(parentIdList.contains(pid)){
|
||||||
companyNameMap.put(d.getDeptId(), nameAndDeptIdMap.get(pid));
|
companyNameMap.put(d.getDeptId(), topDeptNameAndDeptIdMap.get(pid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
nameAndDeptIdMap.entrySet().stream().forEach(d->{
|
topDeptNameAndDeptIdMap.entrySet().stream().forEach(d->{
|
||||||
companyNameMap.put(Long.valueOf(d.getKey()), d.getValue());
|
companyNameMap.put(Long.valueOf(d.getKey()), d.getValue());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -377,6 +436,21 @@ public class RzSalaryDetailServiceImpl extends ServiceImpl<RzSalaryDetailMapper,
|
|||||||
return voResult;
|
return voResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String buildDept(Long deptId, List<SysDept> deptList, Map<Long,String> showDeptNameMap){
|
||||||
|
if(showDeptNameMap.containsKey(deptList)){
|
||||||
|
return showDeptNameMap.get(deptId);
|
||||||
|
}
|
||||||
|
SysDept sysDept = deptList.stream().filter(d -> d.getDeptId().equals(deptId)).findFirst().orElse(null);
|
||||||
|
if(sysDept != null){
|
||||||
|
if("1".equals(sysDept.getIsShowFinancial())){
|
||||||
|
return sysDept.getDeptName();
|
||||||
|
}else{
|
||||||
|
return buildDept(sysDept.getParentId(), deptList, showDeptNameMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private List<RzSalaryDetail> selectRzSalaryDetaiList(RzSalaryDetail rzSalaryDetail) {
|
private List<RzSalaryDetail> selectRzSalaryDetaiList(RzSalaryDetail rzSalaryDetail) {
|
||||||
return getBaseMapper().selectRzSalaryDetailList(rzSalaryDetail);
|
return getBaseMapper().selectRzSalaryDetailList(rzSalaryDetail);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,17 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.evo.common.constant.Constants;
|
import com.evo.common.constant.Constants;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
|
import com.evo.common.utils.Collections;
|
||||||
import com.evo.common.utils.DateUtils;
|
import com.evo.common.utils.DateUtils;
|
||||||
import com.evo.common.utils.SecurityUtils;
|
import com.evo.common.utils.SecurityUtils;
|
||||||
|
import com.evo.common.utils.StringUtils;
|
||||||
import com.evo.finance.domain.RzSalaryDetail;
|
import com.evo.finance.domain.RzSalaryDetail;
|
||||||
import com.evo.finance.mapper.RzSalaryDetailMapper;
|
import com.evo.finance.mapper.RzSalaryDetailMapper;
|
||||||
import com.evo.system.domain.SysStaffDetail;
|
import com.evo.system.domain.SysStaffDetail;
|
||||||
@ -64,38 +69,53 @@ public class RzSalaryStatisticsServiceImpl extends ServiceImpl<RzSalaryStatistic
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public AjaxResult deleteRzSalaryStatisticsById(Long id)
|
public AjaxResult deleteRzSalaryStatisticsById(Long id){
|
||||||
{
|
|
||||||
RzSalaryStatistics rzSalaryStatistics = rzSalaryStatisticsMapper.selectRzSalaryStatisticsById(id);
|
RzSalaryStatistics rzSalaryStatistics = rzSalaryStatisticsMapper.selectRzSalaryStatisticsById(id);
|
||||||
//根据月份查询员工的工资统计
|
//根据月份直接物理删除
|
||||||
List<RzSalaryDetail> gz_list = rzSalaryDetailMapper.selectRzSalaryDetailByMonth(rzSalaryStatistics.getMonth());
|
rzSalaryDetailMapper.deleteRzSalaryDetailByMonth(rzSalaryStatistics.getMonth());
|
||||||
for (RzSalaryDetail rzSalaryDetail : gz_list) {
|
rzSalaryStatisticsMapper.deleteById(rzSalaryStatistics);
|
||||||
//根据员工ID查询员工详情,修改员工详情
|
// if(rzSalaryDetailMapper.deleteRzSalaryDetailByMonth(rzSalaryStatistics.getMonth()) < 1 || rzSalaryStatisticsMapper.deleteById(rzSalaryStatistics)< 1){
|
||||||
SysStaffDetail sysStaffDetail = sysStaffDetailMapper.selectSysStaffDetailByStaffId(rzSalaryDetail.getStaffId());
|
// return AjaxResult.error();
|
||||||
//修改个人详情
|
// }
|
||||||
sysStaffDetail.setAggregatePersonalIncomeTax(sysStaffDetail.getAggregatePersonalIncomeTax().subtract(rzSalaryDetail.getTaxPayable()));
|
|
||||||
sysStaffDetail.setSpecialDeduction(sysStaffDetail.getSpecialDeduction().subtract(sysStaffDetail.getSpecialDeduction().subtract(rzSalaryDetail.getSpecialDeduction())));
|
|
||||||
sysStaffDetail.setTotalWages(sysStaffDetail.getTotalWages().subtract(rzSalaryDetail.getSalaryBeforeTax()));
|
|
||||||
int i = sysStaffDetailMapper.updateSysStaffDetail(sysStaffDetail);
|
|
||||||
if(i < 1){
|
|
||||||
return AjaxResult.error();
|
|
||||||
}
|
|
||||||
//删除个人员工工资详情
|
|
||||||
rzSalaryDetail.setDelFlag(Constants.DELETE_FLAG_1);
|
|
||||||
rzSalaryDetail.setUpdateBy(SecurityUtils.getUsername());
|
|
||||||
rzSalaryDetail.setUpdateTime(DateUtils.getNowDate());
|
|
||||||
i = rzSalaryDetailMapper.updateRzSalaryDetail(rzSalaryDetail);
|
|
||||||
if(i < 1){
|
|
||||||
return AjaxResult.error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rzSalaryStatistics.setDelFlag(Constants.DELETE_FLAG_1);
|
|
||||||
rzSalaryStatistics.setUpdateTime(DateUtils.getNowDate());
|
|
||||||
rzSalaryStatistics.setUpdateBy(SecurityUtils.getUsername());
|
|
||||||
int p = rzSalaryStatisticsMapper.updateRzSalaryStatistics(rzSalaryStatistics);
|
|
||||||
if(p< 1){
|
|
||||||
return AjaxResult.error();
|
|
||||||
}
|
|
||||||
return AjaxResult.success();
|
return AjaxResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AjaxResult confirmRzSalaryStatisticsById(Long id) {
|
||||||
|
RzSalaryStatistics rzSalaryStatistics = rzSalaryStatisticsMapper.selectById(id);
|
||||||
|
if(rzSalaryStatistics == null){
|
||||||
|
return AjaxResult.error("未找到统计信息");
|
||||||
|
}
|
||||||
|
if("已确认".equals(rzSalaryStatistics.getStatus())){
|
||||||
|
return AjaxResult.error("当前信息已确认发放");
|
||||||
|
}
|
||||||
|
if(StringUtils.isEmpty(rzSalaryStatistics.getSalaryInfo())){
|
||||||
|
return AjaxResult.error("未找到当前月份的薪资详情");
|
||||||
|
}
|
||||||
|
List<Long> detailIds = Collections.emptyList();
|
||||||
|
JSONArray jsonArray = JSON.parseArray(rzSalaryStatistics.getSalaryInfo());
|
||||||
|
for (int i = 0; i <jsonArray.size(); i++) {
|
||||||
|
JSONObject jb = jsonArray.getJSONObject(i);
|
||||||
|
if(jb != null){
|
||||||
|
SysStaffDetail detail = sysStaffDetailMapper.selectSysStaffDetailById(jb.getLong("detailId"));
|
||||||
|
if(detail != null){
|
||||||
|
detail.setAggregatePersonalIncomeTax(jb.getBigDecimal("aggregatePersonalIncomeTax"));
|
||||||
|
detail.setSpecialDeduction(jb.getBigDecimal("specialDeduction"));
|
||||||
|
detail.setTotalWages(jb.getBigDecimal("totalWages"));
|
||||||
|
sysStaffDetailMapper.updateById(detail);
|
||||||
|
}else{
|
||||||
|
detailIds.add(jb.getLong("detailId"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Collections.isNotEmpty(detailIds)){
|
||||||
|
return AjaxResult.error("部分员工详情未找到: 未找到的员工详情Id为: " + String.format(",", detailIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
rzSalaryStatistics.setStatus("已确认");
|
||||||
|
rzSalaryStatisticsMapper.updateById(rzSalaryStatistics);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,6 +119,8 @@ public class SecurityConfig
|
|||||||
.antMatchers("/wechat/**").permitAll()
|
.antMatchers("/wechat/**").permitAll()
|
||||||
.antMatchers("/websocket/**").permitAll()
|
.antMatchers("/websocket/**").permitAll()
|
||||||
.antMatchers("/test/**").permitAll()
|
.antMatchers("/test/**").permitAll()
|
||||||
|
.antMatchers("/system/staff/tree/getDingUserId").permitAll()
|
||||||
|
.antMatchers("/callback/**/**").permitAll()
|
||||||
.antMatchers("/api/v1/verify_user").permitAll()
|
.antMatchers("/api/v1/verify_user").permitAll()
|
||||||
.antMatchers("/api/v1/record/face").permitAll()
|
.antMatchers("/api/v1/record/face").permitAll()
|
||||||
.antMatchers("/api/v2/verify_user_yt").permitAll()
|
.antMatchers("/api/v2/verify_user_yt").permitAll()
|
||||||
|
|||||||
@ -49,7 +49,8 @@ public class RzLeaveDetail extends BaseEntity
|
|||||||
private String remarks;
|
private String remarks;
|
||||||
|
|
||||||
private String delFlag;
|
private String delFlag;
|
||||||
|
//钉钉审批id
|
||||||
|
private String processInstanceId;
|
||||||
/***
|
/***
|
||||||
* 扩展字段
|
* 扩展字段
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -29,6 +29,7 @@ public class RzOverTime extends BaseEntity
|
|||||||
/** 部门ID */
|
/** 部门ID */
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
@Excel(name = "部门")
|
@Excel(name = "部门")
|
||||||
|
@TableField(exist = false)
|
||||||
private String deptName;
|
private String deptName;
|
||||||
|
|
||||||
private Long userId;
|
private Long userId;
|
||||||
@ -46,6 +47,7 @@ public class RzOverTime extends BaseEntity
|
|||||||
@Excel(name = "加班总时长")
|
@Excel(name = "加班总时长")
|
||||||
private BigDecimal overHours;
|
private BigDecimal overHours;
|
||||||
@Excel(name = "调休总时长")
|
@Excel(name = "调休总时长")
|
||||||
|
@TableField(exist = false)
|
||||||
private BigDecimal taskHours;
|
private BigDecimal taskHours;
|
||||||
|
|
||||||
/** 删除标识 */
|
/** 删除标识 */
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.evo.personnelMatters.mapper;
|
package com.evo.personnelMatters.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeave;
|
||||||
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
@ -84,4 +85,5 @@ public interface RzLeaveDetailMapper extends BaseMapper<RzLeaveDetail>
|
|||||||
*/
|
*/
|
||||||
Long selectLeaveHourByUserIdAndDateAndType(@Param("userId") Long userId,@Param("date") Date date, @Param("type") Long type);
|
Long selectLeaveHourByUserIdAndDateAndType(@Param("userId") Long userId,@Param("date") Date date, @Param("type") Long type);
|
||||||
|
|
||||||
|
RzLeaveDetail selectRzLeaveDetailByProcessInstanceId(@Param("processInstanceId") String processInstanceId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,4 +51,10 @@ public interface RzLeaveMapper extends BaseMapper<RzLeave>
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RzLeave queryRzLeaveByDateAndUserId(@Param("userId") Long userId, @Param("date") Date date);
|
public RzLeave queryRzLeaveByDateAndUserId(@Param("userId") Long userId, @Param("date") Date date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据员工ID和时间查询请假统计
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public RzLeave queryRzLeaveByUserId(@Param("userId") Long userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.evo.personnelMatters.service;
|
package com.evo.personnelMatters.service;
|
||||||
|
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
|
import com.evo.personnelMatters.domain.RzLeave;
|
||||||
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
import com.evo.personnelMatters.domain.RzLeaveDetail;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -52,4 +53,6 @@ public interface IRzLeaveDetailService
|
|||||||
public AjaxResult deleteRzLeaveDetailById(Long id);
|
public AjaxResult deleteRzLeaveDetailById(Long id);
|
||||||
|
|
||||||
public RzLeaveDetail calculationLeaveHour(RzLeaveDetail rzLeaveDetail);
|
public RzLeaveDetail calculationLeaveHour(RzLeaveDetail rzLeaveDetail);
|
||||||
|
|
||||||
|
public RzLeaveDetail selectRzLeaveDetailByProcessInstanceId(String processInstanceId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,4 +59,12 @@ public interface IRzLeaveService
|
|||||||
public List<RzLeaveDetail> listLeaveDetails(RzLeave rzLeave);
|
public List<RzLeaveDetail> listLeaveDetails(RzLeave rzLeave);
|
||||||
|
|
||||||
List<RzLeave> selectRzLeaveListByDate(RzLeave rzLeave);
|
List<RzLeave> selectRzLeaveListByDate(RzLeave rzLeave);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据员工
|
||||||
|
*
|
||||||
|
* @param userId 员工id
|
||||||
|
* @return 请假管理
|
||||||
|
*/
|
||||||
|
public RzLeave selectRzLeaveByUserId(Long userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.evo.personnelMatters.service;
|
package com.evo.personnelMatters.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.personnelMatters.domain.RzOverTimeDetail;
|
import com.evo.personnelMatters.domain.RzOverTimeDetail;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ import java.util.List;
|
|||||||
* @author chenyj
|
* @author chenyj
|
||||||
* @date 2024-09-09
|
* @date 2024-09-09
|
||||||
*/
|
*/
|
||||||
public interface IRzOverTimeDetailService
|
public interface IRzOverTimeDetailService extends IService<RzOverTimeDetail>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 查询加班详情
|
* 查询加班详情
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
package com.evo.personnelMatters.service;
|
package com.evo.personnelMatters.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.personnelMatters.domain.RzOverTime;
|
import com.evo.personnelMatters.domain.RzOverTime;
|
||||||
import com.evo.personnelMatters.domain.RzOverTimeDetail;
|
import com.evo.personnelMatters.domain.RzOverTimeDetail;
|
||||||
|
import com.evo.system.domain.SysStaff;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,7 +16,7 @@ import java.util.List;
|
|||||||
* @author chenyj
|
* @author chenyj
|
||||||
* @date 2024-09-03
|
* @date 2024-09-03
|
||||||
*/
|
*/
|
||||||
public interface IRzOverTimeService
|
public interface IRzOverTimeService extends IService<RzOverTime>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 查询加班管理
|
* 查询加班管理
|
||||||
@ -60,4 +64,10 @@ public interface IRzOverTimeService
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public List<RzOverTimeDetail> selectRzOverTimeDetailListByUserIdAndMonth(RzOverTime rzOverTime);
|
public List<RzOverTimeDetail> selectRzOverTimeDetailListByUserIdAndMonth(RzOverTime rzOverTime);
|
||||||
|
|
||||||
|
public RzOverTime selectRzOverTimeByNameAndMonth(Long userId, Date overTimeMonth);
|
||||||
|
|
||||||
|
public String overTimeCard(SysStaff sysStaff, Date overTimeMonth);
|
||||||
|
|
||||||
|
public String overTimeOffDutyCard(SysStaff sysStaff , Date date, String sn);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,11 +89,11 @@ public class RzLeaveDetailServiceImpl extends ServiceImpl<RzLeaveDetailMapper, R
|
|||||||
//根据员工姓名查询
|
//根据员工姓名查询
|
||||||
RzLeave rzLeave = rzLeaveMapper.selectRzLeaveById(rzLeaveDetail.getLeaveId());
|
RzLeave rzLeave = rzLeaveMapper.selectRzLeaveById(rzLeaveDetail.getLeaveId());
|
||||||
//验证调休
|
//验证调休
|
||||||
if(Long.valueOf(55).equals(rzLeaveDetail.getType())){
|
// if(Long.valueOf(55).equals(rzLeaveDetail.getType())){
|
||||||
if(!autoLeavedNumber(rzLeave.getUserId(),rzLeaveDetail.getLeaveStartTime(),rzLeaveDetail.getLeaveHour())){
|
// if(!autoLeavedNumber(rzLeave.getUserId(),rzLeaveDetail.getLeaveStartTime(),rzLeaveDetail.getLeaveHour())){
|
||||||
return AjaxResult.error("当前人员的加班时长不足抵扣调休时长!!");
|
// return AjaxResult.error("当前人员的加班时长不足抵扣调休时长!!");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
rzLeaveDetail.setDelFlag(Constants.DELETE_FLAG_0);
|
rzLeaveDetail.setDelFlag(Constants.DELETE_FLAG_0);
|
||||||
if(getBaseMapper().insert(rzLeaveDetail) < 1){
|
if(getBaseMapper().insert(rzLeaveDetail) < 1){
|
||||||
return AjaxResult.error("请假详情新增失败");
|
return AjaxResult.error("请假详情新增失败");
|
||||||
@ -335,6 +335,7 @@ public class RzLeaveDetailServiceImpl extends ServiceImpl<RzLeaveDetailMapper, R
|
|||||||
beginDate = DateUtils.addDays(beginDate,-1);
|
beginDate = DateUtils.addDays(beginDate,-1);
|
||||||
//记录最终需要增加多少天
|
//记录最终需要增加多少天
|
||||||
Integer endDays = 0;
|
Integer endDays = 0;
|
||||||
|
Integer wordDays = holidayDates.size();
|
||||||
//请假类型及不包含法休, 也不包含公休
|
//请假类型及不包含法休, 也不包含公休
|
||||||
if(ParamUtils.getLeaveTypeNotIncludedFaXiuAndPublicHoliday().contains(flag)){
|
if(ParamUtils.getLeaveTypeNotIncludedFaXiuAndPublicHoliday().contains(flag)){
|
||||||
//获取结果当中的假期时间
|
//获取结果当中的假期时间
|
||||||
@ -344,6 +345,7 @@ public class RzLeaveDetailServiceImpl extends ServiceImpl<RzLeaveDetailMapper, R
|
|||||||
rzLeaveDetail.setRemarks("不包含法定假日和周末");
|
rzLeaveDetail.setRemarks("不包含法定假日和周末");
|
||||||
}
|
}
|
||||||
endDays = new BigDecimal(endDays).add(new BigDecimal(holidays.size())).intValue();
|
endDays = new BigDecimal(endDays).add(new BigDecimal(holidays.size())).intValue();
|
||||||
|
wordDays = endDays;
|
||||||
}
|
}
|
||||||
}else
|
}else
|
||||||
//请假类型不包含法休
|
//请假类型不包含法休
|
||||||
@ -355,10 +357,16 @@ public class RzLeaveDetailServiceImpl extends ServiceImpl<RzLeaveDetailMapper, R
|
|||||||
rzLeaveDetail.setRemarks("不包含法定假日");
|
rzLeaveDetail.setRemarks("不包含法定假日");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//因为包含公休, 所以需要剔除公休时长
|
||||||
|
for (String year : yearList){
|
||||||
|
List<String> holidays = Collections.findDuplicatesList(ParamUtils.getHoliddayList(Integer.valueOf(year), 2), holidayDates);
|
||||||
|
//现有工作时长, 需要减去公休时长
|
||||||
|
wordDays = new BigDecimal(wordDays).subtract(new BigDecimal(holidays.size())).intValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//计算结束时间和请假时长 此处使用beginDate 而不使用rzLeaveDetail.getLeaveStartTime() 的原因是, 上面获取全部请假日期的时候, 已经处理过时间, 只需要增加公休,法休时间就可以了
|
//计算结束时间和请假时长 此处使用beginDate 而不使用rzLeaveDetail.getLeaveStartTime() 的原因是, 上面获取全部请假日期的时候, 已经处理过时间, 只需要增加公休,法休时间就可以了
|
||||||
rzLeaveDetail.setLeaveEndTime(DateUtils.addDays(beginDate, endDays));
|
rzLeaveDetail.setLeaveEndTime(DateUtils.addDays(beginDate, endDays));
|
||||||
rzLeaveDetail.setLeaveHour(new BigDecimal(sysDictData.getDictValue()).multiply(Constants.DAY_WORK_HOUR).intValue());
|
rzLeaveDetail.setLeaveHour(new BigDecimal(wordDays).multiply(Constants.DAY_WORK_HOUR).intValue());
|
||||||
}else{
|
}else{
|
||||||
rzLeaveDetail = leaveHour(rzLeaveDetail);
|
rzLeaveDetail = leaveHour(rzLeaveDetail);
|
||||||
// //不需要计算, 过滤节假日啥的, 只过滤周末就好了
|
// //不需要计算, 过滤节假日啥的, 只过滤周末就好了
|
||||||
@ -394,6 +402,11 @@ public class RzLeaveDetailServiceImpl extends ServiceImpl<RzLeaveDetailMapper, R
|
|||||||
return rzLeaveDetail;
|
return rzLeaveDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzLeaveDetail selectRzLeaveDetailByProcessInstanceId(String processInstanceId) {
|
||||||
|
return getBaseMapper().selectRzLeaveDetailByProcessInstanceId(processInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
public RzLeaveDetail leaveHour(RzLeaveDetail rzLeaveDetail) {
|
public RzLeaveDetail leaveHour(RzLeaveDetail rzLeaveDetail) {
|
||||||
if(rzLeaveDetail.getType() == null || rzLeaveDetail.getLeaveStartTime() == null){
|
if(rzLeaveDetail.getType() == null || rzLeaveDetail.getLeaveStartTime() == null){
|
||||||
return rzLeaveDetail;
|
return rzLeaveDetail;
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.evo.personnelMatters.service.impl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.evo.common.annotation.DataScope;
|
import com.evo.common.annotation.DataScope;
|
||||||
import com.evo.common.constant.Constants;
|
import com.evo.common.constant.Constants;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
@ -29,7 +30,7 @@ import java.util.List;
|
|||||||
* @date 2024-08-03
|
* @date 2024-08-03
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class RzLeaveServiceImpl implements IRzLeaveService
|
public class RzLeaveServiceImpl extends ServiceImpl<RzLeaveMapper, RzLeave> implements IRzLeaveService
|
||||||
{
|
{
|
||||||
@Resource
|
@Resource
|
||||||
private RzLeaveMapper rzLeaveMapper;
|
private RzLeaveMapper rzLeaveMapper;
|
||||||
@ -160,4 +161,9 @@ public class RzLeaveServiceImpl implements IRzLeaveService
|
|||||||
wa.like(StringUtils.isNotBlank(rzLeave.getDeptName()),RzLeave::getDeptName,rzLeave.getDeptName());
|
wa.like(StringUtils.isNotBlank(rzLeave.getDeptName()),RzLeave::getDeptName,rzLeave.getDeptName());
|
||||||
return rzLeaveMapper.selectList(wa);
|
return rzLeaveMapper.selectList(wa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzLeave selectRzLeaveByUserId(Long userId) {
|
||||||
|
return getBaseMapper().queryRzLeaveByUserId(userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.evo.personnelMatters.service.impl;
|
package com.evo.personnelMatters.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.evo.attendance.domain.RzAttendance;
|
import com.evo.attendance.domain.RzAttendance;
|
||||||
import com.evo.attendance.domain.RzAttendanceDetail;
|
import com.evo.attendance.domain.RzAttendanceDetail;
|
||||||
import com.evo.attendance.mapper.RzAttendanceDetailMapper;
|
import com.evo.attendance.mapper.RzAttendanceDetailMapper;
|
||||||
@ -34,7 +35,7 @@ import java.util.List;
|
|||||||
* @date 2024-09-09
|
* @date 2024-09-09
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class RzOverTimeDetailServiceImpl implements IRzOverTimeDetailService
|
public class RzOverTimeDetailServiceImpl extends ServiceImpl<RzOverTimeDetailMapper, RzOverTimeDetail> implements IRzOverTimeDetailService
|
||||||
{
|
{
|
||||||
@Resource
|
@Resource
|
||||||
private RzOverTimeDetailMapper rzOverTimeDetailMapper;
|
private RzOverTimeDetailMapper rzOverTimeDetailMapper;
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
package com.evo.personnelMatters.service.impl;
|
package com.evo.personnelMatters.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.evo.attendance.processor.KqUtils;
|
||||||
|
import com.evo.attendance.processor.PunchTheClockStrategyExchangeProcessor;
|
||||||
import com.evo.common.annotation.DataScope;
|
import com.evo.common.annotation.DataScope;
|
||||||
import com.evo.common.constant.Constants;
|
import com.evo.common.constant.Constants;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
|
import com.evo.common.utils.DataUtils;
|
||||||
import com.evo.common.utils.DateUtils;
|
import com.evo.common.utils.DateUtils;
|
||||||
import com.evo.common.utils.SecurityUtils;
|
import com.evo.common.utils.SecurityUtils;
|
||||||
import com.evo.common.utils.StringUtils;
|
import com.evo.common.utils.StringUtils;
|
||||||
@ -15,10 +18,12 @@ import com.evo.personnelMatters.service.IRzOverTimeService;
|
|||||||
import com.evo.system.domain.SysStaff;
|
import com.evo.system.domain.SysStaff;
|
||||||
import com.evo.system.mapper.SysDeptMapper;
|
import com.evo.system.mapper.SysDeptMapper;
|
||||||
import com.evo.system.mapper.SysStaffMapper;
|
import com.evo.system.mapper.SysStaffMapper;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,5 +156,77 @@ public class RzOverTimeServiceImpl extends ServiceImpl<RzOverTimeMapper, RzOverT
|
|||||||
return res_list;
|
return res_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RzOverTime selectRzOverTimeByNameAndMonth(Long userId, Date overTimeMonth) {
|
||||||
|
return getBaseMapper().selectRzOverTimeByNameAndMonth(userId, overTimeMonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String overTimeCard(SysStaff sysStaff, Date overTimeMonth) {
|
||||||
|
//判断打卡月是否统计过加班
|
||||||
|
RzOverTime rzOverTime = getBaseMapper().selectRzOverTimeByNameAndMonth(sysStaff.getUserId(),overTimeMonth);
|
||||||
|
if(rzOverTime == null){
|
||||||
|
rzOverTime = new RzOverTime();
|
||||||
|
rzOverTime.setUserId(sysStaff.getUserId());
|
||||||
|
rzOverTime.setOverHours(new BigDecimal("0.0"));
|
||||||
|
rzOverTime.setDeptId(sysStaff.getDeptId());
|
||||||
|
rzOverTime.setName(sysStaff.getName());
|
||||||
|
rzOverTime.setOverTimeMonth(overTimeMonth);
|
||||||
|
if(getBaseMapper().insert(rzOverTime) < 1){
|
||||||
|
return PunchTheClockStrategyExchangeProcessor.initStaticMessage(1, "打卡失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RzOverTimeDetail rzOverTimeDetail = new RzOverTimeDetail();
|
||||||
|
rzOverTimeDetail.setOverTimeId(rzOverTime.getId());
|
||||||
|
rzOverTimeDetail.setOverTimeStart(overTimeMonth);
|
||||||
|
rzOverTimeDetail.setName(sysStaff.getName());
|
||||||
|
rzOverTimeDetail.setDelFlag(Constants.DELETE_FLAG_0);
|
||||||
|
rzOverTimeDetail.setCreateBy("admin");
|
||||||
|
rzOverTimeDetail.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return (rzOverTimeDetailMapper.insert(rzOverTimeDetail) < 1) ? PunchTheClockStrategyExchangeProcessor.initStaticMessage(1, "打卡失败") : PunchTheClockStrategyExchangeProcessor.initStaticMessage(0, "打卡成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String overTimeOffDutyCard(SysStaff sysStaff, Date date, String sn) {
|
||||||
|
//修改加班打卡记录 根据员工ID和时间查找 统计数据
|
||||||
|
RzOverTime rzOverTime = getBaseMapper().selectRzOverTimeByNameAndMonth(sysStaff.getUserId(),date);
|
||||||
|
//如果没有加班汇总, 生成一条新的
|
||||||
|
if(ObjectUtils.isEmpty(rzOverTime)){
|
||||||
|
rzOverTime = new RzOverTime();
|
||||||
|
rzOverTime.setUserId(sysStaff.getUserId());
|
||||||
|
rzOverTime.setDeptId(sysStaff.getDeptId());
|
||||||
|
rzOverTime.setName(sysStaff.getName());
|
||||||
|
rzOverTime.setOverTimeMonth(date);
|
||||||
|
rzOverTime.setOverHours(DataUtils.DEFAULT_VALUE);
|
||||||
|
rzOverTime.setDelFlag(Constants.DELETE_FLAG_0);
|
||||||
|
rzOverTime.setCreateBy("admin");
|
||||||
|
rzOverTime.setCreateTime(new Date());
|
||||||
|
getBaseMapper().insert(rzOverTime);
|
||||||
|
}
|
||||||
|
//查找加班详情 加班统计ID和加班开始时间
|
||||||
|
RzOverTimeDetail rzOverTimeDetail = rzOverTimeDetailMapper.queryRzOverTimeDetailByDateAndOverId(rzOverTime.getId(),date);
|
||||||
|
if(ObjectUtils.isEmpty(rzOverTimeDetail)){
|
||||||
|
//特殊情况, 会存在过12点的情况, 这时候需要核查下前一天没有下班的加班数据
|
||||||
|
rzOverTimeDetail = rzOverTimeDetailMapper.queryRzOverTimeDetailByDateAndOverIdAndOverTimeEndIsNull(rzOverTime.getId(), DateUtils.addDays(date,-1));
|
||||||
|
//如果前一天也为空
|
||||||
|
if(ObjectUtils.isEmpty(rzOverTimeDetail)){
|
||||||
|
return PunchTheClockStrategyExchangeProcessor.initStaticMessage(1, "未找到当天的加班信息, 请补卡");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rzOverTimeDetail.setOverTimeEnd(date);
|
||||||
|
//计算加班时长 分钟
|
||||||
|
KqUtils.calculateOverTimeHours(rzOverTimeDetail, sysStaff.getUserId(), sn);
|
||||||
|
|
||||||
|
if(rzOverTimeDetailMapper.updateRzOverTimeDetail(rzOverTimeDetail) < 1){
|
||||||
|
return PunchTheClockStrategyExchangeProcessor.initStaticMessage(1, "打卡失败");
|
||||||
|
}
|
||||||
|
//加班修改统计
|
||||||
|
rzOverTime.setOverHours(rzOverTime.getOverHours().add(rzOverTimeDetail.getOverTimeHours()));
|
||||||
|
if(getBaseMapper().updateRzOverTime(rzOverTime) < 1){
|
||||||
|
return PunchTheClockStrategyExchangeProcessor.initStaticMessage(1, "打卡失败");
|
||||||
|
}
|
||||||
|
return PunchTheClockStrategyExchangeProcessor.initStaticMessage(0, "打卡成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -41,9 +42,9 @@ import java.util.List;
|
|||||||
@RequestMapping("/api/v2")
|
@RequestMapping("/api/v2")
|
||||||
public class RzRestaurantDetailController extends BaseController
|
public class RzRestaurantDetailController extends BaseController
|
||||||
{
|
{
|
||||||
@Autowired
|
@Resource
|
||||||
private IRzRestaurantDetailService rzRestaurantDetailService;
|
private IRzRestaurantDetailService rzRestaurantDetailService;
|
||||||
@Autowired
|
@Resource
|
||||||
private ISysStaffService sysStaffService;
|
private ISysStaffService sysStaffService;
|
||||||
/**
|
/**
|
||||||
* 查询餐饮详情列表
|
* 查询餐饮详情列表
|
||||||
@ -89,7 +90,7 @@ public class RzRestaurantDetailController extends BaseController
|
|||||||
*/
|
*/
|
||||||
@RequestMapping("/verify_user_yt")
|
@RequestMapping("/verify_user_yt")
|
||||||
public String verifyUser(@RequestBody String json){
|
public String verifyUser(@RequestBody String json){
|
||||||
return "接口停止使用";//rzRestaurantDetailService.insertRzRestaurantDetail(json);
|
return rzRestaurantDetailService.insertRzRestaurantDetail(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -54,6 +54,8 @@ public class RzRestaurantDetail extends BaseEntity
|
|||||||
/** 删除标记 */
|
/** 删除标记 */
|
||||||
private String delFlag;
|
private String delFlag;
|
||||||
|
|
||||||
|
private String deviceSn;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@ -83,7 +83,6 @@ public class RzRestaurantDetailServiceImpl extends ServiceImpl<RzRestaurantDetai
|
|||||||
@Override
|
@Override
|
||||||
public String insertRzRestaurantDetail(String json)
|
public String insertRzRestaurantDetail(String json)
|
||||||
{
|
{
|
||||||
System.out.println(json.toString());
|
|
||||||
//需要返回的对象
|
//需要返回的对象
|
||||||
RestaurantVo cfiv = new RestaurantVo();
|
RestaurantVo cfiv = new RestaurantVo();
|
||||||
RestaurantData cfd = new RestaurantData();
|
RestaurantData cfd = new RestaurantData();
|
||||||
@ -98,7 +97,6 @@ public class RzRestaurantDetailServiceImpl extends ServiceImpl<RzRestaurantDetai
|
|||||||
if(!ParamUtils.getCanteenOpenHour().contains(hour)){
|
if(!ParamUtils.getCanteenOpenHour().contains(hour)){
|
||||||
cfiv.setResult(2);
|
cfiv.setResult(2);
|
||||||
cfiv.setMsg("不在打卡时间内");
|
cfiv.setMsg("不在打卡时间内");
|
||||||
System.out.println(JSONObject.toJSONString(cfiv));
|
|
||||||
return JSONObject.toJSONString(cfiv);
|
return JSONObject.toJSONString(cfiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +130,7 @@ public class RzRestaurantDetailServiceImpl extends ServiceImpl<RzRestaurantDetai
|
|||||||
RzRestaurantStatistics restaurantStatistics = rzRestaurantStatisticsMapper.selectRzRestaurantStatisticsByUserIdAndDate(Long.valueOf(userId),new Date());
|
RzRestaurantStatistics restaurantStatistics = rzRestaurantStatisticsMapper.selectRzRestaurantStatisticsByUserIdAndDate(Long.valueOf(userId),new Date());
|
||||||
//增加打卡记录
|
//增加打卡记录
|
||||||
RzRestaurantDetail cyFaceInfo = new RzRestaurantDetail();
|
RzRestaurantDetail cyFaceInfo = new RzRestaurantDetail();
|
||||||
|
cyFaceInfo.setDeviceSn(jsonObject.getString("sn"));
|
||||||
cyFaceInfo.setDate(new Date());
|
cyFaceInfo.setDate(new Date());
|
||||||
cyFaceInfo.setStaffId(restaurantStatistics.getStaffId());
|
cyFaceInfo.setStaffId(restaurantStatistics.getStaffId());
|
||||||
cyFaceInfo.setName(restaurantStatistics.getName());
|
cyFaceInfo.setName(restaurantStatistics.getName());
|
||||||
|
|||||||
@ -5,10 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.evo.common.constant.Constants;
|
import com.evo.common.constant.Constants;
|
||||||
import com.evo.common.core.domain.AjaxResult;
|
import com.evo.common.core.domain.AjaxResult;
|
||||||
import com.evo.common.core.domain.entity.RzUpload;
|
import com.evo.common.core.domain.entity.RzUpload;
|
||||||
import com.evo.common.utils.Collections;
|
import com.evo.common.utils.*;
|
||||||
import com.evo.common.utils.DateUtils;
|
|
||||||
import com.evo.common.utils.SecurityUtils;
|
|
||||||
import com.evo.common.utils.StringUtils;
|
|
||||||
import com.evo.common.utils.file.FileUploadUtils;
|
import com.evo.common.utils.file.FileUploadUtils;
|
||||||
import com.evo.equipment.domain.vo.StaffData;
|
import com.evo.equipment.domain.vo.StaffData;
|
||||||
import com.evo.equipment.domain.vo.StaffDto;
|
import com.evo.equipment.domain.vo.StaffDto;
|
||||||
@ -22,6 +19,7 @@ import com.evo.restaurant.service.IRzRestaurantImagesService;
|
|||||||
import com.evo.restaurant.service.IRzRestaurantStatisticsService;
|
import com.evo.restaurant.service.IRzRestaurantStatisticsService;
|
||||||
import com.evo.system.service.RzUploadService;
|
import com.evo.system.service.RzUploadService;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@ -45,6 +43,9 @@ public class RzRestaurantImagesServiceImpl extends ServiceImpl<RzRestaurantImage
|
|||||||
private IEqSnDetailService eqSnDetailService;//餐饮统计
|
private IEqSnDetailService eqSnDetailService;//餐饮统计
|
||||||
@Resource
|
@Resource
|
||||||
private RzUploadService rzUploadService;//文件上传
|
private RzUploadService rzUploadService;//文件上传
|
||||||
|
@Autowired
|
||||||
|
private ParamUtils paramUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询餐饮照片管理列表
|
* 查询餐饮照片管理列表
|
||||||
*
|
*
|
||||||
@ -68,8 +69,7 @@ public class RzRestaurantImagesServiceImpl extends ServiceImpl<RzRestaurantImage
|
|||||||
{
|
{
|
||||||
//根据id查询信息
|
//根据id查询信息
|
||||||
RzRestaurantImages rzRestaurantImages = getBaseMapper().selectRzRestaurantImagesById(id);
|
RzRestaurantImages rzRestaurantImages = getBaseMapper().selectRzRestaurantImagesById(id);
|
||||||
//删除打卡机照片
|
|
||||||
String message = "";
|
|
||||||
//需要返回的对象
|
//需要返回的对象
|
||||||
StaffDto cau = new StaffDto();
|
StaffDto cau = new StaffDto();
|
||||||
//发送的数据
|
//发送的数据
|
||||||
@ -78,8 +78,6 @@ public class RzRestaurantImagesServiceImpl extends ServiceImpl<RzRestaurantImage
|
|||||||
cau.setCmd("to_device");
|
cau.setCmd("to_device");
|
||||||
//无用值,空串
|
//无用值,空串
|
||||||
cau.setForm("");
|
cau.setForm("");
|
||||||
//设备号
|
|
||||||
cau.setTo(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE);
|
|
||||||
//给服务端预留的补充字段,设备端不处理这个字段内容。设备在响应这条指令时原样返回
|
//给服务端预留的补充字段,设备端不处理这个字段内容。设备在响应这条指令时原样返回
|
||||||
cau.setExtra("");
|
cau.setExtra("");
|
||||||
//发送的数据
|
//发送的数据
|
||||||
@ -88,7 +86,12 @@ public class RzRestaurantImagesServiceImpl extends ServiceImpl<RzRestaurantImage
|
|||||||
caud.setUser_id(id+"");
|
caud.setUser_id(id+"");
|
||||||
cau.setData(caud);
|
cau.setData(caud);
|
||||||
//调用websocket,推送给设备
|
//调用websocket,推送给设备
|
||||||
|
ParamUtils.getRestaurantDevSn().stream().forEach(deviceNo ->{
|
||||||
|
//设备号 com.evo.equipment.constant.Constants.EQ_DEVICE_CODE
|
||||||
|
cau.setTo(deviceNo);
|
||||||
WebSocketUsers.sendMessageToUsersByText(JSONObject.toJSONString(cau));
|
WebSocketUsers.sendMessageToUsersByText(JSONObject.toJSONString(cau));
|
||||||
|
});
|
||||||
|
|
||||||
//删除照片
|
//删除照片
|
||||||
String img_name = rzRestaurantImages.getImageUrl().substring(rzRestaurantImages.getImageUrl().lastIndexOf("/")+1);
|
String img_name = rzRestaurantImages.getImageUrl().substring(rzRestaurantImages.getImageUrl().lastIndexOf("/")+1);
|
||||||
File file = new File(com.evo.equipment.constant.Constants.STAFF_IMAGE_ADDRESS + img_name);
|
File file = new File(com.evo.equipment.constant.Constants.STAFF_IMAGE_ADDRESS + img_name);
|
||||||
@ -134,7 +137,7 @@ public class RzRestaurantImagesServiceImpl extends ServiceImpl<RzRestaurantImage
|
|||||||
log.error("处理上传照片信息出现错误", e);
|
log.error("处理上传照片信息出现错误", e);
|
||||||
}
|
}
|
||||||
//下发照片
|
//下发照片
|
||||||
eqSnDetailService.sendPhoto(Collections.asList(com.evo.equipment.constant.Constants.EQ_DEVICE_CODE),
|
eqSnDetailService.sendPhoto(Collections.asList(ParamUtils.getRestaurantDevSn()),
|
||||||
Collections.asList(Collections.asMap("userId", String.valueOf(rzRestaurantImages.getId()),
|
Collections.asList(Collections.asMap("userId", String.valueOf(rzRestaurantImages.getId()),
|
||||||
"name", rzRestaurantImages.getName(), "photoUrl", rzRestaurantImages.getImageUrl())));
|
"name", rzRestaurantImages.getName(), "photoUrl", rzRestaurantImages.getImageUrl())));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -244,7 +244,9 @@ public class RzRestaurantStatisticsServiceImpl extends ServiceImpl<RzRestaurantS
|
|||||||
private void create(Long staffId, Long deptId, String name, Date date){
|
private void create(Long staffId, Long deptId, String name, Date date){
|
||||||
RzRestaurantStatistics rzRestaurantStatistics = getBaseMapper().selectRzRestaurantStatisticsByUserIdAndDate(staffId,date);
|
RzRestaurantStatistics rzRestaurantStatistics = getBaseMapper().selectRzRestaurantStatisticsByUserIdAndDate(staffId,date);
|
||||||
if(StringUtils.isNotNull(rzRestaurantStatistics)){
|
if(StringUtils.isNotNull(rzRestaurantStatistics)){
|
||||||
|
if(rzRestaurantStatistics.getDeptId() == null){
|
||||||
rzRestaurantStatistics.setDeptId(deptId);
|
rzRestaurantStatistics.setDeptId(deptId);
|
||||||
|
}
|
||||||
rzRestaurantStatistics.setName(name);
|
rzRestaurantStatistics.setName(name);
|
||||||
getBaseMapper().updateRzRestaurantStatistics(rzRestaurantStatistics);
|
getBaseMapper().updateRzRestaurantStatistics(rzRestaurantStatistics);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.evo.system.controller;
|
||||||
|
|
||||||
|
import com.evo.common.core.controller.BaseController;
|
||||||
|
import com.evo.common.core.page.TableDataInfo;
|
||||||
|
import com.evo.ding.domain.DingShift;
|
||||||
|
import com.evo.ding.domain.DingShiftGroup;
|
||||||
|
import com.evo.ding.service.DingShiftGroupService;
|
||||||
|
import com.evo.ding.service.DingShiftService;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShiftController
|
||||||
|
*
|
||||||
|
* @author andy.shi
|
||||||
|
* @ClassName:ShiftContriller
|
||||||
|
* @date: 2026年03月27日 9:18
|
||||||
|
* @remark: 开发人员联系方式 1042025947@qq.com/微信同步
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/shift")
|
||||||
|
public class ShiftController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DingShiftService dingShiftService;
|
||||||
|
@Resource
|
||||||
|
private DingShiftGroupService dingShiftGroupService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询班次信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:shift:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(DingShift dingShift){
|
||||||
|
startPage();
|
||||||
|
List<DingShift> list = dingShiftService.selectList(dingShift);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询考勤组信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/group/list")
|
||||||
|
public TableDataInfo list(DingShiftGroup dingShiftGroup){
|
||||||
|
startPage();
|
||||||
|
List<DingShiftGroup> list = dingShiftGroupService.selectList(dingShiftGroup);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ import com.evo.common.utils.poi.ExcelUtil;
|
|||||||
import com.evo.system.domain.SysStaff;
|
import com.evo.system.domain.SysStaff;
|
||||||
import com.evo.system.domain.vo.SysStaffVo;
|
import com.evo.system.domain.vo.SysStaffVo;
|
||||||
import com.evo.system.service.ISysStaffService;
|
import com.evo.system.service.ISysStaffService;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
@ -184,4 +185,12 @@ public class SysStaffController extends BaseController
|
|||||||
{
|
{
|
||||||
return sysStaffService.reEmployment(userId);
|
return sysStaffService.reEmployment(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Log(title = "员工管理-离职员工重新入职", businessType = BusinessType.OTHER)
|
||||||
|
@GetMapping("/tree/getDingUserId")
|
||||||
|
public AjaxResult getDingUserId(@RequestParam("userName") String userName) throws Exception
|
||||||
|
{
|
||||||
|
return sysStaffService.getDingUserId(userName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -215,6 +215,10 @@ public class SysStaff extends BaseEntity
|
|||||||
|
|
||||||
private String extended;
|
private String extended;
|
||||||
|
|
||||||
|
private String dingUserId;
|
||||||
|
//数据来源 1 平台, 2 钉钉
|
||||||
|
private String source;
|
||||||
|
|
||||||
public List<Long> getSubsidyList() {
|
public List<Long> getSubsidyList() {
|
||||||
if(Collections.isEmpty(subsidyList) && StringUtils.isNotEmpty(subsidys)){
|
if(Collections.isEmpty(subsidyList) && StringUtils.isNotEmpty(subsidys)){
|
||||||
subsidyList = Collections.asList(subsidys.split(",")).stream().map(Long::valueOf).collect(Collectors.toList());
|
subsidyList = Collections.asList(subsidys.split(",")).stream().map(Long::valueOf).collect(Collectors.toList());
|
||||||
|
|||||||
@ -129,4 +129,9 @@ public interface SysDeptMapper extends BaseMapper<SysDept>
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int updateDeptForLeader(SysDept dept);
|
public int updateDeptForLeader(SysDept dept);
|
||||||
|
|
||||||
|
|
||||||
|
public SysDept selectByDingDeptId(String dingId);
|
||||||
|
|
||||||
|
public SysDept selectByName(String name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,4 +94,14 @@ s * @return
|
|||||||
*/
|
*/
|
||||||
SysStaff selectLeaderSysStaffByDeptId(Long deptId);
|
SysStaff selectLeaderSysStaffByDeptId(Long deptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询员工管理
|
||||||
|
*
|
||||||
|
* @param dingUserId 员工管理主键
|
||||||
|
* @return 员工管理
|
||||||
|
*/
|
||||||
|
public SysStaff selectSysStaffByDingUserId(String dingUserId);
|
||||||
|
|
||||||
|
SysStaff getDingUserId(@Param("userName") String userName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user