fix(core): stabilize editor lifecycle, transactional versions, and runtime config

This commit is contained in:
greebo
2026-03-20 12:38:10 +03:00
parent 0f9c2a1cbd
commit 239b32a246
17 changed files with 1224 additions and 457 deletions

View File

@@ -2,12 +2,10 @@ from fastapi import APIRouter, Depends, Query
from app.core.config import settings
from app.repositories.audit import create_audit_event
from app.repositories.scheme_groups import clone_scheme_version_groups
from app.repositories.scheme_seats import clone_scheme_version_seats
from app.repositories.scheme_sectors import clone_scheme_version_sectors
from app.repositories.scheme_versions import (
count_scheme_versions,
create_next_scheme_version_from_current,
create_next_scheme_version_from_current_checked,
ensure_draft_scheme_version_consistent,
get_current_scheme_version,
list_scheme_versions,
)
@@ -34,26 +32,12 @@ from app.schemas.scheme_versions import (
SchemeVersionListResponse,
)
from app.security.auth import require_api_key
from app.services.api_errors import raise_conflict
from app.services.publish_service import publish_current_draft_scheme
from app.services.scheme_validation import build_scheme_validation_report
router = APIRouter()
def _build_stale_current_version_detail(
*,
expected_scheme_version_id: str,
actual_scheme_version_id: str,
) -> dict:
return {
"code": "stale_current_version",
"message": "Current scheme version changed. Reload scheme state before creating a new version.",
"expected_scheme_version_id": expected_scheme_version_id,
"actual_scheme_version_id": actual_scheme_version_id,
}
@router.get(f"{settings.api_v1_prefix}/schemes", response_model=SchemeListResponse)
async def get_schemes(
limit: int = Query(default=50, ge=1, le=200),
@@ -155,36 +139,9 @@ async def create_next_scheme_version_endpoint(
expected_current_scheme_version_id: str | None = Query(default=None),
role: str = Depends(require_api_key),
):
current_scheme = await get_scheme_record_by_scheme_id(scheme_id)
current_version = await get_current_scheme_version(
scheme_id=current_scheme.scheme_id,
current_version_number=current_scheme.current_version_number,
)
if (
expected_current_scheme_version_id
and expected_current_scheme_version_id != current_version.scheme_version_id
):
raise_conflict(
_build_stale_current_version_detail(
expected_scheme_version_id=expected_current_scheme_version_id,
actual_scheme_version_id=current_version.scheme_version_id,
)
)
new_version = await create_next_scheme_version_from_current(scheme_id)
await clone_scheme_version_sectors(
source_scheme_version_id=current_version.scheme_version_id,
target_scheme_version_id=new_version.scheme_version_id,
)
await clone_scheme_version_groups(
source_scheme_version_id=current_version.scheme_version_id,
target_scheme_version_id=new_version.scheme_version_id,
)
await clone_scheme_version_seats(
source_scheme_version_id=current_version.scheme_version_id,
target_scheme_version_id=new_version.scheme_version_id,
current_version, new_version = await create_next_scheme_version_from_current_checked(
scheme_id=scheme_id,
expected_current_scheme_version_id=expected_current_scheme_version_id,
)
await create_audit_event(
@@ -214,26 +171,14 @@ async def ensure_draft_scheme_version(
expected_current_scheme_version_id: str | None = Query(default=None),
role: str = Depends(require_api_key),
):
scheme = await get_scheme_record_by_scheme_id(scheme_id)
current_version = await get_current_scheme_version(
scheme_id=scheme.scheme_id,
current_version_number=scheme.current_version_number,
current_version, created, source_scheme_version_id = await ensure_draft_scheme_version_consistent(
scheme_id=scheme_id,
expected_current_scheme_version_id=expected_current_scheme_version_id,
)
if (
expected_current_scheme_version_id
and expected_current_scheme_version_id != current_version.scheme_version_id
):
raise_conflict(
_build_stale_current_version_detail(
expected_scheme_version_id=expected_current_scheme_version_id,
actual_scheme_version_id=current_version.scheme_version_id,
)
)
if scheme.status == "draft" and current_version.status == "draft":
if not created:
return EnsureDraftResponse(
scheme_id=scheme.scheme_id,
scheme_id=current_version.scheme_id,
scheme_version_id=current_version.scheme_version_id,
version_number=current_version.version_number,
status=current_version.status,
@@ -242,42 +187,27 @@ async def ensure_draft_scheme_version(
source_scheme_version_id=None,
)
new_version = await create_next_scheme_version_from_current(scheme_id)
await clone_scheme_version_sectors(
source_scheme_version_id=current_version.scheme_version_id,
target_scheme_version_id=new_version.scheme_version_id,
)
await clone_scheme_version_groups(
source_scheme_version_id=current_version.scheme_version_id,
target_scheme_version_id=new_version.scheme_version_id,
)
await clone_scheme_version_seats(
source_scheme_version_id=current_version.scheme_version_id,
target_scheme_version_id=new_version.scheme_version_id,
)
await create_audit_event(
scheme_id=scheme_id,
event_type="scheme.version.created",
object_type="scheme_version",
object_ref=new_version.scheme_version_id,
object_ref=current_version.scheme_version_id,
details={
"source_scheme_version_id": current_version.scheme_version_id,
"version_number": new_version.version_number,
"normalized_storage_path": new_version.normalized_storage_path,
"source_scheme_version_id": source_scheme_version_id,
"version_number": current_version.version_number,
"normalized_storage_path": current_version.normalized_storage_path,
"reason": "ensure_draft",
},
)
return EnsureDraftResponse(
scheme_id=new_version.scheme_id,
scheme_version_id=new_version.scheme_version_id,
version_number=new_version.version_number,
status=new_version.status,
normalized_storage_path=new_version.normalized_storage_path,
scheme_id=current_version.scheme_id,
scheme_version_id=current_version.scheme_version_id,
version_number=current_version.version_number,
status=current_version.status,
normalized_storage_path=current_version.normalized_storage_path,
created=True,
source_scheme_version_id=current_version.scheme_version_id,
source_scheme_version_id=source_scheme_version_id,
)