From c89754514890fa1c497c09084e6a6f0aa308ddef Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Tue, 12 Nov 2024 21:23:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(bpm):=20=E5=AE=9E=E7=8E=B0=E8=A1=A5?= =?UTF-8?q?=E5=8D=A1=E7=94=B3=E8=AF=B7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增补卡申请 API 接口和实现类 - 添加补卡申请创建、审核等服务方法 - 实现补卡申请结果监听器 - 新增补卡申请相关 VO 类 - 集成 Redis缓存补卡次数 -调用考勤 API 进行补卡操作 --- .../api/oa/BpmOAReplacementCardApiImpl.java | 41 +++++++ .../BpmOAReplacementCardCreateReqVO.java | 2 +- .../ReplacementCardItemVO.java | 15 ++- .../ReplacementCardRecord.java | 15 +++ .../rpc/config/RpcConfiguration.java | 3 +- .../oa/BpmOAReplacementCardService.java | 9 +- .../oa/BpmOAReplacementCardServiceImpl.java | 107 ++++++++++++++++-- .../BpmOAReplacementCardResultListener.java | 2 +- 8 files changed, 178 insertions(+), 16 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAReplacementCardApiImpl.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardRecord.java diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAReplacementCardApiImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAReplacementCardApiImpl.java new file mode 100644 index 00000000..d8a72a5c --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAReplacementCardApiImpl.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.bpm.api.oa; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.replacementCard.ReplacementCardItemVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReplacementCardDO; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReplacementCardService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@RestController +@Validated +public class BpmOAReplacementCardApiImpl implements BpmOAReplacementCardApi{ + + @Resource + private BpmOAReplacementCardService replacementCardService; + + @Override + public CommonResult> getPunchRecordIds() { + List list = replacementCardService.getListByResult(); + + List punchRecordIds = new ArrayList<>(); + for (BpmOAReplacementCardDO item : list) { + + List respVO = item.getApplicationItem(); + //直接从数据库取出来的List 实际上是List类型 所以不能直接遍历 + //将list再次转为json串,然后由json串再转为list + String json = JsonUtils.toJsonString(respVO); + respVO = JsonUtils.parseArray(json, ReplacementCardItemVO.class); + punchRecordIds.addAll(convertList(respVO, ReplacementCardItemVO::getPunchRecordId)); + } + return success(punchRecordIds); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/BpmOAReplacementCardCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/BpmOAReplacementCardCreateReqVO.java index ff209c56..702a3af1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/BpmOAReplacementCardCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/BpmOAReplacementCardCreateReqVO.java @@ -14,7 +14,7 @@ import java.util.List; * * @author 符溶馨 */ -@Schema(description = "管理后台 - 薪资付款申请创建 Request VO") +@Schema(description = "管理后台 - 补卡申请创建 Request VO") @Data @EqualsAndHashCode() @ToString(callSuper = true) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardItemVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardItemVO.java index f45b4e00..c169b106 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardItemVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardItemVO.java @@ -3,14 +3,21 @@ package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.replacementCard; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.time.LocalDate; - @Schema(description = "管理后台 - 补卡明细 Response VO") @Data public class ReplacementCardItemVO { - @Schema(description = "补卡日期") - private LocalDate date; + @Schema(description = "用卡缺卡记录编号") + private Long punchRecordId; + + @Schema(description = "缺卡日期") + private String dayTime; + + @Schema(description = "上下班类型 0上班 1下班") + private Integer workType; + + @Schema(description = "打卡状态 0正常 1迟到 2早退 3缺卡 4未打卡(还没到打卡时间) 5补卡") + private Integer status; @Schema(description = "补卡事由") private String reason; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardRecord.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardRecord.java new file mode 100644 index 00000000..3f2cebc0 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/replacementCard/ReplacementCardRecord.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.replacementCard; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "本月补卡申请 VO") +@Data +public class ReplacementCardRecord { + + @Schema(description = "缺卡日期") + private String dayTime; + + @Schema(description = "上下班类型 0上班 1下班") + private Integer workType; +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java index fce6ee8d..8a564709 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/rpc/config/RpcConfiguration.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; import cn.iocoder.yudao.module.system.api.equipment.UsersExtApi; +import cn.iocoder.yudao.module.system.api.group.AttendanceGroupApi; import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import cn.iocoder.yudao.module.system.api.permission.RoleApi; import cn.iocoder.yudao.module.system.api.position.PositionApi; @@ -25,7 +26,7 @@ import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) @EnableFeignClients(clients = {FileApi.class, RoleApi.class, DeptApi.class, PostApi.class, AdminUserApi.class, SmsSendApi.class, DictDataApi.class, NotifyMessageSendApi.class, SubscribeMessageSendApi.class, SocialClientApi.class, UsersExtApi.class, AttendanceApi.class, BankApi.class, ConfigApi.class, PositionApi.class, SupplierApi.class, AssetsApi.class, - AssetsTypeApi.class, AssetReceiveApi.class + AssetsTypeApi.class, AssetReceiveApi.class, AttendanceApi.class, AttendanceGroupApi.class }) public class RpcConfiguration { } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardService.java index 3818eee3..abb39336 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.replacementCard.BpmOAR import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReplacementCardDO; import javax.validation.Valid; +import java.util.List; /** * 补卡申请 Service 接口 @@ -27,7 +28,7 @@ public interface BpmOAReplacementCardService { * @param id 编号 * @param result 结果 */ - void updateReplacementCardResult(Long id, Integer result); + void updateReplacementCardResult(String processInstanceId, Long id, Integer result); /** * 获得补卡申请 @@ -43,4 +44,10 @@ public interface BpmOAReplacementCardService { * @return 补卡申请 */ BpmOAReplacementCardDO getByProcessInstanceId(String processInstanceId); + + /** + * 处理中的补卡申请 + * @return 补卡申请列表 + */ + List getListByResult(); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardServiceImpl.java index b2507811..12021f57 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReplacementCardServiceImpl.java @@ -1,24 +1,40 @@ package cn.iocoder.yudao.module.bpm.service.oa; +import cn.iocoder.yudao.framework.common.Constants; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.replacementCard.BpmOAReplacementCardCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.replacementCard.ReplacementCardItemVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReplacementCardDO; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAReplacementCardMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.system.api.attendance.AttendanceApi; +import cn.iocoder.yudao.module.system.api.group.AttendanceGroupApi; +import com.alibaba.nacos.common.utils.StringUtils; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_REPLACEMENT_CARD_NOT_EXISTS; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.INSUFFICIENT_NUMBER_OF_CARD_REFILLS; /** * OA 补卡申请 Service 实现类 @@ -38,11 +54,20 @@ public class BpmOAReplacementCardServiceImpl extends BpmOABaseService implements private BpmOAReplacementCardMapper replacementCardMapper; @Resource - private BpmProcessInstanceApi processInstanceApi; + private BpmProcessInstanceService bpmProcessInstanceService; @Resource private BpmHistoryProcessInstanceService historyProcessInstanceService; + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private AttendanceGroupApi attendanceGroupApi; + + @Resource + private AttendanceApi attendanceApi; + @Override public Long createReplacementCard(Long userId, BpmOAReplacementCardCreateReqVO createReqVO) { @@ -54,9 +79,9 @@ public class BpmOAReplacementCardServiceImpl extends BpmOABaseService implements // 发起 BPM 流程 Map processInstanceVariables = new HashMap<>(); - String processInstanceId = processInstanceApi.createProcessInstance(userId, + String processInstanceId = bpmProcessInstanceService.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) - .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(replacementCard.getId()))).getCheckedData(); + .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(replacementCard.getId()))); // 将工作流的编号,更新到 OA 补卡申请单中 replacementCardMapper.updateById(new BpmOAReplacementCardDO().setId(replacementCard.getId()).setProcessInstanceId(processInstanceId)); @@ -72,19 +97,76 @@ public class BpmOAReplacementCardServiceImpl extends BpmOABaseService implements if (fileItems != null && !fileItems.isEmpty()) { uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ; } + + // 发起补卡申请后, 先扣除用户补卡次数 + String key = "ReplacementCardNum" + "_" + userId + "_" + LocalDateTime.now().format(Constants.YEAR_MONTH_FORMAT); + String value = stringRedisTemplate.opsForValue().get(key); + if (StringUtils.isNotEmpty(value)) { + if (Integer.parseInt(value) > 0) { + stringRedisTemplate.opsForValue().increment(key, -(createReqVO.getApplicationItem().size())); + } else { + throw exception(INSUFFICIENT_NUMBER_OF_CARD_REFILLS); + } + }else { + // 如果redis不存在,则从数据库获取 + Integer num = attendanceGroupApi.getReplacementCardNum(userId).getCheckedData(); + if (num > 0) { + num = num - createReqVO.getApplicationItem().size(); + stringRedisTemplate.opsForValue().set(key, num.toString(), 32, TimeUnit.DAYS); + } else { + throw exception(INSUFFICIENT_NUMBER_OF_CARD_REFILLS); + } + } + return replacementCard.getId(); } @Override - public void updateReplacementCardResult(Long id, Integer result) { - validateLeaveExists(id); + @Transactional(rollbackFor = Exception.class) + public void updateReplacementCardResult(String processInstanceId, Long id, Integer result) { + BpmOAReplacementCardDO replacementCard = validateLeaveExists(id); replacementCardMapper.updateById(new BpmOAReplacementCardDO().setId(id).setResult(result)); + + //审核通过 (最后节点) + if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) { + + ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId); + + if (instance.isEnded()) { + + List respVO = replacementCard.getApplicationItem(); + //直接从数据库取出来的List 实际上是List类型 所以不能直接遍历 + //将list再次转为json串,然后由json串再转为list + String json = JsonUtils.toJsonString(respVO); + respVO = JsonUtils.parseArray(json, ReplacementCardItemVO.class); + + // 获取需补卡的打卡记录编号 + List punchRecordIds = convertList(respVO, ReplacementCardItemVO::getPunchRecordId); + + // 审核通过, 则进行批量补卡操作 + attendanceApi.replacementCard(punchRecordIds); + } + } + + // -- 自己取消 + // -- 审核拒绝 + if (BpmProcessInstanceResultEnum.REJECT.getResult().equals(result) + || BpmProcessInstanceResultEnum.CANCEL.getResult().equals(result) + || BpmProcessInstanceResultEnum.BACK.getResult().equals(result)) { + + // 恢复redis 中的补卡次数 + String key = "ReplacementCardNum" + "_" + replacementCard.getUserId() + "_" + LocalDateTime.now().format(Constants.YEAR_MONTH_FORMAT); + stringRedisTemplate.opsForValue().increment(key, replacementCard.getApplicationItem().size()); + } } - private void validateLeaveExists(Long id) { - if (replacementCardMapper.selectById(id) == null) { + private BpmOAReplacementCardDO validateLeaveExists(Long id) { + BpmOAReplacementCardDO replacementCard = replacementCardMapper.selectById(id); + if (replacementCard == null) { throw exception(OA_REPLACEMENT_CARD_NOT_EXISTS); } + + return replacementCard; } @Override @@ -98,4 +180,13 @@ public class BpmOAReplacementCardServiceImpl extends BpmOABaseService implements return replacementCardMapper.selectOne(BpmOAReplacementCardDO::getProcessInstanceId, processInstanceId); } + + @Override + public List getListByResult() { + + return replacementCardMapper.selectList(new LambdaQueryWrapperX() + .eq(BpmOAReplacementCardDO::getUserId, getLoginUserId()) + .eq(BpmOAReplacementCardDO::getResult, BpmProcessInstanceResultEnum.PROCESS.getResult()) + .like(BpmOAReplacementCardDO::getCreateTime, LocalDate.now().format(Constants.YEAR_MONTH_FORMAT))); + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAReplacementCardResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAReplacementCardResultListener.java index a42bbfa3..520d66b4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAReplacementCardResultListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAReplacementCardResultListener.java @@ -27,6 +27,6 @@ public class BpmOAReplacementCardResultListener extends BpmProcessInstanceResult @Override protected void onEvent(BpmProcessInstanceResultEvent event) { - ReplacementCardService.updateReplacementCardResult(Long.parseLong(event.getBusinessKey()), event.getResult()); + ReplacementCardService.updateReplacementCardResult(event.getId(), Long.parseLong(event.getBusinessKey()), event.getResult()); } }