feat(backend): accept samplePayments on market protocol body

Whitelist per-sample payment payload for mobile protocol create/update.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-10-13 15:21:07 +08:00
1 parent cc843535f5
commit 9c61f36db8
2 files changed
+71

No files matched your search

+40
View File
@@ -247,6 +247,43 @@ class MarketProtocolAttachmentsBody(BaseModel):
)
class MarketProtocolPaymentScheduleBody(BaseModel):
model_config = ConfigDict(extra='forbid', populate_by_name=True)
id: Optional[str] = None
schedule_no: Optional[int] = Field(None, alias='scheduleNo')
due_amount: Optional[float] = Field(None, alias='dueAmount')
due_date: Optional[str] = Field(None, alias='dueDate')
schedule_status: Optional[str] = Field(None, alias='scheduleStatus')
transfers: Optional[List[dict]] = None
class MarketProtocolSamplePaymentBody(BaseModel):
model_config = ConfigDict(extra='forbid', populate_by_name=True)
id: Optional[str] = None
sample_code: str = Field(..., min_length=1, alias='sampleCode')
protocol_sample_id: Optional[str] = Field(None, alias='protocolSampleId')
pay_mode: str = Field(..., alias='payMode')
contract_amount: Optional[float] = Field(None, alias='contractAmount')
lump_sum_deadline: Optional[str] = Field(None, alias='lumpSumDeadline')
installment_count: Optional[int] = Field(None, alias='installmentCount')
installment_interval_months: Optional[float] = Field(
None, alias='installmentIntervalMonths'
)
installment_start_date: Optional[str] = Field(
None, alias='installmentStartDate'
)
installment_advance_days: Optional[int] = Field(
None, alias='installmentAdvanceDays'
)
installment_ratios: Optional[List[float]] = Field(
None, alias='installmentRatios'
)
remark: Optional[str] = None
schedules: Optional[List[MarketProtocolPaymentScheduleBody]] = None
class MarketProtocolBody(BaseModel):
"""移动协议白名单;状态、审核、财务、退款及转换字段一律拒绝。"""
@@ -266,6 +303,9 @@ class MarketProtocolBody(BaseModel):
collection: Optional[MarketProtocolCollectionBody] = None
samples: Optional[List[MarketProtocolSampleBody]] = None
attachments: Optional[MarketProtocolAttachmentsBody] = None
sample_payments: Optional[List[MarketProtocolSamplePaymentBody]] = Field(
None, alias='samplePayments'
)
class MarketProtocolAuditBody(BaseModel):
+31
View File
@@ -813,6 +813,37 @@ def test_protocol_create_forbids_existing_customer_ids(source):
)
def test_market_protocol_body_accepts_sample_payments():
from app.schemas.market_mobile import MarketProtocolBody
body = MarketProtocolBody.model_validate(
{
'source': 'cell_storage',
'protocolNo': 'P-PAY-1',
'customer': {'motherName': '李四'},
'samplePayments': [
{
'sampleCode': 'S-001',
'payMode': 'dj',
'contractAmount': 20000,
'lumpSumDeadline': '20261231',
'schedules': [
{
'scheduleNo': 1,
'dueAmount': 20000,
'dueDate': '20261231',
}
],
}
],
}
)
assert body.sample_payments is not None
assert len(body.sample_payments) == 1
assert body.sample_payments[0].sample_code == 'S-001'
assert body.sample_payments[0].pay_mode == 'dj'
def test_protocol_body_rejects_status_finance_and_conversion_fields():
from app.schemas.market_mobile import MarketProtocolBody