fix(invoice): 移除发票创建模型中不必要的必填限制

refactor(valuations): 添加估值计算前的用户配额检查逻辑

docs: 添加发票抬头必填字段的修改方案文档
This commit is contained in:
邹方成 2025-11-26 18:17:47 +08:00
parent 27b6276cdc
commit c15f3e9925
3 changed files with 60 additions and 5 deletions

View File

@ -0,0 +1,34 @@
## 目标
* 添加抬头时将 `公司名称``公司税号``电子邮箱`设为必填,其他字段可为空。
* 现状确认(代码引用)
- 后端必填:`app/schemas/invoice.py:612``InvoiceHeaderCreate` 已要求 `company_name``tax_number` 为必填,`email: EmailStr` 为必填。
- API 入口:`app/api/v1/app_invoices/app_invoices.py:5558` 新增抬头接口使用 `InvoiceHeaderCreate`,后端将严格校验三项必填。
## 修改方案
1. 统一前端校验文案
* 统一三项必填的错误提示为简洁中文,如:“请输入公司名称 / 公司税号 / 电子邮箱”。
* 邮箱格式提示统一为:“请输入有效的电子邮箱”。
2. 后端校验与返回确认
* 保持 `InvoiceHeaderCreate` 的必填与格式限制不变(`app/schemas/invoice.py:612`)。
* 确认更新接口 `InvoiceHeaderUpdate``app/schemas/invoice.py:3239`)允许局部更新、但不影响创建必填逻辑。
3. 验证与测试
* 后端接口验证:对 `POST /app-invoices/headers``app/api/v1/app_invoices/app_invoices.py:5558`)进行用例:缺失任一必填字段应返回 422全部正确应 200/201。
* 可补充最小化单元测试Pydantic 校验用例覆盖必填与格式。
## 交付内容。
* 完成基本交互与接口验证,确保行为符合预期。

View File

@ -301,7 +301,28 @@ async def calculate_valuation(
"""
try:
# 添加后台任务
from app.models.user import AppUser, AppUserQuotaLog
user = await AppUser.filter(id=user_id).first()
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
if (user.remaining_quota or 0) < 1:
raise HTTPException(status_code=400, detail="估值次数不足")
before = user.remaining_quota or 0
user.remaining_quota = before - 1
await user.save()
try:
await AppUserQuotaLog.create(
app_user_id=user_id,
operator_id=user_id,
operator_name=user.alias or user.username or user.phone or "",
before_count=before,
after_count=before - 1,
op_type="consume",
remark="发起估值"
)
except Exception:
pass
background_tasks.add_task(_perform_valuation_calculation, user_id, data)
logger.info("valuation.task_queued user_id={} asset_name={} industry={}",

View File

@ -46,10 +46,10 @@ class InvoiceCreate(BaseModel):
email: EmailStr
company_name: str = Field(..., min_length=1, max_length=128)
tax_number: str = Field(..., min_length=1, max_length=32)
register_address: str = Field(..., min_length=1, max_length=256)
register_phone: str = Field(..., min_length=1, max_length=32)
bank_name: str = Field(..., min_length=1, max_length=128)
bank_account: str = Field(..., min_length=1, max_length=64)
register_address: str = Field(..., max_length=256)
register_phone: str = Field(..., max_length=32)
bank_name: str = Field(..., max_length=128)
bank_account: str = Field(..., max_length=64)
app_user_id: Optional[int] = None
header_id: Optional[int] = None
wechat: Optional[str] = None