Merge branch 'feature/230701-工资单定时发送' into release/2.9.1.2307.01

This commit is contained in:
Harryxzy 2023-07-10 10:09:45 +08:00
commit 9b7ba19d64
16 changed files with 365 additions and 0 deletions

View File

@ -74,6 +74,9 @@ public class SalaryTemplateBO {
.replenishName(saveParam.getReplenishName())
.replenishRule(saveParam.getReplenishRule())
.replenishSalaryItemSetting((saveParam.getSalaryItemSetting() != null ? JsonUtil.toJsonString(saveParam.getReplenishSalaryItemSetting()) : ""))
.autoSendStatus(saveParam.getAutoSendStatus()?1:0)
.autoSendDayOfMonth(saveParam.getAutoSendDayOfMonth())
.autoSendTimeOfDay(saveParam.getAutoSendTimeOfDay())
.createTime(new Date())
.updateTime(new Date())
.creator(employeeId)

View File

@ -54,4 +54,16 @@ public class SalaryTemplateBaseSetDTO {
//消息中心")
private Boolean msgStatus;
// 是否启用工资单定时发送
private Boolean autoSendStatus;
// 自动发送工资单周期1本月2上月
private Integer autoSendCycleType;
// 每月几号自动发送工资单
private String autoSendDayOfMonth;
// 发送时间
private String autoSendTimeOfDay;
}

View File

@ -12,6 +12,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Objects;
/**
* @Description: 工资单模板
@ -62,6 +63,18 @@ public class SalaryTemplateSaveParam {
// 薪资项为0时不显示开启状态falsetrue
private Boolean salaryItemZeroStatus;
// 是否启用工资单定时发送0未启用1已启用
private Boolean autoSendStatus;
// 自动发送工资单周期1本月2上月
private Integer autoSendCycleType;
// 每月几号自动发送工资单
private String autoSendDayOfMonth;
// 自动发放时间
private String autoSendTimeOfDay;
// 薪资项目设置
private List<SalaryTemplateSalaryItemSetListDTO> salaryItemSetting;
@ -116,5 +129,18 @@ public class SalaryTemplateSaveParam {
if (CollectionUtils.isEmpty(saveParam.getReplenishSalaryItemSetting())) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(140509, "补发工资单模板的薪资项目设置不能为空"));
}
if (Objects.isNull(saveParam.getAutoSendStatus())) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(140509, "是否启用自动发放不能为空"));
}
if (saveParam.getAutoSendStatus() == Boolean.TRUE) {
if(StringUtils.isBlank(saveParam.getAutoSendDayOfMonth()))
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(140509, "自动发放日期不能为空"));
if(Objects.isNull(saveParam.getAutoSendCycleType()))
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(140509, "自动发放周期不能为空"));
if(StringUtils.isBlank(saveParam.getAutoSendTimeOfDay()))
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(140509, "自动发放时间不能为空"));
}
}
}

View File

@ -124,6 +124,27 @@ public class SalaryTemplatePO {
*/
private String replenishSalaryItemSetting;
/**
* 是否启用工资单定时发送0未启用1已启用
*/
private Integer autoSendStatus;
/**
* 自动发送工资单周期1本月2上月
*/
private Integer autoSendCycleType;
/**
* 每月几号自动发送工资单
*/
private String autoSendDayOfMonth;
/**
* 自动发放时间
*/
private String autoSendTimeOfDay;
/**
* 创建时间
*/

View File

@ -0,0 +1,54 @@
package com.engine.salary.enums.salarysend;
import com.engine.salary.enums.BaseEnum;
import java.util.Objects;
/**
* @ClassName SalaryAutoSendCycleTypeEnum
* @author Harryxzy
* @date 2023/7/4 17:30
* @description 自动发送工资单周期
*/
public enum SalaryAutoSendCycleTypeEnum implements BaseEnum<Integer> {
THIS_MONTH(1, "本月", 86072),
NEXT_MONTH(2, "下月", 86073);
private int value;
private String defaultLabel;
private int labelId;
SalaryAutoSendCycleTypeEnum(int value, String defaultLabel, int labelId) {
this.value = value;
this.defaultLabel = defaultLabel;
this.labelId = labelId;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getDefaultLabel() {
return defaultLabel;
}
@Override
public Integer getLabelId() {
return labelId;
}
public static SalaryAutoSendCycleTypeEnum parseByValue(int value) {
for (SalaryAutoSendCycleTypeEnum salaryCycleTypeEnum : SalaryAutoSendCycleTypeEnum.values()) {
if (Objects.equals(salaryCycleTypeEnum.getValue(), value)) {
return salaryCycleTypeEnum;
}
}
return null;
}
}

View File

@ -99,4 +99,6 @@ public interface SalarySendInfoMapper {
void updateIgnoreNull(SalarySendInfoPO po);
void deleteBySalaryAcctRecordIds(@Param("salaryAcctRecordId") Collection<Long> ids);
List<SalarySendInfoPO> getNeedSendInfoList(@Param("salarySendIds") List<Long> salarySendIds);
}

View File

@ -684,6 +684,19 @@
</if>
ORDER BY id DESC
</select>
<select id="getNeedSendInfoList" resultType="com.engine.salary.entity.salaryBill.po.SalarySendInfoPO">
select id,salary_send_id
from hrsa_salary_send_info a
where a.delete_type=0
and a.send_status in (0,2)
and (a.salary_acct_type!=1 or a.salary_acct_type is null)
<if test="salarySendIds != null and salarySendIds.size() > 0">
AND a.salary_send_id IN
<foreach collection="salarySendIds" open="(" item="salarySendId" separator="," close=")">
#{salarySendId}
</foreach>
</if>
</select>
<!-- 更新不为NULL的字段 -->

View File

@ -63,4 +63,6 @@ public interface SalarySendMapper {
void batchHandleSalaryAcctTypeHistory();
void deleteBySalaryAcctRecordIds(@Param("salaryAcctRecordId") Collection<Long> ids);
List<SalarySendPO> getNeedSendListBySalarySobIds(@Param("salarySobIds")List<Long> salarySobIds);
}

View File

@ -236,6 +236,22 @@
</if>
ORDER BY id DESC
</select>
<select id="getNeedSendListBySalarySobIds"
resultType="com.engine.salary.entity.salaryBill.po.SalarySendPO">
select
<include refid="salarySendPOColumn" />
from hrsa_salary_send
where
delete_type=0 and send_total != send_num
and (salary_acct_type = 0 or salary_acct_type is null )
and (send_status = 0 or send_status is null)
<if test="salarySobIds != null and salarySobIds.size() > 0">
AND salary_sob_id IN
<foreach collection="salarySobIds" open="(" item="salarySobId" separator="," close=")">
#{salarySobId}
</foreach>
</if>
</select>
<!-- 插入不为NULL的字段 -->

View File

@ -51,6 +51,10 @@
, replenish_name
, replenish_rule
, replenish_salary_item_setting
, auto_send_status
, auto_send_cycle_type
, auto_send_day_of_month
, auto_send_time_of_day
, t.create_time
, t.update_time
, t.creator
@ -76,6 +80,10 @@
replenish_name,
replenish_rule,
replenish_salary_item_setting,
auto_send_status,
auto_send_cycle_type,
auto_send_day_of_month,
auto_send_time_of_day,
create_time,
update_time,
creator,
@ -310,6 +318,9 @@
<if test="deleteType != null and deleteType != ''">
AND delete_type = #{deleteType}
</if>
<if test="autoSendStatus != null and autoSendStatus != ''">
AND auto_send_status = #{autoSendStatus}
</if>
<if test="salarySobIds != null and salarySobIds.size() > 0">
AND salary_sob_id IN
<foreach collection="salarySobIds" open="(" item="id" separator="," close=")">
@ -490,6 +501,18 @@
<if test="replenishSalaryItemSetting != null">
replenish_salary_item_setting=#{replenishSalaryItemSetting},
</if>
<if test="autoSendStatus != null">
auto_send_status=#{autoSendStatus},
</if>
<if test="autoSendCycleType != null">
auto_send_cycle_type=#{autoSendCycleType},
</if>
<if test="autoSendDayOfMonth != null">
auto_send_day_of_month=#{autoSendDayOfMonth},
</if>
<if test="autoSendTimeOfDay != null">
auto_send_time_of_day=#{autoSendTimeOfDay},
</if>
<if test="createTime != null">
create_time=#{createTime},
</if>
@ -568,6 +591,18 @@
<if test="replenishSalaryItemSetting != null">
replenish_salary_item_setting,
</if>
<if test="autoSendStatus != null">
auto_send_status,
</if>
<if test="autoSendCycleType != null">
auto_send_cycle_type,
</if>
<if test="autoSendDayOfMonth != null">
auto_send_day_of_month,
</if>
<if test="autoSendTimeOfDay != null">
auto_send_time_of_day,
</if>
<if test="createTime != null">
create_time,
</if>
@ -642,6 +677,18 @@
<if test="replenishSalaryItemSetting != null">
#{replenishSalaryItemSetting},
</if>
<if test="autoSendStatus != null">
#{autoSendStatus},
</if>
<if test="autoSendCycleType != null">
#{autoSendCycleType},
</if>
<if test="autoSendDayOfMonth != null">
#{autoSendDayOfMonth},
</if>
<if test="autoSendTimeOfDay != null">
#{autoSendTimeOfDay},
</if>
<if test="createTime != null">
#{createTime},
</if>
@ -726,6 +773,18 @@
<if test="replenishSalaryItemSetting != null">
replenish_salary_item_setting,
</if>
<if test="autoSendStatus != null">
auto_send_status,
</if>
<if test="autoSendCycleType != null">
auto_send_cycle_type,
</if>
<if test="autoSendDayOfMonth != null">
auto_send_day_of_month,
</if>
<if test="autoSendTimeOfDay != null">
auto_send_time_of_day,
</if>
<if test="createTime != null">
create_time,
</if>
@ -800,6 +859,18 @@
<if test="replenishSalaryItemSetting != null">
#{replenishSalaryItemSetting},
</if>
<if test="autoSendStatus != null">
#{autoSendStatus},
</if>
<if test="autoSendCycleType != null">
#{autoSendCycleType},
</if>
<if test="autoSendDayOfMonth != null">
#{autoSendDayOfMonth},
</if>
<if test="autoSendTimeOfDay != null">
#{autoSendTimeOfDay},
</if>
<if test="createTime != null">
#{createTime},
</if>

View File

@ -2,6 +2,7 @@ package com.engine.salary.service;
import com.engine.salary.entity.salaryBill.dto.*;
import com.engine.salary.entity.salaryBill.param.*;
import com.engine.salary.entity.salaryBill.po.SalarySendInfoPO;
import com.engine.salary.entity.salaryBill.po.SalarySendPO;
import com.engine.salary.entity.salaryBill.po.SalaryTemplatePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
@ -187,4 +188,17 @@ public interface SalarySendService {
* @param param
*/
Boolean checkMobileCode(SMSCodeCheckParam param);
/**
* 获取工资单id下需要发放的工资单明细
* @return
*/
List<SalarySendInfoPO> getNeedSendInfoList(List<Long> salarySendIds);
/**
* 获取这些模板下未发放完的工资单
* @param salarySobIds
* @return
*/
List<SalarySendPO> getNeedSendListBySalarySobIds(List<Long> salarySobIds);
}

View File

@ -112,4 +112,9 @@ public interface SalaryTemplateService {
* @return
*/
PageInfo<SalaryTemplateListDTO> listPage(SalaryTemplateQueryParam queryParam);
/**
* 获取所有设置了定时发送的默认工资单模板
*/
List<SalaryTemplatePO> getAutoSendTemplate();
}

View File

@ -1557,4 +1557,20 @@ public class SalarySendServiceImpl extends Service implements SalarySendService
return true;
}
@Override
public List<SalarySendInfoPO> getNeedSendInfoList(List<Long> salarySendIds) {
if(CollectionUtils.isEmpty(salarySendIds)){
return Collections.emptyList();
}
return getSalarySendInfoMapper().getNeedSendInfoList(salarySendIds);
}
@Override
public List<SalarySendPO> getNeedSendListBySalarySobIds(List<Long> salarySobIds) {
if(CollectionUtils.isEmpty(salarySobIds)){
return Collections.emptyList();
}
return getSalarySendMapper().getNeedSendListBySalarySobIds(salarySobIds);
}
}

