feat(tenancy): add member detail modal + fix invite name saving
Some checks failed
CI / ruff (push) Successful in 15s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

Merchant team page:
- Consistent member display (full_name + email on every row)
- New view button (eye icon) on all members including owner
- View modal shows account info (username, role, email verified,
  last login, account created) and store memberships with roles
- API enriched with user metadata (username, role, is_email_verified,
  last_login, created_at)

Invite fix (both merchant and store routes):
- first_name and last_name from invite form were never passed to the
  service that creates the User account. Now passed through correctly.

i18n: 6 new keys across 4 locales (view_member, account_information,
username, email_verified, last_login, account_created).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 13:23:20 +02:00
parent d81e9a3fa4
commit 211c46ebbc
10 changed files with 151 additions and 26 deletions

View File

@@ -504,9 +504,15 @@ class MerchantStoreService:
members_map[uid] = {
"user_id": uid,
"email": user.email,
"username": user.username,
"first_name": user.first_name,
"last_name": user.last_name,
"full_name": f"{user.first_name or ''} {user.last_name or ''}".strip() or user.email,
"role": user.role,
"is_active": user.is_active,
"is_email_verified": user.is_email_verified,
"last_login": user.last_login.isoformat() if user.last_login else None,
"created_at": user.created_at.isoformat() if user.created_at else None,
"stores": [],
"is_owner": uid == merchant.owner_user_id,
}

View File

@@ -54,6 +54,8 @@ class StoreTeamService:
inviter: User,
email: str,
role_name: str,
first_name: str | None = None,
last_name: str | None = None,
custom_permissions: list[str] | None = None,
) -> dict[str, Any]:
"""
@@ -148,6 +150,8 @@ class StoreTeamService:
email=email,
username=username,
hashed_password=self.auth_manager.hash_password(temp_password),
first_name=first_name,
last_name=last_name,
role="store_member",
is_active=False, # Will be activated when invitation accepted
is_email_verified=False,