feat(backend): add operational smoke tooling and safe pricing cleanup endpoints

- add backend README and refresh API map and smoke regression docs
- add full backend smoke regression script
- add admin pricing cleanup preview and dry-run endpoints
- add helper script for test pricing cleanup
- verify typed error contracts, draft flow, publish readiness and preview flows
- verify publish preview retention and clean backend startup behavior
This commit is contained in:
greebo
2026-03-19 22:54:12 +03:00
parent 127c5bff71
commit 0f9c2a1cbd
16 changed files with 551 additions and 235 deletions

View File

@@ -1,6 +1,7 @@
from fastapi import APIRouter
from app.api.routes.admin import router as admin_router
from app.api.routes.admin_cleanup import router as admin_cleanup_router
from app.api.routes.audit import router as audit_router
from app.api.routes.editor import router as editor_router
from app.api.routes.pricing import router as pricing_router
@@ -22,5 +23,6 @@ router.include_router(pricing_diagnostics_router)
router.include_router(test_mode_router)
router.include_router(audit_router)
router.include_router(admin_router)
router.include_router(admin_cleanup_router)
router.include_router(editor_router)
router.include_router(publish_router)

View File

@@ -0,0 +1,55 @@
from fastapi import APIRouter, Depends, Query
from app.core.config import settings
from app.schemas.admin_cleanup import (
PricingCleanupExecuteRequest,
PricingCleanupExecuteResponse,
PricingCleanupPreviewResponse,
)
from app.security.auth import require_api_key
from app.services.pricing_cleanup import (
build_pricing_cleanup_preview,
execute_pricing_cleanup,
)
router = APIRouter()
@router.get(
f"{settings.api_v1_prefix}/admin/schemes/{{scheme_id}}/pricing/categories/cleanup-preview",
response_model=PricingCleanupPreviewResponse,
)
async def get_pricing_cleanup_preview(
scheme_id: str,
code_prefix: list[str] = Query(default_factory=list),
name_prefix: list[str] = Query(default_factory=list),
pricing_category_id: list[str] = Query(default_factory=list),
delete_only_without_rules: bool = Query(default=True),
role: str = Depends(require_api_key),
):
return await build_pricing_cleanup_preview(
scheme_id=scheme_id,
code_prefixes=code_prefix,
name_prefixes=name_prefix,
pricing_category_ids=pricing_category_id,
delete_only_without_rules=delete_only_without_rules,
)
@router.post(
f"{settings.api_v1_prefix}/admin/schemes/{{scheme_id}}/pricing/categories/cleanup",
response_model=PricingCleanupExecuteResponse,
)
async def post_pricing_cleanup(
scheme_id: str,
payload: PricingCleanupExecuteRequest,
role: str = Depends(require_api_key),
):
return await execute_pricing_cleanup(
scheme_id=scheme_id,
code_prefixes=payload.code_prefixes,
name_prefixes=payload.name_prefixes,
pricing_category_ids=payload.pricing_category_ids,
delete_only_without_rules=payload.delete_only_without_rules,
dry_run=payload.dry_run,
)