Files
shanxia2.0/backend/app/schemas/crm/opportunity.py
T
2026-08-22 09:08:05 +08:00

243 lines
9.4 KiB
Python
Raw 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.
"""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)