Implement display artifacts, pricing integrity, draft base and publish preview bundle

This commit is contained in:
greebo
2026-03-19 17:58:17 +03:00
parent 85fb2f4bb9
commit c91c5abf15
35 changed files with 3283 additions and 302 deletions

View File

@@ -8,6 +8,7 @@ from lxml import etree
from app.core.config import settings
from app.repositories.pricing import find_effective_price_rule
from app.repositories.scheme_artifacts import get_latest_scheme_artifact
from app.repositories.scheme_groups import list_scheme_version_groups
from app.repositories.scheme_seats import get_scheme_version_seat_by_seat_id, list_scheme_version_seats
from app.repositories.scheme_sectors import list_scheme_version_sectors
@@ -66,13 +67,29 @@ async def _load_current_context(scheme_id: str):
return scheme, version, upload
async def _generate_default_display_artifact_if_needed(scheme, version, upload) -> tuple[bytes, Path]:
async def _load_default_display_artifact(scheme, version, upload) -> tuple[bytes, Path]:
artifact = await get_latest_scheme_artifact(
scheme_version_id=version.scheme_version_id,
artifact_type="display_svg",
artifact_variant=settings.svg_display_mode,
)
if artifact is not None:
path = Path(artifact.storage_path)
if path.exists() and path.is_file():
return path.read_bytes(), path
if version.display_svg_status == "ready" and version.display_svg_storage_path:
path = Path(version.display_svg_storage_path)
if path.exists() and path.is_file():
return path.read_bytes(), path
sanitized_path = Path(upload.sanitized_storage_path)
sanitized_artifact = await get_latest_scheme_artifact(
scheme_version_id=version.scheme_version_id,
artifact_type="sanitized_svg",
artifact_variant="source",
)
sanitized_path = Path(sanitized_artifact.storage_path if sanitized_artifact else upload.sanitized_storage_path)
if not sanitized_path.exists() or not sanitized_path.is_file():
if version.display_svg_status == "pending":
raise HTTPException(
@@ -106,6 +123,16 @@ async def _generate_default_display_artifact_if_needed(scheme, version, upload)
)
display_path = Path(display_path_str)
from app.repositories.scheme_artifacts import create_scheme_artifact
await create_scheme_artifact(
scheme_id=scheme.scheme_id,
scheme_version_id=version.scheme_version_id,
artifact_type="display_svg",
artifact_variant=settings.svg_display_mode,
storage_path=display_path_str,
status="ready",
meta_json=meta,
)
await update_scheme_version_display_artifact(
scheme_version_id=version.scheme_version_id,
display_svg_storage_path=display_path_str,
@@ -113,14 +140,6 @@ async def _generate_default_display_artifact_if_needed(scheme, version, upload)
display_svg_generated_at=datetime.now(timezone.utc),
)
logger.info(
"display_svg.lazy_generate scheme_id=%s scheme_version_id=%s mode=%s view_box=%s",
scheme.scheme_id,
version.scheme_version_id,
settings.svg_display_mode,
meta.get("view_box"),
)
return display_bytes, display_path
@@ -253,11 +272,16 @@ async def get_scheme_current_display_svg(
scheme, version, upload = await _load_current_context(scheme_id)
if resolved_mode == settings.svg_display_mode:
display_bytes, display_path = await _generate_default_display_artifact_if_needed(scheme, version, upload)
_display_bytes, display_path = await _load_default_display_artifact(scheme, version, upload)
filename = f"{scheme.name or scheme.scheme_id}.{resolved_mode}.svg"
return FileResponse(path=display_path, media_type="image/svg+xml", filename=filename)
sanitized_path = Path(upload.sanitized_storage_path)
artifact = await get_latest_scheme_artifact(
scheme_version_id=version.scheme_version_id,
artifact_type="sanitized_svg",
artifact_variant="source",
)
sanitized_path = Path(artifact.storage_path if artifact else upload.sanitized_storage_path)
if not sanitized_path.exists() or not sanitized_path.is_file():
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -292,11 +316,16 @@ async def get_scheme_current_display_svg_meta(
scheme, version, upload = await _load_current_context(scheme_id)
if resolved_mode == settings.svg_display_mode:
display_bytes, _display_path = await _generate_default_display_artifact_if_needed(scheme, version, upload)
display_bytes, _display_path = await _load_default_display_artifact(scheme, version, upload)
meta = _parse_svg_meta_from_bytes(display_bytes)
generated_at = version.display_svg_generated_at
else:
sanitized_path = Path(upload.sanitized_storage_path)
artifact = await get_latest_scheme_artifact(
scheme_version_id=version.scheme_version_id,
artifact_type="sanitized_svg",
artifact_variant="source",
)
sanitized_path = Path(artifact.storage_path if artifact else upload.sanitized_storage_path)
if not sanitized_path.exists() or not sanitized_path.is_file():
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -305,7 +334,7 @@ async def get_scheme_current_display_svg_meta(
sanitized_bytes = sanitized_path.read_bytes()
try:
display_bytes, meta = generate_display_svg(sanitized_bytes, resolved_mode)
display_bytes, _meta = generate_display_svg(sanitized_bytes, resolved_mode)
except Exception:
logger.exception(
"display_svg.meta_on_demand failed scheme_id=%s scheme_version_id=%s mode=%s",