add-preset-shahmatka #141
@ -872,7 +872,7 @@ API: список счетов `GET /directories/accounts`, правила ве
|
||||
`GET …/intercompany-matrix/all` и `POST …/manual`, их XLSX-выгрузки, статичная таблица
|
||||
`GET …/intercompany-matrix/result-table`. Режим PRESET (счета и показатель из правила элиминации):
|
||||
`GET …/intercompany-matrix/preset/{rule_id}`, его выгрузка `…/preset/{rule_id}/export` и строки сводной ОСВ без пары
|
||||
`…/preset/{rule_id}/unpaired-osv`; в ячейке `correction_ids_debit/credit` (применённые корректировки правила).
|
||||
`…/preset/{rule_id}/unpaired-osv`.
|
||||
`GET …/elimination-rules` отдаёт объект `{version_no, is_version_fixed, rules}` (у правила есть `id`): при незаданной
|
||||
версии правил — открытые правила (`valid_to IS NULL`). Ошибки PRESET: 422 `RULE_REQUIRED`, `INVALID_RULE`,
|
||||
`ACCOUNTS_REQUIRED`; правило недействительное для версии или несуществующее — 404. В шапке xlsx — строка «Показатель»,
|
||||
|
||||
@ -31,7 +31,6 @@ from src.models.directories import CompanyGroup, LegalEntity, LegalEntityAlias,
|
||||
from src.models.enums import (
|
||||
ConsolidationApproach,
|
||||
ConsolidationStatus,
|
||||
CorrectionStatus,
|
||||
DocumentStatus,
|
||||
DocumentType,
|
||||
FileStatus,
|
||||
@ -41,7 +40,6 @@ from src.models.enums import (
|
||||
RelatedGroupKind,
|
||||
)
|
||||
from src.models.files import Document, StoredFile
|
||||
from src.models.kfo import Correction
|
||||
from src.models.osv import OsvEntry
|
||||
from src.repositories.directories import LIKE_ESCAPE, escape_like
|
||||
|
||||
@ -565,22 +563,3 @@ async def current_related_groups(
|
||||
for entity_id, group in await session.execute(stmt):
|
||||
groups[entity_id][group.kind] = group
|
||||
return dict(groups)
|
||||
|
||||
|
||||
async def correction_for_version_consolidation(
|
||||
session: AsyncSession, version_id: uuid.UUID, rule_id: uuid.UUID
|
||||
) -> list[Correction]:
|
||||
"""Применённые корректировки правила для версии консолидации."""
|
||||
if not version_id or not rule_id:
|
||||
return []
|
||||
|
||||
stmt = (
|
||||
select(Correction)
|
||||
.where(
|
||||
Correction.consolidation_version_id == version_id,
|
||||
Correction.rule_id == rule_id,
|
||||
Correction.status == CorrectionStatus.APPLIED,
|
||||
)
|
||||
.order_by(Correction.id)
|
||||
)
|
||||
return list((await session.scalars(stmt)).all())
|
||||
|
||||
@ -367,8 +367,6 @@ class IntercompanyMatrixCellOut(BaseModel):
|
||||
)
|
||||
osv_entry_ids_debit: list[uuid.UUID]
|
||||
osv_entry_ids_credit: list[uuid.UUID]
|
||||
correction_ids_debit: list[uuid.UUID] = Field(default_factory=list)
|
||||
correction_ids_credit: list[uuid.UUID] = Field(default_factory=list)
|
||||
|
||||
@field_validator("amount_a", "amount_b", "variance_amount", "variance_percent")
|
||||
@classmethod
|
||||
|
||||
@ -17,7 +17,6 @@ from src.models.accounting import ChartOfAccount, EliminationRule
|
||||
from src.models.consolidation import Consolidation, ConsolidationVersion
|
||||
from src.models.directories import CompanyGroup
|
||||
from src.models.enums import AccountKind, PeriodQuarter
|
||||
from src.repositories import consolidations as consolidation_repo
|
||||
from src.repositories import directories as directory_repo
|
||||
from src.repositories import elimination_rules as elimination_rules_repo
|
||||
from src.schemas.consolidations import (
|
||||
@ -407,63 +406,6 @@ class IntercompanyMatrixService:
|
||||
unmatched = get_unpaired_rows(result.rows, result.matrix)
|
||||
return UnpairedOsvOut(items=[row_out(row) for row in unmatched], total=len(unmatched))
|
||||
|
||||
async def _apply_corrections(
|
||||
self, matrix: IntercompanyMatrixOut, version_id: uuid.UUID, rule_id: uuid.UUID
|
||||
) -> IntercompanyMatrixOut:
|
||||
"""Исключение суммы применённых корректировок из сторон пары пресета."""
|
||||
corrections = await consolidation_repo.correction_for_version_consolidation(
|
||||
self._session, version_id=version_id, rule_id=rule_id
|
||||
)
|
||||
if not corrections:
|
||||
return matrix
|
||||
|
||||
debit_by_pair: dict[tuple[uuid.UUID, uuid.UUID], Decimal] = defaultdict(lambda: ZERO)
|
||||
credit_by_pair: dict[tuple[uuid.UUID, uuid.UUID], Decimal] = defaultdict(lambda: ZERO)
|
||||
debit_ids_by_pair: dict[tuple[uuid.UUID, uuid.UUID], set[uuid.UUID]] = defaultdict(set)
|
||||
credit_ids_by_pair: dict[tuple[uuid.UUID, uuid.UUID], set[uuid.UUID]] = defaultdict(set)
|
||||
for correction in corrections:
|
||||
owner, counterparty = correction.legal_entity_id, correction.counterparty_id
|
||||
if owner is None or counterparty is None:
|
||||
continue
|
||||
pair = (owner, counterparty)
|
||||
if correction.debit_adjustment is not None:
|
||||
debit_by_pair[pair] += correction.debit_adjustment
|
||||
debit_ids_by_pair[pair].add(correction.id)
|
||||
if correction.credit_adjustment is not None:
|
||||
credit_by_pair[pair] += correction.credit_adjustment
|
||||
credit_ids_by_pair[pair].add(correction.id)
|
||||
|
||||
cells = []
|
||||
for cell in matrix.cells:
|
||||
debit_pair = (cell.company_a_id, cell.company_b_id)
|
||||
credit_pair = (cell.company_b_id, cell.company_a_id)
|
||||
amount_a = cell.amount_a - debit_by_pair.get(debit_pair, ZERO)
|
||||
amount_b = cell.amount_b - credit_by_pair.get(credit_pair, ZERO)
|
||||
debit_ids = list(debit_ids_by_pair.get(debit_pair, ()))
|
||||
credit_ids = list(credit_ids_by_pair.get(credit_pair, ()))
|
||||
if not debit_ids and not credit_ids:
|
||||
cells.append(cell)
|
||||
continue
|
||||
variance_amount = abs(amount_a - amount_b)
|
||||
base = min(amount_a, amount_b)
|
||||
variance_percent = None if base == ZERO else variance_amount / base * 100
|
||||
cells.append(
|
||||
IntercompanyMatrixCellOut.model_validate(
|
||||
{
|
||||
**cell.model_dump(),
|
||||
"amount_a": amount_a,
|
||||
"amount_b": amount_b,
|
||||
"correction_ids_debit": debit_ids,
|
||||
"correction_ids_credit": credit_ids,
|
||||
"variance_amount": variance_amount,
|
||||
"variance_percent": variance_percent,
|
||||
"exceeds_threshold": variance_percent is not None
|
||||
and variance_percent > VARIANCE_THRESHOLD_PERCENT,
|
||||
}
|
||||
)
|
||||
)
|
||||
return IntercompanyMatrixOut(companies=matrix.companies, cells=cells)
|
||||
|
||||
async def _resolve_preset_selection(
|
||||
self,
|
||||
rule_id: uuid.UUID | None,
|
||||
@ -514,7 +456,6 @@ class IntercompanyMatrixService:
|
||||
rows = osv_result.consolidated.rows
|
||||
accounts = await directory_repo.list_accounts(self._session)
|
||||
by_id, children = _make_account_tree(accounts)
|
||||
rule: EliminationRule | None = None
|
||||
if mode == "ALL":
|
||||
if debit_account_ids or credit_account_ids:
|
||||
|
|
||||
raise DomainValidationError("ACCOUNTS_NOT_ALLOWED", "Для режима ALL не нужно указывать счета")
|
||||
@ -528,12 +469,10 @@ class IntercompanyMatrixService:
|
||||
credit = _select_accounts(credit_account_ids, (), "K", by_id, children)
|
||||
selection = MatrixSelection(debit, credit, "closing")
|
||||
elif mode == "PRESET":
|
||||
selection, rule = await self._resolve_preset_selection(rule_id, osv_result.version, by_id, children)
|
||||
selection, _ = await self._resolve_preset_selection(rule_id, osv_result.version, by_id, children)
|
||||
else:
|
||||
raise DomainValidationError("INVALID_MODE", "Неизвестный режим выбора счетов")
|
||||
matrix = self._calculate(rows, osv_result.members, selection)
|
||||
if rule is not None:
|
||||
matrix = await self._apply_corrections(matrix, version_id, rule.id)
|
||||
return MatrixBuildResult(
|
||||
matrix=matrix,
|
||||
version=osv_result.version,
|
||||
|
||||
@ -133,8 +133,6 @@ async def test_no_osv_for_selected_accounts(auth_client: AuthClientFactory, seed
|
||||
assert {
|
||||
"osv_entry_ids_debit",
|
||||
"osv_entry_ids_credit",
|
||||
"correction_ids_debit",
|
||||
"correction_ids_credit",
|
||||
"exceeds_threshold",
|
||||
} <= cell.keys()
|
||||
assert {"entry_osv_ids_debit", "entry_osv_ids_credit", "is_more_5_percent"}.isdisjoint(cell)
|
||||
@ -142,7 +140,6 @@ async def test_no_osv_for_selected_accounts(auth_client: AuthClientFactory, seed
|
||||
assert cell["variance_percent"] is None
|
||||
assert cell["one_sided"] is False
|
||||
assert cell["osv_entry_ids_debit"] == cell["osv_entry_ids_credit"] == []
|
||||
assert cell["correction_ids_debit"] == cell["correction_ids_credit"] == []
|
||||
assert cell["skipped_osv_entry_count"] == 0
|
||||
|
||||
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
"""Запрос корректировок к строкам ОСВ версии консолидации."""
|
||||
|
||||
import uuid
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
from src.repositories.consolidations import correction_for_version_consolidation
|
||||
|
||||
|
||||
async def test_correction_query_returns_all_applied_records_without_matching_osv() -> None:
|
||||
session = AsyncMock()
|
||||
corrections = [object(), object()]
|
||||
session.scalars.return_value = SimpleNamespace(all=lambda: corrections)
|
||||
version_id, rule_id = uuid.uuid4(), uuid.uuid4()
|
||||
|
||||
assert await correction_for_version_consolidation(session, version_id, rule_id) == corrections
|
||||
|
||||
stmt = session.scalars.await_args.args[0]
|
||||
sql = str(stmt.compile(dialect=postgresql.dialect()))
|
||||
assert "FROM dkb.correction" in sql
|
||||
assert "osv_entry" not in sql
|
||||
assert "correction.consolidation_version_id" in sql
|
||||
assert "correction.rule_id" in sql
|
||||
assert "correction.status" in sql
|
||||
|
||||
|
||||
async def test_correction_query_requires_version_and_rule() -> None:
|
||||
session = AsyncMock()
|
||||
|
||||
assert await correction_for_version_consolidation(session, None, uuid.uuid4()) == []
|
||||
assert await correction_for_version_consolidation(session, uuid.uuid4(), None) == []
|
||||
session.scalars.assert_not_awaited()
|
||||
@ -82,7 +82,6 @@ def test_routes_are_separate_and_matrix_expands_manual_accounts() -> None:
|
||||
]
|
||||
assert result.cells[0].amount_a == Decimal("100")
|
||||
assert result.cells[0].amount_b == Decimal("90")
|
||||
assert result.cells[0].correction_ids_debit == result.cells[0].correction_ids_credit == []
|
||||
assert result.cells[0].variance_percent == Decimal("11.11")
|
||||
assert isinstance(result, IntercompanyMatrixOut)
|
||||
response = result
|
||||
@ -143,7 +142,6 @@ async def test_preset_applies_exclusions_to_its_own_side_and_rule_measure(monkey
|
||||
monkeypatch.setattr(
|
||||
matrix.elimination_rules_repo, "rule_with_account", AsyncMock(return_value=(rule, rule_accounts))
|
||||
)
|
||||
monkeypatch.setattr(matrix.consolidation_repo, "correction_for_version_consolidation", AsyncMock(return_value=[]))
|
||||
session = SimpleNamespace(execute=AsyncMock(return_value=SimpleNamespace(scalar_one=lambda: "ГК")))
|
||||
service = matrix.IntercompanyMatrixService(session, None, osv_service)
|
||||
captured = []
|
||||
@ -164,79 +162,6 @@ async def test_preset_applies_exclusions_to_its_own_side_and_rule_measure(monkey
|
||||
assert info.measure == "turnover"
|
||||
|
||||
|
||||
async def test_preset_corrections_exclude_amounts_without_changing_osv(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
company_a, company_b = uuid.uuid4(), uuid.uuid4()
|
||||
debit_account, credit_account = uuid.uuid4(), uuid.uuid4()
|
||||
debit_row = _row(company_a, company_b, debit_account, debit="1500")
|
||||
credit_row = _row(company_b, company_a, credit_account, credit="1500")
|
||||
debit_row.entry_ids = (uuid.uuid4(),)
|
||||
credit_row.entry_ids = (uuid.uuid4(),)
|
||||
companies = [
|
||||
IntercompanyMatrixCompanyOut(id=company_a, name="Компания А"),
|
||||
IntercompanyMatrixCompanyOut(id=company_b, name="Компания Б"),
|
||||
]
|
||||
original = matrix.calculate_matrix(
|
||||
[debit_row, credit_row],
|
||||
companies,
|
||||
matrix.MatrixSelection(frozenset({debit_account}), frozenset({credit_account}), "closing"),
|
||||
)
|
||||
debit_correction_id, credit_correction_id, child_correction_id = uuid.uuid4(), uuid.uuid4(), uuid.uuid4()
|
||||
corrections = [
|
||||
SimpleNamespace(
|
||||
id=debit_correction_id,
|
||||
legal_entity_id=company_a,
|
||||
counterparty_id=company_b,
|
||||
debit_adjustment=Decimal("1000"),
|
||||
credit_adjustment=None,
|
||||
),
|
||||
SimpleNamespace(
|
||||
id=credit_correction_id,
|
||||
legal_entity_id=company_b,
|
||||
counterparty_id=company_a,
|
||||
debit_adjustment=None,
|
||||
credit_adjustment=Decimal("500"),
|
||||
),
|
||||
SimpleNamespace(
|
||||
id=child_correction_id,
|
||||
legal_entity_id=company_b,
|
||||
counterparty_id=company_a,
|
||||
debit_adjustment=None,
|
||||
credit_adjustment=Decimal("500"),
|
||||
),
|
||||
]
|
||||
monkeypatch.setattr(
|
||||
matrix.consolidation_repo, "correction_for_version_consolidation", AsyncMock(return_value=corrections)
|
||||
)
|
||||
|
||||
adjusted = await matrix.IntercompanyMatrixService(object(), None, object())._apply_corrections(
|
||||
original, uuid.uuid4(), uuid.uuid4()
|
||||
)
|
||||
|
||||
assert adjusted.cells[0].amount_a == Decimal("500")
|
||||
assert adjusted.cells[0].amount_b == Decimal("500")
|
||||
assert adjusted.cells[0].variance_amount == Decimal("0")
|
||||
assert adjusted.cells[0].osv_entry_ids_debit == [debit_row.entry_ids[0]]
|
||||
assert adjusted.cells[0].osv_entry_ids_credit == [credit_row.entry_ids[0]]
|
||||
assert adjusted.cells[0].correction_ids_debit == [debit_correction_id]
|
||||
assert set(adjusted.cells[0].correction_ids_credit) == {credit_correction_id, child_correction_id}
|
||||
assert adjusted.cells[0].model_dump(mode="json")["correction_ids_debit"] == [str(debit_correction_id)]
|
||||
assert original.cells[0].correction_ids_debit == original.cells[0].correction_ids_credit == []
|
||||
assert original.cells[0].amount_a == Decimal("1500")
|
||||
assert original.cells[0].amount_b == Decimal("1500")
|
||||
assert credit_row.closing_credit == Decimal("1500")
|
||||
|
||||
|
||||
async def test_preset_without_corrections_keeps_matrix(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
original = matrix.IntercompanyMatrixOut(companies=[], cells=[])
|
||||
monkeypatch.setattr(matrix.consolidation_repo, "correction_for_version_consolidation", AsyncMock(return_value=[]))
|
||||
|
||||
adjusted = await matrix.IntercompanyMatrixService(object(), None, object())._apply_corrections(
|
||||
original, uuid.uuid4(), uuid.uuid4()
|
||||
)
|
||||
|
||||
assert adjusted is original
|
||||
|
||||
|
||||
def test_one_sided_reflects_osv_sources_even_when_amount_is_zero() -> None:
|
||||
company_a, company_b = uuid.uuid4(), uuid.uuid4()
|
||||
debit_account, credit_account = uuid.uuid4(), uuid.uuid4()
|
||||
|
||||
@ -134,14 +134,6 @@ def test_matrix_export_has_three_rows_per_debit_company_and_highlights_threshold
|
||||
for offset in range(4)
|
||||
)
|
||||
|
||||
debit_correction_id = UUID("796d1add-eaed-4802-8c79-8b3cdae2cca1")
|
||||
credit_correction_id = UUID("55555555-5555-5555-5555-555555555555")
|
||||
matrix.cells[0].correction_ids_debit = [debit_correction_id]
|
||||
matrix.cells[0].correction_ids_credit = [credit_correction_id]
|
||||
preset_sheet = load_workbook(BytesIO(build_matrix_workbook(matrix, _info(mode="PRESET")))).active
|
||||
assert preset_sheet is not None
|
||||
assert preset_sheet["D12"].comment is None
|
||||
assert preset_sheet["D13"].comment is None
|
||||
|
||||
|
||||
async def test_export_routes_use_matrix_calculation() -> None:
|
||||
|
||||
@ -37,7 +37,7 @@ change не входит. Шахматка — чистая функция от
|
||||
3. **Корректировки из шахматки убираются** (решение 4 выше и `correction_ids_*` в ячейке). Причины: корректировки в
|
||||
ядре никто не создаёт (спринт корректировок), семантика ключа `(rule, A, B)` относительно ячейки (A, B) / (B, A) не
|
||||
утверждена, счета корректировки и `parent_correction_id` не учитывались; §6 описывает шахматку как суммы первички.
|
||||
Код сохранён в ветке `wip/shahmatka-corrections-unpaired` (`0e95f95`) и возвращается после решения по аналитике
|
||||
Код корректировок выделен в ветку `AURORA-1747` и возвращается после решения по аналитике
|
||||
AURORA-1643 «Учитывание корректировок в шахматке».
|
||||
4. **Ручка `…/preset/{rule_id}/unpaired-osv` убирается** (решение 5 выше). Причины: «без пары» по наличию строк
|
||||
(дефект AURORA-1651), ложные срабатывания при пересечении счетов сторон (76 в правиле № 6), нет ячейки и стороны
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
## Why
|
||||
|
||||
Шахматка ВГО (ТЗ §6) считалась только по всем счетам (ALL) или по счетам, выбранным вручную (MANUAL). Аналитику нужен
|
||||
режим «пресет»: счета и показатель берутся из правила элиминации (Прил. 3), с учётом применённых корректировок и со
|
||||
режим «пресет»: счета и показатель берутся из правила элиминации (Прил. 3) и со
|
||||
списком строк сводной ОСВ без пары. Реализация — PR RSHB/arm-core#141 (ветка `add-preset-shahmatka`, автор — Потапова).
|
||||
Требования оформлены как дельты этого change'а при ревью (решение владельца 21.10.2026); спорное поведение вынесено в
|
||||
`design.md`, `## Known issues`, и в спеке не закреплено как окончательное.
|
||||
@ -10,8 +10,7 @@
|
||||
|
||||
- Режим PRESET шахматки: `GET …/intercompany-matrix/preset/{rule_id}`, выгрузка `…/preset/{rule_id}/export`, список
|
||||
строк без пары `…/preset/{rule_id}/unpaired-osv`.
|
||||
- Показатель пресета (`closing` / `turnover`) берётся из правила; в ячейке появляются `correction_ids_debit/credit`,
|
||||
суммы уменьшаются на применённые корректировки правила.
|
||||
- Показатель пресета (`closing` / `turnover`) берётся из правила.
|
||||
- `GET …/elimination-rules` возвращает объект `{version_no, is_version_fixed, rules}` вместо массива; у правила есть
|
||||
`id`. Для версии без зафиксированного `elimination_rules_version` отдаются открытые правила (`valid_to IS NULL`).
|
||||
- xlsx: для PRESET имя файла с `_preset-<rule_id>`, в шапке строка «Показатель»; audit `EXPORT` пишет `mode`
|
||||
@ -24,11 +23,11 @@
|
||||
|
||||
### Modified Capabilities
|
||||
- `consolidations-api`: ответ правил элиминации версии.
|
||||
- `consolidated-osv`: режим PRESET шахматки, корректировки, строки без пары, xlsx пресета.
|
||||
- `consolidated-osv`: режим PRESET шахматки, строки без пары, xlsx пресета.
|
||||
- `audit-trail`: аудит экспорта шахматки (режим PRESET).
|
||||
|
||||
## Impact
|
||||
|
||||
Только `arm-core` (API, сервисы, схемы), таблицы и DBML не меняются. Ломающее изменение контракта
|
||||
`GET …/elimination-rules` (массив → объект); поле `as_of` в ответ не входит. Потребителей старого формата в этом репозитории не проверялось — проверить при слиянии. Non-goals: фиксация версии правил, расчёт «актуальных» правил на отчётную дату, создание корректировок,
|
||||
`GET …/elimination-rules` (массив → объект); поле `as_of` в ответ не входит. Потребителей старого формата в этом репозитории не проверялось — проверить при слиянии. Non-goals: фиксация версии правил, расчёт «актуальных» правил на отчётную дату, создание и применение корректировок,
|
||||
исправление `one_sided` (AURORA-1651).
|
||||
|
||||
@ -28,26 +28,6 @@
|
||||
- **WHEN** `rule_id` не существует
|
||||
- **THEN** 404
|
||||
|
||||
### Requirement: Корректировки в шахматке пресета
|
||||
В режиме PRESET расчёт SHALL учитывать корректировки `correction` со статусом `APPLIED`, у которых
|
||||
`consolidation_version_id` равен версии, а `rule_id` — правилу пресета. Корректировка с `legal_entity_id = A` и
|
||||
`counterparty_id = B` SHALL уменьшать `amount_a` ячейки `(A, B)` на `debit_adjustment` и `amount_b` ячейки `(B, A)` на
|
||||
`credit_adjustment`. Затронутые ячейки SHALL получать пересчитанные `variance_amount`, `variance_percent`,
|
||||
`exceeds_threshold` и ID корректировок в `correction_ids_debit`/`correction_ids_credit`; у остальных ячеек эти массивы
|
||||
пусты (поля есть в ответе всех режимов). Корректировки без `legal_entity_id` или `counterparty_id` SHALL игнорироваться.
|
||||
|
||||
#### Scenario: Корректировка по дебету
|
||||
- **WHEN** есть применённая корректировка правила `(A, B)` с `debit_adjustment = 10`
|
||||
- **THEN** у ячейки `(A, B)` `amount_a` меньше на 10, расхождение пересчитано, `correction_ids_debit` содержит её ID
|
||||
|
||||
#### Scenario: Корректировка по кредиту
|
||||
- **WHEN** есть применённая корректировка правила `(A, B)` с `credit_adjustment = 5`
|
||||
- **THEN** у ячейки `(B, A)` `amount_b` меньше на 5, `correction_ids_credit` содержит её ID
|
||||
|
||||
#### Scenario: Корректировка чужого правила или не применённая
|
||||
- **WHEN** корректировка относится к другому правилу либо имеет статус не `APPLIED`
|
||||
- **THEN** суммы ячеек не меняются, `correction_ids_*` пусты
|
||||
|
||||
### Requirement: Строки сводной ОСВ без пары по пресету
|
||||
`GET /api/v1/consolidations/versions/{version_id}/intercompany-matrix/preset/{rule_id}/unpaired-osv`
|
||||
(`CONSOLIDATION_VIEW`, policy) SHALL возвращать `{items, total}`: все строки сводной ОСВ версии, чьи записи ОСВ
|
||||
|
||||
@ -5,8 +5,9 @@
|
||||
|
||||
## 2. Доработки по решениям владельца 2026-10-21 (автор)
|
||||
|
||||
- [ ] 2.1 Отдельным коммитом убрать учёт корректировок (`_apply_corrections`, `correction_for_version_consolidation`,
|
||||
`correction_ids_*`) и ручку `unpaired-osv` (`get_unpaired_rows`, `UnpairedOsvOut`, маршрут) вместе с тестами;
|
||||
- [x] 2.1 Отдельным коммитом убрать учёт корректировок (`_apply_corrections`, `correction_for_version_consolidation`,
|
||||
`correction_ids_*`) вместе с тестами; код выделен в `AURORA-1747`.
|
||||
- [ ] 2.1a Убрать ручку `unpaired-osv` (`get_unpaired_rows`, `UnpairedOsvOut`, маршрут) вместе с тестами;
|
||||
код сохранён в `wip/shahmatka-corrections-unpaired`.
|
||||
- [ ] 2.2 PRESET — только правила `statement_type = balance`; правило ОФР — 422 `INVALID_RULE`, тест.
|
||||
- [ ] 2.3 Несколько открытых `version_no` — одна версия (max) или явная ошибка, тест.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user
Тут все же буду настаивать. Когда функция\метод возвращает два значения это еще туда сюда, но когда уже больше - код превращается в месиво. Не очевидно, какой параметр возвращается каким (например, надо помнить, что объект MatrixSelection возвращается 5, нужно заходить в определение функции и отсчитывать, в каком он месте. К тому же, если тебе нужен только 2 каких-то придется писать либо matrix, _, _, _, selection, _ = self._build_accounts(...) либо built_account = self._build_account(...)\matrix, selection = built_account[0], built_account[4]). Исходя из вышеперечисленного предлагаю сделать в файле класс
Ну либо через pydantic аналогичный. Вроде _build_account только в двух местах вызывается, там поправить получение даннх в связи с этим
Ну и, соответственно, получение данных теперь будет matrix = (await self._build_account(...)).matrix или просто брать built_account = await self._build_account(...) и далее просто брать че надо, built_account.matrix или там built_account.selection и т д
исправила