From eef9a0136561d626c472e6839bd61b7b818651dc Mon Sep 17 00:00:00 2001 From: A R R R Associates Date: Thu, 3 Sep 2026 15:29:08 +0530 Subject: [PATCH] Allow staff email correction and sync linked login email --- app/modules/employees/service.py | 65 ++++++++++++++++++- .../employees/templates/employees/form.html | 6 +- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/app/modules/employees/service.py b/app/modules/employees/service.py index 92b7a02..cda614b 100644 --- a/app/modules/employees/service.py +++ b/app/modules/employees/service.py @@ -13,6 +13,7 @@ from sqlalchemy.orm import Session, selectinload from app.core.security.passwords import hash_password from app.modules.core.iam.models import User +from app.modules.core.audit.service import write_audit_log from app.modules.alerts.service import create_alert from app.modules.alerts.workflow_escalations import create_workflow_escalation from app.modules.core.iam.scope import build_scope, list_visible_branches, list_visible_tenants, validate_branch_matches_tenant @@ -421,6 +422,7 @@ def update_employee(db: Session, actor: User, emp: Employee, data: dict[str, Any raise HTTPException(status_code=400, detail="Employee code and full name are required.") user_id = cleaned.get("user_id") + linked_user: User | None = None if user_id: linked_user = db.get(User, int(user_id)) if not linked_user: @@ -433,6 +435,46 @@ def update_employee(db: Session, actor: User, emp: Employee, data: dict[str, Any _ensure_unique(db, tenant_id=emp.tenant_id, employee_code=employee_code, user_id=user_id, exclude_id=emp.id) + old_email = (emp.email or "").strip().lower() + requested_email = (cleaned.get("email") or "").strip().lower() + email_changed = requested_email != old_email + + if email_changed: + actor_roles = _role_set(db, actor) + if not actor_roles.intersection({"System Admin", "Firm Admin", "Partner"}): + raise HTTPException( + status_code=403, + detail="Only a Firm Admin or Partner can correct an employee email address.", + ) + + if linked_user is not None and not requested_email: + raise HTTPException( + status_code=400, + detail="Email cannot be blank while the employee is linked to a login user.", + ) + + if requested_email: + duplicate_user_stmt = select(User).where(func.lower(User.email) == requested_email) + if linked_user is not None: + duplicate_user_stmt = duplicate_user_stmt.where(User.id != linked_user.id) + duplicate_user = db.execute(duplicate_user_stmt).scalar_one_or_none() + if duplicate_user: + raise HTTPException(status_code=409, detail="This email address is already used by another login user.") + + duplicate_employee = db.execute( + select(Employee).where( + Employee.tenant_id == emp.tenant_id, + Employee.id != emp.id, + func.lower(Employee.email) == requested_email, + ) + ).scalar_one_or_none() + if duplicate_employee: + raise HTTPException(status_code=409, detail="This email address is already used by another employee in this firm.") + + cleaned["email"] = requested_email or None + if linked_user is not None: + linked_user.email = requested_email + update_fields = [ "employee_code", "full_name", "email", "mobile", "alternate_mobile", "date_of_joining", "date_of_leaving", "employment_type", "status", "is_active", "department", "designation", "reporting_manager_user_id", @@ -447,7 +489,28 @@ def update_employee(db: Session, actor: User, emp: Employee, data: dict[str, Any emp.updated_by_user_id = actor.id emp.updated_at_utc = datetime.now(timezone.utc) _disable_relieved_employee_login(db, emp) - db.commit() + db.flush() + + if email_changed: + write_audit_log( + db, + action="employee.email.corrected", + entity_type="employee", + actor=actor, + entity_id=emp.id, + entity_name=emp.full_name, + target_tenant_id=emp.tenant_id, + target_branch_id=emp.branch_id, + details={ + "old_email": old_email or None, + "new_email": requested_email or None, + "linked_user_id": linked_user.id if linked_user is not None else None, + "login_email_synchronised": linked_user is not None, + }, + ) + else: + db.commit() + db.refresh(emp) return emp diff --git a/app/modules/employees/templates/employees/form.html b/app/modules/employees/templates/employees/form.html index 191b5d2..5d5e43d 100644 --- a/app/modules/employees/templates/employees/form.html +++ b/app/modules/employees/templates/employees/form.html @@ -82,7 +82,11 @@
-
+
+ + + {% if is_edit %}

Firm Admin / Partner can correct this email. If a login user is linked, the same address is applied to that existing login account; user ID, roles and history remain unchanged.

{% endif %} +