diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java index e9af5994..47303cd5 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java @@ -17,6 +17,7 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; /** * 合同订单 @@ -42,6 +43,15 @@ public class ErpContractOrderController extends BaseController { return erpContractOrderService.queryPageList(bo, pageQuery); } + /** + * 查询合同订单待办列表(项目经理或合同激活创建人) + */ + @SaCheckPermission("oa/erp:projectInfo:list") + @GetMapping("/todoList") + public R> todoList(ErpProjectInfoBo bo) { + return R.ok(erpContractOrderService.queryTodoList(bo)); + } + /** * 暂存合同订单(项目信息) */ diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java index 6cb85bd2..15ddf6c6 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java @@ -32,6 +32,14 @@ public interface IErpContractOrderService { */ TableDataInfo queryPageList(ErpProjectInfoBo bo, PageQuery pageQuery); + /** + * 查询合同订单待办列表(权限:项目经理或合同激活创建人) + * + * @param bo 查询条件 + * @return 合同订单待办列表 + */ + List queryTodoList(ErpProjectInfoBo bo); + /** * 查询符合条件的合同订单列表 * diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java index 23c9a32e..206f5728 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java @@ -10,6 +10,7 @@ import org.dromara.common.core.enums.OAStatusEnum; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.oa.erp.domain.ErpContractInfo; import org.dromara.oa.erp.domain.ErpProjectInfo; @@ -53,6 +54,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; + import cn.hutool.core.map.MapUtil; import cn.hutool.core.convert.Convert; @@ -78,7 +80,9 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { private final IErpProjectTypeService projectTypeService; private final ICrmCustomerInfoService crmCustomerInfoService; - /** 项目申请流程编码(新增项目提交时使用) */ + /** + * 项目申请流程编码(新增项目提交时使用) + */ private static final String FLOW_CODE_PROJECT = "xmsq"; @DubboReference(timeout = 300000) @@ -117,6 +121,47 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { return TableDataInfo.build(result); } + /** + * 查询合同订单待办列表(权限:项目经理或合同激活创建人) + */ + @Override + public List queryTodoList(ErpProjectInfoBo bo) { + // 先取基础列表,再按“真实项目经理 / 合同创建人”在内存中过滤 + Long filterManagerId = bo.getManagerId(); + bo.setManagerId(null); + MPJLambdaWrapper lqw = buildQueryWrapper(bo); + List baseList = projectInfoMapper.selectCustomErpProjectInfoVoList(lqw); + if (CollUtil.isEmpty(baseList)) { + return baseList; + } + Long currentUserId = LoginHelper.getUserId(); + if (StringUtils.isNull(filterManagerId)) { + return baseList; + } + // 1) 批量取合同ID + Set contractIds = baseList.stream() + .map(ErpProjectInfoVo::getContractId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + // 2) 合同ID -> 项目经理ID(通过 erp_project_contracts -> erp_project_info) + Map contractId2ManagerId = buildContractIdToProjectManagerIdMap(contractIds); + // 3) 合同ID -> 合同创建人 + Map contractId2CreateBy = buildContractIdToContractCreateByMap(contractIds); + return baseList.stream() + .filter(row -> { + Long contractId = row.getContractId(); + Long realManagerId = contractId != null ? contractId2ManagerId.get(contractId) : null; + Long contractCreateBy = contractId != null ? contractId2CreateBy.get(contractId) : null; + // 过滤条件:页面选择的项目经理(按真实项目经理) + if (filterManagerId != null) { + return Objects.equals(filterManagerId, realManagerId); + } + // 待办权限:真实项目经理 或 合同激活创建人 + return Objects.equals(currentUserId, realManagerId) || Objects.equals(currentUserId, contractCreateBy); + }) + .collect(Collectors.toList()); + } + /** * 查询符合条件的合同订单列表 * @@ -137,36 +182,92 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { */ private MPJLambdaWrapper buildQueryWrapper(ErpProjectInfoBo bo) { MPJLambdaWrapper lqw = JoinWrappers.lambda(ErpProjectInfo.class) - .selectAll(ErpProjectInfo.class) - .eq(ErpProjectInfo::getProjectCategory, ProjectCategoryConstant.CONTRACT_ORDER) - .eq(StringUtils.isNotBlank(bo.getContractFlag()), ErpProjectInfo::getContractFlag, bo.getContractFlag()) - .like(StringUtils.isNotBlank(bo.getProjectCode()), ErpProjectInfo::getProjectCode, bo.getProjectCode()) - .like(StringUtils.isNotBlank(bo.getProjectName()), ErpProjectInfo::getProjectName, bo.getProjectName()) - .eq(StringUtils.isNotBlank(bo.getBusinessDirection()), ErpProjectInfo::getBusinessDirection, bo.getBusinessDirection()) - .eq(StringUtils.isNotBlank(bo.getSpareFlag()), ErpProjectInfo::getSpareFlag, bo.getSpareFlag()) - .eq(bo.getProjectTypeId() != null, ErpProjectInfo::getProjectTypeId, bo.getProjectTypeId()) - .eq(StringUtils.isNotBlank(bo.getPaymentMethod()), ErpProjectInfo::getPaymentMethod, bo.getPaymentMethod()) - .eq(bo.getDeptId() != null, ErpProjectInfo::getDeptId, bo.getDeptId()) - .eq(bo.getManagerId() != null, ErpProjectInfo::getManagerId, bo.getManagerId()) - .eq(bo.getChargeId() != null, ErpProjectInfo::getChargeId, bo.getChargeId()) - .eq(bo.getDeputyId() != null, ErpProjectInfo::getDeputyId, bo.getDeputyId()) - .eq(StringUtils.isNotBlank(bo.getPeopleId()), ErpProjectInfo::getPeopleId, bo.getPeopleId()) - .eq(bo.getAmount() != null, ErpProjectInfo::getAmount, bo.getAmount()) - .eq(StringUtils.isNotBlank(bo.getProjectStatus()), ErpProjectInfo::getProjectStatus, bo.getProjectStatus()) - .eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectInfo::getFlowStatus, bo.getFlowStatus()) - .eq(bo.getContractId() != null, ErpProjectInfo::getContractId, bo.getContractId()) - .eq(bo.getCreateBy() != null, ErpProjectInfo::getCreateBy, bo.getCreateBy()) - .eq(StringUtils.isNotBlank(bo.getOrderPurchaseStatus()), ErpProjectInfo::getOrderPurchaseStatus, bo.getOrderPurchaseStatus()) - .eq(StringUtils.isNotBlank(bo.getOrderDeliveryStatus()), ErpProjectInfo::getOrderDeliveryStatus, bo.getOrderDeliveryStatus()) - .eq(StringUtils.isNotBlank(bo.getOrderInvoiceStatus()), ErpProjectInfo::getOrderInvoiceStatus, bo.getOrderInvoiceStatus()) - .like(StringUtils.isNotBlank(bo.getContractCode()), "c.contract_code", bo.getContractCode()) - .like(StringUtils.isNotBlank(bo.getContractName()), "c.contract_name", bo.getContractName()) - .eq(ErpProjectInfo::getProjectCategory, ProjectCategoryConstant.CONTRACT_ORDER) - .eq("t.del_flag", "0") - .orderByDesc(ErpProjectInfo::getCreateTime); + .selectAll(ErpProjectInfo.class) + .eq(ErpProjectInfo::getProjectCategory, ProjectCategoryConstant.CONTRACT_ORDER) + .eq(StringUtils.isNotBlank(bo.getContractFlag()), ErpProjectInfo::getContractFlag, bo.getContractFlag()) + .like(StringUtils.isNotBlank(bo.getProjectCode()), ErpProjectInfo::getProjectCode, bo.getProjectCode()) + .like(StringUtils.isNotBlank(bo.getProjectName()), ErpProjectInfo::getProjectName, bo.getProjectName()) + .eq(StringUtils.isNotBlank(bo.getBusinessDirection()), ErpProjectInfo::getBusinessDirection, bo.getBusinessDirection()) + .eq(StringUtils.isNotBlank(bo.getSpareFlag()), ErpProjectInfo::getSpareFlag, bo.getSpareFlag()) + .eq(bo.getProjectTypeId() != null, ErpProjectInfo::getProjectTypeId, bo.getProjectTypeId()) + .eq(StringUtils.isNotBlank(bo.getPaymentMethod()), ErpProjectInfo::getPaymentMethod, bo.getPaymentMethod()) + .eq(bo.getDeptId() != null, ErpProjectInfo::getDeptId, bo.getDeptId()) + .eq(bo.getManagerId() != null, ErpProjectInfo::getManagerId, bo.getManagerId()) + .eq(bo.getChargeId() != null, ErpProjectInfo::getChargeId, bo.getChargeId()) + .eq(bo.getDeputyId() != null, ErpProjectInfo::getDeputyId, bo.getDeputyId()) + .eq(StringUtils.isNotBlank(bo.getPeopleId()), ErpProjectInfo::getPeopleId, bo.getPeopleId()) + .eq(bo.getAmount() != null, ErpProjectInfo::getAmount, bo.getAmount()) + .eq(StringUtils.isNotBlank(bo.getProjectStatus()), ErpProjectInfo::getProjectStatus, bo.getProjectStatus()) + .eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectInfo::getFlowStatus, bo.getFlowStatus()) + .eq(bo.getContractId() != null, ErpProjectInfo::getContractId, bo.getContractId()) + .eq(bo.getCreateBy() != null, ErpProjectInfo::getCreateBy, bo.getCreateBy()) + .eq(StringUtils.isNotBlank(bo.getOrderPurchaseStatus()), ErpProjectInfo::getOrderPurchaseStatus, bo.getOrderPurchaseStatus()) + .eq(StringUtils.isNotBlank(bo.getOrderDeliveryStatus()), ErpProjectInfo::getOrderDeliveryStatus, bo.getOrderDeliveryStatus()) + .eq(StringUtils.isNotBlank(bo.getOrderInvoiceStatus()), ErpProjectInfo::getOrderInvoiceStatus, bo.getOrderInvoiceStatus()) + .like(StringUtils.isNotBlank(bo.getContractCode()), "c.contract_code", bo.getContractCode()) + .like(StringUtils.isNotBlank(bo.getContractName()), "c.contract_name", bo.getContractName()) + .eq(ErpProjectInfo::getProjectCategory, ProjectCategoryConstant.CONTRACT_ORDER) + .eq("t.del_flag", "0") + .orderByDesc(ErpProjectInfo::getCreateTime); return lqw; } + private Map buildContractIdToProjectManagerIdMap(Set contractIds) { + if (CollUtil.isEmpty(contractIds)) { + return MapUtil.empty(); + } + // contract_id -> project_id(若一合同关联多个项目,这里取第一条;如需更严格可调整为一对多) + List pcs = projectContractsMapper.selectList(new LambdaQueryWrapper() + .in(ErpProjectContracts::getContractId, contractIds) + .eq(ErpProjectContracts::getDelFlag, "0") + .orderByAsc(ErpProjectContracts::getSortOrder) + .orderByAsc(ErpProjectContracts::getProjectContractsId)); + + if (CollUtil.isEmpty(pcs)) { + return MapUtil.empty(); + } + + Map contractId2ProjectId = pcs.stream() + .filter(x -> x.getContractId() != null && x.getProjectId() != null) + .collect(Collectors.toMap( + ErpProjectContracts::getContractId, + ErpProjectContracts::getProjectId, + (a, b) -> a + )); + + Set projectIds = contractId2ProjectId.values().stream().filter(Objects::nonNull).collect(Collectors.toSet()); + if (CollUtil.isEmpty(projectIds)) { + return MapUtil.empty(); + } + + List projects = projectInfoMapper.selectList(new LambdaQueryWrapper() + .select(ErpProjectInfo::getProjectId, ErpProjectInfo::getManagerId) + .in(ErpProjectInfo::getProjectId, projectIds) + .eq(ErpProjectInfo::getDelFlag, "0")); + + Map projectId2ManagerId = projects.stream() + .filter(p -> p.getProjectId() != null) + .collect(Collectors.toMap(ErpProjectInfo::getProjectId, ErpProjectInfo::getManagerId, (a, b) -> a)); + + return contractId2ProjectId.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> projectId2ManagerId.get(e.getValue()), (a, b) -> a)); + } + + private Map buildContractIdToContractCreateByMap(Set contractIds) { + if (CollUtil.isEmpty(contractIds)) { + return MapUtil.empty(); + } + List contracts = contractInfoMapper.selectList(new LambdaQueryWrapper() + .select(ErpContractInfo::getContractId, ErpContractInfo::getCreateBy) + .in(ErpContractInfo::getContractId, contractIds)); + if (CollUtil.isEmpty(contracts)) { + return MapUtil.empty(); + } + return contracts.stream() + .filter(c -> c.getContractId() != null) + .collect(Collectors.toMap(ErpContractInfo::getContractId, ErpContractInfo::getCreateBy, (a, b) -> a)); + } + /** * 暂存合同订单(项目信息) * @@ -243,9 +344,9 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { if (!projectContractsList.isEmpty()) { // 原有关联 ID 集合 Set oldIds = projectContractsOldList.stream() - .map(ErpProjectContracts::getProjectContractsId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); + .map(ErpProjectContracts::getProjectContractsId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); // 保存新列表(新增项目 + 新增/更新关联合同) for (ErpProjectContractsBo projectContractsBo : projectContractsList) { @@ -288,13 +389,13 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { // 删除在旧列表中但不在新列表中的关联 Set existingIds = projectContractsList.stream() - .map(ErpProjectContractsBo::getProjectContractsId) - .filter(Objects::nonNull) - .filter(oldIds::contains) - .collect(Collectors.toSet()); + .map(ErpProjectContractsBo::getProjectContractsId) + .filter(Objects::nonNull) + .filter(oldIds::contains) + .collect(Collectors.toSet()); List toDelete = projectContractsOldList.stream() - .filter(contract -> !existingIds.contains(contract.getProjectContractsId())) - .toList(); + .filter(contract -> !existingIds.contains(contract.getProjectContractsId())) + .toList(); for (ErpProjectContracts item : toDelete) { projectContractsMapper.deleteById(item.getProjectContractsId()); } @@ -382,7 +483,7 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { /** * 保存项目阶段计划列表 * - * @param projectInfo 项目信息 + * @param projectInfo 项目信息 * @param planStageList 项目阶段计划列表 */ private void savePlanStageList(ErpProjectInfo projectInfo, List planStageList) { @@ -404,20 +505,20 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { queryWrapper.eq(ErpProjectPlanStage::getProjectPlanId, projectPlanId); List existingStages = planStageMapper.selectList(queryWrapper); List existingIds = existingStages.stream() - .map(ErpProjectPlanStage::getPlanStageId) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + .map(ErpProjectPlanStage::getPlanStageId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); // 收集前端传来的ID列表(已存在的记录) List newIds = planStageList.stream() - .map(ErpProjectPlanStageBo::getPlanStageId) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + .map(ErpProjectPlanStageBo::getPlanStageId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); // 删除不在新列表中的原有记录 List idsToDelete = existingIds.stream() - .filter(id -> !newIds.contains(id)) - .collect(Collectors.toList()); + .filter(id -> !newIds.contains(id)) + .collect(Collectors.toList()); if (CollUtil.isNotEmpty(idsToDelete)) { planStageMapper.deleteBatchIds(idsToDelete); } @@ -501,12 +602,12 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { throw new ServiceException("合同甲方客户信息不存在,请先在客户管理中维护客户信息"); } if (StringUtils.isBlank(customerInfo.getOssId()) - || StringUtils.isBlank(customerInfo.getTaxNumber()) - || StringUtils.isBlank(customerInfo.getBankAccountOpening()) - || StringUtils.isBlank(customerInfo.getBankNumber())) { + || StringUtils.isBlank(customerInfo.getTaxNumber()) + || StringUtils.isBlank(customerInfo.getBankAccountOpening()) + || StringUtils.isBlank(customerInfo.getBankNumber())) { String customerName = StringUtils.isNotBlank(customerInfo.getCustomerName()) - ? customerInfo.getCustomerName() - : String.valueOf(oneCustomerId); + ? customerInfo.getCustomerName() + : String.valueOf(oneCustomerId); throw new ServiceException("客户【" + customerName + "】的附件、税号、开户银行、银行账号不能为空,请先在客户管理中完善!"); } } @@ -521,7 +622,7 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { TenantHelper.dynamic(processEvent.getTenantId(), () -> { log.info("当前任务执行了{}", processEvent.toString()); ErpProjectInfo projectInfo = projectInfoMapper.selectById( - Convert.toLong(processEvent.getBusinessId()) + Convert.toLong(processEvent.getBusinessId()) ); if (projectInfo != null) { projectInfo.setFlowStatus(processEvent.getStatus()); @@ -538,10 +639,10 @@ public class ErpContractOrderServiceImpl implements IErpContractOrderService { } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) { projectInfo.setProjectStatus(OAStatusEnum.COMPLETED.getStatus()); } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.INVALID.getStatus()) - || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) { + || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) { projectInfo.setProjectStatus(OAStatusEnum.INVALID.getStatus()); } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.BACK.getStatus()) - || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.CANCEL.getStatus())) { + || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.CANCEL.getStatus())) { projectInfo.setProjectStatus(OAStatusEnum.DRAFT.getStatus()); } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.DRAFT.getStatus())) { projectInfo.setProjectStatus(OAStatusEnum.DRAFT.getStatus());