模块: 06-报价单管理
版本: v1.0
日期: 2025-10-03
关联文档:
- 需求文档:
docs/06-报价单管理模块需求.md- 原型图:
yuanxing/06-报价单管理原型图.md- 数据库:
sql/crm/06-crm_quote.sql
接口地址: GET /crm/quote/list
接口描述: 分页查询报价单列表,支持多条件筛选
权限标识: crm:quote:list
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | pageNum | Integer | 否 | 页码,默认1 | | pageSize | Integer | 否 | 每页条数,默认10 | | quoteNo | String | 否 | 报价单编号(模糊查询) | | quoteTitle | String | 否 | 报价单标题(模糊查询) | | customerId | Long | 否 | 客户ID | | customerName | String | 否 | 客户名称(模糊查询) | | opportunityId | Long | 否 | 商机ID | | status | String | 否 | 状态 | | ownerUserId | Long | 否 | 负责人ID | | minAmount | BigDecimal | 否 | 最小金额 | | maxAmount | BigDecimal | 否 | 最大金额 | | isLatest | Integer | 否 | 是否最新版本(0否 1是) | | quoteDateBegin | String | 否 | 报价日期开始 | | quoteDateEnd | String | 否 | 报价日期结束 | | beginTime | String | 否 | 创建开始时间 | | endTime | String | 否 | 创建结束时间 |
返回示例:
{
"code": 200,
"msg": "查询成功",
"rows": [
{
"id": 1,
"quoteNo": "QUO20250101001",
"quoteTitle": "华为CRM系统采购报价",
"customerId": 1,
"customerName": "华为技术有限公司",
"opportunityId": 1,
"contactId": 1,
"contactName": "张伟",
"contactMobile": "13800138000",
"contactEmail": "zhangwei@huawei.com",
"version": "V1.0",
"parentId": 0,
"isLatest": 1,
"totalAmount": 150000.00,
"discountRate": 10.00,
"discountAmount": 15000.00,
"finalAmount": 135000.00,
"validityDays": 30,
"quoteDate": "2025-01-10",
"expireDate": "2025-02-09",
"status": "submitted",
"pdfUrl": "/upload/quote/QUO20250101001.pdf",
"pdfGenerated": 1,
"shareLink": "https://crm.com/share/abc123",
"shareCode": "abc123",
"viewCount": 5,
"lastViewTime": "2025-01-12 10:30:00",
"ownerUserId": 1,
"ownerUserName": "张三",
"contractId": null,
"paymentTerms": "合同签订后7个工作日内支付30%预付款",
"deliveryTerms": "付款到账后15个工作日内完成部署",
"createTime": "2025-01-10 09:00:00",
"remark": ""
}
],
"total": 56
}
接口地址: GET /crm/quote/{id}
接口描述: 根据ID查询报价单详细信息
权限标识: crm:quote:query
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 报价单ID |
返回示例: 同1.1列表返回的单条数据,包含完整字段
接口地址: POST /crm/quote
接口描述: 新增报价单信息
权限标识: crm:quote:add
请求体:
{
"quoteNo": "QUO20250110001",
"quoteTitle": "华为CRM系统采购报价",
"customerId": 1,
"opportunityId": 1,
"contactId": 1,
"version": "V1.0",
"validityDays": 30,
"quoteDate": "2025-01-10",
"discountRate": 10.00,
"ownerUserId": 1,
"paymentTerms": "合同签订后7个工作日内支付30%预付款",
"deliveryTerms": "付款到账后15个工作日内完成部署",
"products": [
{
"productId": 1,
"quantity": 1,
"price": 12800.00,
"discount": 10.00
},
{
"productId": 2,
"quantity": 1,
"price": 138000.00,
"discount": 10.00
}
],
"remark": ""
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | quoteNo | String | 是 | 报价单编号,唯一,格式:QUO+yyyyMMdd+4位流水号 | | quoteTitle | String | 是 | 报价单标题,最大200字符 | | customerId | Long | 是 | 客户ID | | opportunityId | Long | 否 | 商机ID | | contactId | Long | 否 | 联系人ID | | version | String | 否 | 版本号,默认V1.0 | | validityDays | Integer | 否 | 有效期天数,默认30 | | quoteDate | String | 否 | 报价日期,默认当前日期 | | discountRate | BigDecimal | 否 | 整单折扣率(百分比) | | ownerUserId | Long | 否 | 负责人ID,默认当前用户 | | paymentTerms | String | 否 | 付款条款,最大500字符 | | deliveryTerms | String | 否 | 交付条款,最大500字符 | | products | Array | 是 | 产品列表,至少1个 | | remark | String | 否 | 备注,最大500字符 |
校验规则:
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1,
"quoteNo": "QUO20250110001"
}
}
接口地址: PUT /crm/quote
接口描述: 修改报价单信息
权限标识: crm:quote:edit
请求体: 同新增接口,但需要传入id
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: DELETE /crm/quote/{ids}
接口描述: 删除报价单(支持批量)
权限标识: crm:quote:remove
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 报价单ID数组 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: PUT /crm/quote/submit
接口描述: 提交报价单进行审批
权限标识: crm:quote:submit
请求体:
{
"id": 1,
"approverIds": [5, 6],
"remark": "提交审批"
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 报价单ID | | approverIds | Long[] | 是 | 审批人ID列表 | | remark | String | 否 | 提交说明 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: POST /crm/quote/generatePdf
接口描述: 生成报价单PDF文件
权限标识: crm:quote:edit
请求体:
{
"id": 1
}
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"pdfUrl": "/upload/quote/QUO20250110001.pdf"
}
}
接口地址: POST /crm/quote/generateShare
接口描述: 生成报价单分享链接
权限标识: crm:quote:share
请求体:
{
"id": 1,
"validityDays": 7
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 报价单ID | | validityDays | Integer | 否 | 链接有效期天数,默认7天 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"shareLink": "https://crm.com/share/abc123",
"shareCode": "abc123",
"expireDate": "2025-01-17"
}
}
接口地址: GET /crm/quote/share/{shareCode}
接口描述: 通过分享码查看报价单(无需登录)
权限标识: 无(公开接口)
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | shareCode | String | 是 | 分享码 |
业务规则:
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": {
"quoteNo": "QUO20250110001",
"quoteTitle": "华为CRM系统采购报价",
"customerName": "华为技术有限公司",
"contactName": "张伟",
"finalAmount": 135000.00,
"quoteDate": "2025-01-10",
"expireDate": "2025-02-09",
"pdfUrl": "/upload/quote/QUO20250110001.pdf",
"products": [],
"paymentTerms": "合同签订后7个工作日内支付30%预付款",
"deliveryTerms": "付款到账后15个工作日内完成部署"
}
}
接口地址: PUT /crm/quote/accept
接口描述: 客户接受报价单
权限标识: crm:quote:edit
请求体:
{
"id": 1,
"remark": "客户已接受"
}
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: PUT /crm/quote/reject
接口描述: 客户拒绝报价单
权限标识: crm:quote:edit
请求体:
{
"id": 1,
"rejectReason": "价格不合适",
"remark": ""
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 报价单ID | | rejectReason | String | 是 | 拒绝原因,最大500字符 | | remark | String | 否 | 备注 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: POST /crm/quote/toContract
接口描述: 将报价单转为合同
权限标识: crm:quote:toContract
请求体:
{
"id": 1,
"contractNo": "CON20250110001",
"contractTitle": "华为CRM系统采购合同",
"signDate": "2025-01-15",
"effectiveDate": "2025-01-15",
"expiryDate": "2026-01-14",
"remark": ""
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 报价单ID | | contractNo | String | 是 | 合同编号 | | contractTitle | String | 是 | 合同标题 | | signDate | String | 是 | 签订日期 | | effectiveDate | String | 是 | 生效日期 | | expiryDate | String | 是 | 到期日期 | | remark | String | 否 | 备注 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"contractId": 1,
"contractNo": "CON20250110001"
}
}
接口地址: POST /crm/quote/export
接口描述: 导出报价单数据到Excel
权限标识: crm:quote:export
请求体: 查询参数同1.1列表查询接口
返回: Excel文件流
接口地址: GET /crm/quote/product/list
接口描述: 查询指定报价单的产品列表
权限标识: crm:quote:query
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | quoteId | Long | 是 | 报价单ID |
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"quoteId": 1,
"productId": 1,
"productName": "CRM系统标准版",
"productNo": "PRD20250101001",
"categoryId": 11,
"categoryName": "CRM系统",
"model": "V5.4.0",
"unit": "套",
"quantity": 1,
"price": 12800.00,
"discount": 10.00,
"subtotal": 11520.00,
"description": "包含客户管理、销售管理等基础功能",
"sort": 1,
"remark": ""
}
]
}
接口地址: POST /crm/quote/product
接口描述: 向报价单添加产品
权限标识: crm:quote:edit
请求体:
{
"quoteId": 1,
"productId": 1,
"quantity": 1,
"price": 12800.00,
"discount": 10.00,
"description": "包含客户管理、销售管理等基础功能",
"remark": ""
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | quoteId | Long | 是 | 报价单ID | | productId | Long | 是 | 产品ID | | quantity | Integer | 是 | 数量,必须大于0 | | price | BigDecimal | 是 | 单价,保留2位小数 | | discount | BigDecimal | 否 | 折扣百分比,默认0 | | description | String | 否 | 产品描述,最大1000字符 | | remark | String | 否 | 备注 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: PUT /crm/quote/product
接口描述: 修改报价单产品信息
权限标识: crm:quote:edit
请求体: 同添加接口,但需要传入id
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: DELETE /crm/quote/product/{ids}
接口描述: 删除报价单产品(支持批量)
权限标识: crm:quote:edit
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 报价单产品ID数组 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: GET /crm/quote/approval/list
接口描述: 查询指定报价单的审批记录列表
权限标识: crm:quote:query
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | quoteId | Long | 是 | 报价单ID |
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"quoteId": 1,
"quoteNo": "QUO20250110001",
"step": 1,
"approverId": 5,
"approverName": "王经理",
"approvalResult": "approved",
"approvalOpinion": "同意",
"approvalTime": "2025-01-11 10:00:00",
"createTime": "2025-01-10 16:00:00",
"remark": ""
}
]
}
接口地址: POST /crm/quote/approval
接口描述: 审批人审批报价单
权限标识: crm:quote:approval
请求体:
{
"id": 1,
"approvalResult": "approved",
"approvalOpinion": "同意通过",
"remark": ""
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 审批记录ID | | approvalResult | String | 是 | 审批结果:approved/rejected | | approvalOpinion | String | 否 | 审批意见,文本类型 | | remark | String | 否 | 备注 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: PUT /crm/quote/approval/withdraw
接口描述: 撤回已提交的审批
权限标识: crm:quote:edit
请求体:
{
"id": 1,
"remark": "需要修改报价"
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 报价单ID | | remark | String | 否 | 撤回原因 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功"
}
接口地址: GET /crm/quote/versions
接口描述: 查询报价单的所有版本
权限标识: crm:quote:query
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | quoteNo | String | 是 | 报价单编号(首版) |
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"quoteNo": "QUO20250110001",
"version": "V1.0",
"finalAmount": 135000.00,
"status": "rejected",
"isLatest": 0,
"createTime": "2025-01-10 09:00:00"
},
{
"id": 2,
"quoteNo": "QUO20250110001",
"version": "V1.1",
"finalAmount": 128000.00,
"status": "accepted",
"isLatest": 1,
"createTime": "2025-01-12 14:00:00"
}
]
}
接口地址: POST /crm/quote/newVersion
接口描述: 基于现有报价单创建新版本
权限标识: crm:quote:add
请求体:
{
"id": 1,
"version": "V1.1",
"remark": "根据客户反馈调整价格"
}
请求参数说明: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 原报价单ID | | version | String | 是 | 新版本号,如V1.1, V2.0 | | remark | String | 否 | 版本说明 |
业务规则:
返回示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 2,
"quoteNo": "QUO20250110001",
"version": "V1.1"
}
}
接口地址: GET /crm/quote/statistics/overview
接口描述: 获取报价单统计概览数据
权限标识: crm:quote:list
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ownerUserId | Long | 否 | 负责人ID,不传则查询当前用户 | | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 |
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": {
"totalCount": 56,
"draftCount": 8,
"submittedCount": 12,
"acceptedCount": 28,
"rejectedCount": 5,
"expiredCount": 3,
"totalAmount": 4580000.00,
"acceptedAmount": 2850000.00,
"acceptRate": 73.68,
"avgAmount": 81785.71
}
}
接口地址: GET /crm/quote/statistics/status
接口描述: 按状态统计报价单分布情况
权限标识: crm:quote:list
请求参数: 无
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": [
{
"status": "draft",
"statusName": "草稿",
"count": 8,
"amount": 420000.00,
"percent": 14.29
},
{
"status": "accepted",
"statusName": "已接受",
"count": 28,
"amount": 2850000.00,
"percent": 50.00
}
]
}
接口地址: GET /crm/quote/statistics/trend
接口描述: 分析报价单数量和金额趋势
权限标识: crm:quote:list
请求参数: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | type | String | 否 | 统计类型:month/quarter/year,默认month | | beginTime | String | 否 | 开始时间 | | endTime | String | 否 | 结束时间 |
返回示例:
{
"code": 200,
"msg": "查询成功",
"data": [
{
"period": "2025-01",
"totalCount": 18,
"acceptedCount": 12,
"totalAmount": 1250000.00,
"acceptedAmount": 850000.00,
"acceptRate": 66.67
}
]
}
public class CrmQuoteBo extends BaseEntity {
/** 主键ID */
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
private Long id;
/** 报价单编号 */
@NotBlank(message = "报价单编号不能为空", groups = { AddGroup.class, EditGroup.class })
private String quoteNo;
/** 报价单标题 */
@NotBlank(message = "报价单标题不能为空", groups = { AddGroup.class, EditGroup.class })
private String quoteTitle;
/** 客户ID */
@NotNull(message = "客户ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long customerId;
/** 商机ID */
private Long opportunityId;
/** 联系人ID */
private Long contactId;
/** 版本号 */
private String version;
/** 父版本ID */
private Long parentId;
/** 整单折扣率 */
private BigDecimal discountRate;
/** 有效期天数 */
@Min(value = 1, message = "有效期天数必须大于0")
private Integer validityDays;
/** 报价日期 */
private String quoteDate;
/** 负责人ID */
private Long ownerUserId;
/** 付款条款 */
private String paymentTerms;
/** 交付条款 */
private String deliveryTerms;
/** 产品列表 */
@NotEmpty(message = "产品列表不能为空", groups = { AddGroup.class })
private List<CrmQuoteProductBo> products;
/** 备注 */
private String remark;
}
public class CrmQuoteVo implements Serializable {
/** 主键ID */
@ExcelProperty(value = "ID")
private Long id;
/** 报价单编号 */
@ExcelProperty(value = "报价单编号")
private String quoteNo;
/** 报价单标题 */
@ExcelProperty(value = "报价单标题")
private String quoteTitle;
/** 客户ID */
private Long customerId;
/** 客户名称 */
@ExcelProperty(value = "客户名称")
private String customerName;
/** 商机ID */
private Long opportunityId;
/** 联系人ID */
private Long contactId;
/** 联系人姓名 */
@ExcelProperty(value = "联系人")
private String contactName;
/** 联系人手机 */
private String contactMobile;
/** 联系人邮箱 */
private String contactEmail;
/** 版本号 */
@ExcelProperty(value = "版本号")
private String version;
/** 父版本ID */
private Long parentId;
/** 是否最新版本 */
private Integer isLatest;
/** 总金额 */
@ExcelProperty(value = "总金额")
private BigDecimal totalAmount;
/** 折扣率 */
@ExcelProperty(value = "折扣率")
private BigDecimal discountRate;
/** 折扣金额 */
@ExcelProperty(value = "折扣金额")
private BigDecimal discountAmount;
/** 最终金额 */
@ExcelProperty(value = "最终金额")
private BigDecimal finalAmount;
/** 有效期天数 */
@ExcelProperty(value = "有效期(天)")
private Integer validityDays;
/** 报价日期 */
@ExcelProperty(value = "报价日期")
private String quoteDate;
/** 到期日期 */
@ExcelProperty(value = "到期日期")
private String expireDate;
/** 状态 */
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "crm_quote_status")
private String status;
/** 拒绝原因 */
private String rejectReason;
/** PDF文件路径 */
private String pdfUrl;
/** PDF是否已生成 */
private Integer pdfGenerated;
/** 分享链接 */
private String shareLink;
/** 分享码 */
private String shareCode;
/** 查看次数 */
@ExcelProperty(value = "查看次数")
private Integer viewCount;
/** 最后查看时间 */
private LocalDateTime lastViewTime;
/** 负责人ID */
private Long ownerUserId;
/** 负责人姓名 */
@ExcelProperty(value = "负责人")
private String ownerUserName;
/** 关联合同ID */
private Long contractId;
/** 付款条款 */
private String paymentTerms;
/** 交付条款 */
private String deliveryTerms;
/** 创建时间 */
@ExcelProperty(value = "创建时间")
private LocalDateTime createTime;
/** 备注 */
@ExcelProperty(value = "备注")
private String remark;
}
| 字典值 | 字典标签 | 说明 |
|---|---|---|
| draft | 草稿 | 编辑中 |
| submitted | 已提交 | 已提交审批 |
| accepted | 已接受 | 客户已接受 |
| rejected | 已拒绝 | 客户已拒绝 |
| expired | 已过期 | 超过有效期 |
| contract | 已转合同 | 已生成合同 |
| 权限标识 | 说明 |
|---|---|
| crm:quote:list | 报价单列表查询 |
| crm:quote:query | 报价单详情查询 |
| crm:quote:add | 报价单新增 |
| crm:quote:edit | 报价单修改 |
| crm:quote:remove | 报价单删除 |
| crm:quote:export | 报价单导出 |
| crm:quote:submit | 报价单提交审批 |
| crm:quote:approval | 报价单审批 |
| crm:quote:share | 生成分享链接 |
| crm:quote:toContract | 转为合同 |
文档结束