From ec0ffa16519168dd90ae7dad5307599f17416d38 Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Sat, 22 Feb 2025 16:27:36 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat(smartfactory):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=91=98=E5=B7=A5=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加员工工资创建接口 - 优化员工数据统计功能 - 增加工种名称和业务类型字段 - 调整员工信息展示和导入模板 - 重构员工工资查询逻辑 --- .../factorydata/FactoryDataController.java | 11 ++-- .../admin/staff/StaffController.java | 38 ++++++++++++-- .../admin/staff/vo/StaffImportExcelVO.java | 3 ++ .../admin/staff/vo/StaffPageReqVO.java | 9 ++-- .../admin/staff/vo/StaffRespVO.java | 3 ++ .../admin/staff/vo/StaffSaveReqVO.java | 3 ++ .../staffsalary/StaffSalaryController.java | 20 +++---- .../dal/dataobject/staff/StaffDO.java | 5 ++ .../dal/mysql/staff/StaffMapper.java | 40 +++++++++++++- .../service/staff/StaffServiceImpl.java | 52 +++++++++++++++---- .../staffsalary/StaffSalaryService.java | 7 +++ .../staffsalary/StaffSalaryServiceImpl.java | 30 ++++++++++- .../resources/mapper/staff/StaffMapper.xml | 5 +- 13 files changed, 184 insertions(+), 42 deletions(-) diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/factorydata/FactoryDataController.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/factorydata/FactoryDataController.java index c7331d84..a805986f 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/factorydata/FactoryDataController.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/factorydata/FactoryDataController.java @@ -33,9 +33,7 @@ import java.text.DecimalFormat; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -213,11 +211,14 @@ public class FactoryDataController { List sizeDOS = sizeService.getListSize(); List size = sizeDOS.stream().map(info -> info.getId() + ":" + info.getName()).collect(Collectors.toList()); + Map> mapDropDown = new HashMap<>(); + mapDropDown.put(0, factory); + mapDropDown.put(2, size); + // 输出 ExcelUtils.write(response, "出入库数据导入模板.xls", "详情", FactoryDataImportVO.class, null, - 0, factory, - 2, size); + mapDropDown); } @PostMapping("/import") diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/StaffController.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/StaffController.java index 357813c0..bc314a8c 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/StaffController.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/StaffController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.smartfactory.controller.admin.staff; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -26,10 +27,15 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 员工") @@ -75,9 +81,9 @@ public class StaffController { @Operation(summary = "获得员工") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('factory:staff:query')") - public CommonResult getStaff(@RequestParam("id") Long id) { + public CommonResult getStaff(@RequestParam("id") Long id) { StaffDO staff = staffService.getStaff(id); - return success(BeanUtils.toBean(staff, StaffRespVO.class)); + return success(staff); } @GetMapping("/getListByFactory") @@ -96,7 +102,19 @@ public class StaffController { @PreAuthorize("@ss.hasPermission('factory:staff:query')") public CommonResult> getStaffPage(@Valid StaffPageReqVO pageReqVO) { PageResult pageResult = staffService.getStaffPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, StaffRespVO.class)); + PageResult result = BeanUtils.toBean(pageResult, StaffRespVO.class); + if (CollUtil.isNotEmpty(result.getList())) { + + // 获取工厂详情 + Set factoryIds = convertSet(result.getList(), StaffRespVO::getFactoryId); + Map factoryInfoMap = convertMap(factoryInfoService.getFactoryList(factoryIds), FactoryInfoDO::getId); + result.getList().forEach(data -> { + // 设置工厂名称 + data.setFactoryName(factoryInfoMap.containsKey(data.getFactoryId()) ? factoryInfoMap.get(data.getFactoryId()).getName() : null); + }); + } + + return success(result); } @GetMapping("/export-excel") @@ -128,11 +146,21 @@ public class StaffController { .map(item -> item.getValue() + ":" + item.getLabel()) .collect(Collectors.toList()); + // 获取业务类型名称 + List businessTypeVOs = dictDataApi.getDictDataList("system_settlement_type").getCheckedData(); + List businessTypeName = businessTypeVOs.stream() + .map(item -> item.getValue() + ":" + item.getLabel()) + .collect(Collectors.toList()); + + Map> mapDropDown = new HashMap<>(); + mapDropDown.put(1, factoryName); + mapDropDown.put(2, workTypeName); + mapDropDown.put(3, businessTypeName); + // 输出 ExcelUtils.write(response, "工人导入模板.xlsx", "工人列表", StaffImportExcelVO.class, null, - 1, factoryName, - 2, workTypeName); + mapDropDown); } @PostMapping("/import") diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffImportExcelVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffImportExcelVO.java index af42ec3a..f384d2c5 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffImportExcelVO.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffImportExcelVO.java @@ -30,6 +30,9 @@ public class StaffImportExcelVO { @ExcelProperty("工种名称") private String workTypeName; + @ExcelProperty("业务类型名称") + private String businessTypeName; + @ExcelProperty("手机号码") @Mobile private String mobile; diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffPageReqVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffPageReqVO.java index dc6dbc10..4a20ce13 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffPageReqVO.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffPageReqVO.java @@ -15,15 +15,12 @@ public class StaffPageReqVO extends PageParam { @Schema(description = "员工昵称") private String nickName; - @Schema(description = "年龄") - private Integer age; - - @Schema(description = "用户性别(0男 1女 2未知)") - private Integer sex; - @Schema(description = "工种id", example = "6971") private Integer workTypeId; + @Schema(description = "所属业务类型") + private Integer businessType; + @Schema(description = "工厂id", example = "6971") private Long factoryId; diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffRespVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffRespVO.java index 0d0f7506..cc1f3e7f 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffRespVO.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffRespVO.java @@ -31,6 +31,9 @@ public class StaffRespVO { @Schema(description = "工种id", example = "6971") private Integer workTypeId; + @Schema(description = "所属业务类型") + private Integer businessType; + @Schema(description = "工厂id", example = "6971") private Long factoryId; diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffSaveReqVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffSaveReqVO.java index 7e75f02f..a16ce756 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffSaveReqVO.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staff/vo/StaffSaveReqVO.java @@ -27,6 +27,9 @@ public class StaffSaveReqVO { @Schema(description = "工种id", example = "6971") private Integer workTypeId; + @Schema(description = "所属业务类型") + private Integer businessType; + @Schema(description = "工厂id", example = "6971") private Long factoryId; diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java index 3d22c139..9e0ded4f 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java @@ -6,6 +6,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffPageReqVO; +import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffRespVO; +import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffSaveReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO; @@ -49,8 +52,12 @@ public class StaffSalaryController { @Resource private FactoryInfoService factoryInfoService; - @Resource - private LoanApi loanApi; + @PostMapping("/create") + @Operation(summary = "创建员工工资") + @PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:create')") + public CommonResult createStaff(@Valid @RequestBody StaffSalarySaveReqVO createReqVO) { + return success(staffSalaryService.createStaffSalary(createReqVO)); + } @PutMapping("/update") @Operation(summary = "更新厂区员工工资") @@ -83,15 +90,8 @@ public class StaffSalaryController { @PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:query')") public CommonResult getStaffSalary(@RequestParam("id") Long id) { StaffSalaryDO staffSalary = staffSalaryService.getStaffSalary(id); - StaffSalaryRespVO respVO = BeanUtils.toBean(staffSalary, StaffSalaryRespVO.class); - if (respVO != null) { - // 获取员工借支信息 - LoanDTO loanDTO = loanApi.getByUserId(staffSalary.getStaffId()).getCheckedData(); - // 设置员工借支余额 - respVO.setLoanAmount(loanDTO.getRemainingAmount()); - } - return success(respVO); + return success(BeanUtils.toBean(staffSalary, StaffSalaryRespVO.class)); } @GetMapping("/get-list") diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staff/StaffDO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staff/StaffDO.java index 346a27b8..95f9f8ab 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staff/StaffDO.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staff/StaffDO.java @@ -48,6 +48,11 @@ public class StaffDO extends BaseDO { */ private Integer workTypeId; + /** + * 所属业务类型 + */ + private Integer businessType; + /** * 工厂id */ diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java index 26903be2..9c80bbce 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staff/StaffMapper.java @@ -3,12 +3,18 @@ package cn.iocoder.yudao.module.smartfactory.dal.mysql.staff; 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.module.smartfactory.controller.admin.staff.vo.StaffPageReqVO; +import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO; +import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO; +import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factoryinfo.FactoryInfoDO; import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staff.StaffDO; +import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Objects; /** * 员工 Mapper @@ -20,8 +26,9 @@ public interface StaffMapper extends BaseMapperX { default PageResult selectPage(StaffPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(StaffDO::getAge, reqVO.getAge()) .eqIfPresent(StaffDO::getWorkTypeId, reqVO.getWorkTypeId()) + .eqIfPresent(StaffDO::getFactoryId, reqVO.getFactoryId()) + .likeIfPresent(StaffDO::getNickName, reqVO.getNickName()) .eqIfPresent(StaffDO::getStatus, reqVO.getStatus()) .orderByDesc(StaffDO::getId)); } @@ -40,4 +47,35 @@ public interface StaffMapper extends BaseMapperX { * @return 员工信息列表 */ List getStaffDataV2(@Param("factoryId") Long factoryId); + + default PageResult selectSalaryPage(StaffSalaryPageReqVO pageReqVO) { + + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .selectAs(StaffDO::getId, StaffSalaryRespVO::getStaffId) + .selectAs(StaffDO::getNickName, StaffSalaryRespVO::getStaffName) + .selectAs(StaffDO::getFactoryId, StaffSalaryRespVO::getFactoryId) + .selectAs(FactoryInfoDO::getName, StaffSalaryRespVO::getFactoryName) + .selectAs(StaffDO::getWorkTypeId, StaffSalaryRespVO::getWorkTypeId) + .selectAs(StaffSalaryDO::getMonth, StaffSalaryRespVO::getMonth) + .selectAs(StaffDO::getSalary, StaffSalaryRespVO::getSalary) + .selectAs(StaffSalaryDO::getId, StaffSalaryRespVO::getId) + .selectAs(StaffSalaryDO::getAttendanceDays, StaffSalaryRespVO::getAttendanceDays) + .selectAs(StaffSalaryDO::getPayableAmount, StaffSalaryRespVO::getPayableAmount) + .selectAs(StaffSalaryDO::getReturnAmount, StaffSalaryRespVO::getReturnAmount) + .selectAs(StaffSalaryDO::getDeductionAmount, StaffSalaryRespVO::getDeductionAmount) + .selectAs(StaffSalaryDO::getRealAmount, StaffSalaryRespVO::getRealAmount) + .selectAs(StaffSalaryDO::getDeductionItems, StaffSalaryRespVO::getDeductionItems) + .selectAs(StaffSalaryDO::getStatus, StaffSalaryRespVO::getStatus) + .selectAs(StaffSalaryDO::getCreateTime, StaffSalaryRespVO::getCreateTime); + query.leftJoin(StaffSalaryDO.class, on -> on + .eq(StaffDO::getId, StaffSalaryDO::getStaffId) + .eq(Objects.nonNull(pageReqVO.getMonth()), StaffSalaryDO::getMonth, pageReqVO.getMonth()) + .eq(Objects.nonNull(pageReqVO.getStatus()), StaffSalaryDO::getStatus, pageReqVO.getStatus())); + query.leftJoin(FactoryInfoDO.class, FactoryInfoDO::getId, StaffDO::getFactoryId); + query.eqIfPresent(StaffDO::getFactoryId, pageReqVO.getFactoryId()); + query.eqIfPresent(StaffDO::getWorkTypeId, pageReqVO.getWorkTypeId()); + query.eqIfPresent(StaffDO::getId, pageReqVO.getStaffId()); + + return selectJoinPage(pageReqVO, StaffSalaryRespVO.class, query); + } } diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java index 54c6fb1c..5dfcc890 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java @@ -16,17 +16,19 @@ import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffPageR import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffSaveReqVO; import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staff.StaffDO; import cn.iocoder.yudao.module.smartfactory.dal.mysql.staff.StaffMapper; +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; +import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_NOT_EXISTS; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_IMPORT_LIST_IS_EMPTY; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS; @@ -43,6 +45,9 @@ public class StaffServiceImpl implements StaffService { @Resource private StaffMapper staffMapper; + @Resource + private DictDataApi dictDataApi; + @Override public Long createStaff(StaffSaveReqVO createReqVO) { // 插入 @@ -54,7 +59,9 @@ public class StaffServiceImpl implements StaffService { @Override public void updateStaff(StaffSaveReqVO updateReqVO) { - validateUserForCreateOrUpdate(updateReqVO.getId(), null, null, null); + if (staffMapper.selectById(updateReqVO.getId()) == null) { + throw exception(STAFF_NOT_EXISTS); + } // 更新 StaffDO updateObj = BeanUtils.toBean(updateReqVO, StaffDO.class); staffMapper.updateById(updateObj); @@ -66,7 +73,7 @@ public class StaffServiceImpl implements StaffService { staffMapper.deleteById(id); } - private void validateUserForCreateOrUpdate(Long id, String username, String mobile, String idCard) { + private void validateUserForCreate(Long id, String username, String mobile, String idCard) { // 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确 DataPermissionUtils.executeIgnore(() -> { @@ -95,7 +102,18 @@ public class StaffServiceImpl implements StaffService { @Override public StaffDataRespVO getStaffData(Long factoryId) { StaffDataRespVO vo = new StaffDataRespVO(); - List dos = staffMapper.getStaffData(factoryId); + List dos = staffMapper.selectList(new LambdaQueryWrapperX() + .ne(StaffDO::getStatus, 0)); + + // 获取工种信息 + List workTypeVOs = dictDataApi.getDictDataList("user_work_type").getCheckedData(); + Map workTypeMap = workTypeVOs.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + + // 设置工种名称 + dos.forEach(item -> { + item.setPostName(workTypeMap.getOrDefault(item.getWorkTypeId().toString(), "")); + }); + vo.setTotal(dos.size()); vo.setMaleTotal((int) dos.stream().filter(a -> a.getSex() == 0).count()); vo.setFemaleTotal((int) dos.stream().filter(a -> a.getSex() == 1).count()); @@ -112,6 +130,14 @@ public class StaffServiceImpl implements StaffService { public StaffDataRespVO getStaffDataV2(Long factoryId) { StaffDataRespVO vo = new StaffDataRespVO(); List dos = staffMapper.getStaffDataV2(factoryId); + // 获取工种信息 + List workTypeVOs = dictDataApi.getDictDataList("user_work_type").getCheckedData(); + Map workTypeMap = workTypeVOs.stream().collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel)); + + // 设置工种名称 + dos.forEach(item -> { + item.setPostName(workTypeMap.getOrDefault(item.getWorkTypeId().toString(), "")); + }); vo.setTotal(dos.size()); vo.setMaleTotal((int) dos.stream().filter(a -> a.getSex() == 0).count()); vo.setFemaleTotal((int) dos.stream().filter(a -> a.getSex() == 1).count()); @@ -137,7 +163,7 @@ public class StaffServiceImpl implements StaffService { //校验,判断是否有不符合的原因 try { if (!updateSupport) { - validateUserForCreateOrUpdate(null, importUser.getNickName(), null, importUser.getIdCard()); + validateUserForCreate(null, importUser.getNickName(), null, importUser.getIdCard()); } } catch (ServiceException ex) { respVO.getFailureUsernames().put(importUser.getNickName(), ex.getMessage()); @@ -167,11 +193,17 @@ public class StaffServiceImpl implements StaffService { updateUser.setWorkTypeId(Integer.valueOf(importUser.getWorkTypeName().split(":")[0])); } + // 设置业务类型 + if (StrUtil.isNotEmpty(importUser.getBusinessTypeName())) { + + updateUser.setBusinessType(Integer.valueOf(importUser.getBusinessTypeName().split(":")[0])); + } + // 判断如果不存在,在进行插入 if (updateSupport) { StaffDO staffDO = staffMapper.selectOne(new LambdaQueryWrapperX() - .eq(StaffDO::getIdCard, importUser.getIdCard()) - .eq(StaffDO::getNickName, importUser.getNickName())); + .eqIfPresent(StaffDO::getIdCard, importUser.getIdCard()) + .eqIfPresent(StaffDO::getNickName, importUser.getNickName())); updateUser.setId(staffDO.getId()); staffMapper.updateById(updateUser); diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java index b122440b..fa0666d2 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java @@ -16,6 +16,13 @@ import java.util.List; */ public interface StaffSalaryService { + /** + * 创建厂区员工工资 + * @param createReqVO 创建信息 + * @return 工资编号 + */ + Long createStaffSalary(StaffSalarySaveReqVO createReqVO); + /** * 更新厂区员工工资 * diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java index 7cfd0778..f2704092 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.Staf import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO; import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO; +import cn.iocoder.yudao.module.smartfactory.dal.mysql.staff.StaffMapper; import cn.iocoder.yudao.module.smartfactory.dal.mysql.staffsalary.StaffSalaryMapper; import cn.iocoder.yudao.module.system.api.loan.LoanApi; import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO; @@ -19,6 +20,7 @@ import java.math.BigDecimal; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_EXISTS; import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_NOT_EXISTS; /** @@ -33,9 +35,30 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { @Resource private StaffSalaryMapper staffSalaryMapper; + @Resource + private StaffMapper staffMapper; + @Resource private LoanApi loanApi; + @Override + public Long createStaffSalary(StaffSalarySaveReqVO createReqVO) { + + // 校验当前月份工资是否存在 + Long count = staffSalaryMapper.selectCount(new LambdaQueryWrapperX() + .eq(StaffSalaryDO::getStaffId, createReqVO.getStaffId()) + .eq(StaffSalaryDO::getMonth, createReqVO.getMonth())); + if (count > 0L) { + throw exception(STAFF_SALARY_EXISTS); + } + + // 插入 + StaffSalaryDO staffSalaryDO = BeanUtils.toBean(createReqVO, StaffSalaryDO.class); + staffSalaryMapper.insert(staffSalaryDO); + + return staffSalaryDO.getId(); + } + @Override public void updateStaffSalary(StaffSalarySaveReqVO updateReqVO) { // 校验存在 @@ -68,7 +91,12 @@ public class StaffSalaryServiceImpl implements StaffSalaryService { @Override public PageResult getStaffSalaryPage(StaffSalaryPageReqVO pageReqVO) { - return staffSalaryMapper.selectSalaryPage(pageReqVO); + + if (pageReqVO.getMonth() != null) { + return staffMapper.selectSalaryPage(pageReqVO); + }else { + return staffSalaryMapper.selectSalaryPage(pageReqVO); + } } @Override diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/resources/mapper/staff/StaffMapper.xml b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/resources/mapper/staff/StaffMapper.xml index d502a30e..c3bc4930 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/resources/mapper/staff/StaffMapper.xml +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/resources/mapper/staff/StaffMapper.xml @@ -37,18 +37,15 @@ ext.work_type as workType, b.factory_id as factoryId, a.idcard as idCard, - a.status as status, - d.label as postName + a.status as status FROM system_users AS a LEFT JOIN system_users_ext AS ext ON a.id = ext.user_id LEFT JOIN system_dept AS b ON a.dept_id = b.id LEFT JOIN sf_factory_info AS c ON b.factory_id = c.id - left join system_dict_data as d on ext.work_type = d.value a.user_type = 2 and a.deleted = 0 - and d.dict_type = 'user_work_type' and b.factory_id = #{factoryId} From b169fadbf2ef181c14be879ed6efedfebadd957a Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Sat, 22 Feb 2025 16:27:48 +0800 Subject: [PATCH 2/7] =?UTF-8?q?refactor(excel):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E4=B8=8B=E6=8B=89=E6=A1=86=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 ExcelUtils 类中的 write 方法,使用 Map> 类型参数替代原有的多个参数 - 更新 SpinnerWriteHandler 类,使用新的参数类型处理下拉框数据 - 优化下拉框数据的处理逻辑,提高代码的可扩展性和维护性 --- .../framework/excel/core/util/ExcelUtils.java | 6 +-- .../excel/core/util/SpinnerWriteHandler.java | 39 +++++++------------ .../enums/ErrorCodeConstants.java | 3 ++ 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index 35fec2bb..b69b953b 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Map; /** * Excel 工具类 @@ -49,14 +50,13 @@ public class ExcelUtils { public static void write(HttpServletResponse response, String filename, String sheetName, Class head, List data, - int col, List value, - int col1,List value1) throws IOException { + Map> mapDropDown) throws IOException { // 输出excel EasyExcel.write(response.getOutputStream(), head) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 - .registerWriteHandler(new SpinnerWriteHandler(col, value, col1, value1)) + .registerWriteHandler(new SpinnerWriteHandler(mapDropDown)) .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 .excelType(ExcelTypeEnum.XLS) .sheet(sheetName).doWrite(data); diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/SpinnerWriteHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/SpinnerWriteHandler.java index 919d0217..6b78777e 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/SpinnerWriteHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/SpinnerWriteHandler.java @@ -13,36 +13,25 @@ import java.util.Map; public class SpinnerWriteHandler implements SheetWriteHandler { - private int col; - - private int col1; - - private List deptName; - - private List postName; + private Map> mapDropDown; public SpinnerWriteHandler() { } - public SpinnerWriteHandler(int col, List deptName, - int col1, List postName) { + public SpinnerWriteHandler(Map> mapDropDown) { - this.col = col; - this.col1 = col1; - this.deptName = deptName; - this.postName = postName; + this.mapDropDown = mapDropDown; } - @Override public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { - Map mapDropDown = new HashMap<>(); - // 这里的key值 对应导出列的顺序 从0开始 - if (deptName != null) { - mapDropDown.put(col, deptName.toArray(new String[0])); - } - mapDropDown.put(col1, postName.toArray(new String[0])); +// Map> mapDropDown = new HashMap<>(); +// // 这里的key值 对应导出列的顺序 从0开始 +// if (deptName != null) { +// mapDropDown.put(col, deptName); +// } +// mapDropDown.put(col1, postName); Sheet sheet = writeSheetHolder.getSheet(); /// 开始设置下拉框 DataValidationHelper helper = sheet.getDataValidationHelper();// 设置下拉框 @@ -56,7 +45,7 @@ public class SpinnerWriteHandler implements SheetWriteHandler { Name category1Name = workbook.createName(); category1Name.setNameName(hiddenName); - for (Map.Entry entry : mapDropDown.entrySet()) { + for (Map.Entry> entry : mapDropDown.entrySet()) { /*** 起始行、终止行、起始列、终止列 **/ CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, entry.getKey(), entry.getKey()); @@ -65,18 +54,18 @@ public class SpinnerWriteHandler implements SheetWriteHandler { String excelLine = getExcelLine(entry.getKey()); // 循环赋值 - String[] values = entry.getValue(); - for (int i = 0, length = values.length; i < length; i++) { + List values = entry.getValue(); + for (int i = 0; i < values.size(); i++) { // 3:表示你开始的行数 3表示 你开始的列数 Row row = hidden.getRow(i); if (row == null) { row = hidden.createRow(i); } - row.createCell(entry.getKey()).setCellValue(values[i]); + row.createCell(entry.getKey()).setCellValue(values.get(i)); } // hidden!$H:$1:$H$50 sheet为hidden的 H1列开始H50行数据获取下拉数组 String refers = hiddenName + "!$"+excelLine+ - "$1:$"+excelLine +"$"+ (values.length); + "$1:$"+excelLine +"$"+ (values.size()); /*** 设置下拉框数据 **/ DataValidationConstraint constraint = helper.createFormulaListConstraint(refers); diff --git a/zn-module-smartfactory/zn-module-smartfactory-api/src/main/java/cn/iocoder/yudao/module/smartfactory/enums/ErrorCodeConstants.java b/zn-module-smartfactory/zn-module-smartfactory-api/src/main/java/cn/iocoder/yudao/module/smartfactory/enums/ErrorCodeConstants.java index 54f60b83..9e1e8c46 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-api/src/main/java/cn/iocoder/yudao/module/smartfactory/enums/ErrorCodeConstants.java +++ b/zn-module-smartfactory/zn-module-smartfactory-api/src/main/java/cn/iocoder/yudao/module/smartfactory/enums/ErrorCodeConstants.java @@ -17,6 +17,8 @@ public interface ErrorCodeConstants { ErrorCode SIZE_NOT_EXISTS = new ErrorCode(1_000_000_004, "规格不存在"); + ErrorCode STAFF_NOT_EXISTS = new ErrorCode(1_000_000_005, "员工不存在"); + //打包线模块 ErrorCode PACKAGE_NOT_EXISTS = new ErrorCode(1_000_001_001, "打包线信息不存在"); ErrorCode PACKAGE_DATA_EXISTS = new ErrorCode(1_000_001_001, "当前日期的数据已存在"); @@ -32,4 +34,5 @@ public interface ErrorCodeConstants { // ========== 工资模块 1_000_004_000 ========== ErrorCode STAFF_SALARY_NOT_EXISTS = new ErrorCode(1_000_004_001, "工资记录不存在!"); ErrorCode INDUSTRIAL_INJURY_NOT_EXISTS = new ErrorCode(1_000_004_002, "工伤记录不存在!"); + ErrorCode STAFF_SALARY_EXISTS = new ErrorCode(1_000_004_003, "工资记录已存在"); } From 72b60dd1abe42b612f0df1e3f7b891821ff678e0 Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Sat, 22 Feb 2025 16:28:15 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix(system):=20=E4=BC=98=E5=8C=96=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95=E5=92=8C=E9=83=A8=E9=97=A8=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在补卡失败时添加错误日志记录 - 新增按工厂 ID 获取部门列表的接口 - 优化部门简单响应 VO,添加机构类型字段 - 调整贷款控制器,使用工厂信息 API 获取部门信息 - 修改日志使用列表查询方式 - 优化用户导出模板中的部门和岗位数据加载 --- .../yudao/module/system/api/dept/DeptApiImpl.java | 8 ++++++++ .../admin/dept/vo/dept/DeptSimpleRespVO.java | 5 ++++- .../controller/admin/loan/LoanController.java | 15 +++++++++++++-- .../controller/admin/user/UserController.java | 14 ++++++++++---- .../admin/worklog/LogFormController.java | 6 ++++-- .../system/dal/mysql/worklog/LogUseMapper.java | 2 ++ .../service/attendance/AttendanceServiceImpl.java | 2 ++ .../module/system/service/dept/DeptService.java | 2 +- .../system/service/dept/DeptServiceImpl.java | 2 +- .../system/service/worklog/LogUseServiceImpl.java | 6 +----- .../src/main/resources/logback-spring.xml | 2 +- .../resources/mapper/worklog/WorkLogUseMapper.xml | 13 +++++++++++++ 12 files changed, 60 insertions(+), 17 deletions(-) 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 f147139e..adecb122 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 @@ -108,6 +108,14 @@ public class DeptApiImpl implements DeptApi { return success(BeanUtils.toBean(deptDO, DeptRespDTO.class)); } + @Override + @DataPermission(enable = false) + public CommonResult> getDeptByFactoryIds(Collection factoryIds) { + + List deptDOS = deptService.getDeptListByFactoryIds(factoryIds); + return success(BeanUtils.toBean(deptDOS, DeptRespDTO.class)); + } + @Override @DataPermission(enable = false) public CommonResult> getChildDeptList(Long deptId) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java index 9079f238..6d4b73b3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java @@ -9,7 +9,7 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor -public class DeptSimpleRespVO { +public class DeptSimpleRespVO { @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; @@ -28,4 +28,7 @@ public class DeptSimpleRespVO { @Schema(description = "工厂编号") private Long factoryId; + + @Schema(description = "机构类型 | 字典值参考 system_dept_type", example = "0") + private String type; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java index 038caebb..16ca407f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java @@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.FactoryInfoApi; +import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO; import cn.iocoder.yudao.module.smartfactory.api.staff.StaffApi; import cn.iocoder.yudao.module.smartfactory.api.staff.dto.StaffDTO; import cn.iocoder.yudao.module.system.controller.admin.loan.vo.LoanPageReqVO; @@ -44,7 +46,7 @@ public class LoanController { private StaffApi staffApi; @Resource - private DeptService deptService; + private FactoryInfoApi factoryInfoApi; @GetMapping("/get") @Operation(summary = "获得借支管理") @@ -55,6 +57,15 @@ public class LoanController { return success(BeanUtils.toBean(loan, LoanRespVO.class)); } + @GetMapping("/getByStaffId") + @Operation(summary = "获得指定员工的借支管理") + @Parameter(name = "staffId", description = "员工编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:loan:query')") + public CommonResult getByStaffId(@RequestParam("id") Long id) { + LoanDO loan = loanService.getByUserId(id); + return success(BeanUtils.toBean(loan, LoanRespVO.class)); + } + @GetMapping("/page") @Operation(summary = "获得借支管理分页") @PreAuthorize("@ss.hasPermission('system:loan:query')") @@ -70,7 +81,7 @@ public class LoanController { // 获取部门信息 Set deptIds = convertSet(result.getList(), LoanRespVO::getDeptId); - Map deptMap = convertMap(deptService.getDeptList(deptIds), DeptDO::getId); + Map deptMap = factoryInfoApi.getFactoryMap(deptIds); result.getList().forEach(item -> { // 设置借支用户名称 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java index 16cbea78..9a2eb701 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java @@ -372,11 +372,14 @@ public class UserController { List postDO = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); postDO.sort(Comparator.comparing(PostDO::getSort)); + Map> mapDropDown = new HashMap<>(); + mapDropDown.put(1, getDeptNameFun(deptDO)); + mapDropDown.put(2, getPostNameFun(postDO)); + // 输出 Excel ExcelUtils.write(response, "用户数据.xls", "数据", UserRespVO.class, UserConvert.INSTANCE.convertList(list, deptMap, postMap, positionMap), - 1, getDeptNameFun(deptDO), - 2, getPostNameFun(postDO)); + mapDropDown); } @GetMapping("/get-import-template") @@ -397,11 +400,14 @@ public class UserController { List postDO = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); postDO.sort(Comparator.comparing(PostDO::getSort)); + Map> mapDropDown = new HashMap<>(); + mapDropDown.put(1, getDeptNameFun(deptDO)); + mapDropDown.put(2, getPostNameFun(postDO)); + // 输出 ExcelUtils.write(response, "用户导入模板.xlsx", "用户列表", UserImportExcelVO.class, null, - 1, getDeptNameFun(deptDO), - 2, getPostNameFun(postDO)); + mapDropDown); } @PostMapping("/import") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogFormController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogFormController.java index 6e0c509d..5cd94cda 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogFormController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/worklog/LogFormController.java @@ -71,8 +71,10 @@ public class LogFormController { //获取规则信息 LogRuleDO logRuleDO = logRuleService.getLogRule(form.getId()); - //设置日志类型 - logFormRespVO.setType(logRuleDO.getType()); + if (logRuleDO != null) { + //设置日志类型 + logFormRespVO.setType(logRuleDO.getType()); + } } return success(logFormRespVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogUseMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogUseMapper.java index 88d14789..6bca784b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogUseMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/worklog/LogUseMapper.java @@ -45,4 +45,6 @@ public interface LogUseMapper extends BaseMapperX { * @return */ List getFormIdsByDataPermission(Long userId); + + List selectUseDeptList(); } \ 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 df8d5e22..d0cffcde 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 @@ -1084,6 +1084,7 @@ public class AttendanceServiceImpl implements AttendanceService { // -- 如果有报错的话 - 那么进行回滚操作 - 并且redis 中的补卡次数也要+1 (redis并不会回滚) String key = "ReplacementCardNum" + "_" + userId + "_" + LocalDateTime.now().format(Constants.YEAR_MONTH_FORMAT); stringRedisTemplate.opsForValue().increment(key, 1); + log.error("补卡失败", e); throw exception(ABNORMAL_CARD_REPLENISHMENT); } } @@ -1115,6 +1116,7 @@ public class AttendanceServiceImpl implements AttendanceService { // -- 如果有报错的话 - 那么进行回滚操作 - 并且redis 中的补卡次数也要+1 (redis并不会回滚) String key = "ReplacementCardNum" + "_" + userId + "_" + LocalDateTime.now().format(Constants.YEAR_MONTH_FORMAT); stringRedisTemplate.opsForValue().increment(key, punchRecordIds.size()); + log.error("补卡失败", e); throw exception(ABNORMAL_CARD_REPLENISHMENT); } } 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 53bd84dd..45b6c329 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 @@ -160,7 +160,7 @@ public interface DeptService { * @param factoryIds * @return */ - List getDeptListByFactoryIds(List factoryIds); + List getDeptListByFactoryIds(Collection factoryIds); /** * 获取部门列表 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 5784c05a..7dedab46 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 @@ -356,7 +356,7 @@ public class DeptServiceImpl implements DeptService { } @Override - public List getDeptListByFactoryIds(List factoryIds) { + public List getDeptListByFactoryIds(Collection factoryIds) { return deptMapper.selectList(new LambdaQueryWrapper() .in(DeptDO::getFactoryId, factoryIds)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java index e25fd904..e002fee8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java @@ -98,11 +98,7 @@ public class LogUseServiceImpl implements LogUseService { @Override public List getUseDeptList() { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.select("DISTINCT use_user_dept"); - - List logUseDOS = logUseMapper.selectList(queryWrapper); - return convertList(logUseDOS, LogUseDO::getUseUserDept); + return logUseMapper.selectUseDeptList(); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/logback-spring.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/logback-spring.xml index b1b9f3fa..a9262550 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/logback-spring.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/logback-spring.xml @@ -66,7 +66,7 @@ - + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/WorkLogUseMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/WorkLogUseMapper.xml index 56117716..957572a0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/WorkLogUseMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/worklog/WorkLogUseMapper.xml @@ -30,4 +30,17 @@ deleted = 0 and form_id = #{formId} + + \ No newline at end of file From d1e94a0d3dff17e3d32bcdcb68a5fb1a5eab830a Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Sat, 22 Feb 2025 16:29:06 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat(product):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=95=86=E6=9C=BA=E5=85=B3=E8=81=94=E4=BA=A7=E5=93=81=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BA=A7=E5=93=81=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在产品模块中添加了根据商机 ID 查询产品列表的功能 - 更新了产品分页查询接口,使用 goodsCateId 替代 cateId- 在 RpcConfiguration 中添加了 BusinessApi 客户端 -优化了 StoreProductMapper 中的产品查询条件 --- .../yudao-module-product-biz/pom.xml | 6 +++++ .../storeproduct/StoreProductController.java | 26 +++++++++++++++++++ .../vo/StoreProductPageReqVO.java | 4 +-- .../storeproduct/StoreProductMapper.java | 2 +- .../rpc/config/RpcConfiguration.java | 3 ++- .../yudao/module/system/api/dept/DeptApi.java | 7 ++++- .../controller/admin/loan/LoanController.java | 2 -- .../service/worklog/LogUseServiceImpl.java | 1 - .../staffsalary/StaffSalaryController.java | 5 ---- .../service/staff/StaffServiceImpl.java | 1 - 10 files changed, 43 insertions(+), 14 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/pom.xml b/yudao-module-mall/yudao-module-product-biz/pom.xml index 6ed7d2f2..ce523439 100644 --- a/yudao-module-mall/yudao-module-product-biz/pom.xml +++ b/yudao-module-mall/yudao-module-product-biz/pom.xml @@ -110,6 +110,12 @@ cn.iocoder.cloud yudao-spring-boot-starter-monitor + + cn.iocoder.cloud + yudao-module-crm-api + 2.0.0-jdk8-snapshot + compile + diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/StoreProductController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/StoreProductController.java index 797fef3b..371e1de4 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/StoreProductController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/StoreProductController.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.product.controller.admin.storeproduct; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.hrm.api.crmbusiness.BusinessApi; +import cn.iocoder.yudao.module.hrm.api.crmbusiness.dto.CrmBusinessProductDTO; import cn.iocoder.yudao.module.product.controller.admin.storeproduct.vo.*; import cn.iocoder.yudao.module.product.convert.storeproduct.StoreProductConvert; import cn.iocoder.yudao.module.product.dal.dataobject.storeproduct.StoreProductDO; @@ -25,8 +28,10 @@ import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 商品") @RestController @@ -39,6 +44,8 @@ public class StoreProductController { @Resource private StoreProductAttrValueService storeProductAttrValueService; + @Resource + private BusinessApi businessApi; @PostMapping("/create") @Operation(summary = "创建商品") @@ -83,6 +90,25 @@ public class StoreProductController { return success(StoreProductConvert.INSTANCE.convertList(list)); } + @GetMapping("/listByBusinessId") + @Operation(summary = "获得指定商机的商品列表") + @Parameter(name = "businessId", description = "商机ID", required = true, example = "1024,2048") + @PreAuthorize("@ss.hasPermission('shop:store-product:query')") + public CommonResult> getStoreProductList(@RequestParam("businessId") Long businessId) { + + // 获取商机绑定产品的信息 + List businessProductList = businessApi.getBusinessProduct(businessId).getCheckedData(); + // 获取产品编号 + Set ids = convertSet(businessProductList, CrmBusinessProductDTO::getProductId); + + if (CollUtil.isNotEmpty(ids)) { + List list = storeProductService.getStoreProductList(ids); + return success(StoreProductConvert.INSTANCE.convertList(list)); + }else { + return success(CollUtil.newArrayList()); + } + } + @GetMapping("/page") @Operation(summary = "获得商品分页") @PreAuthorize("@ss.hasPermission('shop:store-product:query')") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/vo/StoreProductPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/vo/StoreProductPageReqVO.java index 63d38461..f609a546 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/vo/StoreProductPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/storeproduct/vo/StoreProductPageReqVO.java @@ -28,8 +28,8 @@ public class StoreProductPageReqVO extends PageParam { @Schema(description = "库存售罄", example = "0") private String stock; - @Schema(description = "库存售罄", example = "0") - private String cateId; + @Schema(description = "商品分类id", example = "0") + private String goodsCateId; private List catIds; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/storeproduct/StoreProductMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/storeproduct/StoreProductMapper.java index 924a7b9e..bb0a24fd 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/storeproduct/StoreProductMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/storeproduct/StoreProductMapper.java @@ -27,7 +27,7 @@ public interface StoreProductMapper extends BaseMapperX { wrapper.likeIfPresent(StoreProductDO::getStoreName, reqVO.getStoreName()) .likeIfPresent(StoreProductDO::getShopName, reqVO.getShopName()) .eqIfPresent(StoreProductDO::getIsPostage, reqVO.getIsPostage()) - .eqIfPresent(StoreProductDO::getCateId, reqVO.getCateId()) + .eqIfPresent(StoreProductDO::getCateId, reqVO.getGoodsCateId()) .orderByDesc(StoreProductDO::getId); wrapper.eq(StoreProductDO::getIsShow, Convert.toInt(reqVO.getIsShow())); diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/rpc/config/RpcConfiguration.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/rpc/config/RpcConfiguration.java index a5f8aff4..1c9f5eec 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/rpc/config/RpcConfiguration.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/rpc/config/RpcConfiguration.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.module.product.framework.rpc.config; +import cn.iocoder.yudao.module.hrm.api.crmbusiness.BusinessApi; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) -@EnableFeignClients(clients = {MemberUserApi.class, MemberLevelApi.class}) +@EnableFeignClients(clients = {MemberUserApi.class, MemberLevelApi.class, BusinessApi.class}) public class RpcConfiguration { } 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 d7b831cd..56ab81bb 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 @@ -68,11 +68,16 @@ public interface DeptApi { @Parameter(name = "factoryId", description = "工厂编号", example = "100001", required = true) void deleteDept(@RequestParam("factoryId") Long factoryId); - @PostMapping(PREFIX + "/getByFactoryId") + @GetMapping(PREFIX + "/getByFactoryId") @Operation(summary = "根据工厂ID获得部门信息") @Parameter(name = "factoryId", description = "工厂编号", example = "100001", required = true) CommonResult getDeptByFactoryId(@RequestParam("factoryId") Long factoryId); + @GetMapping(PREFIX + "/getByFactoryIds") + @Operation(summary = "根据工厂ID获得部门信息") + @Parameter(name = "factoryIds", description = "工厂编号", example = "100001", required = true) + CommonResult> getDeptByFactoryIds(@RequestParam("factoryIds") Collection factoryIds); + /** * 获得指定编号的部门 Map diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java index 16ca407f..ad86ff6a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/loan/LoanController.java @@ -10,9 +10,7 @@ import cn.iocoder.yudao.module.smartfactory.api.staff.StaffApi; import cn.iocoder.yudao.module.smartfactory.api.staff.dto.StaffDTO; import cn.iocoder.yudao.module.system.controller.admin.loan.vo.LoanPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.loan.vo.LoanRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.loan.LoanDO; -import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.loan.LoanService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java index e002fee8..54fb5216 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/worklog/LogUseServiceImpl.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.dal.dataobject.worklog.LogUseDO; import cn.iocoder.yudao.module.system.dal.mysql.worklog.LogUseMapper; import cn.iocoder.yudao.module.system.service.worklog.dto.LogUseSaveReqDTO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java index 9e0ded4f..5f524825 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java @@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffPageReqVO; -import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffRespVO; -import cn.iocoder.yudao.module.smartfactory.controller.admin.staff.vo.StaffSaveReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO; @@ -18,8 +15,6 @@ import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSala import cn.iocoder.yudao.module.smartfactory.service.factoryinfo.FactoryInfoService; import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService; import cn.iocoder.yudao.module.smartfactory.service.staffsalary.StaffSalaryService; -import cn.iocoder.yudao.module.system.api.loan.LoanApi; -import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java index 5dfcc890..899b83ae 100644 --- a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staff/StaffServiceImpl.java @@ -27,7 +27,6 @@ import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_NOT_EXISTS; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_IMPORT_LIST_IS_EMPTY; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS; From 4900d87c40bbce8ca4e907e2334f274c51b15077 Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Sat, 22 Feb 2025 16:29:30 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat(bpm):=20=E6=96=B0=E5=A2=9E=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=AE=9A=E4=B9=89=E4=BD=BF=E7=94=A8=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 BpmProcessDefinitionExtDO 中添加 dataScope、dataScopeDeptIds 和 dataScopeUserIds 字段 - 实现流程定义使用权限的更新接口- 修改流程定义列表查询逻辑,根据用户权限进行过滤 -优化流程定义查询接口,返回更详细的信息 --- .../definition/BpmTaskRuleScriptEnum.java | 6 +- .../BpmProcessDefinitionController.java | 20 ++++ .../process/BpmProcessDefinitionRespVO.java | 3 + .../vo/process/DefinitionScopeVO.java | 25 ++++ .../admin/oa/BpmOAImprestController.java | 17 ++- .../admin/oa/BpmOALoanController.java | 14 ++- .../admin/oa/BpmOAPaymentController.java | 2 + .../vo/imprest/BpmOAImprestCreateReqVO.java | 4 + .../oa/vo/imprest/BpmOAImprestRespVO.java | 6 + .../admin/oa/vo/loan/BpmOALoanRespVO.java | 3 + .../oa/vo/print/BpmOAPrintDataRespVO.java | 29 +++++ .../vo/instance/BpmProcessInstanceRespVO.java | 7 ++ .../task/BpmProcessInstanceConvert.java | 8 +- .../definition/BpmProcessDefinitionExtDO.java | 17 +++ .../financialpayment/FinancialPaymentDO.java | 2 +- .../bpm/dal/dataobject/oa/BpmOAImprestDO.java | 5 + .../bpm/dal/mysql/oa/BpmOAPaymentMapper.java | 5 +- .../impl/BpmTaskAssignLeaderScript.java | 82 +++++++++++++ .../BpmTaskCurrentAssignLeaderScript.java | 106 ++++++++++------- .../script/impl/BpmTaskEntryLeaderScript.java | 11 +- .../impl/BpmTaskFactoryLeaderScript.java | 110 ++++++++++++++++++ .../BpmProcessDefinitionService.java | 6 + .../BpmProcessDefinitionServiceImpl.java | 46 +++++++- .../FinancialPaymentServiceImpl.java | 66 +++++++++-- .../service/oa/BpmOAExpensesServiceImpl.java | 60 +--------- .../service/oa/BpmOAImprestServiceImpl.java | 4 +- .../bpm/service/oa/BpmOALoanServiceImpl.java | 36 ++++-- .../service/oa/BpmOAPaymentServiceImpl.java | 14 ++- ...mOASupplierPurchasePaymentServiceImpl.java | 2 +- .../task/BpmProcessInstanceServiceImpl.java | 2 +- .../mapper/oa/BpmOAPaymentMapper.xml | 11 ++ 31 files changed, 579 insertions(+), 150 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/DefinitionScopeVO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderScript.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskFactoryLeaderScript.java diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java index ff987f2e..5d20d11a 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java @@ -18,12 +18,14 @@ public enum BpmTaskRuleScriptEnum { LEADER_X1(20L, "流程发起人的一级领导"), LEADER_X2(21L, "流程发起人的二级领导"), LEADER_X3(22L, "流程发起人的三级领导"), - LEADER_X4(23L, "审批人的上级领导"), + LEADER_X4(23L, "发起人的上级领导"), LEADER_X5(24L, "调岗部门领导"), LEADER_X6(25L, "分配任务的责任人"), LEADER_X7(26L, "入职部门领导"), LEADER_X8(27L, "调薪部门领导"), - LEADER_X9(28L, "调薪人上级领导"); + LEADER_X9(28L, "调薪人上级领导"), + LEADER_X10(29L, "所选工厂的领导"), + LEADER_X11(30L, "审批人的上级领导"); /** * 脚本编号 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java index 0c2fb4a4..c583d12b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.*; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -12,6 +14,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.validation.Valid; import java.util.List; import java.util.stream.Collectors; @@ -61,4 +64,21 @@ public class BpmProcessDefinitionController { String bpmnXML = bpmDefinitionService.getProcessDefinitionBpmnXML(id); return success(bpmnXML); } + + @PutMapping ("/update-scope") + @Operation(summary = "修改流程定义的 Scope") + public CommonResult updateProcessDefinitionScope(@Valid @RequestBody DefinitionScopeVO scopeVO) { + bpmDefinitionService.updateProcessDefinitionScope(scopeVO); + return success(true); + } + + @GetMapping ("/get") + @Operation(summary = "获得流程定义") + @Parameter(name = "processDefinitionId", description = "流程定义编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')") + public CommonResult getProcessDefinition(@RequestParam("processDefinitionId") String processDefinitionId) { + + BpmProcessDefinitionExtDO definitionExtDO = bpmDefinitionService.getProcessDefinitionExt(processDefinitionId); + return success(BeanUtils.toBean(definitionExtDO, DefinitionScopeVO.class)); + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java index af84cb0a..639183d8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java @@ -16,6 +16,9 @@ public class BpmProcessDefinitionRespVO { @Schema(description = "版本", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer version; + @Schema(description = "流程Key") + private String key; + @Schema(description = "流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") @NotEmpty(message = "流程名称不能为空") private String name; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/DefinitionScopeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/DefinitionScopeVO.java new file mode 100644 index 00000000..c6f9a5dc --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/DefinitionScopeVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "管理后台 - 流程定义的 ScopeVO") +@Data +public class DefinitionScopeVO { + + @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "流程定义的编号不能为空") + private String processDefinitionId; + + @Schema(description = "使用权限范围 | 1全员 2指定部门 3指定用户", example = "1") + private Integer dataScope; + + @Schema(description = "使用权限范围 | 指定部门编号数组", example = "1,2,3") + private List dataScopeDeptIds; + + @Schema(description = "使用权限范围 | 指定用户编号数组", example = "1,2,3") + private List dataScopeUserIds; +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAImprestController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAImprestController.java index 725b93ff..35f4d254 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAImprestController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAImprestController.java @@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAImprestDO; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAImprestService; import cn.iocoder.yudao.module.system.api.bank.BankApi; import cn.iocoder.yudao.module.system.api.bank.dto.BankRespDTO; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -38,6 +40,9 @@ public class BpmOAImprestController { @Resource private BankApi bankApi; + @Resource + private DeptApi deptApi; + @PostMapping("/create") @Operation(summary = "创建请求申请") public CommonResult createImprest(@Valid @RequestBody BpmOAImprestCreateReqVO createReqVO) { @@ -52,14 +57,18 @@ public class BpmOAImprestController { BpmOAImprestDO imprest = imprestService.getImprest(id); BpmOAImprestRespVO respVO = BpmOAImprestConvert.INSTANCE.convert(imprest); - if (respVO != null && imprest.getBankId() != null) { + if (respVO != null) { // 获取收款账号信息 - BankRespDTO bankRespDTO = bankApi.getBank(imprest.getBankId()).getCheckedData(); + BankRespDTO bankRespDTO = bankApi.getBank(respVO.getBankId()).getCheckedData(); if (bankRespDTO != null) { respVO.setBankName(bankRespDTO.getBankName()); respVO.setNickname(bankRespDTO.getNickname()); respVO.setBankNo(bankRespDTO.getBankNo()); } + + // 获取公司信息 + DeptRespDTO company = deptApi.getDept(respVO.getCompanyId()).getCheckedData(); + respVO.setCompanyName(company.getName()); } return success(respVO); @@ -99,6 +108,10 @@ public class BpmOAImprestController { respVO.setNickname(bankRespDTO.getNickname()); respVO.setBankNo(bankRespDTO.getBankNo()); } + + // 获取公司信息 + DeptRespDTO company = deptApi.getDept(respVO.getCompanyId()).getCheckedData(); + respVO.setCompanyName(company.getName()); } return success(respVO); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALoanController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALoanController.java index 2f561685..6107cf7b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALoanController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALoanController.java @@ -5,7 +5,9 @@ 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.loan.BpmOALoanCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan.BpmOALoanRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO; +import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService; import cn.iocoder.yudao.module.bpm.service.oa.BpmOALoanService; import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.FactoryInfoApi; import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO; @@ -31,8 +33,7 @@ import java.util.Map; import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** @@ -64,6 +65,9 @@ public class BpmOALoanController { @Resource private FactoryInfoApi factoryInfoApi; + @Resource + private FinancialPaymentService financialPaymentService; + @PostMapping("/create") @Operation(summary = "创建借支申请") public CommonResult createLoan(@Valid @RequestBody BpmOALoanCreateReqVO createReqVO) { @@ -146,6 +150,10 @@ public class BpmOALoanController { List respVOS = BeanUtils.toBean(loanList, BpmOALoanRespVO.class); if (CollUtil.isNotEmpty(respVOS)) { + // 获取支付信息 + List processInstanceIds = convertList(loanList, BpmOALoanDO::getProcessInstanceId); + Map financialPayments = convertMap(financialPaymentService.getFinancialPaymentList(processInstanceIds), FinancialPaymentDO::getProcessInstanceId); + // 获取申请人信息 Set userIds = convertSet(loanList, BpmOALoanDO::getUserId); Map userMap = userApi.getUserMap(userIds); @@ -165,6 +173,8 @@ public class BpmOALoanController { item.setSfUserName(loanUserMap.get(item.getSfUserId()).getNickName()); // 设置借支用户部门名称 item.setFactoryName(factoryMap.get(item.getFactoryId()).getName()); + // 设置支付状态 + item.setStatus(financialPayments.containsKey(item.getProcessInstanceId()) ? financialPayments.get(item.getProcessInstanceId()).getStatus() : 2); }); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAPaymentController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAPaymentController.java index e8258487..b2c0228f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAPaymentController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAPaymentController.java @@ -84,6 +84,8 @@ public class BpmOAPaymentController { @Parameter(name = "type", description = "付款类型", required = true, example = "1") public CommonResult> getPayment(@RequestParam("type") Integer type) { + List list = paymentService.getPaymentList(type); + return success(paymentService.getPaymentList(type)); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestCreateReqVO.java index f89b3e63..d6a24717 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestCreateReqVO.java @@ -36,6 +36,10 @@ public class BpmOAImprestCreateReqVO { @NotNull(message = "费用事由不能为空") private String reason; + @Schema(description = "付款公司编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "付款公司编号不能为空") + private Long companyId; + @Schema(description = "费用金额", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "费用金额不能为空") private BigDecimal amount; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestRespVO.java index a1e1b103..596ccd7b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/imprest/BpmOAImprestRespVO.java @@ -44,6 +44,12 @@ public class BpmOAImprestRespVO extends BpmOABaseRespVO { @NotNull(message = "费用事由不能为空") private String reason; + @Schema(description = "付款公司编号") + private Long companyId; + + @Schema(description = "付款公司名称") + private String companyName; + @Schema(description = "费用金额", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "费用金额不能为空") private BigDecimal amount; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/loan/BpmOALoanRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/loan/BpmOALoanRespVO.java index 961898d4..a1e5decd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/loan/BpmOALoanRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/loan/BpmOALoanRespVO.java @@ -54,4 +54,7 @@ public class BpmOALoanRespVO extends BpmOABaseRespVO { @Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED) private List fileItems; + + @Schema(description = "支付状态 | 0待支付 1分批支付中 2已支付 3拒绝") + private Integer status; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAPrintDataRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAPrintDataRespVO.java index 9e6c9b67..15a507e7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAPrintDataRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/print/BpmOAPrintDataRespVO.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.cash.BpmOACashRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.reimbursement.BpmOAReimbursementRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -30,11 +31,39 @@ public class BpmOAPrintDataRespVO extends BpmOABaseRespVO { @Schema(description = "流程审批节点信息【包含人员签名地址】") List processTasks ; + /** + * 发起流程的用户 + */ + private User startUser; + /** * 抄送用户信息 */ private List ccUsers; + @Schema(description = "用户信息") + @Data + public static class User { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String nickname; + + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long deptId; + + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") + private String deptName; + + @Schema(description = "公司编号") + private Long companyId; + + @Schema(description = "公司名称") + private String companyName; + } + @Schema(description = "抄送用户信息") @Data public static class CCUser { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java index a9cc810f..112a7b6a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java @@ -54,14 +54,21 @@ public class BpmProcessInstanceRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") private String nickname; @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long deptId; + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") private String deptName; + @Schema(description = "公司编号") + private Long companyId; + + @Schema(description = "公司名称") + private String companyName; } @Schema(description = "流程定义信息") 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 884171ea..c53b7cd8 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 @@ -97,7 +97,7 @@ public interface BpmProcessInstanceConvert { default BpmProcessInstanceRespVO convert2(HistoricProcessInstance processInstance, BpmProcessInstanceExtDO processInstanceExt, ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt, - String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) { + String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept, DeptRespDTO companyDept) { BpmProcessInstanceRespVO respVO = convert2(processInstance); copyTo(processInstanceExt, respVO); respVO.setBusinessKey(processInstance.getBusinessKey()) ; @@ -111,6 +111,12 @@ public interface BpmProcessInstanceConvert { if (dept != null) { respVO.getStartUser().setDeptName(dept.getName()); } + if (companyDept != null) { + // 设置用户所属公司编号 + respVO.getStartUser().setCompanyId(companyDept.getId()); + // 设置用户所属公司名称 + respVO.getStartUser().setCompanyName(companyDept.getName()); + } } return respVO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java index 1a4abc9c..9788a8b3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java @@ -90,4 +90,21 @@ public class BpmProcessDefinitionExtDO extends BaseDO { * 流程图标路径地址 */ private String processImg ; + + /** + * 使用权限范围 | 1全员 2指定部门 3指定用户 + */ + private Integer dataScope; + + /** + * 使用权限 指定部门数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List dataScopeDeptIds; + + /** + * 使用权限 指定用户数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List dataScopeUserIds; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/financialpayment/FinancialPaymentDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/financialpayment/FinancialPaymentDO.java index 7529055f..12336b16 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/financialpayment/FinancialPaymentDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/financialpayment/FinancialPaymentDO.java @@ -55,7 +55,7 @@ public class FinancialPaymentDO extends BaseDO { */ private String reason; /** - * 流程类型 1现金支出 2备用金 3采购付款 4报销 5供应商采购付款 6开支日报 + * 流程类型 1现金支出 2备用金 3采购付款 4报销 5付款申请 6薪资付款 7借支申请 8供应商采购付款 */ private Integer type; /** diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAImprestDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAImprestDO.java index 1d059a2f..a7be0dd7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAImprestDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOAImprestDO.java @@ -65,6 +65,11 @@ public class BpmOAImprestDO extends BaseDO { */ private String reason; + /** + * 付款公司编号 + */ + private Long companyId; + /** * 申请金额 */ diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAPaymentMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAPaymentMapper.java index 6bd17c2d..04242082 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAPaymentMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAPaymentMapper.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentPa import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAPaymentDO; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import io.swagger.v3.oas.annotations.Parameter; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -15,7 +16,9 @@ import java.util.List; @Mapper public interface BpmOAPaymentMapper extends BaseMapperX { - List selectPaymentList(@Param("type") Integer type); + List selectPaymentList(@Param("type") Integer type, + @Param("deptId") Long deptId, + @Param("method") Integer method); default PageResult selectTicketsPage(BpmOAPaymentPageReqVO pageReqVO, Long userId) { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderScript.java new file mode 100644 index 00000000..4d259228 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderScript.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; +import static java.util.Collections.emptySet; + +/** + * 分配给审批人的上级领导 审批的 Script 实现类 + */ +@Component +public class BpmTaskAssignLeaderScript implements BpmTaskAssignScript { + + @Resource + @Lazy // 解决循环依赖 + private DeptApi deptApi; + @Resource + @Lazy // 解决循环依赖 + private AdminUserApi userApi; + + @Resource + @Lazy // 解决循环依赖 + private BpmProcessInstanceService bpmProcessInstanceService; + + @Resource + @Lazy // 解决循环依赖 + private BpmTaskService bpmTaskService ; + + @Override + public Set calculateTaskCandidateUsers(DelegateExecution execution) { + + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); + List bpmTaskRespVOs = bpmTaskService.getTaskListByProcessInstanceId(processInstance.getProcessInstanceId()); + if (CollUtil.isEmpty(bpmTaskRespVOs)) { + return emptySet(); + } + + // 获取最后一个Task任务相关数据 + BpmTaskRespVO bpmTaskRespVO = bpmTaskRespVOs.get(0) ; + Long assigneeUserId = bpmTaskRespVO.getAssigneeUser().getId(); + + // 获取审批人部门信息 + DeptRespDTO dept = getUserDept(assigneeUserId); + if (dept == null || dept.getParentId() == null) { + return emptySet(); + } + // 获取审批人的上级部门信息 + DeptRespDTO assignDept = deptApi.getDept(dept.getParentId()).getCheckedData(); + + return assignDept != null && assignDept.getLeaderUserId() != null ? asSet(assignDept.getLeaderUserId()) : emptySet(); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.LEADER_X11; + } + + private DeptRespDTO getUserDept(Long userId) { + AdminUserRespDTO user = userApi.getUser(userId).getCheckedData(); + if (user.getDeptId() == null) { // 找不到部门,所以无法使用该规则 + return null; + } + return deptApi.getDept(user.getDeptId()).getCheckedData(); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskCurrentAssignLeaderScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskCurrentAssignLeaderScript.java index 5ee180d6..53352670 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskCurrentAssignLeaderScript.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskCurrentAssignLeaderScript.java @@ -13,9 +13,11 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.context.annotation.Lazy; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.awt.event.PaintEvent; import java.util.List; import java.util.Set; @@ -23,18 +25,18 @@ import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; import static java.util.Collections.emptySet; /** - * 分配给审批人的上级领导 审批的 Script 实现类 + * 分配给发起人的上级领导 审批的 Script 实现类 * - */ @Component public class BpmTaskCurrentAssignLeaderScript extends BpmTaskAssignLeaderAbstractScript { + @Resource + private AdminUserApi userApi; - @Resource - private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; + @Resource @Lazy // 解决循环依赖 private BpmProcessInstanceService bpmProcessInstanceService; @@ -43,6 +45,10 @@ public class BpmTaskCurrentAssignLeaderScript extends BpmTaskAssignLeaderAbstrac @Lazy // 解决循环依赖 private BpmTaskService bpmTaskService ; + @Resource + @Lazy // 解决循环依赖 + private StringRedisTemplate stringRedisTemplate; + @Override public Set calculateTaskCandidateUsers(DelegateExecution execution) { // 获得发起人 @@ -51,65 +57,77 @@ public class BpmTaskCurrentAssignLeaderScript extends BpmTaskAssignLeaderAbstrac if (CollUtil.isEmpty(bpmTaskRespVOs)) { return emptySet(); } - Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); - //获取最后一个Task任务相关数据 + // 获取最后一个Task任务相关数据 BpmTaskRespVO bpmTaskRespVO = bpmTaskRespVOs.get(0) ; - Long assigneeUserId = bpmTaskRespVO.getAssigneeUser().getId() ; + Long assigneeUserId = bpmTaskRespVO.getAssigneeUser().getId(); - // 获得对应 发起人 的部门 - DeptRespDTO dept = getUserDept(startUserId); - if (dept == null) { // 找不到发起人的部门,所以无法使用该规则 - return emptySet(); - } + // 获取审批节点当前的 审批部门信息 + String key = "assignee_dept_" + processInstance.getId(); + String deptId = stringRedisTemplate.opsForValue().get(key); + if (deptId == null) { - int count = 0; - Long parentId = dept.getParentId(); - for (int i = 0; i < dept.getLevel(); i++) { + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); + // 获得对应 发起人 的部门 + DeptRespDTO dept = getUserDept(startUserId); + if (dept == null) { // 找不到发起人的部门,所以无法使用该规则 + return emptySet(); + } - if (i == 0) { //第一次查找 判断审批人是否为发起人部门负责人 - if (assigneeUserId.toString().equals(processInstance.getStartUserId()) - && !dept.getLeaderUserId().toString().equals(processInstance.getStartUserId())){ //如果发起人不是所在部门负责人时 + int count = 0; + Long parentId = dept.getParentId(); + for (int i = 0; i < dept.getLevel(); i++) { + if (i == 0) { //第一次查找 判断审批人是否为发起人部门负责人 + if (assigneeUserId.toString().equals(processInstance.getStartUserId()) + && !dept.getLeaderUserId().toString().equals(processInstance.getStartUserId())){ //如果发起人不是所在部门负责人时 + + count = 1; + break; + } + } + + //获得发起人的上级部门 + DeptRespDTO parentDept = deptApi.getDept(parentId).getCheckedData(); + if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少 + return emptySet(); + } + + if (!parentDept.getLeaderUserId().toString().equals(assigneeUserId.toString())){ //如果发起人上级部门负责人不为当前审批人时 + + dept = parentDept; count = 1; break; } + + parentId = parentDept.getParentId(); } - //获得发起人的上级部门 - DeptRespDTO parentDept = deptApi.getDept(parentId).getCheckedData(); - if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少 + if (count == 0){// 找不到父级部门。原因是:人的所属部门配在了最高节点了 return emptySet(); } - if (!parentDept.getLeaderUserId().toString().equals(assigneeUserId.toString())){ //如果发起人上级部门负责人不为当前审批人时 - dept = parentDept; - count = 1; - break; - } - - parentId = parentDept.getParentId(); + return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); } - if (count == 0){// 找不到父级部门。原因是:人的所属部门配在了最高节点了 + DeptRespDTO assigneeDept = deptApi.getDept(Long.valueOf(deptId)).getCheckedData(); + if (assigneeDept == null) { return emptySet(); } - return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); + // 判断当前审批人是不是 当前审批部门的负责人 + if (!assigneeUserId.equals(assigneeDept.getLeaderUserId())) { + return asSet(assigneeDept.getLeaderUserId()); + }else { -// //获取最后一个Task任务相关数据 -// BpmTaskRespVO bpmTaskRespVO = bpmTaskRespVOs.get(0) ; -// Long assigneeUserId = bpmTaskRespVO.getAssigneeUser().getId() ; -// // 获取当前审批用户的部门信息 -// DeptRespDTO dept = getUserDept(assigneeUserId); -// if (dept == null) { // 找不到发起人的部门,所以无法使用该规则 -// return emptySet(); -// } -// DeptRespDTO parentDept = deptApi.getDept(dept.getParentId()).getCheckedData(); -// if (parentDept == null) { // 找不到父级部门。原因是:人的所属部门配在了最高节点了 -// return emptySet(); -// } -// return parentDept.getLeaderUserId() != null ? asSet(parentDept.getLeaderUserId()) : emptySet(); + // 获得上级部门信息 + DeptRespDTO parentDept = deptApi.getDept(assigneeDept.getParentId()).getCheckedData(); + if (parentDept != null) { + // 更新审批部门缓存 + stringRedisTemplate.opsForValue().set(key, parentDept.getId().toString()); + } + return parentDept != null && parentDept.getLeaderUserId() != null ? asSet(parentDept.getLeaderUserId()) : emptySet(); + } } @Override @@ -118,7 +136,7 @@ public class BpmTaskCurrentAssignLeaderScript extends BpmTaskAssignLeaderAbstrac } private DeptRespDTO getUserDept(Long userId) { - AdminUserRespDTO user = adminUserApi.getUser(userId).getCheckedData(); + AdminUserRespDTO user = userApi.getUser(userId).getCheckedData(); if (user.getDeptId() == null) { // 找不到部门,所以无法使用该规则 return null; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java index 1e0ef6ec..a236c88e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskEntryLeaderScript.java @@ -50,20 +50,15 @@ public class BpmTaskEntryLeaderScript implements BpmTaskAssignScript { return emptySet(); } - //根据流程实例ID 取到调岗流程表单 + //根据流程实例ID 取到入职流程表单 BpmOAEntryDO entryDO = entryService.getEntry(Long.valueOf(processInstance.getBusinessKey())); - //获取调岗部门ID + //获取入职部门ID Long deptId = entryDO.getEntryDeptId(); //根据部门ID 获取部门信息 DeptRespDTO dept = deptApi.getDept(deptId).getCheckedData(); - if (dept.getLevel() > 3) { //判断部门层级 - String[] flag = dept.getFlag().split("-"); - dept = deptApi.getDept(Long.valueOf(flag[3])).getCheckedData(); - } - - return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); + return dept != null && dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); } @Override diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskFactoryLeaderScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskFactoryLeaderScript.java new file mode 100644 index 00000000..874719e2 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskFactoryLeaderScript.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesItemDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalaryDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOAExpensesService; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALoanService; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOASalaryService; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; +import static java.util.Collections.emptySet; + +/** + * 分配给所选工厂的领导 审批的 Script 实现类 + */ +@Component +public class BpmTaskFactoryLeaderScript extends BpmTaskAssignLeaderAbstractScript { + + @Resource + private AdminUserApi userApi; + + @Resource + private DeptApi deptApi; + + @Resource + @Lazy // 解决循环依赖 + private BpmProcessInstanceService bpmProcessInstanceService; + + @Resource + @Lazy // 解决循环依赖 + private BpmTaskService bpmTaskService; + + @Resource + @Lazy // 解决循环依赖 + private BpmOAExpensesService expensesService; + + @Resource + @Lazy // 解决循环依赖 + private BpmOALoanService loanService; + + @Override + public Set calculateTaskCandidateUsers(DelegateExecution execution) { + // 获得发起人 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); + List bpmTaskRespVOs = bpmTaskService.getTaskListByProcessInstanceId(processInstance.getProcessInstanceId()); + if (CollUtil.isEmpty(bpmTaskRespVOs)) { + return emptySet(); + } + + DeptRespDTO dept = null; + switch (processInstance.getProcessDefinitionKey()) { + case "oa_expenses_2": + // 根据流程实例ID 取到开支日报流程表单 + List expensesItems = expensesService.getExpensesItem(Long.valueOf(processInstance.getBusinessKey())); + // 获取开支所属工厂信息 + if (CollUtil.isNotEmpty(expensesItems)) { + + DeptRespDTO factory = deptApi.getDeptByFactoryId(expensesItems.get(0).getDeptId()).getCheckedData(); + // 获取工厂上级部门信息 + dept = deptApi.getDept(factory.getParentId()).getCheckedData(); + } + break; + case "oa_loan_2": + // 根据流程实例ID 取到借支流程表单 + BpmOALoanDO loanDO = loanService.getLoan(Long.valueOf(processInstance.getBusinessKey())); + + if (loanDO != null) { + // 获取借支工厂信息 + DeptRespDTO factory = deptApi.getDeptByFactoryId(loanDO.getFactoryId()).getCheckedData(); + // 获取工厂上级部门信息 + dept = deptApi.getDept(factory.getParentId()).getCheckedData(); + } + break; + case "oa_salary_2": + // 获取发起人的部门信息 + AdminUserRespDTO userRespDTO = userApi.getUser(Long.valueOf(processInstance.getStartUserId())).getCheckedData(); + DeptRespDTO deptRespDTO = deptApi.getDept(userRespDTO.getDeptId()).getCheckedData(); + + // 判断是否是属于工厂部门 + if (deptRespDTO.getFactoryId() != null) { + dept = deptApi.getDept(deptRespDTO.getParentId()).getCheckedData(); + } + break; + } + + return dept != null && dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.LEADER_X10; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java index c8bf91ea..7e0464a6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java @@ -160,4 +160,10 @@ public interface BpmProcessDefinitionService { * @return 流程定义列表 */ List getProcessDefinitionSimpleList(BpmProcessDefinitionListReqVO reqVO); + + /** + * 更新流程定义的权限范围 + * @param scopeVO 更新信息 + */ + void updateProcessDefinitionScope(DefinitionScopeVO scopeVO); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 78276b56..44ce2824 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.*; import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert; @@ -14,6 +15,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitio import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; +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.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.BpmnModel; @@ -33,10 +36,8 @@ 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.*; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH; -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static java.util.Collections.emptyList; /** @@ -66,6 +67,9 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @Resource private DeptApi deptApi; + @Resource + private AdminUserApi userApi; + @Override public ProcessDefinition getProcessDefinition(String id) { return repositoryService.getProcessDefinition(id); @@ -160,6 +164,24 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ .collect(Collectors.toList()); } + @Override + public void updateProcessDefinitionScope(DefinitionScopeVO scopeVO) { + // 校验流程定义是否存在 + BpmProcessDefinitionExtDO definitionExtDO = processDefinitionMapper.selectByProcessDefinitionId(scopeVO.getProcessDefinitionId()); + if (definitionExtDO == null) { + throw exception(PROCESS_DEFINITION_NOT_EXISTS); + } + + BpmProcessDefinitionExtDO updateDO = new BpmProcessDefinitionExtDO(); + updateDO.setId(definitionExtDO.getId()); + updateDO.setDataScope(scopeVO.getDataScope()); + updateDO.setDataScopeDeptIds(scopeVO.getDataScopeDeptIds()); + updateDO.setDataScopeUserIds(scopeVO.getDataScopeUserIds()); + + // 更新 + processDefinitionMapper.updateById(updateDO); + } + @Override public String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) { // 创建 Deployment 部署 @@ -288,11 +310,24 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ return Collections.emptyList(); } + // 获取当前登录用户信息 + AdminUserRespDTO userRespDTO = userApi.getUser(getLoginUserId()).getCheckedData(); + // 获得 BpmProcessDefinitionDO Map - List processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds( - convertList(processDefinitions, ProcessDefinition::getId)); + List processDefinitionDOs = processDefinitionMapper.selectList(new LambdaQueryWrapperX() + .inIfPresent(BpmProcessDefinitionExtDO::getProcessDefinitionId, convertList(processDefinitions, ProcessDefinition::getId)) + .eq(BpmProcessDefinitionExtDO::getDataScope, 1) + .or() + .like(BpmProcessDefinitionExtDO::getDataScopeDeptIds, userRespDTO.getDeptId()) + .or() + .like(BpmProcessDefinitionExtDO::getDataScopeUserIds, userRespDTO.getId()) + ); Map processDefinitionDOMap = convertMap(processDefinitionDOs, BpmProcessDefinitionExtDO::getProcessDefinitionId); + + // 移除 无权限的流程定义 + processDefinitions.removeIf(item -> !processDefinitionDOMap.containsKey(item.getId())); + // 执行查询,并返回 return BpmProcessDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap); } @@ -331,5 +366,4 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ return new PageResult<>(BpmProcessDefinitionConvert.INSTANCE.convertList(processDefinitions, deploymentMap, processDefinitionDOMap, formMap), definitionCount); } - } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/financialpayment/FinancialPaymentServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/financialpayment/FinancialPaymentServiceImpl.java index bc748f67..5904a9c8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/financialpayment/FinancialPaymentServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/financialpayment/FinancialPaymentServiceImpl.java @@ -28,8 +28,9 @@ import cn.iocoder.yudao.module.system.api.auth.AdminOauthUserOtherInfoApi; import cn.iocoder.yudao.module.system.api.auth.dto.AdminOauthUserOtherInfoApiDTO; import cn.iocoder.yudao.module.system.api.auth.vo.AdminOauthUserOtherInfoApiVO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.loan.LoanApi; +import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO; import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.extern.slf4j.Slf4j; @@ -37,6 +38,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -70,7 +72,7 @@ public class FinancialPaymentServiceImpl implements FinancialPaymentService { @Resource private SubscribeMessageSendApi subscribeMessageSendApi; @Resource - private AdminUserApi userApi; + private LoanApi loanApi; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @@ -78,6 +80,15 @@ public class FinancialPaymentServiceImpl implements FinancialPaymentService { @Resource private AdminOauthUserOtherInfoApi adminOauthUserOtherInfoApi; + @Resource + private BpmOALoanMapper loanMapper; + + @Resource + private BpmOAPaymentMapper paymentMapper; + + @Resource + private BpmOASalaryMapper salaryMapper; + @Override public Long createFinancialPayment(FinancialPaymentSaveVO vo) { FinancialPaymentItemSaveReqVO createReqVO = vo.getFinancialPaymentItemSaveReqVO(); @@ -103,16 +114,31 @@ public class FinancialPaymentServiceImpl implements FinancialPaymentService { // TODO: 2024/8/18 - 驳回该流程通过流程实例id 发消息通知发起人 - 更改状态 financialPayment.setStatus(3); // -- 修改流程状态 - if (financialPayment.getType() == 1) { - cashMapper.updateById(new BpmOACashDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); - } else if (financialPayment.getType() == 2) { - imprestMapper.updateById(new BpmOAImprestDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); - } else if (financialPayment.getType() == 3) { - oAProcurePayMapper.updateById(new BpmOAProcurePayDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); - } else if (financialPayment.getType() == 4) { - reimbursementMapper.updateById(new BpmOAReimbursementDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); - } else if (financialPayment.getType() == 5) { - supplierPurchasePaymentMapper.updateById(new BpmOASupplierPurchasePaymentDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + switch (financialPayment.getType()) { + case 1: + cashMapper.updateById(new BpmOACashDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 2: + imprestMapper.updateById(new BpmOAImprestDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 3: + oAProcurePayMapper.updateById(new BpmOAProcurePayDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 4: + reimbursementMapper.updateById(new BpmOAReimbursementDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 5: + paymentMapper.updateById(new BpmOAPaymentDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 6: + salaryMapper.updateById(new BpmOASalaryDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 7: + loanMapper.updateById(new BpmOALoanDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; + case 8: + supplierPurchasePaymentMapper.updateById(new BpmOASupplierPurchasePaymentDO().setId(financialPayment.getObjectId()).setResult(BpmProcessInstanceResultEnum.BACK.getResult())); + break; } BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(financialPayment.getProcessInstanceId()) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) @@ -120,6 +146,22 @@ public class FinancialPaymentServiceImpl implements FinancialPaymentService { processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); } this.updateById(financialPayment); + + // 判断是借支申请时 + if (financialPayment.getType() == 7 && financialPayment.getStatus() == 2) { + + // 获取借支信息 + BpmOALoanDO loanDO = loanMapper.selectById(financialPayment.getObjectId()); + + // 同步插入借支表中 + LoanDTO createDO = new LoanDTO() + .setUserId(loanDO.getSfUserId()) + .setDeptId(loanDO.getFactoryId()) + .setAmount(loanDO.getTotalMoney()) + .setReturnAmount(BigDecimal.ZERO); + loanApi.createLoan(createDO); + } + // -- 获取发起人的openId AdminOauthUserOtherInfoApiVO item = adminOauthUserOtherInfoApi.getByCondition( new AdminOauthUserOtherInfoApiDTO().setUserIds(Collections.singletonList(financialPayment.getUserId())) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAExpensesServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAExpensesServiceImpl.java index 464672a1..4b108bfd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAExpensesServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAExpensesServiceImpl.java @@ -1,7 +1,5 @@ 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.pojo.UploadUserFile; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; @@ -9,37 +7,29 @@ import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesRespVO; import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAExpensesConvert; -import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesItemDO; -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAExpensesItemMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAExpensesMapper; 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.bank.BankApi; import cn.iocoder.yudao.module.system.api.bank.dto.BankRespDTO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.flowable.engine.runtime.ProcessInstance; 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 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.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_EXPENSES_NOT_EXISTS; @@ -66,22 +56,12 @@ public class BpmOAExpensesServiceImpl extends BpmOABaseService implements BpmOAE @Resource private BpmProcessInstanceApi processInstanceApi; - @Resource - @Lazy // 解决循环依赖 - private BpmProcessInstanceService bpmProcessInstanceService; - - @Resource - private FinancialPaymentService financialPaymentService; - @Resource private DeptApi deptApi; @Resource private BankApi bankApi; - @Resource - private AdminUserApi userApi; - @Resource @Lazy // 解决循环依赖 private BpmHistoryProcessInstanceService historyProcessInstanceService; @@ -131,41 +111,6 @@ public class BpmOAExpensesServiceImpl extends BpmOABaseService implements BpmOAE BpmOAExpensesDO expenses = validateLeaveExists(id); expensesMapper.updateById(new BpmOAExpensesDO().setId(id).setResult(result)); - - // 获取现金支出明细 - List expensesItemDOs = getExpensesItem(id); - - List procureIds = new ArrayList<>(); - //审核通过 (最后节点) - if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) { - - ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId); - - if (instance.isEnded()) { - - String reason = expensesItemDOs.stream() - .map(BpmOAExpensesItemDO::getDetail) - .filter(StrUtil::isNotEmpty) - .collect(Collectors.joining(",")); - - BpmProcessInstanceExtDO processInstance = bpmProcessInstanceService.getProcessInstanceDO(processInstanceId); - CommonResult user = userApi.getUser(expenses.getUserId()); - // -- 插入到财务支付表中 - financialPaymentService.save(new FinancialPaymentDO() - .setUserId(expenses.getUserId()) - .setDeptId(user.getData() == null ? null : user.getData().getDeptId()) - .setProcessInstanceId(expenses.getProcessInstanceId()) - .setProcessInstanceName(processInstance.getName()) - .setReason(reason) - .setObjectId(id) - .setType(6) - .setStatus(0) - .setAmountPayable(expenses.getTotalMoney()) - .setBeginTime(processInstance.getCreateTime()) - .setEndTime(processInstance.getEndTime()) - ); - } - } } private BpmOAExpensesDO validateLeaveExists(Long id) { @@ -207,7 +152,8 @@ public class BpmOAExpensesServiceImpl extends BpmOABaseService implements BpmOAE List expensesItemDOs = getExpensesItem(expenses.getId()); //获取部门信息map - Map deptMap = deptApi.getDeptMap(convertSet(expensesItemDOs, BpmOAExpensesItemDO::getDeptId)); + List deptList = deptApi.getDeptByFactoryIds(convertSet(expensesItemDOs, BpmOAExpensesItemDO::getDeptId)).getCheckedData(); + Map deptMap = convertMap(deptList, DeptRespDTO::getFactoryId); // 获取银行卡信息 BankRespDTO bankRespDTO = null; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAImprestServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAImprestServiceImpl.java index cf679694..98ca3924 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAImprestServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAImprestServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.service.oa; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.imprest.BpmOAImprestCreateReqVO; @@ -65,7 +66,8 @@ public class BpmOAImprestServiceImpl extends BpmOABaseService implements BpmOAIm public Long createImprest(Long userId, BpmOAImprestCreateReqVO createReqVO) { //插入OA 备用金申请 - BpmOAImprestDO imprest = BpmOAImprestConvert.INSTANCE.convert(createReqVO).setUserId(userId) + BpmOAImprestDO imprest = BeanUtils.toBean(createReqVO, BpmOAImprestDO.class) + .setUserId(userId) .setStatus(BpmOAImprestDO.FLAG_FALSE) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); imprestMapper.insert(imprest); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALoanServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALoanServiceImpl.java index db136c9b..b8778e1a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALoanServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALoanServiceImpl.java @@ -1,25 +1,28 @@ package cn.iocoder.yudao.module.bpm.service.oa; import cn.hutool.core.collection.CollectionUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan.BpmOALoanCreateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALoanMapper; 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.loan.LoanApi; -import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO; +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.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -51,7 +54,10 @@ public class BpmOALoanServiceImpl extends BpmOABaseService implements BpmOALoanS private BpmHistoryProcessInstanceService historyProcessInstanceService; @Resource - private LoanApi loanApi; + private AdminUserApi userApi; + + @Resource + private FinancialPaymentService financialPaymentService; @Override @@ -93,14 +99,24 @@ public class BpmOALoanServiceImpl extends BpmOABaseService implements BpmOALoanS if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) { ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId); - if (instance.isEnded()) { - // 同步插入借支表中 - LoanDTO createDO = new LoanDTO() - .setAmount(loanDO.getTotalMoney()) - .setReturnAmount(BigDecimal.ZERO); - loanApi.createLoan(createDO); + BpmProcessInstanceExtDO processInstance = processInstanceService.getProcessInstanceDO(processInstanceId); + // -- 插入到财务支付表中 + CommonResult user = userApi.getUser(loanDO.getUserId()); + financialPaymentService.save(new FinancialPaymentDO() + .setUserId(loanDO.getUserId()) + .setDeptId(user.getData() == null ? null : user.getData().getDeptId()) + .setProcessInstanceId(loanDO.getProcessInstanceId()) + .setReason("") + .setObjectId(id) + .setType(7) + .setStatus(0) + .setAmountPayable(loanDO.getTotalMoney()) + .setProcessInstanceName(processInstance.getName()) + .setBeginTime(processInstance.getCreateTime()) + .setEndTime(processInstance.getEndTime()) + ); } } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAPaymentServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAPaymentServiceImpl.java index b82376f7..ab6229a0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAPaymentServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAPaymentServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.oa; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.iocoder.yudao.framework.common.enums.DeptTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; @@ -34,6 +35,7 @@ import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_PAYMENT_FILES_NOT_NULL; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_PAYMENT_NOT_EXISTS; @@ -157,7 +159,17 @@ public class BpmOAPaymentServiceImpl extends BpmOABaseService implements BpmOAPa @Override public List getPaymentList(Integer type) { - return paymentMapper.selectPaymentList(type); + int method = 0; + // 获取发起人的部门信息 + AdminUserRespDTO userDTO = userApi.getUser(getLoginUserId()).getCheckedData(); + DeptRespDTO deptDTO = deptApi.getDept(userDTO.getDeptId()).getCheckedData(); + + // 判断财务部门时,查询全部分批记录 + if (deptDTO != null && deptDTO.getType().equals(DeptTypeEnum.FINANCE_DEPT.getValue())) { + method = 1; + } + + return paymentMapper.selectPaymentList(type, userDTO.getDeptId(), method); } @Override 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 aede1898..2418db71 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 @@ -161,7 +161,7 @@ public class BpmOASupplierPurchasePaymentServiceImpl extends BpmOABaseService im .setProcessInstanceId(supplierPurchasePaymentDO.getProcessInstanceId()) .setReason(supplierPurchasePaymentDO.getRemark()) .setObjectId(id) - .setType(5) + .setType(8) .setStatus(0) .setAmountPayable(supplierPurchasePaymentDO.getTotalMoney()) .setProcessInstanceName(processInstance.getName()) 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 6551ae1e..dac1d876 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.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.payment.BpmOAPaymentRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmOAPrintDataRespVO; 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.BpmProcessCcDO; 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.BpmOAPaymentDO; 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.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.BpmProcessCcService; 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.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.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.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; 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 ; @Resource private BpmProcessCcService processCcService; @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 @Transactional(rollbackFor = Exception.class) 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); //获取流程发起人User AdminUserRespDTO startUser = adminUserApi.getUser(userId).getCheckedData(); //获取流程发起人部门信息 DeptRespDTO startDeptInfo = deptApi.getDept(startUser.getDeptId()).getCheckedData(); // 获取岗位信息 Set postIds = startUser.getPostIds(); ArrayList list = new ArrayList<>(postIds); //配置通用流程变量 variables.put("post_id", list.get(0).toString()); // 只获配置的首个岗位 variables.put("user_id", userId.toString()); // 配置发起人用户id variables.put("dept_id", startUser.getDeptId().toString()); // 配置发起人部门id variables.put("dept_flag", startDeptInfo.getFlag()); // 配置发起人部门flag // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 创建流程后,添加抄送人 processCCToUsers(instance, variables); } }); return instance.getId(); // // 补全流程实例的拓展表 // processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) // .setFormVariables(variables)); // // /** 创建流程后,添加抄送人 End add by yj 2024.1.4 */ // processCCToUsers(definition, instance); // /** 通过自己发起的流程 */ // approveSelfTask(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; } } } /** * 创建流程后,添加抄送人 * @param instance 流程实例 */ private void processCCToUsers(ProcessInstance instance, Map variables) { // 根据流程名称、流程发起人 查询流程配置的抄送人信息 List processCcList = processCcService.getCCListByName(instance.getName(), Long.valueOf(instance.getStartUserId())); // 提取抄送信息用中对应的用户组编号 Set userGroupIds = processCcList.stream() .flatMap(data -> data.getUserGroupId().stream()) .collect(Collectors.toSet()); //根据processDefinitionId 将ccIds保存到bpm_process_instance_ext中的ccIds字段 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessDefinitionId(instance.getProcessDefinitionId()) .setFormVariables(variables) .setProcessInstanceId(instance.getProcessInstanceId()); if (CollectionUtil.isNotEmpty(userGroupIds)) { // 获取用户组信息 List userGroups = userGroupService.getUserGroupList(userGroupIds); // 提取用户组中对应的用户ID Set userIds = userGroups.stream() .flatMap(data -> data.getMemberUserIds().stream()) .collect(Collectors.toSet()); // 将用户ID列表转换为字符串 String ccIds = userIds.stream() .map(id -> "[" + id + "]") // 每个值用方括号包裹 .collect(Collectors.joining()); //根据processDefinitionId 将ccIds保存到bpm_process_instance_ext中的ccIds字段 instanceExtDO.setCcids(ccIds); } processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); } @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 @Lazy // 解决循环依赖 private BpmOAReimbursementService reimbursementService; @Resource @Lazy // 解决循环依赖 private BpmOACashService cashService; @Resource @Lazy // 解决循环依赖 private BpmOAImprestService imprestService; @Resource @Lazy // 解决循环依赖 private BpmOAPaymentService paymentService; @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)); // 设置抄送人信息 List ccUsers = userRespDTOS.stream().map(user -> { BpmOAPrintDataRespVO.CCUser cc = new BpmOAPrintDataRespVO.CCUser(); cc.setCcUserId(user.getId()); cc.setCcUserName(user.getNickname()); cc.setCcDeptName(deptMapDTO.get(user.getDeptId()).getName()); return cc; }).collect(Collectors.toList()); BpmOAPrintDataRespVO printData = new BpmOAPrintDataRespVO(); // 设置抄送人 printData.setCcUsers(ccUsers); switch (key) { case "oa_reimbursement": BpmOAReimbursementDO reimbursement = reimbursementService.getReimbursement(businessKey); BpmOAReimbursementRespVO bpmOAReimbursementRespVO = reimbursementService.convert(reimbursement); //报销业务数据 // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(reimbursement.getUserId())); //备用金信息查询 BpmOAImprestDO bpmOAImprestDO = imprestService.getImprest(reimbursement.getImprestId()); if (bpmOAImprestDO != null) { //设置备用金 金额 bpmOAReimbursementRespVO.setAmount(bpmOAImprestDO.getAmount()); // 设置备用金 剩余金额 bpmOAReimbursementRespVO.setRemainingAmount(bpmOAImprestDO.getAmount().subtract(bpmOAImprestDO.getReimbursedAmount())); } printData.setBpmOAReimbursementRespVO(bpmOAReimbursementRespVO); printData.setProcessTasks(taskRespVOList); break; case "oa_cash": BpmOACashDO cashDO = cashService.getCash(businessKey); BpmOACashRespVO cashRespVO = cashService.convertCash(cashDO); // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(cashDO.getUserId())); //备用金信息查询 BpmOAImprestDO cashImprestDO = imprestService.getImprest(cashDO.getImprestId()); if (cashImprestDO != null) { //设置备用金 金额 cashRespVO.setAmount(cashImprestDO.getAmount()); // 设置备用金 剩余金额 cashRespVO.setRemainingAmount(cashImprestDO.getAmount().subtract(cashImprestDO.getReimbursedAmount())); } printData.setBpmOACashRespVO(cashRespVO); printData.setProcessTasks(taskRespVOList); break; case "oa_payment_2": BpmOAPaymentDO paymentDO = paymentService.getPayment(businessKey); BpmOAPaymentRespVO paymentRespVO = paymentService.convertPayment(paymentDO); // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(paymentDO.getUserId())); printData.setBpmOAPaymentRespVO(paymentRespVO); printData.setProcessTasks(taskRespVOList); break; } bpmProcessInstancePrintDataRespVO.setPrintDataRespVO(printData); 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.common.util.object.BeanUtils; 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.payment.BpmOAPaymentRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmOAPrintDataRespVO; 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.BpmProcessCcDO; 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.BpmOAPaymentDO; 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.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.BpmProcessCcService; 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.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.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.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; 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 ; @Resource private BpmProcessCcService processCcService; @Resource @Lazy // 解决循环依赖 private StringRedisTemplate stringRedisTemplate; @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 @Transactional(rollbackFor = Exception.class) 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; DeptRespDTO companyDept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()).getCheckedData(); companyDept = deptApi.getUserCompanyDept(startUser.getId()).getCheckedData(); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept, companyDept); } @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); // 删除 流程审批部门缓存 updateAssigneeDeptRedis(event.getProcessInstanceId()); // 发送流程实例的状态事件 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); // 删除 流程审批部门缓存 updateAssigneeDeptRedis(instance.getProcessInstanceId()); 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); // 删除 流程审批部门缓存 updateAssigneeDeptRedis(id); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } /** * 删除 流程审批部门缓存 * @param processInstanceId 流程实例id */ public void updateAssigneeDeptRedis(String processInstanceId) { stringRedisTemplate.delete("assignee_dept_" + processInstanceId); } 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); //获取流程发起人User AdminUserRespDTO startUser = adminUserApi.getUser(userId).getCheckedData(); //获取流程发起人部门信息 DeptRespDTO startDeptInfo = deptApi.getDept(startUser.getDeptId()).getCheckedData(); // 获取岗位信息 Set postIds = startUser.getPostIds(); ArrayList list = new ArrayList<>(postIds); //配置通用流程变量 variables.put("post_id", list.get(0).toString()); // 只获配置的首个岗位 variables.put("user_id", userId.toString()); // 配置发起人用户id variables.put("dept_id", startUser.getDeptId().toString()); // 配置发起人部门id variables.put("dept_flag", startDeptInfo.getFlag()); // 配置发起人部门flag // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 设置流程审批部门缓存 stringRedisTemplate.opsForValue().set("assignee_dept_" + instance.getId(), startUser.getDeptId().toString()); // 在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 创建流程后,添加抄送人 processCCToUsers(instance, variables); } }); return instance.getId(); // // 补全流程实例的拓展表 // processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) // .setFormVariables(variables)); // // /** 创建流程后,添加抄送人 End add by yj 2024.1.4 */ // processCCToUsers(definition, instance); // /** 通过自己发起的流程 */ // approveSelfTask(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); } @Override public List getProcessInstancesGroupByModelName(BpmProcessInstanceStatisticsReqVO pageReqVO) { pageReqVO = getUserids(pageReqVO); return processInstanceExtMapper.getProcessInstancesGroupByModelName(pageReqVO); } @Override public List getProcessInstancesGroupByResultStatus(BpmProcessInstanceStatisticsReqVO pageReqVO) { pageReqVO = getUserids(pageReqVO); return processInstanceExtMapper.getProcessInstancesGroupByResultStatus(pageReqVO); } @Override 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; } } } /** * 创建流程后,添加抄送人 * @param instance 流程实例 */ private void processCCToUsers(ProcessInstance instance, Map variables) { // 根据流程名称、流程发起人 查询流程配置的抄送人信息 List processCcList = processCcService.getCCListByName(instance.getName(), Long.valueOf(instance.getStartUserId())); // 提取抄送信息用中对应的用户组编号 Set userGroupIds = processCcList.stream() .flatMap(data -> data.getUserGroupId().stream()) .collect(Collectors.toSet()); //根据processDefinitionId 将ccIds保存到bpm_process_instance_ext中的ccIds字段 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessDefinitionId(instance.getProcessDefinitionId()) .setFormVariables(variables) .setProcessInstanceId(instance.getProcessInstanceId()); if (CollectionUtil.isNotEmpty(userGroupIds)) { // 获取用户组信息 List userGroups = userGroupService.getUserGroupList(userGroupIds); // 提取用户组中对应的用户ID Set userIds = userGroups.stream() .flatMap(data -> data.getMemberUserIds().stream()) .collect(Collectors.toSet()); // 将用户ID列表转换为字符串 String ccIds = userIds.stream() .map(id -> "[" + id + "]") // 每个值用方括号包裹 .collect(Collectors.joining()); //根据processDefinitionId 将ccIds保存到bpm_process_instance_ext中的ccIds字段 instanceExtDO.setCcids(ccIds); } processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); } @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 @Lazy // 解决循环依赖 private BpmOAReimbursementService reimbursementService; @Resource @Lazy // 解决循环依赖 private BpmOACashService cashService; @Resource @Lazy // 解决循环依赖 private BpmOAImprestService imprestService; @Resource @Lazy // 解决循环依赖 private BpmOAPaymentService paymentService; @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)); // 设置抄送人信息 List ccUsers = userRespDTOS.stream().map(user -> { BpmOAPrintDataRespVO.CCUser cc = new BpmOAPrintDataRespVO.CCUser(); cc.setCcUserId(user.getId()); cc.setCcUserName(user.getNickname()); cc.setCcDeptName(deptMapDTO.get(user.getDeptId()).getName()); return cc; }).collect(Collectors.toList()); BpmOAPrintDataRespVO printData = new BpmOAPrintDataRespVO(); // 设置抄送人 printData.setCcUsers(ccUsers); // 设置发起人信息 printData.setStartUser(BeanUtils.toBean(bpmProcessInstance.getStartUser(), BpmOAPrintDataRespVO.User.class)); switch (key) { case "oa_reimbursement": BpmOAReimbursementDO reimbursement = reimbursementService.getReimbursement(businessKey); BpmOAReimbursementRespVO bpmOAReimbursementRespVO = reimbursementService.convert(reimbursement); //报销业务数据 // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(reimbursement.getUserId())); //备用金信息查询 BpmOAImprestDO bpmOAImprestDO = imprestService.getImprest(reimbursement.getImprestId()); if (bpmOAImprestDO != null) { //设置备用金 金额 bpmOAReimbursementRespVO.setAmount(bpmOAImprestDO.getAmount()); // 设置备用金 剩余金额 bpmOAReimbursementRespVO.setRemainingAmount(bpmOAImprestDO.getAmount().subtract(bpmOAImprestDO.getReimbursedAmount())); } printData.setBpmOAReimbursementRespVO(bpmOAReimbursementRespVO); printData.setProcessTasks(taskRespVOList); break; case "oa_cash": BpmOACashDO cashDO = cashService.getCash(businessKey); BpmOACashRespVO cashRespVO = cashService.convertCash(cashDO); // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(cashDO.getUserId())); //备用金信息查询 BpmOAImprestDO cashImprestDO = imprestService.getImprest(cashDO.getImprestId()); if (cashImprestDO != null) { //设置备用金 金额 cashRespVO.setAmount(cashImprestDO.getAmount()); // 设置备用金 剩余金额 cashRespVO.setRemainingAmount(cashImprestDO.getAmount().subtract(cashImprestDO.getReimbursedAmount())); } printData.setBpmOACashRespVO(cashRespVO); printData.setProcessTasks(taskRespVOList); break; case "oa_payment_2": BpmOAPaymentDO paymentDO = paymentService.getPayment(businessKey); BpmOAPaymentRespVO paymentRespVO = paymentService.convertPayment(paymentDO); // 移除自己得审批节点 taskRespVOList.removeIf(data -> data.getAssigneeUser().getId().equals(paymentDO.getUserId())); printData.setBpmOAPaymentRespVO(paymentRespVO); printData.setProcessTasks(taskRespVOList); break; } bpmProcessInstancePrintDataRespVO.setPrintDataRespVO(printData); 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/resources/mapper/oa/BpmOAPaymentMapper.xml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAPaymentMapper.xml index e5570c95..4c894ffe 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAPaymentMapper.xml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/BpmOAPaymentMapper.xml @@ -13,10 +13,21 @@