Merge remote-tracking branch 'origin/dev' into dev

dev
wanghao 2 months ago
commit be42558fa5

@ -113,4 +113,15 @@ public class ErpAfterSalesController extends BaseController {
return R.ok(list); return R.ok(list);
} }
/**
*
*/
@SaCheckPermission("oa/erp:afterSales:add")
@Log(title = "项目售后信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/submitAndFlowStart")
public R<ErpAfterSalesVo> submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpAfterSalesBo bo) {
return R.ok(erpAfterSalesService.submitAndFlowStart(bo));
}
} }

@ -101,6 +101,17 @@ public class ErpBudgetInfoController extends BaseController {
return toAjax(erpBudgetInfoService.updateByBo(bo)); return toAjax(erpBudgetInfoService.updateByBo(bo));
} }
/**
*
*/
@SaCheckPermission("oa:erp/budgetInfo:change")
@Log(title = "项目预算", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/change")
public R<Void> change(@Validated(AddGroup.class) @RequestBody ErpBudgetInfoBo bo) {
return toAjax(erpBudgetInfoService.changeByBo(bo));
}
/** /**
* *
* *

@ -15,7 +15,11 @@ import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController; import org.dromara.common.web.core.BaseController;
import org.dromara.oa.erp.domain.bo.ErpContractInfoBo;
import org.dromara.oa.erp.domain.bo.ErpProjectReportBo;
import org.dromara.oa.erp.domain.bo.ErpProjectReportDetailBo; import org.dromara.oa.erp.domain.bo.ErpProjectReportDetailBo;
import org.dromara.oa.erp.domain.bo.ProjectReportAndDetailWrapperBo;
import org.dromara.oa.erp.domain.vo.ErpContractInfoVo;
import org.dromara.oa.erp.domain.vo.ErpProjectReportDetailVo; import org.dromara.oa.erp.domain.vo.ErpProjectReportDetailVo;
import org.dromara.oa.erp.service.IErpProjectReportDetailService; import org.dromara.oa.erp.service.IErpProjectReportDetailService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -114,4 +118,18 @@ public class ErpProjectReportDetailController extends BaseController {
return R.ok(list); return R.ok(list);
} }
/**
*
* @param wrapper
* @return
*/
@SaCheckPermission("oa/erp:projectReportDetail:add")
@Log(title = "项目周报明细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/projectReportSubmitAndFlowStart")
public R<ErpProjectReportDetailVo> projectReportSubmitAndFlowStart(@Validated(AddGroup.class) @RequestBody ProjectReportAndDetailWrapperBo wrapper) {
ErpProjectReportBo projectReport = wrapper.getProjectReport();
ErpProjectReportDetailBo projectDetailReport = wrapper.getProjectDetailReport();
return R.ok(erpProjectReportDetailService.projectReportSubmitAndFlowStart(projectReport, projectDetailReport));
}
} }

@ -42,7 +42,7 @@ public class ErpBudgetInfo extends TenantEntity {
/** /**
* +1 * +1
*/ */
private Long budgetVersion; private Integer budgetVersion;
/** /**
* 1 2 3 * 1 2 3

@ -1,9 +1,6 @@
package org.dromara.oa.erp.domain; package org.dromara.oa.erp.domain;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity; import org.dromara.common.tenant.core.TenantEntity;
@ -27,7 +24,7 @@ public class ErpProjectReport extends TenantEntity {
/** /**
* ID * ID
*/ */
@TableId(value = "report_id", type = IdType.AUTO) @TableId(value = "report_id", type = IdType.ASSIGN_ID)
private Long reportId; private Long reportId;
/** /**
@ -101,5 +98,27 @@ public class ErpProjectReport extends TenantEntity {
*/ */
private String projectCode; private String projectCode;
/**
*
*/
@TableField(exist = false)
private String deptName;
/**
*
*/
@TableField(exist = false)
private String managerName;
/**
*
*/
@TableField(exist = false)
private String chargeName;
/**
*
*/
@TableField(exist = false)
private String deputyName;
} }

@ -28,7 +28,7 @@ public class ErpProjectReportDetail extends TenantEntity {
/** /**
* ID * ID
*/ */
@TableId(value = "report_detail_id", type = IdType.AUTO) @TableId(value = "report_detail_id", type = IdType.ASSIGN_ID)
private Long reportDetailId; private Long reportDetailId;
/** /**

@ -13,10 +13,12 @@ import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.List; // 1. 别忘了导包 List import java.util.List; // 1. 别忘了导包 List
import java.util.Map;
// 2. 导入两个子表的 BO 对象,因为前端传的是子表的业务数据 // 2. 导入两个子表的 BO 对象,因为前端传的是子表的业务数据
import org.dromara.oa.erp.domain.bo.ErpAfterSalesLaborCostsBo; import org.dromara.oa.erp.domain.bo.ErpAfterSalesLaborCostsBo;
import org.dromara.oa.erp.domain.bo.ErpAfterSalesMaterialCostsBo; import org.dromara.oa.erp.domain.bo.ErpAfterSalesMaterialCostsBo;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
/** /**
* erp_after_sales * erp_after_sales
@ -180,5 +182,20 @@ public class ErpAfterSalesBo extends BaseEntity {
*/ */
private List<ErpAfterSalesMaterialCostsBo> materialCostsList; private List<ErpAfterSalesMaterialCostsBo> materialCostsList;
/**
*
*/
private String flowCode;
/**
* {'entity': {}}
*/
private Map<String, Object> variables;
/**
*
*/
private RemoteFlowInstanceBizExt bizExt;
} }

@ -44,7 +44,7 @@ public class ErpBudgetInfoBo extends BaseEntity {
/** /**
* +1 * +1
*/ */
private Long budgetVersion; private Integer budgetVersion;
/** /**
* 1 2 3 * 1 2 3

@ -1,5 +1,6 @@
package org.dromara.oa.erp.domain.bo; package org.dromara.oa.erp.domain.bo;
import cn.idev.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@ -90,5 +91,23 @@ public class ErpProjectReportBo extends BaseEntity {
*/ */
private String projectCode; private String projectCode;
/**
*
*/
private String deptName;
/**
*
*/
private String managerName;
/**
*
*/
private String chargeName;
/**
*
*/
private String deputyName;
} }

@ -1,5 +1,6 @@
package org.dromara.oa.erp.domain.bo; package org.dromara.oa.erp.domain.bo;
import cn.hutool.core.util.ObjectUtil;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@ -7,8 +8,12 @@ import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.oa.erp.domain.ErpProjectReportDetail; import org.dromara.oa.erp.domain.ErpProjectReportDetail;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/** /**
* erp_project_report_detail * erp_project_report_detail
@ -96,6 +101,10 @@ public class ErpProjectReportDetailBo extends BaseEntity {
* *
*/ */
private String flowStatus; private String flowStatus;
/**
*
*/
private String flowCode;
/** /**
* *
@ -127,5 +136,49 @@ public class ErpProjectReportDetailBo extends BaseEntity {
*/ */
private String activeFlag; private String activeFlag;
/**
* {'entity': {}}
*/
private Map<String, Object> variables;
/**
*
*/
private RemoteFlowInstanceBizExt bizExt;
/**
*
*/
private String deptName;
/**
*
*/
private String managerName;
/**
*
*/
private String chargeName;
/**
*
*/
private String deputyName;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
public RemoteFlowInstanceBizExt getBizExt() {
if (ObjectUtil.isNull(bizExt)) {
bizExt = new RemoteFlowInstanceBizExt();
}
return bizExt;
}
} }

