diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml
index c54b61c89..b905bf6da 100644
--- a/yudao-module-crm/yudao-module-crm-biz/pom.xml
+++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml
@@ -27,6 +27,11 @@
yudao-module-crm-api
${revision}
+
+ cn.iocoder.boot
+ yudao-module-bpm-api
+ ${revision}
+
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
index c2935184f..7f2541ae7 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
@@ -140,4 +140,12 @@ public class CrmContractController {
return success(true);
}
+ @PutMapping("/approve")
+ @Operation(summary = "发起合同审批流程")
+ @PreAuthorize("@ss.hasPermission('crm:contract:update')")
+ public CommonResult transfer(@RequestParam("id") Long id) {
+ contractService.handleApprove(id, getLoginUserId());
+ return success(true);
+ }
+
}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java
index e495bbfa5..607aa08f5 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java
@@ -7,10 +7,13 @@ import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFu
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
+import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -35,10 +38,6 @@ public class CrmContractSaveReqVO {
@DiffLogField(name = "商机", function = CrmBusinessParseFunction.NAME)
private Long businessId;
- @Schema(description = "工作流编号", example = "1043")
- @DiffLogField(name = "工作流编号")
- private Long processInstanceId;
-
@Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED)
@DiffLogField(name = "下单日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -86,16 +85,30 @@ public class CrmContractSaveReqVO {
@DiffLogField(name = "公司签约人", function = SysAdminUserParseFunction.NAME)
private Long signUserId;
- @Schema(description = "最后跟进时间")
- @DiffLogField(name = "最后跟进时间")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private LocalDateTime contactLastTime;
-
@Schema(description = "备注", example = "你猜")
@DiffLogField(name = "备注")
private String remark;
- // TODO @dhb52:增加一个 status 字段:具体有哪些值,你来枚举下;主要页面上有个【草稿】【提交审核】的流程,可以看看。然后要对接工作流,这块也可以看看,不确定的地方问我。
+ @Schema(description = "产品列表")
+ private List productItems;
+ @Schema(description = "商品属性")
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class CrmContractProductItem {
+
+ @Schema(description = "产品编号", example = "20529")
+ @NotNull(message = "产品编号不能为空")
+ private Long id;
+
+ @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
+ @NotNull(message = "产品数量不能为空")
+ private Long count;
+
+ @Schema(description = "产品折扣")
+ private Integer discountPercent;
+
+ }
}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
index b1275f4c5..83121dbdd 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
@@ -2,13 +2,12 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
+import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
-import java.math.BigDecimal;
-
/**
* 商机产品关联表 DO
*
@@ -29,14 +28,12 @@ public class CrmBusinessProductDO extends BaseDO {
*/
@TableId
private Long id;
-
/**
* 商机编号
*
* 关联 {@link CrmBusinessDO#getId()}
*/
private Long businessId;
-
/**
* 产品编号
*
@@ -50,29 +47,27 @@ public class CrmBusinessProductDO extends BaseDO {
private Integer price;
/**
- * 销售价格
+ * 销售价格, 单位:分
*/
- private BigDecimal salesPrice;
-
+ private Integer salesPrice;
/**
* 数量
*/
- private BigDecimal count;
-
- // TODO @lzxhqs:改成 discountPercent
+ private Integer count;
/**
* 折扣
*/
- private BigDecimal discountPercent;
-
- // TODO @lzxhqs:改成 totalPrice;总计价格,和现有项目风格一致;
+ private Integer discountPercent;
/**
- * 小计(折扣后价格)
+ * 总计价格(折扣后价格)
*/
- private BigDecimal totalPrice;
+ private Integer totalPrice;
/**
* 单位
+ *
+ * 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT}
*/
- private String unit;
+ private Integer unit;
+
}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java
index bdaff7271..e70e7a3cb 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java
@@ -45,7 +45,7 @@ public class CrmContractDO extends BaseDO {
/**
* 工作流编号
*/
- private Long processInstanceId;
+ private String processInstanceId;
/**
* 下单日期
*/
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
index a4ac3d3d7..6523782dd 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.crm.dal.dataobject.product;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -38,7 +39,7 @@ public class CrmProductDO extends BaseDO {
/**
* 单位
*
- * 字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_PRODUCT_UNIT}
+ * 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT}
*/
private Integer unit;
/**
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
index f4e33dfa0..a3e631201 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
@@ -41,7 +41,7 @@ public interface CrmContractMapper extends BaseMapperX {
default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) {
MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
// 拼接数据权限的查询条件
- CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(),
+ CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTRACT.getType(),
CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
// 拼接自身的查询条件
mpjLambdaWrapperX.selectAll(CrmContractDO.class)
@@ -56,7 +56,7 @@ public interface CrmContractMapper extends BaseMapperX {
default List selectBatchIds(Collection ids, Long userId) {
MPJLambdaWrapperX query = new MPJLambdaWrapperX<>();
// 构建数据权限连表条件
- CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
+ CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), ids, userId);
// 拼接自身的查询条件
query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId);
return selectJoinList(CrmContractDO.class, query);
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
index 6695e4f5d..9847af328 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
@@ -57,6 +57,14 @@ public interface CrmContractService {
*/
void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO);
+ /**
+ * 发起合同审批流程
+ *
+ * @param id 合同编号
+ * @param userId 用户编号
+ */
+ void handleApprove(Long id, Long userId);
+
/**
* 获得合同
*
@@ -111,9 +119,11 @@ public interface CrmContractService {
Long getContractCountByCustomerId(Long customerId);
/**
- * 根据商机ID获取关联客户的合同数量 TODO @lzxhqs:1)方法注释,和参数注释之间要有空行;2)中英文之间有空格,更清晰,例如说 商机 ID
- * @param businessId 商机ID
+ * 根据商机ID获取关联客户的合同数量
+ *
+ * @param businessId 商机编号
* @return 数量
*/
Long selectCountByBusinessId(Long businessId);
+
}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
index 1f1561f9b..5e83eccb0 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
+import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
@@ -13,6 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService;
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
@@ -40,28 +43,33 @@ import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
@Validated
public class CrmContractServiceImpl implements CrmContractService {
+ public static final String CONTRACT_APPROVE = "contract-approve"; // 合同审批流程标识
+
@Resource
private CrmContractMapper contractMapper;
@Resource
private CrmPermissionService crmPermissionService;
+ @Resource
+ private CrmBusinessProductService businessProductService;
+
+ @Resource
+ private BpmProcessInstanceApi bpmProcessInstanceApi;
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}",
success = CRM_CONTRACT_CREATE_SUCCESS)
public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) {
- createReqVO.setId(null);
// TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
// 插入合同
- CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class);
+ CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null);
contractMapper.insert(contract);
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
.setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId())
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
-
// 4. 记录操作日志上下文
LogRecordContext.putVariable("contract", contract);
return contract.getId();
@@ -141,6 +149,16 @@ public class CrmContractServiceImpl implements CrmContractService {
contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class).setId(contractUpdateFollowUpReqBO.getBizId()));
}
+ @Override
+ public void handleApprove(Long id, Long userId) {
+ // 创建合同审批流程实例
+ String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
+ .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id)));
+
+ // 更新合同工作流编号
+ contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId));
+ }
+
//======================= 查询相关 =======================
@Override
@@ -182,6 +200,5 @@ public class CrmContractServiceImpl implements CrmContractService {
public Long selectCountByBusinessId(Long businessId) {
return contractMapper.selectCountByBusinessId(businessId);
}
-
// TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
}