- W26: NestJS API + Next.js Web + Prisma + SQLite scaffold - W26: Lead 模型 + Crawler + 询价发布助手 (线索池 + 一键发布) - W29.x: MCP 集成 (Integration 模型 + connectMcp + publish_rfq 5 工具端到端跑通) - W30: 3 字段补充 (notes / quotationType / quotationDemand) - W31 P1: 自动填 enterpriseId / userId (Prisma companyUserId 字段 + get_app_identity tool + lead.service.ts publishArgs) - W31: detail 详情页 + admin UI 集成管理 (OpenAppListView + AuditLogListView) 关联: ~/Documents/02-平台开发/产品开发/F002-W31-交接文档.md GIT-AUDIT-REPORT-2026-06-24.md
205 lines
8.2 KiB
Markdown
205 lines
8.2 KiB
Markdown
# 需求:F002 MCP publish_rfq 补全商务字段
|
||
|
||
**提出方**:平台助手(nest-api)
|
||
**接收方**:devbox 产品网络(renren-supplier-server)
|
||
**优先级**:P1
|
||
**时间**:2026-06-22
|
||
|
||
## 一、背景
|
||
|
||
平台助手正在用 MCP 协议替换旧的 Playwright GUI 流程(`direv-publish` skill),自动把抓取的招标线索发布到 B2B 平台。当前 MCP `publish_rfq` tool(对应 `supplier/inquiry/publish` 接口)只设了 5 个字段,**丢失了 11 个关键商务字段**,导致发布的询价质量远低于旧 GUI 流程。
|
||
|
||
## 二、当前 F002 publish 实现的问题
|
||
|
||
`renren-supplier-server` 的 `InquiryServiceImpl.publish()` 当前只设了这些字段:
|
||
|
||
| ✅ 已设 | ❌ 未设(旧 GUI 流程里有) |
|
||
|--------|------------------------|
|
||
| `title` | `inquiryValidDate`(截止日期)|
|
||
| `note`(来自 description)| `deliverDate`(要求交货日期)|
|
||
| `purchaseQuantity` | `shippingAddress`(收货地址)|
|
||
| `userId` | `contactName`(联系人)|
|
||
| `inquiryEnterpriseId` | `contactPhone`(联系电话)|
|
||
| `inquiryEnterpriseName` | `freightFlag`(报价含运费)|
|
||
| `orderId` | `paymentMethod`(付款方式)|
|
||
| `publishDate` | `invoiceType`(开票要求)|
|
||
| `quotationType` | `quotationDemand`(报价要求)|
|
||
| `apprStatus` | `name`/`mobile`(询价人姓名/电话)|
|
||
| `auditDate` | `inquiryParty`(询价主体)|
|
||
| `urls`(附件)| `procurementType`(采购类型)|
|
||
|
||
**对比**:旧 GUI 流程有 18 个字段 + 商品封面图。
|
||
|
||
## 三、需求:补全 11 个核心商务字段
|
||
|
||
### 3.1 MCP `publish_rfq` tool schema 升级
|
||
|
||
在 `product_network_mcp/src/tools/inquiry.ts` 的 `publish_rfq` zod schema 里增加:
|
||
|
||
```typescript
|
||
{
|
||
title: z.string(),
|
||
description: z.string().optional(),
|
||
qty: z.number().positive().optional(),
|
||
// ===== 新增字段 =====
|
||
deadline: z.string().optional().describe("询价截止日期 YYYY-MM-DD(映射 inquiryValidDate)"),
|
||
deliveryDate: z.string().optional().describe("要求交货日期 YYYY-MM-DD(映射 deliverDate)"),
|
||
shippingAddress: z.string().optional().describe("收货地址(映射 shippingAddress)"),
|
||
contactName: z.string().optional().describe("联系人(映射 contactName)"),
|
||
contactPhone: z.string().optional().describe("联系电话(映射 contactPhone)"),
|
||
freightFlag: z.enum(["含运费", "不含运费"]).optional().describe("报价是否含运费"),
|
||
paymentMethod: z.string().optional().describe("付款方式名称,如 货到付款(映射 paymentMethod 字典)"),
|
||
invoiceType: z.enum(["增值税专票", "增值税普票", "不开发票"]).optional().describe("开票要求(1/2/3)"),
|
||
procurementType: z.string().optional().describe("采购类型:定量采购/议价采购(映射 procurementType 字典)"),
|
||
inquiryParty: z.string().optional().describe("询价主体(公司名,如 郑州巨变网络科技有限公司)"),
|
||
// ===== 现有字段保留 =====
|
||
userId: z.number().optional(),
|
||
enterpriseId: z.number().optional(),
|
||
enterpriseName: z.string().optional(),
|
||
attachments: z.array(z.string()).optional(),
|
||
}
|
||
```
|
||
|
||
### 3.2 Java 后端 `InquiryServiceImpl.publish()` 升级
|
||
|
||
`renren-supplier-server/src/main/java/io/renren/service/impl/InquiryServiceImpl.java`
|
||
|
||
**当前实现**(F002 简化版)只设了 6 个字段,需要补:
|
||
|
||
```java
|
||
public Result<Map<String, Object>> publish(Map<String, Object> params) {
|
||
InquiryEntity inquiryEntity = new InquiryEntity();
|
||
|
||
// ===== 已有字段 =====
|
||
inquiryEntity.setTitle((String) params.get("title"));
|
||
inquiryEntity.setNote((String) params.get("description"));
|
||
// qty / userId / enterpriseId / enterpriseName / urls / 系统字段...
|
||
|
||
// ===== 新增字段映射 =====
|
||
|
||
// 截止日期(YYYY-MM-DD 字符串 → Date)
|
||
String deadline = (String) params.get("deadline");
|
||
if (StringUtils.isNotBlank(deadline)) {
|
||
inquiryEntity.setInquiryValidDate(DateUtil.parse(deadline, "yyyy-MM-dd"));
|
||
}
|
||
|
||
// 要求交货日期
|
||
String deliveryDate = (String) params.get("deliveryDate");
|
||
if (StringUtils.isNotBlank(deliveryDate)) {
|
||
inquiryEntity.setDeliverDate(DateUtil.parse(deliveryDate, "yyyy-MM-dd"));
|
||
}
|
||
|
||
// 收货地址
|
||
String shippingAddress = (String) params.get("shippingAddress");
|
||
if (StringUtils.isNotBlank(shippingAddress)) {
|
||
inquiryEntity.setShippingAddress(shippingAddress);
|
||
}
|
||
|
||
// 联系人/电话
|
||
String contactName = (String) params.get("contactName");
|
||
if (StringUtils.isNotBlank(contactName)) {
|
||
inquiryEntity.setContactName(contactName);
|
||
}
|
||
String contactPhone = (String) params.get("contactPhone");
|
||
if (StringUtils.isNotBlank(contactPhone)) {
|
||
inquiryEntity.setContactPhone(contactPhone);
|
||
}
|
||
|
||
// 询价主体
|
||
String inquiryParty = (String) params.get("inquiryParty");
|
||
if (StringUtils.isNotBlank(inquiryParty)) {
|
||
inquiryEntity.setInquiryParty(inquiryParty);
|
||
}
|
||
|
||
// 报价含运费(0=不含/1=含)
|
||
String freightFlag = (String) params.get("freightFlag");
|
||
if ("含运费".equals(freightFlag)) {
|
||
inquiryEntity.setFreightFlag("1");
|
||
} else if ("不含运费".equals(freightFlag)) {
|
||
inquiryEntity.setFreightFlag("0");
|
||
}
|
||
|
||
// 采购类型(字典映射:定量采购/议价采购 → procurementType 枚举值)
|
||
// 需要确认现有字典值
|
||
|
||
// 付款方式(字符串 → paymentMethod 字典 ID,需要查 supplier-server 的字典表)
|
||
// 建议:先按字符串存,Java 后端查表映射
|
||
|
||
// 发票要求(1/2/3)
|
||
String invoiceType = (String) params.get("invoiceType");
|
||
if ("增值税专票".equals(invoiceType)) {
|
||
inquiryEntity.setInvoiceType(1);
|
||
} else if ("增值税普票".equals(invoiceType)) {
|
||
inquiryEntity.setInvoiceType(2);
|
||
} else if ("不开发票".equals(invoiceType)) {
|
||
inquiryEntity.setInvoiceType(3);
|
||
}
|
||
|
||
// ... 系统字段保持不变
|
||
insert(inquiryEntity);
|
||
|
||
// 返回不变
|
||
Map<String, Object> result = new HashMap<>();
|
||
result.put("rfqId", inquiryEntity.getId());
|
||
result.put("orderId", orderId);
|
||
result.put("status", "published");
|
||
return new Result<Map<String, Object>>().ok(result);
|
||
}
|
||
```
|
||
|
||
## 四、验收标准
|
||
|
||
升级后,平台助手通过 MCP `publish_rfq` 发布一条询价,在 B2B 平台 `list_my_rfqs` 接口查询时,能看到以下字段都正确填充:
|
||
|
||
- ✅ `note`(备注)
|
||
- ✅ `purchaseQuantity`(数量)
|
||
- ✅ `inquiryValidDate`(截止日期,非 null)
|
||
- ✅ `deliverDate`(交货日期,非 null)
|
||
- ✅ `shippingAddress`(收货地址)
|
||
- ✅ `contactName`(联系人)
|
||
- ✅ `contactPhone`(电话)
|
||
- ✅ `inquiryParty`(询价主体)
|
||
- ✅ `freightFlag`(运费标识)
|
||
- ✅ `invoiceType`(发票类型)
|
||
- ✅ `quotationType`(报价方式)
|
||
|
||
## 五、不在本次升级范围
|
||
|
||
下列字段有特殊复杂度,**不在本次升级中处理**:
|
||
|
||
- ❌ `match_category` 智能匹配(API 暂未实现,等 devbox 后端补齐)
|
||
- ❌ 商品封面图(MCP 无对应机制,旧 GUI 用 AI 生图,新 MCP 不支持)
|
||
- ❌ 多商品(询价单 → 询价明细 1:N,旧 GUI 是单商品)
|
||
|
||
## 六、测试用例
|
||
|
||
升级后请用以下 payload 测试:
|
||
|
||
```json
|
||
{
|
||
"title": "【测试】新疆水泥采购 100 吨",
|
||
"description": "P.O 42.5 普通硅酸盐水泥",
|
||
"qty": 100,
|
||
"deadline": "2026-12-31",
|
||
"deliveryDate": "2027-01-30",
|
||
"shippingAddress": "新疆乌鲁木齐市新市区XX路XX号",
|
||
"contactName": "郑钊",
|
||
"contactPhone": "15532027557",
|
||
"freightFlag": "含运费",
|
||
"paymentMethod": "货到付款",
|
||
"invoiceType": "增值税专票",
|
||
"inquiryParty": "郑州巨变网络科技有限公司",
|
||
"attachments": ["https://example.com/notice.pdf"]
|
||
}
|
||
```
|
||
|
||
调用 `list_my_rfqs` 验证上述字段都被持久化。
|
||
|
||
## 七、平台助手这边的改动(已完成)
|
||
|
||
✅ Lead 模型已加 4 个新字段:`quantity`、`unit`、`regionDetail`、`attachments`
|
||
✅ `publishToDirev` 参数拼接逻辑已改:只传 schema 接受的字段(不传 unknown 字段)
|
||
✅ 端到端验证:当前新 schema 下能成功创建询价并拿到真 rfqId
|
||
|
||
待 devbox 升级 schema 后,平台助手这边只需把新参数加进 `publishToDirev` 的 `publishArgs` 对象即可,无需改 schema/迁移数据。
|