View File

@ -132,6 +132,7 @@ public class SalaryTemplateServiceImpl extends Service implements SalaryTemplate
salaryTemplate.setTextContentPosition(saveParam.getTextContentPosition());
salaryTemplate.setSalaryItemNullStatus(saveParam.getSalaryItemNullStatus()?1:0);
salaryTemplate.setSalaryItemZeroStatus(saveParam.getSalaryItemZeroStatus()?1:0);
salaryTemplate.setAutoSendCycleType(saveParam.getAutoSendCycleType());
mapper.insert(salaryTemplate);
// 记录日志
// SalaryLoggerUtil.recordAddSingleLog(salaryTemplateLoggerTemplate,
@ -190,6 +191,8 @@ public class SalaryTemplateServiceImpl extends Service implements SalaryTemplate
salaryTemplateNew.setTextContentPosition(saveParam.getTextContentPosition());
salaryTemplateNew.setSalaryItemNullStatus(saveParam.getSalaryItemNullStatus()?1:0);
salaryTemplateNew.setSalaryItemZeroStatus(saveParam.getSalaryItemZeroStatus()?1:0);
salaryTemplateNew.setAutoSendStatus(saveParam.getAutoSendStatus()?1:0);
salaryTemplateNew.setAutoSendCycleType(saveParam.getAutoSendCycleType());
// todo 薪资项目设置检查校验
salaryTemplateNew.setSalaryItemSetting(saveParam.getSalaryItemSetting() != null ? JSONUtil.toJsonStr(saveParam.getSalaryItemSetting()) : "");
salaryTemplateNew.setReplenishSalaryItemSetting(saveParam.getReplenishSalaryItemSetting() != null ? JSONUtil.toJsonStr(saveParam.getReplenishSalaryItemSetting()) : "");
@ -315,4 +318,9 @@ public class SalaryTemplateServiceImpl extends Service implements SalaryTemplate
PageInfo<SalaryTemplateListDTO> page = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), salaryTemplateDTOList, SalaryTemplateListDTO.class);
return page;
}
@Override
public List<SalaryTemplatePO> getAutoSendTemplate() {
return mapper.listSome(SalaryTemplatePO.builder().autoSendStatus(NumberUtils.INTEGER_ONE).useType(NumberUtils.INTEGER_ONE).deleteType(NumberUtils.INTEGER_ZERO).build());
}
}