@ -0,0 +1,12 @@
package org.dromara.oa.erp.domain.bo;
import jakarta.validation.Valid;
import lombok.Data;
@Data
public class ProjectReportAndDetailWrapperBo {
@Valid
private ErpProjectReportBo projectReport;
@Valid
private ErpProjectReportDetailBo projectDetailReport;
}

@ -51,7 +51,7 @@ public class ErpBudgetInfoVo implements Serializable {
* +1 * +1
*/ */
@ExcelProperty(value = "版本,新版本+1") @ExcelProperty(value = "版本,新版本+1")
private Long budgetVersion; private Integer budgetVersion;
/** /**
* 1 2 3 * 1 2 3

@ -155,5 +155,28 @@ public class ErpProjectReportDetailVo implements Serializable {
@ExcelDictFormat(readConverterExp = "1=是,0=否") @ExcelDictFormat(readConverterExp = "1=是,0=否")
private String activeFlag; private String activeFlag;
/**
*
*/
@ExcelProperty(value = "部门名称")
private String deptName;
/**
*
*/
@ExcelProperty(value = "项目经理名称")
private String managerName;
/**
*
*/
@ExcelProperty(value = "部门负责人名称")
private String chargeName;
/**
*
*/
@ExcelProperty(value = "分管副总名称")
private String deputyName;
} }

@ -6,6 +6,7 @@ import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.oa.erp.domain.ErpProjectReport; import org.dromara.oa.erp.domain.ErpProjectReport;
import java.io.Serial; import java.io.Serial;
@ -21,7 +22,7 @@ import java.io.Serializable;
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
@AutoMapper(target = ErpProjectReport.class) @AutoMapper(target = ErpProjectReport.class)
public class ErpProjectReportVo implements Serializable { public class ErpProjectReportVo extends BaseEntity implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -29,13 +30,13 @@ public class ErpProjectReportVo implements Serializable {
/** /**
* ID * ID
*/ */
@ExcelProperty(value = "项目周报ID") // @ExcelProperty(value = "项目周报ID")
private Long reportId; private Long reportId;
/** /**
* ID * ID
*/ */
@ExcelProperty(value = "项目ID") // @ExcelProperty(value = "项目ID")
private Long projectId; private Long projectId;
/** /**
@ -43,6 +44,11 @@ public class ErpProjectReportVo implements Serializable {
*/ */
@ExcelProperty(value = "项目名称") @ExcelProperty(value = "项目名称")
private String projectName; private String projectName;
/**
*
*/
@ExcelProperty(value = "项目编码")
private String projectCode;
/** /**
* *
@ -53,70 +59,27 @@ public class ErpProjectReportVo implements Serializable {
/** /**
* *
*/ */
@ExcelProperty(value = "项目经理") // @ExcelProperty(value = "项目经理")
private Long managerId; private Long managerId;
/** /**
* ID * ID
*/ */
@ExcelProperty(value = "部门ID") // @ExcelProperty(value = "部门ID")
private Long deptId; private Long deptId;
/** /**
* *
*/ */
@ExcelProperty(value = "部门负责人") // @ExcelProperty(value = "部门负责人")
private Long chargeId; private Long chargeId;
/** /**
* *
*/ */
@ExcelProperty(value = "分管副总") // @ExcelProperty(value = "分管副总")
private Long deputyId; private Long deputyId;
/**
*
*/
@ExcelProperty(value = "周报情况说明")
private String informationNote;
/**
*
*/
@ExcelProperty(value = "排序号")
private Long sortOrder;
/**
* ID
*/
@ExcelProperty(value = "附件ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "预=留")
private String ossId;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=是,0=否")
private String activeFlag;
/**
*
*/
@ExcelProperty(value = "项目编码")
private String projectCode;
/**
*
*/
@ExcelProperty(value = "项目类型名称")
private String typeName;
/** /**
* *
*/ */
@ -140,5 +103,43 @@ public class ErpProjectReportVo implements Serializable {
*/ */
@ExcelProperty(value = "分管副总名称") @ExcelProperty(value = "分管副总名称")
private String deputyName; private String deputyName;
/**
*
*/
@ExcelProperty(value = "周报情况说明")
private String informationNote;
/**
*
*/
// @ExcelProperty(value = "排序号")
private Long sortOrder;
/**
* ID
*/
@ExcelProperty(value = "附件ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "预=留")
private String ossId;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=是,0=否")
private String activeFlag;
/**
*
*/
// @ExcelProperty(value = "项目类型名称")
private String typeName;
} }

@ -45,4 +45,8 @@ public interface ErpProjectReportMapper extends BaseMapperPlus<ErpProjectReport,
}) })
public List<ErpProjectReportVo> selectCustomErpProjectReportVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectReport> queryWrapper); public List<ErpProjectReportVo> selectCustomErpProjectReportVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectReport> queryWrapper);
public ErpProjectReportVo selectVoAndUserById(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectReport> queryWrapper);
public List<ErpProjectReportVo> selectVoAndUserList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectReport> queryWrapper);
} }

@ -66,4 +66,12 @@ public interface IErpAfterSalesService {
* @return * @return
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
*
* @param bo
* @return
*/
ErpAfterSalesVo submitAndFlowStart(ErpAfterSalesBo bo);
} }

@ -58,6 +58,14 @@ public interface IErpBudgetInfoService {
*/ */
Boolean updateByBo(ErpBudgetInfoBo bo); Boolean updateByBo(ErpBudgetInfoBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean changeByBo(ErpBudgetInfoBo bo);
/** /**
* *
* *

@ -2,7 +2,11 @@ package org.dromara.oa.erp.service;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.oa.erp.domain.bo.ErpContractInfoBo;
import org.dromara.oa.erp.domain.bo.ErpProjectReportBo;
import org.dromara.oa.erp.domain.bo.ErpProjectReportDetailBo; import org.dromara.oa.erp.domain.bo.ErpProjectReportDetailBo;
import org.dromara.oa.erp.domain.bo.ProjectReportAndDetailWrapperBo;
import org.dromara.oa.erp.domain.vo.ErpContractInfoVo;
import org.dromara.oa.erp.domain.vo.ErpProjectReportDetailVo; import org.dromara.oa.erp.domain.vo.ErpProjectReportDetailVo;
import java.util.Collection; import java.util.Collection;
@ -65,4 +69,11 @@ public interface IErpProjectReportDetailService {
* @return * @return
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
*
* @param
* @return
*/
ErpProjectReportDetailVo projectReportSubmitAndFlowStart(ErpProjectReportBo projectReport, ErpProjectReportDetailBo projectDetailReport);
} }

