feat(tenancy): add resend invitation for pending team members
Some checks failed
Some checks failed
New resend_invitation() service method regenerates the token and
resends the invitation email for pending members.
Available on all frontends:
- Merchant: POST /merchants/account/team/stores/{sid}/members/{uid}/resend
- Store: POST /store/team/members/{uid}/resend
UI: paper-airplane icon appears on pending members in both merchant
and store team pages.
i18n: resend_invitation + invitation_resent keys in 4 locales.
Also translated previously untranslated invitation_sent_successfully
in fr/de/lb.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -907,6 +907,69 @@ class StoreTeamService:
|
||||
db.flush()
|
||||
return role
|
||||
|
||||
def resend_invitation(
|
||||
self,
|
||||
db: Session,
|
||||
store: Store,
|
||||
user_id: int,
|
||||
inviter: User,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Resend invitation to a pending team member.
|
||||
|
||||
Generates a new token and resends the email.
|
||||
Only works for pending invitations (not yet accepted).
|
||||
"""
|
||||
store_user = (
|
||||
db.query(StoreUser)
|
||||
.filter(
|
||||
StoreUser.store_id == store.id,
|
||||
StoreUser.user_id == user_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not store_user:
|
||||
raise UserNotFoundException(str(user_id))
|
||||
|
||||
if store_user.invitation_accepted_at is not None:
|
||||
raise InvalidInvitationTokenException("Invitation already accepted")
|
||||
|
||||
# Generate new token and update sent time
|
||||
new_token = self._generate_invitation_token()
|
||||
store_user.invitation_token = new_token
|
||||
store_user.invitation_sent_at = datetime.utcnow()
|
||||
db.flush()
|
||||
|
||||
# Get role name for email
|
||||
role_name = store_user.role.name if store_user.role else "member"
|
||||
|
||||
# Send email
|
||||
try:
|
||||
self._send_invitation_email(
|
||||
db=db,
|
||||
email=store_user.user.email,
|
||||
store=store,
|
||||
token=new_token,
|
||||
inviter=inviter,
|
||||
role_name=role_name,
|
||||
)
|
||||
except Exception: # noqa: EXC003
|
||||
logger.exception(
|
||||
f"Failed to resend invitation email to {store_user.user.email}"
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"Resent invitation to {store_user.user.email} for store "
|
||||
f"{store.store_code} by {inviter.username}"
|
||||
)
|
||||
|
||||
return {
|
||||
"email": store_user.user.email,
|
||||
"store_code": store.store_code,
|
||||
"invitation_sent": True,
|
||||
}
|
||||
|
||||
def _send_invitation_email(
|
||||
self,
|
||||
db: Session,
|
||||
|
||||
Reference in New Issue
Block a user