You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

9.8 KiB

crm-project(A5 项目管理)API-SUMMARY

对称 .scratch/customer-module/API-SUMMARY.md 形态;随票增量登记,票 18 做全量核对。 契约权威:.scratch/crm-project-wayfinding/deliverable-spec.md;实现:crm-projectcom.crm.project)。

0. 通用约定

  • 鉴权 Bearer(Authorization: Bearer <token>),响应信封 Result<T> = {code, success, message, data}code=0 成功。
  • 分页:入参 BaseParamcurrent/size/keyword/orderBy/asc)→ 出参 PageResult<T> = {content,total,size,current,pages,empty}
  • 雪花 id Long 序列化为字符串收发。
  • 风格遵 ADR-0017:POST 写(表单绑定,禁 @RequestBody)、GET 读(query 参数);禁 @PathVariable/@PutMapping/@DeleteMapping。Entity 不出 Controller,deleted 不出参。
  • 深 tag 遵 ADR-0024:一级 = A5 项目管理;页面目录 = 项目管理(看板视图)/项目管理(分屏视图)/项目管理(列表视图)/我的项目/项目详情/项目建档(详情页对应原型 a5-1-2-1 页签详情,v29 树一行索引未展开,拍板记录于票仓 README Decisions)。
  • 数据权限:@DataScope(module="project", ownerColumn="owner_user_id", deptColumn="owner_dept_id")(module 已由 crm-auth DataInitializer 内置 seed)。
  • 错误码段:68xxx(ProjectConstants)。

