автоматическое проставление версии правил при создании консолидация, если таких создается версия консолидации создается с NULL
This commit is contained in:
parent
22facb3ddf
commit
232fecec39
@ -2,6 +2,7 @@
|
||||
|
||||
import uuid
|
||||
from collections.abc import Collection
|
||||
from datetime import date
|
||||
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@ -44,6 +45,16 @@ async def current_open_version_no(session: AsyncSession) -> int | None:
|
||||
return await session.scalar(_current_open_version_stmt())
|
||||
|
||||
|
||||
async def latest_effective_version_no(session: AsyncSession, as_of: date) -> int | None:
|
||||
"""Максимальный номер версии правил, действующей на дату создания"""
|
||||
return await session.scalar(
|
||||
select(func.max(EliminationRule.version_no)).where(
|
||||
EliminationRule.valid_from <= as_of,
|
||||
(EliminationRule.valid_to.is_(None) | (EliminationRule.valid_to >= as_of)),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def is_valid_for_version(rule: EliminationRule | None, version_no: int | None) -> bool:
|
||||
"""Проверить версию правила §4 либо отсутствие `valid_to`."""
|
||||
return rule is not None and (rule.version_no == version_no if version_no is not None else rule.valid_to is None)
|
||||
|
||||
@ -16,7 +16,7 @@ from collections.abc import Sequence
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.api.dependencies.audit import RequestAudit
|
||||
from src.common.clock import utc_now
|
||||
from src.common.clock import moscow_date, utc_now
|
||||
from src.common.exceptions import ConflictError, DomainValidationError, NotFoundError
|
||||
from src.domain import checklist as checklist_domain
|
||||
from src.domain.consolidation_periods import quarters_through, reporting_date
|
||||
@ -40,6 +40,7 @@ from src.models.enums import (
|
||||
)
|
||||
from src.repositories import consolidations as repo
|
||||
from src.repositories import directories as directories_repo
|
||||
from src.repositories import elimination_rules as elimination_rules_repo
|
||||
from src.repositories.users import UserWithAccess
|
||||
from src.schemas.consolidations import (
|
||||
ChecklistCellOut,
|
||||
@ -347,6 +348,9 @@ class ConsolidationService:
|
||||
scenario=ConsolidationScenario.CREATE,
|
||||
approach=ConsolidationApproach.BASIC,
|
||||
goodwill_enabled=False,
|
||||
elimination_rules_version=await elimination_rules_repo.latest_effective_version_no(
|
||||
self._session, moscow_date(now)
|
||||
),
|
||||
initiator_id=user.id,
|
||||
initiator_office_id=user.regional_office_id,
|
||||
is_in_work=True,
|
||||
|
||||
@ -4,13 +4,16 @@
|
||||
|
||||
import uuid
|
||||
from collections.abc import Sequence
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.common.clock import moscow_date, utc_now
|
||||
from src.models.access import AppUser
|
||||
from src.models.accounting import EliminationRule
|
||||
from src.models.audit_ex import AuditEvent
|
||||
from src.models.consolidation import (
|
||||
Consolidation,
|
||||
@ -139,6 +142,7 @@ async def test_create_consolidation_rb_q3_2024(auth_client: AuthClientFactory, s
|
||||
assert str(consolidation.id) == card["consolidation_id"]
|
||||
version = (await seeded.execute(select(ConsolidationVersion))).scalar_one()
|
||||
assert (version.initiator_id, version.created_by, version.is_in_work) == (user.id, user.id, True)
|
||||
assert version.elimination_rules_version == 1
|
||||
assert await _count(seeded, ConsolidationLock) == 0
|
||||
assert await _count(seeded, ConsolidationMember) == len(entities)
|
||||
assert await _count(seeded, ConsolidationStatusHistory) == 1
|
||||
@ -162,6 +166,44 @@ async def test_create_consolidation_rb_q3_2024(auth_client: AuthClientFactory, s
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_create_fixes_rules_for_creation_date_not_reporting_period(
|
||||
auth_client: AuthClientFactory, seeded: AsyncSession
|
||||
) -> None:
|
||||
group, gsk, _ = await _scenario(seeded)
|
||||
today = moscow_date(utc_now())
|
||||
source = (await seeded.scalars(select(EliminationRule).where(EliminationRule.rule_no == 1))).one()
|
||||
next_rule = EliminationRule(
|
||||
statement_type=source.statement_type,
|
||||
rule_no=source.rule_no,
|
||||
article_1_line=source.article_1_line,
|
||||
article_2_line=source.article_2_line,
|
||||
side_1=source.side_1,
|
||||
measure=source.measure,
|
||||
elimination_mode=source.elimination_mode,
|
||||
excise_adjust=source.excise_adjust,
|
||||
version_no=2,
|
||||
valid_from=today + timedelta(days=1),
|
||||
)
|
||||
seeded.add(next_rule)
|
||||
await seeded.flush()
|
||||
client = await auth_client(KA_RF)
|
||||
|
||||
first = await client.post(CONSOLIDATIONS, json=_body(group, gsk, year=2024))
|
||||
assert first.status_code == HTTP_CREATED, first.text
|
||||
first_version = await seeded.get(ConsolidationVersion, uuid.UUID(first.json()["id"]))
|
||||
assert first_version is not None
|
||||
assert first_version.elimination_rules_version == 1
|
||||
|
||||
next_rule.valid_from = today
|
||||
second = await client.post(CONSOLIDATIONS, json=_body(group, gsk, year=2023))
|
||||
assert second.status_code == HTTP_CREATED, second.text
|
||||
second_version = await seeded.get(ConsolidationVersion, uuid.UUID(second.json()["id"]))
|
||||
assert second_version is not None
|
||||
assert second_version.elimination_rules_version == next_rule.version_no
|
||||
assert first_version.elimination_rules_version == 1
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_create_reporting_date_for_q4_is_next_year(auth_client: AuthClientFactory, seeded: AsyncSession) -> None:
|
||||
group, gsk, _ = await _scenario(seeded)
|
||||
|
||||
@ -15,7 +15,13 @@ Q3 → 01.10.year, Q4 → 01.01.year+1; ASSUMPTION(OQ-40)), `consolidation_versi
|
||||
`is_in_work = true`), `consolidation_member` периметра (`is_head_entity = false`), первую запись
|
||||
`consolidation_status_history` (`from_status` NULL → `INITIATED`), подхват подтверждённых документов ЮЛ периметра (см.
|
||||
`documents-api` «Подхват документов») и одно событие `audit_event(CONSOLIDATION_CREATE)`, у которого
|
||||
`after_value.members` — отсортированный список ЮЛ периметра; ответ 201 с карточкой версии. Периметр SHALL быть: без
|
||||
`after_value.members` — отсортированный список ЮЛ периметра; ответ 201 с карточкой версии.
|
||||
При создании версии система SHALL автоматически записать в `consolidation_version.elimination_rules_version` номер
|
||||
самой актуальной версии правил: максимальный `version_no` среди правил, действующих на московскую календарную дату
|
||||
создания версии (`valid_from <= дата` и `valid_to IS NULL` либо `valid_to >= дата`; OQ-174, docs PR #146).
|
||||
Пользователь не выбирает версию правил. Отчётные год, квартал и `reporting_date` не влияют на определение номера.
|
||||
Если на дату создания нет действующих правил, поле остаётся NULL.
|
||||
Периметр SHALL быть: без
|
||||
`legal_entity_ids` (поле отсутствует или `null`) — текущие члены ГСК; с `legal_entity_ids` — ровно эти ЮЛ после
|
||||
схлопывания дублей (порядок первого вхождения), каждое SHALL принадлежать ГК консолидации
|
||||
(`legal_entity.company_group_id`), иначе 422 `ENTITY_NOT_IN_GROUP` с перечнем `legal_entity_ids` чужих в порядке
|
||||
@ -33,6 +39,10 @@ SHALL оставаться NULL (фиксируется при верифика
|
||||
- **THEN** 201; версия №1 `INITIATED`, `reporting_date = 2024-10-01`, два `consolidation_member`, история с одной записью,
|
||||
`audit_event(CONSOLIDATION_CREATE)` с `consolidation_version_id`; активной блокировки нет
|
||||
|
||||
#### Scenario: Правила действуют на дату создания версии
|
||||
- **WHEN** в день создания консолидации за 2024 год действует версия правил 2, а версия 1 действовала в отчётном периоде
|
||||
- **THEN** `consolidation_version.elimination_rules_version = 2`; номер не меняется при последующей публикации правил
|
||||
|
||||
#### Scenario: Выбранный периметр шире ГСК
|
||||
- **WHEN** в ГК три ЮЛ, в ГСК два из них, создаётся консолидация с `legal_entity_ids` из всех трёх ЮЛ ГК
|
||||
- **THEN** 201; в `members` три ЮЛ; `after_value.members` события `CONSOLIDATION_CREATE` — три ЮЛ; состав ГСК не изменился
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user