fix(#237): разнесение — без строк вне периметра и «сам на себя» (AURORA-2034)
§5 п. 2a: в агрегаты и нераспределённые идут только строки между разными компаниями периметра версии; строка с ручным решением аналитика остаётся видна. На копии стенда нераспределённых РБ 2025 К1 — 37 → 3, РБ 2024 К3 — 31 → 3 (вместе с «76-исключениями»). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d13a9554a1
commit
3296e4a849
@ -100,17 +100,23 @@ def distribute_vgo_rows(data: DistributionInput) -> Distribution:
|
|||||||
for row in data.rows:
|
for row in data.rows:
|
||||||
if not used.isdisjoint(row.entry_ids):
|
if not used.isdisjoint(row.entry_ids):
|
||||||
continue
|
continue
|
||||||
rule_ids = rules_for(data.owners, row.account_id, row_side(row.closing_debit, row.closing_credit))
|
manual = row.entry_ids in data.manual_keys
|
||||||
if (
|
# §5 п. 2a: разносятся только строки между разными компаниями периметра; строка с контрагентом вне периметра
|
||||||
row.entry_ids not in data.manual_keys
|
# или «сам на себя» в таблицу не попадает, если по ней нет ручного решения аналитика (AURORA-2034)
|
||||||
and len(rule_ids) == 1
|
in_perimeter = (
|
||||||
and (
|
|
||||||
row.legal_entity_id in data.members
|
row.legal_entity_id in data.members
|
||||||
and row.counterparty_id in data.members
|
and row.counterparty_id in data.members
|
||||||
and (row.closing_debit not in (None, ZERO) or row.closing_credit not in (None, ZERO))
|
and row.legal_entity_id != row.counterparty_id
|
||||||
)
|
)
|
||||||
|
if not manual and not in_perimeter:
|
||||||
|
continue
|
||||||
|
rule_ids = rules_for(data.owners, row.account_id, row_side(row.closing_debit, row.closing_credit))
|
||||||
|
if (
|
||||||
|
not manual
|
||||||
|
and len(rule_ids) == 1
|
||||||
|
and (row.closing_debit not in (None, ZERO) or row.closing_credit not in (None, ZERO))
|
||||||
):
|
):
|
||||||
auto_rules[row.entry_ids] = next(iter(rule_ids))
|
auto_rules[row.entry_ids] = next(iter(rule_ids))
|
||||||
elif rule_ids or row.entry_ids in data.manual_keys:
|
elif rule_ids or manual:
|
||||||
unassigned.add(row.entry_ids)
|
unassigned.add(row.entry_ids)
|
||||||
return Distribution(selected, auto_rules, frozenset(unassigned), frozenset(used))
|
return Distribution(selected, auto_rules, frozenset(unassigned), frozenset(used))
|
||||||
|
|||||||
@ -131,6 +131,45 @@ def test_credit_row_is_matched_by_credit_side_rules_only() -> None:
|
|||||||
assert distribution.unassigned == {debit_row.entry_ids}
|
assert distribution.unassigned == {debit_row.entry_ids}
|
||||||
|
|
||||||
|
|
||||||
|
def test_rows_outside_perimeter_or_to_itself_are_not_unallocated() -> None:
|
||||||
|
"""Разносятся только строки между компаниями периметра (§5 п. 2a): контрагент вне периметра и «сам на себя»
|
||||||
|
в нераспределённые не попадают; ручное решение аналитика по такой строке сохраняется (AURORA-2034)."""
|
||||||
|
rule_5, rule_6, account, company_a, company_b, outsider = (uuid.uuid4() for _ in range(6))
|
||||||
|
inside = _row(uuid.uuid4(), company_a, company_b, 1)
|
||||||
|
outside = _row(uuid.uuid4(), company_a, outsider, 2)
|
||||||
|
to_itself = _row(uuid.uuid4(), company_a, company_a, 3)
|
||||||
|
to_itself_single = _row(uuid.uuid4(), company_b, company_b, 4)
|
||||||
|
outside_manual = _row(uuid.uuid4(), company_a, outsider, 5)
|
||||||
|
for row in (inside, outside, to_itself, to_itself_single, outside_manual):
|
||||||
|
row.account_id = account
|
||||||
|
owners = account_owners([(rule_5, {account}, set()), (rule_6, {account}, {account})])
|
||||||
|
single = account_owners([(rule_6, {account}, set())])
|
||||||
|
distribution = distribute_vgo_rows(
|
||||||
|
DistributionInput(
|
||||||
|
rows=[inside, outside, to_itself, outside_manual],
|
||||||
|
exact_ids=set(),
|
||||||
|
diff_ids=[],
|
||||||
|
manual_keys={outside_manual.entry_ids},
|
||||||
|
owners=owners,
|
||||||
|
members={company_a, company_b},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert distribution.unassigned == {inside.entry_ids, outside_manual.entry_ids}
|
||||||
|
assert distribution.auto_rules == {}
|
||||||
|
single_distribution = distribute_vgo_rows(
|
||||||
|
DistributionInput(
|
||||||
|
rows=[to_itself_single],
|
||||||
|
exact_ids=set(),
|
||||||
|
diff_ids=[],
|
||||||
|
manual_keys=set(),
|
||||||
|
owners=single,
|
||||||
|
members={company_a, company_b},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert single_distribution.auto_rules == {}
|
||||||
|
assert single_distribution.unassigned == frozenset()
|
||||||
|
|
||||||
|
|
||||||
async def test_unallocated_credit_row_offers_only_credit_side_rules(monkeypatch: pytest.MonkeyPatch) -> None:
|
async def test_unallocated_credit_row_offers_only_credit_side_rules(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
"""Меню «Отнести к правилу» Кт-строки — только правила, где счёт на стороне кредита (AURORA-2034)."""
|
"""Меню «Отнести к правилу» Кт-строки — только правила, где счёт на стороне кредита (AURORA-2034)."""
|
||||||
version_id, company_a, company_b, rule_1, rule_2, rule_3, account = (uuid.uuid4() for _ in range(7))
|
version_id, company_a, company_b, rule_1, rule_2, rule_3, account = (uuid.uuid4() for _ in range(7))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user