diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/PageUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/PageUtils.java index 45706ee1..6084e186 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/PageUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/PageUtils.java @@ -13,4 +13,15 @@ public class PageUtils { return (pageParam.getPageNo() - 1) * pageParam.getPageSize(); } + /** + * 根据当前页面,判断是否还有下一页 + * @param total + * @param pageParam + * @return + */ + public static boolean hasNextPage(int total, PageParam pageParam) { + int totalPages = (total + pageParam.getPageSize() - 1) / pageParam.getPageSize(); + return pageParam.getPageNo() < totalPages; + } + } diff --git a/yudao-gateway/src/main/resources/bootstrap-prod.yaml b/yudao-gateway/src/main/resources/bootstrap-prod.yaml index a073d0b9..a69d0f03 100644 --- a/yudao-gateway/src/main/resources/bootstrap-prod.yaml +++ b/yudao-gateway/src/main/resources/bootstrap-prod.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 47.97.8.94:8848 + server-addr: 127.0.0.1:8848 discovery: namespace: prod # 命名空间。这里使用 prod 生产环境环境 @@ -14,7 +14,7 @@ spring: nacos: # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 config: - server-addr: 47.97.8.94:8848 # Nacos 服务器地址 + server-addr: 127.0.0.1:8848 # Nacos 服务器地址 namespace: prod # 命名空间。这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP name: # 使用的 Nacos 配置集的 dataId,默认为 spring.application.name 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 eb02a3e7..97b89e5f 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 @@ -37,6 +37,7 @@ public interface ErrorCodeConstants { ErrorCode OA_ENTRY_NOT_EXISTS = new ErrorCode(1_009_001_111, "入职申请不存在"); ErrorCode OA_GOOut_NOT_EXISTS = new ErrorCode(1_009_001_112, "外出申请不存在"); ErrorCode OA_SALARY_NOT_EXISTS = new ErrorCode(1_009_001_113, "薪资付款申请不存在"); + ErrorCode OA_ASSET_NOT_EXISTS = new ErrorCode(1_009_001_114, "资产申领不存在"); // ========== 流程模型 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/financialpayment/FinancialPaymentController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/financialpayment/FinancialPaymentController.java index 2398a8eb..6e6e0e7a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/financialpayment/FinancialPaymentController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/financialpayment/FinancialPaymentController.java @@ -41,14 +41,12 @@ public class FinancialPaymentController { @PostMapping("/create") @Operation(summary = "创建财务支付子表") - @PreAuthorize("@ss.hasPermission('bpm:financial-payment:create')") public CommonResult createFinancialPayment(@Valid @RequestBody FinancialPaymentSaveVO vo) { return success(financialPaymentService.createFinancialPayment(vo)); } @PutMapping("/update") @Operation(summary = "更新财务支付管理") - @PreAuthorize("@ss.hasPermission('bpm:financial-payment:update')") public CommonResult updateFinancialPayment(@Valid @RequestBody FinancialPaymentSaveReqVO updateReqVO) { financialPaymentService.updateFinancialPayment(updateReqVO); return success(true); @@ -71,7 +69,6 @@ public class FinancialPaymentController { @DeleteMapping("/delete") @Operation(summary = "删除财务支付管理") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('bpm:financial-payment:delete')") public CommonResult deleteFinancialPayment(@RequestParam("id") Long id) { financialPaymentService.deleteFinancialPayment(id); return success(true); @@ -80,7 +77,6 @@ public class FinancialPaymentController { @GetMapping("/get") @Operation(summary = "获得财务支付管理") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('bpm:financial-payment:query')") public CommonResult getFinancialPayment(@RequestParam("id") Long id) { FinancialPaymentDO financialPayment = financialPaymentService.getFinancialPayment(id); FinancialPaymentRespVO vo = BeanUtils.toBean(financialPayment, FinancialPaymentRespVO.class); @@ -105,7 +101,6 @@ public class FinancialPaymentController { @GetMapping("/page") @Operation(summary = "获得财务支付管理分页") - @PreAuthorize("@ss.hasPermission('bpm:financial-payment:query')") public CommonResult> getFinancialPaymentPage(@Valid FinancialPaymentPageReqVO pageReqVO) { PageResult pageResult = financialPaymentService.getFinancialPaymentPage(pageReqVO); return success(BeanUtils.toBean(pageResult, FinancialPaymentRespVO.class)); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAAssetClaimController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAAssetClaimController.java new file mode 100644 index 00000000..73544484 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAAssetClaimController.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.assetClaim.BpmOAAssetClaimCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.assetClaim.BpmOAAssetClaimRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAAssetClaimDO; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAAssetClaimService; +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 static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - OA 资金申领") +@RestController +@RequestMapping("/bpm/oa/assetClaim") +@Validated +public class BpmOAAssetClaimController { + + @Resource + private BpmOAAssetClaimService assetClaimService; + + @PostMapping("/create") + @Operation(summary = "创建请求申请") + public CommonResult createAssetClaim(@Valid @RequestBody BpmOAAssetClaimCreateReqVO createReqVO) { + + return success(assetClaimService.createAssetClaim(getLoginUserId(), createReqVO)); + } + + @GetMapping("/get") + @Operation(summary = "获得资金申领申请") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + public CommonResult getAssetClaim(@RequestParam("id") Long id) { + + BpmOAAssetClaimDO assetClaimDO = assetClaimService.getAssetClaim(id); + + return success(BeanUtils.toBean(assetClaimDO, BpmOAAssetClaimRespVO.class)); + } + + @GetMapping("/getByProcessInstanceId") + @Operation(summary = "获得资金申领申请") + @Parameter(name = "processInstanceId", description = "流程实例编号", required = true, example = "1024") + public CommonResult getAssetClaimByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) { + + BpmOAAssetClaimDO assetClaimDO = assetClaimService.getByProcessInstanceId(processInstanceId); + + return success(BeanUtils.toBean(assetClaimDO, BpmOAAssetClaimRespVO.class)); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAEvectionController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAEvectionController.java index 87032694..941fe8f3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAEvectionController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAEvectionController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.controller.admin.oa; +import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.evection.BpmOAEvectionCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.evection.BpmOAEvectionRespVO; @@ -16,8 +17,10 @@ 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.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** @@ -54,9 +57,9 @@ public class BpmOAEvectionController { BpmOAEvectionRespVO respVO = BpmOAEvectionConvert.INSTANCE.convert(evection); - if (evection.getTogetherUserId() != null) { - AdminUserRespDTO userRespDTO = userApi.getUser(evection.getTogetherUserId()).getCheckedData(); - respVO.setTogetherUserName(userRespDTO.getNickname()); + if (CollectionUtil.isNotEmpty(evection.getTogetherUserIds())) { + List userRespDTOs = userApi.getUserList(respVO.getTogetherUserIds()).getCheckedData(); + respVO.setTogetherUserName(String.join("、", convertList(userRespDTOs, AdminUserRespDTO::getNickname))); } return success(respVO); @@ -71,9 +74,9 @@ public class BpmOAEvectionController { BpmOAEvectionRespVO respVO = BpmOAEvectionConvert.INSTANCE.convert(evection); - if (evection.getTogetherUserId() != null) { - AdminUserRespDTO userRespDTO = userApi.getUser(evection.getTogetherUserId()).getCheckedData(); - respVO.setTogetherUserName(userRespDTO.getNickname()); + if (CollectionUtil.isNotEmpty(evection.getTogetherUserIds())) { + List userRespDTOs = userApi.getUserList(evection.getTogetherUserIds()).getCheckedData(); + respVO.setTogetherUserName(String.join("、", convertList(userRespDTOs, AdminUserRespDTO::getNickname))); } return success(respVO); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASalaryController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASalaryController.java index 969e6cad..7bbb3207 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASalaryController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASalaryController.java @@ -42,6 +42,10 @@ public class BpmOASalaryController { @Operation(summary = "创建请求申请") public CommonResult createSalary(@Valid @RequestBody BpmOASalaryCreateReqVO createReqVO) { + if (createReqVO.getFactoryId() != null) { + DeptRespDTO dto = deptApi.getDeptByFactoryId(createReqVO.getFactoryId()).getCheckedData(); + createReqVO.setCompanyDeptId(dto.getId()); + } return success(salaryService.createSalary(getLoginUserId(), createReqVO)); } @@ -51,9 +55,18 @@ public class BpmOASalaryController { public CommonResult getSalary(@RequestParam("id") Long id) { BpmOASalaryDO salary = salaryService.getSalary(id); + if (salary == null) { + return success(new BpmOASalaryRespVO()); + } - return success(BpmOASalaryConvert.INSTANCE.convert(salary) - .setCompanyName(getDept(salary.getCompanyDeptId()).getName())); + // 获取部门详情 + DeptRespDTO dto = getDept(salary.getCompanyDeptId()); + + BpmOASalaryRespVO respVO = BpmOASalaryConvert.INSTANCE.convert(salary) + .setCompanyName(dto.getName()) + .setFactoryId(dto.getFactoryId()); + + return success(respVO); } @GetMapping("/getByProcessInstanceId") @@ -63,8 +76,14 @@ public class BpmOASalaryController { BpmOASalaryDO salary = salaryService.getByProcessInstanceId(processInstanceId); - return success(BpmOASalaryConvert.INSTANCE.convert(salary) - .setCompanyName(getDept(salary.getCompanyDeptId()).getName())); + // 获取部门详情 + DeptRespDTO dto = getDept(salary.getCompanyDeptId()); + + BpmOASalaryRespVO respVO = BpmOASalaryConvert.INSTANCE.convert(salary) + .setCompanyName(dto.getName()) + .setFactoryId(dto.getFactoryId()); + + return success(respVO); } /** diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASupplierProcurementPlanController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASupplierProcurementPlanController.java index a59bf6f3..69ef4a46 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASupplierProcurementPlanController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOASupplierProcurementPlanController.java @@ -78,6 +78,14 @@ public class BpmOASupplierProcurementPlanController { return success(BeanUtils.toBean(pageResult, BpmOASupplierProcurementPlanRespVO.class)); } + @GetMapping("/getPlanItem") + @Operation(summary = "获得供应商采购计划商品列表") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + public CommonResult> getPlanItem(@RequestParam("id") Long id) { + List items = oaSupplierProcurementPlanItemService.getByProcurementPlanId(id); + List itemVos = BeanUtils.toBean(items, BpmOASupplierProcurementPlanItemRespVO.class); + return success(itemVos); + } @GetMapping("/getListBySupplierId") @Operation(summary = "根据供应商id获取采购计划列表") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/assetClaim/BpmOAAssetClaimCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/assetClaim/BpmOAAssetClaimCreateReqVO.java new file mode 100644 index 00000000..ecdb43f9 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/assetClaim/BpmOAAssetClaimCreateReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.assetClaim; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 资产申领 创建 Request VO + * + * @author 符溶馨 + */ +@Schema(description = "管理后台 - 资产申领创建 Request VO") +@Data +@EqualsAndHashCode() +@ToString(callSuper = true) +public class BpmOAAssetClaimCreateReqVO { + + @Schema(description = "收款人信息", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "报销总金额不能为空") + private Long assetsTypeId; + + @Schema(description = "现金支出明细") + private Integer num; + + @Schema(description = "单位") + private String util; + + @Schema(description = "流程实例编号") + private String processInstanceId; + + @Schema(description = "状态-参见 bpm_process_instance_result 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer result; + + @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/assetClaim/BpmOAAssetClaimRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/assetClaim/BpmOAAssetClaimRespVO.java new file mode 100644 index 00000000..c1db832d --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/assetClaim/BpmOAAssetClaimRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.assetClaim; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.cash.Cash; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.List; + +/** + * @author 符溶馨 + */ +@Schema(description = "管理后台 - 现金支出 请求Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BpmOAAssetClaimRespVO extends BpmOABaseRespVO { + + @Schema(description = "收款人信息") + private Long assetsTypeId; + + @Schema(description = "现金支出明细") + private List num; + + @Schema(description = "报销总金额", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "报销总金额不能为空") + private BigDecimal util; + + @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/evection/BpmOAEvectionCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionCreateReqVO.java index 6f11302f..f73ff020 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionCreateReqVO.java @@ -11,6 +11,7 @@ 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; @@ -30,7 +31,7 @@ public class BpmOAEvectionCreateReqVO { private String reason; @Schema(description = "随行人用户编号") - private Long togetherUserId; + private Set togetherUserIds; @Schema(description = "出差起点", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "出差起点不能为空") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionRespVO.java index b62c17ea..0e882979 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/evection/BpmOAEvectionRespVO.java @@ -12,6 +12,7 @@ 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; @@ -29,7 +30,7 @@ public class BpmOAEvectionRespVO extends BpmOABaseRespVO { private String reason; @Schema(description = "随行人用户编号") - private Long togetherUserId; + private Set togetherUserIds; @Schema(description = "随行人用户名称") private String togetherUserName; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularCreateReqVO.java index 1ef6b506..41030e41 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularCreateReqVO.java @@ -37,6 +37,10 @@ public class BpmOARegularCreateReqVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) private LocalDate confirmationDate; + @Schema(description = "期望转正时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate desireDate; + @Schema(description = "备注", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private String notes; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularRespVO.java index a2c20fd3..9a0d45ca 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/regular/BpmOARegularRespVO.java @@ -36,6 +36,10 @@ public class BpmOARegularRespVO extends BpmOABaseRespVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) private LocalDate confirmationDate; + @Schema(description = "期望转正时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate desireDate; + @Schema(description = "备注", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private String notes; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java index d96b67ba..17f537b3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryCreateReqVO.java @@ -5,15 +5,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; import java.math.BigDecimal; -import java.time.LocalDate; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; - /** * 薪资付款申请 创建 Request VO * @@ -29,10 +25,12 @@ public class BpmOASalaryCreateReqVO { @NotNull(message = "申请原因不能为空") private String reason; - @Schema(description = "付款公司", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "付款公司不能为空") + @Schema(description = "付款公司") private Long companyDeptId; + @Schema(description = "付款工厂编号") + private Long factoryId; + @Schema(description = "付款总额", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "付款总额不能为空") private BigDecimal paymentTotal; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java index 5e73265f..b853a85c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/salary/BpmOASalaryRespVO.java @@ -6,15 +6,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; -import javax.validation.constraints.NotNull; import java.math.BigDecimal; -import java.time.LocalDate; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; - /** * @author 符溶馨 */ @@ -33,6 +28,9 @@ public class BpmOASalaryRespVO extends BpmOABaseRespVO { @Schema(description = "付款公司名称") private String companyName; + @Schema(description = "付款工厂") + private Long FactoryId; + @Schema(description = "付款总额") private BigDecimal paymentTotal; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanPageReqVO.java index f435c36f..527e0919 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanPageReqVO.java @@ -48,6 +48,9 @@ public class BpmOASupplierProcurementPlanPageReqVO extends PageParam { @Schema(description = "是否上传凭证 0否 1是") private Integer certificateFlag; + @Schema(description = "是否已分配到资产中 0否 1是", example = "5984") + private Integer assignedFlag; + @Schema(description = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanReqVO.java index 16c7fcca..5a03073a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanReqVO.java @@ -17,6 +17,9 @@ public class BpmOASupplierProcurementPlanReqVO { @Schema(description = "供应商id", example = "123") private Long supplierId; + @Schema(description = "是否已分配到资产中 0否 1是", example = "5984") + private Integer assignedFlag; + @Schema(description = "流程实例的编号", example = "5984") private String processInstanceId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanRespVO.java index 5aa316a5..37a1f4c8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanRespVO.java @@ -41,6 +41,9 @@ public class BpmOASupplierProcurementPlanRespVO { @Schema(description = "备注") private String remark; + @Schema(description = "是否已分配到资产中 0否 1是", example = "5984") + private Integer assignedFlag; + @Schema(description = "流程实例的编号", example = "5984") private String processInstanceId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanSaveReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanSaveReqVO.java index ff3ffe2e..4b8ddeea 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanSaveReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierprocurementplan/BpmOASupplierProcurementPlanSaveReqVO.java @@ -42,6 +42,9 @@ public class BpmOASupplierProcurementPlanSaveReqVO { @Schema(description = "备注") private String remark; + @Schema(description = "是否已分配到资产中 0否 1是", example = "5984") + private Integer assignedFlag; + @Schema(description = "流程实例的编号", example = "5984") private String processInstanceId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierpurchasepayment/BpmOASupplierPurchasePaymentSaveReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierpurchasepayment/BpmOASupplierPurchasePaymentSaveReqVO.java index 5eee9148..1c75da61 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierpurchasepayment/BpmOASupplierPurchasePaymentSaveReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/supplierpurchasepayment/BpmOASupplierPurchasePaymentSaveReqVO.java @@ -18,7 +18,6 @@ public class BpmOASupplierPurchasePaymentSaveReqVO { private Long id; @Schema(description = "申请人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "14357") - @NotNull(message = "申请人的用户编号不能为空") private Long userId; @Schema(description = "供应商id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13580") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java index cde137a2..c5a9f9f9 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java @@ -198,4 +198,13 @@ public class BpmTaskController { return success(taskService.getTaskListByProcessInstanceIds(historyProcessInstanceIds)); } + + + @GetMapping("getCurrentToDoProcessInstacePreAndNex-page") + @Operation(summary = "获取当前待处理流程实例(带查询条件),上一个流程和下一个流程的实例ID") + public CommonResult> getCurrentToDoProcessInstacePreAndNex(@RequestParam("processInstanceId") String processInstanceId,@Valid BpmTaskTodoPageReqVO pageVO) { + return success(taskService.getCurrentToDoProcessInstacePreAndNex(getLoginUserId(), processInstanceId, pageVO)); + } + + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java index 52b1258c..d96531e8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -61,4 +62,7 @@ public class BpmProcessInstancePageItemRespVO { private String userName ; } + @Schema(description = "业务表字段信息", example = "报销总金额:999.11,开户行信息:银行卡,收款人卡号:1234567") + private String detailInfo ; + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java index bc1ee019..884171ea 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java @@ -55,6 +55,10 @@ public interface BpmProcessInstanceConvert { Map> taskMap, Map userMap ) { List list = convertList(page.getList()); + for (int i = 0; i < list.size(); i++) { + BpmProcessInstancePageItemRespVO vo = list.get(i) ; + vo.setDetailInfo(page.getList().get(i).getDetailInfo()) ; + } list.forEach(respVO -> respVO.setTasks(convertList2(taskMap.get(respVO.getId()),userMap))); return new PageResult<>(list, page.getTotal()); } @@ -96,6 +100,7 @@ public interface BpmProcessInstanceConvert { String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) { BpmProcessInstanceRespVO respVO = convert2(processInstance); copyTo(processInstanceExt, respVO); + respVO.setBusinessKey(processInstance.getBusinessKey()) ; // definition respVO.setProcessDefinition(convert2(processDefinition)); copyTo(processDefinitionExt, respVO.getProcessDefinition()); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAAssetClaimDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAAssetClaimDO.java new file mode 100644 index 00000000..4472c1e1 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAAssetClaimDO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; + +import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; + +import java.util.List; + +/** + * OA 资产申领 DO + * + * @author 符溶馨 + */ +@TableName(value ="bpm_oa_asset_claim", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BpmOAAssetClaimDO extends BaseDO { + + /** + * 出差表单主键 + */ + @TableId + private Long id; + + /** + * 申请人的用户编号 + * 关联 AdminUserDO 的 id 属性 + */ + private Long userId; + + /** + * 资产类型编号 + */ + private Long assetsTypeId; + + /** + * 数量 + */ + private Integer num; + + /** + * 单位 + */ + private String util; + + /** + * 申请事由 + */ + 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/BpmOAEvectionDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAEvectionDO.java index 10d2006d..08b8bbbe 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAEvectionDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAEvectionDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -12,6 +13,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; +import java.util.Set; /** * OA 出差申请 DO @@ -48,9 +50,10 @@ public class BpmOAEvectionDO extends BaseDO { private String reason; /** - * 随行人用户编号 + * 随行人用户编号组 */ - private Long togetherUserId; + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set togetherUserIds; /** * 出差地点 起点 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOARegularDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOARegularDO.java index 12db2ee2..e2aefb23 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOARegularDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOARegularDO.java @@ -36,7 +36,6 @@ public class BpmOARegularDO extends BaseDO { /** * 申请人的用户编号 - * * 关联 AdminUserDO 的 id 属性 */ private Long userId; @@ -56,13 +55,18 @@ public class BpmOARegularDO extends BaseDO { */ private LocalDate confirmationDate; + /** + * 期望转正时间 + */ + private LocalDate desireDate; + /** * 备注 */ private String notes; /** - * 出差的结果 + * 结果 * * 枚举 {@link BpmProcessInstanceResultEnum} * 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASupplierProcurementPlanDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASupplierProcurementPlanDO.java index 4140eeb5..e0c6a569 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASupplierProcurementPlanDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOASupplierProcurementPlanDO.java @@ -70,6 +70,10 @@ public class BpmOASupplierProcurementPlanDO extends BaseDO { * 备注 */ private String remark; + /** + * 是否已分配到资产中 0否 1是 + */ + private Integer assignedFlag; /** * 流程实例的编号 */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java index 535b7219..d1147f94 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java @@ -93,4 +93,27 @@ public class BpmProcessInstanceExtDO extends BaseDO { @TableField(typeHandler = JacksonTypeHandler.class) private Map formVariables; + /** + * 流程业务主键ID + */ + @TableField(exist = false) + private String businessKey ; + + /** + * 当前流程实例对应的表名称 + */ + @TableField(exist = false) + private String tableName ; + + /** + * 当前流程实例在我的流程列表中需要显示的字段中英文 + */ + @TableField(exist = false) + private String fieldNames ; + + /** + * 当前流程实例在我的流程列表中需要显示的转换后的数据 + */ + @TableField(exist = false) + private String detailInfo ; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/DynamicMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/DynamicMapper.java new file mode 100644 index 00000000..33d9bd05 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/DynamicMapper.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.bpm.dal.mysql; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Map; + +/** + * 功能描述 + * + * @author: yj + * @date: 2024年09月24日 12:10 + */ +@Mapper +public interface DynamicMapper extends BaseMapperX { + + @Select("${SQL}") + Map selectListByTableName(@Param("SQL")String sql); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAAssetClaimMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAAssetClaimMapper.java new file mode 100644 index 00000000..8168557e --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAAssetClaimMapper.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.BpmOAAssetClaimDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 资产申领 Mapper + * + * @author 符溶馨 + + */ +@Mapper +public interface BpmOAAssetClaimMapper extends BaseMapperX { +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java index a74ba74f..bd1b3a53 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java @@ -3,13 +3,18 @@ package cn.iocoder.yudao.module.bpm.dal.mysql.task; 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.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import org.apache.ibatis.annotations.Mapper; import java.util.Arrays; import java.util.List; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + @Mapper public interface BpmProcessInstanceExtMapper extends BaseMapperX { @@ -30,9 +35,34 @@ public interface BpmProcessInstanceExtMapper extends BaseMapperX selectPage(Long userId, BpmProcessInstanceMyPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - //只能查询流程标识定义为oa开头的流程 - .likeIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, "oa_") +// return selectPage(reqVO, new LambdaQueryWrapperX() +// //只能查询流程标识定义为oa开头的流程 +// .likeIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, "oa_") +// .eqIfPresent(BpmProcessInstanceExtDO::getStartUserId, userId) +// .likeIfPresent(BpmProcessInstanceExtDO::getName, reqVO.getName()) +// .eqIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, reqVO.getProcessDefinitionId()) +// .eqIfPresent(BpmProcessInstanceExtDO::getCategory, reqVO.getCategory()) +// .eqIfPresent(BpmProcessInstanceExtDO::getStatus, reqVO.getStatus()) +// .eqIfPresent(BpmProcessInstanceExtDO::getResult, reqVO.getResult()) +// .betweenIfPresent(BpmProcessInstanceExtDO::getCreateTime, reqVO.getCreateTime()) +// .orderByDesc(BpmProcessInstanceExtDO::getId)); + Long tenantId = TenantContextHolder.getTenantId() ; + MPJLambdaWrapperX queryWrapper = new MPJLambdaWrapperX<>(); + queryWrapper.selectAll(BpmProcessInstanceExtDO.class); + queryWrapper.selectAs("b.BUSINESS_KEY_", BpmProcessInstanceExtDO::getBusinessKey); + queryWrapper.selectAs("d.name", BpmProcessInstanceExtDO::getTableName); + queryWrapper.selectAs("d.field_names", BpmProcessInstanceExtDO::getFieldNames); + queryWrapper.leftJoin(BpmProcessDefinitionExtDO.class,"e", on -> on. + eq(BpmProcessDefinitionExtDO::getProcessDefinitionId, + BpmProcessInstanceExtDO::getProcessDefinitionId)) ; + //通过流程定义的关联业务配置表单ID,获取业务表,需要显示的中文名及英文字段 + queryWrapper.leftJoin("bpm_business_table_info d on e.business_table_info_id = d.id") ; + //通过流程实例ID 获取流程业务主键ID + queryWrapper.leftJoin("ACT_HI_PROCINST b on b.PROC_INST_ID_ = t.process_instance_id") ; + //通过流程业务主键ID 查询对应的业务表,获取业务数据 业务表名,是通过流程定义获取 + //queryWrapper.leftJoin("(select * from ( select name from bpm_business_table_info where id = e.business_table_info_id ) ) c on b.BUSINESS_KEY_ = c.id") ; + queryWrapper.eq("t.TENANT_ID", tenantId); + queryWrapper.likeIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, "oa_") .eqIfPresent(BpmProcessInstanceExtDO::getStartUserId, userId) .likeIfPresent(BpmProcessInstanceExtDO::getName, reqVO.getName()) .eqIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, reqVO.getProcessDefinitionId()) @@ -40,7 +70,8 @@ public interface BpmProcessInstanceExtMapper extends BaseMapperX processInstanceVariables = new HashMap<>(); + String processInstanceId = processInstanceService.createProcessInstance(userId, + new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) + .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(assetClaim.getId()))); + + // 将工作流的编号,更新到 OA 现金支出单中 + assetClaimMapper.updateById(new BpmOAAssetClaimDO().setId(assetClaim.getId()).setProcessInstanceId(processInstanceId)); + + // 判断是否为重新发起的流程 + if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) { + + historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId()); + } + + List fileItems = createReqVO.getFileItems(); + //这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id + if (fileItems != null && !fileItems.isEmpty()) { + uploadBpmFileProcessInstanceId(processInstanceId, fileItems); + } + return assetClaim.getId(); + } + + @Override + public BpmOAAssetClaimDO getAssetClaim(Long id) { + + return assetClaimMapper.selectById(id); + } + + @Override + public BpmOAAssetClaimDO getByProcessInstanceId(String processInstanceId) { + + return assetClaimMapper.selectOne(BpmOAAssetClaimDO::getProcessInstanceId, processInstanceId); + } + + @Override + public void updateAssetClaimResult(String processInstanceId, Long id, Integer result) { + + validateLeaveExists(id); + assetClaimMapper.updateById(new BpmOAAssetClaimDO().setId(id).setResult(result)); + } + + private void validateLeaveExists(Long id) { + if (assetClaimMapper.selectById(id) == null) { + throw exception(OA_ASSET_NOT_EXISTS); + } + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAGoOutServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAGoOutServiceImpl.java index c241e274..9af9f160 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAGoOutServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAGoOutServiceImpl.java @@ -97,7 +97,6 @@ public class BpmOAGoOutServiceImpl extends BpmOABaseService implements BpmOAGoOu // -- 自己取消 // -- 审核拒绝 - //所有关联的采购申请改为 未支付状态 if (BpmProcessInstanceResultEnum.REJECT.getResult().equals(result) || BpmProcessInstanceResultEnum.CANCEL.getResult().equals(result) || BpmProcessInstanceResultEnum.BACK.getResult().equals(result)) { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularService.java index 375afa6b..f3e3c3c6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularService.java @@ -28,7 +28,7 @@ public interface BpmOARegularService { * @param id 编号 * @param result 结果 */ - void updateRegularResult(Long id, Integer result); + void updateRegularResult(String processInstanceId, Long id, Integer result); /** * 获得转正申请 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularServiceImpl.java index 9c25d532..dbaf8160 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOARegularServiceImpl.java @@ -1,21 +1,37 @@ package cn.iocoder.yudao.module.bpm.service.oa; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 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.regular.BpmOARegularCreateReqVO; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.Reimbursement; import cn.iocoder.yudao.module.bpm.convert.oa.BpmOARegularConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO; +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.BpmOARegularDO; +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.oa.BpmOARegularMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_REGULAR_NOT_EXISTS; @@ -44,6 +60,12 @@ public class BpmOARegularServiceImpl extends BpmOABaseService implements BpmOARe @Resource private BpmHistoryProcessInstanceService historyProcessInstanceService; + @Resource + private BpmProcessInstanceService bpmProcessInstanceService; + + @Resource + private AdminUserApi userApi; + @Override public Long createRegular(Long userId, BpmOARegularCreateReqVO createReqVO) { @@ -76,9 +98,21 @@ public class BpmOARegularServiceImpl extends BpmOABaseService implements BpmOARe } @Override - public void updateRegularResult(Long id, Integer result) { + public void updateRegularResult(String processInstanceId, Long id, Integer result) { validateLeaveExists(id); + //审核通过 (最后节点) + if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) { + + ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId); + + if (instance.isEnded()) { + + // 同步修改用户编制状态为在职状态 + userApi.updateUserStaffing(Long.valueOf(instance.getStartUserId()), 7); + } + } + regularMapper.updateById(new BpmOARegularDO().setId(id).setResult(result)); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierProcurementPlanServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierProcurementPlanServiceImpl.java index 1affb7f2..7b29c774 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierProcurementPlanServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierProcurementPlanServiceImpl.java @@ -165,10 +165,11 @@ public class BpmOASupplierProcurementPlanServiceImpl extends BpmOABaseService im public void uploadDeliveryReceipt(TheArrivalFileItemsVO vo) { BpmOASupplierProcurementPlanDO supplierProcurementPlanDO = oaSupplierProcurementPlanMapper.selectById(vo.getId()); //判断是否需要更新到资产 - Boolean updateAssetFlag = false; - if (CollectionUtil.isEmpty(supplierProcurementPlanDO.getTheArrivalFileItems())) { + boolean updateAssetFlag = false; + if (supplierProcurementPlanDO.getAssignedFlag() == 0) { updateAssetFlag = true; } + supplierProcurementPlanDO.setAssignedFlag(1); supplierProcurementPlanDO.setTheArrivalFileItems(vo.getTheArrivalFileItems()); oaSupplierProcurementPlanMapper.updateById(supplierProcurementPlanDO); // ----- 如果需要更新到资产 - diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierPurchasePaymentServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierPurchasePaymentServiceImpl.java index 3d32538b..aede1898 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierPurchasePaymentServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOASupplierPurchasePaymentServiceImpl.java @@ -22,6 +22,7 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService; import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.system.api.supplier.SupplierApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -66,7 +67,8 @@ public class BpmOASupplierPurchasePaymentServiceImpl extends BpmOABaseService im private BpmOASupplierProcurementPlanMapper supplierProcurementPlanMapper; @Resource private BpmOASupplierProcurementPlanItemMapper supplierProcurementPlanItemMapper; - + @Resource + private SupplierApi supplierApi; /** * 供应商采购支付 @@ -76,9 +78,9 @@ public class BpmOASupplierPurchasePaymentServiceImpl extends BpmOABaseService im @Override public Long createOASupplierPurchasePayment(BpmOASupplierPurchasePaymentSaveReqVO createReqVO) { // 插入 + Long userId = WebFrameworkUtils.getLoginUserId(); BpmOASupplierPurchasePaymentDO supplierPurchasePaymentDO = BeanUtils.toBean(createReqVO, BpmOASupplierPurchasePaymentDO.class); supplierPurchasePaymentMapper.insert(supplierPurchasePaymentDO); - Long userId = WebFrameworkUtils.getLoginUserId(); // 发起 BPM 流程 Map processInstanceVariables = new HashMap<>(); @@ -118,7 +120,10 @@ public class BpmOASupplierPurchasePaymentServiceImpl extends BpmOABaseService im @Override public BpmOASupplierPurchasePaymentDO getOASupplierPurchasePayment(Long id) { - BpmOASupplierPurchasePaymentDO supplierPurchasePaymentDO = supplierPurchasePaymentMapper.getById(id); + BpmOASupplierPurchasePaymentDO supplierPurchasePaymentDO = supplierPurchasePaymentMapper.selectById(id); + // 根据supplierId 供应商id查询供应商 + CommonResult result = supplierApi.getNameById(supplierPurchasePaymentDO.getSupplierId()); + supplierPurchasePaymentDO.setSupplierName(result.getData()); List supplierProcurementPlanIds = Arrays.stream(supplierPurchasePaymentDO.getSupplierProcurementPlanIds().split(",")).map(Long::valueOf).collect(Collectors.toList()); List planDOS = supplierProcurementPlanMapper.selectList(new LambdaQueryWrapper().in(BpmOASupplierProcurementPlanDO::getId, supplierProcurementPlanIds)); List planItemDOS = supplierProcurementPlanItemMapper.selectList(new LambdaQueryWrapper().in(BpmOASupplierProcurementPlanItemDO::getProcurementPlanId, supplierProcurementPlanIds)); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAAssetClaimResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAAssetClaimResultListener.java new file mode 100644 index 00000000..c8b76ac9 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOAAssetClaimResultListener.java @@ -0,0 +1,32 @@ +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.BpmOAAssetClaimService; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAAssetClaimServiceImpl; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * OA 现金支出的结果的监听器实现类 + * + * @author 符溶馨 + */ +@Component +public class BpmOAAssetClaimResultListener extends BpmProcessInstanceResultEventListener { + @Resource + private BpmOAAssetClaimService assetClaimService; + + @Override + protected String getProcessDefinitionKey() { + + return BpmOAAssetClaimServiceImpl.PROCESS_KEY; + } + + @Override + protected void onEvent(BpmProcessInstanceResultEvent event) { + + assetClaimService.updateAssetClaimResult(event.getId(), 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/oa/listener/BpmOARegularResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOARegularResultListener.java index 85da3c7a..0e00ac6e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOARegularResultListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOARegularResultListener.java @@ -27,6 +27,6 @@ public class BpmOARegularResultListener extends BpmProcessInstanceResultEventLis @Override protected void onEvent(BpmProcessInstanceResultEvent event) { - regularService.updateRegularResult(Long.parseLong(event.getBusinessKey()), event.getResult()); + regularService.updateRegularResult(event.getId(), 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 78fe109e..dbddfbc9 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.collection.CollectionUtil; import cn.hutool.core.date.LocalDateTimeUtil; 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.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; 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.cash.BpmOACashRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmOACashPrintDataRespVO; 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.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.BpmOACashDO; 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.*; import cn.iocoder.yudao.module.infra.api.config.ConfigApi; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.api.bank.BankApi; 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.time.temporal.ChronoUnit; 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; @Resource private ConfigApi configApi; @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 @DataPermission(enable = false) 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 @DataPermission(enable = false) 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) @DataPermission(enable = false) 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) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .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); } // 设置当前用户 FlowableUtils.setAuthenticatedUserId(userId); // 创建流程实例 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 * @param * @return */ 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); String BpmConstantsName = BpmConstants.CC_NAME; // 获取发起人信息 AdminUserRespDTO userRespDTO = adminUserApi.getUser(Long.valueOf(instance.getStartUserId())).getCheckedData(); DeptRespDTO deptRespDTO = deptApi.getDept(userRespDTO.getDeptId()).getCheckedData(); //发起人是深圳分公司 if (deptRespDTO.getFlag().contains("136")) { BpmConstantsName = BpmConstants.CCSZ_NAME; } for (BpmTaskAssignRuleDO rule : rules) { String key = rule.getTaskDefinitionKey(); //任务名称 Integer type = rule.getType(); if (!key.isEmpty() && key.equals(BpmConstantsName) && 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)) { //发起人部门为 生产部及以下时 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 @DataPermission(enable = false) public BpmProcessInstanceExtDO getProcessInstanceDO(String id) { return processInstanceExtMapper.selectByProcessInstanceId(id); } @Resource private FileApi fileApi; @Resource private BankApi bankApi; @Resource @Lazy // 解决循环依赖 private BpmOAReimbursementService reimbursementService; @Resource @Lazy // 解决循环依赖 private BpmOACashService cashService; @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 // 判断是否可见外勤人员信息 List userIds = new ArrayList<>(); String type = configApi.getConfigKey("sys.user.type").getCheckedData(); if ("1".equals(type)) { //不可见时 // 获取所有外勤人员 用户编号 userIds = adminUserApi.getUserIdsByUserNature(4).getCheckedData(); } // 获得流程审批信息 List taskRespVOList = taskService.getTaskListByProcessInstanceId(processInstanceId); // 移除外勤人员信息 List finalUserIds = userIds; taskRespVOList.removeIf(data -> finalUserIds.contains(data.getAssigneeUser().getId())); //给User添加签名地址 taskRespVOList.forEach(taskRespVO -> taskRespVO.getAssigneeUser().setSignURL( fileApi.getUserSignImgPath( taskRespVO.getAssigneeUser().getId() ).getData() ) ); //获取流程抄送用户编号 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))); } // 移除 外勤人员信息 ccUserIds.removeAll(userIds); } List userRespDTOS = adminUserApi.getUserList(ccUserIds).getCheckedData(); //获取抄送用户部门信息 Map deptMapDTO = deptApi.getDeptMap(convertSet(userRespDTOS, AdminUserRespDTO::getDeptId)); if ("oa_reimbursement".equals(key)) { //报销流程 BpmOAReimbursementDO reimbursement = reimbursementService.getReimbursement(businessKey); BpmOAReimbursementRespVO bpmOAReimbursementRespVO = reimbursementService.convert(reimbursement); //报销业务数据 // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(reimbursement.getUserId())); //备用金信息查询 BpmOAImprestDO bpmOAImprestDO = imprestService.getImprestByReimbursementId(reimbursement.getId()); if (bpmOAImprestDO != null) { //设置备用金 金额 bpmOAReimbursementRespVO.setAmount(bpmOAImprestDO.getAmount()); } // 设置抄送人信息 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); } if ("oa_cash".equals(key)) { BpmOACashDO cashDO = cashService.getCash(businessKey); BpmOACashRespVO cashRespVO = cashService.convertCash(cashDO); // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(cashDO.getUserId())); // 设置抄送人信息 List ccUsers = userRespDTOS.stream().map(user -> { BpmOACashPrintDataRespVO.CCUser cc = new BpmOACashPrintDataRespVO.CCUser(); cc.setCcUserId(user.getId()); cc.setCcUserName(user.getNickname()); cc.setCcDeptName(deptMapDTO.get(user.getDeptId()).getName()); return cc; }).collect(Collectors.toList()); BpmOACashPrintDataRespVO cashPrintData = new BpmOACashPrintDataRespVO(); cashPrintData.setBpmOACashRespVO(cashRespVO); cashPrintData.setProcessTasks(taskRespVOList); cashPrintData.setCcUsers(ccUsers); bpmProcessInstancePrintDataRespVO.setBpmOACashPrintDataRespVO(cashPrintData); } return bpmProcessInstancePrintDataRespVO; } @Override public Map> getProcessInstanceResultStatusStatisticsGroupTime(BpmProcessInstanceStatisticsReqVO pageReqVO) { pageReqVO = getUserids(pageReqVO); pageReqVO.setRecentDays(pageReqVO.getRecentDays() == null ? 7 : pageReqVO.getRecentDays()); List list = processInstanceExtMapper.getProcessInstanceResultStatusStatisticsGroupTime(pageReqVO); // -- 获取到日期列表 LocalDateTime now = LocalDateTimeUtil.now(); LocalDateTime offset = LocalDateTimeUtil.offset(LocalDateTimeUtil.now(), -1L * pageReqVO.getRecentDays(), ChronoUnit.DAYS); List dateList = DateUtils.betweenDayList(offset, now); //根据时间分组 Map> map = list.stream().collect(Collectors.groupingBy(BpmProcessInstanceResultStatusStatisticsGroupTimeVO::getTime)); List keys = new ArrayList<>(CollectionUtil.subtract(dateList, new ArrayList<>(map.keySet()))); if (CollectionUtil.isNotEmpty(keys)) { for (String key : keys) { map.put(key, new ArrayList<>()); } } List statusList = Arrays.asList(1, 2, 3, 4); for (Map.Entry> entry : map.entrySet()) { List items = entry.getValue(); List results = items.stream().map(BpmProcessInstanceResultStatusStatisticsGroupTimeVO::getResult).collect(Collectors.toList()); List saveList = new ArrayList<>(CollectionUtil.subtract(statusList, results)); // -- 如果没有的话组装上缺少的 if (CollectionUtil.isNotEmpty(saveList)) { for (Integer status : saveList) { items.add(new BpmProcessInstanceResultStatusStatisticsGroupTimeVO() .setTime(entry.getKey()) .setTotalCount(0) .setResult(status) .setName("")); } } } return map; } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.LocalDateTimeUtil; 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.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 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.cash.BpmOACashRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmOACashPrintDataRespVO; 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.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.BpmOACashDO; 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.DynamicMapper; 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.*; import cn.iocoder.yudao.module.infra.api.config.ConfigApi; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.api.bank.BankApi; 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 jodd.util.StringUtil; 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.HistoricActivityInstance; import org.flowable.engine.history.HistoricActivityInstanceQuery; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; 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.time.temporal.ChronoUnit; 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; @Resource private ConfigApi configApi; @Resource private DynamicMapper dynamicMapper ; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } public String transform(String input) { if(StringUtil.isNotEmpty(input)) { String[] parts = input.split(","); StringBuilder result = new StringBuilder(); for (String part : parts) { String[] keyValue = part.split(":"); if (keyValue.length > 1) { result.append(keyValue[1]).append(","); } } if (result.length() > 0) { return result.substring(0, result.length() - 1); } } return ""; } public String replaceValues(String input, Map map) { String[] parts = input.split(","); StringBuilder result = new StringBuilder(); for (String part : parts) { String[] keyValue = part.split(":"); if (keyValue.length > 1) { String key = keyValue[1].trim(); // 去除可能的空格 if (map.containsKey(key)) { Object value = map.get(key); String stringValue = (value != null) ? value.toString() : ""; // 将值转换为字符串 result.append(keyValue[0].trim()).append(":").append(stringValue).append(","); } else { //result.append(part).append(","); } } } if (result.length() > 0) { return result.substring(0, result.length() - 1); } return ""; } @Override @TenantIgnore public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); List bpmProcessInstanceExtDOList = pageResult.getList() ; for (int i = 0; i < bpmProcessInstanceExtDOList.size() ; i++) { BpmProcessInstanceExtDO bpmProcessInstanceExtDO = bpmProcessInstanceExtDOList.get(i) ; String input = bpmProcessInstanceExtDO.getFieldNames() ; if(StringUtil.isNotEmpty(input)) { String sql = "SELECT " + transform(bpmProcessInstanceExtDO.getFieldNames()) + " FROM " + bpmProcessInstanceExtDO.getTableName() + " WHERE id=" + bpmProcessInstanceExtDO.getBusinessKey(); log.info(sql); Map map = dynamicMapper.selectListByTableName(sql) ; String detailInfo = replaceValues(bpmProcessInstanceExtDO.getFieldNames(),map) ; bpmProcessInstanceExtDO.setDetailInfo(detailInfo); } } 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 @DataPermission(enable = false) 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 @DataPermission(enable = false) 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) @DataPermission(enable = false) 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) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .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); } // 设置当前用户 FlowableUtils.setAuthenticatedUserId(userId); // 创建流程实例 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 * @param * @return */ 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); String BpmConstantsName = BpmConstants.CC_NAME; // 获取发起人信息 AdminUserRespDTO userRespDTO = adminUserApi.getUser(Long.valueOf(instance.getStartUserId())).getCheckedData(); DeptRespDTO deptRespDTO = deptApi.getDept(userRespDTO.getDeptId()).getCheckedData(); //发起人是深圳分公司 if (deptRespDTO.getFlag().contains("136")) { BpmConstantsName = BpmConstants.CCSZ_NAME; } for (BpmTaskAssignRuleDO rule : rules) { String key = rule.getTaskDefinitionKey(); //任务名称 Integer type = rule.getType(); if (!key.isEmpty() && key.equals(BpmConstantsName) && 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)) { //发起人部门为 生产部及以下时 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 @DataPermission(enable = false) public BpmProcessInstanceExtDO getProcessInstanceDO(String id) { return processInstanceExtMapper.selectByProcessInstanceId(id); } @Resource private FileApi fileApi; @Resource private BankApi bankApi; @Resource @Lazy // 解决循环依赖 private BpmOAReimbursementService reimbursementService; @Resource @Lazy // 解决循环依赖 private BpmOACashService cashService; @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 // 判断是否可见外勤人员信息 List userIds = new ArrayList<>(); String type = configApi.getConfigKey("sys.user.type").getCheckedData(); if ("1".equals(type)) { //不可见时 // 获取所有外勤人员 用户编号 userIds = adminUserApi.getUserIdsByUserNature(4).getCheckedData(); } // 获得流程审批信息 List taskRespVOList = taskService.getTaskListByProcessInstanceId(processInstanceId); // 移除外勤人员信息 List finalUserIds = userIds; taskRespVOList.removeIf(data -> finalUserIds.contains(data.getAssigneeUser().getId())); //给User添加签名地址 taskRespVOList.forEach(taskRespVO -> taskRespVO.getAssigneeUser().setSignURL( fileApi.getUserSignImgPath( taskRespVO.getAssigneeUser().getId() ).getData() ) ); //获取流程抄送用户编号 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))); } // 移除 外勤人员信息 ccUserIds.removeAll(userIds); } List userRespDTOS = adminUserApi.getUserList(ccUserIds).getCheckedData(); //获取抄送用户部门信息 Map deptMapDTO = deptApi.getDeptMap(convertSet(userRespDTOS, AdminUserRespDTO::getDeptId)); if ("oa_reimbursement".equals(key)) { //报销流程 BpmOAReimbursementDO reimbursement = reimbursementService.getReimbursement(businessKey); BpmOAReimbursementRespVO bpmOAReimbursementRespVO = reimbursementService.convert(reimbursement); //报销业务数据 // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(reimbursement.getUserId())); //备用金信息查询 BpmOAImprestDO bpmOAImprestDO = imprestService.getImprestByReimbursementId(reimbursement.getId()); if (bpmOAImprestDO != null) { //设置备用金 金额 bpmOAReimbursementRespVO.setAmount(bpmOAImprestDO.getAmount()); } // 设置抄送人信息 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); } if ("oa_cash".equals(key)) { BpmOACashDO cashDO = cashService.getCash(businessKey); BpmOACashRespVO cashRespVO = cashService.convertCash(cashDO); // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(cashDO.getUserId())); // 设置抄送人信息 List ccUsers = userRespDTOS.stream().map(user -> { BpmOACashPrintDataRespVO.CCUser cc = new BpmOACashPrintDataRespVO.CCUser(); cc.setCcUserId(user.getId()); cc.setCcUserName(user.getNickname()); cc.setCcDeptName(deptMapDTO.get(user.getDeptId()).getName()); return cc; }).collect(Collectors.toList()); BpmOACashPrintDataRespVO cashPrintData = new BpmOACashPrintDataRespVO(); cashPrintData.setBpmOACashRespVO(cashRespVO); cashPrintData.setProcessTasks(taskRespVOList); cashPrintData.setCcUsers(ccUsers); bpmProcessInstancePrintDataRespVO.setBpmOACashPrintDataRespVO(cashPrintData); } return bpmProcessInstancePrintDataRespVO; } @Override public Map> getProcessInstanceResultStatusStatisticsGroupTime(BpmProcessInstanceStatisticsReqVO pageReqVO) { pageReqVO = getUserids(pageReqVO); pageReqVO.setRecentDays(pageReqVO.getRecentDays() == null ? 7 : pageReqVO.getRecentDays()); List list = processInstanceExtMapper.getProcessInstanceResultStatusStatisticsGroupTime(pageReqVO); // -- 获取到日期列表 LocalDateTime now = LocalDateTimeUtil.now(); LocalDateTime offset = LocalDateTimeUtil.offset(LocalDateTimeUtil.now(), -1L * pageReqVO.getRecentDays(), ChronoUnit.DAYS); List dateList = DateUtils.betweenDayList(offset, now); //根据时间分组 Map> map = list.stream().collect(Collectors.groupingBy(BpmProcessInstanceResultStatusStatisticsGroupTimeVO::getTime)); List keys = new ArrayList<>(CollectionUtil.subtract(dateList, new ArrayList<>(map.keySet()))); if (CollectionUtil.isNotEmpty(keys)) { for (String key : keys) { map.put(key, new ArrayList<>()); } } List statusList = Arrays.asList(1, 2, 3, 4); for (Map.Entry> entry : map.entrySet()) { List items = entry.getValue(); List results = items.stream().map(BpmProcessInstanceResultStatusStatisticsGroupTimeVO::getResult).collect(Collectors.toList()); List saveList = new ArrayList<>(CollectionUtil.subtract(statusList, results)); // -- 如果没有的话组装上缺少的 if (CollectionUtil.isNotEmpty(saveList)) { for (Integer status : saveList) { items.add(new BpmProcessInstanceResultStatusStatisticsGroupTimeVO() .setTime(entry.getKey()) .setTotalCount(0) .setResult(status) .setName("")); } } } return map; } } \ 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/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index fb6743fc..a1b1ce5e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -239,4 +239,14 @@ public interface BpmTaskService { BpmTaskExtDO getTaskByProcessInstanceIdAndResult(String processInstanceId, Integer result); + /** + * 获取当前待处理流程实例(带查询条件),上一个流程和下一个流程的实例ID + * + * @param userId 用户编号 + * @param processInstanceId 流程实例id + * @param pageReqVO 分页请求 + * @return 流程任务分页 + */ + Map getCurrentToDoProcessInstacePreAndNex(Long userId, String processInstanceId,BpmTaskTodoPageReqVO pageReqVO); + } 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 9f25b6c4..88a13ca2 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 @@ -265,7 +265,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 获得 ProcessInstance List historicProcessInstances = processInstanceService.getHistoricProcessInstances( - convertSet(tasks, HistoricTaskInstance::getProcessInstanceId)); + convertSet(tasks, HistoricTaskInstance::getProcessInstanceId)); // 判断搜索条件是否选择用户 if (pageVO.getUserId() != null) { @@ -1375,10 +1375,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { List tasks = taskQuery.list(); if (!tasks.isEmpty()) { Task currentTask = tasks.get(0); - System.out.println("当前任务节点ID: " + currentTask.getId()); - System.out.println("当前任务节点名称: " + currentTask.getName()); - System.out.println("当前任务节点创建时间: " + currentTask.getCreateTime()); - System.out.println("当前任务节点分配给: " + currentTask.getAssignee()); +// System.out.println("当前任务节点ID: " + currentTask.getId()); +// System.out.println("当前任务节点名称: " + currentTask.getName()); +// System.out.println("当前任务节点创建时间: " + currentTask.getCreateTime()); +// System.out.println("当前任务节点分配给: " + currentTask.getAssignee()); return currentTask.getId(); } else { System.out.println("没有找到当前进行中的任务节点"); @@ -1399,4 +1399,132 @@ public class BpmTaskServiceImpl implements BpmTaskService { .eq(BpmTaskExtDO::getProcessInstanceId, processInstanceId) .eq(BpmTaskExtDO::getResult, result)); } + + /** + * 获取当前待处理流程实例(带查询条件),上一个流程和下一个流程的实例ID + * + * @param userId 用户编号 + * @param processInstanceId 流程实例id + * @param pageVO 分页请求 + * @return 流程任务分页 + */ + public Map getCurrentToDoProcessInstacePreAndNex(Long userId, String processInstanceId,BpmTaskTodoPageReqVO pageVO) { + PageResult list = getTodoTaskPage(userId, pageVO) ; + + List vos = list.getList() ; + List processInstanceIds = new ArrayList<>() ; + for (BpmTaskTodoPageItemRespVO vo : vos) { + processInstanceIds.add(vo.getProcessInstance().getId()) ; + } + String pre = null ; + String next = null ; + Long total = list.getTotal() ; + + Integer pageNo = pageVO.getPageNo() ; + //hasNext == true 还有下一页 false 没有下一页 + boolean hasNext = PageUtils.hasNextPage(total.intValue(),pageVO) ; + //hasPre == true 还有下上页 false 没有上一页 + boolean hasPre = pageVO.getPageNo() > 1 ; + //获取上一个 + for (int i = 0; i < processInstanceIds.size(); i++) { + if( processInstanceIds.get(i).equals(processInstanceId) ) { + if( i > 0 ) { + pre = processInstanceIds.get(i - 1) ; + }else if( hasPre ) { + pageVO.setPageNo(pageNo - 1); + list = getTodoTaskPage(userId, pageVO) ; + BpmTaskTodoPageItemRespVO vo = list.getList().get(list.getList().size()-1); + pre = vo.getProcessInstance().getId() ; + }else { + pre = null ; + } + } + } + //获取下一个 + for (int i = 0; i < processInstanceIds.size(); i++) { + if( processInstanceIds.get(i).equals(processInstanceId) ) { + if( i < processInstanceIds.size() - 1 ) { + next = processInstanceIds.get(i + 1) ; + }else if( hasNext ) { + pageVO.setPageNo(pageNo + 1); + list = getTodoTaskPage(userId, pageVO) ; + BpmTaskTodoPageItemRespVO vo = list.getList().get(0); + next = vo.getProcessInstance().getId() ; + }else { + next = null ; + } + } + } + + + +// int index = processInstanceIds.indexOf(processInstanceId); +// if(index == 0 ) { +// //下标未0 +// if (pageNo == 1) { +// //如果pageNo == 1 说明是第一页,第一条数据,那么就没有pre +// log.info("没有上个"); +// pre = null; +// } else { +// //如果pageNo > 1 说明是不是第一页的第一条数据,那么就有pre +// //设置当前页面-1,并查询数据 +// pageVO.setPageNo(pageNo - 1); +// log.info("查询上一页"); +// list = getTodoTaskPage(userId, pageVO) ; +// BpmTaskTodoPageItemRespVO vo = list.getList().get(list.getList().size()-1); +// pre = vo.getProcessInstance().getId() ; +// } +// if( processInstanceIds.size() == 1 ) { +// //说明这一页,只有一条数据,没有下一条了 +// log.info("没有下一个"); +// next = null ; +// }else { +// next = processInstanceIds.get(index + 1); +// } +// } else if( index == processInstanceIds.size() -1 ) { +// //如果下标==数据集合的size-1,说明是当前页面的最后一条数据 +// pre = processInstanceIds.get(index - 1); +// if(!hasNext) { +// //如果没有下一页了 +// log.info("没有下一个"); +// next = null; ; +// }else { +// //正常下一条数据 +// //设置当前页面+1,并查询数据 +// pageVO.setPageNo(pageNo + 1); +// log.info("查询下一页"); +// list = getTodoTaskPage(userId, pageVO) ; +// BpmTaskTodoPageItemRespVO vo = list.getList().get(0); +// next = vo.getProcessInstance().getId() ; +// +// //审批处理后的下一条数据, 因为处理的是当前页最后一条数据,假设10条数据,处理了一条变成9条,重新查询后,会把原来第二页的数据查询在第一页的来。 +// //所有重新查询当前页面后,取最后一条数据 +// /** +// log.info("审批后重新查询"); +// list = getTodoTaskPage(userId, pageVO) ; +// BpmTaskTodoPageItemRespVO vo1 = list.getList().get(processInstanceIds.size() -1); +// next = vo1.getProcessInstance().getId() ; +// **/ +// } +// +// }else if( index > 0 && index < processInstanceIds.size() ){ +// //如果下标大于0 且不等于processInstanceIds.size() ,说明是中间的数据 +// pre = processInstanceIds.get(index - 1); +// next = processInstanceIds.get(index + 1); +// }else { +// log.info("传入的processInstanceId:"+processInstanceId+"在列表中不存在"); +// pre = null ; +// next = null ; +// } + + Map map = new HashMap<>() ; + map.put("pre",pre) ; + map.put("next",next); + map.put("current",processInstanceId) ; + map.put("total",total.toString()) ; + map.put("currentPage",pageVO.getPageNo().toString()) ; + return map ; + } + } + diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application-prod.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application-prod.yaml index c759584a..0401246c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application-prod.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application-prod.yaml @@ -67,7 +67,7 @@ spring: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 - password: ZNredis2024! # 密码,建议生产环境开启 + password: yhtkj@2024! # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/bootstrap-prod.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/bootstrap-prod.yaml index 4e48a732..a33845dd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/bootstrap-prod.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/bootstrap-prod.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 47.97.8.94:8848 + server-addr: 127.0.0.1:8848 discovery: namespace: prod # 命名空间。这里使用 dev 开发环境 metadata: @@ -16,7 +16,7 @@ spring: nacos: # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 config: - server-addr: 47.97.8.94:8848 # Nacos 服务器地址 + server-addr: 127.0.0.1:8848 # Nacos 服务器地址 namespace: prod # 命名空间 dev 的ID,不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev,这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId,默认为 spring.application.name diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml index 156c5415..65e07f99 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml @@ -56,7 +56,7 @@ spring: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 1 # 数据库索引 - password: yhtkj@2024! # 密码,建议生产环境开启 +# password: yhtkj@2024! # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-prod.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-prod.yaml index fb6de20d..aa992fed 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-prod.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-prod.yaml @@ -71,7 +71,7 @@ spring: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 - password: ZNredis2024! # 密码,建议生产环境开启 + password: yhtkj@2024! # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/bootstrap-prod.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/bootstrap-prod.yaml index 4e48a732..a33845dd 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/bootstrap-prod.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/bootstrap-prod.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 47.97.8.94:8848 + server-addr: 127.0.0.1:8848 discovery: namespace: prod # 命名空间。这里使用 dev 开发环境 metadata: @@ -16,7 +16,7 @@ spring: nacos: # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 config: - server-addr: 47.97.8.94:8848 # Nacos 服务器地址 + server-addr: 127.0.0.1:8848 # Nacos 服务器地址 namespace: prod # 命名空间 dev 的ID,不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev,这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId,默认为 spring.application.name diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java index 79f760e7..602f2a69 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java @@ -53,8 +53,8 @@ public interface DeptApi { CommonResult createDept(@RequestBody DeptRespDTO deptRespDTO); @PostMapping(PREFIX + "/update") - @Operation(summary = "修改部门信息") - void updateDept(@RequestBody DeptRespDTO deptRespDTO); + @Operation(summary = "修改工厂部门信息") + void updateFactoryDept(@RequestBody DeptRespDTO deptRespDTO); @PostMapping(PREFIX + "/delete") @Operation(summary = "删除部门信息") diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApi.java index 11a54b57..2d307596 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApi.java @@ -1,14 +1,16 @@ package cn.iocoder.yudao.module.system.api.supplier; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.system.api.subscribe.dto.SubscribeMessageReqDTO; import cn.iocoder.yudao.module.system.api.supplier.dto.SupplierRpcDTO; import cn.iocoder.yudao.module.system.enums.ApiConstants; 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.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; @FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = @Tag(name = "RPC 服务 - 供应商新增编辑") @@ -20,4 +22,9 @@ public interface SupplierApi { @Operation(summary = "新增编辑供应商") CommonResult saveOrEdit(@RequestBody SupplierRpcDTO supplier); + + @GetMapping(PREFIX + "/getNameById") + @Operation(summary = "获取供应商名称") + @Parameter(name = "id", description = "供应商id", example = "1", required = true) + CommonResult getNameById(@RequestParam("id") Long id); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index 4b7f6d74..d36ee377 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -84,6 +84,13 @@ public interface AdminUserApi { void updateFieldworkType(@RequestParam("userId") Long userId, @RequestParam("fieldworkFlag") Integer fieldworkFlag); + @PostMapping(PREFIX + "/updateUserStaffing") + @Operation(summary = "修改用户信息") + @Parameter(name = "userId", description = "用户id", example = "1024", required = true) + @Parameter(name = "userStaffing", description = "用户编制", example = "1", required = true) + void updateUserStaffing(@RequestParam("userId") Long userId, + @RequestParam("userStaffing") Integer userStaffing); + @GetMapping(PREFIX + "/getUserIdsByUserNature") @Operation(summary = "获取所有用户性质为外勤的用户") @Parameter(name = "userNature", description = "用户性质", example = "3", required = true) 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 690d3328..2f1de939 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 @@ -53,6 +53,7 @@ public interface ErrorCodeConstants { ErrorCode DEPT_EXISTS_USER = new ErrorCode(1_002_004_005, "部门中存在员工,无法删除"); ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择"); ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门"); + ErrorCode FACTORY_DEPT_NOT_FOUND = new ErrorCode(1_002_004_008, "当前工厂没有对应部门"); // ========== 职称模块 1-002-005-000 ========== ErrorCode POST_NOT_FOUND = new ErrorCode(1_002_005_000, "当前职称不存在"); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index e0de6245..9ecd4202 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -75,21 +75,14 @@ public class DeptApiImpl implements DeptApi { } @Override - public void updateDept(DeptRespDTO deptRespDTO) { + public void updateFactoryDept(DeptRespDTO deptRespDTO) { - DeptDO deptDO = deptService.getDeptByFactoryId(deptRespDTO.getFactoryId()); - - if (deptDO != null) { - - DeptSaveReqVO deptSaveReqVO = BeanUtils.toBean(deptDO, DeptSaveReqVO.class); - deptSaveReqVO.setLeaderUserId(deptRespDTO.getLeaderUserId()); - deptSaveReqVO.setName(deptRespDTO.getName()); - - deptService.updateDept(deptSaveReqVO); - } + DeptSaveReqVO deptSaveReqVO = BeanUtils.toBean(deptRespDTO, DeptSaveReqVO.class); + deptService.updateFactoryDept(deptSaveReqVO); } @Override + @DataPermission(enable = false) public void deleteDept(Long factoryId) { DeptDO deptDO = deptService.getDeptByFactoryId(factoryId); @@ -100,6 +93,7 @@ public class DeptApiImpl implements DeptApi { } @Override + @DataPermission(enable = false) public CommonResult getDeptByFactoryId(Long factoryId) { DeptDO deptDO = deptService.getDeptByFactoryId(factoryId); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApiImpl.java index aaec46de..d3268598 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/supplier/SupplierApiImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.supplier; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.system.api.supplier.dto.SupplierRpcDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.supplier.SupplierDO; import cn.iocoder.yudao.module.system.service.supplier.SupplierService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; @@ -23,4 +24,10 @@ public class SupplierApiImpl implements SupplierApi { supplierService.saveOrEdit(supplier); return success(true); } + + @Override + public CommonResult getNameById(Long id) { + SupplierDO supplier = supplierService.getSupplier(id); + return success(supplier == null ? "其他" : supplier.getSupplierName()); + } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index 8ebf04bc..5f090bfb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -96,6 +96,12 @@ public class AdminUserApiImpl implements AdminUserApi { userService.updateFieldworkType(userId, fieldworkFlag); } + @Override + public void updateUserStaffing(Long userId, Integer userStaffing) { + + userService.updateUserStaffing(userId, userStaffing); + } + @Override public CommonResult> getUserIdsByUserNature(Integer userNature) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceRulesVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceRulesVO.java index 38c0cdc4..997aff74 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceRulesVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/attendance/vo/AttendanceRulesVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.attendance.vo; +import cn.iocoder.yudao.module.system.dal.dataobject.attendance.group.AttendanceGroupDO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -15,6 +16,8 @@ public class AttendanceRulesVO { private String officeLocation; @Schema(description = "是否允许外勤打卡 0否 1是") private Integer fieldworkFlag; + @Schema(description = "考勤组信息") + private AttendanceGroupDO attendanceGroupDO; @Data public static class WorkRules { 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 2f1c3685..4262dd1d 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 @@ -128,6 +128,15 @@ public class DeptController { return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); } + @GetMapping(value = { "/virtually-list"}) + @Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项") + public CommonResult> getVirtuallyDeptList() { + List list = deptService.getDeptList( + new DeptListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + + return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); + } + @GetMapping(value = {"/all-list"}) @Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项") @DataPermission(enable = false) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/LaborContractController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/LaborContractController.java index f84a4899..5da17d0b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/LaborContractController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/LaborContractController.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractRespVO; import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.SigningDateRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.laborcontract.LaborContractDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -21,9 +22,12 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; 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 @@ -101,4 +105,20 @@ public class LaborContractController { return success(laborContractService.getLaborContractPage(pageReqVO)); } + + @GetMapping("/getSigningDate") + @Operation(summary = "获得当前登录用户的入职时间和转正时间") + public CommonResult getSigningDate() { + + LaborContractDO contractDO = laborContractService.getSigningDate(getLoginUserId()); + if (contractDO == null) { + return success(new SigningDateRespVO()); + } + + SigningDateRespVO respVO = BeanUtils.toBean(contractDO, SigningDateRespVO.class); + // 设置转正日期 + LocalDate regularDate = contractDO.getSigningDate().plusMonths(contractDO.getProbationPeriodTime()); + respVO.setRegularDate(regularDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + return success(respVO); + } } \ 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/laborcontract/vo/LaborContractPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/LaborContractPageReqVO.java index a9be2932..b399fe49 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/LaborContractPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/LaborContractPageReqVO.java @@ -8,6 +8,7 @@ import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; +import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -23,6 +24,9 @@ public class LaborContractPageReqVO extends PageParam { @Schema(description = "部门id", example = "128") private Long deptId; + @Schema(description = "部门id", example = "128") + private List deptIds; + @Schema(description = "签约日期") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDate[] signingDate; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/SigningDateRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/SigningDateRespVO.java new file mode 100644 index 00000000..31650d41 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/SigningDateRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +@Schema(description = "管理后台 - 劳动合同管理 Response VO") +@Data +public class SigningDateRespVO { + + @Schema(description = "签约日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private String signingDate; + + @Schema(description = "转正日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private String regularDate; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/UploadFile.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/UploadFile.java index 723b9c14..5ce0d6c5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/UploadFile.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/laborcontract/vo/UploadFile.java @@ -9,9 +9,12 @@ import lombok.Data; @Data public class UploadFile { - @Schema(description = "文件管理 fileId", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.jpg") + @Schema(description = "文件管理 fileId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private String fileId; + @Schema(description = "文件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.jpg") + private String fileName; + @Schema(description = "文件URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx.xxx/xx/xx/123.jpgss") private String url; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/dto/UserPageDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/dto/UserPageDTO.java index 206bea70..9ec18627 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/dto/UserPageDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/dto/UserPageDTO.java @@ -14,4 +14,6 @@ public class UserPageDTO extends PageParam { private String name; @Schema(description = "状态(0正常 1停用)不传则全部", example = "1") private Integer status; + @Schema(description = "部门id", example = "1") + private Long deptId; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java index 07faf809..ad9b6cca 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java @@ -137,7 +137,7 @@ public interface AdminUserMapper extends BaseMapperX { " contract_duration AS contractDuration,\n" + " probation_period_time AS probationPeriodTime,\n" + " status,\n" + - " create_time AS createTime,\n" + + " create_time AS createTime\n" + " FROM\n" + " system_labor_contract lc\n" + " INNER JOIN (SELECT\n" + @@ -153,7 +153,7 @@ public interface AdminUserMapper extends BaseMapperX { " AND lc.create_time = max.max_create_time) a on a.user_id = t.id"); queryWrapper.eq(AdminUserDO::getUserType, 1); queryWrapper.likeIfPresent(AdminUserDO::getNickname, pageReqVO.getUserName()); - queryWrapper.eqIfPresent(AdminUserDO::getDeptId, pageReqVO.getDeptId()); + queryWrapper.inIfPresent(AdminUserDO::getDeptId, pageReqVO.getDeptIds()); if (Objects.nonNull(pageReqVO.getSigningDate())) { queryWrapper.between("a.signing_date", pageReqVO.getSigningDate()[0], pageReqVO.getSigningDate()[1]); } @@ -163,6 +163,7 @@ public interface AdminUserMapper extends BaseMapperX { queryWrapper.eq(Objects.nonNull(pageReqVO.getStatus()), "a.status", pageReqVO.getStatus()); queryWrapper.groupBy(AdminUserDO::getId); queryWrapper.orderByAsc("a.status"); + queryWrapper.orderByAsc(AdminUserDO::getId); return selectJoinPage(mpPage, LaborContractRespVO.class, queryWrapper); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java index db0446d2..966f338e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogInstanceMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.worklog; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; @@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.worklog.LogInstanceDO; import cn.iocoder.yudao.module.system.dal.dataobject.worklog.LogReadDo; import cn.iocoder.yudao.module.system.service.worklog.dto.LogReadUserRespDTO; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -65,8 +65,8 @@ public interface LogInstanceMapper extends BaseMapperX { .eq(LogReadDo::getLogInstanceId, LogInstanceDO::getId) .eq(LogReadDo::getReadUserId, userId) .eq(LogReadDo::getDeleted, 0)); - queryWrapper.leftJoin("(SELECT log_instance_id, COUNT(log_instance_id) AS readCount FROM work_log_read where read_status = 1 GROUP BY log_instance_id) c on t.id = c.log_instance_id"); - queryWrapper.leftJoin("(SELECT log_instance_id, COUNT(log_instance_id) AS unReadCount FROM work_log_read where read_status = 0 GROUP BY log_instance_id) AS d ON t.id = d.log_instance_id"); + queryWrapper.leftJoin("(SELECT log_instance_id, COUNT(log_instance_id) AS readCount FROM work_log_read where read_status = 1 and deleted = 0 GROUP BY log_instance_id) c on t.id = c.log_instance_id"); + queryWrapper.leftJoin("(SELECT log_instance_id, COUNT(log_instance_id) AS unReadCount FROM work_log_read where read_status = 0 and deleted = 0 GROUP BY log_instance_id) AS d ON t.id = d.log_instance_id"); queryWrapper.leftJoin("(SELECT work_log_id, COUNT(work_log_id) AS comment FROM work_log_comment GROUP BY work_log_id) AS b ON t.id = b.work_log_id"); queryWrapper.eqIfPresent(LogInstanceDO::getDeptId, reqVO.getDeptId()); queryWrapper.eqIfPresent(LogInstanceDO::getFormId, reqVO.getFormId()); @@ -108,9 +108,76 @@ public interface LogInstanceMapper extends BaseMapperX { * @param type * @return */ - LogInstanceRespVO getNextOrUp(@Param("reqVO") LogInstancePageReqVO dto, + LogInstanceRespVO getMyNextOrUp(@Param("reqVO") LogInstancePageReqVO dto, @Param("id") Long id, @Param("userId") Long userId, @Param("type") Integer type, - @Param("pagingType") Integer pagingType, @Param("userIds") List userIds); + + default IPage getNextOrUp(@Param("reqVO") LogInstancePageReqVO reqVO, + @Param("id") Long id, + @Param("userId") Long userId, + @Param("type") Integer type, + @Param("userIds") List userIds){ + + String sql = ""; + + MPJLambdaWrapperX queryWrapper = new MPJLambdaWrapperX<>(); + queryWrapper.selectAs(LogInstanceDO::getId, LogInstanceRespVO::getId); + queryWrapper.selectAs(LogInstanceDO::getName, LogInstanceRespVO::getName); + queryWrapper.innerJoin(UserPostDO.class, "userPost", UserPostDO::getUserId, LogInstanceDO::getStartUserId); + queryWrapper.innerJoin(DeptDO.class, "dept", DeptDO::getId, LogInstanceDO::getDeptId); + queryWrapper.innerJoin(PostDO.class, "post", PostDO::getId, UserPostDO::getPostId); + if (type == 1) { + sql = " (t.time > tt.time) or\n" + + " (t.time = tt.time and tt.sort > post.sort) or\n" + + " (t.time = tt.time and tt.sort = post.sort and tt.create_time < t.create_time)"; + + queryWrapper.orderByAsc(LogInstanceDO::getTime); + queryWrapper.orderByDesc(PostDO::getSort); + queryWrapper.orderByAsc(LogInstanceDO::getCreateTime); + } + if (type == 0) { + sql = " (t.time < tt.time) or\n" + + " (t.time = tt.time and tt.sort < post.sort) or\n" + + " (t.time = tt.time and tt.sort = post.sort and tt.create_time > t.create_time)"; + + queryWrapper.orderByDesc(LogInstanceDO::getTime); + queryWrapper.orderByAsc(PostDO::getSort); + queryWrapper.orderByDesc(LogInstanceDO::getCreateTime); + } + queryWrapper.innerJoin("(\n" + + "SELECT \n" + + " a.id,\n" + + " a.name,\n" + + " a.time,\n" + + " d.sort,\n" + + " a.create_time\n" + + "FROM \n" + + " work_log_instance_ext a\n" + + " INNER JOIN system_user_post b ON (b.user_id = a.start_user_id) \n" + + " INNER JOIN system_dept c ON (c.id = a.dept_id) \n" + + " INNER JOIN system_post d ON (d.id = b.post_id) \n" + + "WHERE \n" + + " a.id = " + id + "\n" + + " AND a.deleted = 0 \n" + + " AND b.deleted = 0 \n" + + " AND c.deleted = 0 \n" + + " AND d.deleted = 0\n" + + ") tt on \n" + sql); + queryWrapper.eqIfPresent(LogInstanceDO::getDeptId, reqVO.getDeptId()); + queryWrapper.eqIfPresent(LogInstanceDO::getFormId, reqVO.getFormId()); + queryWrapper.eqIfPresent(LogInstanceDO::getStartUserId, reqVO.getStartUserId()); + queryWrapper.betweenIfPresent(LogInstanceDO::getTime, reqVO.getCreateTime()); + queryWrapper.inIfPresent(LogInstanceDO::getStartUserId, userIds); + queryWrapper.ne(LogInstanceDO::getStartUserId, userId); + + if (reqVO.getIsProduce() != null && reqVO.getIsProduce() == 1) { + queryWrapper.like(DeptDO::getFlag, "166"); + } + if (reqVO.getIsProduce() != null && reqVO.getIsProduce() == 2) { + queryWrapper.notLike(DeptDO::getFlag, "166"); + } + + return selectJoinPage(new Page<>(1, 1), LogInstanceRespVO.class, queryWrapper); + } } \ 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/attendance/AttendanceServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java index 8917df6a..bb941bde 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/attendance/AttendanceServiceImpl.java @@ -954,6 +954,7 @@ public class AttendanceServiceImpl implements AttendanceService { vo.setFieldworkFlag(group.getFieldworkFlag()); vo.setWorkRules(workRules); vo.setOfficeLocation(group.getAddress()); + vo.setAttendanceGroupDO(group); return vo; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/comment/WorkLogCommentServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/comment/WorkLogCommentServiceImpl.java index 1dada112..06e86815 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/comment/WorkLogCommentServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/comment/WorkLogCommentServiceImpl.java @@ -31,6 +31,7 @@ import javax.annotation.Resource; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; /** @@ -115,7 +116,7 @@ public class WorkLogCommentServiceImpl implements WorkLogCommentService { List records = pageList.getRecords(); if (dto.getIsShowWorkLogContent() != null && dto.getIsShowWorkLogContent() == 1 && !records.isEmpty()) { //模版ids过滤 - List workFormIds = records.stream().map(CommentPageListVO::getWorkFormId).collect(Collectors.toList()); + Set workFormIds = records.stream().map(CommentPageListVO::getWorkFormId).collect(Collectors.toSet()); // 查询模版列表 List formList = logFormService.getFormList(workFormIds); Map formMap = formList.stream().collect(Collectors.toMap(LogFormDO::getId, item -> item)); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java index 0699591f..2a9222ec 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java @@ -30,6 +30,12 @@ public interface DeptService { */ void updateDept(DeptSaveReqVO updateReqVO); + /** + * 更新工厂部门 + * @param updateReqVO 更新信息 + */ + void updateFactoryDept(DeptSaveReqVO updateReqVO); + /** * 删除部门 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java index 7c38f45c..ccbc738d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java @@ -128,6 +128,17 @@ public class DeptServiceImpl implements DeptService { deptMapper.updateById(updateObj); } + @Override + public void updateFactoryDept(DeptSaveReqVO updateReqVO) { + + // 校验自己存在 + validateFactoryDeptExists(updateReqVO.getFactoryId()); + + DeptDO update = BeanUtils.toBean(updateReqVO, DeptDO.class); + deptMapper.update(update, new LambdaQueryWrapperX() + .eq(DeptDO::getFactoryId, updateReqVO.getFactoryId())); + } + @Override @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 @@ -153,6 +164,17 @@ public class DeptServiceImpl implements DeptService { } } + @VisibleForTesting + void validateFactoryDeptExists(Long factoryId) { + if (factoryId == null) { + return; + } + DeptDO dept = deptMapper.selectOne(DeptDO::getFactoryId, factoryId); + if (dept == null) { + throw exception(FACTORY_DEPT_NOT_FOUND); + } + } + @VisibleForTesting void validateParentDept(Long id, Long parentId) { if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) { @@ -289,6 +311,7 @@ public class DeptServiceImpl implements DeptService { } @Override + @DataPermission(enable = false) public DeptDO getDeptByFactoryId(Long factoryId) { return deptMapper.selectOne(DeptDO::getFactoryId, factoryId); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractService.java index f8853c3b..d78f804e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractService.java @@ -83,5 +83,10 @@ public interface LaborContractService { */ List getListByEndTime(LocalDate now); - + /** + * 获得当前登录用户的入职时间和转正时间 + * @param userId 用户编号 + * @return 日期 + */ + LaborContractDO getSigningDate(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/laborcontract/LaborContractServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractServiceImpl.java index ba0a7396..9dd84289 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/laborcontract/LaborContractServiceImpl.java @@ -1,14 +1,17 @@ package cn.iocoder.yudao.module.system.service.laborcontract; +import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractRespVO; import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.laborcontract.LaborContractDO; import cn.iocoder.yudao.module.system.dal.mysql.laborcontract.LaborContractMapper; import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import cn.iocoder.yudao.module.system.service.dept.DeptService; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.springframework.stereotype.Service; @@ -20,6 +23,7 @@ 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.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.LABOR_CONTRACT_NOT_EXISTS; /** @@ -37,6 +41,9 @@ public class LaborContractServiceImpl implements LaborContractService { @Resource private AdminUserMapper userMapper; + @Resource + private DeptService deptService; + @Override public Long createLaborContract(LaborContractSaveReqVO createReqVO) { // 插入 @@ -93,6 +100,13 @@ public class LaborContractServiceImpl implements LaborContractService { @Override public PageResult getLaborContractPage(LaborContractPageReqVO pageReqVO) { + if (pageReqVO.getDeptId() != null) { + + // 获取所有子级部门 + List deptDOS = deptService.getChildDept(pageReqVO.getDeptId()); + pageReqVO.setDeptIds(convertList(deptDOS, DeptDO::getId)); + } + Page page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); IPage pageList = userMapper.selectContractPage(page, pageReqVO); @@ -118,4 +132,15 @@ public class LaborContractServiceImpl implements LaborContractService { .lt(LaborContractDO::getExpirationDate, now) .eq(LaborContractDO::getStatus, 3)); } + + @Override + public LaborContractDO getSigningDate(Long userId) { + + List list = laborContractMapper.selectList(new LambdaQueryWrapperX() + .eq(LaborContractDO::getUserId, userId) + .isNotNull(LaborContractDO::getProbationPeriodTime) + .orderByDesc(LaborContractDO::getCreateTime)); + + return CollectionUtil.isEmpty(list) ? null : list.get(0); + } } \ 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/user/AdminUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java index 88b1f0fd..670a6325 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java @@ -103,6 +103,14 @@ public interface AdminUserService { */ void updateFieldwork(Long id, Integer fieldworkFlag); + /** + * 修改用户编制 + * + * @param id 用户编号 + * @param userStaffing 编制 + */ + void updateUserStaffing(Long id, Integer userStaffing); + /** * 修改外勤打卡状态 * 用于临时开启外勤打卡 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index 654fbd0f..0702033f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -277,6 +277,12 @@ public class AdminUserServiceImpl implements AdminUserService { userMapper.updateById(updateObj); } + @Override + public void updateUserStaffing(Long id, Integer userStaffing) { + + userMapper.updateById(new AdminUserDO().setId(id).setUserStaffing(userStaffing)); + } + @Override public void updateFieldworkType(Long id, Integer fieldworkFlag) { // 更新状态 @@ -356,8 +362,8 @@ public class AdminUserServiceImpl implements AdminUserService { .header("Connection", "keep-alive") .header("Content-Type", "application/json") .header("Cookie", "JSESSIONID=node07ayjwewvdr8q3ov9smy6m94c3668.node0") - .header("Origin", "http://47.97.8.94:8082") - .header("Referer", "http://47.97.8.94:8082/settings/device") + .header("Origin", "http://127.0.0.1:8082") + .header("Referer", "http://127.0.0.1:8082/settings/device") .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36") .body(JSONUtil.toJsonStr(object)) .timeout(20000) // 设置超时时间 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogInstanceServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogInstanceServiceImpl.java index ebde0cd3..873fc912 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogInstanceServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogInstanceServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.service.worklog; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -256,14 +257,14 @@ public class LogInstanceServiceImpl implements LogInstanceService { if (!records.isEmpty()) { //模版ids过滤 - List workFormIds = records.stream().map(LogInstanceRespVO::getFormId).collect(Collectors.toList()); + Set workFormIds = records.stream().map(LogInstanceRespVO::getFormId).collect(Collectors.toSet()); // 查询模版列表 List formList = logFormService.getFormList(workFormIds); Map formMap = formList.stream().collect(Collectors.toMap(LogFormDO::getId, item -> item)); //查询用户信息列表 - List userIds = records.stream().map(LogInstanceRespVO::getStartUserId).collect(Collectors.toList()); + Set userIds = records.stream().map(LogInstanceRespVO::getStartUserId).collect(Collectors.toSet()); Map userMap = adminUserService.getUserMap(userIds); //遍历 @@ -400,10 +401,26 @@ public class LogInstanceServiceImpl implements LogInstanceService { //以及岗位为总监或副总监的用户 leaderUserIds = adminUserService.getUserByBoss(); } - LogInstanceRespVO upLogInstance = logInstanceMapper.getNextOrUp(dto, id, getLoginUserId(), 1, pagingType, leaderUserIds); - LogInstanceRespVO nextLogInstance = logInstanceMapper.getNextOrUp(dto, id, getLoginUserId(), 0, pagingType, leaderUserIds); - vo.setUpLogInstance(upLogInstance); - vo.setNextLogInstance(nextLogInstance); + if (pagingType == 0) { + IPage upLogInstances = logInstanceMapper.getNextOrUp(dto, id, getLoginUserId(), 1, leaderUserIds); + IPage nextLogInstances = logInstanceMapper.getNextOrUp(dto, id, getLoginUserId(), 0, leaderUserIds); + + if (CollectionUtil.isNotEmpty(upLogInstances.getRecords())) { + vo.setUpLogInstance(upLogInstances.getRecords().get(0)); + } + if (CollectionUtil.isNotEmpty(nextLogInstances.getRecords())) { + vo.setNextLogInstance(nextLogInstances.getRecords().get(0)); + } + } + + if (pagingType == 1) { + LogInstanceRespVO upLogInstance = logInstanceMapper.getMyNextOrUp(dto, id, getLoginUserId(), 1, leaderUserIds); + LogInstanceRespVO nextLogInstance = logInstanceMapper.getMyNextOrUp(dto, id, getLoginUserId(), 0, leaderUserIds); + + vo.setUpLogInstance(upLogInstance); + vo.setNextLogInstance(nextLogInstance); + } + //获取日志详情 return vo; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml index daf0e773..6c9c05dd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml @@ -56,7 +56,7 @@ spring: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 1 # 数据库索引 - password: yhtkj@2024! # 密码,建议生产环境开启 +# password: yhtkj@2024! # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-prod.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-prod.yaml index ac893e8d..47e40b16 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-prod.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-prod.yaml @@ -67,7 +67,7 @@ spring: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 - password: ZNredis2024! # 密码,建议生产环境开启 + password: yhtkj@2024! # 密码,建议生产环境开启 --- #################### MQ 消息队列相关配置 #################### @@ -92,7 +92,7 @@ xxl: job: enabled: true # 是否开启调度中心,默认为 true 开启 admin: - addresses: http://47.97.8.94:9090/xxl-job-admin # 调度中心部署跟地址 + addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址 executor: appname: ${spring.application.name} # 执行器 AppName ip: # 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/bootstrap-prod.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/bootstrap-prod.yaml index 4e48a732..a33845dd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/bootstrap-prod.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/bootstrap-prod.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 47.97.8.94:8848 + server-addr: 127.0.0.1:8848 discovery: namespace: prod # 命名空间。这里使用 dev 开发环境 metadata: @@ -16,7 +16,7 @@ spring: nacos: # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 config: - server-addr: 47.97.8.94:8848 # Nacos 服务器地址 + server-addr: 127.0.0.1:8848 # Nacos 服务器地址 namespace: prod # 命名空间 dev 的ID,不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev,这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId,默认为 spring.application.name diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml index 8a0da8fc..edf9770b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml @@ -73,6 +73,9 @@ #{groupId} + + and a.dept_id = #{dto.deptId} + and a.nickname like concat('%', #{dto.name}, '%') diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogInstanceMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogInstanceMapper.xml index d6c4932b..bbb92770 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogInstanceMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/LogInstanceMapper.xml @@ -94,61 +94,66 @@ or result.data_scope = 1 ) - @@ -156,13 +161,11 @@