@ -1,6 +1,12 @@
package org.dromara.oa.erp.service.impl; package org.dromara.oa.erp.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -10,6 +16,7 @@ import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.oa.erp.domain.ErpAfterSalesLaborCosts; import org.dromara.oa.erp.domain.ErpAfterSalesLaborCosts;
import org.dromara.oa.erp.domain.ErpAfterSalesMaterialCosts; import org.dromara.oa.erp.domain.ErpAfterSalesMaterialCosts;
import org.dromara.oa.erp.domain.bo.ErpAfterSalesLaborCostsBo; import org.dromara.oa.erp.domain.bo.ErpAfterSalesLaborCostsBo;
@ -18,6 +25,8 @@ import org.dromara.oa.erp.domain.vo.ErpAfterSalesLaborCostsVo;
import org.dromara.oa.erp.domain.vo.ErpAfterSalesMaterialCostsVo; import org.dromara.oa.erp.domain.vo.ErpAfterSalesMaterialCostsVo;
import org.dromara.oa.erp.service.IErpAfterSalesLaborCostsService; import org.dromara.oa.erp.service.IErpAfterSalesLaborCostsService;
import org.dromara.oa.erp.service.IErpAfterSalesMaterialCostsService; import org.dromara.oa.erp.service.IErpAfterSalesMaterialCostsService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.dromara.oa.erp.domain.bo.ErpAfterSalesBo; import org.dromara.oa.erp.domain.bo.ErpAfterSalesBo;
import org.dromara.oa.erp.domain.vo.ErpAfterSalesVo; import org.dromara.oa.erp.domain.vo.ErpAfterSalesVo;
@ -26,7 +35,12 @@ import org.dromara.oa.erp.mapper.ErpAfterSalesMapper;
import org.dromara.oa.erp.service.IErpAfterSalesService; import org.dromara.oa.erp.service.IErpAfterSalesService;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.context.event.EventListener;
import org.dromara.workflow.api.event.ProcessEvent;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Collection; import java.util.Collection;
@ -39,12 +53,14 @@ import java.util.Collection;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
@Slf4j
public class ErpAfterSalesServiceImpl implements IErpAfterSalesService { public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
private final ErpAfterSalesMapper baseMapper; private final ErpAfterSalesMapper baseMapper;
// 【修改点 1】注入两个子表的 Service @DubboReference(timeout = 30000)
// 注意:这里必须加 final配合 @RequiredArgsConstructor 使用 private RemoteWorkflowService remoteWorkflowService;
private final IErpAfterSalesLaborCostsService laborCostsService; private final IErpAfterSalesLaborCostsService laborCostsService;
private final IErpAfterSalesMaterialCostsService materialCostsService; private final IErpAfterSalesMaterialCostsService materialCostsService;
@ -56,31 +72,21 @@ public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
*/ */
@Override @Override
public ErpAfterSalesVo queryById(Long afterSalesId){ public ErpAfterSalesVo queryById(Long afterSalesId){
// 1. 查询主表 VO
ErpAfterSalesVo vo = baseMapper.selectVoById(afterSalesId); ErpAfterSalesVo vo = baseMapper.selectVoById(afterSalesId);
// 2. 如果主表存在,继续查询子表
if (vo != null) { if (vo != null) {
// ============ 处理人工费 ============
// 2.1 使用 list 方法查询出 Entity 列表
List<ErpAfterSalesLaborCosts> laborEntities = laborCostsService.list( List<ErpAfterSalesLaborCosts> laborEntities = laborCostsService.list(
new LambdaQueryWrapper<ErpAfterSalesLaborCosts>() new LambdaQueryWrapper<ErpAfterSalesLaborCosts>()
.eq(ErpAfterSalesLaborCosts::getAfterSalesId, afterSalesId) .eq(ErpAfterSalesLaborCosts::getAfterSalesId, afterSalesId)
); );
// 2.2 将 Entity 列表转换为 VO 列表 (核心修复点)
List<ErpAfterSalesLaborCostsVo> laborVos = MapstructUtils.convert(laborEntities, ErpAfterSalesLaborCostsVo.class); List<ErpAfterSalesLaborCostsVo> laborVos = MapstructUtils.convert(laborEntities, ErpAfterSalesLaborCostsVo.class);
// 2.3 塞入主表对象
vo.setLaborCostsList(laborVos); vo.setLaborCostsList(laborVos);
// ============ 处理材料费 ============
// 3.1 使用 list 方法查询出 Entity 列表
List<ErpAfterSalesMaterialCosts> materialEntities = materialCostsService.list( List<ErpAfterSalesMaterialCosts> materialEntities = materialCostsService.list(
new LambdaQueryWrapper<ErpAfterSalesMaterialCosts>() new LambdaQueryWrapper<ErpAfterSalesMaterialCosts>()
.eq(ErpAfterSalesMaterialCosts::getAfterSalesId, afterSalesId) .eq(ErpAfterSalesMaterialCosts::getAfterSalesId, afterSalesId)
); );
// 3.2 将 Entity 列表转换为 VO 列表
List<ErpAfterSalesMaterialCostsVo> materialVos = MapstructUtils.convert(materialEntities, ErpAfterSalesMaterialCostsVo.class); List<ErpAfterSalesMaterialCostsVo> materialVos = MapstructUtils.convert(materialEntities, ErpAfterSalesMaterialCostsVo.class);
// 3.3 塞入主表对象
vo.setMaterialCostsList(materialVos); vo.setMaterialCostsList(materialVos);
} }
return vo; return vo;
@ -155,35 +161,23 @@ public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
@Override @Override
@Transactional(rollbackFor = Exception.class) // 【重要】开启事务!如果子表保存失败,主表也要回滚,防止数据不一致 @Transactional(rollbackFor = Exception.class) // 【重要】开启事务!如果子表保存失败,主表也要回滚,防止数据不一致
public Boolean insertByBo(ErpAfterSalesBo bo) { public Boolean insertByBo(ErpAfterSalesBo bo) {
// 1. 将 BO (业务对象) 转换为 Entity (数据库实体)
// MapstructUtils 是 Plus 封装的高性能 Bean 拷贝工具
ErpAfterSales add = MapstructUtils.convert(bo, ErpAfterSales.class); ErpAfterSales add = MapstructUtils.convert(bo, ErpAfterSales.class);
// 2. 校验数据(这是生成的代码自带的)
validEntityBeforeSave(add); validEntityBeforeSave(add);
// 3. 保存主表
// baseMapper.insert(add) 返回受影响行数大于0表示成功
// 成功后MyBatis 会自动把生成的 ID 回填到 add 对象中
boolean flag = baseMapper.insert(add) > 0; boolean flag = baseMapper.insert(add) > 0;
bo.setAfterSalesId(add.getAfterSalesId()); // 将生成的 ID 回填给 BO
// 4. 如果主表保存成功,开始处理子表
if (flag) { if (flag) {
Long afterSalesId = add.getAfterSalesId(); // 拿到主表刚才生成的 ID Long afterSalesId = add.getAfterSalesId();
// --- 处理子表 A人员费用 ---
List<ErpAfterSalesLaborCostsBo> laborBoList = bo.getLaborCostsList(); List<ErpAfterSalesLaborCostsBo> laborBoList = bo.getLaborCostsList();
// 使用 CollUtil.isNotEmpty 判断列表不为空
if (CollUtil.isNotEmpty(laborBoList)) { if (CollUtil.isNotEmpty(laborBoList)) {
// 将 BO 列表转为 Entity 列表
List<ErpAfterSalesLaborCosts> laborList = MapstructUtils.convert(laborBoList, ErpAfterSalesLaborCosts.class); List<ErpAfterSalesLaborCosts> laborList = MapstructUtils.convert(laborBoList, ErpAfterSalesLaborCosts.class);
// 遍历每个子对象,把主表 ID 填进去,建立外键关联
laborList.forEach(item -> item.setAfterSalesId(afterSalesId)); laborList.forEach(item -> item.setAfterSalesId(afterSalesId));
// 批量保存
laborCostsService.saveBatch(laborList); laborCostsService.saveBatch(laborList);
} }
// --- 处理子表 B材料费用 ---
List<ErpAfterSalesMaterialCostsBo> materialBoList = bo.getMaterialCostsList(); List<ErpAfterSalesMaterialCostsBo> materialBoList = bo.getMaterialCostsList();
if (CollUtil.isNotEmpty(materialBoList)) { if (CollUtil.isNotEmpty(materialBoList)) {
List<ErpAfterSalesMaterialCosts> materialList = MapstructUtils.convert(materialBoList, ErpAfterSalesMaterialCosts.class); List<ErpAfterSalesMaterialCosts> materialList = MapstructUtils.convert(materialBoList, ErpAfterSalesMaterialCosts.class);
@ -203,17 +197,14 @@ public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
@Override @Override
@Transactional(rollbackFor = Exception.class) // 【重要】开启事务 @Transactional(rollbackFor = Exception.class) // 【重要】开启事务
public Boolean updateByBo(ErpAfterSalesBo bo) { public Boolean updateByBo(ErpAfterSalesBo bo) {
// 1. 更新主表数据
ErpAfterSales update = MapstructUtils.convert(bo, ErpAfterSales.class); ErpAfterSales update = MapstructUtils.convert(bo, ErpAfterSales.class);
validEntityBeforeSave(update); validEntityBeforeSave(update);
// updateById 会根据主键 ID 更新其他字段
int row = baseMapper.updateById(update); int row = baseMapper.updateById(update);
// 2. 如果主表更新成功,开始处理子表
if (row > 0) { if (row > 0) {
Long afterSalesId = bo.getAfterSalesId(); Long afterSalesId = bo.getAfterSalesId();
// ================== 1. 处理人员费用 ================== // ================== 处理人员费用 ==================
// 先删除旧的 // 先删除旧的
laborCostsService.remove(new LambdaQueryWrapper<ErpAfterSalesLaborCosts>() laborCostsService.remove(new LambdaQueryWrapper<ErpAfterSalesLaborCosts>()
.eq(ErpAfterSalesLaborCosts::getAfterSalesId, afterSalesId)); .eq(ErpAfterSalesLaborCosts::getAfterSalesId, afterSalesId));
@ -223,7 +214,7 @@ public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
if (CollUtil.isNotEmpty(laborBoList)) { if (CollUtil.isNotEmpty(laborBoList)) {
List<ErpAfterSalesLaborCosts> laborList = MapstructUtils.convert(laborBoList, ErpAfterSalesLaborCosts.class); List<ErpAfterSalesLaborCosts> laborList = MapstructUtils.convert(laborBoList, ErpAfterSalesLaborCosts.class);
// 【核心修改点 👇】遍历列表,清空 ID // 遍历列表,清空 ID
laborList.forEach(item -> { laborList.forEach(item -> {
item.setLaborCostsId(null); // 关键清空ID让MP重新生成雪花ID避免和逻辑删除的数据冲突 item.setLaborCostsId(null); // 关键清空ID让MP重新生成雪花ID避免和逻辑删除的数据冲突
item.setAfterSalesId(afterSalesId); item.setAfterSalesId(afterSalesId);
@ -232,17 +223,14 @@ public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
laborCostsService.saveBatch(laborList); laborCostsService.saveBatch(laborList);
} }
// ================== 2. 处理材料费用 ================== // ================== 处理材料费用 ==================
// 先删除旧的
materialCostsService.remove(new LambdaQueryWrapper<ErpAfterSalesMaterialCosts>() materialCostsService.remove(new LambdaQueryWrapper<ErpAfterSalesMaterialCosts>()
.eq(ErpAfterSalesMaterialCosts::getAfterSalesId, afterSalesId)); .eq(ErpAfterSalesMaterialCosts::getAfterSalesId, afterSalesId));
// 后新增新的
List<ErpAfterSalesMaterialCostsBo> materialBoList = bo.getMaterialCostsList(); List<ErpAfterSalesMaterialCostsBo> materialBoList = bo.getMaterialCostsList();
if (CollUtil.isNotEmpty(materialBoList)) { if (CollUtil.isNotEmpty(materialBoList)) {
List<ErpAfterSalesMaterialCosts> materialList = MapstructUtils.convert(materialBoList, ErpAfterSalesMaterialCosts.class); List<ErpAfterSalesMaterialCosts> materialList = MapstructUtils.convert(materialBoList, ErpAfterSalesMaterialCosts.class);
// 【核心修改点 👇】遍历列表,清空 ID
materialList.forEach(item -> { materialList.forEach(item -> {
item.setMaterialCostsId(null); // 关键清空ID item.setMaterialCostsId(null); // 关键清空ID
item.setAfterSalesId(afterSalesId); item.setAfterSalesId(afterSalesId);
@ -275,4 +263,104 @@ public class ErpAfterSalesServiceImpl implements IErpAfterSalesService {
} }
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;
} }
/**
*
*
* @param bo
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class) // 开启全局事务
public ErpAfterSalesVo submitAndFlowStart(ErpAfterSalesBo bo) {
ErpAfterSales add = MapstructUtils.convert(bo, ErpAfterSales.class);
validEntityBeforeSave(add);
if (bo.getAfterSalesId() == null) {
this.insertByBo(bo);
} else {
this.updateByBo(bo);
}
// 准备启动流程参数
// 后端发起需要忽略权限
if (bo.getVariables() == null) {
bo.setVariables(new HashMap<>());
}
bo.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(bo.getAfterSalesId().toString());
startProcess.setFlowCode(bo.getFlowCode());
startProcess.setVariables(bo.getVariables());
startProcess.setBizExt(bo.getBizExt());
// 确保 BizExt 里也有 BusinessId
if (bo.getBizExt() != null) {
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
}
// 调用远程服务启动流程
// startCompleteTask 表示“启动并自动完成第一个发起节点”,直接流转到下一个审批人
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
if (!flagOne) {
throw new ServiceException("流程发起异常");
}
return MapstructUtils.convert(add, ErpAfterSalesVo.class);
}
/**
* (: 稿退)
*
* @param processEvent
*/
@EventListener(condition = "#processEvent.flowCode == 'OAAS'")
public void processHandler(ProcessEvent processEvent) {
// 多租户上下文切换(防止异步线程找不到租户)
TenantHelper.dynamic(processEvent.getTenantId(), () -> {
log.info("【售后流程监听】开始处理: key={}, status={}", processEvent.getFlowCode(), processEvent.getStatus());
// 根据 BusinessId 查询出当前的售后单
Long afterSalesId = Convert.toLong(processEvent.getBusinessId());
ErpAfterSales afterSales = baseMapper.selectById(afterSalesId);
if (afterSales == null) {
log.error("未找到对应的售后单据id={}", afterSalesId);
return;
}
// 同步流程状态 (flow_status)
afterSales.setFlowStatus(processEvent.getStatus());
// 根据流程状态,更新业务状态 (after_sales_status)
String status = processEvent.getStatus();
// A. 审批中
if (BusinessStatusEnum.WAITING.getStatus().equals(status)) {
afterSales.setAfterSalesStatus("1");
}
// B. 流程结束/审批通过 (Finish)
else if (BusinessStatusEnum.FINISH.getStatus().equals(status)) {
afterSales.setAfterSalesStatus("2");
}
// C. 驳回 (Back) 或 撤销 (Cancel)
else if (BusinessStatusEnum.BACK.getStatus().equals(status)
|| BusinessStatusEnum.CANCEL.getStatus().equals(status)) {
afterSales.setAfterSalesStatus("0");
}
// D. 作废 (Invalid) 或 终止 (Termination)
else if (BusinessStatusEnum.INVALID.getStatus().equals(status)
|| BusinessStatusEnum.TERMINATION.getStatus().equals(status)) {
afterSales.setAfterSalesStatus("0");
}
// 4. 更新数据库
baseMapper.updateById(afterSales);
});
}
} }

@ -1,6 +1,7 @@
package org.dromara.oa.erp.service.impl; package org.dromara.oa.erp.service.impl;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -157,7 +158,8 @@ public class ErpBudgetInfoServiceImpl extends AbstractWorkflowService<ErpBudgetI
private <T> List<T> queryBudgetCosts(BaseMapper<T> mapper, Class<T> entityClass, Long budgetId) { private <T> List<T> queryBudgetCosts(BaseMapper<T> mapper, Class<T> entityClass, Long budgetId) {
MPJLambdaWrapper<T> wrapper = JoinWrappers.lambda(entityClass) MPJLambdaWrapper<T> wrapper = JoinWrappers.lambda(entityClass)
.selectAll(entityClass) .selectAll(entityClass)
.eq("budget_id", budgetId); // 直接使用字段名 .eq("budget_id", budgetId)
.orderByAsc("sort_order"); // 直接使用字段名
return mapper.selectList(wrapper); return mapper.selectList(wrapper);
} }
@ -268,7 +270,6 @@ public class ErpBudgetInfoServiceImpl extends AbstractWorkflowService<ErpBudgetI
public Boolean insertByBo(ErpBudgetInfoBo bo) { public Boolean insertByBo(ErpBudgetInfoBo bo) {
ErpBudgetInfo add = MapstructUtils.convert(bo, ErpBudgetInfo.class); ErpBudgetInfo add = MapstructUtils.convert(bo, ErpBudgetInfo.class);
validEntityBeforeSave(add); validEntityBeforeSave(add);
add.setBudgetVersion(1L);
boolean flag = baseMapper.insert(add) > 0; boolean flag = baseMapper.insert(add) > 0;
if (add.getProjectCategory().equals(ProjectCategoryEnum.MARKET.getCode()) if (add.getProjectCategory().equals(ProjectCategoryEnum.MARKET.getCode())
@ -331,6 +332,55 @@ public class ErpBudgetInfoServiceImpl extends AbstractWorkflowService<ErpBudgetI
return isUpdated; return isUpdated;
} }
/**
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean changeByBo(ErpBudgetInfoBo bo) {
//当前变更预算的版本
Integer currentBudgetVersion = bo.getBudgetVersion();
// 1. 查询项目的所有预算(包括不可用的)
LambdaQueryWrapper<ErpBudgetInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErpBudgetInfo::getProjectId, bo.getProjectId())
.orderByDesc(ErpBudgetInfo::getBudgetVersion);
List<ErpBudgetInfo> allBudgets = baseMapper.selectList(queryWrapper);
if (allBudgets.isEmpty()) {
throw new RuntimeException("项目不存在");
}
// 2.判断此变更项目预算的状态
ErpBudgetInfo currentEffectiveBudget = allBudgets.stream()
.filter(b -> currentBudgetVersion.equals(b.getBudgetVersion()))
.findFirst()
.orElse(null);
if (currentEffectiveBudget == null || !currentEffectiveBudget.getBudgetStatus().equals(FlowConfigEnum.BUDGET.getCompletedBusinessStatus())) {
throw new RuntimeException("项目不存在可用的预算进行变更");
}
// 3. 获取最新版本号(包括所有状态的预算)
Integer latestVersion = allBudgets.stream()
.map(ErpBudgetInfo::getBudgetVersion)
.max(Integer::compareTo)
.orElse(0);
if (latestVersion.compareTo(currentBudgetVersion) > 0) {
throw new RuntimeException("已经有正在变更的项目预算,版本号:" + latestVersion);
}
bo.setBudgetVersion(currentBudgetVersion+1);
return insertByBo(bo);
}
/** /**
* *
*/ */
@ -694,19 +744,19 @@ public class ErpBudgetInfoServiceImpl extends AbstractWorkflowService<ErpBudgetI
@Override @Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) { if (isValid) {
ids.forEach(id->{ ids.forEach(id -> {
ErpBudgetInfo erpBudgetInfo = baseMapper.selectById(id); ErpBudgetInfo erpBudgetInfo = baseMapper.selectById(id);
if(!erpBudgetInfo.getBudgetStatus().equals(OAStatusEnum.DRAFT.getStatus()) if (!erpBudgetInfo.getBudgetStatus().equals(OAStatusEnum.DRAFT.getStatus())
|| !erpBudgetInfo.getFlowStatus().equals(BusinessStatusEnum.DRAFT.getStatus())){ || !erpBudgetInfo.getFlowStatus().equals(BusinessStatusEnum.DRAFT.getStatus())) {
throw new ServiceException("此项目预算已进入审批,不能删除!"); throw new ServiceException("此项目预算已进入审批,不能删除!");
} }
LambdaUpdateWrapper<ErpBudgetInfo> luw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<ErpBudgetInfo> luw = new LambdaUpdateWrapper<>();
// luw.set(ObjectUtil.isNull(config.getPrefix()), SysOssConfig::getPrefix, ""); // luw.set(ObjectUtil.isNull(config.getPrefix()), SysOssConfig::getPrefix, "");
luw.set(ErpBudgetInfo::getBudgetVersion,null); luw.set(ErpBudgetInfo::getBudgetVersion, null);
luw.set(ErpBudgetInfo::getDelFlag,"1"); luw.set(ErpBudgetInfo::getDelFlag, "1");
luw.set(ErpBudgetInfo::getUpdateBy, LoginHelper.getUserId()); luw.set(ErpBudgetInfo::getUpdateBy, LoginHelper.getUserId());
luw.set(ErpBudgetInfo::getUpdateTime,new Date()); luw.set(ErpBudgetInfo::getUpdateTime, new Date());
luw.eq(ErpBudgetInfo::getBudgetId, erpBudgetInfo.getBudgetId()); luw.eq(ErpBudgetInfo::getBudgetId, erpBudgetInfo.getBudgetId());
boolean flag = baseMapper.update(null, luw) > 0; boolean flag = baseMapper.update(null, luw) > 0;

@ -1,23 +1,48 @@
package org.dromara.oa.erp.service.impl; package org.dromara.oa.erp.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.toolkit.JoinWrappers;
import lombok.extern.slf4j.Slf4j;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.dromara.common.core.enums.BusinessStatusEnum;
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.MapstructUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.oa.erp.domain.ErpContractInfo;
import org.dromara.oa.erp.domain.ErpProjectReport;
import org.dromara.oa.erp.domain.ErpProjectReportDetail; import org.dromara.oa.erp.domain.ErpProjectReportDetail;
import org.dromara.oa.erp.domain.bo.ErpContractInfoBo;
import org.dromara.oa.erp.domain.bo.ErpProjectReportBo;
import org.dromara.oa.erp.domain.bo.ErpProjectReportDetailBo; import org.dromara.oa.erp.domain.bo.ErpProjectReportDetailBo;
import org.dromara.oa.erp.domain.bo.ProjectReportAndDetailWrapperBo;
import org.dromara.oa.erp.domain.vo.ErpContractInfoVo;
import org.dromara.oa.erp.domain.vo.ErpProjectReportDetailVo; import org.dromara.oa.erp.domain.vo.ErpProjectReportDetailVo;
import org.dromara.oa.erp.domain.vo.ErpProjectReportVo;
import org.dromara.oa.erp.mapper.ErpProjectReportDetailMapper; import org.dromara.oa.erp.mapper.ErpProjectReportDetailMapper;
import org.dromara.oa.erp.mapper.ErpProjectReportMapper;
import org.dromara.oa.erp.service.IErpProjectReportDetailService; import org.dromara.oa.erp.service.IErpProjectReportDetailService;
import org.dromara.oa.erp.service.IErpProjectReportService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.event.ProcessEvent;
import org.redisson.api.RedissonClient;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* Service * Service
@ -27,10 +52,17 @@ import java.util.Map;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
@Slf4j
public class ErpProjectReportDetailServiceImpl implements IErpProjectReportDetailService { public class ErpProjectReportDetailServiceImpl implements IErpProjectReportDetailService {
private final IErpProjectReportService erpProjectReportService;
private final ErpProjectReportDetailMapper baseMapper; private final ErpProjectReportDetailMapper baseMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
/** /**
* *
* *
@ -38,23 +70,23 @@ public class ErpProjectReportDetailServiceImpl implements IErpProjectReportDetai
* @return * @return
*/ */
@Override @Override
public ErpProjectReportDetailVo queryById(Long reportDetailId){ public ErpProjectReportDetailVo queryById(Long reportDetailId) {
return baseMapper.selectVoById(reportDetailId); return baseMapper.selectVoById(reportDetailId);
} }
/** /**
* *
* *
* @param bo * @param bo
* @param pageQuery * @param pageQuery
* @return * @return
*/ */
@Override @Override
public TableDataInfo<ErpProjectReportDetailVo> queryPageList(ErpProjectReportDetailBo bo, PageQuery pageQuery) { public TableDataInfo<ErpProjectReportDetailVo> queryPageList(ErpProjectReportDetailBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectReportDetail> lqw = buildQueryWrapper(bo); MPJLambdaWrapper<ErpProjectReportDetail> lqw = buildQueryWrapper(bo);
Page<ErpProjectReportDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); Page<ErpProjectReportDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result); return TableDataInfo.build(result);
} }
/** /**
* *
@ -71,27 +103,26 @@ public class ErpProjectReportDetailServiceImpl implements IErpProjectReportDetai
private MPJLambdaWrapper<ErpProjectReportDetail> buildQueryWrapper(ErpProjectReportDetailBo bo) { private MPJLambdaWrapper<ErpProjectReportDetail> buildQueryWrapper(ErpProjectReportDetailBo bo) {
Map<String, Object> params = bo.getParams(); Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectReportDetail> lqw = JoinWrappers.lambda(ErpProjectReportDetail.class) MPJLambdaWrapper<ErpProjectReportDetail> lqw = JoinWrappers.lambda(ErpProjectReportDetail.class)
.selectAll(ErpProjectReportDetail.class) .selectAll(ErpProjectReportDetail.class)
.eq(bo.getReportId() != null, ErpProjectReportDetail::getReportId, bo.getReportId()) .eq(bo.getReportId() != null, ErpProjectReportDetail::getReportId, bo.getReportId())
.eq(bo.getProjectId() != null, ErpProjectReportDetail::getProjectId, bo.getProjectId()) .eq(bo.getProjectId() != null, ErpProjectReportDetail::getProjectId, bo.getProjectId())
.eq(bo.getFillTime() != null, ErpProjectReportDetail::getFillTime, bo.getFillTime()) .eq(bo.getFillTime() != null, ErpProjectReportDetail::getFillTime, bo.getFillTime())
.eq(StringUtils.isNotBlank(bo.getCurrentWorkWeek()), ErpProjectReportDetail::getCurrentWorkWeek, bo.getCurrentWorkWeek()) .eq(StringUtils.isNotBlank(bo.getCurrentWorkWeek()), ErpProjectReportDetail::getCurrentWorkWeek, bo.getCurrentWorkWeek())
.eq(StringUtils.isNotBlank(bo.getMilestonePlan()), ErpProjectReportDetail::getMilestonePlan, bo.getMilestonePlan()) .eq(StringUtils.isNotBlank(bo.getMilestonePlan()), ErpProjectReportDetail::getMilestonePlan, bo.getMilestonePlan())
.eq(StringUtils.isNotBlank(bo.getSecondaryPhase()), ErpProjectReportDetail::getSecondaryPhase, bo.getSecondaryPhase()) .eq(StringUtils.isNotBlank(bo.getSecondaryPhase()), ErpProjectReportDetail::getSecondaryPhase, bo.getSecondaryPhase())
.eq(StringUtils.isNotBlank(bo.getTasksCompleted()), ErpProjectReportDetail::getTasksCompleted, bo.getTasksCompleted()) .eq(StringUtils.isNotBlank(bo.getTasksCompleted()), ErpProjectReportDetail::getTasksCompleted, bo.getTasksCompleted())
.eq(StringUtils.isNotBlank(bo.getNextPlan()), ErpProjectReportDetail::getNextPlan, bo.getNextPlan()) .eq(StringUtils.isNotBlank(bo.getNextPlan()), ErpProjectReportDetail::getNextPlan, bo.getNextPlan())
.eq(StringUtils.isNotBlank(bo.getRiskResolution()), ErpProjectReportDetail::getRiskResolution, bo.getRiskResolution()) .eq(StringUtils.isNotBlank(bo.getRiskResolution()), ErpProjectReportDetail::getRiskResolution, bo.getRiskResolution())
.eq(bo.getPlannedCompletionRate() != null, ErpProjectReportDetail::getPlannedCompletionRate, bo.getPlannedCompletionRate()) .eq(bo.getPlannedCompletionRate() != null, ErpProjectReportDetail::getPlannedCompletionRate, bo.getPlannedCompletionRate())
.eq(StringUtils.isNotBlank(bo.getInformationNote()), ErpProjectReportDetail::getInformationNote, bo.getInformationNote()) .eq(StringUtils.isNotBlank(bo.getInformationNote()), ErpProjectReportDetail::getInformationNote, bo.getInformationNote())
.eq(StringUtils.isNotBlank(bo.getScheduleStatus()), ErpProjectReportDetail::getScheduleStatus, bo.getScheduleStatus()) .eq(StringUtils.isNotBlank(bo.getScheduleStatus()), ErpProjectReportDetail::getScheduleStatus, bo.getScheduleStatus())
.eq(StringUtils.isNotBlank(bo.getProjectReportStatus()), ErpProjectReportDetail::getProjectReportStatus, bo.getProjectReportStatus()) .eq(StringUtils.isNotBlank(bo.getProjectReportStatus()), ErpProjectReportDetail::getProjectReportStatus, bo.getProjectReportStatus())
.eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectReportDetail::getFlowStatus, bo.getFlowStatus()) .eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectReportDetail::getFlowStatus, bo.getFlowStatus())
.eq(bo.getSortOrder() != null, ErpProjectReportDetail::getSortOrder, bo.getSortOrder()) .eq(bo.getSortOrder() != null, ErpProjectReportDetail::getSortOrder, bo.getSortOrder())
.eq(StringUtils.isNotBlank(bo.getProjectPhases()), ErpProjectReportDetail::getProjectPhases, bo.getProjectPhases()) .eq(StringUtils.isNotBlank(bo.getProjectPhases()), ErpProjectReportDetail::getProjectPhases, bo.getProjectPhases())
.eq(bo.getContractId() != null, ErpProjectReportDetail::getContractId, bo.getContractId()) .eq(bo.getContractId() != null, ErpProjectReportDetail::getContractId, bo.getContractId())
.eq(StringUtils.isNotBlank(bo.getOssId()), ErpProjectReportDetail::getOssId, bo.getOssId()) .eq(StringUtils.isNotBlank(bo.getOssId()), ErpProjectReportDetail::getOssId, bo.getOssId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectReportDetail::getActiveFlag, bo.getActiveFlag()) .eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectReportDetail::getActiveFlag, bo.getActiveFlag());
;
return lqw; return lqw;
} }
@ -128,7 +159,7 @@ public class ErpProjectReportDetailServiceImpl implements IErpProjectReportDetai
/** /**
* *
*/ */
private void validEntityBeforeSave(ErpProjectReportDetail entity){ private void validEntityBeforeSave(ErpProjectReportDetail entity) {
//TODO 做一些数据校验,如唯一约束 //TODO 做一些数据校验,如唯一约束
} }
@ -141,9 +172,83 @@ public class ErpProjectReportDetailServiceImpl implements IErpProjectReportDetai
*/ */
@Override @Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){ if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
} }
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;
} }
/**
*
*
* @param projectReport
* @param projectDetailReport
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ErpProjectReportDetailVo projectReportSubmitAndFlowStart(ErpProjectReportBo projectReport, ErpProjectReportDetailBo projectDetailReport) {
if (StringUtils.isNotNull(projectReport.getReportId())) {
ErpProjectReportVo existingReport = erpProjectReportService.queryById(projectReport.getReportId());
if (existingReport != null) {
erpProjectReportService.updateByBo(projectReport);
} else {
erpProjectReportService.insertByBo(projectReport);
}
} else {
erpProjectReportService.insertByBo(projectReport);
}
ErpProjectReportDetail erpProjectReportDetail = MapstructUtils.convert(projectDetailReport, ErpProjectReportDetail.class);
validEntityBeforeSave(erpProjectReportDetail);
if (StringUtils.isNull(projectDetailReport.getReportDetailId())) {
this.insertByBo(projectDetailReport);
} else {
this.updateByBo(projectDetailReport);
}
// 后端发起需要忽略权限
projectDetailReport.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(projectDetailReport.getReportDetailId().toString());
startProcess.setFlowCode(projectDetailReport.getFlowCode());
startProcess.setVariables(projectDetailReport.getVariables());
startProcess.setBizExt(projectDetailReport.getBizExt());
projectDetailReport.getBizExt().setBusinessId(startProcess.getBusinessId());
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
if (!flagOne) {
throw new ServiceException("流程发起异常");
}
return MapstructUtils.convert(erpProjectReportDetail, ErpProjectReportDetailVo.class);
}
/**
* (: 稿退)
*
* @param processEvent
*/
@EventListener(condition = "#processEvent.flowCode =='XMZB'")
public void processHandler(ProcessEvent processEvent) {
TenantHelper.dynamic(processEvent.getTenantId(), () -> {
log.info("当前任务执行了{}", processEvent.toString());
ErpProjectReportDetail projectReportDetail = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
projectReportDetail.setFlowStatus(processEvent.getStatus());
Map<String, Object> params = processEvent.getParams();
if (MapUtil.isNotEmpty(params)) {
// 办理人
String handler = Convert.toStr(params.get("handler"));
}
if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.WAITING.getStatus())) {
projectReportDetail.setProjectReportStatus(OAStatusEnum.APPROVING.getStatus());
} else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) {
projectReportDetail.setProjectReportStatus(OAStatusEnum.COMPLETED.getStatus());
} else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.INVALID.getStatus())
|| Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) {
projectReportDetail.setProjectReportStatus(OAStatusEnum.INVALID.getStatus());
} else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.BACK.getStatus())
|| Objects.equals(processEvent.getStatus(), BusinessStatusEnum.CANCEL.getStatus())) {
projectReportDetail.setProjectReportStatus(OAStatusEnum.DRAFT.getStatus());
}
baseMapper.updateById(projectReportDetail);
});
}
} }

@ -8,6 +8,7 @@ import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.oa.erp.domain.ErpProjectContracts;
import org.dromara.oa.erp.domain.ErpProjectReport; import org.dromara.oa.erp.domain.ErpProjectReport;
import org.dromara.oa.erp.domain.bo.ErpProjectReportBo; import org.dromara.oa.erp.domain.bo.ErpProjectReportBo;
import org.dromara.oa.erp.domain.vo.ErpProjectReportVo; import org.dromara.oa.erp.domain.vo.ErpProjectReportVo;
@ -38,23 +39,27 @@ public class ErpProjectReportServiceImpl implements IErpProjectReportService {
* @return * @return
*/ */
@Override @Override
public ErpProjectReportVo queryById(Long reportId){ public ErpProjectReportVo queryById(Long reportId) {
return baseMapper.selectVoById(reportId); ErpProjectReportBo bo = new ErpProjectReportBo();
bo.setReportId(reportId);
MPJLambdaWrapper<ErpProjectReport> lqw = buildQueryWrapper(bo);
lqw.eq(reportId != null, ErpProjectReport::getReportId, bo.getReportId());
return baseMapper.selectVoAndUserById(lqw);
} }
/** /**
* *
* *
* @param bo * @param bo
* @param pageQuery * @param pageQuery
* @return * @return
*/ */
@Override @Override
public TableDataInfo<ErpProjectReportVo> queryPageList(ErpProjectReportBo bo, PageQuery pageQuery) { public TableDataInfo<ErpProjectReportVo> queryPageList(ErpProjectReportBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectReport> lqw = buildQueryWrapper(bo); MPJLambdaWrapper<ErpProjectReport> lqw = buildQueryWrapper(bo);
Page<ErpProjectReportVo> result = baseMapper.selectCustomErpProjectReportVoList(pageQuery.build(), lqw); Page<ErpProjectReportVo> result = baseMapper.selectCustomErpProjectReportVoList(pageQuery.build(), lqw);
return TableDataInfo.build(result); return TableDataInfo.build(result);
} }
/** /**
* *
@ -65,27 +70,32 @@ public class ErpProjectReportServiceImpl implements IErpProjectReportService {
@Override @Override
public List<ErpProjectReportVo> queryList(ErpProjectReportBo bo) { public List<ErpProjectReportVo> queryList(ErpProjectReportBo bo) {
MPJLambdaWrapper<ErpProjectReport> lqw = buildQueryWrapper(bo); MPJLambdaWrapper<ErpProjectReport> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw); return baseMapper.selectVoAndUserList(lqw);
} }
private MPJLambdaWrapper<ErpProjectReport> buildQueryWrapper(ErpProjectReportBo bo) { private MPJLambdaWrapper<ErpProjectReport> buildQueryWrapper(ErpProjectReportBo bo) {
Map<String, Object> params = bo.getParams(); Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectReport> lqw = JoinWrappers.lambda(ErpProjectReport.class) MPJLambdaWrapper<ErpProjectReport> lqw = JoinWrappers.lambda(ErpProjectReport.class)
.selectAll(ErpProjectReport.class) .selectAll(ErpProjectReport.class)
.eq(bo.getProjectId() != null, ErpProjectReport::getProjectId, bo.getProjectId()) .eq(bo.getProjectId() != null, ErpProjectReport::getProjectId, bo.getProjectId())
.like(StringUtils.isNotBlank(bo.getProjectName()), ErpProjectReport::getProjectName, bo.getProjectName()) .eq(StringUtils.isNotBlank(bo.getMilestonePlan()), ErpProjectReport::getMilestonePlan, bo.getMilestonePlan())
.eq(StringUtils.isNotBlank(bo.getMilestonePlan()), ErpProjectReport::getMilestonePlan, bo.getMilestonePlan()) .eq(bo.getManagerId() != null, ErpProjectReport::getManagerId, bo.getManagerId())
.eq(bo.getManagerId() != null, ErpProjectReport::getManagerId, bo.getManagerId()) .eq(bo.getDeptId() != null, ErpProjectReport::getDeptId, bo.getDeptId())
.eq(bo.getDeptId() != null, ErpProjectReport::getDeptId, bo.getDeptId()) .eq(bo.getChargeId() != null, ErpProjectReport::getChargeId, bo.getChargeId())
.eq(bo.getChargeId() != null, ErpProjectReport::getChargeId, bo.getChargeId()) .eq(bo.getDeputyId() != null, ErpProjectReport::getDeputyId, bo.getDeputyId())
.eq(bo.getDeputyId() != null, ErpProjectReport::getDeputyId, bo.getDeputyId()) .eq(StringUtils.isNotBlank(bo.getInformationNote()), ErpProjectReport::getInformationNote, bo.getInformationNote())
.eq(StringUtils.isNotBlank(bo.getInformationNote()), ErpProjectReport::getInformationNote, bo.getInformationNote()) .eq(bo.getSortOrder() != null, ErpProjectReport::getSortOrder, bo.getSortOrder())
.eq(bo.getSortOrder() != null, ErpProjectReport::getSortOrder, bo.getSortOrder()) .eq(StringUtils.isNotBlank(bo.getOssId()), ErpProjectReport::getOssId, bo.getOssId())
.eq(StringUtils.isNotBlank(bo.getOssId()), ErpProjectReport::getOssId, bo.getOssId()) .eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectReport::getActiveFlag, bo.getActiveFlag())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectReport::getActiveFlag, bo.getActiveFlag()) .eq("t.del_flag", "0")
.eq(StringUtils.isNotBlank(bo.getProjectCode()), ErpProjectReport::getProjectCode, bo.getProjectCode()) .like(StringUtils.isNotBlank(bo.getProjectName()), ErpProjectReport::getProjectName, bo.getProjectName())
; .like(StringUtils.isNotBlank(bo.getProjectCode()), ErpProjectReport::getProjectCode, bo.getProjectCode())
.apply(StringUtils.isNotBlank(bo.getDeptName()), "d.dept_name LIKE CONCAT('%', {0}, '%')", bo.getDeptName())
.apply(StringUtils.isNotBlank(bo.getManagerName()), "u1.nick_name LIKE CONCAT('%', {0}, '%')", bo.getManagerName())
.apply(StringUtils.isNotBlank(bo.getChargeName()), "u2.nick_name LIKE CONCAT('%', {0}, '%')", bo.getChargeName())
.apply(StringUtils.isNotBlank(bo.getDeputyName()), "u3.nick_name LIKE CONCAT('%', {0}, '%')", bo.getDeputyName());
return lqw; return lqw;
} }
/** /**
@ -121,7 +131,7 @@ public class ErpProjectReportServiceImpl implements IErpProjectReportService {
/** /**
* *
*/ */
private void validEntityBeforeSave(ErpProjectReport entity){ private void validEntityBeforeSave(ErpProjectReport entity) {
//TODO 做一些数据校验,如唯一约束 //TODO 做一些数据校验,如唯一约束
} }
@ -134,7 +144,7 @@ public class ErpProjectReportServiceImpl implements IErpProjectReportService {
*/ */
@Override @Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){ if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
} }
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;

@ -6,38 +6,66 @@
<resultMap type="org.dromara.oa.erp.domain.vo.ErpProjectReportVo" id="ErpProjectReportResult"> <resultMap type="org.dromara.oa.erp.domain.vo.ErpProjectReportVo" id="ErpProjectReportResult">
</resultMap> </resultMap>
<!-- 抽取公共的SELECT字段 -->
<sql id="selectReportVoColumns">
t.report_id,
t.tenant_id,
t.project_id,
t.project_name,
t.milestone_plan,
t.manager_id,
t.dept_id,
t.charge_id,
t.deputy_id,
t.information_note,
t.sort_order,
t.oss_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
t.project_code,
d.dept_name AS deptName,
u1.nick_name AS managerName,
u2.nick_name AS chargeName,
u3.nick_name AS deputyName
</sql>
<!-- 抽取公共的表连接 -->
<sql id="fromReportWithJoin">
FROM erp_project_report t
LEFT JOIN sys_dept d ON d.dept_id = t.dept_id
LEFT JOIN sys_user u1 ON u1.user_id = t.manager_id
LEFT JOIN sys_user u2 ON u2.user_id = t.charge_id
LEFT JOIN sys_user u3 ON u3.user_id = t.deputy_id
</sql>
<!-- 方法1使用resultMap -->
<select id="selectCustomErpProjectReportVoList" resultMap="ErpProjectReportResult"> <select id="selectCustomErpProjectReportVoList" resultMap="ErpProjectReportResult">
select t.report_id, SELECT
t.tenant_id, <include refid="selectReportVoColumns"/>
t.project_id, <include refid="fromReportWithJoin"/>
t.project_name, ${ew.customSqlSegment}
t.milestone_plan, </select>
t.manager_id,
t.dept_id, <!-- 方法2使用resultType -->
t.charge_id, <select id="selectVoAndUserById" resultType="org.dromara.oa.erp.domain.vo.ErpProjectReportVo">
t.deputy_id, SELECT
t.information_note, <include refid="selectReportVoColumns"/>
t.sort_order, <include refid="fromReportWithJoin"/>
t.oss_id, ${ew.customSqlSegment}
t.remark, </select>
t.active_flag,
t.del_flag, <!-- 方法3使用resultType -->
t.create_dept, <select id="selectVoAndUserList" resultType="org.dromara.oa.erp.domain.vo.ErpProjectReportVo">
t.create_by, SELECT
t.create_time, <include refid="selectReportVoColumns"/>
t.update_by, <include refid="fromReportWithJoin"/>
t.update_time, ${ew.customSqlSegment}
t.project_code,
d.dept_name deptName,
u1.nick_name managerName,
u2.nick_name chargeName,
u3.nick_name deputyName
from erp_project_report t
left join sys_dept d on d.dept_id = t.dept_id
left join sys_user u1 on u1.user_id = t.manager_id
left join sys_user u2 on u2.user_id = t.charge_id
left join sys_user u3 on u3.user_id = t.deputy_id
${ew.getCustomSqlSegment}
</select> </select>
</mapper> </mapper>

Loading…
Cancel
Save