feat(oa/erp): 新增项目计划模块及相关功能

- 新增项目计划实体类 ErpProjectPlan 及其业务对象 ErpProjectPlanBo
- 新增项目计划阶段实体类 ErpProjectPlanStage 及其业务对象 ErpProjectPlanStageBo
- 实现项目计划的增删改查、分页查询及导出功能
- 支持项目计划与项目、合同、用户等信息的关联查询
- 实现项目计划提交并发起工作流的功能
- 添加项目计划状态和流程状态的监听处理逻辑
- 提供项目计划阶段的延迟天数和进度备注更新机制
- 增加项目经理权限校验,确保只有项目经理可提交或修改计划
- 支持项目计划的批量插入、更新和删除操作
- 集成工作流服务,实现项目计划审批流程的启动和处理
dev
zangch@mesnac.com 3 months ago
parent 7b444396d5
commit cd8bd06a69

@ -0,0 +1,130 @@
package org.dromara.oa.erp.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanBo;
import org.dromara.oa.erp.service.IErpProjectPlanService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/oa/erp/erpProjectPlan
*
* @author Yinq
* @date 2025-10-30
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/erp/erpProjectPlan")
public class ErpProjectPlanController extends BaseController {
private final IErpProjectPlanService erpProjectPlanService;
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:list")
@GetMapping("/list")
public TableDataInfo<ErpProjectPlanVo> list(ErpProjectPlanBo bo, PageQuery pageQuery) {
return erpProjectPlanService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:export")
@Log(title = "项目计划", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ErpProjectPlanBo bo, HttpServletResponse response) {
List<ErpProjectPlanVo> list = erpProjectPlanService.queryList(bo);
ExcelUtil.exportExcel(list, "项目计划", ErpProjectPlanVo.class, response);
}
/**
*
*
* @param projectPlanId
*/
@SaCheckPermission("oa/erp:erpProjectPlan:query")
@GetMapping("/{projectPlanId}")
public R<ErpProjectPlanVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("projectPlanId") Long projectPlanId) {
return R.ok(erpProjectPlanService.queryById(projectPlanId));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:add")
@Log(title = "项目计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<ErpProjectPlanVo> add(@Validated(AddGroup.class) @RequestBody ErpProjectPlanBo bo) {
erpProjectPlanService.insertByBo(bo);
return R.ok(erpProjectPlanService.queryById(bo.getProjectPlanId()));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:edit")
@Log(title = "项目计划", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ErpProjectPlanBo bo) {
return toAjax(erpProjectPlanService.updateByBo(bo));
}
/**
*
*
* @param projectPlanIds
*/
@SaCheckPermission("oa/erp:erpProjectPlan:remove")
@Log(title = "项目计划", businessType = BusinessType.DELETE)
@DeleteMapping("/{projectPlanIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable("projectPlanIds") Long[] projectPlanIds) {
return toAjax(erpProjectPlanService.deleteWithValidByIds(List.of(projectPlanIds), true));
}
/**
*
*/
@GetMapping("/getErpProjectPlanList")
public R<List<ErpProjectPlanVo>> getErpProjectPlanList(ErpProjectPlanBo bo) {
List<ErpProjectPlanVo> list = erpProjectPlanService.queryList(bo);
return R.ok(list);
}
/**
*
* @param bo
* @return
*/
@SaCheckPermission("oa/erp:erpProjectPlan:add")
@Log(title = "项目计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/projectPlanSubmitAndFlowStart")
public R<ErpProjectPlanVo> projectPlanSubmitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectPlanBo bo) {
return R.ok(erpProjectPlanService.projectPlanSubmitAndFlowStart(bo));
}
}

@ -0,0 +1,116 @@
package org.dromara.oa.erp.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo;
import org.dromara.oa.erp.service.IErpProjectPlanStageService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/oa/erp/erpProjectPlanStage
*
* @author Yinq
* @date 2025-10-30
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/erp/erpProjectPlanStage")
public class ErpProjectPlanStageController extends BaseController {
private final IErpProjectPlanStageService erpProjectPlanStageService;
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:list")
@GetMapping("/list")
public TableDataInfo<ErpProjectPlanStageVo> list(ErpProjectPlanStageBo bo, PageQuery pageQuery) {
return erpProjectPlanStageService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:export")
@Log(title = "项目计划阶段", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ErpProjectPlanStageBo bo, HttpServletResponse response) {
List<ErpProjectPlanStageVo> list = erpProjectPlanStageService.queryList(bo);
ExcelUtil.exportExcel(list, "项目计划阶段", ErpProjectPlanStageVo.class, response);
}
/**
*
*
* @param planStageId
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:query")
@GetMapping("/{planStageId}")
public R<ErpProjectPlanStageVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("planStageId") Long planStageId) {
return R.ok(erpProjectPlanStageService.queryById(planStageId));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:add")
@Log(title = "项目计划阶段", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ErpProjectPlanStageBo bo) {
return toAjax(erpProjectPlanStageService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:edit")
@Log(title = "项目计划阶段", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ErpProjectPlanStageBo bo) {
return toAjax(erpProjectPlanStageService.updateByBo(bo));
}
/**
*
*
* @param planStageIds
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:remove")
@Log(title = "项目计划阶段", businessType = BusinessType.DELETE)
@DeleteMapping("/{planStageIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable("planStageIds") Long[] planStageIds) {
return toAjax(erpProjectPlanStageService.deleteWithValidByIds(List.of(planStageIds), true));
}
/**
*
*/
@GetMapping("/getErpProjectPlanStageList")
public R<List<ErpProjectPlanStageVo>> getErpProjectPlanStageList(ErpProjectPlanStageBo bo) {
List<ErpProjectPlanStageVo> list = erpProjectPlanStageService.queryList(bo);
return R.ok(list);
}
}

@ -0,0 +1,87 @@
package org.dromara.oa.erp.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* erp_project_plan
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("erp_project_plan")
public class ErpProjectPlan extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "project_plan_id", type = IdType.ASSIGN_ID)
private Long projectPlanId;
/**
* ID
*/
private Long projectId;
/**
*
*/
private Long managerId;
/**
*
*/
private Long chargeId;
/**
*
*/
private String paymentMethod;
/**
* (1 2 3)
*/
private String projectPlanStatus;
/**
*
*/
private String flowStatus;
/**
*
*/
private Long sortOrder;
/**
* ID()
*/
private Long contractId;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
* 0 1
*/
@TableLogic
private String delFlag;
}