View File

@ -0,0 +1,101 @@
package com.engine.salary.timer;
import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.salaryBill.param.SalarySendGrantParam;
import com.engine.salary.entity.salaryBill.po.SalarySendInfoPO;
import com.engine.salary.entity.salaryBill.po.SalarySendPO;
import com.engine.salary.entity.salaryBill.po.SalaryTemplatePO;
import com.engine.salary.service.SalaryBillService;
import com.engine.salary.service.SalarySendService;
import com.engine.salary.service.SalaryTemplateService;
import com.engine.salary.service.impl.SalaryBillServiceImpl;
import com.engine.salary.service.impl.SalarySendServiceImpl;
import com.engine.salary.service.impl.SalaryTemplateServiceImpl;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import weaver.hrm.User;
import weaver.interfaces.schedule.BaseCronJob;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Harryxzy
* @ClassName AutoSendSalaryJob
* @date 2023/07/03 10:39
* @description 自动发送工资单
*/
public class AutoSendSalaryJob extends BaseCronJob {
private SalarySendService getSalarySendService(User user) {
return ServiceUtil.getService(SalarySendServiceImpl.class, user);
}
private SalaryTemplateService getSalaryTemplateService(User user) {
return ServiceUtil.getService(SalaryTemplateServiceImpl.class, user);
}
private SalaryBillService getSalaryBillService(User user) {
return ServiceUtil.getService(SalaryBillServiceImpl.class, user);
}
@Override
public void execute() {
User tempUser = new User();
tempUser.setUid(1);
tempUser.setLoginid("sysadmin");
// 获取所有设置了定时发送的默认工资单模板
List<SalaryTemplatePO> autoSendTemplate = getSalaryTemplateService(tempUser).getAutoSendTemplate();
Map<Long, SalaryTemplatePO> autoSendTypeMap = SalaryEntityUtil.convert2Map(autoSendTemplate, SalaryTemplatePO::getSalarySobId);
List<Long> salarySobIds = autoSendTemplate.stream().map(SalaryTemplatePO::getSalarySobId).collect(Collectors.toList());
// 获取这些模板下未发放完的正常(非补发非冻结)工资单
List<SalarySendPO> salarySendList = getSalarySendService(tempUser).getNeedSendListBySalarySobIds(salarySobIds);
LocalDateTime nowLocalDateTime = SalaryDateUtil.dateToLocalDateTime(new Date());
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
List<Long> needSendIds = salarySendList.stream().filter(sendPO -> {
SalaryTemplatePO templatePO = autoSendTypeMap.get(sendPO.getSalarySobId());
if (templatePO == null) {
return false;
}
LocalDate autoSendDate = null;
if (templatePO.getAutoSendCycleType() == 1) {
// 薪资所属月当月
autoSendDate = SalaryDateUtil.dateToLocalDate(sendPO.getSalaryMonth());
} else {
// 薪资所属月下月
autoSendDate = SalaryDateUtil.dateToLocalDate(sendPO.getSalaryMonth()).plusMonths(1);
}
int maxDays = autoSendDate.lengthOfMonth();
Integer sendDays = Integer.valueOf(templatePO.getAutoSendDayOfMonth());
if (sendDays.intValue() > maxDays) {
sendDays = maxDays;
}
autoSendDate = autoSendDate.withDayOfMonth(sendDays);
LocalDateTime autoSendDateTime = null;
try {
// 加上时间
autoSendDateTime = autoSendDate.atTime(SalaryDateUtil.dateToLocalDateTime(timeFormat.parse(templatePO.getAutoSendTimeOfDay())).toLocalTime());
} catch (ParseException e) {
throw new RuntimeException(e);
}
if (!autoSendDateTime.isAfter(nowLocalDateTime)) {
// 自动发放时间早于或等于现在的发放记录
return true;
}
return false;
}).map(SalarySendPO::getId).collect(Collectors.toList());
// 获取工资单发放记录下需要发放的工资单明细
List<SalarySendInfoPO> needSendInfoList = getSalarySendService(tempUser).getNeedSendInfoList(needSendIds);
Map<Long, Set<Long>> sendMap = SalaryEntityUtil.group2Map(needSendInfoList, SalarySendInfoPO::getSalarySendId, SalarySendInfoPO::getId);
for(Map.Entry<Long, Set<Long>> entry : sendMap.entrySet()){
// 发放
getSalaryBillService(tempUser).grant(SalarySendGrantParam.builder().salarySendId(entry.getKey()).ids(new ArrayList<Long>(entry.getValue())).build());
}
}
}

View File

@ -153,6 +153,7 @@ public class SalaryTemplateWrapper extends Service {
salaryTemplateBaseSetDTO.setMsgStatus(po.getMsgStatus().equals(SalaryTemplateWhetherEnum.TRUE.getValue()));
salaryTemplateBaseSetDTO.setSalarySob(po.getSalarySobId());
salaryTemplateBaseSetDTO.setSendEmail(po.getSendEmailId());
salaryTemplateBaseSetDTO.setAutoSendStatus(po.getAutoSendStatus() == null ? false : po.getAutoSendStatus().equals(SalaryTemplateWhetherEnum.TRUE.getValue()));
// 规则赋值 如果为ALL传 如果为byRule传薪资项目ID
salaryTemplateBaseSetDTO.setReplenishRule(SalaryTemplateReplenishRuleEnum.ALL.getValue().equals(po.getReplenishRule()) ? "" : po.getReplenishRule());
// 规则设置赋值