243 lines
9.4 KiB
Python
243 lines
9.4 KiB
Python
"""CRM 商机管理 Pydantic Schemas"""
|
||
|
||
from typing import List, Optional
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field
|
||
|
||
|
||
class OpportunityListBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
page: int = Field(default=1, ge=1, description="页码")
|
||
pageSize: int = Field(default=10, ge=1, le=500, description="每页条数")
|
||
keyword: Optional[str] = Field(default=None, description="关键词(商机名/客户名 OR)")
|
||
opportunity_no: Optional[str] = Field(default=None, alias="opportunityNo")
|
||
opportunity_name: Optional[str] = Field(default=None, alias="opportunityName")
|
||
customer_name: Optional[str] = Field(default=None, alias="customerName")
|
||
customer_id: Optional[str] = Field(default=None, alias="customerId")
|
||
stage: Optional[str] = Field(default=None)
|
||
status: Optional[str] = Field(default=None)
|
||
source: Optional[str] = Field(default=None)
|
||
owner_user_id: Optional[str] = Field(default=None, alias="ownerUserId")
|
||
view_type: Optional[str] = Field(default=None, alias="viewType", description="mine/all")
|
||
begin_time: Optional[str] = Field(default=None, alias="beginTime")
|
||
end_time: Optional[str] = Field(default=None, alias="endTime")
|
||
create_time_range: Optional[List[str]] = Field(default=None, alias="createTimeRange")
|
||
amount_min: Optional[float] = Field(default=None, alias="amountMin")
|
||
amount_max: Optional[float] = Field(default=None, alias="amountMax")
|
||
min_amount: Optional[float] = Field(default=None, alias="minAmount")
|
||
max_amount: Optional[float] = Field(default=None, alias="maxAmount")
|
||
|
||
ids: Optional[List[str]] = Field(default=None, description="导出指定ID列表")
|
||
columns: Optional[List[str]] = Field(default=None, description="导出列(前端 visibleColumns)")
|
||
|
||
|
||
class OpportunityDetailBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityCreateBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_no: Optional[str] = Field(default=None, alias="opportunityNo")
|
||
opportunity_name: str = Field(..., alias="opportunityName", min_length=1, max_length=200)
|
||
customer_id: str = Field(..., alias="customerId")
|
||
contact_id: Optional[str] = Field(default=None, alias="contactId")
|
||
stage: Optional[str] = Field(default="initial")
|
||
stage_percent: Optional[int] = Field(default=None, alias="stagePercent")
|
||
win_rate: Optional[float] = Field(default=None, alias="winRate")
|
||
amount: Optional[float] = Field(default=0)
|
||
expect_deal_date: Optional[str] = Field(default=None, alias="expectDealDate")
|
||
source: Optional[str] = Field(default=None)
|
||
type: Optional[str] = Field(default=None)
|
||
description: Optional[str] = Field(default=None)
|
||
owner_user_id: Optional[str] = Field(default=None, alias="ownerUserId")
|
||
competitors: Optional[str] = Field(default=None)
|
||
key_factors: Optional[str] = Field(default=None, alias="keyFactors")
|
||
remark: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityUpdateBody(OpportunityCreateBody):
|
||
id: str = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityDeleteBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
ids: List[str] = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityAssignBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
ids: List[str] = Field(..., min_length=1)
|
||
owner_user_id: str = Field(..., alias="ownerUserId")
|
||
remark: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityChangeStageBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., min_length=1)
|
||
stage: str = Field(...)
|
||
stage_percent: int = Field(..., alias="stagePercent")
|
||
win_rate: float = Field(..., alias="winRate")
|
||
change_reason: Optional[str] = Field(default=None, alias="changeReason")
|
||
remark: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityMarkWonBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., min_length=1)
|
||
actual_deal_date: Optional[str] = Field(default=None, alias="actualDealDate")
|
||
actual_amount: Optional[float] = Field(default=None, alias="actualAmount")
|
||
remark: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityMarkLostBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., min_length=1)
|
||
lost_reason: str = Field(..., alias="lostReason")
|
||
remark: Optional[str] = Field(default=None)
|
||
competitor_info: Optional[str] = Field(default=None, alias="competitorInfo")
|
||
improvement: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityBatchUpdateStageBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
ids: List[str] = Field(..., min_length=1)
|
||
stage: str = Field(...)
|
||
stage_percent: int = Field(..., alias="stagePercent")
|
||
win_rate: Optional[float] = Field(default=None, alias="winRate")
|
||
change_reason: str = Field(..., alias="changeReason")
|
||
update_expect_date: Optional[bool] = Field(default=None, alias="updateExpectDate")
|
||
notify_owner: Optional[bool] = Field(default=None, alias="notifyOwner")
|
||
|
||
|
||
class OpportunityBatchUpdateExpectDateBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
ids: List[str] = Field(..., min_length=1)
|
||
update_type: str = Field(..., alias="updateType")
|
||
expect_deal_date: Optional[str] = Field(default=None, alias="expectDealDate")
|
||
days: Optional[int] = Field(default=None)
|
||
change_reason: Optional[str] = Field(default=None, alias="changeReason")
|
||
|
||
|
||
class OpportunityStageLogListBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: str = Field(..., alias="opportunityId")
|
||
|
||
|
||
class OpportunityStatisticsBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
owner_user_id: Optional[str] = Field(default=None, alias="ownerUserId")
|
||
begin_time: Optional[str] = Field(default=None, alias="beginTime")
|
||
end_time: Optional[str] = Field(default=None, alias="endTime")
|
||
type: Optional[str] = Field(default="month", description="赢单率统计维度 day/week/month")
|
||
|
||
|
||
class OpportunityKanbanBody(OpportunityListBody):
|
||
pass
|
||
|
||
|
||
class OpportunityFollowListBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: Optional[str] = Field(default=None, alias="opportunityId")
|
||
page: int = Field(default=1, ge=1)
|
||
pageSize: int = Field(default=10, ge=1, le=500)
|
||
|
||
|
||
class OpportunityFollowDetailBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityFollowCreateBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: str = Field(..., alias="opportunityId")
|
||
follow_type: str = Field(..., alias="followType")
|
||
follow_content: str = Field(..., alias="followContent")
|
||
follow_time: Optional[str] = Field(default=None, alias="followTime")
|
||
next_time: Optional[str] = Field(default=None, alias="nextTime")
|
||
next_plan: Optional[str] = Field(default=None, alias="nextPlan")
|
||
next_content: Optional[str] = Field(default=None, alias="nextContent")
|
||
attachments: Optional[str] = Field(default=None)
|
||
remark: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityFollowUpdateBody(OpportunityFollowCreateBody):
|
||
id: str = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityFollowDeleteBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
ids: List[str] = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityProductListBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: Optional[str] = Field(default=None, alias="opportunityId")
|
||
product_id: Optional[str] = Field(default=None, alias="productId")
|
||
page: int = Field(default=1, ge=1)
|
||
pageSize: int = Field(default=10, ge=1, le=500)
|
||
|
||
|
||
class OpportunityProductByOpportunityBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: Optional[str] = Field(default=None, alias="opportunityId")
|
||
id: Optional[str] = Field(default=None, description="商机ID(路径兼容)")
|
||
|
||
|
||
class OpportunityProductDetailBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
id: str = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityProductCreateBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: str = Field(..., alias="opportunityId")
|
||
product_id: str = Field(..., alias="productId")
|
||
product_name: Optional[str] = Field(default=None, alias="productName")
|
||
product_no: Optional[str] = Field(default=None, alias="productNo")
|
||
product_code: Optional[str] = Field(default=None, alias="productCode")
|
||
quantity: float = Field(...)
|
||
price: float = Field(...)
|
||
discount: Optional[float] = Field(default=0)
|
||
subtotal: Optional[float] = Field(default=None)
|
||
sort: Optional[int] = Field(default=0)
|
||
sort_order: Optional[int] = Field(default=None, alias="sortOrder")
|
||
remark: Optional[str] = Field(default=None)
|
||
|
||
|
||
class OpportunityProductBatchAddBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
opportunity_id: str = Field(..., alias="opportunityId")
|
||
product_list: List[OpportunityProductCreateBody] = Field(..., alias="productList")
|
||
|
||
|
||
class OpportunityProductUpdateBody(OpportunityProductCreateBody):
|
||
id: str = Field(..., min_length=1)
|
||
|
||
|
||
class OpportunityProductDeleteBody(BaseModel):
|
||
model_config = ConfigDict(populate_by_name=True)
|
||
|
||
ids: List[str] = Field(..., min_length=1)
|