arm-core/api/tests/test_domain_quality_facts.py

187 lines
7.2 KiB
Python
Raw 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.

"""Чистые снимки payload фактов качества (§14.1): форма для ОБ/ОФР и для ОСВ."""
import uuid
from decimal import Decimal
from src.domain.quality_facts import build_intake_payload, build_outcome_payload
from src.models.enums import (
DocumentIssueKind,
DocumentStatus,
DocumentType,
IssueSeverity,
IssueSource,
StatementLineStatus,
)
from src.models.files import Document
from src.models.statements import DocumentIssue, FinancialStatementLine, FinancialStatementValue
from tests.quality_payload_contract import assert_intake_payload_valid, assert_outcome_payload_valid
ROW_COUNT = 4_200
def make_document(document_type: DocumentType = DocumentType.BALANCE) -> Document:
return Document(
id=uuid.uuid4(),
document_type=document_type,
status=DocumentStatus.RECOGNIZED,
)
def test_build_intake_payload_statement_has_lines_and_values():
document = make_document(document_type=DocumentType.BALANCE)
payload = build_intake_payload(document, lines=[...], values=[...], issues=[])
assert "lines" in payload and "values" in payload
assert "osv_warnings" not in payload
def test_build_intake_payload_osv_has_no_lines_or_values():
document = make_document(document_type=DocumentType.OSV)
payload = build_intake_payload(document, osv_warnings=["OSV_SOMETHING"])
assert "lines" not in payload and "values" not in payload
assert payload["osv_warnings"] == ["OSV_SOMETHING"]
def test_build_intake_payload_statement_serializes_line_value_and_issue_fields():
document = make_document(document_type=DocumentType.INCOME)
line_id = uuid.uuid4()
column_id = uuid.uuid4()
line = FinancialStatementLine(
id=line_id,
source_ref="row:3",
row_index=3,
line_code="2110",
line_code_text="2110",
line_status=StatementLineStatus.ok,
needs_review=True,
)
value = FinancialStatementValue(
line_id=line_id,
column_id=column_id,
amount=Decimal("1500.00"),
string_value=None,
source_text="1 500",
confidence=Decimal("95.00"),
is_recognized=True,
needs_review=False,
)
issue = DocumentIssue(
document_id=document.id,
kind=DocumentIssueKind.relation,
code="RELATION_BROKEN",
severity=IssueSeverity.error,
message="нарушено",
source=IssueSource.core,
relation="2110 = 2120",
codes=["2110"],
)
payload = build_intake_payload(document, lines=[line], values=[value], issues=[issue])
assert payload["lines"] == [
{
"id": str(line_id),
"ref": "row:3",
"row_index": 3,
"line_code": "2110",
"line_code_text": "2110",
"line_status": "ok",
"needs_review": True,
}
]
assert payload["values"] == [
{
"line_ref": "row:3",
"column": str(column_id),
"amount": "1500.00",
"string_value": None,
"source_text": "1 500",
"confidence": 95.0,
"is_recognized": True,
"needs_review": False,
}
]
assert payload["issues"] == [
{
"kind": "relation",
"code": "RELATION_BROKEN",
"severity": "error",
"source": "core",
"field": None,
"relation": "2110 = 2120",
"codes": ["2110"],
"line_ids": None,
}
]
def test_build_outcome_payload_statement_has_fixes_and_no_osv_warnings():
document = make_document(document_type=DocumentType.BALANCE)
fix = {"what": "line_code", "was": "2110", "became": "2120", "source": "service", "rule": "§5"}
payload = build_outcome_payload(document, lines=[], values=[], issues=[], fixes=[fix])
assert payload["fixes"] == [fix]
assert "lines" in payload and "values" in payload
assert "osv_warnings" not in payload
def test_build_outcome_payload_osv_has_fixes_and_no_lines():
document = make_document(document_type=DocumentType.OSV)
fix = {"what": "period", "was": "2024 Q1", "became": "2024 Q2", "source": "ours", "rule": "§5"}
payload = build_outcome_payload(document, osv_warnings=["OSV_SOMETHING"], fixes=[fix])
assert payload["osv_warnings"] == ["OSV_SOMETHING"]
assert payload["fixes"] == [fix]
assert "lines" not in payload and "values" not in payload
def test_build_intake_payload_includes_header_source_for_statement():
document = make_document(document_type=DocumentType.BALANCE)
header_source = {"inn": {"text": "7701234567", "confidence": Decimal("100.00")}}
payload = build_intake_payload(document, lines=[], values=[], header_source=header_source)
assert payload["header"]["header_source"] == {"inn": {"text": "7701234567", "confidence": "100.00"}}
def test_build_outcome_payload_includes_header_source_for_statement():
document = make_document(document_type=DocumentType.INCOME)
header_source = {"okpo": {"text": "12345678", "confidence": None}}
payload = build_outcome_payload(document, lines=[], values=[], fixes=[], header_source=header_source)
assert payload["header"]["header_source"] == {"okpo": {"text": "12345678", "confidence": None}}
def test_build_intake_payload_includes_osv_row_count():
document = make_document(document_type=DocumentType.OSV)
payload = build_intake_payload(document, osv_warnings=["OSV_SOMETHING"], osv_row_count=ROW_COUNT)
assert payload["row_count"] == ROW_COUNT
assert payload["osv_warnings"] == ["OSV_SOMETHING"]
def test_build_outcome_payload_includes_osv_row_count():
document = make_document(document_type=DocumentType.OSV)
payload = build_outcome_payload(document, osv_warnings=[], fixes=[], osv_row_count=0)
assert payload["row_count"] == 0
def test_header_source_and_row_count_absent_when_kwargs_omitted():
balance = build_intake_payload(make_document(document_type=DocumentType.BALANCE), lines=[], values=[])
assert "header_source" not in balance["header"]
osv = build_intake_payload(make_document(document_type=DocumentType.OSV), osv_warnings=[])
assert "row_count" not in osv
outcome_osv = build_outcome_payload(make_document(document_type=DocumentType.OSV), osv_warnings=[], fixes=[])
assert "row_count" not in outcome_osv
def test_payload_with_null_is_recognized_matches_contract():
"""I-9: ячейка без признака распознавания (правка аналитика, пустая ячейка источника) проходит схему контракта."""
document = make_document(document_type=DocumentType.BALANCE)
line = FinancialStatementLine(
id=uuid.uuid4(),
source_ref="row:1",
row_index=1,
line_code="1100",
line_status=StatementLineStatus.ok,
needs_review=False,
)
value = FinancialStatementValue(
line_id=line.id, column_id=uuid.uuid4(), amount=Decimal("10.00"), is_recognized=None, needs_review=False
)
intake = build_intake_payload(document, lines=[line], values=[value], issues=[])
assert intake["values"][0]["is_recognized"] is None
assert_intake_payload_valid(intake)
assert_outcome_payload_valid(build_outcome_payload(document, lines=[line], values=[value], issues=[], fixes=[]))