Files
gaokao-volunteer-system/data/orders/public_flow.py

118 lines
3.2 KiB
Python
Raw Normal View History

"""用户端 Web 自助订单创建流程T12.3)。"""
from __future__ import annotations
from typing import Literal, Optional
from pydantic import BaseModel, Field, model_validator
from data.orders.dao import OrdersDAO
from data.orders.models import Order, generate_order_id
ServiceVersion = Literal["audit", "basic", "standard", "premium"]
_SERVICE_PRICES: dict[ServiceVersion, int] = {
"audit": 4900,
"basic": 4900,
"standard": 9900,
"premium": 19900,
}
_SUPPORTED_PUBLIC_PROVINCES = {
"北京",
"天津",
"上海",
"重庆",
"河北",
"河南",
"山东",
"山西",
"陕西",
"辽宁",
"吉林",
"黑龙江",
"江苏",
"浙江",
"安徽",
"福建",
"江西",
"湖北",
"湖南",
"广东",
"海南",
"四川",
"贵州",
"云南",
"甘肃",
"青海",
"新疆",
}
def service_price_for(service_version: ServiceVersion) -> int:
return _SERVICE_PRICES[service_version]
class PublicOrderCreate(BaseModel):
service_version: ServiceVersion
amount_cents: int = Field(ge=0)
customer_name: Optional[str] = None
customer_phone: Optional[str] = Field(default=None, min_length=1)
customer_wechat: Optional[str] = None
customer_email: Optional[str] = None
candidate_name: str = Field(min_length=1)
candidate_province: Optional[str] = None
notes: Optional[str] = None
@model_validator(mode="after")
def _validate_minimal_checkout(self) -> "PublicOrderCreate":
expected_amount = service_price_for(self.service_version)
if self.amount_cents != expected_amount:
raise ValueError("amount_cents 与套餐价格不一致")
if not self.customer_phone and not self.customer_wechat:
raise ValueError("customer_phone / customer_wechat 至少填写一个")
if self.candidate_province and self.candidate_province not in _SUPPORTED_PUBLIC_PROVINCES:
raise ValueError("candidate_province 当前暂不支持")
return self
class PublicOrderCreated(BaseModel):
order_id: str
source: str
status: str
service_version: str
amount_cents: int
next_step: str
def create_public_order(dao: OrdersDAO, request: PublicOrderCreate) -> Order:
order = Order(
id=generate_order_id(),
source="web",
service_version=request.service_version,
amount_cents=service_price_for(request.service_version),
status="pending",
customer_name=request.customer_name,
customer_phone=request.customer_phone,
customer_wechat=request.customer_wechat,
customer_email=request.customer_email,
candidate_name=request.candidate_name,
candidate_province=request.candidate_province,
notes=request.notes,
tags=["web-self-service", f"package:{request.service_version}"],
)
return dao.create(order, actor="public_web", reason="public_create")
def to_created_payload(order: Order) -> PublicOrderCreated:
return PublicOrderCreated(
order_id=order.id,
source=order.source,
status=order.status,
service_version=order.service_version,
amount_cents=order.amount_cents,
next_step="payment",
)