diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApi.java index dfc9290e..382caea5 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApi.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApi.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; +import javax.annotation.security.PermitAll; import java.util.List; import java.util.Map; @@ -18,5 +19,6 @@ public interface BpmOAGoOutApi { @GetMapping(PREFIX + "/getGoOutByTime") @Operation(summary = "获取当日以及昨日外出的用户编号") + @PermitAll CommonResult>> getLeaveListByTime(); } diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java index 251635ea..694023d9 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java @@ -20,7 +20,8 @@ public enum BpmTaskRuleScriptEnum { LEADER_X3(22L, "流程发起人的三级领导"), LEADER_X4(23L, "审批人的一级领导"), LEADER_X5(24L, "调岗部门领导"), - LEADER_X6(25L, "分配任务的责任人"); + LEADER_X6(25L, "分配任务的责任人"), + LEADER_X7(26L, "入职部门领导"); /** * 脚本编号 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApiImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApiImpl.java index 034e0d56..24d2b42d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApiImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/oa/BpmOAGoOutApiImpl.java @@ -7,6 +7,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import javax.annotation.security.PermitAll; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.HashMap; @@ -30,6 +31,7 @@ public class BpmOAGoOutApiImpl implements BpmOAGoOutApi{ private BpmOAGoOutService goOutService; @Override + @PermitAll public CommonResult>> getLeaveListByTime() { // 定义格式化模式 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java new file mode 100644 index 00000000..d96b67ba --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +/** + * 薪资付款申请 创建 Request VO + * + * @author 符溶馨 + */ +@Schema(description = "管理后台 - 薪资付款申请创建 Request VO") +@Data +@EqualsAndHashCode() +@ToString(callSuper = true) +public class BpmOASalaryCreateReqVO { + + @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "申请原因不能为空") + private String reason; + + @Schema(description = "付款公司", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "付款公司不能为空") + private Long companyDeptId; + + @Schema(description = "付款总额", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "付款总额不能为空") + private BigDecimal paymentTotal; + + @Schema(description = "支付对象") + private String paymentRecipient; + + @Schema(description = "流程实例编号") + private String processInstanceId; + + @Schema(description = "状态-参见 bpm_process_instance_result 枚举") + private Integer result; + + @Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "附件不能为空") + private List fileItems; +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java new file mode 100644 index 00000000..b221f362 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +/** + * @author 符溶馨 + */ +@Schema(description = "管理后台 - 薪资付款申请 请求Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BpmOASalaryRespVO extends BpmOABaseRespVO { + + @Schema(description = "申请原因") + private String reason; + + @Schema(description = "付款公司") + private Long companyDeptId; + + @Schema(description = "付款总额") + private BigDecimal paymentTotal; + + @Schema(description = "支付对象") + private String paymentRecipient; + + @Schema(description = "流程实例编号") + private String processInstanceId; + + @Schema(description = "状态-参见 bpm_process_instance_result 枚举") + private Integer result; + + @Schema(description = "上传文件") + private List fileItems; +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOASalaryConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOASalaryConvert.java new file mode 100644 index 00000000..57fd2abe --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOASalaryConvert.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.bpm.convert.oa; + +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary.BpmOASalaryCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary.BpmOASalaryRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalaryDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 用章申请 Convert + * + * @author 符溶馨 + */ +@Mapper +public interface BpmOASalaryConvert { + + BpmOASalaryConvert INSTANCE = Mappers.getMapper(BpmOASalaryConvert.class); + + BpmOASalaryDO convert(BpmOASalaryCreateReqVO bean); + + BpmOASalaryRespVO convert(BpmOASalaryDO bean); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASalaryDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASalaryDO.java new file mode 100644 index 00000000..404311ad --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASalaryDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.math.BigDecimal; +import java.util.List; + +/** + * OA 用章申请 DO + * + * @author 符溶馨 + */ +@TableName(value ="bpm_oa_salary", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BpmOASalaryDO extends BaseDO { + + /** + * 出差表单主键 + */ + @TableId + private Long id; + + /** + * 申请人的用户编号 + * + * 关联 AdminUserDO 的 id 属性 + */ + private Long userId; + + /** + * 申请事由 + */ + private String reason; + + /** + * 付款公司 + */ + private Long companyDeptId; + + /** + * 付款总额 + */ + private BigDecimal paymentTotal; + + /** + * 支付对象 + */ + private String paymentRecipient; + + /** + * 薪资付款申请的结果 + * + * 枚举 {@link BpmProcessInstanceResultEnum} + * 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈 + */ + private Integer result; + + /** + * 对应的流程编号 + * + * 关联 ProcessInstance 的 id 属性 + */ + private String processInstanceId; + + /** + * 附件基本信息 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List fileItems ; +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASealDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASealDO.java index 8e4680e7..cb217e1f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASealDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASealDO.java @@ -73,7 +73,6 @@ public class BpmOASealDO extends BaseDO { /** * 用章的结果 - * * 枚举 {@link BpmProcessInstanceResultEnum} * 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈 */ @@ -81,7 +80,6 @@ public class BpmOASealDO extends BaseDO { /** * 对应的流程编号 - * * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOaSalaryMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOaSalaryMapper.java new file mode 100644 index 00000000..adb53a3d --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOaSalaryMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.bpm.dal.mysql.oa; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalaryDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BpmOaSalaryMapper extends BaseMapperX { +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java new file mode 100644 index 00000000..65dd6a4b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAEntryService; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.context.annotation.Lazy; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; +import static java.util.Collections.emptySet; + +public class BpmTaskEntryLeaderScript implements BpmTaskAssignScript { + + @Resource + private DeptApi deptApi; + @Resource + private BpmOAEntryService entryService; + + @Resource + @Lazy // 解决循环依赖 + private BpmProcessInstanceService bpmProcessInstanceService; + + @Resource + @Lazy // 解决循环依赖 + private BpmTaskService bpmTaskService ; + + @Override + public Set calculateTaskCandidateUsers(DelegateExecution execution) { + + // 获得发起人 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); + List bpmTaskRespVOs = bpmTaskService.getTaskListByProcessInstanceId(processInstance.getProcessInstanceId()); + if (CollUtil.isEmpty(bpmTaskRespVOs)) { + return emptySet(); + } + + //根据流程实例ID 取到调岗流程表单 + BpmOAEntryDO entryDO = entryService.getEntryByProcessInstanceId(processInstance.getProcessInstanceId()); + //获取调岗部门ID + Long deptId = entryDO.getEntryDeptId(); + + //根据部门ID 获取部门信息 + DeptRespDTO dept = deptApi.getDept(deptId).getCheckedData(); + if (dept.getLevel() > 3) { //判断部门层级 + + String [] flag = dept.getFlag().split("-"); + dept = deptApi.getDept(Long.valueOf(flag[3])).getCheckedData(); + } + + return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.LEADER_X7; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASalaryService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASalaryService.java new file mode 100644 index 00000000..a2f25bb7 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASalaryService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.bpm.service.oa; + +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary.BpmOASalaryCreateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalaryDO; + +import javax.validation.Valid; + +/** + * 薪资付款申请 Service 接口 + * + * @author 符溶馨 + */ +public interface BpmOASalaryService { + + /** + * 创建用章申请 + * + * @param userId 用户编号 + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSalary(Long userId, @Valid BpmOASalaryCreateReqVO createReqVO); + + /** + * 更新用章申请的状态 + * + * @param id 编号 + * @param result 结果 + */ + void updateSalaryResult(Long id, Integer result); + + /** + * 获得用章申请 + * + * @param id 编号 + * @return 用章申请 + */ + BpmOASalaryDO getSalary(Long id); + + /** + * 获得指定的用章申请 + * @param processInstanceId 流程实例编号 + * @return 用章申请 + */ + BpmOASalaryDO getByProcessInstanceId(String processInstanceId); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASalaryServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASalaryServiceImpl.java new file mode 100644 index 00000000..3094e878 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASalaryServiceImpl.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.bpm.service.oa; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary.BpmOASalaryCreateReqVO; +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOASalaryConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalaryDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOaSalaryMapper; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * OA 薪资付款申请 Service 实现类 + * + * @author 符溶馨 + */ +@Service +@Validated +public class BpmOASalaryServiceImpl extends BpmOABaseService implements BpmOASalaryService{ + + /** + * OA 薪资付款对应的流程定义 KEY + */ + public static final String PROCESS_KEY = "oa_salary_2"; + + @Resource + private BpmOaSalaryMapper salaryMapper; + + @Resource + private BpmProcessInstanceApi processInstanceApi; + + @Resource + private BpmHistoryProcessInstanceService historyProcessInstanceService; + + @Override + public Long createSalary(Long userId, BpmOASalaryCreateReqVO createReqVO) { + + //插入OA 薪资付款申请 + BpmOASalaryDO salary = BpmOASalaryConvert.INSTANCE.convert(createReqVO).setUserId(userId) + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); + salaryMapper.insert(salary) ; + + // 发起 BPM 流程 + Map processInstanceVariables = new HashMap<>(); + String processInstanceId = processInstanceApi.createProcessInstance(userId, + new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) + .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(salary.getId()))).getCheckedData(); + + // 将工作流的编号,更新到 OA 用章单中 + salaryMapper.updateById(new BpmOASalaryDO().setId(salary.getId()).setProcessInstanceId(processInstanceId)); + + // 判断是否为重新发起的流程 + if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) { + + historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId()); + } + + List fileItems = createReqVO.getFileItems() ; + //这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id + if (fileItems != null && !fileItems.isEmpty()) { + uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ; + } + return salary.getId(); + } + + @Override + public void updateSalaryResult(Long id, Integer result) { + + } + + @Override + public BpmOASalaryDO getSalary(Long id) { + return null; + } + + @Override + public BpmOASalaryDO getByProcessInstanceId(String processInstanceId) { + return null; + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogInstanceController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogInstanceController.java index 14f022b7..a204279c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogInstanceController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogInstanceController.java @@ -209,6 +209,23 @@ public class LogInstanceController { return success(readUserVO); } + @GetMapping("/get-unRead") + @Operation(summary = "获取当前登录用户可查看日志未读的数量") + @PreAuthorize("@ss.hasPermission('system:view-log:query')") + public CommonResult unRead() { + + return success(logReadService.getUnRead(getLoginUserId())); + } + + @PostMapping("/setRead") + @Operation(summary = "一键已读功能") + @PreAuthorize("@ss.hasPermission('system:view-log:query')") + public CommonResult setRead() { + + logReadService.setRead(getLoginUserId()); + return success(true); + } + @GetMapping("/export-excel") @Operation(summary = "导出日志实例 Excel") @PreAuthorize("@ss.hasPermission('system:log-instance:export')") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java index c90ba23a..2525f4c4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java @@ -62,7 +62,7 @@ public interface LogInstanceMapper extends BaseMapperX { queryWrapper.inIfPresent(LogInstanceDO::getStartUserId, userIds); } - return selectPage(reqVO, queryWrapper); + return selectPage(reqVO, queryWrapper.orderByDesc(LogInstanceDO::getTime)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/birthday/BirthdayJob.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/birthday/BirthdayJob.java index d9645c32..4d7ac00b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/birthday/BirthdayJob.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/birthday/BirthdayJob.java @@ -1,11 +1,19 @@ package cn.iocoder.yudao.module.system.job.birthday; +import cn.hutool.json.JSONObject; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi; +import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.context.XxlJobContext; import com.xxl.job.core.handler.annotation.XxlJob; +import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Component; @@ -14,16 +22,27 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Component @Slf4j @EnableScheduling public class BirthdayJob { - @Resource private AdminUserMapper adminUserMapper; + @Resource + private AdminUserService userService; + + @Resource + private PermissionService permissionService; + + @Resource + private SubscribeMessageSendApi subscribeMessageSendApi; + /** * 生日提醒 * @@ -32,15 +51,44 @@ public class BirthdayJob { @XxlJob("birthdayJob") @TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意 public ReturnT execute() { + + // 生日提醒 + birthdayRemind(); + + // 返回执行成功 + return ReturnT.SUCCESS; + } + + private void birthdayRemind() { + String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd")); // -- 获取当天月日 生日的人员列表 List list = adminUserMapper.selectList(new LambdaQueryWrapper() .like(AdminUserDO::getBirthdayDay, time)); if (!list.isEmpty()) { - // TODO: 2024/9/2 发送短信未指定人 - log.info("生日提醒,生日为{},人员为{}", time, list); + + //获取参数 + XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext(); + String jobParam = xxlJobContext.getJobParam(); + if (!StringUtil.isNullOrEmpty(jobParam)) { + + // 解析参数 + JSONObject object = new JSONObject(jobParam); + Long roleId = object.getLong("roleId"); + + Set userIds = permissionService.getUserRoleIdListByRoleId(CollectionUtils.singleton(roleId)); + //获得用户组中 用户信息 + List userDOs = userService.getUserList(userIds); + for (AdminUserDO adminUserDO : userDOs) { + if( adminUserDO.getOpenId() != null && !adminUserDO.getOpenId().isEmpty()) { + + subscribeMessageSendApi.sendCompanyNotice(NoticeConvert.INSTANCE.convertBirthday( + adminUserDO.getOpenId(), "formal")); + } + } + + log.info("生日提醒,生日为{},人员为{}", time, convertList(list, AdminUserDO::getNickname)); + } } - // 返回执行成功 - return ReturnT.SUCCESS; } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/fieldwork/FieldworkJob.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/fieldwork/FieldworkJob.java new file mode 100644 index 00000000..c4ff63d8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/fieldwork/FieldworkJob.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.system.job.fieldwork; + +import cn.hutool.core.collection.CollectionUtil; +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.bpm.api.oa.BpmOAGoOutApi; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +@Component +@Slf4j +@EnableScheduling +public class FieldworkJob { + + @Resource + private AdminUserMapper adminUserMapper; + + @Resource + private BpmOAGoOutApi goOutApi; + + /** + * 外勤打卡权限调整, 针对外出申请流程 + */ + @XxlJob("fieldworkJob") + @TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意 + public ReturnT execute() { + + // 外勤打卡权限变更 + try { + + // 获取用户编号 + Map> goOutList = goOutApi.getLeaveListByTime().getCheckedData(); + + if (CollectionUtil.isNotEmpty(goOutList.get("now"))) { + + // 讲需要当天外出的用户,设置外勤打卡权限 + adminUserMapper.update(new AdminUserDO().setFieldworkFlag(1).setFieldworkType(2), + new LambdaQueryWrapper() + .in(AdminUserDO::getId, goOutList.get("now")) + .ne(AdminUserDO::getFieldworkType, 1)); + } + + if (CollectionUtil.isNotEmpty(goOutList.get("yesterday"))) { + + // 将昨日外出的用户,关闭外勤打卡权限 + adminUserMapper.update(new AdminUserDO().setFieldworkFlag(0).setFieldworkType(0), + new LambdaQueryWrapper() + .in(AdminUserDO::getId, goOutList.get("yesterday")) + .eq(AdminUserDO::getFieldworkType, 2)); + } + }catch (Exception ex) { + log.info(ex.toString()); + } + + // 返回执行成功 + return ReturnT.SUCCESS; + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadService.java index b95522bb..f09137c1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadService.java @@ -49,4 +49,17 @@ public interface LogReadService { * @return 阅读状态 */ Boolean isReadByLogId(Long logId); + + /** + * 获取当前登录用户可查看日志未读的数量 + * @param userId 用户编号 + * @return 未读数量 + */ + Long getUnRead(Long userId); + + /** + * 一键已读 + * @param loginUserId 登录用户编号 + */ + void setRead(Long loginUserId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadServiceImpl.java index 6f72b9eb..90c14ba3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogReadServiceImpl.java @@ -86,4 +86,20 @@ public class LogReadServiceImpl implements LogReadService{ return count > 0L; } + + @Override + public Long getUnRead(Long userId) { + + return logReadMapper.selectCount(new LambdaQueryWrapperX() + .eq(LogReadDo::getReadUserId, userId) + .eq(LogReadDo::getReadStatus, 0)); + } + + @Override + public void setRead(Long loginUserId) { + + logReadMapper.update(new LogReadDo().setReadStatus(1), new LambdaQueryWrapperX() + .eq(LogReadDo::getReadUserId, loginUserId) + .eq(LogReadDo::getReadStatus, 0)); + } }