Use registration master for service catalogue scope types
This commit is contained in:
@@ -14,6 +14,7 @@ from app.modules.core.audit.service import model_snapshot, pair_before_after, wr
|
||||
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
|
||||
from app.modules.core.rbac.permission_guard import require_permission
|
||||
from app.modules.core.tenancy.models import Branch
|
||||
from app.modules.registrations.models import RegistrationType
|
||||
from app.modules.services.models import FirmServiceSelection, FirmServiceTaskTemplate, ServiceCatalogue, ServiceCategory, ServiceDefaultTaskTemplate, ServiceDueDateRule, FirmTaskDocumentRequirement, FirmTaskDocumentTemplate
|
||||
from app.modules.services.bulk_imports import (
|
||||
build_template as build_bulk_import_template,
|
||||
@@ -87,6 +88,50 @@ def _render(request: Request, template: str, db, user, **ctx):
|
||||
return templates.TemplateResponse(template, _base_ctx(request, user, db, **ctx))
|
||||
|
||||
|
||||
def _active_registration_types(db):
|
||||
"""Return the active Registration Type master rows used by Service Catalogue forms."""
|
||||
return db.execute(
|
||||
select(RegistrationType)
|
||||
.where(RegistrationType.is_active.is_(True))
|
||||
.order_by(RegistrationType.sort_order, RegistrationType.name, RegistrationType.code)
|
||||
).scalars().all()
|
||||
|
||||
|
||||
def _registration_type_form_context(db):
|
||||
registration_types = _active_registration_types(db)
|
||||
return {
|
||||
"registration_types": registration_types,
|
||||
"registration_type_codes": [row.code.upper() for row in registration_types],
|
||||
}
|
||||
|
||||
|
||||
def _validated_registration_type_code(db, value: str, *, existing_value: str | None = None) -> str | None:
|
||||
"""Validate a submitted catalogue registration code against Registration Type master.
|
||||
|
||||
Existing non-master legacy values are allowed only when left unchanged so editing an
|
||||
unrelated field never destroys historical catalogue data. New/changed values must be
|
||||
active Registration Type master codes.
|
||||
"""
|
||||
code = (value or "").strip().upper()
|
||||
if not code:
|
||||
return None
|
||||
|
||||
exists = db.execute(
|
||||
select(RegistrationType.id).where(
|
||||
RegistrationType.code == code,
|
||||
RegistrationType.is_active.is_(True),
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
if exists is not None:
|
||||
return code
|
||||
|
||||
current = (existing_value or "").strip().upper()
|
||||
if current and code == current:
|
||||
return code
|
||||
|
||||
raise ValueError("registration_type")
|
||||
|
||||
|
||||
def _redirect_denied():
|
||||
from app.core.http_responses import ui_access_denied
|
||||
return ui_access_denied()
|
||||
@@ -476,7 +521,7 @@ def catalogue_create_page(request: Request):
|
||||
if not _is_system_admin(db, user):
|
||||
return _redirect_denied()
|
||||
require_permission(db, user, 'services.create')
|
||||
return _render(request, 'modules/services/templates/services/catalogue_form.html', db, user, title='Create Service Catalogue', mode='create', catalogue=None, categories=list_categories(db))
|
||||
return _render(request, 'modules/services/templates/services/catalogue_form.html', db, user, title='Create Service Catalogue', mode='create', catalogue=None, categories=list_categories(db), **_registration_type_form_context(db))
|
||||
except Exception:
|
||||
return _redirect_denied()
|
||||
finally:
|
||||
@@ -495,6 +540,10 @@ def catalogue_create_submit(request: Request, service_code: str = Form(...), ser
|
||||
return _redirect_denied()
|
||||
require_permission(db, user, 'services.create')
|
||||
selected_category = get_category(db, int(category_id)) if str(category_id).strip() else None
|
||||
try:
|
||||
registration_type_code = _validated_registration_type_code(db, required_registration_type)
|
||||
except ValueError:
|
||||
return RedirectResponse(url='/services/catalogue/new?error=registration_type', status_code=303)
|
||||
row = ServiceCatalogue(
|
||||
service_code=normalize_code(service_code),
|
||||
service_name=service_name.strip(),
|
||||
@@ -503,7 +552,7 @@ def catalogue_create_submit(request: Request, service_code: str = Form(...), ser
|
||||
recurrence_type=recurrence_type.strip() or None,
|
||||
engagement_type=normalize_engagement_type(engagement_type),
|
||||
service_scope_type=(service_scope_type or 'client').strip().lower(),
|
||||
required_registration_type=(required_registration_type or '').strip().upper() or None,
|
||||
required_registration_type=registration_type_code,
|
||||
sort_order=sort_order,
|
||||
description=description.strip() or None,
|
||||
applicable_individual=applicable_individual is not None,
|
||||
@@ -806,7 +855,7 @@ def catalogue_edit_page(request: Request, catalogue_id: int):
|
||||
row = get_catalogue(db, catalogue_id)
|
||||
if not row or not row.is_active:
|
||||
return RedirectResponse(url='/services/catalogue', status_code=303)
|
||||
return _render(request, 'modules/services/templates/services/catalogue_form.html', db, user, title='Edit Service Catalogue', mode='edit', catalogue=row, categories=list_categories(db))
|
||||
return _render(request, 'modules/services/templates/services/catalogue_form.html', db, user, title='Edit Service Catalogue', mode='edit', catalogue=row, categories=list_categories(db), **_registration_type_form_context(db))
|
||||
except Exception:
|
||||
return _redirect_denied()
|
||||
finally:
|
||||
@@ -828,13 +877,22 @@ def catalogue_edit_submit(request: Request, catalogue_id: int, service_name: str
|
||||
if not row or not row.is_active:
|
||||
return RedirectResponse(url='/services/catalogue', status_code=303)
|
||||
selected_category = get_category(db, int(category_id)) if str(category_id).strip() else None
|
||||
try:
|
||||
registration_type_code = _validated_registration_type_code(
|
||||
db, required_registration_type, existing_value=row.required_registration_type
|
||||
)
|
||||
except ValueError:
|
||||
return RedirectResponse(
|
||||
url=f'/services/catalogue/{catalogue_id}/edit?error=registration_type',
|
||||
status_code=303,
|
||||
)
|
||||
row.service_name = service_name.strip()
|
||||
row.category_id = selected_category.id if selected_category else None
|
||||
row.category = selected_category.name if selected_category else None
|
||||
row.recurrence_type = recurrence_type.strip() or None
|
||||
row.engagement_type = normalize_engagement_type(engagement_type)
|
||||
row.service_scope_type = (service_scope_type or 'client').strip().lower()
|
||||
row.required_registration_type = (required_registration_type or '').strip().upper() or None
|
||||
row.required_registration_type = registration_type_code
|
||||
row.sort_order = sort_order
|
||||
row.applicable_individual = applicable_individual is not None
|
||||
row.applicable_proprietorship = applicable_proprietorship is not None
|
||||
|
||||
Reference in New Issue
Block a user