feat(attendance): 添加补卡功能和财务支付取消领取

- 在考勤功能中,增加补卡次数限制和补卡操作接口。- 财务支付功能中,增加取消领取操作,优化支付管理。

重构和样式调整:
- 无

fixes:
-无

BREAKING CHANGE:
-考勤组实体和相关请求/响应VO中增加replacementCardNum字段,以支持补卡次数限制。
- 财务支付的取消领取操作可能会对相关业务逻辑产生影响,需确保在使用前进行测试。
This commit is contained in:
aikai 2024-08-27 09:19:01 +08:00
parent c1760c89b6
commit 5921928c96
15 changed files with 198 additions and 1 deletions

View File

@ -62,6 +62,13 @@ public class FinancialPaymentController {
return success(true);
}
@PostMapping("/cancel")
@Operation(summary = "取消领取")
public CommonResult<Boolean> cancel(@RequestBody List<Long> ids) {
financialPaymentService.cancel(ids);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除财务支付管理")
@Parameter(name = "id", description = "编号", required = true)
@ -88,7 +95,8 @@ public class FinancialPaymentController {
item.setFinancialPaymentId(financialPaymentItemDO.getFinancialPaymentId());
item.setCreateTime(financialPaymentItemDO.getCreateTime());
if (CollectionUtil.isNotEmpty(financialPaymentItemDO.getFileItems())) {
item.setFileItems(new ArrayList<UploadUserFile>());
List<UploadUserFile> uploadUserFiles = BeanUtils.toBean(financialPaymentItemDO.getFileItems(), UploadUserFile.class);
item.setFileItems(uploadUserFiles);
}
items.add(item);
}

View File

@ -24,6 +24,9 @@ public class FinancialPaymentPageReqVO extends PageParam {
@Schema(description = "申请人的用户名称", example = "13599")
private String nickname;
@Schema(description = "财务名称", example = "13599")
private String financeName;
@Schema(description = "原因", example = "13599")
private String reason;

View File

@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 财务支付管理 Mapper
*
@ -32,4 +34,11 @@ public interface FinancialPaymentMapper extends BaseMapperX<FinancialPaymentDO>
* @return
*/
FinancialPaymentDO getFinancialPayment(@Param("id") Long id);
/**
* 拒绝领取
*
* @param ids
*/
void cancel(@Param("ids") List<Long> ids);
}

View File

@ -74,4 +74,11 @@ public interface FinancialPaymentService {
* @param financialPayment
*/
void updateById(FinancialPaymentDO financialPayment);
/**
* 取消领取
*
* @param ids
*/
void cancel(List<Long> ids);
}

View File

@ -169,4 +169,9 @@ public class FinancialPaymentServiceImpl implements FinancialPaymentService {
financialPaymentMapper.updateById(financialPayment);
}
@Override
public void cancel(List<Long> ids) {
financialPaymentMapper.cancel(ids);
}
}

View File

