|
|
|
|
@ -11,30 +11,34 @@ import org.dromara.common.core.exception.ServiceException;
|
|
|
|
|
import org.dromara.common.core.utils.MapstructUtils;
|
|
|
|
|
import org.dromara.common.core.utils.ObjectUtils;
|
|
|
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
|
|
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
|
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
import com.github.yulichang.toolkit.JoinWrappers;
|
|
|
|
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
|
|
import org.dromara.common.tenant.helper.TenantHelper;
|
|
|
|
|
import org.dromara.oa.erp.domain.*;
|
|
|
|
|
import org.dromara.oa.erp.domain.bo.ErpProjectChangeBo;
|
|
|
|
|
import org.dromara.oa.erp.domain.vo.ErpProjectChangeVo;
|
|
|
|
|
import org.dromara.oa.erp.mapper.*;
|
|
|
|
|
import org.dromara.oa.erp.service.IErpProjectChangeService;
|
|
|
|
|
import org.dromara.workflow.api.RemoteWorkflowService;
|
|
|
|
|
import org.dromara.workflow.api.domain.RemoteStartProcess;
|
|
|
|
|
import org.dromara.workflow.api.event.ProcessEvent;
|
|
|
|
|
import org.springframework.context.event.EventListener;
|
|
|
|
|
import org.dromara.common.satoken.utils.LoginHelper;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.dromara.oa.erp.domain.bo.ErpProjectChangeBo;
|
|
|
|
|
import org.dromara.oa.erp.domain.vo.ErpProjectChangeVo;
|
|
|
|
|
import org.dromara.oa.erp.service.IErpProjectChangeService;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.dromara.common.satoken.utils.LoginHelper;
|
|
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.time.ZoneId;
|
|
|
|
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
|
|
|
|
import com.github.yulichang.toolkit.JoinWrappers;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 项目变更申请Service业务层处理
|
|
|
|
|
@ -47,12 +51,18 @@ import java.util.stream.Collectors;
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
|
|
|
|
|
// 计划变更主子表
|
|
|
|
|
private final ErpProjectChangeMapper baseMapper;
|
|
|
|
|
private final ErpProjectChangeBudgetMapper changeBudgetMapper;
|
|
|
|
|
private final ErpProjectChangeProgressMapper changeProgressMapper;
|
|
|
|
|
private final ErpProjectInfoMapper projectInfoMapper;
|
|
|
|
|
//项目计划主子表
|
|
|
|
|
private final ErpProjectPlanMapper projectPlanMapper;
|
|
|
|
|
private final ErpProjectPlanStageMapper planStageMapper;
|
|
|
|
|
//项目预算主子表
|
|
|
|
|
private final ErpBudgetDetailMapper budgetDetailMapper;
|
|
|
|
|
private final ErpBudgetInfoMapper budgetInfoMapper;
|
|
|
|
|
//项目信息
|
|
|
|
|
private final ErpProjectInfoMapper projectInfoMapper;
|
|
|
|
|
|
|
|
|
|
@DubboReference(timeout = 30000)
|
|
|
|
|
private RemoteWorkflowService remoteWorkflowService;
|
|
|
|
|
@ -91,6 +101,24 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
|
|
|
|
|
return projectChangeVo;
|
|
|
|
|
}
|
|
|
|
|
/* @Override
|
|
|
|
|
public ErpProjectChangeVo queryById(Long projectChangeId){
|
|
|
|
|
ErpProjectChangeVo vo = baseMapper.selectCustomErpProjectChangeVoById(projectChangeId);
|
|
|
|
|
if (vo != null) {
|
|
|
|
|
// 查询预算变更明细
|
|
|
|
|
List<ErpProjectChangeBudget> budgetList = changeBudgetMapper.selectList(
|
|
|
|
|
Wrappers.<ErpProjectChangeBudget>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeBudget::getProjectChangeId, projectChangeId)
|
|
|
|
|
.orderByAsc(ErpProjectChangeBudget::getSortOrder)
|
|
|
|
|
);
|
|
|
|
|
vo.setBudgetList(budgetList);
|
|
|
|
|
|
|
|
|
|
// 查询进度变更明细(连表查询项目阶段信息)
|
|
|
|
|
List<ErpProjectChangeProgress> progressList = changeProgressMapper.selectProgressWithStageInfo(projectChangeId);
|
|
|
|
|
vo.setProgressList(progressList);
|
|
|
|
|
}
|
|
|
|
|
return vo;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 分页查询项目变更申请列表
|
|
|
|
|
@ -102,7 +130,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
@Override
|
|
|
|
|
public TableDataInfo<ErpProjectChangeVo> queryPageList(ErpProjectChangeBo bo, PageQuery pageQuery) {
|
|
|
|
|
MPJLambdaWrapper<ErpProjectChange> lqw = buildQueryWrapper(bo);
|
|
|
|
|
Page<ErpProjectChangeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
|
|
|
|
Page<ErpProjectChangeVo> result = baseMapper.selectCustomErpProjectChangeVoList(pageQuery.build(), lqw);
|
|
|
|
|
return TableDataInfo.build(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -115,7 +143,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
@Override
|
|
|
|
|
public List<ErpProjectChangeVo> queryList(ErpProjectChangeBo bo) {
|
|
|
|
|
MPJLambdaWrapper<ErpProjectChange> lqw = buildQueryWrapper(bo);
|
|
|
|
|
return baseMapper.selectVoList(lqw);
|
|
|
|
|
return baseMapper.selectCustomErpProjectChangeVoList(lqw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private MPJLambdaWrapper<ErpProjectChange> buildQueryWrapper(ErpProjectChangeBo bo) {
|
|
|
|
|
@ -148,37 +176,50 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
return lqw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新增项目变更申请
|
|
|
|
|
*
|
|
|
|
|
* @param bo 项目变更申请
|
|
|
|
|
* @return 是否新增成功
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public Boolean insertByBo(ErpProjectChangeBo bo) {
|
|
|
|
|
// 权限校验:只有项目经理才能提交
|
|
|
|
|
validateProjectManager(bo.getProjectManagerId());
|
|
|
|
|
|
|
|
|
|
ErpProjectChange add = MapstructUtils.convert(bo, ErpProjectChange.class);
|
|
|
|
|
validEntityBeforeSave(add);
|
|
|
|
|
|
|
|
|
|
List<ErpProjectChangeBudget> budgetList = bo.getBudgetList();
|
|
|
|
|
List<ErpProjectChangeProgress> progressList = bo.getProgressList();
|
|
|
|
|
// 设置默认状态
|
|
|
|
|
if (StringUtils.isBlank(add.getProjectChangeStatus())) {
|
|
|
|
|
add.setProjectChangeStatus("1"); // 暂存
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isBlank(add.getActiveFlag())) {
|
|
|
|
|
add.setActiveFlag("1");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean flag = baseMapper.insert(add) > 0;
|
|
|
|
|
if (flag) {
|
|
|
|
|
bo.setProjectChangeId(add.getProjectChangeId());
|
|
|
|
|
|
|
|
|
|
// 保存预算变更明细
|
|
|
|
|
if (ObjectUtils.isNotEmpty(budgetList)) {
|
|
|
|
|
for (ErpProjectChangeBudget budget : budgetList) {
|
|
|
|
|
if (bo.getBudgetList() != null && !bo.getBudgetList().isEmpty()) {
|
|
|
|
|
for (int i = 0; i < bo.getBudgetList().size(); i++) {
|
|
|
|
|
ErpProjectChangeBudget budget = bo.getBudgetList().get(i);
|
|
|
|
|
budget.setProjectChangeId(add.getProjectChangeId());
|
|
|
|
|
budget.setSortOrder( (i + 1));
|
|
|
|
|
changeBudgetMapper.insert(budget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 保存进度变更明细
|
|
|
|
|
if (ObjectUtils.isNotEmpty(progressList)) {
|
|
|
|
|
for (ErpProjectChangeProgress progress : progressList) {
|
|
|
|
|
if (bo.getProgressList() != null && !bo.getProgressList().isEmpty()) {
|
|
|
|
|
for (int i = 0; i < bo.getProgressList().size(); i++) {
|
|
|
|
|
ErpProjectChangeProgress progress = bo.getProgressList().get(i);
|
|
|
|
|
progress.setProjectChangeId(add.getProjectChangeId());
|
|
|
|
|
progress.setSortOrder( (i + 1));
|
|
|
|
|
changeProgressMapper.insert(progress);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -190,93 +231,62 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
* 修改项目变更申请
|
|
|
|
|
*
|
|
|
|
|
* @param bo 项目变更申请
|
|
|
|
|
* @return 是否修改成功
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public Boolean updateByBo(ErpProjectChangeBo bo) {
|
|
|
|
|
// 权限校验:只有项目经理才能修改
|
|
|
|
|
validateProjectManager(bo.getProjectManagerId());
|
|
|
|
|
|
|
|
|
|
// 状态校验:只有草稿状态才能修改
|
|
|
|
|
ErpProjectChange existing = baseMapper.selectById(bo.getProjectChangeId());
|
|
|
|
|
if (existing == null) {
|
|
|
|
|
throw new ServiceException("项目变更申请不存在");
|
|
|
|
|
}
|
|
|
|
|
if (!"1".equals(existing.getProjectChangeStatus())) {
|
|
|
|
|
throw new ServiceException("只有草稿状态的变更申请才能修改");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ErpProjectChange update = MapstructUtils.convert(bo, ErpProjectChange.class);
|
|
|
|
|
validEntityBeforeSave(update);
|
|
|
|
|
|
|
|
|
|
List<ErpProjectChangeBudget> budgetList = bo.getBudgetList();
|
|
|
|
|
List<ErpProjectChangeProgress> progressList = bo.getProgressList();
|
|
|
|
|
boolean flag = baseMapper.updateById(update) > 0;
|
|
|
|
|
if (flag) {
|
|
|
|
|
// 删除原有的预算变更明细
|
|
|
|
|
changeBudgetMapper.delete(Wrappers.<ErpProjectChangeBudget>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeBudget::getProjectChangeId, bo.getProjectChangeId()));
|
|
|
|
|
|
|
|
|
|
// 处理预算变更明细
|
|
|
|
|
if (budgetList != null && !budgetList.isEmpty()) {
|
|
|
|
|
for (ErpProjectChangeBudget budget : budgetList) {
|
|
|
|
|
budget.setProjectChangeId(bo.getProjectChangeId());
|
|
|
|
|
changeBudgetMapper.insertOrUpdate(budget);
|
|
|
|
|
// 删除原有的进度变更明细
|
|
|
|
|
changeProgressMapper.delete(Wrappers.<ErpProjectChangeProgress>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeProgress::getProjectChangeId, bo.getProjectChangeId()));
|
|
|
|
|
|
|
|
|
|
// 重新保存预算变更明细
|
|
|
|
|
if (bo.getBudgetList() != null && !bo.getBudgetList().isEmpty()) {
|
|
|
|
|
for (int i = 0; i < bo.getBudgetList().size(); i++) {
|
|
|
|
|
ErpProjectChangeBudget budget = bo.getBudgetList().get(i);
|
|
|
|
|
budget.setChangeBudgetId(null); // 清空主键,让数据库重新生成
|
|
|
|
|
budget.setProjectChangeId(bo.getProjectChangeId());
|
|
|
|
|
budget.setSortOrder( (i + 1));
|
|
|
|
|
changeBudgetMapper.insert(budget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 删除前端未提交的旧数据
|
|
|
|
|
Set<Long> existingBudgetIds = budgetList.stream()
|
|
|
|
|
.map(ErpProjectChangeBudget::getChangeBudgetId)
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
MPJLambdaWrapper<ErpProjectChangeBudget> budgetLqw = JoinWrappers.lambda(ErpProjectChangeBudget.class);
|
|
|
|
|
budgetLqw.eq(ErpProjectChangeBudget::getProjectChangeId, bo.getProjectChangeId());
|
|
|
|
|
List<ErpProjectChangeBudget> oldBudgetList = changeBudgetMapper.selectList(budgetLqw);
|
|
|
|
|
oldBudgetList.stream()
|
|
|
|
|
.filter(budget -> !existingBudgetIds.contains(budget.getChangeBudgetId()))
|
|
|
|
|
.forEach(budget -> changeBudgetMapper.deleteById(budget.getChangeBudgetId()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理进度变更明细
|
|
|
|
|
if (progressList != null && !progressList.isEmpty()) {
|
|
|
|
|
for (ErpProjectChangeProgress progress : progressList) {
|
|
|
|
|
progress.setProjectChangeId(bo.getProjectChangeId());
|
|
|
|
|
changeProgressMapper.insertOrUpdate(progress);
|
|
|
|
|
// 重新保存进度变更明细
|
|
|
|
|
if (bo.getProgressList() != null && !bo.getProgressList().isEmpty()) {
|
|
|
|
|
for (int i = 0; i < bo.getProgressList().size(); i++) {
|
|
|
|
|
ErpProjectChangeProgress progress = bo.getProgressList().get(i);
|
|
|
|
|
progress.setChangeProgressId(null); // 清空主键,让数据库重新生成
|
|
|
|
|
progress.setProjectChangeId(bo.getProjectChangeId());
|
|
|
|
|
progress.setSortOrder( (i + 1));
|
|
|
|
|
changeProgressMapper.insert(progress);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 删除前端未提交的旧数据
|
|
|
|
|
Set<Long> existingProgressIds = progressList.stream()
|
|
|
|
|
.map(ErpProjectChangeProgress::getChangeProgressId)
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
MPJLambdaWrapper<ErpProjectChangeProgress> progressLqw = JoinWrappers.lambda(ErpProjectChangeProgress.class);
|
|
|
|
|
progressLqw.eq(ErpProjectChangeProgress::getProjectChangeId, bo.getProjectChangeId());
|
|
|
|
|
List<ErpProjectChangeProgress> oldProgressList = changeProgressMapper.selectList(progressLqw);
|
|
|
|
|
oldProgressList.stream()
|
|
|
|
|
.filter(progress -> !existingProgressIds.contains(progress.getChangeProgressId()))
|
|
|
|
|
.forEach(progress -> changeProgressMapper.deleteById(progress.getChangeProgressId()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return baseMapper.updateById(update) > 0;
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 保存前的数据校验
|
|
|
|
|
*/
|
|
|
|
|
private void validEntityBeforeSave(ErpProjectChange entity){
|
|
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验并批量删除项目变更申请信息
|
|
|
|
|
*
|
|
|
|
|
* @param ids 待删除的主键集合
|
|
|
|
|
* @param isValid 是否进行有效性校验
|
|
|
|
|
* @return 是否删除成功
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@GlobalTransactional(rollbackFor = Exception.class)
|
|
|
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
|
|
|
if(isValid){
|
|
|
|
|
//TODO 做一些业务上的校验,判断是否需要校验
|
|
|
|
|
}
|
|
|
|
|
// 先删除子表
|
|
|
|
|
changeBudgetMapper.delete(Wrappers.<ErpProjectChangeBudget>lambdaQuery().in(ErpProjectChangeBudget::getProjectChangeId, ids));
|
|
|
|
|
changeProgressMapper.delete(Wrappers.<ErpProjectChangeProgress>lambdaQuery().in(ErpProjectChangeProgress::getProjectChangeId, ids));
|
|
|
|
|
// 删除主表
|
|
|
|
|
baseMapper.deleteByIds(ids);
|
|
|
|
|
//删除工作流
|
|
|
|
|
List<Long> businessIds = ids.stream().toList();
|
|
|
|
|
return remoteWorkflowService.deleteInstance(businessIds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据项目 ID 准备项目变更信息(带出项目信息和项目计划阶段)
|
|
|
|
|
*
|
|
|
|
|
* @param projectId 项目 ID
|
|
|
|
|
* @return 项目变更信息
|
|
|
|
|
* 根据项目ID准备项目变更信息
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public ErpProjectChangeVo prepareByProjectWithInfo(Long projectId) {
|
|
|
|
|
@ -284,124 +294,268 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
throw new ServiceException("项目ID不能为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 若存在审批中的项目变更则禁止再次发起
|
|
|
|
|
long approvingCount = baseMapper.selectCount(Wrappers.<ErpProjectChange>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, projectId)
|
|
|
|
|
.eq(ErpProjectChange::getDelFlag, "0")
|
|
|
|
|
.eq(ErpProjectChange::getProjectChangeStatus, OAStatusEnum.APPROVING.getStatus()));// "2"审批中,"3"可用
|
|
|
|
|
if (approvingCount > 0) {
|
|
|
|
|
throw new ServiceException("该项目存在未完成的变更申请,请等待审批完成后再发起新的变更");
|
|
|
|
|
// 检查是否有未完成的变更(状态1或2)
|
|
|
|
|
List<ErpProjectChange> existingChanges = baseMapper.selectList(
|
|
|
|
|
Wrappers.<ErpProjectChange>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, projectId)
|
|
|
|
|
.in(ErpProjectChange::getProjectChangeStatus, Arrays.asList("1", "2"))
|
|
|
|
|
.orderByDesc(ErpProjectChange::getCreateTime)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!existingChanges.isEmpty()) {
|
|
|
|
|
// 如果有暂存记录,返回该记录供继续编辑
|
|
|
|
|
ErpProjectChange draftChange = existingChanges.stream()
|
|
|
|
|
.filter(change -> "1".equals(change.getProjectChangeStatus()))
|
|
|
|
|
.findFirst().orElse(null);
|
|
|
|
|
if (draftChange != null) {
|
|
|
|
|
return queryById(draftChange.getProjectChangeId());
|
|
|
|
|
}
|
|
|
|
|
throw new ServiceException("该项目存在未完成的变更申请,请先完成或取消后再发起新的变更");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果已有暂存记录,返回该记录供继续编辑
|
|
|
|
|
ErpProjectChange draftChange = baseMapper.selectOne(Wrappers.<ErpProjectChange>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, projectId)
|
|
|
|
|
.eq(ErpProjectChange::getDelFlag, "0")
|
|
|
|
|
.eq(ErpProjectChange::getProjectChangeStatus, "1")
|
|
|
|
|
.orderByDesc(ErpProjectChange::getCreateTime)
|
|
|
|
|
.last("limit 1"));
|
|
|
|
|
if (draftChange != null) {
|
|
|
|
|
return queryById(draftChange.getProjectChangeId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通过自定义Mapper方法查询项目信息和用户名称(连表查询sys_user)
|
|
|
|
|
// 查询项目信息
|
|
|
|
|
ErpProjectChangeVo vo = baseMapper.prepareByProjectId(projectId);
|
|
|
|
|
if (vo == null) {
|
|
|
|
|
throw new ServiceException("项目不存在");
|
|
|
|
|
throw new ServiceException("项目信息不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询项目计划信息
|
|
|
|
|
MPJLambdaWrapper<ErpProjectPlan> planLqw = JoinWrappers.lambda(ErpProjectPlan.class)
|
|
|
|
|
.eq(ErpProjectPlan::getProjectId, projectId)
|
|
|
|
|
.eq(ErpProjectPlan::getDelFlag, "0");
|
|
|
|
|
ErpProjectPlan projectPlan = projectPlanMapper.selectOne(planLqw);
|
|
|
|
|
// 计算变更次数(已完成的变更数量)
|
|
|
|
|
Long changeCount = baseMapper.selectCount(
|
|
|
|
|
Wrappers.<ErpProjectChange>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, projectId)
|
|
|
|
|
.eq(ErpProjectChange::getProjectChangeStatus, "3")
|
|
|
|
|
);
|
|
|
|
|
vo.setChangeNumber(changeCount.intValue() + 1);
|
|
|
|
|
|
|
|
|
|
if (projectPlan != null) {
|
|
|
|
|
// 查询项目计划阶段
|
|
|
|
|
MPJLambdaWrapper<ErpProjectPlanStage> stageLqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
|
|
|
|
|
.eq(ErpProjectPlanStage::getProjectPlanId, projectPlan.getProjectPlanId())
|
|
|
|
|
.eq(ErpProjectPlanStage::getDelFlag, "0")
|
|
|
|
|
.orderByAsc(ErpProjectPlanStage::getSortOrder);
|
|
|
|
|
List<ErpProjectPlanStage> planStageList = planStageMapper.selectList(stageLqw);
|
|
|
|
|
// 如果存在已完成的变更,将最新一次的变更数据作为默认值
|
|
|
|
|
if (changeCount > 0) {
|
|
|
|
|
ErpProjectChange lastChange = baseMapper.selectOne(
|
|
|
|
|
Wrappers.<ErpProjectChange>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, projectId)
|
|
|
|
|
.eq(ErpProjectChange::getProjectChangeStatus, "3")
|
|
|
|
|
.orderByDesc(ErpProjectChange::getCreateTime)
|
|
|
|
|
.last("limit 1")
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 将项目阶段转换为进度变更明细
|
|
|
|
|
if (ObjectUtils.isNotEmpty(planStageList)) {
|
|
|
|
|
List<ErpProjectChangeProgress> progressList = planStageList.stream().map(stage -> {
|
|
|
|
|
ErpProjectChangeProgress progress = new ErpProjectChangeProgress();
|
|
|
|
|
progress.setPlanStageId(stage.getPlanStageId()); // 绑定项目计划阶段ID
|
|
|
|
|
progress.setProjectPhases(stage.getProjectPhases()); // 项目阶段字典值(禁用显示)
|
|
|
|
|
progress.setMilestoneName(""); // 里程碑名称由用户手动输入
|
|
|
|
|
progress.setOriginalStart(stage.getPlanStartTime()); // 原计划开始时间
|
|
|
|
|
progress.setOriginalEnd(stage.getPlanEndTime()); // 原计划结束时间
|
|
|
|
|
progress.setChangedStart(stage.getPlanStartTime()); // 初始值设为原计划时间
|
|
|
|
|
progress.setChangedEnd(stage.getPlanEndTime()); // 初始值设为原计划时间
|
|
|
|
|
progress.setSortOrder(stage.getSortOrder()); // 排序顺序
|
|
|
|
|
return progress;
|
|
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
if (lastChange != null) {
|
|
|
|
|
// 复制上一次变更的项目当前情况说明等信息作为参考
|
|
|
|
|
vo.setCurrentStatus(lastChange.getCurrentStatus());
|
|
|
|
|
vo.setChangeReason(""); // 变更原因需要重新填写
|
|
|
|
|
vo.setFollowUpWork(""); // 后续工作需要重新填写
|
|
|
|
|
|
|
|
|
|
// 查询上一次变更的预算变更明细作为参考
|
|
|
|
|
List<ErpProjectChangeBudget> lastBudgetList = changeBudgetMapper.selectList(
|
|
|
|
|
Wrappers.<ErpProjectChangeBudget>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeBudget::getProjectChangeId, lastChange.getProjectChangeId())
|
|
|
|
|
.orderByAsc(ErpProjectChangeBudget::getSortOrder)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
List<ErpProjectChangeBudget> budgetList = new ArrayList<>();
|
|
|
|
|
// 将上一次的变更后预算作为本次的变更前预算
|
|
|
|
|
for (ErpProjectChangeBudget lastBudget : lastBudgetList) {
|
|
|
|
|
ErpProjectChangeBudget newBudget = new ErpProjectChangeBudget();
|
|
|
|
|
newBudget.setBudgetDetailId(lastBudget.getBudgetDetailId());
|
|
|
|
|
newBudget.setSubjectName(lastBudget.getSubjectName());
|
|
|
|
|
newBudget.setBudgetBefore(lastBudget.getBudgetAfter()); // 上次变更后 = 本次变更前
|
|
|
|
|
newBudget.setBudgetAfter(lastBudget.getBudgetAfter()); // 默认值
|
|
|
|
|
newBudget.setAmountUsed(lastBudget.getAmountUsed());
|
|
|
|
|
newBudget.setSortOrder(lastBudget.getSortOrder());
|
|
|
|
|
budgetList.add(newBudget);
|
|
|
|
|
}
|
|
|
|
|
vo.setBudgetList(budgetList);
|
|
|
|
|
|
|
|
|
|
// 查询上一次变更的进度变更明细作为参考
|
|
|
|
|
List<ErpProjectChangeProgress> lastProgressList = changeProgressMapper.selectList(
|
|
|
|
|
Wrappers.<ErpProjectChangeProgress>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeProgress::getProjectChangeId, lastChange.getProjectChangeId())
|
|
|
|
|
.orderByAsc(ErpProjectChangeProgress::getSortOrder)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
List<ErpProjectChangeProgress> progressList = new ArrayList<>();
|
|
|
|
|
// 将上一次的变更后时间作为本次的原计划时间
|
|
|
|
|
for (ErpProjectChangeProgress lastProgress : lastProgressList) {
|
|
|
|
|
ErpProjectChangeProgress newProgress = new ErpProjectChangeProgress();
|
|
|
|
|
newProgress.setPlanStageId(lastProgress.getPlanStageId());
|
|
|
|
|
newProgress.setProjectPhases(lastProgress.getProjectPhases());
|
|
|
|
|
newProgress.setMilestoneName(lastProgress.getMilestoneName());
|
|
|
|
|
newProgress.setOriginalStart(lastProgress.getChangedStart()); // 上次变更后 = 本次原计划
|
|
|
|
|
newProgress.setOriginalEnd(lastProgress.getChangedEnd()); // 上次变更后 = 本次原计划
|
|
|
|
|
newProgress.setChangedStart(lastProgress.getChangedStart()); // 默认值
|
|
|
|
|
newProgress.setChangedEnd(lastProgress.getChangedEnd()); // 默认值
|
|
|
|
|
newProgress.setCompletionDegree(lastProgress.getCompletionDegree());
|
|
|
|
|
newProgress.setSortOrder(lastProgress.getSortOrder());
|
|
|
|
|
progressList.add(newProgress);
|
|
|
|
|
}
|
|
|
|
|
vo.setProgressList(progressList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初始化空的预算变更列表(由用户手动添加)
|
|
|
|
|
vo.setBudgetList(new ArrayList<>());
|
|
|
|
|
// 设置申请变更日期为当前日期
|
|
|
|
|
vo.setApplyChangeDate(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
|
|
|
|
|
|
|
|
|
// 计算变更次数:查询该项目已完成的变更次数
|
|
|
|
|
MPJLambdaWrapper<ErpProjectChange> changeCountLqw = JoinWrappers.lambda(ErpProjectChange.class)
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, projectId)
|
|
|
|
|
.eq(ErpProjectChange::getDelFlag, "0")
|
|
|
|
|
.eq(ErpProjectChange::getProjectChangeStatus, OAStatusEnum.COMPLETED.getStatus());
|
|
|
|
|
int changeCount = Math.toIntExact(baseMapper.selectCount(changeCountLqw));
|
|
|
|
|
// 如果没有历史变更记录,从项目计划阶段和预算明细中初始化数据
|
|
|
|
|
if (changeCount == 0) {
|
|
|
|
|
// 查询项目计划阶段,转换为进度变更明细
|
|
|
|
|
List<ErpProjectPlanStage> planStages = planStageMapper.selectList(
|
|
|
|
|
Wrappers.<ErpProjectPlanStage>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectPlanStage::getProjectId, projectId)
|
|
|
|
|
.orderByAsc(ErpProjectPlanStage::getSortOrder)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
vo.setChangeNumber(changeCount + 1); // 当前变更次数 = 已有次数 + 1
|
|
|
|
|
List<ErpProjectChangeProgress> progressList = new ArrayList<>();
|
|
|
|
|
for (ErpProjectPlanStage stage : planStages) {
|
|
|
|
|
ErpProjectChangeProgress progress = new ErpProjectChangeProgress();
|
|
|
|
|
progress.setPlanStageId(stage.getPlanStageId());
|
|
|
|
|
progress.setProjectPhases(stage.getProjectPhases());
|
|
|
|
|
progress.setMilestoneName(""); // 里程碑名称由用户手动输入
|
|
|
|
|
progress.setOriginalStart(stage.getPlanStartTime());
|
|
|
|
|
progress.setOriginalEnd(stage.getPlanEndTime());
|
|
|
|
|
progress.setChangedStart(stage.getPlanStartTime()); // 默认值
|
|
|
|
|
progress.setChangedEnd(stage.getPlanEndTime()); // 默认值
|
|
|
|
|
progress.setCompletionDegree(BigDecimal.ZERO); // 默认完成程度
|
|
|
|
|
progress.setSortOrder(stage.getSortOrder());
|
|
|
|
|
progressList.add(progress);
|
|
|
|
|
}
|
|
|
|
|
vo.setProgressList(progressList);
|
|
|
|
|
|
|
|
|
|
// 设置默认值
|
|
|
|
|
// 查询项目预算明细,转换为预算变更明细
|
|
|
|
|
// 首先查询项目的有效预算
|
|
|
|
|
ErpBudgetInfo budgetInfo = budgetInfoMapper.selectOne(
|
|
|
|
|
Wrappers.<ErpBudgetInfo>lambdaQuery()
|
|
|
|
|
.eq(ErpBudgetInfo::getProjectId, projectId)
|
|
|
|
|
.eq(ErpBudgetInfo::getBudgetStatus, "3") // 可用状态
|
|
|
|
|
.orderByDesc(ErpBudgetInfo::getBudgetVersion)
|
|
|
|
|
.last("limit 1")
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
List<ErpProjectChangeBudget> budgetList = new ArrayList<>();
|
|
|
|
|
if (budgetInfo != null) {
|
|
|
|
|
// 查询预算明细
|
|
|
|
|
List<ErpBudgetDetail> budgetDetails = budgetDetailMapper.selectList(
|
|
|
|
|
Wrappers.<ErpBudgetDetail>lambdaQuery()
|
|
|
|
|
.eq(ErpBudgetDetail::getBudgetId, budgetInfo.getBudgetId())
|
|
|
|
|
.orderByAsc(ErpBudgetDetail::getSortOrder)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for (ErpBudgetDetail detail : budgetDetails) {
|
|
|
|
|
ErpProjectChangeBudget budget = new ErpProjectChangeBudget();
|
|
|
|
|
budget.setBudgetDetailId(detail.getBudgetDetailId());
|
|
|
|
|
budget.setSubjectName(detail.getBudgetItem());
|
|
|
|
|
//xins的预算表数据库是decimal,实体类ErpBudgetDetail却是Long,所以这里需要转换一下
|
|
|
|
|
BigDecimal budgetCost = BigDecimal.valueOf(detail.getBudgetCost());
|
|
|
|
|
budget.setBudgetBefore(budgetCost);
|
|
|
|
|
budget.setBudgetAfter(budgetCost); // 默认值
|
|
|
|
|
budget.setAmountUsed(BigDecimal.ZERO); // 默认已使用金额为0
|
|
|
|
|
budget.setSortOrder(Math.toIntExact(detail.getSortOrder()));
|
|
|
|
|
budgetList.add(budget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vo.setBudgetList(budgetList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置默认状态
|
|
|
|
|
vo.setProjectChangeStatus("1"); // 暂存
|
|
|
|
|
vo.setActiveFlag("1");
|
|
|
|
|
vo.setProjectChangeStatus("1"); // 1-暂存
|
|
|
|
|
|
|
|
|
|
return vo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 提交项目变更并发起审批流
|
|
|
|
|
*
|
|
|
|
|
* @param bo 项目变更申请
|
|
|
|
|
* @return 是否成功
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@GlobalTransactional(rollbackFor = Exception.class)
|
|
|
|
|
public ErpProjectChangeVo projectChangeSubmitAndFlowStart(ErpProjectChangeBo bo) {
|
|
|
|
|
|
|
|
|
|
ErpProjectChange add = MapstructUtils.convert(bo, ErpProjectChange.class);
|
|
|
|
|
validEntityBeforeSave(add) ;
|
|
|
|
|
public Boolean projectChangeSubmitAndFlowStart(ErpProjectChangeBo bo) {
|
|
|
|
|
// 权限校验:只有项目经理才能提交
|
|
|
|
|
validateProjectManager(bo.getProjectManagerId());
|
|
|
|
|
|
|
|
|
|
// 保存或更新项目变更数据
|
|
|
|
|
boolean saveFlag;
|
|
|
|
|
// 检查是否有未完成的变更
|
|
|
|
|
List<ErpProjectChange> existingChanges = baseMapper.selectList(
|
|
|
|
|
Wrappers.<ErpProjectChange>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChange::getProjectId, bo.getProjectId())
|
|
|
|
|
.in(ErpProjectChange::getProjectChangeStatus, Arrays.asList("1", "2"))
|
|
|
|
|
.ne(bo.getProjectChangeId() != null, ErpProjectChange::getProjectChangeId, bo.getProjectChangeId())
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!existingChanges.isEmpty()) {
|
|
|
|
|
throw new ServiceException("该项目存在其他未完成的变更申请,请先完成或取消后再提交");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置状态为审批中
|
|
|
|
|
// bo.setProjectChangeStatus("2");
|
|
|
|
|
// bo.setFlowStatus("running");
|
|
|
|
|
|
|
|
|
|
Boolean result;
|
|
|
|
|
if (bo.getProjectChangeId() == null) {
|
|
|
|
|
saveFlag = insertByBo(bo);
|
|
|
|
|
result = insertByBo(bo);
|
|
|
|
|
} else {
|
|
|
|
|
saveFlag = updateByBo(bo);
|
|
|
|
|
result = updateByBo(bo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!saveFlag) {
|
|
|
|
|
throw new ServiceException("保存项目变更失败");
|
|
|
|
|
if (result) {
|
|
|
|
|
// 发起审批流程
|
|
|
|
|
// 后端发起需要忽略权限
|
|
|
|
|
bo.getVariables().put("ignore", true);
|
|
|
|
|
RemoteStartProcess startProcess = new RemoteStartProcess();
|
|
|
|
|
startProcess.setBusinessId(bo.getProjectChangeId().toString());
|
|
|
|
|
startProcess.setFlowCode(bo.getFlowCode());
|
|
|
|
|
startProcess.setVariables(bo.getVariables());
|
|
|
|
|
startProcess.setBizExt(bo.getBizExt());
|
|
|
|
|
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
|
|
|
|
|
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
|
|
|
|
|
if (!flagOne) {
|
|
|
|
|
throw new ServiceException("发起审批流程失败");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 后端发起需要忽略权限
|
|
|
|
|
bo.getVariables().put("ignore", true);
|
|
|
|
|
RemoteStartProcess startProcess = new RemoteStartProcess();
|
|
|
|
|
startProcess.setBusinessId(bo.getProjectChangeId().toString());
|
|
|
|
|
startProcess.setFlowCode(bo.getFlowCode());
|
|
|
|
|
startProcess.setVariables(bo.getVariables());
|
|
|
|
|
startProcess.setBizExt(bo.getBizExt());
|
|
|
|
|
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
|
|
|
|
|
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
|
|
|
|
|
if (!flagOne) {
|
|
|
|
|
throw new ServiceException("流程发起异常");
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 权限校验:只有项目经理才能提交
|
|
|
|
|
*/
|
|
|
|
|
private void validateProjectManager(Long projectManagerId) {
|
|
|
|
|
// 超级管理员跳过校验
|
|
|
|
|
if (LoginHelper.isSuperAdmin()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MapstructUtils.convert(add, ErpProjectChangeVo.class);
|
|
|
|
|
Long currentUserId = LoginHelper.getUserId();
|
|
|
|
|
if (!Objects.equals(currentUserId, projectManagerId)) {
|
|
|
|
|
throw new ServiceException("只有项目经理才能提交项目计划变更");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验并批量删除项目变更申请信息
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
|
|
|
if(isValid){
|
|
|
|
|
// 校验是否可以删除(只能删除暂存状态的记录)
|
|
|
|
|
List<ErpProjectChange> changes = baseMapper.selectBatchIds(ids);
|
|
|
|
|
for (ErpProjectChange change : changes) {
|
|
|
|
|
if (!"1".equals(change.getProjectChangeStatus())) {
|
|
|
|
|
throw new ServiceException("只能删除暂存状态的变更申请");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除主表和子表数据
|
|
|
|
|
for (Long id : ids) {
|
|
|
|
|
changeBudgetMapper.delete(Wrappers.<ErpProjectChangeBudget>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeBudget::getProjectChangeId, id));
|
|
|
|
|
changeProgressMapper.delete(Wrappers.<ErpProjectChangeProgress>lambdaQuery()
|
|
|
|
|
.eq(ErpProjectChangeProgress::getProjectChangeId, id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return baseMapper.deleteBatchIds(ids) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void validEntityBeforeSave(ErpProjectChange entity){
|
|
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -426,20 +580,4 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验项目经理权限
|
|
|
|
|
*
|
|
|
|
|
* @param projectManagerId 项目经理ID
|
|
|
|
|
*/
|
|
|
|
|
private void validateProjectManager(Long projectManagerId) {
|
|
|
|
|
// 超级管理员跳过校验
|
|
|
|
|
if (LoginHelper.isSuperAdmin()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Long currentUserId = LoginHelper.getUserId();
|
|
|
|
|
if (!currentUserId.equals(projectManagerId)) {
|
|
|
|
|
throw new ServiceException("只有项目经理才能提交项目变更申请");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|