1. 错误码总表(68xxx,ProjectConstants

常量 含义
68001 CODE_PROJECT_INVALID 项目入参非法(参数缺失/客户目录校验不过/冲突拦截)
68002 CODE_PROJECT_NOT_EXIST 项目不存在或已被删除
68003 CODE_PROJECT_LOCKED 当前状态/终态锁不允许此操作(结项/已关闭/赢单锁死)
68004 CODE_STAGE_TRANSITION_INVALID 非法阶段迁移(越级/方向错误/非 3→5 连跳)
68005 CODE_ROLLBACK_FORBIDDEN 阶段回退权限不足(仅管理员+销售总监)
68006 CODE_ROLLBACK_TARGET_INVALID 回退目标非法(不在已过节点/低于 stage1 下限)
68007 CODE_SCHEME_CARD_MISMATCH 方案卡校验失败(不存在/归属或客户与项目不符)
68008 CODE_CONFLICT_RELEASE_INVALID 冲突解除(报备审核回填)条件不满足(非 stage0 等)
68009 CODE_BID_RESULT_INVALID 赢/输标记条件不满足(非 stage5/已标记)
66015 (crm-opportunity)CODE_SCHEME_CARD_PROJECT_PORT_UNWIRED PROJECT 归属方案卡校验桩未接线——A5 部署后由真实现覆盖,正常不可再见
66007/66008/66009/66010 (crm-opportunity)方案卡族 A5 建档经 OpportunitySchemeCardService 读卡时可能透出(66008 已在 create 翻译为 68007)

2. 接口清单(按页面/子域,随票增量)

2.1 项目建档(票 02)

方法 路径 说明 入参
POST /api/project/create 独立建项目(本期唯一可达建项目入口) projectName* / customerId* / schemeCardId* / sourceOppId / projectAmount / regionCode / brand

行为要点:客户必填目录选(CustomerCatalogPort.requireLive,归档/缺失拒绝);方案卡必填且卡客户=项目客户;PROJECT 归属卡不得重复绑定他项目;冲突检测留桩恒无冲突;落库 stage=0/status=1/filing_status=1/bid_result=0;owner 三列取操作人快照(操作人=初始负责人);写两条动态(CREATE + FILING_SUBMIT)。出参 data = 项目 id。

2.2 项目详情(票 02)

方法 路径 说明 入参
GET /api/project/detail 详情主档 + 头部 id*

出参 ProjectDTO 全量(阶段专属扩展列组仅 detail 回显);阶段名回显 = 字典名(project_stage 分组)→ 枚举名兜底,别名优先接入点归票 13;客户名经 CustomerCatalogPort 回显(客户已归档时留空不阻断)。

2.3 项目列表(票 03)

方法 路径 说明 入参
GET /api/project/list 列表+分屏共用 scope*(manage/mine)/ stage(0~6 七值,越界 68001)/ filingStatus(0~3 独立筛)/ keyword(项目名模糊)/ current / size / orderBy / asc

行为要点:manage 走 @DataScope 部门天花板(拦截器按实体注解注入,本模块代码不加条件);mine 显式 owner_user_id=当前用户;默认 createTime 倒序;行回显轴展示名 + 客户名(CustomerCatalogPort,客户归档留空)。「报备中」不是阶段值(原型混轴笔误,grill#10)。

2.4 项目看板(票 04)

方法 路径 说明 入参
GET /api/project/board 看板聚合 scope*

出参 ProjectBoardDTO:固定 7 列(stage 0~6 全画,空列 count=0)+ 每列计数与卡片 + conflictPendingCount badge(=stage0 数);stage0 卡 conflictActionAvailable(审核中可解除/驳回可再审);赢单停 stage5、stage6 仅输单(状态机保证);列头阶段名走「别名优先→字典名→枚举名」回退(别名票 13)。

2.5 状态机动作(票 05–08)

方法 路径 说明 入参
POST /api/project/stage/advance 推进(逐级 +1;stage3 skipBidding=true 唯一连跳 3→5) id* / skipBidding(默认 false)
GET /api/project/stage/rollback-targets 回退可选节点(弹窗数据源;stage0 空=置灰) id*
POST /api/project/stage/rollback 多步回退(仅管理员+销售总监;三终态锁) id* / targetStage*
POST /api/project/close 关闭(任意 stage → status=2,记因四要素) id* / closeType* / closeReason / closeRemark
POST /api/project/bid-result/mark 标记赢单(1)/输单(2)(stage5 专用分叉) id* / bidResult*
POST /api/project/filing/review 冲突解除=报备审核回填(通过双写 filing=2+stage 0→1;驳回 filing=3 停 stage0 可再审) id* / approved* / remark

行为要点:全部写端点动态留痕(推进/回退/冲突解除带结构化 from/to 阶段);状态落库 @Version CAS(并发变化 68003);回退授权 = 内置 ROLE_ADMIN ∨ crm_auth_user.title=销售总监(DefaultProjectRollbackAuthorizer,无独立销售总监角色 code——拍板记 README Decisions);回退可选节点由项目动态阶段迁移留痕投影(3→5 连跳跳过的 stage4 不在列);赢输标记仅 stage5 未标记态,赢单锁死(回退 68003)、输单 stage6/status=3 终态。

2.6 详情 Tab(票 09–11)

通用 Tab(项目自建子表;文件本体走 crm-file):

方法 路径 说明 入参
GET /api/project/follow/list 跟进记录分页(时间倒序) projectId* / current / size
POST /api/project/follow/add 新增跟进(写动态 FOLLOW_ADD) projectId* / followContent* / followTime*(yyyy-MM-dd HH:mm:ss) / followWay
GET /api/project/attachment/list 附件列表 projectId* / bizType(PROJECT/FOLLOW_UP)
POST /api/project/attachment/add 新增附件(fileId 先经 crm-file 上传) projectId* / fileId* / bizType* / bizId / materialType / remark
POST /api/project/attachment/delete 删除附件(软删) id*
GET /api/project/customer/list 关联客户(一项目一客户;目录字段) projectId*
GET /api/project/timeline/list 项目动态投影读(倒序分页,全事件) projectId* / current / size

阶段专属 Tab(全读 crm_project 主表扩展列,零阶段子表):

方法 路径 出参
GET /api/project/scheme schemeBudget / schemeVersion / schemeTaskStatus
GET /api/project/quote quoteTotal / quoteStatus(清单明细行不落 CRM)
GET /api/project/bidding bidDeadline / bidBudget / brandControl / bidBaseType / bidBaseTypeName(票13) / allocRatio / bidBond / bidFileId / bidderName(投标主体一对一本期)
GET /api/project/bid-open bidOpenTime / bidOpenPlace / bidAwardMethod / bidAwardAmount / bidResult / bidResultName / bidTime

(后续票:2.7 移交同步……随票追加于此)

3. 状态 / 值域附录

  • project_stage:0 冲突处理 / 1 方案设计 / 2 商务报价 / 3 招投标准备 / 4 商务跟进 / 5 赢单输单 / 6 结项(仅输单进)
  • project_status:1 进行中 / 2 已关闭 / 3 已结项(赢单本期不落 3)
  • filing_status:0 未报备(本期不可达·预留)/ 1 报备审核中(建项即此态)/ 2 报备通过 / 3 报备驳回
  • bid_result:0 未定 / 1 赢单(stage5 闭环锁死)/ 2 输单(stage6 终态)
  • close_type:MANUAL / CUSTOMER_CANCEL / LOST_CONTACT / OTHER
  • 任务状态语义码:PENDING / DOING / DONE
  • scope:manage(项目管理,@DataScope)/ mine(我的项目)

4. 联调速查

  • 建档前置数据:一个有效客户(crm-customer)+ 该客户名下一张商机归属方案卡(crm-opportunity 方案卡保存接口,A3 商机管理 分区)。
  • demo 单页见票仓 14/15 产出;.bru 位于 E:\code\crm-api-docs\A5 项目管理\(agent 不提交 git,留人工审查)。

5. 已知缺口与范围外(如实记录,避免联调踩坑)

  • 冲突检测留桩恒「无冲突」(spec §8 选甲):不会出现冲突拦截分支;ConflictPullDTO 维度配置源缺失为 spin-out 前置。
  • PROJECT 归属方案卡的独立 HTTP 创建端点本期无(服务级通道 + A5 建档校验已通;自动转项目 spin-out 后接入)。
  • 阶段名别名列头(stageAliasJson 优先)票 13 接入前,阶段名一律走字典名/枚举名兜底。
  • 输单复盘字段(竞品/输单原因等)为后续字段(票 07 标注),本期 stage6 仅状态落位。