diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index 90017516..f983d7ce 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -31,6 +31,7 @@ public interface ErrorCodeConstants { ErrorCode OA_SHIFTJOBS_NOT_EXISTS = new ErrorCode(1_009_001_107, "调岗申请不存在"); ErrorCode OA_SECOND_NOT_EXISTS = new ErrorCode(1_009_001_108, "借调申请不存在"); ErrorCode OA_IMPREST_NOT_EXISTS = new ErrorCode(1_009_001_109, "备用金申请不存在"); + ErrorCode OA_INCENTIVE_NOT_EXISTS = new ErrorCode(1_009_001_110, "奖惩申请不存在"); // ========== 流程模型 1-009-002-000 ========== ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1_009_002_000, "已经存在流程标识为【{}】的流程"); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAIncentiveController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAIncentiveController.java new file mode 100644 index 00000000..7c828820 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAIncentiveController.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive.BpmOAIncentiveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive.BpmOAIncentiveRespVO; +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAIncentiveConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAIncentiveDO; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAIncentiveService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +/** + * OA 奖惩申请 Controller + * + * @author 符溶馨 + + */ +@Tag(name = "管理后台 - OA 奖惩申请") +@RestController +@RequestMapping("/bpm/oa/incentive") +@Validated +public class BpmOAIncentiveController { + + @Resource + private BpmOAIncentiveService incentiveService; + + @Resource + private AdminUserApi userApi; + + @Resource + private DeptApi deptApi; + + @PostMapping("/create") + @Operation(summary = "创建请求申请") + public CommonResult createIncentive(@Valid @RequestBody BpmOAIncentiveCreateReqVO createReqVO) { + + return success(incentiveService.createIncentive(getLoginUserId(), createReqVO)); + } + + @GetMapping("/get") + @Operation(summary = "获得奖惩申请") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + public CommonResult getIncentive(@RequestParam("id") Long id) { + + BpmOAIncentiveDO incentive = incentiveService.getIncentive(id); + + //获得 用户信息集合 + List userRespDTO = userApi.getUserListByDeptIds(incentive.getIncentiveDeptIds()).getCheckedData(); + + //获得 部门信息集合 + Map deptRespDTOS = deptApi.getDeptMap(incentive.getIncentiveDeptIds()); + + Map> userInfo = new HashMap<>(); + //遍历 部门map集合 + deptRespDTOS.forEach((key, value) -> { + + List userName = userRespDTO.stream().filter(user -> user.getDeptId().toString().contains(key.toString()) + && incentive.getIncentiveUserIds().contains(user.getId())) + .map(AdminUserRespDTO::getNickname).collect(Collectors.toList()); + + userInfo.put(value.getName(), userName); + }); + + BpmOAIncentiveRespVO bpmOAIncentiveRespVO = BpmOAIncentiveConvert.INSTANCE.convert(incentive); + bpmOAIncentiveRespVO.setUserInfo(userInfo); + return success(bpmOAIncentiveRespVO); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAReimbursementController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAReimbursementController.java index 3ea354d6..5eec7422 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAReimbursementController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAReimbursementController.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.controller.admin.oa; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAReimbursementConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReimbursementService; @@ -34,7 +35,7 @@ public class BpmOAReimbursementController { @PostMapping("/create") // @PreAuthorize("@ss.hasPermission('bpm:oa-reimbursement:create')") @Operation(summary = "创建请求申请") - public CommonResult createLeave(@Valid @RequestBody BpmOAReimbursementCreateReqVO createReqVO) { + public CommonResult createReimbursement(@Valid @RequestBody BpmOAReimbursementCreateReqVO createReqVO) { return success(service.createReimbursement(getLoginUserId(), createReqVO)); } @@ -42,9 +43,10 @@ public class BpmOAReimbursementController { // @PreAuthorize("@ss.hasPermission('bpm:oa-reimbursement:query')") @Operation(summary = "获得报销申请") @Parameter(name = "id", description = "编号", required = true, example = "1024") - public CommonResult getLeave(@RequestParam("id") Long id) { + public CommonResult getReimbursement(@RequestParam("id") Long id) { + BpmOAReimbursementDO reimbursement = service.getReimbursement(id); - return success(BpmOAReimbursementConvert.INSTANCE.convert(reimbursement)); + return success(service.convert(reimbursement)); } // @GetMapping("/page") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/incentive/BpmOAIncentiveCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/incentive/BpmOAIncentiveCreateReqVO.java new file mode 100644 index 00000000..0ec8a73b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/incentive/BpmOAIncentiveCreateReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive; + +import cn.iocoder.yudao.module.bpm.controller.admin.upload.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.LocalDateTime; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 奖惩申请创建 Request VO") +@Data +@EqualsAndHashCode() +@ToString(callSuper = true) +public class BpmOAIncentiveCreateReqVO { + + @Schema(description = "奖惩类型 字典值参考 bpm_oa_incentive_type", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "奖惩类型不能为空") + private Integer type; + + @Schema(description = "奖惩人编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "奖惩人编号不能为空") + private Set incentiveUserIds; + + @Schema(description = "奖惩人部门编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "奖惩人部门编号不能为空") + private Set incentiveDeptIds; + + @Schema(description = "奖惩时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "奖惩时间不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime time; + + @Schema(description = "奖惩金额", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "奖惩金额不能为空") + private BigDecimal amount; + + @Schema(description = "奖惩事由", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "奖惩事由不能为空") + private String reason; + + @Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED) + 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/incentive/BpmOAIncentiveRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/incentive/BpmOAIncentiveRespVO.java new file mode 100644 index 00000000..26a36d40 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/incentive/BpmOAIncentiveRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive; + +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.upload.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 java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 奖惩申请响应数据 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BpmOAIncentiveRespVO extends BpmOABaseRespVO { + + @Schema(description = "奖惩类型 字典值参考 bpm_oa_incentive_type") + private Integer type; + + @Schema(description = "奖惩人信息列表 key:部门名称, value:用户名称集合") + private Map> userInfo; + + @Schema(description = "奖惩时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime time; + + @Schema(description = "奖惩金额") + private BigDecimal amount; + + @Schema(description = "奖惩事由") + private String reason; + + @Schema(description = "上传文件") + 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/print/BpmOAReimbursementPrintDataRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAReimbursementPrintDataRespVO.java index f16845d7..4949b7d2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAReimbursementPrintDataRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAReimbursementPrintDataRespVO.java @@ -1,4 +1,5 @@ package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print; + import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; @@ -21,4 +22,22 @@ public class BpmOAReimbursementPrintDataRespVO extends BpmOABaseRespVO { @Schema(description = "流程审批节点信息【包含人员签名地址】", requiredMode = Schema.RequiredMode.REQUIRED) List processTasks ; + /** + * 抄送用户信息 + */ + private List ccUsers; + + @Schema(description = "抄送用户信息") + @Data + public static class CCUser { + + @Schema(description = "抄送用户编号", example = "146,128") + private Long ccUserId; + + @Schema(description = "抄送用户名称", example = "张三") + private String ccUserName; + + @Schema(description = "抄送用户部门名称", example = "研发部") + private String ccDeptName; + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementCreateReqVO.java index 96abe8cd..68222c36 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementCreateReqVO.java @@ -15,6 +15,15 @@ import java.util.List; @ToString(callSuper = true) public class BpmOAReimbursementCreateReqVO { + @Schema(description = "收款人名称") + private String nickname; + + @Schema(description = "收款人卡号") + private String bankNo; + + @Schema(description = "开户行信息") + private String bankName; + @Schema(description = "报销项目明细", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "报销项目不能为空") private List reimbursements; @@ -40,5 +49,4 @@ public class BpmOAReimbursementCreateReqVO { @Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED) 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/reimbursement/BpmOAReimbursementRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementRespVO.java index 5aa5d23a..c7135e35 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/BpmOAReimbursementRespVO.java @@ -18,14 +18,18 @@ public class BpmOAReimbursementRespVO extends BpmOABaseRespVO { /** * 收款人信息 */ - private PayeeUser payeeUser; + @Schema(description = "收款人名称") + private String nickname; - @Schema(description = "报销费用归属部门ID", requiredMode = Schema.RequiredMode.REQUIRED) - private Long belongDeptId ; + @Schema(description = "开户行信息") + private String bankName; + + @Schema(description = "收款人卡号") + private String bankNo; @Schema(description = "报销项目明细", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "报销项目不能为空") - private List reimbursements; + private List reimbursements; @Schema(description = "报销总金额", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "报销总金额不能为空") @@ -39,7 +43,10 @@ public class BpmOAReimbursementRespVO extends BpmOABaseRespVO { @NotNull(message = "报销类型不能为空") private BigDecimal reimbursementType ; - @Schema(description = "备用金差额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @Schema(description = "备用金金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + private BigDecimal amount ; + + @Schema(description = "备用金差额 = 备用金额 - 报销总金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private BigDecimal difference ; @Schema(description = "报销发票总数", requiredMode = Schema.RequiredMode.REQUIRED) @@ -48,33 +55,4 @@ public class BpmOAReimbursementRespVO extends BpmOABaseRespVO { @Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED) private List fileItems ; - - @Schema(description = "收款人信息") - @Data - public static class PayeeUser { - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") - private String nickname; - - @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long deptId; - - @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") - private String deptName; - - @Schema(description = "电子签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx.jpg") - private String signURL; - - @Schema(description = "用户银行卡业务表ID", requiredMode = Schema.RequiredMode.REQUIRED) - private Long bankId; - - @Schema(description = "开户行信息", requiredMode = Schema.RequiredMode.REQUIRED) - private String bankNName; - - @Schema(description = "银行卡号", requiredMode = Schema.RequiredMode.REQUIRED) - private String bankNo; - } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/Reimbursement.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/Reimbursement.java index 12537820..96445a67 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/Reimbursement.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/Reimbursement.java @@ -15,11 +15,14 @@ import java.util.Date; @Data public class Reimbursement { + @Schema(description = "所属部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "128") + private Long deptId; + @Schema(description = "报销金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "23.45") private BigDecimal money; - @Schema(description = "报销类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "如:住宿、火车票、宴请等") - private String type; + @Schema(description = "报销类别 字典值 参考 bpm_oa_reimbursement_type", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String type; @Schema(description = "发生时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-09 12:31:12") private Date happenTime; @@ -29,4 +32,7 @@ public class Reimbursement { @Schema(description = "费用明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "请吃饭") private String detail ; + + @Schema(description = "采购计划编号", example = "1") + private Long procureId; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/ReimbursementDTO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/ReimbursementDTO.java new file mode 100644 index 00000000..514c3676 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/reimbursement/ReimbursementDTO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 功能描述 报销项目明细 + * 前端返回值用 + */ +@Data +public class ReimbursementDTO { + + @Schema(description = "所属部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "128") + private Long deptId; + + @Schema(description = "所属部门名称", example = "研发部") + private String deptName; + + @Schema(description = "报销金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "23.45") + private BigDecimal money; + + @Schema(description = "报销类别 字典值 参考 bpm_oa_reimbursement_type", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String type; + + @Schema(description = "发生时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-09 12:31:12") + private Date happenTime; + + @Schema(description = "发票张数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + private Integer quantity ; + + @Schema(description = "费用明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "请吃饭") + private String detail ; + + @Schema(description = "采购计划编号", example = "1") + private Long procureId; +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAIncentiveConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAIncentiveConvert.java new file mode 100644 index 00000000..5f25c0be --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAIncentiveConvert.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.bpm.convert.oa; + +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive.BpmOAIncentiveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive.BpmOAIncentiveRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAIncentiveDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 奖惩申请 Convert + * + * @author 符溶馨 + */ +@Mapper +public interface BpmOAIncentiveConvert { + + BpmOAIncentiveConvert INSTANCE = Mappers.getMapper(BpmOAIncentiveConvert.class); + + BpmOAIncentiveDO convert(BpmOAIncentiveCreateReqVO bean); + + BpmOAIncentiveRespVO convert(BpmOAIncentiveDO bean); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAReimbursementConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAReimbursementConvert.java index afff07a8..572fd72f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAReimbursementConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOAReimbursementConvert.java @@ -1,11 +1,18 @@ package cn.iocoder.yudao.module.bpm.convert.oa; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.Reimbursement; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.ReimbursementDTO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.List; +import java.util.Map; + /** * 报销申请 Convert * @@ -18,10 +25,18 @@ public interface BpmOAReimbursementConvert { BpmOAReimbursementDO convert(BpmOAReimbursementCreateReqVO bean); - BpmOAReimbursementRespVO convert(BpmOAReimbursementDO bean); -// -// List convertList(List list); -// -// PageResult convertPage(PageResult page); + default List convertList(List list, Map deptMap) { + + return CollectionUtils.convertList(list, reimbursement -> convert(reimbursement, deptMap.get(reimbursement.getDeptId()))); + } + + default ReimbursementDTO convert(ReimbursementDTO reimbursement, DeptRespDTO dept) { + + if (dept != null) { + reimbursement.setDeptName(dept.getName()); + } + + return reimbursement; + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAIncentiveDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAIncentiveDO.java new file mode 100644 index 00000000..fe26778d --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAIncentiveDO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; +import cn.iocoder.yudao.module.bpm.controller.admin.upload.UploadUserFile; +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.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +/** + * OA 奖惩申请 DO + * + * @author 符溶馨 + */ +@TableName(value ="bpm_oa_incentive", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BpmOAIncentiveDO extends BaseDO { + + + /** + * 出差表单主键 + */ + @TableId + private Long id; + + /** + * 申请人的用户编号 + */ + private Long userId; + + /** + * 奖惩类型 + * 1:奖励 2:惩罚 + */ + private Integer type; + + /** + * 奖惩人用户编号 + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set incentiveUserIds; + + /** + * 奖惩人部门编号 + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set incentiveDeptIds; + + /** + * 奖惩时间 + */ + private LocalDateTime time; + + /** + * 奖惩金额 + */ + private BigDecimal amount; + + /** + * 奖惩事由 + */ + private String reason; + + /** + * 用章的结果 + * + * 枚举 {@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/BpmOAReimbursementDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAReimbursementDO.java index 2440b7c6..fe8741cc 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAReimbursementDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAReimbursementDO.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; import java.math.BigDecimal; +import java.util.LinkedHashMap; import java.util.List; /** @@ -49,6 +50,21 @@ public class BpmOAReimbursementDO extends BaseDO { */ private Long userId; + /** + * 收款人名称 + */ + private String nickname; + + /** + * 收款人卡号 + */ + private String bankNo; + + /** + * 开户行信息 + */ + private String bankName; + /** * 报销明细数据JSON */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAIncentiveMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAIncentiveMapper.java new file mode 100644 index 00000000..9bccea9b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAIncentiveMapper.java @@ -0,0 +1,15 @@ +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.BpmOAIncentiveDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 奖惩申请 Mapper + * + * @author 符溶馨 + + */ +@Mapper +public interface BpmOAIncentiveMapper extends BaseMapperX { +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAIncentiveService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAIncentiveService.java new file mode 100644 index 00000000..f6b3b9bb --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAIncentiveService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.bpm.service.oa; + +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.incentive.BpmOAIncentiveCreateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAIncentiveDO; + +import javax.validation.Valid; + +/** + * 奖惩申请 Service 接口 + * + * @author 符溶馨 + + */ +public interface BpmOAIncentiveService { + + /** + * 创建奖惩申请 + * + * @param userId 用户编号 + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createIncentive(Long userId, @Valid BpmOAIncentiveCreateReqVO createReqVO); + + /** + * 更新奖惩申请的状态 + * + * @param id 编号 + * @param result 结果 + */ + void updateIncentiveResult(Long id, Integer result); + + /** + * 获得奖惩申请 + * + * @param id 编号 + * @return 奖惩申请 + */ + BpmOAIncentiveDO getIncentive(Long id); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAIncentiveServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAIncentiveServiceImpl.java new file mode 100644 index 00000000..ddaa01b7 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAIncentiveServiceImpl.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.bpm.service.oa; + +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.incentive.BpmOAIncentiveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.upload.UploadUserFile; +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAIncentiveConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAIncentiveDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAIncentiveMapper; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +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; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_INCENTIVE_NOT_EXISTS; + +/** + * OA 奖惩申请 Service 实现类 + * + * @author 符溶馨 + + */ +@Service +@Validated +public class BpmOAIncentiveServiceImpl extends BpmOABaseService implements BpmOAIncentiveService{ + + /** + * OA 奖惩对应的流程定义 KEY + */ + public static final String PROCESS_KEY = "oa_incentive"; + + @Resource + private BpmOAIncentiveMapper incentiveMapper; + + @Resource + private BpmProcessInstanceApi processInstanceApi; + + @Override + public Long createIncentive(Long userId, BpmOAIncentiveCreateReqVO createReqVO) { + + //插入OA 奖惩申请 + BpmOAIncentiveDO incentive = BpmOAIncentiveConvert.INSTANCE.convert(createReqVO).setUserId(userId) + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); + incentiveMapper.insert(incentive) ; + + // 发起 BPM 流程 + Map processInstanceVariables = new HashMap<>(); + String processInstanceId = processInstanceApi.createProcessInstance(userId, + new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) + .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(incentive.getId()))).getCheckedData(); + + // 将工作流的编号,更新到 OA 奖惩单中 + incentiveMapper.updateById(new BpmOAIncentiveDO().setId(incentive.getId()).setProcessInstanceId(processInstanceId)); + + List fileItems = createReqVO.getFileItems() ; + //这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id + if (fileItems != null && !fileItems.isEmpty()) { + uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ; + } + return incentive.getId(); + } + + @Override + public void updateIncentiveResult(Long id, Integer result) { + + validateLeaveExists(id); + incentiveMapper.updateById(new BpmOAIncentiveDO().setId(id).setResult(result)); + } + + private void validateLeaveExists(Long id) { + if (incentiveMapper.selectById(id) == null) { + throw exception(OA_INCENTIVE_NOT_EXISTS); + } + } + + @Override + public BpmOAIncentiveDO getIncentive(Long id) { + + return incentiveMapper.selectById(id); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementService.java index 823e6519..57cd37eb 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.oa; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; import javax.validation.Valid; @@ -40,13 +41,5 @@ public interface BpmOAReimbursementService { */ BpmOAReimbursementDO getReimbursement(Long id); - /** - * 获得请假申请分页 - * - * @param userId 用户编号 - * @param pageReqVO 分页查询 - * @return 请假申请分页 - */ -// PageResult getLeavePage(Long userId, BpmOALeavePageReqVO pageReqVO); - + BpmOAReimbursementRespVO convert(BpmOAReimbursementDO bpmOAReimbursementDO); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementServiceImpl.java index 5a59007b..9f367af5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAReimbursementServiceImpl.java @@ -1,16 +1,27 @@ package cn.iocoder.yudao.module.bpm.service.oa; +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.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.procure.BpmOAProcureListEditReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.Reimbursement; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.ReimbursementDTO; import cn.iocoder.yudao.module.bpm.controller.admin.upload.UploadUserFile; import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAReimbursementConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAImprestDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAProcureDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAImprestMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAReimbursementMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -18,11 +29,10 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_REIMBURSEMENT_NOT_EXISTS; /** @@ -57,6 +67,15 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B @Resource private BpmOAImprestMapper bpmOAImprestMapper; + @Resource + private BpmOAProcureService bpmOAProcureService; + + @Resource + private DeptApi deptApi; + + @Resource + private AdminUserApi userApi; + @Override public Long createReimbursement(Long userId, BpmOAReimbursementCreateReqVO createReqVO) { BpmOAReimbursementDO reimbursement = BpmOAReimbursementConvert.INSTANCE.convert(createReqVO).setUserId(userId) @@ -78,6 +97,31 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(bpmOAImprestDO.getId()).setReimbursementId(reimbursement.getId()).setStatus(BpmOAImprestDO.IN_PROGRESS)); } + //判断是否有 采购报销 + List procureIds = new ArrayList<>(); + for (Reimbursement data : reimbursement.getReimbursements()) { + + //报销类别为 采购费时 + if ("4".equals(data.getType())) { + + BpmOAProcureDO procureDO = bpmOAProcureService.getOaProcure(data.getProcureId()); + if (procureDO != null) { + + procureIds.add(procureDO.getId()); + } + } + } + + if (!procureIds.isEmpty()) { + + //所有关联的采购申请改为 进行中状态 + bpmOAProcureService.updatePayFlagByIds( + new BpmOAProcureListEditReqVO() + .setPayFlag(BpmOAProcureDO.IN_PROGRESS) + .setProcureIds(procureIds) + ); + } + List fileItems = createReqVO.getFileItems() ; //这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id if (fileItems != null && !fileItems.isEmpty()) { @@ -95,12 +139,49 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) { ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId); - BpmOAImprestDO bpmOAImprestDO = bpmOAImprestMapper.selectOne(BpmOAImprestDO::getReimbursementId, id); - if (instance.isEnded() && bpmOAImprestDO != null) { + if (instance.isEnded()) { - //将相应备用金申请状态改为 已报销 - bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(bpmOAImprestDO.getId()).setStatus(BpmOAImprestDO.FLAG_TRUE)); + //获得备用金信息 + BpmOAImprestDO bpmOAImprestDO = bpmOAImprestMapper.selectOne(BpmOAImprestDO::getReimbursementId, id); + if (bpmOAImprestDO != null) { + + //将相应备用金申请状态改为 已报销 + bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(bpmOAImprestDO.getId()).setStatus(BpmOAImprestDO.FLAG_TRUE)); + } + + //判断是否有采购报销 + List procureIds = new ArrayList<>(); + BpmOAReimbursementDO bpmOAReimbursementDO = getReimbursement(id); + List reimbursements = bpmOAReimbursementDO.getReimbursements(); + + //直接从数据库取出来的List 实际上是List类型 所以不能直接遍历 + //将list再次转为json串,然后由json串再转为list + String json = JsonUtils.toJsonString(reimbursements); + reimbursements = JsonUtils.parseArray(json, Reimbursement.class); + + for (Reimbursement reimbursement : reimbursements) { + + //报销类别为 采购费时 + if ("4".equals(reimbursement.getType())) { + + BpmOAProcureDO procureDO = bpmOAProcureService.getOaProcure(reimbursement.getProcureId()); + if (procureDO != null) { + + procureIds.add(procureDO.getId()); + } + } + } + + if (!procureIds.isEmpty()) { + + //所有关联的采购申请改为 已支付状态 + bpmOAProcureService.updatePayFlagByIds( + new BpmOAProcureListEditReqVO() + .setPayFlag(BpmOAProcureDO.FLAG_TRUE) + .setProcureIds(procureIds) + ); + } } } @@ -118,6 +199,39 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B //将相应备用金申请状态改为 未报销 bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(bpmOAImprestDO.getId()).setStatus(BpmOAImprestDO.FLAG_FALSE)); } + + //判断是否有采购报销 + List procureIds = new ArrayList<>(); + BpmOAReimbursementDO bpmOAReimbursementDO = getReimbursement(id); + List reimbursements = bpmOAReimbursementDO.getReimbursements(); + + //直接从数据库取出来的List 实际上是List类型 所以不能直接遍历 + //将list再次转为json串,然后由json串再转为list + String json = JsonUtils.toJsonString(reimbursements); + reimbursements = JsonUtils.parseArray(json, Reimbursement.class); + + for (Reimbursement reimbursement : reimbursements) { + + //报销类别为 采购费时 + if ("4".equals(reimbursement.getType())) { + + BpmOAProcureDO procureDO = bpmOAProcureService.getOaProcure(reimbursement.getProcureId()); + if (procureDO != null) { + + procureIds.add(procureDO.getId()); + } + } + } + + if (!procureIds.isEmpty()) { + + //所有关联的采购申请改为 未支付状态 + bpmOAProcureService.updatePayFlagByIds( + new BpmOAProcureListEditReqVO() + .setPayFlag(BpmOAProcureDO.FLAG_FALSE) + .setProcureIds(procureIds) + ); + } } reimbursementMapper.updateById(new BpmOAReimbursementDO().setId(id).setResult(result)); @@ -131,6 +245,39 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B @Override public BpmOAReimbursementDO getReimbursement(Long id) { + return reimbursementMapper.selectById(id); } -} + + @Override + public BpmOAReimbursementRespVO convert(BpmOAReimbursementDO reimbursementDO) { + + List reimbursement = reimbursementDO.getReimbursements(); + + //直接从数据库取出来的List 实际上是List类型 所以不能直接遍历 + //将list再次转为json串,然后由json串再转为list + String json = JsonUtils.toJsonString(reimbursement); + reimbursement = JsonUtils.parseArray(json, Reimbursement.class); + + //针对之前的数据, 没有设置明细所属部门的 手动设置发起人的部门编号 + AdminUserRespDTO userRespDTO = userApi.getUser(reimbursementDO.getUserId()).getCheckedData(); + for (Reimbursement data : reimbursement) { + + if (data.getDeptId() != null) { + break; + } + + data.setDeptId(userRespDTO.getDeptId()); + } + + //获取部门信息map + Map deptMap = deptApi.getDeptMap(convertSet(reimbursement, Reimbursement::getDeptId)); + + List reimbursementDTOS = BeanUtils.toBean(reimbursement, ReimbursementDTO.class); + + BpmOAReimbursementRespVO bpmOAReimbursementRespVO = BeanUtils.toBean(reimbursementDO, BpmOAReimbursementRespVO.class); + bpmOAReimbursementRespVO.setReimbursements(BpmOAReimbursementConvert.INSTANCE.convertList(reimbursementDTOS, deptMap)); //拼接数据 + + return bpmOAReimbursementRespVO; + } +} \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAIncentiveResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAIncentiveResultListener.java new file mode 100644 index 00000000..a0ec11bd --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAIncentiveResultListener.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.bpm.service.oa.listener; + +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventListener; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAIncentiveService; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAIncentiveServiceImpl; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * OA 奖惩的结果的监听器实现类 + * + * @author 符溶馨 + */ +@Component +public class BpmOAIncentiveResultListener extends BpmProcessInstanceResultEventListener { + + @Resource + private BpmOAIncentiveService incentiveService; + + @Override + protected String getProcessDefinitionKey() { + return BpmOAIncentiveServiceImpl.PROCESS_KEY; + } + + @Override + protected void onEvent(BpmProcessInstanceResultEvent event) { + incentiveService.updateIncentiveResult(Long.parseLong(event.getBusinessKey()), event.getResult()); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 91eb6372..db9fc2f8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1 +1 @@ -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmOAReimbursementPrintDataRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstancePrintDataReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstancePrintDataRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAReimbursementConvert; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmConstants; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReimbursementService; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.lang.reflect.Field; import java.text.DecimalFormat; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private TaskService engineTaskService; @Resource private BpmTaskAssignRuleMapper taskRuleMapper; @Resource private BpmUserGroupService userGroupService; @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource @Lazy // 解决循环依赖 private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); List ids = taskMap.values().stream() .flatMap(Collection::stream) .map(Task::getAssignee) .collect(Collectors.toList()); Iterator iterator = ids.iterator(); while (iterator.hasNext()) { String id = iterator.next(); if (id == null) { iterator.remove(); } } List longIds = ids.stream() .map(Long::valueOf) .collect(Collectors.toList()); // 获得 User Map Map userMap = adminUserApi.getUserMap(longIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap, userMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())).getCheckedData(); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()).getCheckedData(); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); Map processVariables = runtimeService.getVariables(instance.getProcessInstanceId()); String reason = (String)processVariables.get("approve_reason") ; // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance,reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); /** 创建流程后,添加抄送人 End add by yj 2024.1.4 */ processCCToUsers(definition,instance) ; /** 通过自己发起的流程 */ approveSelfTask(instance.getId()) ; return instance.getId(); } private void approveSelfTask(String processInstanceId ) { List tasks =engineTaskService.createTaskQuery().processInstanceId(processInstanceId).list() ; if( tasks != null && tasks.size() > 0) { Task task = tasks.get(0) ; String assigneeId = task.getAssignee(); //如果当前登陆用户是审批人,那么自动审批通过 if( assigneeId.equals( SecurityFrameworkUtils.getLoginUserId().toString() )) { BpmTaskApproveReqVO reqVO = new BpmTaskApproveReqVO() ; reqVO.setId(task.getId()) ; reqVO.setReason(BpmConstants.AUTO_APPRAVAL); taskService.approveTask(getLoginUserId(), reqVO); } } } /** * 获得抄送我的流程实例的分页 * * @param userId 用户编号 * @param pageReqVO 分页请求 * @return 流程实例的分页 */ public PageResult getMyCCProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectCCPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap,null); } public List getProcessInstancesGroupByModelName(BpmProcessInstanceStatisticsReqVO pageReqVO){ pageReqVO = getUserids(pageReqVO) ; return processInstanceExtMapper.getProcessInstancesGroupByModelName(pageReqVO) ; } public List getProcessInstancesGroupByResultStatus(BpmProcessInstanceStatisticsReqVO pageReqVO){ pageReqVO = getUserids(pageReqVO) ; return processInstanceExtMapper.getProcessInstancesGroupByResultStatus(pageReqVO) ; } public PageResult getStatisticsProcessInstancePage(@Valid BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectStatisticePage(pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); List ids = taskMap.values().stream() .flatMap(Collection::stream) .map(Task::getAssignee) .collect(Collectors.toList()); Iterator iterator = ids.iterator(); while (iterator.hasNext()) { String id = iterator.next(); if (id == null) { iterator.remove(); } } List longIds = ids.stream() .map(Long::valueOf) .collect(Collectors.toList()); //获得 审批人 User Map Map assigneeUserMap = adminUserApi.getUserMap(longIds); //获得 发起人 User Map List bpieDOs = pageResult.getList() ; longIds = new ArrayList<>() ; for (BpmProcessInstanceExtDO bpieDO: bpieDOs) { longIds.add(bpieDO.getStartUserId()) ; } Map startUserMap = adminUserApi.getUserMap(longIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertStatisticsPage(pageResult, taskMap, assigneeUserMap,startUserMap); } @Resource PermissionApi permissionApi; /** * 根据数据权限,查询关联操作的用户IDS * @param pageReqVO * @return * @param */ private T getUserids(T pageReqVO) { try { Class clazz = (Class) pageReqVO.getClass(); Field idField = clazz.getDeclaredField("userIds"); idField.setAccessible(true); // 设置可访问性 Long[] userIds = null; Long userId = WebFrameworkUtils.getLoginUserId(); DeptDataPermissionRespDTO deptDataPermission = permissionApi.getDeptDataPermission(userId).getCheckedData(); //查询全部 if (deptDataPermission.getAll()) { //idField.set(pageReqVO, null); // 设置属性值 return pageReqVO; } // 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限 if (CollUtil.isEmpty(deptDataPermission.getDeptIds()) && Boolean.FALSE.equals(deptDataPermission.getSelf())) { //设置成0,一个不存在的用户Id,就查询不到数据了。 userIds = new Long[]{0L}; idField.set(pageReqVO, userIds); return pageReqVO; } //情况三 至查询自己 if (deptDataPermission.getSelf()) { userIds = new Long[]{userId}; idField.set(pageReqVO, userIds); return pageReqVO; } Set deptIds = deptDataPermission.getDeptIds(); //查询部门关联的用户Id List users = adminUserApi.getUserListByDeptIds(deptIds).getCheckedData(); List tempList = new ArrayList<>(); for (AdminUserRespDTO user : users) { Long id = user.getId(); tempList.add(id); } tempList.add(userId); userIds = tempList.stream().toArray(Long[]::new); //将临时的List集合转换成数组集合 idField.set(pageReqVO, userIds); return pageReqVO; }catch (Exception exception){ exception.printStackTrace(); throw exception(BPM_SYSTEM_BUG); } } /** * /创建流程后,添加抄送人 Begin add by yj 2024.1.4 * 在设计流程的时候,需要添加一个任务块 名字必须叫Activity_cc 分配权限的时候,需要选择用户组。 * * @param definition * @param instance */ private void processCCToUsers(ProcessDefinition definition, ProcessInstance instance) { //获取bpm_task_assign_reule (Bpm 任务规则表)的流程中有没有配置抄送节点 固定抄送名称为:Activity_cc String processDefinitionId = definition.getId() ; List rules = taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, null); for(BpmTaskAssignRuleDO rule :rules ){ String key = rule.getTaskDefinitionKey() ; //任务名称 Integer type = rule.getType() ; if( !key.isEmpty() && key.equals(BpmConstants.CC_NAME) && type == 40 ) { StringBuffer str = new StringBuffer() ; Set options = rule.getOptions() ; List list = new ArrayList(options); for(Long groupId : list) { //需要根据这个groupId,查询这个组中的用户id BpmUserGroupDO userGroup = userGroupService.getUserGroup(groupId); Set userIds = userGroup.getMemberUserIds() ; List userIdList = new ArrayList(userIds); for(Long user_id : userIdList) { str.append("[").append(user_id).append("]") ; } } String ccids = str.toString() ; //根据processDefinitionId 将ccids保存到bpm_process_instance_ext中的ccids字段 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessDefinitionId(processDefinitionId) .setCcids(ccids) .setProcessInstanceId(instance.getProcessInstanceId()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); break ; } } } @Resource private BpmTaskExtMapper taskExtMapper; @Override public List getUserProcessTpo10(BpmProcessInstanceStatisticsReqVO pageReqVO) { //按审核人分组查询,统计已完成流程数量及平均耗时间 List respVOS = processInstanceExtMapper.getUserProcessTpo10(pageReqVO); if( respVOS == null || respVOS.size() == 0) { return null ; } List idList = respVOS.stream() .map(BpmProcessFinishStatisticsRespVO::getUserId) .collect(Collectors.toList()); //根据userId,查询UserMap Map userMap = adminUserApi.getUserMap(idList) ; Long[] idsArray = new Long[userMap.size()]; // 使用 map 的 keySet() 方法获取键集合 Set keys = userMap.keySet(); // 遍历键集合,将每个键添加到数组中 int index = 0; for (Long key : keys) { idsArray[index++] = key; } pageReqVO.setUserIds(idsArray) ; //按审核人分组查询,未审批完成的流程数量 List bpmTaskExtDOs = processInstanceExtMapper.selectUnfinishProcessCount( pageReqVO ) ; //按审核人分组查询,未完成的记录数 Map unFinfishCountCountMap = new HashMap<>(); for (BpmProcessFinishStatisticsRespVO item : bpmTaskExtDOs) { unFinfishCountCountMap.put(item.getUserId(), item.getUnFinfishCount()); } respVOS.forEach(respVO -> respVO.setName( userMap.get(respVO.getUserId()).getNickname())); respVOS.forEach(respVO -> respVO.setUnFinfishCount( unFinfishCountCountMap.get(respVO.getUserId()))); //获取排行榜第一记录的耗时,作为基础数据 double num = Double.parseDouble(respVOS.get(0).getUserTime()); // 先将字符串转换为双精度浮点数 int baseNumber = (int)num; // 再通过类型转换操作符将其转换为整数 DecimalFormat df = new DecimalFormat("#.00"); respVOS.forEach(respVO -> { //格式化流程完成率 float finfishCount = (float) respVO.getFinfishCount() ; float unFinfishCount = respVO.getUnFinfishCount() == null ? 0: respVO.getUnFinfishCount(); float all = finfishCount + unFinfishCount ; float result = finfishCount / all; float rate = result * 100 ; respVO.setCompletionRate(df.format(rate)+"%") ; double dValue = Double.parseDouble(respVO.getUserTime()); // 将字符串转换为double类型 int roundedValue = (int) Math.round(dValue); // 使用Math.round()进行四舍五入,并转换为int类型 respVO.setUserTime(roundedValue+"") ; //格式化进度百度比, 参照最高的数据进行百分比显示 double percentage = ((int)Double.parseDouble(respVO.getUserTime()) / (double) baseNumber) * 100; respVO.setPercentage((int) Math.round(percentage)) ; //设置未完成 respVO.setUnFinfishCount( Integer.valueOf((int)unFinfishCount)) ; }); return respVOS ; } @Override public BpmProcessInstanceExtDO getProcessInstanceDO(String id) { return processInstanceExtMapper.selectByProcessInstanceId(id); } @Resource private FileApi fileApi; @Resource @Lazy // 解决循环依赖 private BpmOAReimbursementService reimbursementService; @Override public BpmProcessInstancePrintDataRespVO getOAReportPrintData(BpmProcessInstancePrintDataReqVO reqVO) { BpmProcessInstancePrintDataRespVO bpmProcessInstancePrintDataRespVO = new BpmProcessInstancePrintDataRespVO() ; String key = reqVO.getKey() ; //流程标识 String processInstanceId = reqVO.getId() ; //流程实例ID bpmProcessInstancePrintDataRespVO.setId(processInstanceId) ; bpmProcessInstancePrintDataRespVO.setKey(key) ; BpmProcessInstanceRespVO bpmProcessInstance = getProcessInstanceVO(processInstanceId) ; Long businessKey = Long.valueOf(bpmProcessInstance.getBusinessKey()); //流程业务表-主键ID if(key.equals("oa_reimbursement")) { //报销流程 BpmOAReimbursementDO reimbursement = reimbursementService.getReimbursement(businessKey); BpmOAReimbursementRespVO bpmOAReimbursementRespVO = BpmOAReimbursementConvert.INSTANCE.convert(reimbursement); //报销业务数据 List taskRespVOList = taskService.getTaskListByProcessInstanceId(processInstanceId) ; //报销审核人数据 //给User添加签名地址 taskRespVOList.forEach(taskRespVO -> taskRespVO.getAssigneeUser().setSignURL( fileApi.getUserSignImgPath( taskRespVO.getAssigneeUser().getId() ).getData() ) ); BpmOAReimbursementPrintDataRespVO reimbursementPrintData = new BpmOAReimbursementPrintDataRespVO() ; reimbursementPrintData.setBpmOAReimbursementRespVO(bpmOAReimbursementRespVO) ; reimbursementPrintData.setProcessTasks(taskRespVOList) ; bpmProcessInstancePrintDataRespVO.setBpmOAReimbursementPrintDataRespVO(reimbursementPrintData) ; } return bpmProcessInstancePrintDataRespVO ; } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmOAReimbursementPrintDataRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstancePrintDataReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstancePrintDataRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAReimbursementConvert; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAImprestDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmConstants; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAImprestService; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAProcureServiceImpl; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReimbursementService; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.lang.reflect.Field; import java.text.DecimalFormat; import java.time.LocalDateTime; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; 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.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private TaskService engineTaskService; @Resource private BpmTaskAssignRuleMapper taskRuleMapper; @Resource private BpmUserGroupService userGroupService; @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource @Lazy // 解决循环依赖 private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); List ids = taskMap.values().stream() .flatMap(Collection::stream) .map(Task::getAssignee) .collect(Collectors.toList()); Iterator iterator = ids.iterator(); while (iterator.hasNext()) { String id = iterator.next(); if (id == null) { iterator.remove(); } } List longIds = ids.stream() .map(Long::valueOf) .collect(Collectors.toList()); // 获得 User Map Map userMap = adminUserApi.getUserMap(longIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap, userMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())).getCheckedData(); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()).getCheckedData(); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); Map processVariables = runtimeService.getVariables(instance.getProcessInstanceId()); String reason = (String)processVariables.get("approve_reason") ; // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance,reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); /** 创建流程后,添加抄送人 End add by yj 2024.1.4 */ processCCToUsers(definition,instance) ; /** 通过自己发起的流程 */ approveSelfTask(instance.getId()) ; return instance.getId(); } private void approveSelfTask(String processInstanceId ) { List tasks =engineTaskService.createTaskQuery().processInstanceId(processInstanceId).list() ; if( tasks != null && tasks.size() > 0) { Task task = tasks.get(0) ; String assigneeId = task.getAssignee(); //如果当前登陆用户是审批人,那么自动审批通过 if( assigneeId.equals( SecurityFrameworkUtils.getLoginUserId().toString() )) { BpmTaskApproveReqVO reqVO = new BpmTaskApproveReqVO() ; reqVO.setId(task.getId()) ; reqVO.setReason(BpmConstants.AUTO_APPRAVAL); taskService.approveTask(getLoginUserId(), reqVO); } } } /** * 获得抄送我的流程实例的分页 * * @param userId 用户编号 * @param pageReqVO 分页请求 * @return 流程实例的分页 */ public PageResult getMyCCProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectCCPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap,null); } public List getProcessInstancesGroupByModelName(BpmProcessInstanceStatisticsReqVO pageReqVO){ pageReqVO = getUserids(pageReqVO) ; return processInstanceExtMapper.getProcessInstancesGroupByModelName(pageReqVO) ; } public List getProcessInstancesGroupByResultStatus(BpmProcessInstanceStatisticsReqVO pageReqVO){ pageReqVO = getUserids(pageReqVO) ; return processInstanceExtMapper.getProcessInstancesGroupByResultStatus(pageReqVO) ; } public PageResult getStatisticsProcessInstancePage(@Valid BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectStatisticePage(pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); List ids = taskMap.values().stream() .flatMap(Collection::stream) .map(Task::getAssignee) .collect(Collectors.toList()); Iterator iterator = ids.iterator(); while (iterator.hasNext()) { String id = iterator.next(); if (id == null) { iterator.remove(); } } List longIds = ids.stream() .map(Long::valueOf) .collect(Collectors.toList()); //获得 审批人 User Map Map assigneeUserMap = adminUserApi.getUserMap(longIds); //获得 发起人 User Map List bpieDOs = pageResult.getList() ; longIds = new ArrayList<>() ; for (BpmProcessInstanceExtDO bpieDO: bpieDOs) { longIds.add(bpieDO.getStartUserId()) ; } Map startUserMap = adminUserApi.getUserMap(longIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertStatisticsPage(pageResult, taskMap, assigneeUserMap,startUserMap); } @Resource PermissionApi permissionApi; /** * 根据数据权限,查询关联操作的用户IDS * @param pageReqVO * @return * @param */ private T getUserids(T pageReqVO) { try { Class clazz = (Class) pageReqVO.getClass(); Field idField = clazz.getDeclaredField("userIds"); idField.setAccessible(true); // 设置可访问性 Long[] userIds = null; Long userId = WebFrameworkUtils.getLoginUserId(); DeptDataPermissionRespDTO deptDataPermission = permissionApi.getDeptDataPermission(userId).getCheckedData(); //查询全部 if (deptDataPermission.getAll()) { //idField.set(pageReqVO, null); // 设置属性值 return pageReqVO; } // 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限 if (CollUtil.isEmpty(deptDataPermission.getDeptIds()) && Boolean.FALSE.equals(deptDataPermission.getSelf())) { //设置成0,一个不存在的用户Id,就查询不到数据了。 userIds = new Long[]{0L}; idField.set(pageReqVO, userIds); return pageReqVO; } //情况三 至查询自己 if (deptDataPermission.getSelf()) { userIds = new Long[]{userId}; idField.set(pageReqVO, userIds); return pageReqVO; } Set deptIds = deptDataPermission.getDeptIds(); //查询部门关联的用户Id List users = adminUserApi.getUserListByDeptIds(deptIds).getCheckedData(); List tempList = new ArrayList<>(); for (AdminUserRespDTO user : users) { Long id = user.getId(); tempList.add(id); } tempList.add(userId); userIds = tempList.stream().toArray(Long[]::new); //将临时的List集合转换成数组集合 idField.set(pageReqVO, userIds); return pageReqVO; }catch (Exception exception){ exception.printStackTrace(); throw exception(BPM_SYSTEM_BUG); } } /** * /创建流程后,添加抄送人 Begin add by yj 2024.1.4 * 在设计流程的时候,需要添加一个任务块 名字必须叫Activity_cc 分配权限的时候,需要选择用户组。 * * @param definition * @param instance */ private void processCCToUsers(ProcessDefinition definition, ProcessInstance instance) { //获取bpm_task_assign_reule (Bpm 任务规则表)的流程中有没有配置抄送节点 固定抄送名称为:Activity_cc String processDefinitionId = definition.getId() ; List rules = taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, null); for(BpmTaskAssignRuleDO rule :rules ){ String key = rule.getTaskDefinitionKey() ; //任务名称 Integer type = rule.getType() ; if( !key.isEmpty() && key.equals(BpmConstants.CC_NAME) && type == 40 ) { StringBuffer str = new StringBuffer() ; Set options = rule.getOptions() ; List list = new ArrayList(options); for(Long groupId : list) { //需要根据这个groupId,查询这个组中的用户id BpmUserGroupDO userGroup = userGroupService.getUserGroup(groupId); Set userIds = userGroup.getMemberUserIds() ; List userIdList = new ArrayList(userIds); for(Long user_id : userIdList) { str.append("[").append(user_id).append("]") ; } } //流程是采购计划时 if (definition.getKey().equals(BpmOAProcureServiceImpl.PROCESS_KEY)) { AdminUserRespDTO userRespDTO = adminUserApi.getUser(Long.valueOf(instance.getStartUserId())).getCheckedData(); DeptRespDTO deptRespDTO = deptApi.getDept(userRespDTO.getDeptId()).getCheckedData(); //发起人部门为 生产部及以下时 if (deptRespDTO.getFlag().contains("130")) { //添加 供应部抄送 BpmUserGroupDO userGroup = userGroupService.getUserGroup(121L); Set userIds = userGroup.getMemberUserIds() ; List userIdList = new ArrayList(userIds); for(Long user_id : userIdList) { str.append("[").append(user_id).append("]") ; } } } String ccids = str.toString() ; //根据processDefinitionId 将ccids保存到bpm_process_instance_ext中的ccids字段 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessDefinitionId(processDefinitionId) .setCcids(ccids) .setProcessInstanceId(instance.getProcessInstanceId()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); break ; } } } @Resource private BpmTaskExtMapper taskExtMapper; @Override public List getUserProcessTpo10(BpmProcessInstanceStatisticsReqVO pageReqVO) { //按审核人分组查询,统计已完成流程数量及平均耗时间 List respVOS = processInstanceExtMapper.getUserProcessTpo10(pageReqVO); if( respVOS == null || respVOS.size() == 0) { return null ; } List idList = respVOS.stream() .map(BpmProcessFinishStatisticsRespVO::getUserId) .collect(Collectors.toList()); //根据userId,查询UserMap Map userMap = adminUserApi.getUserMap(idList) ; Long[] idsArray = new Long[userMap.size()]; // 使用 map 的 keySet() 方法获取键集合 Set keys = userMap.keySet(); // 遍历键集合,将每个键添加到数组中 int index = 0; for (Long key : keys) { idsArray[index++] = key; } pageReqVO.setUserIds(idsArray) ; //按审核人分组查询,未审批完成的流程数量 List bpmTaskExtDOs = processInstanceExtMapper.selectUnfinishProcessCount( pageReqVO ) ; //按审核人分组查询,未完成的记录数 Map unFinfishCountCountMap = new HashMap<>(); for (BpmProcessFinishStatisticsRespVO item : bpmTaskExtDOs) { unFinfishCountCountMap.put(item.getUserId(), item.getUnFinfishCount()); } respVOS.forEach(respVO -> respVO.setName( userMap.get(respVO.getUserId()).getNickname())); respVOS.forEach(respVO -> respVO.setUnFinfishCount( unFinfishCountCountMap.get(respVO.getUserId()))); //获取排行榜第一记录的耗时,作为基础数据 double num = Double.parseDouble(respVOS.get(0).getUserTime()); // 先将字符串转换为双精度浮点数 int baseNumber = (int)num; // 再通过类型转换操作符将其转换为整数 DecimalFormat df = new DecimalFormat("#.00"); respVOS.forEach(respVO -> { //格式化流程完成率 float finfishCount = (float) respVO.getFinfishCount() ; float unFinfishCount = respVO.getUnFinfishCount() == null ? 0: respVO.getUnFinfishCount(); float all = finfishCount + unFinfishCount ; float result = finfishCount / all; float rate = result * 100 ; respVO.setCompletionRate(df.format(rate)+"%") ; double dValue = Double.parseDouble(respVO.getUserTime()); // 将字符串转换为double类型 int roundedValue = (int) Math.round(dValue); // 使用Math.round()进行四舍五入,并转换为int类型 respVO.setUserTime(roundedValue+"") ; //格式化进度百度比, 参照最高的数据进行百分比显示 double percentage = ((int)Double.parseDouble(respVO.getUserTime()) / (double) baseNumber) * 100; respVO.setPercentage((int) Math.round(percentage)) ; //设置未完成 respVO.setUnFinfishCount( Integer.valueOf((int)unFinfishCount)) ; }); return respVOS ; } @Override public BpmProcessInstanceExtDO getProcessInstanceDO(String id) { return processInstanceExtMapper.selectByProcessInstanceId(id); } @Resource private FileApi fileApi; @Resource @Lazy // 解决循环依赖 private BpmOAReimbursementService reimbursementService; @Resource @Lazy // 解决循环依赖 private BpmOAImprestService imprestService; @Override public BpmProcessInstancePrintDataRespVO getOAReportPrintData(BpmProcessInstancePrintDataReqVO reqVO) { BpmProcessInstancePrintDataRespVO bpmProcessInstancePrintDataRespVO = new BpmProcessInstancePrintDataRespVO() ; String key = reqVO.getKey() ; //流程标识 String processInstanceId = reqVO.getId() ; //流程实例ID bpmProcessInstancePrintDataRespVO.setId(processInstanceId) ; bpmProcessInstancePrintDataRespVO.setKey(key) ; BpmProcessInstanceRespVO bpmProcessInstance = getProcessInstanceVO(processInstanceId) ; Long businessKey = Long.valueOf(bpmProcessInstance.getBusinessKey()); //流程业务表-主键ID if("oa_reimbursement".equals(key)) { //报销流程 BpmOAReimbursementDO reimbursement = reimbursementService.getReimbursement(businessKey); BpmOAReimbursementRespVO bpmOAReimbursementRespVO = reimbursementService.convert(reimbursement); //报销业务数据 List taskRespVOList = taskService.getTaskListByProcessInstanceId(processInstanceId) ; //报销审核人数据 //给User添加签名地址 taskRespVOList.forEach(taskRespVO -> taskRespVO.getAssigneeUser().setSignURL( fileApi.getUserSignImgPath( taskRespVO.getAssigneeUser().getId() ).getData() ) ); //备用金信息查询 BpmOAImprestDO bpmOAImprestDO = imprestService.getImprestByReimbursementId(reimbursement.getId()); if (bpmOAImprestDO != null) { //设置备用金 金额 bpmOAReimbursementRespVO.setAmount(bpmOAImprestDO.getAmount()); } //获取流程抄送用户编号 BpmProcessInstanceExtDO processInstanceExtDO = getProcessInstanceDO(processInstanceId); //获取流程抄送用户信息 List ccUserIds = new ArrayList<>(); if (processInstanceExtDO.getCcids() != null && !processInstanceExtDO.getCcids().isEmpty()) { Pattern pattern = Pattern.compile("\\[(\\d+)]"); Matcher matcher = pattern.matcher(processInstanceExtDO.getCcids()); while (matcher.find()) { ccUserIds.add(Long.parseLong(matcher.group(1))); } } List userRespDTOS = adminUserApi.getUserList(ccUserIds).getCheckedData(); //获取抄送用户部门信息 Map deptMapDTO = deptApi.getDeptMap(convertSet(userRespDTOS, AdminUserRespDTO::getDeptId)); //拼接数据 List ccUsers = userRespDTOS.stream().map(user -> { BpmOAReimbursementPrintDataRespVO.CCUser cc = new BpmOAReimbursementPrintDataRespVO.CCUser(); cc.setCcUserId(user.getId()); cc.setCcUserName(user.getNickname()); cc.setCcDeptName(deptMapDTO.get(user.getDeptId()).getName()); return cc; }).collect(Collectors.toList()); BpmOAReimbursementPrintDataRespVO reimbursementPrintData = new BpmOAReimbursementPrintDataRespVO() ; reimbursementPrintData.setBpmOAReimbursementRespVO(bpmOAReimbursementRespVO) ; reimbursementPrintData.setProcessTasks(taskRespVOList); reimbursementPrintData.setCcUsers(ccUsers); bpmProcessInstancePrintDataRespVO.setBpmOAReimbursementPrintDataRespVO(reimbursementPrintData) ; } return bpmProcessInstancePrintDataRespVO ; } } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 0bbde32a..3e125832 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -418,6 +418,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { paramMap.put("post_id", postId.toString()); paramMap.put("user_id", userId.toString()); paramMap.put("dept_id", startUser.getDeptId().toString()); //配置发起人部门id + paramMap.put("dept_flag", startDeptInfo.getFlag()); //配置发起人部门flag paramMap.put("approve_reason", reqVO.getReason()); //通过原因---因为Task任务的通过,是通过监听事件处理的,reason数据无法传递给监听函数。所以通过此中方法传递 taskService.complete(task.getId(), paramMap); @@ -718,6 +719,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { } @Override + @Transactional(rollbackFor = Exception.class) public void updateTaskExtAssign(Task task) { // BpmTaskExtDO taskExtDO = // new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId()); diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 40cc9286..86d40f38 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -74,6 +74,9 @@ public interface ErrorCodeConstants { // ========== 通知公告 1-002-008-000 ========== ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1_002_008_001, "当前通知公告不存在"); + ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1_002_008_002, "用户组不存在"); + ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1_002_008_003, "名字为【{}】的用户组已被禁用"); + // ========== 短信渠道 1-002-011-000 ========== ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1_002_011_000, "短信渠道不存在"); ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1_002_011_001, "短信渠道不处于开启状态,不允许选择"); @@ -199,4 +202,10 @@ public interface ErrorCodeConstants { ErrorCode LOG_NOT_DATE = new ErrorCode(1_009_010_007, "只能修改当天提交的日志"); ErrorCode LOG_NOT_UPDATE = new ErrorCode(1_009_010_008, "已过了提交时间,不能修改"); + + ErrorCode BANK_NOT_EXISTS = new ErrorCode(1_009_020_001, "银行卡信息不存在"); + + ErrorCode BANK_EXISTS = new ErrorCode(1_009_020_003, "银行卡号已存在"); + + ErrorCode BANK_NOT_CREATOR = new ErrorCode(1_009_020_002, "你不是当前银行卡信息的创建者,不能进行修改!"); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/UserBankController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/UserBankController.java new file mode 100644 index 00000000..134bcb5a --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/UserBankController.java @@ -0,0 +1,130 @@ +package cn.iocoder.yudao.module.system.controller.admin.bank; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankRespVO; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.bank.BankDO; +import cn.iocoder.yudao.module.system.service.bank.UserBankService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 用户银行卡信息") +@RestController +@RequestMapping("/system/user-bank") +@Validated +public class UserBankController { + + @Resource + private UserBankService userBankService; + + @PostMapping("/create") + @Operation(summary = "创建银行卡信息") + @PreAuthorize("@ss.hasPermission('system:user-bank:create')") + public CommonResult createBank(@Valid @RequestBody UserBankSaveReqVO createReqVO) { + + return success(userBankService.createBank(createReqVO)); + } + + @PostMapping("/create-bank") + @Operation(summary = "创建银行卡信息") + @PreAuthorize("@ss.hasPermission('system:user-bank:create')") + public CommonResult createPayBank(@Valid @RequestBody UserBankSaveReqVO createReqVO) { + + userBankService.createPayBank(createReqVO); + return success(true); + } + + @PostMapping("/create-user") + @Operation(summary = "创建用户和银行卡关联信息") + @PreAuthorize("@ss.hasPermission('system:user-bank:create')") + public CommonResult createUserBank(@RequestBody List bankId) { + + userBankService.createUserBank(bankId); + return success(true); + } + + @PutMapping("/update") + @Operation(summary = "更新银行卡信息") + @PreAuthorize("@ss.hasPermission('system:user-bank:update')") + public CommonResult updateBank(@Valid @RequestBody UserBankSaveReqVO updateReqVO) { + userBankService.updateBank(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除用户和银行卡关联信息") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('system:user-bank:delete')") + public CommonResult deleteUserBank(@RequestParam("id") Long id) { + userBankService.deleteUserBank(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得银行卡信息") + @Parameter(name = "bankId", description = "银行卡信息编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:user-bank:query')") + public CommonResult getBank(@RequestParam("bankId") Long bankId) { + + BankDO userBank = userBankService.getBank(bankId); + return success(BeanUtils.toBean(userBank, UserBankRespVO.class)); + } + + @GetMapping("/page-bank") + @Operation(summary = "获得银行卡信息分页列表") + @PreAuthorize("@ss.hasPermission('system:user-bank:query')") + public CommonResult> getBankPage(@Valid UserBankPageReqVO pageReqVO) { + + PageResult pageResult = new PageResult(); + List bankIds = userBankService.getBankIds(getLoginUserId()); + if (bankIds.isEmpty()) { + + pageResult = userBankService.getBankPageIn(pageReqVO, null); + }else { + pageResult = userBankService.getBankPageNotIn(pageReqVO, bankIds); + } + + + return success(BeanUtils.toBean(pageResult, UserBankRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得用户和银行卡关联信息分页") + @PreAuthorize("@ss.hasPermission('system:user-bank:query')") + public CommonResult> getUserBankPage(@Valid UserBankPageReqVO pageReqVO) { + + PageResult pageResult = new PageResult(); + List bankIds = userBankService.getBankIds(getLoginUserId()); + if (!bankIds.isEmpty()) { + + pageResult = userBankService.getBankPageIn(pageReqVO, bankIds); + } + + + return success(BeanUtils.toBean(pageResult, UserBankRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得用户和银行卡关联信息列表") + @PreAuthorize("@ss.hasPermission('system:user-bank:query')") + public CommonResult> getUserBankList() { + + List bankDOS = userBankService.getBankListByUserId(getLoginUserId()); + + return success(BeanUtils.toBean(bankDOS, UserBankRespVO.class)); + } +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankPageReqVO.java new file mode 100644 index 00000000..2dea421d --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.controller.admin.bank.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 用户银行卡信息分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class UserBankPageReqVO extends PageParam { + + @Schema(description = "用户编号", example = "31665") + private Long userId; + + @Schema(description = "银行卡用户名称", example = "芋艿") + private String nickname; + + @Schema(description = "银行卡号") + private String bankNo; + + @Schema(description = "开户行信息", example = "赵六") + private String bankName; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankRespVO.java new file mode 100644 index 00000000..a89cfae0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankRespVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.system.controller.admin.bank.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 用户银行卡信息 Response VO") +@Data +@ExcelIgnoreUnannotated +public class UserBankRespVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3548") + @ExcelProperty("ID") + private Long id; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31665") + private Long userId; + + @Schema(description = "银行卡用户名称", example = "芋艿") + @ExcelProperty("银行卡用户名称") + private String nickname; + + @Schema(description = "银行卡号") + @ExcelProperty("银行卡号") + private String bankNo; + + @Schema(description = "开户行信息", example = "赵六") + @ExcelProperty("开户行信息") + private String bankName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankSaveReqVO.java new file mode 100644 index 00000000..caf9ce35 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/bank/vo/UserBankSaveReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.system.controller.admin.bank.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 用户银行卡信息新增/修改 Request VO") +@Data +public class UserBankSaveReqVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3548") + private Long id; + + @Schema(description = "银行卡用户名称", example = "芋艿") + private String nickname; + + @Schema(description = "银行卡号") + private String bankNo; + + @Schema(description = "开户行信息", example = "赵六") + private String bankName; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java index 6af6dc9a..f8656de5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO; @@ -78,6 +79,15 @@ public class DeptController { return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); } + @GetMapping(value = {"/all-list"}) + @Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项") + @DataPermission(enable = false) + public CommonResult> getAllDeptList() { + List list = deptService.getDeptList( + new DeptListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); + } + @GetMapping("/get") @Operation(summary = "获得部门信息") @Parameter(name = "id", description = "编号", required = true, example = "1024") @@ -87,7 +97,6 @@ public class DeptController { return success(BeanUtils.toBean(dept, DeptRespVO.class)); } - @GetMapping("/getUserDept") @Operation(summary = "获取当前登录用户部门信息") public CommonResult getUserDept() { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java index 175e4b24..7e93f18a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; @@ -83,6 +84,17 @@ public class PostController { return success(BeanUtils.toBean(list, PostSimpleRespVO.class)); } + @GetMapping(value = {"/all-list"}) + @Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") + @DataPermission(enable = false) + public CommonResult> getAllPostList() { + // 获得岗位列表,只要开启状态的 + List list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); + // 排序后,返回给前端 + list.sort(Comparator.comparing(PostDO::getSort)); + return success(BeanUtils.toBean(list, PostSimpleRespVO.class)); + } + @GetMapping("/page") @Operation(summary = "获得岗位分页列表") @PreAuthorize("@ss.hasPermission('system:post:query')") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java index 33821c69..14dd1952 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java @@ -1,15 +1,14 @@ package cn.iocoder.yudao.module.system.controller.admin.notice; -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePushReqVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeRespVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; +import cn.iocoder.yudao.module.system.service.notice.NoticeGroupService; import cn.iocoder.yudao.module.system.service.notice.NoticeService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -33,7 +32,7 @@ public class NoticeController { private NoticeService noticeService; @Resource - private WebSocketSenderApi webSocketSenderApi; + private NoticeGroupService groupService; @PostMapping("/create") @Operation(summary = "创建通知公告") @@ -78,18 +77,16 @@ public class NoticeController { } @PostMapping("/push") - @Operation(summary = "推送通知公告", description = "只发送给 websocket 连接在线的用户") - @Parameter(name = "id", description = "编号", required = true, example = "1024") + @Operation(summary = "推送通知公告") @PreAuthorize("@ss.hasPermission('system:notice:update')") - public CommonResult push(@RequestParam("id") Long id) { - NoticeDO notice = noticeService.getNotice(id); - Assert.notNull(notice, "公告不能为空"); + public CommonResult push(@Valid @RequestBody NoticePushReqVO pushReqVO) { + // 通过 websocket 推送给在线的用户 //webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), "notice-push", notice); + //小程序发送公告订阅消息 //获取改造方式, push 方法传入需要推送的用户ID集合【 将ID集合查询出用户集合, 只获取openId的用户,进行推送 】 - noticeService.sendNotice(notice); + noticeService.sendNotice(pushReqVO); return success(true); } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeGroupController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeGroupController.java new file mode 100644 index 00000000..325b1db6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeGroupController.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupRespVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO; +import cn.iocoder.yudao.module.system.convert.notice.NoticeGroupConvert; +import cn.iocoder.yudao.module.system.convert.user.UserConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeGroupDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import cn.iocoder.yudao.module.system.service.notice.NoticeGroupService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - 用户组") +@RestController +@RequestMapping("/system/notice/user-group") +@Validated +public class NoticeGroupController { + + @Resource + private NoticeGroupService userGroupService; + + @Resource + private AdminUserService userService; + @Resource + private DeptService deptService; + + @PostMapping("/create") + @Operation(summary = "创建用户组") + @PreAuthorize("@ss.hasPermission('system:notice-gropu:create')") + public CommonResult createUserGroup(@Valid @RequestBody NoticeGroupCreateReqVO createReqVO) { + return success(userGroupService.createUserGroup(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新用户组") + @PreAuthorize("@ss.hasPermission('system:notice-gropu:update')") + public CommonResult updateUserGroup(@Valid @RequestBody NoticeGroupUpdateReqVO updateReqVO) { + userGroupService.updateUserGroup(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除用户组") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('system:notice-gropu:delete')") + public CommonResult deleteUserGroup(@RequestParam("id") Long id) { + userGroupService.deleteUserGroup(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得用户组") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:notice-gropu:query')") + public CommonResult getUserGroup(@RequestParam("id") Long id) { + + NoticeGroupDO userGroup = userGroupService.getUserGroup(id); + + //获得用户信息 + List userDOS = userService.getUserList(userGroup.getMemberUserIds()); + //获得部门信息 map + Map deptMap = deptService.getDeptMap(convertList(userDOS, AdminUserDO::getDeptId)); + + List userRespVOS = convertList(userDOS, user -> UserConvert.INSTANCE.convert(user, deptMap.get(user.getDeptId()))); + + NoticeGroupRespVO noticeGroupRespVO = NoticeGroupConvert.INSTANCE.convert(userGroup); + noticeGroupRespVO.setUserInfo(userRespVOS); + noticeGroupRespVO.setMemberDeptIds(deptMap.keySet()); + + return success(noticeGroupRespVO); + } + + @GetMapping("/page") + @Operation(summary = "获得用户组分页") + @PreAuthorize("@ss.hasPermission('system:notice-gropu:query')") + public CommonResult> getUserGroupPage(@Valid NoticeGroupPageReqVO pageVO) { + PageResult pageResult = userGroupService.getUserGroupPage(pageVO); + return success(NoticeGroupConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/list-all-simple") + @Operation(summary = "获取用户组精简信息列表", description = "只包含被开启的用户组,主要用于前端的下拉选项") + public CommonResult> getSimpleUserGroups() { + // 获用户门列表,只要开启状态的 + List list = userGroupService.getUserGroupListByStatus(CommonStatusEnum.ENABLE.getStatus()); + // 排序后,返回给前端 + return success(NoticeGroupConvert.INSTANCE.convertList2(list)); + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePushReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePushReqVO.java new file mode 100644 index 00000000..f9320089 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePushReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Set; + +@Schema(description = "公告推送信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class NoticePushReqVO { + + @Schema(description = "公告编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") + private Long id; + + @Schema(description = "推送类型 | 0:全员 1:部门 2:用户组", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer type; + + @Schema(description = "推送部门编号") + private List deptIds; + + @Schema(description = "推送用户组编号") + private Set groupId; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupBaseVO.java new file mode 100644 index 00000000..5efc634a --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupBaseVO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Set; + +/** +* 用户组 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class NoticeGroupBaseVO { + + @Schema(description = "组名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @NotNull(message = "组名不能为空") + private String name; + + @Schema(description = "描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + @NotNull(message = "描述不能为空") + private String description; + + @Schema(description = "成员编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3") + @NotNull(message = "成员编号数组不能为空") + private Set memberUserIds; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + private Integer status; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupCreateReqVO.java new file mode 100644 index 00000000..26140419 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 用户组创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class NoticeGroupCreateReqVO extends NoticeGroupBaseVO { + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupPageReqVO.java new file mode 100644 index 00000000..3f20bf33 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupPageReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo.group; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 用户组分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class NoticeGroupPageReqVO extends PageParam { + + @Schema(description = "组名", example = "芋道") + private String name; + + @Schema(description = "状态", example = "1") + private Integer status; + + @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Schema(description = "创建时间") + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupRespVO.java new file mode 100644 index 00000000..6231bb15 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo.group; + +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +@Schema(description = "管理后台 - 用户组 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class NoticeGroupRespVO extends NoticeGroupBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "成员部门编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[126][128]") + @NotNull(message = "成员部门编号数组不能为空") + private Set memberDeptIds; + + @Schema(description = "成员信息") + private List userInfo; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupUpdateReqVO.java new file mode 100644 index 00000000..8a1e9e08 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/group/NoticeGroupUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 用户组更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class NoticeGroupUpdateReqVO extends NoticeGroupBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "编号不能为空") + private Long id; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogStatisticsController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogStatisticsController.java index 71aeabb9..7f11e1ac 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogStatisticsController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogStatisticsController.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.LogStatisticsDetailsListDTO; +import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.MyManageModelDTO; import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.NeedWriteHistoryDTO; import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.statistics.LogStatisticsDetailsListVO; import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.statistics.LogStatisticsDetailsVO; @@ -20,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @@ -42,6 +44,13 @@ public class LogStatisticsController { return success(logStatisticsService.myManageModel()); } + @GetMapping("/getMyManageModelStatistics") + @Operation(summary = "获取我管理的模版的统计") + @PermitAll + public CommonResult> getMyManageModelStatistics(@ModelAttribute MyManageModelDTO dto) { + return success(logStatisticsService.getMyManageModelStatistics(dto)); + } + @GetMapping("/getStatistics") @Operation(summary = "获取日志统计") public CommonResult getStatistics(@ModelAttribute LogStatisticsDetailsListDTO dto) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/LogStatisticsDetailsListDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/LogStatisticsDetailsListDTO.java index 677b2259..dc2bfa36 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/LogStatisticsDetailsListDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/LogStatisticsDetailsListDTO.java @@ -14,4 +14,10 @@ public class LogStatisticsDetailsListDTO { @Schema(description = "结束时间 格式yyyy-MM-dd 如果是日报的话 开始时间结束时间都传同一天即可") private String endTime; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "部门id") + private Long deptId; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/MyManageModelDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/MyManageModelDTO.java new file mode 100644 index 00000000..3dc5bc81 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/dto/statistics/MyManageModelDTO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +@Data +public class MyManageModelDTO { + + @Schema(description = "当前用户id") + private Long userId; + + @Schema(description = "部门id") + private Long deptId; + + @Schema(description = "类型 1日报 2周报") + private Integer type; + + @Schema(description = "开始时间 格式yyyy-MM-dd") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT) + private Date beginTime; + + @Schema(description = "结束时间 格式yyyy-MM-dd") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT) + private Date endTime; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java index a4bfe192..ab53efc6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java @@ -1,22 +1,19 @@ package cn.iocoder.yudao.module.system.convert.notice; import cn.iocoder.yudao.framework.common.util.date.DateUtils; -import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO; import cn.iocoder.yudao.module.system.api.subscribe.dto.MsgData; import cn.iocoder.yudao.module.system.api.subscribe.dto.SubscribeMessageReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.Date; -import java.util.Map; /** * 功能描述 * - * @author: yj - * @date: 2024年04月07日 19:44 + * @author yj + * date 2024年04月07日 19:44 */ @Mapper public interface NoticeConvert { @@ -30,20 +27,25 @@ public interface NoticeConvert { * @param miniProgramState 小程序的状态 * @return */ - default SubscribeMessageReqDTO convertCompanyNotice(String openId, NoticeDO notice, String nickname, String miniProgramState) { + default SubscribeMessageReqDTO convertCompanyNotice(String openId, NoticeDO notice, String noticeLabel, String nickname, String miniProgramState) { SubscribeMessageReqDTO message = new SubscribeMessageReqDTO(); message.setToUser(openId); message.setTemplateId("OF4-948Vz9rtE_VA55rmDxo4azOwmrjjk33jDpOiPiY"); //通知类型 MsgData noticeType = new MsgData(); noticeType.setName("thing1"); - noticeType.setValue(notice.getType()+""); //这里根据业务需求填写具体的公告类型 如全员公告, xxx公告 + noticeType.setValue(noticeLabel); //这里根据业务需求填写具体的公告类型 如全员公告, xxx公告 message.addData(noticeType); //公告标题 + String value = notice.getTitle(); + if (value.length() > 10) { + value = value.substring(0,10) + ". . . . "; + } + MsgData title = new MsgData(); title.setName("thing6"); - title.setValue(notice.getTitle()); + title.setValue(value); message.addData(title); //通知内容 @@ -65,7 +67,7 @@ public interface NoticeConvert { message.addData(createTime); message.setMiniprogramState(miniProgramState); - message.setPage("pages/index"); + message.setPage("/subPages/notice/detail?id=" + notice.getId()); return message; } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeGroupConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeGroupConvert.java new file mode 100644 index 00000000..ab5249b6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeGroupConvert.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.system.convert.notice; + + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupRespVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeGroupDO; +import org.mapstruct.Mapper; +import org.mapstruct.Named; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 用户组 Convert + * + + */ +@Mapper +public interface NoticeGroupConvert { + + NoticeGroupConvert INSTANCE = Mappers.getMapper(NoticeGroupConvert.class); + + NoticeGroupDO convert(NoticeGroupCreateReqVO bean); + + NoticeGroupDO convert(NoticeGroupUpdateReqVO bean); + + NoticeGroupRespVO convert(NoticeGroupDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + @Named("convertList2") + List convertList2(List list); + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/bank/BankDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/bank/BankDO.java new file mode 100644 index 00000000..2cca5fb9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/bank/BankDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.dal.dataobject.bank; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 管理后台的用户银行卡信息 DO + */ +@TableName(value = "system_bank", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BankDO extends BaseDO { + + /** + * ID + */ + @TableId + private Long id; + + /** + * 银行卡用户名称 + */ + private String nickname; + + /** + * 银行卡号 + */ + private String bankNo; + + /** + * 开户行信息 + */ + private String bankName; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/bank/UserBankDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/bank/UserBankDO.java new file mode 100644 index 00000000..4dbd2d42 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/bank/UserBankDO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.dal.dataobject.bank; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 用户和银行卡关联 DO + */ +@TableName(value = "system_user_bank", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserBankDO extends BaseDO { + + /** + * ID + */ + @TableId + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 银行卡信息 ID + */ + private Long bankId; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notice/NoticeGroupDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notice/NoticeGroupDO.java new file mode 100644 index 00000000..c285f194 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notice/NoticeGroupDO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.system.dal.dataobject.notice; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.util.Set; + +/** + * 公告推送 用户组 + */ +@TableName(value = "system_notice_group", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class NoticeGroupDO extends BaseDO { + + /** + * 编号,自增 + */ + @TableId + private Long id; + /** + * 组名 + */ + private String name; + /** + * 描述 + */ + private String description; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + /** + * 成员用户编号数组 + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set memberUserIds; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/bank/BankMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/bank/BankMapper.java new file mode 100644 index 00000000..170b9a71 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/bank/BankMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.system.dal.mysql.bank; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.bank.BankDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 银行卡信息 Mapper + * + * @author 符溶馨 + */ +@Mapper +public interface BankMapper extends BaseMapperX { + + default PageResult selectPageIn(UserBankPageReqVO reqVO, List bankId) { + + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(BankDO::getNickname, reqVO.getNickname()) + .inIfPresent(BankDO::getId, bankId) + .orderByDesc(BankDO::getId)); + } + + default PageResult selectPageNotIn(UserBankPageReqVO reqVO, List bankId) { + + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(BankDO::getNickname, reqVO.getNickname()) + .notIn(BankDO::getId, bankId) + .orderByDesc(BankDO::getId)); + } + + default List selectBankList(List bankId) { + + return selectList(new LambdaQueryWrapperX() + .in(BankDO::getId, bankId)); + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/bank/UserBankMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/bank/UserBankMapper.java new file mode 100644 index 00000000..815f6b1b --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/bank/UserBankMapper.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.system.dal.mysql.bank; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.bank.UserBankDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户和银行卡关联 Mapper + * + * @author 符溶馨 + */ +@Mapper +public interface UserBankMapper extends BaseMapperX { + + default UserBankDO selectByBankId(Long userId, Long bankId) { + + return selectOne(new LambdaQueryWrapperX() + .eq(UserBankDO::getUserId, userId) + .eq(UserBankDO::getBankId, bankId)); + } +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notice/NoticeGroupMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notice/NoticeGroupMapper.java new file mode 100644 index 00000000..0d9ad145 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notice/NoticeGroupMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.system.dal.mysql.notice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeGroupDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 公告推送用户组 Mapper + */ +@Mapper +public interface NoticeGroupMapper extends BaseMapperX { + + default PageResult selectPage(NoticeGroupPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(NoticeGroupDO::getName, reqVO.getName()) + .eqIfPresent(NoticeGroupDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(NoticeGroupDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(NoticeGroupDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(NoticeGroupDO::getStatus, status); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogStatisticsMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogStatisticsMapper.java index a6b5be45..badd3b92 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogStatisticsMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogStatisticsMapper.java @@ -53,7 +53,7 @@ public interface LogStatisticsMapper extends BaseMapperX { * @param formId * @return */ - List getStatistics(@Param("formId") Long formId, @Param("dateList") List dateList); + List getStatistics(@Param("formId") Long formId, @Param("userId") Long userId, @Param("deptId") Long deptId, @Param("dateList") List dateList); /** * 获取当天/本周的统计 @@ -72,7 +72,7 @@ public interface LogStatisticsMapper extends BaseMapperX { * @param dateList * @return */ - List getMyCurrentStatistics(@Param("userId") Long userId, @Param("formId") Long formId, @Param("dateList") List dateList); + List getMyCurrentStatistics(@Param("userId") Long userId, @Param("deptId") Long deptId, @Param("formId") Long formId, @Param("dateList") List dateList); /** * 获取我的日志历史记录 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/ThreadPool/config/AsyncConfig.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/ThreadPool/config/AsyncConfig.java new file mode 100644 index 00000000..d39eedd0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/ThreadPool/config/AsyncConfig.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.framework.ThreadPool.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ThreadPoolExecutor; + +@Configuration(proxyBeanMethods = false) +public class AsyncConfig { + + public static final String NOTIFY_THREAD_POOL_TASK_EXECUTOR = "NOTIFY_THREAD_POOL_TASK_EXECUTOR"; + + @Bean(NOTIFY_THREAD_POOL_TASK_EXECUTOR) + public ThreadPoolTaskExecutor notifyThreadPoolTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(2); // 设置核心线程数 + executor.setMaxPoolSize(4); // 设置最大线程数 + executor.setKeepAliveSeconds(60); // 设置空闲时间 + executor.setQueueCapacity(100); // 设置队列大小 + executor.setThreadNamePrefix("notify-"); // 配置线程池的前缀 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + // 进行加载 + executor.initialize(); + return executor; + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/ThreadPool/core/package-info.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/ThreadPool/core/package-info.java new file mode 100644 index 00000000..41e950dd --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/ThreadPool/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.system.framework.ThreadPool.core; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/bank/UserBankService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/bank/UserBankService.java new file mode 100644 index 00000000..51e18b54 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/bank/UserBankService.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.system.service.bank; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.bank.BankDO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 用户银行卡信息 Service 接口 + * + * @author 符溶馨 + */ +public interface UserBankService { + + /** + * 创建用户银行卡信息 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createBank(@Valid UserBankSaveReqVO createReqVO); + + /** + * 创建用户银行卡信息 + * + * @param createReqVO 创建信息 + */ + void createPayBank(@Valid UserBankSaveReqVO createReqVO); + + /** + * 创建用户和银行卡关联信息 + * + * @param bankId 银行卡信息编号组 + */ + void createUserBank(List bankId); + + /** + * 更新银行卡信息 + * + * @param updateReqVO 更新信息 + */ + void updateBank(@Valid UserBankSaveReqVO updateReqVO); + + /** + * 删除用户银行卡信息 + * + * @param id 编号 + */ + void deleteUserBank(Long id); + + /** + * 获得用户银行卡信息 + * + * @param bankId 银行卡信息编号 + * @return 银行卡信息 + */ + BankDO getBank(Long bankId); + + /** + * 获得银行卡信息编号组 + * @param userId 用户ID + * @return 银行卡信息编号组 + */ + List getBankIds(Long userId); + + /** + * 获得银行卡信息分页 + * + * @param pageReqVO 分页查询 + * @return 银行卡信息分页 + */ + PageResult getBankPageIn(UserBankPageReqVO pageReqVO, List bankId); + + /** + * 获得银行卡信息分页 + * + * @param pageReqVO 分页查询 + * @return 银行卡信息分页 + */ + PageResult getBankPageNotIn(UserBankPageReqVO pageReqVO, List bankId); + + List getBankListByUserId(Long userId); +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/bank/UserBankServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/bank/UserBankServiceImpl.java new file mode 100644 index 00000000..2e6b80f3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/bank/UserBankServiceImpl.java @@ -0,0 +1,190 @@ +package cn.iocoder.yudao.module.system.service.bank; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.bank.vo.UserBankSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.bank.BankDO; +import cn.iocoder.yudao.module.system.dal.dataobject.bank.UserBankDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.bank.BankMapper; +import cn.iocoder.yudao.module.system.dal.mysql.bank.UserBankMapper; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +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.system.enums.ErrorCodeConstants.*; + +/** + * 用户银行卡信息 Service 实现类 + * + * @author 符溶馨 + */ +@Service +@Validated +public class UserBankServiceImpl implements UserBankService { + + @Resource + private UserBankMapper userBankMapper; + + @Resource + private BankMapper bankMapper; + + @Resource + private AdminUserService adminUserService; + + @Override + public Long createBank(UserBankSaveReqVO createReqVO) { + + //校验银行卡号是否已存在 + Long count = bankMapper.selectCount(BankDO::getBankNo, createReqVO.getBankNo()); + if (count > 0L) { + throw exception(BANK_EXISTS); + } + + // 插入 + BankDO bank = BeanUtils.toBean(createReqVO, BankDO.class); + bankMapper.insert(bank); + // 返回 + return bank.getId(); + } + + @Override + public void createPayBank(UserBankSaveReqVO createReqVO) { + + //校验银行卡号是否已存在 + BankDO bankDO = bankMapper.selectOne(BankDO::getBankNo, createReqVO.getBankNo()); + if (bankDO != null) { + + UserBankDO userBankDO = userBankMapper.selectByBankId(getLoginUserId(), bankDO.getId()); + if (userBankDO == null) { + + userBankDO = new UserBankDO(); + userBankDO.setUserId(getLoginUserId()); + userBankDO.setBankId(bankDO.getId()); + userBankDO.setCreator(Objects.requireNonNull(getLoginUserId()).toString()); + + userBankMapper.insert(userBankDO); + } + }else { + + // 插入 + BankDO bank = BeanUtils.toBean(createReqVO, BankDO.class); + bankMapper.insert(bank); + + UserBankDO userBankDO = new UserBankDO(); + userBankDO.setUserId(getLoginUserId()); + userBankDO.setBankId(bank.getId()); + userBankDO.setCreator(Objects.requireNonNull(getLoginUserId()).toString()); + + userBankMapper.insert(userBankDO); + } + } + + @Override + public void createUserBank(List bankId) { + + //获取当前登录用户信息 + AdminUserDO adminUserDO = adminUserService.getUser(getLoginUserId()); + + List useDOs = bankId.stream() + .map(id -> { + UserBankDO userBankDO = new UserBankDO(); + userBankDO.setUserId(adminUserDO.getId()); + userBankDO.setBankId(id); + userBankDO.setCreator(String.valueOf(adminUserDO.getId())); + return userBankDO; + }).collect(Collectors.toList()); + + userBankMapper.insertBatch(useDOs); + } + + @Override + public void updateBank(UserBankSaveReqVO updateReqVO) { + // 校验存在 + validateBankExists(updateReqVO.getId()); + + // 更新 + BankDO updateObj = BeanUtils.toBean(updateReqVO, BankDO.class); + bankMapper.updateById(updateObj); + } + + @Override + public void deleteUserBank(Long id) { + // 校验存在 + UserBankDO userBankDO = userBankMapper.selectByBankId(getLoginUserId(), id); + if (userBankDO == null) { + throw exception(BANK_NOT_EXISTS); + } + + // 删除 + userBankMapper.deleteById(userBankDO); + + BankDO bankDO = bankMapper.selectById(userBankDO.getBankId()); + //校验当前登录用户是否是 该银行卡信息的创建者 + if (bankDO.getCreator().equals(userBankDO.getUserId().toString())) { + + // 同步删除 银行卡信息 + bankMapper.deleteById(bankDO.getId()); + } + } + + private void validateBankExists(Long id) { + + BankDO bankDO = bankMapper.selectById(id); + + if (bankDO == null) { + throw exception(BANK_NOT_EXISTS); + } + + //校验当前登录用户是否是 该银行卡信息的创建者 + if (!Long.valueOf(bankDO.getCreator()).equals(getLoginUserId())) { + throw exception(BANK_NOT_CREATOR); + } + } + + @Override + public BankDO getBank(Long id) { + + return bankMapper.selectById(id); + } + + @Override + public List getBankIds(Long userId) { + + List userBankDOS = userBankMapper.selectList(UserBankDO::getUserId, userId); + + return convertList(userBankDOS, UserBankDO::getBankId); + } + + @Override + public PageResult getBankPageIn(UserBankPageReqVO pageReqVO, List bankId) { + + return bankMapper.selectPageIn(pageReqVO, bankId); + } + + @Override + public PageResult getBankPageNotIn(UserBankPageReqVO pageReqVO, List bankId) { + + return bankMapper.selectPageNotIn(pageReqVO, bankId); + } + + @Override + public List getBankListByUserId(Long userId) { + + if (getBankIds(userId).isEmpty()) { + + return null; + } + + return bankMapper.selectBankList(getBankIds(userId)); + } +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeGroupService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeGroupService.java new file mode 100644 index 00000000..6ab3713d --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeGroupService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.system.service.notice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeGroupDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * 用户组 Service 接口 + * + + */ +public interface NoticeGroupService { + + /** + * 创建用户组 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createUserGroup(@Valid NoticeGroupCreateReqVO createReqVO); + + /** + * 更新用户组 + * + * @param updateReqVO 更新信息 + */ + void updateUserGroup(@Valid NoticeGroupUpdateReqVO updateReqVO); + + /** + * 删除用户组 + * + * @param id 编号 + */ + void deleteUserGroup(Long id); + + /** + * 获得用户组 + * + * @param id 编号 + * @return 用户组 + */ + NoticeGroupDO getUserGroup(Long id); + + /** + * 获得用户组列表 + * + * @param ids 编号 + * @return 用户组列表 + */ + List getUserGroupList(Collection ids); + + /** + * 获得指定状态的用户组列表 + * + * @param status 状态 + * @return 用户组列表 + */ + List getUserGroupListByStatus(Integer status); + + /** + * 获得用户组分页 + * + * @param pageReqVO 分页查询 + * @return 用户组分页 + */ + PageResult getUserGroupPage(NoticeGroupPageReqVO pageReqVO); + + /** + * 校验用户组们是否有效。如下情况,视为无效: + * 1. 用户组编号不存在 + * 2. 用户组被禁用 + * + * @param ids 用户组编号数组 + */ + void validUserGroups(Set ids); + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeGroupServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeGroupServiceImpl.java new file mode 100644 index 00000000..1d06282a --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeGroupServiceImpl.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.system.service.notice; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.group.NoticeGroupUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.notice.NoticeGroupConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeGroupDO; +import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeGroupMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_GROUP_IS_DISABLE; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS; + + +/** + * 用户组 Service 实现类 + * + + */ +@Service +@Validated +public class NoticeGroupServiceImpl implements NoticeGroupService { + + @Resource + private NoticeGroupMapper userGroupMapper; + + @Override + public Long createUserGroup(NoticeGroupCreateReqVO createReqVO) { + // 插入 + NoticeGroupDO userGroup = NoticeGroupConvert.INSTANCE.convert(createReqVO); + userGroupMapper.insert(userGroup); + // 返回 + return userGroup.getId(); + } + + @Override + public void updateUserGroup(NoticeGroupUpdateReqVO updateReqVO) { + // 校验存在 + this.validateUserGroupExists(updateReqVO.getId()); + // 更新 + NoticeGroupDO updateObj = NoticeGroupConvert.INSTANCE.convert(updateReqVO); + userGroupMapper.updateById(updateObj); + } + + @Override + public void deleteUserGroup(Long id) { + // 校验存在 + this.validateUserGroupExists(id); + // 删除 + userGroupMapper.deleteById(id); + } + + private void validateUserGroupExists(Long id) { + if (userGroupMapper.selectById(id) == null) { + throw exception(USER_GROUP_NOT_EXISTS); + } + } + + @Override + public NoticeGroupDO getUserGroup(Long id) { + return userGroupMapper.selectById(id); + } + + @Override + public List getUserGroupList(Collection ids) { + return userGroupMapper.selectBatchIds(ids); + } + + + @Override + public List getUserGroupListByStatus(Integer status) { + return userGroupMapper.selectListByStatus(status); + } + + @Override + public PageResult getUserGroupPage(NoticeGroupPageReqVO pageReqVO) { + return userGroupMapper.selectPage(pageReqVO); + } + + @Override + public void validUserGroups(Set ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + // 获得用户组信息 + List userGroups = userGroupMapper.selectBatchIds(ids); + Map userGroupMap = CollectionUtils.convertMap(userGroups, NoticeGroupDO::getId); + // 校验 + ids.forEach(id -> { + NoticeGroupDO userGroup = userGroupMap.get(id); + if (userGroup == null) { + throw exception(USER_GROUP_NOT_EXISTS); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(userGroup.getStatus())) { + throw exception(USER_GROUP_IS_DISABLE, userGroup.getName()); + } + }); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java index c714098f..1894f715 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.notice; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePushReqVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; @@ -50,7 +51,7 @@ public interface NoticeService { /** * 小程序发送公告订阅消息 - * @param notice + * @param pushReqVO 推送信息 */ - void sendNotice(NoticeDO notice) ; + void sendNotice(NoticePushReqVO pushReqVO) ; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java index 8f847f5c..94bf3885 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java @@ -7,21 +7,28 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePushReqVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeGroupDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper; +import cn.iocoder.yudao.module.system.service.dict.DictDataService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.google.common.annotations.VisibleForTesting; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import javax.annotation.Resource; - +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND; +import static cn.iocoder.yudao.module.system.framework.ThreadPool.config.AsyncConfig.NOTIFY_THREAD_POOL_TASK_EXECUTOR; /** * 通知公告 Service 实现类 @@ -34,6 +41,15 @@ public class NoticeServiceImpl implements NoticeService { @Resource private NoticeMapper noticeMapper; + @Resource + private NoticeGroupService noticeGroupService; + + @Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR) + private ThreadPoolTaskExecutor threadPoolTaskExecutor; + + @Resource + private DictDataService dictDataService; + @Override public Long createNotice(NoticeSaveReqVO createReqVO) { NoticeDO notice = BeanUtils.toBean(createReqVO, NoticeDO.class); @@ -86,21 +102,55 @@ public class NoticeServiceImpl implements NoticeService { private SubscribeMessageSendApi subscribeMessageSendApi; @Override - public void sendNotice(NoticeDO notice) { + public void sendNotice(NoticePushReqVO pushReqVO) { + + //获得公告信息 + NoticeDO notice = getNotice(pushReqVO.getId()); + if (notice == null) { + throw exception(NOTICE_NOT_FOUND); + } + + // 获得公告类型 字典label + DictDataDO dictDataDO = dictDataService.getDictData("system_notice_type", String.valueOf(notice.getType())); + //获取当前登陆用户的名称 LoginUser user = SecurityFrameworkUtils.getLoginUser() ; AdminUserDO currentUser = userService.getUser(user.getId()) ; - //查询所有状态是开启的用户 - List list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus()); - for(AdminUserDO adminUserDO : list) { - if( adminUserDO.getOpenId() != null && !adminUserDO.getOpenId().equals("") ) { - System.out.println("====" + adminUserDO.getNickname()); - //获取openId有值的用户 - subscribeMessageSendApi.sendCompanyNotice(NoticeConvert.INSTANCE.convertCompanyNotice( - adminUserDO.getOpenId(), notice , currentUser.getNickname(), - "formal")); + List userDOs = new ArrayList<>(); + switch (pushReqVO.getType()) { + + //全员推送 + case 0: + //获得用户信息 + userDOs = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus()); + break; + //部门推送 + case 1: + //获得用户信息 + userDOs = userService.getUserListByDeptIds(pushReqVO.getDeptIds()); + break; + //用户组推送 + case 2: + //获得用户组信息 + List groupDOs = noticeGroupService.getUserGroupList(pushReqVO.getGroupId()); + + //获得用户组中 用户信息 + userDOs = userService.getUserList(groupDOs.stream().flatMap(group -> group.getMemberUserIds().stream()).collect(Collectors.toSet())); + break; + } + + for(AdminUserDO adminUserDO : userDOs) { + if( adminUserDO.getOpenId() != null && !adminUserDO.getOpenId().isEmpty()) { + + threadPoolTaskExecutor.execute(() -> { + + //获取openId有值的用户 + subscribeMessageSendApi.sendCompanyNotice(NoticeConvert.INSTANCE.convertCompanyNotice( + adminUserDO.getOpenId(), notice, dictDataDO.getLabel(), currentUser.getNickname(), + "formal")); + }); } } } -} +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsService.java index 1ee00c89..7942eda4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.worklog; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.LogStatisticsDetailsListDTO; +import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.MyManageModelDTO; import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.NeedWriteHistoryDTO; import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.statistics.*; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -105,4 +106,12 @@ public interface LogStatisticsService { * @return */ List getNeedWriteHistory(NeedWriteHistoryDTO dto); + + /** + * 获取我管理的模版的统计 + * + * @param dto + * @return + */ + List getMyManageModelStatistics(MyManageModelDTO dto); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsServiceImpl.java index a844714d..823e57df 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogStatisticsServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.LogStatisticsDetailsListDTO; +import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.MyManageModelDTO; import cn.iocoder.yudao.module.system.controller.admin.worklog.dto.statistics.NeedWriteHistoryDTO; import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.statistics.*; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -171,19 +172,22 @@ public class LogStatisticsServiceImpl implements LogStatisticsService { LogRuleDO logRuleDO = logRuleService.getLogRuleByFormId(dto.getFormId()); // 判断开始时间是否当天 / 是否本周 boolean flag = false; - Date begin = DateUtil.parse(dto.getBeginTime(), "yyyy-MM-dd").toJdkDate(); List logStatisticsDOS = new ArrayList<>(); - if (logRuleDO.getType() == 1) { - flag = DateUtil.isSameDay(begin, new Date()); - } else if (logRuleDO.getType() == 2) { - flag = DateUtil.isSameWeek(begin, new Date(), true); + List dateList = new ArrayList<>(); + if (StrUtil.isNotEmpty(dto.getBeginTime()) && StrUtil.isNotEmpty(dto.getEndTime())) { + Date begin = DateUtil.parse(dto.getBeginTime(), "yyyy-MM-dd").toJdkDate(); + if (logRuleDO.getType() == 1) { + flag = DateUtil.isSameDay(begin, new Date()); + } else if (logRuleDO.getType() == 2) { + flag = DateUtil.isSameWeek(begin, new Date(), true); + } + dateList = DateUtils.betweenDayStrList(dto.getBeginTime(), dto.getEndTime()); } - List dateList = DateUtils.betweenDayStrList(dto.getBeginTime(), dto.getEndTime()); // 这里将区间转换为具体的日期 因为mysql BETWEEN 会导致索引失效 if (flag) { logStatisticsDOS = logStatisticsMapper.getCurrentStatistics(dto.getFormId(), dateList); } else { - logStatisticsDOS = logStatisticsMapper.getStatistics(dto.getFormId(), dateList); + logStatisticsDOS = logStatisticsMapper.getStatistics(dto.getFormId(), dto.getUserId(), dto.getDeptId(), dateList); } List onTime = logStatisticsDOS.stream().filter(a -> a.getStatus() == 1).collect(Collectors.toList()); List late = logStatisticsDOS.stream().filter(a -> a.getStatus() == 2).collect(Collectors.toList()); @@ -251,7 +255,7 @@ public class LogStatisticsServiceImpl implements LogStatisticsService { // -- 需要提交的话查看下是否需要提交 if (flag) { List dateList = DateUtils.betweenDayList(beginDate, endDate); - List logUseVOS = logStatisticsMapper.getMyCurrentStatistics(userId, logFormDO.getId(), dateList); + List logUseVOS = logStatisticsMapper.getMyCurrentStatistics(userId, null, logFormDO.getId(), dateList); //按时提交数量 Integer onTimeNum = Math.toIntExact(logUseVOS.stream().filter(a -> a.getStatus() == 1).count()); //迟交数量 @@ -288,7 +292,7 @@ public class LogStatisticsServiceImpl implements LogStatisticsService { if (flag) { logStatisticsDOS = logStatisticsMapper.getCurrentStatistics(dto.getFormId(), dateList); } else { - logStatisticsDOS = logStatisticsMapper.getStatistics(dto.getFormId(), dateList); + logStatisticsDOS = logStatisticsMapper.getStatistics(dto.getFormId(), dto.getUserId(), dto.getDeptId(), dateList); } return logStatisticsDOS; } @@ -343,4 +347,40 @@ public class LogStatisticsServiceImpl implements LogStatisticsService { // 这里将区间转换为具体的日期 因为mysql BETWEEN 会导致索引失效 return logStatisticsMapper.getNeedWriteHistory(dto, dateList); } + + @Override + public List getMyManageModelStatistics(MyManageModelDTO dto) { + List formIds = logUseMapper.getFormIdsByDataPermission(null); + if (formIds.isEmpty()) { + return Collections.emptyList(); + } + List list = new ArrayList<>(); + List formList = logFormMapper.selectList(new LambdaQueryWrapper() + .in(LogFormDO::getId, formIds) + .eq(LogFormDO::getStatus, 0) + .isNotNull(LogFormDO::getRuleId) + ); + + for (LogFormDO logFormDO : formList) { + LogStatisticsModelVO vo = new LogStatisticsModelVO(); + BeanUtil.copyProperties(logFormDO, vo); + List dateList = new ArrayList<>(); + if (dto.getBeginTime() != null && dto.getEndTime() != null) { + dateList = DateUtils.betweenDayList(dto.getBeginTime(), dto.getEndTime()); + } + List logUseVOS = logStatisticsMapper.getMyCurrentStatistics(dto.getUserId(), dto.getDeptId(), logFormDO.getId(), dateList); + //按时提交数量 + Integer onTimeNum = Math.toIntExact(logUseVOS.stream().filter(a -> a.getStatus() == 1).count()); + //迟交数量 + Integer lateNum = Math.toIntExact(logUseVOS.stream().filter(a -> a.getStatus() == 2).count()); + //未提交数量 + Integer unSubmittedNum = Math.toIntExact(logUseVOS.stream().filter(a -> a.getStatus() == 3).count()); + //按天统计 + vo.setOnTimeNum(onTimeNum); + vo.setUnSubmittedNum(unSubmittedNum); + vo.setLateNum(lateNum); + list.add(vo); + } + return list; + } } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogStatisticsMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogStatisticsMapper.xml index 01762795..a04fa97a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogStatisticsMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogStatisticsMapper.xml @@ -33,7 +33,7 @@ a.dept_id AS deptId, c.`name` AS deptName, b.log_instance_ext_id AS logInstanceExtId, - b.`status` AS `status`, + ifnull(b.`status`,3) AS `status`, d.create_time AS createTime FROM system_users AS a @@ -44,6 +44,13 @@ AND b.form_id = #{formId} + + and a.id = #{userId} + + + and a.dept_id = #{deptId} + + AND b.time IN @@ -107,6 +114,9 @@ and a.use_user_id = #{userId} + + and a.use_user_dept = #{deptId} +