@ -40,6 +40,9 @@
<if test="vo.reason != null and vo.reason != ''">
and a.reason like concat('%', #{vo.reason}, '%')
</if>
<if test="vo.financeName != null and vo.financeName != ''">
and d.nickname like concat('%', #{vo.financeName}, '%')
</if>
<if test="vo.receiveType != null">
<if test="vo.receiveType == 1">
and a.receive_user_id is null
@ -73,6 +76,14 @@
</where>
ORDER BY a.status asc,a.end_time DESC
</select>
<update id="cancel">
update bpm_financial_payment set receive_user_id = null
where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
and status = 0
</update>
<select id="getFinancialPayment"
resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO">
select

View File

@ -204,6 +204,9 @@ public interface ErrorCodeConstants {
ErrorCode GROUP_SHIFT_IN_USE = new ErrorCode(1_003_014_000, "班次使用中不允许删除");
ErrorCode THERE_ARE_STILL_PEOPLE_IN_THE_ATTENDANCE_GROUP_WHO_ARE_NOT_ALLOWED_TO_BE_DELETED = new ErrorCode(1_003_015_000, "考勤组还有人员不允许删除");
ErrorCode INSUFFICIENT_NUMBER_OF_CARD_REFILLS = new ErrorCode(1_003_016_000, "补卡次数不足");
ErrorCode ABNORMAL_CARD_REPLENISHMENT = new ErrorCode(1_003_017_000, "补卡异常");
ErrorCode CANNOT_FIND_THE_RECORD_THAT_NEEDS_TO_BE_REPLACED = new ErrorCode(1_003_018_000, "查询不到需要补卡的记录");
ErrorCode LOG_FORM_NOT_USE = new ErrorCode(1_009_010_004, "你不用使用该日志模板");

View File

@ -39,6 +39,20 @@ public class AttendanceController {
return success(vo);
}
@GetMapping("/getReplacementCardNum")
@Operation(summary = "获取本月剩余补卡次数")
public CommonResult<Integer> getReplacementCardNum() {
Integer num = attendanceService.getReplacementCardNum();
return success(num);
}
@PostMapping("/replacementCard")
@Operation(summary = "补卡")
public CommonResult replacementCard(@RequestBody AttendanceReplacementCardDTO dto) {
attendanceService.replacementCard(dto);
return success("补卡成功");
}
@GetMapping("/getRules/{groupId}")
@Operation(summary = "获取考勤规则")
public CommonResult<AttendanceRulesVO> getRules(@PathVariable Long groupId) {

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.system.controller.admin.attendance.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Data
@Accessors(chain = true)
public class AttendanceReplacementCardDTO {
@Schema(description = "日期 yyyy-MM-dd格式")
private String actualDayTime;
@Schema(description = "班次子表id")
private Long attendanceGroupShiftItemId;
@Schema(description = "上下班类型 0上班 1下班")
private Integer workType;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.controller.admin.group.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -48,6 +49,10 @@ public class AttendanceGroupPageReqVO extends PageParam {
@Schema(description = "节假日自动排休 0否 1是")
private Integer autoHolidaysFlag;
@Schema(description = "可补卡次数(每个月1号凌晨重置 默认3次)")
private Integer replacementCardNum;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@ -63,6 +63,10 @@ public class AttendanceGroupRespVO {
@ExcelProperty("节假日自动排休 0否 1是")
private Integer autoHolidaysFlag;
@Schema(description = "可补卡次数(每个月1号凌晨重置 默认3次)")
@ExcelProperty("可补卡次数(每个月1号凌晨重置 默认3次)")
private Integer replacementCardNum;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;

View File

@ -40,4 +40,6 @@ public class AttendanceGroupSaveReqVO {
@Schema(description = "节假日自动排休 0否 1是")
private Integer autoHolidaysFlag;
@Schema(description = "可补卡次数(每个月1号凌晨重置 默认3次)")
private Integer replacementCardNum;
}

View File

@ -68,6 +68,11 @@ public class AttendanceGroupDO extends BaseDO {
* 节假日自动排休 0否 1是
*/
private Integer autoHolidaysFlag;
/**
* 可补卡次数(每个月1号凌晨重置 默认3次)
*/
private Integer replacementCardNum;
/**
* 管理员名称列表逗号隔开

View File

@ -113,4 +113,30 @@ public interface AttendanceService {
* @return
*/
AttendanceRulesVO getRulesByUserId();
/**
* 获取本月补卡次数
*
* @return
*/
Integer getReplacementCardNum();
/**
* 使用补卡次数
*
* @param userId
*/
void useReplacementCardNum(Long userId);
/**
* 使用补卡次数
*/
void useReplacementCardNum();
/**
* 补卡
*
* @param dto
*/
void replacementCard(AttendanceReplacementCardDTO dto);
}

View File

@ -948,6 +948,80 @@ public class AttendanceServiceImpl implements AttendanceService {
return this.getRules(activationGroup.getId());
}
@Override
public Integer getReplacementCardNum() {
Long userId = getLoginUserId();
Integer num = 0;
String key = "ReplacementCardNum" + "_" + userId + "_" + LocalDateTime.now().format(Constants.REPO_DATE_FORMAT);
String value = stringRedisTemplate.opsForValue().get(key);
if (StringUtils.isEmpty(value)) {
// -- 获取当前用户
AttendanceGroupDO group = attendanceGroupService.getByUserId(userId);
if (group != null) {
num = group.getReplacementCardNum();
}
stringRedisTemplate.opsForValue().set(key, num.toString(), 32, TimeUnit.DAYS);
return num;
}
return Integer.valueOf(value);
}
@Override
public void useReplacementCardNum() {
this.useReplacementCardNum(null);
}
@Override
public void replacementCard(AttendanceReplacementCardDTO dto) {
Long userId = getLoginUserId();
//先减去补卡次数
this.useReplacementCardNum(userId);
try {
int update = attendancePunchRecordMapper.update(new AttendancePunchRecordDO().setStatus(AttendanceOnTheDayDTO.REPLACEMENT_CARD),
new LambdaQueryWrapper<AttendancePunchRecordDO>()
.eq(AttendancePunchRecordDO::getUserId, userId)
.eq(AttendancePunchRecordDO::getAttendanceGroupShiftItemId, dto.getAttendanceGroupShiftItemId())
.eq(AttendancePunchRecordDO::getWorkType, dto.getWorkType())
.eq(AttendancePunchRecordDO::getActualDayTime, dto.getActualDayTime())
.eq(AttendancePunchRecordDO::getStatus, AttendanceOnTheDayDTO.PUNCH_STATUS_MISS));
if (update <= 0) {
throw exception(CANNOT_FIND_THE_RECORD_THAT_NEEDS_TO_BE_REPLACED);
}
} catch (Exception e) {
// -- 如果有报错的话 - 那么进行回滚操作 - 并且redis 中的补卡次数也要+1 (redis并不会回滚)
String key = "ReplacementCardNum" + "_" + userId + "_" + LocalDateTime.now().format(Constants.REPO_DATE_FORMAT);
stringRedisTemplate.opsForValue().increment(key, 1);
throw exception(ABNORMAL_CARD_REPLENISHMENT);
}
}
@Override
public void useReplacementCardNum(Long userId) {
userId = userId == null ? getLoginUserId() : userId;
String key = "ReplacementCardNum" + "_" + userId + "_" + LocalDateTime.now().format(Constants.REPO_DATE_FORMAT);
String value = stringRedisTemplate.opsForValue().get(key);
if (StringUtils.isNotEmpty(value)) {
if (Integer.parseInt(value) > 0) {
stringRedisTemplate.opsForValue().increment(key, -1);
} else {
throw exception(INSUFFICIENT_NUMBER_OF_CARD_REFILLS);
}
return;
}
// -- 如果redis不存在则从数据库获取
Integer num = 0;
AttendanceGroupDO group = attendanceGroupService.getByUserId(userId);
if (group != null) {
num = group.getReplacementCardNum();
}
if (num > 0) {
num = num - 1;
stringRedisTemplate.opsForValue().set(key, num.toString(), 32, TimeUnit.DAYS);
} else {
throw exception(INSUFFICIENT_NUMBER_OF_CARD_REFILLS);
}
}
/**
* 按日导出