@ -0,0 +1,129 @@
package org.dromara.oa.erp.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* erp_project_plan_stage
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("erp_project_plan_stage")
public class ErpProjectPlanStage extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "plan_stage_id", type = IdType.AUTO)
private Long planStageId;
/**
* ID
*/
private Long projectId;
/**
* ID
*/
private Long projectPlanId;
/**
*
*/
private String projectPhases;
/**
*
*/
private Date planStartTime;
/**
*
*/
private Date planEndTime;
/**
*
*/
private String collectionStage;
/**
* (%)
*/
private Long repaymentRate;
/**
*
*/
private Long repaymentAmount;
/**
*
*/
private Date repaymentTime;
/**
*
*/
private Long delayDay;
/**
*
*/
private Date receivableDate;
/**
*
*/
private String reasonsExplanation;
/**
*
*/
private String scheduleRemark;
/**
*
*/
private Date realStartTime;
/**
*
*/
private Date realEndTime;
/**
*
*/
private Long sortOrder;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
* 0 1
*/
@TableLogic
private String delFlag;
}

@ -0,0 +1,144 @@
package org.dromara.oa.erp.domain.bo;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
// import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
import java.util.*;
/**
* erp_project_plan
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ErpProjectPlan.class, reverseConvertGenerate = false)
public class ErpProjectPlanBo extends BaseEntity {
/**
* ID
*/
@NotNull(message = "项目计划ID不能为空", groups = { EditGroup.class })
private Long projectPlanId;
/**
* ID
*/
private Long projectId;
/**
*
*/
private Long managerId;
/**
*
*/
private Long chargeId;
/**
*
*/
private String paymentMethod;
/**
* (1 2 3)
*/
private String projectPlanStatus;
/**
*
*/
private String flowStatus;
/**
*
*/
private Long sortOrder;
/**
* ID()
*/
private Long contractId;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
*
*/
private List<ErpProjectPlanStage> planStageList;
/**
*
*/
private String projectName;
/**
*
*/
private String managerName;
/**
*
*/
private String chargeName;
/**
*
*/
private String contractName;
/**
*
*/
private String flowCode;
/**
* ( )
*/
private String handler;
/**
* {'entity': {}}
*/
private Map<String, Object> variables;
/**
*
*/
private RemoteFlowInstanceBizExt bizExt;
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,122 @@
package org.dromara.oa.erp.domain.bo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* erp_project_plan_stage
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ErpProjectPlanStage.class, reverseConvertGenerate = false)
public class ErpProjectPlanStageBo extends BaseEntity {
/**
* ID
*/
@NotNull(message = "计划阶段ID不能为空", groups = { EditGroup.class })
private Long planStageId;
/**
* ID
*/
private Long projectId;
/**
* ID
*/
private Long projectPlanId;
/**
*
*/
private String projectPhases;
/**
*
*/
private Date planStartTime;
/**
*
*/
private Date planEndTime;
/**
*
*/
private String collectionStage;
/**
* (%)
*/
private Long repaymentRate;
/**
*
*/
private Long repaymentAmount;
/**
*
*/
private Date repaymentTime;
/**
*
*/
private Long delayDay;
/**
*
*/
private Date receivableDate;
/**
*
*/
private String reasonsExplanation;
/**
*
*/
private String scheduleRemark;
/**
*
*/
private Date realStartTime;
/**
*
*/
private Date realEndTime;
/**
*
*/
private Long sortOrder;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
}

