| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- """顺丰月结抬头与结算规则。不访问数据库。"""
- from __future__ import annotations
- from dataclasses import dataclass
- from datetime import datetime
- from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
- from typing import Any, Optional
- SF_TRANSPORT_MODE = "sfkd"
- SETTLE_UNSETTLED = "wjs"
- SETTLE_SETTLED = "yjs"
- _AMOUNT_QUANT = Decimal("0.01")
- _MAX_AMOUNT = Decimal("9999999999999999.99")
- @dataclass(frozen=True)
- class FreightHeaderPlan:
- transport_mode: str
- waybill_no: Optional[str]
- freight_amount: Optional[Decimal]
- settle_status: Optional[str]
- clear_settle_time: bool
- def normalize_waybill(value: Any) -> str:
- return str(value or "").strip()
- def _is_blank(value: Any) -> bool:
- return value is None or (isinstance(value, str) and value.strip() == "")
- def parse_optional_amount(value: Any) -> Optional[Decimal]:
- if _is_blank(value):
- return None
- try:
- amount = Decimal(str(value))
- except (InvalidOperation, ValueError):
- raise ValueError("运费金额格式不正确")
- if not amount.is_finite():
- raise ValueError("运费金额格式不正确")
- if amount < 0:
- raise ValueError("运费不能为负数")
- if amount > _MAX_AMOUNT:
- raise ValueError("运费金额超出范围")
- return amount.quantize(_AMOUNT_QUANT, rounding=ROUND_HALF_UP)
- def freight_amount_label(transport_mode: Optional[str], amount: Optional[Decimal]) -> str:
- if (transport_mode or "") == SF_TRANSPORT_MODE and amount is None:
- return "月结"
- if amount is None:
- return ""
- return format(Decimal(amount).quantize(_AMOUNT_QUANT, rounding=ROUND_HALF_UP), "f")
- def plan_freight_header(
- *,
- transport_mode: str,
- waybill_no: Any = None,
- freight_amount: Any = None,
- ) -> FreightHeaderPlan:
- mode = str(transport_mode or "").strip()
- if not mode:
- raise ValueError("请选择运输方式")
- if mode == SF_TRANSPORT_MODE:
- waybill = normalize_waybill(waybill_no)
- if not waybill:
- raise ValueError("请填写顺丰单号")
- if len(waybill) > 64:
- raise ValueError("顺丰单号不能超过 64 个字符")
- return FreightHeaderPlan(mode, waybill, None, SETTLE_UNSETTLED, True)
- if normalize_waybill(waybill_no):
- raise ValueError("该运输方式不能填写顺丰单号")
- amount = parse_optional_amount(freight_amount)
- if amount is None:
- raise ValueError("请填写运费")
- return FreightHeaderPlan(mode, None, amount, None, True)
- def resolve_header_for_save(
- *,
- transport_mode: str,
- existing_waybill: Any,
- existing_amount: Any,
- existing_settle_status: Any,
- waybill_supplied: bool,
- waybill_no: Any,
- amount_supplied: bool,
- freight_amount: Any,
- ) -> FreightHeaderPlan:
- if (existing_settle_status or "") == SETTLE_SETTLED:
- raise ValueError("已结算的运费不能修改运输方式或顺丰单号")
- if transport_mode == SF_TRANSPORT_MODE:
- waybill = waybill_no if waybill_supplied else existing_waybill
- return plan_freight_header(
- transport_mode=transport_mode, waybill_no=waybill, freight_amount=None
- )
- amount = freight_amount if amount_supplied else existing_amount
- return plan_freight_header(
- transport_mode=transport_mode, waybill_no="", freight_amount=amount
- )
- def plan_settle(*, current_amount: Optional[Decimal], submitted_amount: Any, now: datetime):
- amount = current_amount if _is_blank(submitted_amount) else parse_optional_amount(submitted_amount)
- return amount, SETTLE_SETTLED, now
- def assert_settle_request(ids: list, submitted_amount: Any) -> None:
- if not ids:
- raise ValueError("请选择运费批次")
- if len(ids) != 1 and not _is_blank(submitted_amount):
- raise ValueError("批量结算不能填写运费")
- def plan_fill_amount(*, current_amount: Optional[Decimal], settle_status: Optional[str], submitted_amount: Any) -> Decimal:
- if settle_status != SETTLE_SETTLED or current_amount is not None:
- raise ValueError("只有已结算且仍为月结的运费可以补填金额")
- amount = parse_optional_amount(submitted_amount)
- if amount is None:
- raise ValueError("请填写运费")
- return amount
- def assert_freight_mutable(settle_status: Optional[str], action: str) -> None:
- if (settle_status or "") != SETTLE_SETTLED:
- return
- if action == "delete":
- raise ValueError("已结算的运费不能删除")
- if action == "items":
- raise ValueError("已结算的运费不能调整样本")
- raise ValueError("已结算的运费不能修改运输方式或顺丰单号")
|