2026-10-18 14:28:38 +04:00

98 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Статус документа и конверта (спека «Шаг 8 — статус документа и конверта»).
Одна функция на сервис и ядро: вход не зависит от источника строк.
"""
from collections.abc import Sequence
from dataclasses import dataclass
from arm_statements.model import (
DocStatus,
DocumentType,
EnvelopeStatus,
LineStatus,
PeriodKind,
Severity,
StatementDocument,
StatementWarning,
)
_ACCEPTABLE_LINES = frozenset({LineStatus.OK, LineStatus.DETAIL})
@dataclass(frozen=True, slots=True)
class StatusLine:
line_status: LineStatus
needs_review: bool
@dataclass(frozen=True, slots=True)
class StatusValue:
line_status: LineStatus
needs_review: bool
@dataclass(frozen=True, slots=True)
class StatusInput:
document_type: DocumentType
layout_found: bool
has_organization_or_inn: bool
period_known: bool
needs_review_fields: tuple[str, ...]
lines: tuple[StatusLine, ...]
values: tuple[StatusValue, ...]
hard_failures: int
accepted: bool
warning_severities: tuple[Severity, ...]
def document_status(data: StatusInput) -> DocStatus:
"""`DISCLOSURE` — всегда `done`; иначе `done` только при выполнении всех условий спеки."""
if data.document_type is DocumentType.DISCLOSURE:
return DocStatus.DONE
done = (
data.layout_found
and data.has_organization_or_inn
and data.period_known
and all(line.line_status in _ACCEPTABLE_LINES for line in data.lines)
and not any(line.needs_review for line in data.lines)
# значения строк detail в статус не входят (Р-23)
and not any(v.needs_review for v in data.values if v.line_status is not LineStatus.DETAIL)
and not data.needs_review_fields
and (data.hard_failures == 0 or data.accepted)
and Severity.ERROR not in data.warning_severities
)
return DocStatus.DONE if done else DocStatus.NEEDS_CHECK
def envelope_status(
document_statuses: Sequence[DocStatus], file_warnings: Sequence[StatementWarning]
) -> EnvelopeStatus:
if not document_statuses:
return EnvelopeStatus.ERROR
if all(s is DocStatus.DONE for s in document_statuses) and all(
w.severity is not Severity.ERROR for w in file_warnings
):
return EnvelopeStatus.DONE
return EnvelopeStatus.NEEDS_CHECK
def status_input(document: StatementDocument) -> StatusInput:
"""Вход функции статуса из документа шагов 2–8."""
header = document.header
period_known = header.report_date.value is not None or any(
c.period_kind is PeriodKind.ABSOLUTE and c.period_date is not None for c in document.columns
)
return StatusInput(
document_type=document.document_type,
layout_found=document.lines != (),
has_organization_or_inn=bool(header.organization_name.value or header.inn.value),
period_known=period_known,
needs_review_fields=header.needs_review_fields,
lines=tuple(StatusLine(line.line_status, line.needs_review) for line in document.lines),
values=tuple(StatusValue(line.line_status, v.needs_review) for line in document.lines for v in line.values),
hard_failures=0 if document.checks is None else len(document.checks.relations_failed),
accepted=False,
warning_severities=tuple(w.severity for w in document.warnings),
)