enhanced generic navigation tree
This commit is contained in:
parent
d98c31a4d1
commit
ab48e2e853
9 changed files with 44 additions and 15 deletions
|
|
@ -28,7 +28,7 @@ class UserMandate(BaseModel):
|
||||||
)
|
)
|
||||||
mandateId: str = Field(
|
mandateId: str = Field(
|
||||||
description="FK → Mandate.id (CASCADE DELETE)",
|
description="FK → Mandate.id (CASCADE DELETE)",
|
||||||
json_schema_extra={"frontend_type": "select", "frontend_readonly": False, "frontend_required": True, "frontend_fk_source": "/api/mandates/", "frontend_fk_display_field": "name"}
|
json_schema_extra={"frontend_type": "select", "frontend_readonly": False, "frontend_required": True, "frontend_fk_source": "/api/mandates/", "frontend_fk_display_field": "label"}
|
||||||
)
|
)
|
||||||
enabled: bool = Field(
|
enabled: bool = Field(
|
||||||
default=True,
|
default=True,
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class Role(BaseModel):
|
||||||
mandateId: Optional[str] = Field(
|
mandateId: Optional[str] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
description="FK → Mandate.id (CASCADE DELETE). Null = Global/Template role.",
|
description="FK → Mandate.id (CASCADE DELETE). Null = Global/Template role.",
|
||||||
json_schema_extra={"frontend_type": "select", "frontend_readonly": True, "frontend_visible": True, "frontend_required": False, "frontend_fk_source": "/api/mandates/", "frontend_fk_display_field": "name"}
|
json_schema_extra={"frontend_type": "select", "frontend_readonly": True, "frontend_visible": True, "frontend_required": False, "frontend_fk_source": "/api/mandates/", "frontend_fk_display_field": "label"}
|
||||||
)
|
)
|
||||||
featureInstanceId: Optional[str] = Field(
|
featureInstanceId: Optional[str] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,10 @@ class Mandate(BaseModel):
|
||||||
description="Name of the mandate",
|
description="Name of the mandate",
|
||||||
json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": True}
|
json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": True}
|
||||||
)
|
)
|
||||||
description: Optional[str] = Field(
|
label: Optional[str] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
description="Description of the mandate",
|
description="Display label of the mandate",
|
||||||
json_schema_extra={"frontend_type": "textarea", "frontend_readonly": False, "frontend_required": False}
|
json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": False}
|
||||||
)
|
)
|
||||||
enabled: bool = Field(
|
enabled: bool = Field(
|
||||||
default=True,
|
default=True,
|
||||||
|
|
@ -104,7 +104,7 @@ registerModelLabels(
|
||||||
{
|
{
|
||||||
"id": {"en": "ID", "de": "ID", "fr": "ID"},
|
"id": {"en": "ID", "de": "ID", "fr": "ID"},
|
||||||
"name": {"en": "Name", "de": "Name", "fr": "Nom"},
|
"name": {"en": "Name", "de": "Name", "fr": "Nom"},
|
||||||
"description": {"en": "Description", "de": "Beschreibung", "fr": "Description"},
|
"label": {"en": "Label", "de": "Label", "fr": "Libellé"},
|
||||||
"enabled": {"en": "Enabled", "de": "Aktiviert", "fr": "Activé"},
|
"enabled": {"en": "Enabled", "de": "Aktiviert", "fr": "Activé"},
|
||||||
"isSystem": {"en": "System Mandate", "de": "System-Mandant", "fr": "Mandat système"},
|
"isSystem": {"en": "System Mandate", "de": "System-Mandant", "fr": "Mandat système"},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ def initBootstrap(db: DatabaseConnector) -> None:
|
||||||
# Initialize root mandate
|
# Initialize root mandate
|
||||||
mandateId = initRootMandate(db)
|
mandateId = initRootMandate(db)
|
||||||
|
|
||||||
|
# Migrate existing mandate records: description -> label
|
||||||
|
_migrateMandateDescriptionToLabel(db)
|
||||||
|
|
||||||
# Initialize system role TEMPLATES (mandateId=None, isSystemRole=True)
|
# Initialize system role TEMPLATES (mandateId=None, isSystemRole=True)
|
||||||
initRoles(db)
|
initRoles(db)
|
||||||
|
|
||||||
|
|
@ -276,6 +279,32 @@ def initRootMandate(db: DatabaseConnector) -> Optional[str]:
|
||||||
return mandateId
|
return mandateId
|
||||||
|
|
||||||
|
|
||||||
|
def _migrateMandateDescriptionToLabel(db: DatabaseConnector) -> None:
|
||||||
|
"""
|
||||||
|
Migration: Rename 'description' field to 'label' in all Mandate records.
|
||||||
|
Copies existing 'description' values to 'label' and removes the old field.
|
||||||
|
Safe to run multiple times (idempotent).
|
||||||
|
"""
|
||||||
|
allMandates = db.getRecordset(Mandate)
|
||||||
|
migratedCount = 0
|
||||||
|
for mandateRecord in allMandates:
|
||||||
|
mandateId = mandateRecord.get("id")
|
||||||
|
hasDescription = "description" in mandateRecord and mandateRecord.get("description") is not None
|
||||||
|
hasLabel = "label" in mandateRecord and mandateRecord.get("label") is not None
|
||||||
|
|
||||||
|
if hasDescription and not hasLabel:
|
||||||
|
# Copy description to label
|
||||||
|
updateData = {"label": mandateRecord["description"]}
|
||||||
|
db.recordModify(Mandate, mandateId, updateData)
|
||||||
|
migratedCount += 1
|
||||||
|
logger.info(f"Migrated mandate {mandateId}: description -> label")
|
||||||
|
|
||||||
|
if migratedCount > 0:
|
||||||
|
logger.info(f"Migrated {migratedCount} mandate(s) from description to label")
|
||||||
|
else:
|
||||||
|
logger.debug("No mandate description->label migration needed")
|
||||||
|
|
||||||
|
|
||||||
def initAdminUser(db: DatabaseConnector, mandateId: Optional[str]) -> Optional[str]:
|
def initAdminUser(db: DatabaseConnector, mandateId: Optional[str]) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Creates the Admin user if it doesn't exist.
|
Creates the Admin user if it doesn't exist.
|
||||||
|
|
|
||||||
|
|
@ -1444,7 +1444,7 @@ class AppObjects:
|
||||||
|
|
||||||
return Mandate(**filteredMandates[0])
|
return Mandate(**filteredMandates[0])
|
||||||
|
|
||||||
def createMandate(self, name: str, description: str = None, enabled: bool = True) -> Mandate:
|
def createMandate(self, name: str, label: str = None, enabled: bool = True) -> Mandate:
|
||||||
"""
|
"""
|
||||||
Creates a new mandate if user has permission.
|
Creates a new mandate if user has permission.
|
||||||
Automatically copies system template roles (admin, user, viewer) to the new mandate.
|
Automatically copies system template roles (admin, user, viewer) to the new mandate.
|
||||||
|
|
@ -1453,7 +1453,7 @@ class AppObjects:
|
||||||
raise PermissionError("No permission to create mandates")
|
raise PermissionError("No permission to create mandates")
|
||||||
|
|
||||||
# Create mandate data using model
|
# Create mandate data using model
|
||||||
mandateData = Mandate(name=name, description=description, enabled=enabled)
|
mandateData = Mandate(name=name, label=label, enabled=enabled)
|
||||||
|
|
||||||
# Create mandate record
|
# Create mandate record
|
||||||
createdRecord = self.db.recordCreate(Mandate, mandateData)
|
createdRecord = self.db.recordCreate(Mandate, mandateData)
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ def getBalanceForMandate(
|
||||||
from modules.interfaces.interfaceDbApp import getInterface as getAppInterface
|
from modules.interfaces.interfaceDbApp import getInterface as getAppInterface
|
||||||
appInterface = getAppInterface(ctx.user, mandateId=targetMandateId)
|
appInterface = getAppInterface(ctx.user, mandateId=targetMandateId)
|
||||||
mandate = appInterface.getMandate(targetMandateId)
|
mandate = appInterface.getMandate(targetMandateId)
|
||||||
mandateName = mandate.get("name", "") if mandate else ""
|
mandateName = (mandate.get("label") or mandate.get("name", "")) if mandate else ""
|
||||||
|
|
||||||
return BillingBalanceResponse(
|
return BillingBalanceResponse(
|
||||||
mandateId=targetMandateId,
|
mandateId=targetMandateId,
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ def create_mandate(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get optional fields with defaults
|
# Get optional fields with defaults
|
||||||
description = mandateData.get('description')
|
label = mandateData.get('label')
|
||||||
enabled = mandateData.get('enabled', True)
|
enabled = mandateData.get('enabled', True)
|
||||||
|
|
||||||
appInterface = interfaceDbApp.getRootInterface()
|
appInterface = interfaceDbApp.getRootInterface()
|
||||||
|
|
@ -200,7 +200,7 @@ def create_mandate(
|
||||||
# Create mandate
|
# Create mandate
|
||||||
newMandate = appInterface.createMandate(
|
newMandate = appInterface.createMandate(
|
||||||
name=name,
|
name=name,
|
||||||
description=description,
|
label=label,
|
||||||
enabled=enabled
|
enabled=enabled
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ def create_invitation(
|
||||||
from modules.connectors.connectorMessagingEmail import ConnectorMessagingEmail
|
from modules.connectors.connectorMessagingEmail import ConnectorMessagingEmail
|
||||||
# Get mandate name for the email
|
# Get mandate name for the email
|
||||||
mandate = rootInterface.getMandate(str(context.mandateId))
|
mandate = rootInterface.getMandate(str(context.mandateId))
|
||||||
mandateName = mandate.name if mandate else "PowerOn"
|
mandateName = (mandate.label or mandate.name) if mandate else "PowerOn"
|
||||||
|
|
||||||
emailConnector = ConnectorMessagingEmail()
|
emailConnector = ConnectorMessagingEmail()
|
||||||
emailSubject = f"Einladung zu {mandateName}"
|
emailSubject = f"Einladung zu {mandateName}"
|
||||||
|
|
@ -249,7 +249,7 @@ def create_invitation(
|
||||||
|
|
||||||
# Get mandate name for notification
|
# Get mandate name for notification
|
||||||
mandate = rootInterface.getMandate(str(context.mandateId))
|
mandate = rootInterface.getMandate(str(context.mandateId))
|
||||||
mandateName = mandate.mandateLabel if mandate and mandate.mandateLabel else "PowerOn"
|
mandateName = (mandate.label or mandate.name) if mandate else "PowerOn"
|
||||||
inviterName = context.user.fullName or context.user.username
|
inviterName = context.user.fullName or context.user.username
|
||||||
|
|
||||||
createInvitationNotification(
|
createInvitationNotification(
|
||||||
|
|
@ -529,7 +529,7 @@ def validate_invitation(
|
||||||
# Get mandate name
|
# Get mandate name
|
||||||
mandate = rootInterface.getMandate(str(mandateId)) if mandateId else None
|
mandate = rootInterface.getMandate(str(mandateId)) if mandateId else None
|
||||||
if mandate:
|
if mandate:
|
||||||
mandateName = mandate.name
|
mandateName = mandate.label or mandate.name
|
||||||
|
|
||||||
# Get role names
|
# Get role names
|
||||||
roleIds = invitation.roleIds or []
|
roleIds = invitation.roleIds or []
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ def _buildDynamicBlock(
|
||||||
mandateId = str(instance.mandateId)
|
mandateId = str(instance.mandateId)
|
||||||
if mandateId not in mandatesMap:
|
if mandateId not in mandatesMap:
|
||||||
mandate = rootInterface.getMandate(mandateId)
|
mandate = rootInterface.getMandate(mandateId)
|
||||||
mandateName = mandate.name if mandate and hasattr(mandate, 'name') else mandateId
|
mandateName = (mandate.label or mandate.name) if mandate else mandateId
|
||||||
mandatesMap[mandateId] = {
|
mandatesMap[mandateId] = {
|
||||||
"id": mandateId,
|
"id": mandateId,
|
||||||
"uiLabel": mandateName,
|
"uiLabel": mandateName,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue