fc / apps /preservation_date /services /validators.py
jun2024's picture
Upload 2241 files
b4f2238 verified
Raw History Blame Contribute Delete
3.63 kB
"""保全措施法律约束校验器."""
from __future__ import annotations
import logging
from typing import ClassVar
from django.utils.translation import gettext_lazy as _
from .models import PreservationMeasure
logger = logging.getLogger(__name__)
class MeasureValidator:
"""保全措施法律约束校验器.
对提取的保全措施进行法律约束和逻辑一致性校验,
仅追加 ``pending_note``,不修改其他字段。
"""
# 法定期限上限(天数, 提示文案)
DURATION_LIMITS: ClassVar[dict[str, tuple[int, str]]] = {
"查封": (1095, str(_("不动产查封最长3年"))),
"冻结": (365, str(_("银行存款冻结最长1年"))),
"扣押": (730, str(_("动产扣押最长2年"))),
}
# ---- 校验提示文案 ----
_MSG_DATE_INVERTED: str = str(_("到期日期早于起算日期,请人工核实"))
_MSG_DURATION_EXCEEDED: str = str(_("期限超过法定上限({limit_desc}),请人工核实"))
_MSG_PENDING_HAS_END_DATE: str = str(_("轮候状态不应有确定到期日期,请人工核实"))
# 多条提示之间的分隔符
_SEP: str = ";"
# ------------------------------------------------------------------
# public
# ------------------------------------------------------------------
def validate(self, measure: PreservationMeasure) -> PreservationMeasure:
"""校验单个措施,追加校验提示到 ``pending_note``,不修改原始数据."""
warnings: list[str] = []
self._check_date_order(measure, warnings)
self._check_duration_limit(measure, warnings)
self._check_pending_end_date(measure, warnings)
if warnings:
existing = measure.pending_note or ""
suffix = self._SEP.join(warnings)
measure.pending_note = f"{existing}{self._SEP}{suffix}" if existing else suffix
return measure
def validate_all(self, measures: list[PreservationMeasure]) -> list[PreservationMeasure]:
"""批量校验."""
return [self.validate(m) for m in measures]
# ------------------------------------------------------------------
# private checks
# ------------------------------------------------------------------
def _check_date_order(
self,
measure: PreservationMeasure,
warnings: list[str],
) -> None:
"""规则 1:end_date < start_date → 追加提示."""
if measure.start_date is not None and measure.end_date is not None and measure.end_date < measure.start_date:
warnings.append(self._MSG_DATE_INVERTED)
def _check_duration_limit(
self,
measure: PreservationMeasure,
warnings: list[str],
) -> None:
"""规则 2/3/4:期限超过法定上限 → 追加提示."""
if measure.start_date is None or measure.end_date is None:
return
actual_days = (measure.end_date - measure.start_date).days
for keyword, (max_days, limit_desc) in self.DURATION_LIMITS.items():
if keyword in measure.measure_type and actual_days > max_days:
warnings.append(self._MSG_DURATION_EXCEEDED.format(limit_desc=limit_desc))
break # 每个措施只匹配一种类型
def _check_pending_end_date(
self,
measure: PreservationMeasure,
warnings: list[str],
) -> None:
"""规则 5:is_pending=True 且 end_date 不为 None → 追加提示."""
if measure.is_pending and measure.end_date is not None:
warnings.append(self._MSG_PENDING_HAS_END_DATE)