@ -0,0 +1,151 @@
package org.dromara.oa.erp.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* erp_project_plan_stage
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ErpProjectPlanStage.class)
public class ErpProjectPlanStageVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@ExcelProperty(value = "计划阶段ID")
private Long planStageId;
/**
* ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* ID
*/
@ExcelProperty(value = "项目计划ID")
private Long projectPlanId;
/**
*
*/
@ExcelProperty(value = "项目阶段")
@ExcelDictFormat(dictType = " project_phases")
private String projectPhases;
/**
*
*/
@ExcelProperty(value = "计划开始时间")
private Date planStartTime;
/**
*
*/
@ExcelProperty(value = "计划结束时间")
private Date planEndTime;
/**
*
*/
@ExcelProperty(value = "回款阶段")
@ExcelDictFormat(dictType = " collection_stage")
private String collectionStage;
/**
* (%)
*/
@ExcelProperty(value = "预计回款比例(%)")
private Long repaymentRate;
/**
*
*/
@ExcelProperty(value = "预计回款金额")
private Long repaymentAmount;
/**
*
*/
@ExcelProperty(value = "预计回款时间")
private Date repaymentTime;
/**
*
*/
@ExcelProperty(value = "回款延期天数")
private Long delayDay;
/**
*
*/
@ExcelProperty(value = "应收款日期")
private Date receivableDate;
/**
*
*/
@ExcelProperty(value = "原因说明")
private String reasonsExplanation;
/**
*
*/
@ExcelProperty(value = "进度备注")
private String scheduleRemark;
/**
*
*/
@ExcelProperty(value = "实际开始时间")
private Date realStartTime;
/**
*
*/
@ExcelProperty(value = "实际结束时间")
private Date realEndTime;
/**
*
*/
@ExcelProperty(value = "排序号")
private Long sortOrder;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "active_flag")
private String activeFlag;
}

@ -0,0 +1,129 @@
package org.dromara.oa.erp.domain.vo;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* erp_project_plan
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ErpProjectPlan.class)
public class ErpProjectPlanVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@ExcelProperty(value = "项目计划ID")
private Long projectPlanId;
/**
* ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
*
*/
@ExcelProperty(value = "项目经理")
private Long managerId;
/**
*
*/
@ExcelProperty(value = "部门负责人")
private Long chargeId;
/**
*
*/
@ExcelProperty(value = "付款方式")
private String paymentMethod;
/**
* (1 2 3)
*/
@ExcelProperty(value = "项目计划状态(1暂存 2审批中 3可用)", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "project_plan_status")
private String projectPlanStatus;
/**
*
*/
@ExcelProperty(value = "流程状态")
private String flowStatus;
/**
*
*/
@ExcelProperty(value = "排序号")
private Long sortOrder;
/**
* ID()
*/
@ExcelProperty(value = "合同ID(预留)")
private Long contractId;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "active_flag")
private String activeFlag;
/**
*
*/
private List<ErpProjectPlanStageVo> planStageList;
/**
*
*/
@ExcelProperty(value = "项目名称")
private String projectName;
/**
*
*/
@ExcelProperty(value = "项目经理名称")
private String managerName;
/**
*
*/
@ExcelProperty(value = "部门负责人名称")
private String chargeName;
/**
*
*/
@ExcelProperty(value = "合同名称")
private String contractName;
}

