Mix calculator
This commit is contained in:
@@ -17,6 +17,7 @@ MODULE_CATALOG = (
|
||||
("dashboard", "Dashboard", "workspace", "Top-level operational dashboard"),
|
||||
("raw_materials", "Raw Materials", "costing", "Maintain live material costs and versions"),
|
||||
("mix_master", "Mix Master", "costing", "Create and maintain mix worksheets"),
|
||||
("mix_calculator", "Mix Calculator", "production", "Create and review client-specific mix calculation sessions"),
|
||||
("products", "Products", "pricing", "Review finished product pricing"),
|
||||
("scenarios", "Scenarios", "planning", "Run scenario overrides and comparisons"),
|
||||
("powerbi_export", "Power BI Export", "reporting", "Expose client access data to BI consumers"),
|
||||
@@ -43,6 +44,7 @@ def client_access_query() -> Select[tuple[ClientAccount]]:
|
||||
|
||||
def list_client_accounts(db: Session) -> list[ClientAccount]:
|
||||
ensure_client_user_module_permissions(db)
|
||||
ensure_client_feature_access(db)
|
||||
return db.scalars(client_access_query()).all()
|
||||
|
||||
|
||||
@@ -50,9 +52,19 @@ def get_client_user_by_email(db: Session, *, email: str, tenant_id: str | None =
|
||||
statement = select(ClientUser).where(ClientUser.email == email)
|
||||
if tenant_id:
|
||||
statement = statement.where(ClientUser.tenant_id == tenant_id)
|
||||
return db.scalar(
|
||||
user = db.scalar(
|
||||
statement.options(selectinload(ClientUser.module_permissions)).order_by(ClientUser.id.desc())
|
||||
)
|
||||
if user is None:
|
||||
return None
|
||||
|
||||
if ensure_user_module_permissions(db, user):
|
||||
db.commit()
|
||||
return db.scalar(
|
||||
statement.options(selectinload(ClientUser.module_permissions)).order_by(ClientUser.id.desc())
|
||||
)
|
||||
|
||||
return user
|
||||
|
||||
|
||||
def module_access_map(user: ClientUser) -> dict[str, str]:
|
||||
@@ -66,13 +78,15 @@ def has_access_level(access_level: str | None, minimum_level: str) -> bool:
|
||||
def default_access_level_for_role(role: str, module_key: str) -> str:
|
||||
normalized = role.strip().lower()
|
||||
if normalized == "superadmin":
|
||||
return "manage" if module_key == "client_access" else "edit"
|
||||
return "manage" if module_key in {"client_access", "mix_calculator"} else "edit"
|
||||
if normalized == "admin":
|
||||
if module_key == "mix_calculator":
|
||||
return "manage"
|
||||
return "edit" if module_key != "client_access" else "none"
|
||||
if normalized == "operator":
|
||||
return "edit" if module_key in {"dashboard", "raw_materials", "mix_master", "products", "scenarios"} else "none"
|
||||
return "edit" if module_key in {"dashboard", "raw_materials", "mix_master", "mix_calculator", "products", "scenarios"} else "none"
|
||||
if normalized == "viewer":
|
||||
return "view" if module_key in {"dashboard", "products", "powerbi_export"} else "none"
|
||||
return "view" if module_key in {"dashboard", "mix_calculator", "products", "powerbi_export"} else "none"
|
||||
return "none"
|
||||
|
||||
|
||||
@@ -106,6 +120,45 @@ def ensure_client_user_module_permissions(db: Session) -> None:
|
||||
db.commit()
|
||||
|
||||
|
||||
def ensure_client_feature_access(db: Session) -> None:
|
||||
clients = db.scalars(
|
||||
select(ClientAccount).options(
|
||||
selectinload(ClientAccount.users).selectinload(ClientUser.module_permissions),
|
||||
selectinload(ClientAccount.features),
|
||||
)
|
||||
).all()
|
||||
changed = False
|
||||
|
||||
for client in clients:
|
||||
existing_feature_keys = {feature.feature_key for feature in client.features}
|
||||
permission_levels: dict[str, str] = {}
|
||||
|
||||
for user in client.users:
|
||||
for permission in user.module_permissions:
|
||||
current_level = permission_levels.get(permission.module_key, "none")
|
||||
if ACCESS_LEVEL_ORDER.get(permission.access_level, 0) > ACCESS_LEVEL_ORDER.get(current_level, 0):
|
||||
permission_levels[permission.module_key] = permission.access_level
|
||||
|
||||
for feature_key, feature_name, feature_group, description in MODULE_CATALOG:
|
||||
if feature_key in existing_feature_keys:
|
||||
continue
|
||||
db.add(
|
||||
ClientFeatureAccess(
|
||||
tenant_id=client.tenant_id,
|
||||
client_account_id=client.id,
|
||||
feature_key=feature_key,
|
||||
feature_name=feature_name,
|
||||
feature_group=feature_group,
|
||||
description=description,
|
||||
enabled=has_access_level(permission_levels.get(feature_key), "view"),
|
||||
)
|
||||
)
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
db.commit()
|
||||
|
||||
|
||||
def serialize_client_user(user: ClientUser) -> dict:
|
||||
return {
|
||||
"id": user.id,
|
||||
|
||||
Reference in New Issue
Block a user