thread-master/apps/backend/generate/api/crm.api

279 lines
8.3 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

syntax = "v1"
// demand-radar: contacts / touches / follow-ups / conversion / stats
// spec: docs/product/demand-radar/spec.md §5.2
// 未實作能力一律回 501crmDomain.ErrNotReady禁止 102000 空成功。
// 命名紅線:不得以 lead 指稱銷售線索。
type (
// ---------- Contact ----------
ContactPublic {
Id string `json:"id"`
SourcePlatform string `json:"source_platform"`
AuthorHandle string `json:"author_handle"`
DisplayName string `json:"display_name,optional"`
Stage string `json:"stage"` // new_found | engaged | dm_sent | replied | quoted | won | lost
NeedsFollowUp bool `json:"needs_follow_up"`
FollowUpDays int `json:"follow_up_days"`
LastTouchAt int64 `json:"last_touch_at,optional"`
OpportunityIds []string `json:"opportunity_ids"`
OpportunityCount int `json:"opportunity_count"`
MergedFrom []string `json:"merged_from,optional"`
TopIntentBand string `json:"top_intent_band,optional"`
TopIntentScore int `json:"top_intent_score,optional"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
ContactBrief {
Id string `json:"id"`
SourcePlatform string `json:"source_platform"`
AuthorHandle string `json:"author_handle"`
DisplayName string `json:"display_name,optional"`
Stage string `json:"stage"`
}
// StageCount — 八格視圖用stage 值另含 needs_follow_up跨階段檢視非階段值
StageCount {
Stage string `json:"stage"`
Count int `json:"count"`
}
ListContactsReq {
Page int `form:"page,default=1"`
PageSize int `form:"pageSize,default=20"`
Stage string `form:"stage,optional"`
// FollowUp: true | false留空不篩選
FollowUp string `form:"follow_up,optional"`
Band string `form:"band,optional"`
// Sort: last_touch_at | intent_score預設 last_touch_at 倒序)
Sort string `form:"sort,optional"`
}
ContactListData {
List []ContactPublic `json:"list"`
Pagination Pagination `json:"pagination"`
StageCounts []StageCount `json:"stage_counts"`
}
ContactTouchPublic {
Id string `json:"id"`
ContactId string `json:"contact_id"`
Type string `json:"type"` // stage | reply | note | conversion
FromStage string `json:"from_stage,optional"`
ToStage string `json:"to_stage,optional"`
Body string `json:"body,optional"`
ActorUid int64 `json:"actor_uid"`
CreatedAt int64 `json:"created_at"`
}
ContactOpportunityBrief {
Id string `json:"id"`
Permalink string `json:"permalink"`
Text string `json:"text"`
IntentScore int `json:"intent_score"`
IntentBand string `json:"intent_band"`
CreatedAt int64 `json:"created_at"`
}
GetContactReq {
Id string `path:"id"`
Page int `form:"page,default=1"`
PageSize int `form:"pageSize,default=20"`
}
ContactDetailData {
Contact ContactPublic `json:"contact"`
Touches []ContactTouchPublic `json:"touches"`
Pagination Pagination `json:"pagination"`
Opportunities []ContactOpportunityBrief `json:"opportunities"`
}
ContactIdReq {
Id string `path:"id"`
}
UpdateContactStageReq {
Id string `path:"id"`
Stage string `json:"stage"`
Note string `json:"note,optional"`
}
SetContactFollowUpReq {
Id string `path:"id"`
NeedsFollowUp bool `json:"needs_follow_up"`
Days int `json:"days,optional"`
}
CreateContactNoteReq {
Id string `path:"id"`
Body string `json:"body"`
}
MergeContactReq {
Id string `path:"id"`
SourceContactId string `json:"source_contact_id"`
}
UnmergeContactReq {
Id string `path:"id"`
MergedContactId string `json:"merged_contact_id"`
}
// ---------- Conversion寫既有 growth_outcomes不另建成交帳 ----------
CreateCrmConversionReq {
Id string `path:"id"`
Amount float64 `json:"amount,optional"`
Currency string `json:"currency,optional"`
Note string `json:"note,optional"`
}
UpdateCrmConversionReq {
Id string `path:"id"`
Amount float64 `json:"amount,optional"`
Currency string `json:"currency,optional"`
Note string `json:"note,optional"`
}
DeleteCrmConversionReq {
Id string `path:"id"`
}
CrmConversionData {
ContactId string `json:"contact_id"`
OutcomeId string `json:"outcome_id,optional"`
Stage string `json:"stage"`
Amount float64 `json:"amount,optional"`
Currency string `json:"currency,optional"`
Note string `json:"note,optional"`
UpdatedAt int64 `json:"updated_at"`
}
// ---------- FollowUp ----------
FollowUpPublic {
Id string `json:"id"`
ContactId string `json:"contact_id"`
DueAt int64 `json:"due_at"`
Status string `json:"status"` // scheduled | notified | done | snoozed | escalated
NotifiedCount int `json:"notified_count"`
Contact ContactBrief `json:"contact"`
CreatedAt int64 `json:"created_at"`
}
ListFollowUpsReq {
Page int `form:"page,default=1"`
PageSize int `form:"pageSize,default=20"`
Status string `form:"status,optional"`
}
FollowUpListData {
List []FollowUpPublic `json:"list"`
Pagination Pagination `json:"pagination"`
}
FollowUpIdReq {
Id string `path:"id"`
}
SnoozeFollowUpReq {
Id string `path:"id"`
Days int `json:"days"`
}
GenerateFollowUpMessageReq {
Id string `path:"id"`
}
GenerateFollowUpMessageData {
Text string `json:"text"`
}
// ---------- Stats樣本 < 5 只給絕對數) ----------
TermConversionStat {
Term string `json:"term"`
Accepted int `json:"accepted"`
Replied int `json:"replied"`
Won int `json:"won"`
ConversionRate float64 `json:"conversion_rate,optional"`
InsufficientSample bool `json:"insufficient_sample"`
}
VariantConversionStat {
Variant string `json:"variant"`
Used int `json:"used"`
Replied int `json:"replied"`
Won int `json:"won"`
SuccessRate float64 `json:"success_rate,optional"`
InsufficientSample bool `json:"insufficient_sample"`
}
SourceConversionStat {
Source string `json:"source"` // radar | scout | manual_import
Won int `json:"won"`
InsufficientSample bool `json:"insufficient_sample"`
}
CrmStatsReq {
From int64 `form:"from,optional"`
To int64 `form:"to,optional"`
}
CrmStatsData {
Terms []TermConversionStat `json:"terms"`
Variants []VariantConversionStat `json:"variants"`
Sources []SourceConversionStat `json:"sources"`
}
)
@server (
group: crm
prefix: /api/v1/crm
middleware: AuthJWT
)
service gateway {
@handler ListContacts
get /contacts (ListContactsReq) returns (ContactListData)
@handler GetContact
get /contacts/:id (GetContactReq) returns (ContactDetailData)
@handler UpdateContactStage
post /contacts/:id/stage (UpdateContactStageReq) returns (ContactPublic)
@handler SetContactFollowUp
post /contacts/:id/follow-up (SetContactFollowUpReq) returns (ContactPublic)
@handler CreateContactNote
post /contacts/:id/notes (CreateContactNoteReq) returns (ContactTouchPublic)
@handler MergeContact
post /contacts/:id/merge (MergeContactReq) returns (ContactPublic)
@handler UnmergeContact
post /contacts/:id/unmerge (UnmergeContactReq) returns (ContactPublic)
@handler CreateContactConversion
post /contacts/:id/conversion (CreateCrmConversionReq) returns (CrmConversionData)
@handler UpdateContactConversion
put /contacts/:id/conversion (UpdateCrmConversionReq) returns (CrmConversionData)
@handler DeleteContactConversion
delete /contacts/:id/conversion (DeleteCrmConversionReq) returns (OkData)
@handler ListFollowUps
get /followups (ListFollowUpsReq) returns (FollowUpListData)
@handler DoneFollowUp
post /followups/:id/done (FollowUpIdReq) returns (FollowUpPublic)
@handler SnoozeFollowUp
post /followups/:id/snooze (SnoozeFollowUpReq) returns (FollowUpPublic)
@handler GenerateFollowUpMessage
post /followups/:id/message (GenerateFollowUpMessageReq) returns (GenerateFollowUpMessageData)
@handler GetCrmStats
get /stats (CrmStatsReq) returns (CrmStatsData)
}