@ -0,0 +1,113 @@
package org.dromara.oa.erp.mapper;
import java.util.List;
import java.util.Collection;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author Yinq
* @date 2025-10-30
*/
public interface ErpProjectPlanMapper extends BaseMapperPlus<ErpProjectPlan, ErpProjectPlanVo> {
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
public Page<ErpProjectPlanVo> selectCustomErpProjectPlanVoList(@Param("page") Page<ErpProjectPlanVo> page, @Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlan> queryWrapper);
/**
*
*
* @param queryWrapper
* @return
*/
public List<ErpProjectPlanVo> selectCustomErpProjectPlanVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlan> queryWrapper);
/**
* ID
*
* @param projectPlanId ID
* @return
*/
ErpProjectPlanVo selectCustomErpProjectPlanVoById(@Param("projectPlanId") Long projectPlanId);
/**
* ID
*
* @param ids ID
* @return
*/
List<ErpProjectPlanVo> selectCustomErpProjectPlanVoByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Long countCustomErpProjectPlan(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<ErpProjectPlanVo> selectCustomErpProjectPlanVoPage(@Param("page") Page<ErpProjectPlanVo> page, @Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
/**
*
*
* @param list
* @return
*/
int batchInsertErpProjectPlan(@Param("list") List<ErpProjectPlan> list);
/**
*
*
* @param list
* @return
*/
int batchUpdateErpProjectPlan(@Param("list") List<ErpProjectPlan> list);
/**
*
*
* @param queryWrapper
* @return
*/
int deleteCustomErpProjectPlan(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
/**
* ID
*
* @param ids ID
* @return
*/
int deleteCustomErpProjectPlanByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Boolean existsErpProjectPlan(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
}

@ -0,0 +1,113 @@
package org.dromara.oa.erp.mapper;
import java.util.List;
import java.util.Collection;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author Yinq
* @date 2025-10-30
*/
public interface ErpProjectPlanStageMapper extends BaseMapperPlus<ErpProjectPlanStage, ErpProjectPlanStageVo> {
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
public Page<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoList(@Param("page") Page<ErpProjectPlanStageVo> page, @Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlanStage> queryWrapper);
/**
*
*
* @param queryWrapper
* @return
*/
public List<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlanStage> queryWrapper);
/**
* ID
*
* @param planStageId ID
* @return
*/
ErpProjectPlanStageVo selectCustomErpProjectPlanStageVoById(@Param("planStageId") Long planStageId);
/**
* ID
*
* @param ids ID
* @return
*/
List<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Long countCustomErpProjectPlanStage(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoPage(@Param("page") Page<ErpProjectPlanStageVo> page, @Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
/**
*
*
* @param list
* @return
*/
int batchInsertErpProjectPlanStage(@Param("list") List<ErpProjectPlanStage> list);
/**
*
*
* @param list
* @return
*/
int batchUpdateErpProjectPlanStage(@Param("list") List<ErpProjectPlanStage> list);
/**
*
*
* @param queryWrapper
* @return
*/
int deleteCustomErpProjectPlanStage(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
/**
* ID
*
* @param ids ID
* @return
*/
int deleteCustomErpProjectPlanStageByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Boolean existsErpProjectPlanStage(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
}

@ -0,0 +1,76 @@
package org.dromara.oa.erp.service;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
public interface IErpProjectPlanService {
/**
*
*
* @param projectPlanId
* @return
*/
ErpProjectPlanVo queryById(Long projectPlanId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<ErpProjectPlanVo> queryPageList(ErpProjectPlanBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<ErpProjectPlanVo> queryList(ErpProjectPlanBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(ErpProjectPlanBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(ErpProjectPlanBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
*
* @param bo
* @return
*/
ErpProjectPlanVo projectPlanSubmitAndFlowStart(ErpProjectPlanBo bo);
}

@ -0,0 +1,69 @@
package org.dromara.oa.erp.service;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
public interface IErpProjectPlanStageService {
/**
*
*
* @param planStageId
* @return
*/
ErpProjectPlanStageVo queryById(Long planStageId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<ErpProjectPlanStageVo> queryPageList(ErpProjectPlanStageBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<ErpProjectPlanStageVo> queryList(ErpProjectPlanStageBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(ErpProjectPlanStageBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(ErpProjectPlanStageBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

@ -0,0 +1,322 @@
package org.dromara.oa.erp.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
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.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.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.tenant.helper.TenantHelper;
import org.dromara.oa.erp.domain.ErpProjectInfo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper;
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.ErpProjectPlanBo;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.mapper.ErpProjectPlanMapper;
import org.dromara.oa.erp.service.IErpProjectPlanService;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
private final ErpProjectPlanMapper baseMapper;
private final ErpProjectPlanStageMapper planStageMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
/**
*
*
* @param projectPlanId
* @return
*/
@Override
public ErpProjectPlanVo queryById(Long projectPlanId){
// 使用自定义方法查询,包含关联数据
ErpProjectPlanVo projectPlanVo = baseMapper.selectCustomErpProjectPlanVoById(projectPlanId);
// 查询项目计划阶段列表
MPJLambdaWrapper<ErpProjectPlanStage> lqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
.selectAll(ErpProjectPlanStage.class)
.eq("t.del_flag", "0")
.eq(projectPlanId != null, ErpProjectPlanStage::getProjectPlanId, projectPlanId);
List<ErpProjectPlanStageVo> planStageList = planStageMapper.selectVoList(lqw);
projectPlanVo.setPlanStageList(planStageList);
return projectPlanVo;
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<ErpProjectPlanVo> queryPageList(ErpProjectPlanBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectPlan> lqw = buildQueryWrapper(bo);
// 使用自定义分页查询方法获取包含关联数据的结果
Page<ErpProjectPlanVo> result = baseMapper.selectCustomErpProjectPlanVoList(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<ErpProjectPlanVo> queryList(ErpProjectPlanBo bo) {
MPJLambdaWrapper<ErpProjectPlan> lqw = buildQueryWrapper(bo);
// 使用自定义查询方法获取包含关联数据的列表
return baseMapper.selectCustomErpProjectPlanVoList(lqw);
}
private MPJLambdaWrapper<ErpProjectPlan> buildQueryWrapper(ErpProjectPlanBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectPlan> lqw = JoinWrappers.lambda(ErpProjectPlan.class)
.selectAll(ErpProjectPlan.class)
.eq(ErpProjectPlan::getDelFlag, "0")
// 关联项目信息
.select(ErpProjectInfo::getProjectName)
.leftJoin(ErpProjectInfo.class,ErpProjectInfo::getProjectId, ErpProjectPlan::getProjectId)
.eq(bo.getProjectId() != null, ErpProjectPlan::getProjectId, bo.getProjectId())
.eq(bo.getManagerId() != null, ErpProjectPlan::getManagerId, bo.getManagerId())
.eq(bo.getChargeId() != null, ErpProjectPlan::getChargeId, bo.getChargeId())
.eq(StringUtils.isNotBlank(bo.getPaymentMethod()), ErpProjectPlan::getPaymentMethod, bo.getPaymentMethod())
.eq(StringUtils.isNotBlank(bo.getProjectPlanStatus()), ErpProjectPlan::getProjectPlanStatus, bo.getProjectPlanStatus())
.eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectPlan::getFlowStatus, bo.getFlowStatus())
.eq(bo.getSortOrder() != null, ErpProjectPlan::getSortOrder, bo.getSortOrder())
.eq(bo.getContractId() != null, ErpProjectPlan::getContractId, bo.getContractId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectPlan::getActiveFlag, bo.getActiveFlag());
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ErpProjectPlanBo bo) {
ErpProjectPlan add = MapstructUtils.convert(bo, ErpProjectPlan.class);
validEntityBeforeSave(add);
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getManagerId());
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
boolean flag = baseMapper.insert(add) > 0;
if (flag && planStageList != null && !planStageList.isEmpty()) {
bo.setProjectPlanId(add.getProjectPlanId());
for (ErpProjectPlanStage planStage : planStageList) {
planStage.setProjectPlanId(add.getProjectPlanId());
planStage.setProjectId(add.getProjectId());
planStageMapper.insert(planStage);
}
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(ErpProjectPlanBo bo) {
// 获取原有数据
ErpProjectPlan existingPlan = baseMapper.selectById(bo.getProjectPlanId());
if (existingPlan == null) {
throw new ServiceException("项目计划不存在");
}
// 权限校验:只有项目经理才能修改
validateProjectManager(existingPlan.getManagerId());
// 如果不是草稿状态只允许更新阶段的delayDay和scheduleRemark
if (!"1".equals(existingPlan.getProjectPlanStatus())) {
// 非草稿状态,只更新阶段的特定字段
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
if (planStageList != null && !planStageList.isEmpty()) {
for (ErpProjectPlanStage newStage : planStageList) {
if (newStage.getPlanStageId() != null) {
// 只更新delayDay、scheduleRemark和receivableDate
ErpProjectPlanStage existingStage = planStageMapper.selectById(newStage.getPlanStageId());
if (existingStage != null) {
existingStage.setDelayDay(newStage.getDelayDay());
existingStage.setScheduleRemark(newStage.getScheduleRemark());
existingStage.setReceivableDate(newStage.getReceivableDate());
planStageMapper.updateById(existingStage);
}
}
}
}
// 不更新主表数据
return true;
}
// 草稿状态,允许全面更新
ErpProjectPlan update = MapstructUtils.convert(bo, ErpProjectPlan.class);
validEntityBeforeSave(update);
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
MPJLambdaWrapper<ErpProjectPlanStage> lqwRecord = JoinWrappers.lambda(ErpProjectPlanStage.class);
lqwRecord.eq(ErpProjectPlanStage::getProjectPlanId, bo.getProjectPlanId());
List<ErpProjectPlanStage> planStageOldList = planStageMapper.selectList(lqwRecord);
// 如果计划阶段列表不为空且不为空列表,则进行处理
if (planStageList != null && !planStageList.isEmpty()) {
// 遍历计划阶段列表设置项目ID并插入或更新数据库记录
for (ErpProjectPlanStage planStage : planStageList) {
planStage.setProjectId(update.getProjectId());
planStageMapper.insertOrUpdate(planStage);
}
// 收集当前计划阶段列表中已存在的计划阶段ID集合
Set<Long> existingPlanStageIds = planStageList.stream()
.map(ErpProjectPlanStage::getPlanStageId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 从旧的计划阶段列表中筛选出需要删除的记录(即不在当前列表中的记录)
List<ErpProjectPlanStage> filterPlanStageIds = planStageOldList.stream()
.filter(stage -> !existingPlanStageIds.contains(stage.getPlanStageId()))
.toList();
// 删除需要移除的计划阶段记录
for (ErpProjectPlanStage filterPlanStageId : filterPlanStageIds) {
planStageMapper.deleteById(filterPlanStageId.getPlanStageId());
}
}
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(ErpProjectPlan entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param managerId ID
*/
private void validateProjectManager(Long managerId) {
// 超级管理员跳过校验
if (LoginHelper.isSuperAdmin()) {
return;
}
// 普通用户判断当前用户ID是否等于项目经理ID
Long currentUserId = LoginHelper.getUserId();
if (!currentUserId.equals(managerId)) {
throw new ServiceException("只有项目经理才能提交项目计划");
}
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
*
*
* @param bo
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public ErpProjectPlanVo projectPlanSubmitAndFlowStart(ErpProjectPlanBo bo) {
ErpProjectPlan add = MapstructUtils.convert(bo, ErpProjectPlan.class);
validEntityBeforeSave(add);
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getManagerId());
if (StringUtils.isNull(bo.getProjectPlanId())) {
this.insertByBo(bo);
} else {
this.updateByBo(bo);
}
// 后端发起需要忽略权限
bo.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(bo.getProjectPlanId().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 MapstructUtils.convert(add, ErpProjectPlanVo.class);
}
/**
* (: 稿退)
*
* @param processEvent
*/
@EventListener(condition = "#processEvent.flowCode =='OAPS'")
public void processHandler(ProcessEvent processEvent) {
TenantHelper.dynamic(processEvent.getTenantId(), () -> {
log.info("当前任务执行了{}", processEvent.toString());
ErpProjectPlan projectPlan = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
projectPlan.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.FINISH.getStatus())) {
projectPlan.setProjectPlanStatus(OAStatusEnum.COMPLETED.getStatus());
}
baseMapper.updateById(projectPlan);
});
}
}

@ -0,0 +1,149 @@
package org.dromara.oa.erp.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
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.springframework.stereotype.Service;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper;
import org.dromara.oa.erp.service.IErpProjectPlanStageService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
@RequiredArgsConstructor
@Service
public class ErpProjectPlanStageServiceImpl implements IErpProjectPlanStageService {
private final ErpProjectPlanStageMapper baseMapper;
/**
*
*
* @param planStageId
* @return
*/
@Override
public ErpProjectPlanStageVo queryById(Long planStageId){
return baseMapper.selectVoById(planStageId);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<ErpProjectPlanStageVo> queryPageList(ErpProjectPlanStageBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectPlanStage> lqw = buildQueryWrapper(bo);
Page<ErpProjectPlanStageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<ErpProjectPlanStageVo> queryList(ErpProjectPlanStageBo bo) {
MPJLambdaWrapper<ErpProjectPlanStage> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private MPJLambdaWrapper<ErpProjectPlanStage> buildQueryWrapper(ErpProjectPlanStageBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectPlanStage> lqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
.selectAll(ErpProjectPlanStage.class)
.eq(ErpProjectPlanStage::getDelFlag, "0")
.eq(bo.getProjectId() != null, ErpProjectPlanStage::getProjectId, bo.getProjectId())
.eq(bo.getProjectPlanId() != null, ErpProjectPlanStage::getProjectPlanId, bo.getProjectPlanId())
.eq(StringUtils.isNotBlank(bo.getProjectPhases()), ErpProjectPlanStage::getProjectPhases, bo.getProjectPhases())
.eq(bo.getPlanStartTime() != null, ErpProjectPlanStage::getPlanStartTime, bo.getPlanStartTime())
.eq(bo.getPlanEndTime() != null, ErpProjectPlanStage::getPlanEndTime, bo.getPlanEndTime())
.eq(StringUtils.isNotBlank(bo.getCollectionStage()), ErpProjectPlanStage::getCollectionStage, bo.getCollectionStage())
.eq(bo.getRepaymentRate() != null, ErpProjectPlanStage::getRepaymentRate, bo.getRepaymentRate())
.eq(bo.getRepaymentAmount() != null, ErpProjectPlanStage::getRepaymentAmount, bo.getRepaymentAmount())
.eq(bo.getRepaymentTime() != null, ErpProjectPlanStage::getRepaymentTime, bo.getRepaymentTime())
.eq(bo.getDelayDay() != null, ErpProjectPlanStage::getDelayDay, bo.getDelayDay())
.eq(bo.getReceivableDate() != null, ErpProjectPlanStage::getReceivableDate, bo.getReceivableDate())
.eq(StringUtils.isNotBlank(bo.getReasonsExplanation()), ErpProjectPlanStage::getReasonsExplanation, bo.getReasonsExplanation())
.eq(StringUtils.isNotBlank(bo.getScheduleRemark()), ErpProjectPlanStage::getScheduleRemark, bo.getScheduleRemark())
.eq(bo.getRealStartTime() != null, ErpProjectPlanStage::getRealStartTime, bo.getRealStartTime())
.eq(bo.getRealEndTime() != null, ErpProjectPlanStage::getRealEndTime, bo.getRealEndTime())
.eq(bo.getSortOrder() != null, ErpProjectPlanStage::getSortOrder, bo.getSortOrder())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectPlanStage::getActiveFlag, bo.getActiveFlag())
;
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean insertByBo(ErpProjectPlanStageBo bo) {
ErpProjectPlanStage add = MapstructUtils.convert(bo, ErpProjectPlanStage.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPlanStageId(add.getPlanStageId());
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean updateByBo(ErpProjectPlanStageBo bo) {
ErpProjectPlanStage update = MapstructUtils.convert(bo, ErpProjectPlanStage.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(ErpProjectPlanStage entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

@ -0,0 +1,307 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.oa.erp.mapper.ErpProjectPlanMapper">
<resultMap type="org.dromara.oa.erp.domain.vo.ErpProjectPlanVo" id="ErpProjectPlanResult">
</resultMap>
<select id="selectCustomErpProjectPlanVoList" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
${ew.getCustomSqlSegment}
</select>
<!-- 根据ID查询详情 -->
<select id="selectCustomErpProjectPlanVoById" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
where t.project_plan_id = #{projectPlanId}
</select>
<!-- 批量查询 - 根据ID列表 -->
<select id="selectCustomErpProjectPlanVoByIds" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
where t.project_plan_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 统计查询 -->
<select id="countCustomErpProjectPlan" resultType="java.lang.Long">
select count(1) from erp_project_plan t
${ew.getCustomSqlSegment}
</select>
<!-- 分页查询(带自定义条件) -->
<select id="selectCustomErpProjectPlanVoPage" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
${ew.getCustomSqlSegment}
</select>
<!-- 批量插入 -->
<insert id="batchInsertErpProjectPlan">
insert into erp_project_plan(
tenant_id,
project_id,
manager_id,
charge_id,
payment_method,
project_plan_status,
flow_status,
sort_order,
contract_id,
remark,
active_flag,
del_flag,
create_dept,
create_by,
create_time,
update_by,
update_time
)
values
<foreach collection="list" item="item" separator=",">
(
#{item.tenantId},
#{item.projectId},
#{item.managerId},
#{item.chargeId},
#{item.paymentMethod},
#{item.projectPlanStatus},
#{item.flowStatus},
#{item.sortOrder},
#{item.contractId},
#{item.remark},
#{item.activeFlag},
#{item.delFlag},
#{item.createDept},
#{item.createBy},
#{item.createTime},
#{item.updateBy},
#{item.updateTime}
)
</foreach>
</insert>
<!-- 批量更新 -->
<update id="batchUpdateErpProjectPlan">
<foreach collection="list" item="item" separator=";">
update erp_project_plan
<set>
<if test="item.tenantId != null and item.tenantId != ''">
tenant_id = #{item.tenantId},
</if>
<if test="item.projectId != null">
project_id = #{item.projectId},
</if>
<if test="item.managerId != null">
manager_id = #{item.managerId},
</if>
<if test="item.chargeId != null">
charge_id = #{item.chargeId},
</if>
<if test="item.paymentMethod != null and item.paymentMethod != ''">
payment_method = #{item.paymentMethod},
</if>
<if test="item.projectPlanStatus != null and item.projectPlanStatus != ''">
project_plan_status = #{item.projectPlanStatus},
</if>
<if test="item.flowStatus != null and item.flowStatus != ''">
flow_status = #{item.flowStatus},
</if>
<if test="item.sortOrder != null">
sort_order = #{item.sortOrder},
</if>
<if test="item.contractId != null">
contract_id = #{item.contractId},
</if>
<if test="item.remark != null and item.remark != ''">
remark = #{item.remark},
</if>
<if test="item.activeFlag != null and item.activeFlag != ''">
active_flag = #{item.activeFlag},
</if>
<if test="item.delFlag != null and item.delFlag != ''">
del_flag = #{item.delFlag},
</if>
<if test="item.createDept != null">
create_dept = #{item.createDept},
</if>
<if test="item.createBy != null">
create_by = #{item.createBy},
</if>
<if test="item.createTime != null">
create_time = #{item.createTime},
</if>
<if test="item.updateBy != null">
update_by = #{item.updateBy},
</if>
<if test="item.updateTime != null">
update_time = #{item.updateTime}
</if>
</set>
where project_plan_id = #{item.projectPlanId}
</foreach>
</update>
<!-- 根据自定义条件删除 -->
<delete id="deleteCustomErpProjectPlan">
delete from erp_project_plan
${ew.getCustomSqlSegment}
</delete>
<!-- 根据ID列表批量删除 -->
<delete id="deleteCustomErpProjectPlanByIds">
delete from erp_project_plan
where project_plan_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 检查是否存在 -->
<select id="existsErpProjectPlan" resultType="java.lang.Boolean">
select count(1) > 0 from erp_project_plan t
${ew.getCustomSqlSegment}
</select>
</mapper>

@ -0,0 +1,262 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper">
<resultMap type="org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo" id="ErpProjectPlanStageResult">
</resultMap>
<select id="selectCustomErpProjectPlanStageVoList" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
<!-- 根据ID查询详情 -->
<select id="selectCustomErpProjectPlanStageVoById" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time
from erp_project_plan_stage t
where t.plan_stage_id = #{planStageId}
</select>
<!-- 批量查询 - 根据ID列表 -->
<select id="selectCustomErpProjectPlanStageVoByIds" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time
from erp_project_plan_stage t
where t.plan_stage_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 统计查询 -->
<select id="countCustomErpProjectPlanStage" resultType="java.lang.Long">
select count(1) from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
<!-- 分页查询(带自定义条件) -->
<select id="selectCustomErpProjectPlanStageVoPage" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time
from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
<!-- 批量插入 -->
<insert id="batchInsertErpProjectPlanStage">
insert into erp_project_plan_stage(
tenant_id,
project_id,
project_plan_id,
project_phases,
plan_start_time,
plan_end_time,
collection_stage,
repayment_rate,
repayment_amount,
repayment_time,
delay_day,
receivable_date,
reasons_explanation,
schedule_remark,
real_start_time,
real_end_time,
sort_order,
remark,
active_flag,
del_flag,
create_dept,
create_by,
create_time,
update_by,
update_time
)
values
<foreach collection="list" item="item" separator=",">
(
#{item.tenantId},
#{item.projectId},
#{item.projectPlanId},
#{item.projectPhases},
#{item.planStartTime},
#{item.planEndTime},
#{item.collectionStage},
#{item.repaymentRate},
#{item.repaymentAmount},
#{item.repaymentTime},
#{item.delayDay},
#{item.receivableDate},
#{item.reasonsExplanation},
#{item.scheduleRemark},
#{item.realStartTime},
#{item.realEndTime},
#{item.sortOrder},
#{item.remark},
#{item.activeFlag},
#{item.delFlag},
#{item.createDept},
#{item.createBy},
#{item.createTime},
#{item.updateBy},
#{item.updateTime}
)
</foreach>
</insert>
<!-- 批量更新 -->
<update id="batchUpdateErpProjectPlanStage">
<foreach collection="list" item="item" separator=";">
update erp_project_plan_stage
<set>
<if test="item.tenantId != null and item.tenantId != ''">
tenant_id = #{item.tenantId},
</if>
<if test="item.projectId != null">
project_id = #{item.projectId},
</if>
<if test="item.projectPlanId != null">
project_plan_id = #{item.projectPlanId},
</if>
<if test="item.projectPhases != null and item.projectPhases != ''">
project_phases = #{item.projectPhases},
</if>
<if test="item.planStartTime != null">
plan_start_time = #{item.planStartTime},
</if>
<if test="item.planEndTime != null">
plan_end_time = #{item.planEndTime},
</if>
<if test="item.collectionStage != null and item.collectionStage != ''">
collection_stage = #{item.collectionStage},
</if>
<if test="item.repaymentRate != null">
repayment_rate = #{item.repaymentRate},
</if>
<if test="item.repaymentAmount != null">
repayment_amount = #{item.repaymentAmount},
</if>
<if test="item.repaymentTime != null">
repayment_time = #{item.repaymentTime},
</if>
<if test="item.delayDay != null">
delay_day = #{item.delayDay},
</if>
<if test="item.receivableDate != null">
receivable_date = #{item.receivableDate},
</if>
<if test="item.reasonsExplanation != null and item.reasonsExplanation != ''">
reasons_explanation = #{item.reasonsExplanation},
</if>
<if test="item.scheduleRemark != null and item.scheduleRemark != ''">
schedule_remark = #{item.scheduleRemark},
</if>
<if test="item.realStartTime != null">
real_start_time = #{item.realStartTime},
</if>
<if test="item.realEndTime != null">
real_end_time = #{item.realEndTime},
</if>
<if test="item.sortOrder != null">
sort_order = #{item.sortOrder},
</if>
<if test="item.remark != null and item.remark != ''">
remark = #{item.remark},
</if>
<if test="item.activeFlag != null and item.activeFlag != ''">
active_flag = #{item.activeFlag},
</if>
<if test="item.delFlag != null and item.delFlag != ''">
del_flag = #{item.delFlag},
</if>
<if test="item.createDept != null">
create_dept = #{item.createDept},
</if>
<if test="item.createBy != null">
create_by = #{item.createBy},
</if>
<if test="item.createTime != null">
create_time = #{item.createTime},
</if>
<if test="item.updateBy != null">
update_by = #{item.updateBy},
</if>
<if test="item.updateTime != null">
update_time = #{item.updateTime}
</if>
</set>
where plan_stage_id = #{item.planStageId}
</foreach>
</update>
<!-- 根据自定义条件删除 -->
<delete id="deleteCustomErpProjectPlanStage">
delete from erp_project_plan_stage
${ew.getCustomSqlSegment}
</delete>
<!-- 根据ID列表批量删除 -->
<delete id="deleteCustomErpProjectPlanStageByIds">
delete from erp_project_plan_stage
where plan_stage_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 检查是否存在 -->
<select id="existsErpProjectPlanStage" resultType="java.lang.Boolean">
select count(1) > 0 from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
</mapper>
Loading…
Cancel
Save