feat(statements): созданные пустые строки вне проверок §7 (#80)
statement_amounts не отдаёт проверкам строки с line_code_original_value IS NULL, у которых все суммы пустые; заполненная хотя бы в одной колонке строка проверяется по всем колонкам. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
37e7f40890
commit
2d21a416d6
@ -127,7 +127,9 @@ async def statement_amounts(
|
||||
session: AsyncSession, meta_id: uuid.UUID
|
||||
) -> tuple[list[int], list[tuple[str, dict[int, Decimal | None]]]]:
|
||||
"""Индексы колонок и `(код строки, {колонка: сумма})` по возрастанию кода — вход `run_checks`. Порядок строк
|
||||
формы в БД не хранится (DBML не хранит), поэтому порядок строк — лексикографический порядок кодов."""
|
||||
формы в БД не хранится (DBML не хранит), поэтому порядок строк — лексикографический порядок кодов.
|
||||
Созданные правкой строки (`line_code_original_value IS NULL`) без единой суммы не участвуют
|
||||
(spec statement-checks, design D-5)."""
|
||||
columns = (
|
||||
await session.execute(
|
||||
select(FinancialStatementColumn.id, FinancialStatementColumn.column_index)
|
||||
@ -138,16 +140,29 @@ async def statement_amounts(
|
||||
index_by_id = {column_id: index for column_id, index in columns}
|
||||
rows = (
|
||||
await session.execute(
|
||||
select(FinancialStatementLine.line_code, FinancialStatementValue.column_id, FinancialStatementValue.amount)
|
||||
select(
|
||||
FinancialStatementLine.line_code,
|
||||
FinancialStatementLine.line_code_original_value,
|
||||
FinancialStatementValue.column_id,
|
||||
FinancialStatementValue.amount,
|
||||
)
|
||||
.join(FinancialStatementValue, FinancialStatementValue.line_id == FinancialStatementLine.id)
|
||||
.where(FinancialStatementLine.meta_id == meta_id)
|
||||
.order_by(FinancialStatementLine.line_code)
|
||||
)
|
||||
).all()
|
||||
by_code: dict[str, dict[int, Decimal | None]] = {}
|
||||
for code, column_id, amount in rows:
|
||||
added: set[str] = set() # строки, созданные правкой аналитика (design D-5)
|
||||
for code, original, column_id, amount in rows:
|
||||
by_code.setdefault(code or "", {})[index_by_id[column_id]] = amount
|
||||
return [index for _, index in columns], list(by_code.items())
|
||||
if original is None:
|
||||
added.add(code or "")
|
||||
lines = [
|
||||
(code, amounts)
|
||||
for code, amounts in by_code.items()
|
||||
if code not in added or any(amount is not None for amount in amounts.values())
|
||||
]
|
||||
return [index for _, index in columns], lines
|
||||
|
||||
|
||||
async def value_flags(session: AsyncSession, meta_id: uuid.UUID) -> list[tuple[bool, bool | None, Decimal | None]]:
|
||||
|
||||
@ -1286,3 +1286,39 @@ async def test_patch_duplicate_line_code_rejected(
|
||||
)
|
||||
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
|
||||
assert response.json()["detail"]["code"] == "DUPLICATE_CELL"
|
||||
|
||||
|
||||
async def test_template_line_checks_follow_filled_amounts(
|
||||
seeded: AsyncSession, fixtures_dir: Path, auth_client: AuthClientFactory
|
||||
) -> None:
|
||||
"""Review Focus 4 (spec statement-checks): заполненная в одной колонке строка проверяется по всем колонкам,
|
||||
очищенная — снова не участвует."""
|
||||
document = await form(seeded, fixtures_dir)
|
||||
sums = await drop_line(seeded, document, "1700")
|
||||
assert sums[1] not in (None, Decimal(0)) and sums[2] not in (None, Decimal(0)) # колонки 1, 2 непустые
|
||||
client = await auth_client(KA_RF)
|
||||
col0 = await _column(client, document.id, 0)
|
||||
response = await client.patch(
|
||||
f"/documents/{document.id}/statement",
|
||||
json={"values": [{"line_code": "1700", "column_id": col0, "amount": str(sums[0])}]},
|
||||
)
|
||||
failed = response.json()["checks"]["failed"]
|
||||
relation = "1700 = 1300 + 1400 + 1500"
|
||||
assert sorted(f["column_index"] for f in failed if f["relation"] == relation) == [1, 2]
|
||||
assert all(f["column_index"] != 0 for f in failed)
|
||||
response = await client.patch(
|
||||
f"/documents/{document.id}/statement",
|
||||
json={
|
||||
"values": [
|
||||
{
|
||||
"line_id": next(i["id"] for i in response.json()["lines"] if i["line_code"] == "1700"),
|
||||
"column_id": col0,
|
||||
"amount": None,
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK, response.text
|
||||
after_clear = response.json()["checks"]["failed"]
|
||||
assert not any(f["relation"].startswith("1700 =") for f in after_clear) # очищенная 1700 снова не цель
|
||||
assert {f["column_index"] for f in after_clear if f["relation"] == "1600 = 1700"} == {0, 1, 2}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user