"""Logic for vend_contact.""" from typing import Optional from flask import g from sqlalchemy import orm from permissions import types from permissions.models import ( contact as contact_model, owsusers, vend_contact as vend_contact_model, vend_contact_role, ) def _parse_name(name: str) -> tuple[str, str]: """Parse a full name into first and last name. Args: name: Full name to parse Returns: Tuple of (first_name, last_name) """ if not name or not name.strip(): return '', '' parts = name.strip().split(None, 1) # Split on whitespace, max 2 parts if len(parts) == 1: # Only one name provided, treat it as first name return parts[0], '' else: # Two or more parts: first part is first name, rest is last name return parts[0], parts[1] def create_vend_contact_and_roles( session: orm.session.Session, role_ids: list[int], identity: types.Identity, vendor_id: int, subaccount_id: Optional[int], master_contact: bool, existing_profile: dict | None, ) -> Optional[vend_contact_model.VendContact]: """Create contact, vend_contact, and vend_contact_role records. May raise.""" if master_contact: master = vend_contact_model.YNEnum.Y vend_contact_model.VendContact.update_existing_master_contact( tx=session, vendor_id=vendor_id ) g.log.info( 'Master contact updated for vendor.', resources={ 'vendor_id': vendor_id, 'identity_id': identity.id, }, ) else: master = vend_contact_model.YNEnum.N if existing_profile: vend_contact = vend_contact_model.VendContact.get_by_id( session=session, vend_contact_id=existing_profile['profile_id'], ) if not vend_contact: g.log.error( 'No vend_contact found for existing label profile', resources={'label_profile_id': existing_profile['profile_id']}, ) raise RuntimeError('No vend_contact found for existing label profile') # Not allowing master to be set to N if it was previously Y. # That should be done via setting a new master contact. if master == vend_contact_model.YNEnum.Y and vend_contact.master != master: vend_contact.master = master if vend_contact.active == vend_contact_model.YNEnum.N: vend_contact.active = vend_contact_model.YNEnum.Y else: # This may result in a duplicate contact (same behavior as v1 settings). It's fine. # Use first_name and last_name if they exist, otherwise parse from name field first_name = identity.first_name last_name = identity.last_name if not first_name or not last_name: parsed_first, parsed_last = _parse_name(identity.name) first_name = first_name or parsed_first last_name = last_name or parsed_last contact = contact_model.Contact.create( first_name=first_name, last_name=last_name, email=identity.email, ) session.add(contact) vend_contact = vend_contact_model.VendContact.create( contact=contact, vendor_id=vendor_id, subaccount_id=subaccount_id, email=identity.email, auth0_user_id=identity.auth0_user_id, master=master, ) session.add(vend_contact) vc_roles = vend_contact_role.VendContactRole.create_by_role_ids_if_not_exist( tx=session, vend_contact=vend_contact, role_ids=role_ids, ) for vc_role in vc_roles: session.add(vc_role) return vend_contact def set_new_auth0_vend_contact_id( session: orm.session.Session, identity: types.Identity, admin_id: str, admin_profile_id: int ): """Set a new auth0 vend_contact_id for the given identity.""" active_vend_contact = vend_contact_model.VendContact.get_next_active_for_identity_or_none( session=session, identity=identity ) if active_vend_contact: g.log.info( 'Setting new auth0 vend_contact for user', resources={ 'identity_id': identity.id, 'vend_contact_id': active_vend_contact.id, 'vendor_id': active_vend_contact.vendor_id, 'subaccount_id': active_vend_contact.subaccount_id, 'admin_identity_id': admin_id, }, ) owsusers.set_auth0_vend_contact_id( vend_contact_id=active_vend_contact.id, identity_id=identity.id, auth0_user_id=identity.auth0_user_id, admin_id=admin_id, admin_profile_id=admin_profile_id, ) else: g.log.info( 'Identity has no active vend_contacts; user will not have workstation access', resources={ 'identity_id': identity.id, 'admin_identity_id': admin_id, }, )