email wiring

This commit is contained in:
debu-2 2026-10-04 20:50:47 +05:30
parent ee23b71f0f
commit 42cd937f0a
12 changed files with 494 additions and 45 deletions

View file

@ -8,11 +8,13 @@ from datetime import date
from pwdlib import PasswordHash
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.models import Account
from app.schemas import OrgMemberCreate, OrgMemberRead
from app.services.domain_provisioning import account_is_domain_owner
from app.services.org_invitations import send_employee_invitation
from app.services.org_sections import get_org_section
password_hasher = PasswordHash.recommended()
PLACEHOLDER_BIRTHDATE = date(1990, 1, 1)
@ -38,6 +40,8 @@ async def can_manage_org_members(
async def member_read(
session: AsyncSession,
member: Account,
*,
invitation_sent: bool = False,
) -> OrgMemberRead:
is_owner = await account_is_domain_owner(
session,
@ -55,7 +59,9 @@ async def member_read(
member_status=member.member_status,
must_change_password=member.must_change_password,
is_domain_owner=is_owner,
groups=[],
section_id=member.section_id,
section_name=member.section.name if member.section else None,
invitation_sent=invitation_sent,
created_at=member.created_at,
)
@ -66,6 +72,7 @@ async def list_org_members(
) -> tuple[list[OrgMemberRead], dict[str, int]]:
result = await session.scalars(
select(Account)
.options(selectinload(Account.section))
.where(
Account.account_type == "company",
Account.company_domain == company_domain,
@ -124,6 +131,12 @@ async def create_org_member(
if existing:
raise ValueError("That email address is already registered.")
section = None
if payload.section_id:
section = await get_org_section(session, company_domain, payload.section_id)
if section is None:
raise ValueError("Selected section was not found.")
phone_number = _placeholder_phone()
while await session.scalar(
select(Account).where(Account.phone_number == phone_number)
@ -142,22 +155,32 @@ async def create_org_member(
member_status=member_status,
invitation_email=invitation_email,
must_change_password=payload.force_password_change,
section_id=section.id if section else None,
created_by_id=manager.id,
password_hash=password_hasher.hash(payload.password),
)
session.add(member)
await session.flush()
if section:
member.section = section
invitation_sent = False
if payload.send_invitation:
await send_employee_invitation(
session,
member=member,
manager=manager,
initial_password=payload.password,
force_password_change=payload.force_password_change,
)
try:
await send_employee_invitation(
session,
member=member,
manager=manager,
initial_password=payload.password,
force_password_change=payload.force_password_change,
)
invitation_sent = True
except Exception as error:
raise ValueError(
f"Could not send invitation email: {error}"
) from error
return await member_read(session, member)
return await member_read(session, member, invitation_sent=invitation_sent)
async def update_org_member_role(