Add phase 1 client consultant referral and linkage
This commit is contained in:
@@ -12,11 +12,18 @@ from sqlalchemy.orm import Session
|
||||
from app.modules.clients import repository
|
||||
from app.modules.clients.schemas import ClientCreate
|
||||
from app.modules.clients.service import create_client_service
|
||||
from app.modules.consultants.service import get_consultant
|
||||
|
||||
TEMPLATE_COLUMNS = [
|
||||
"uploader_user_id",
|
||||
"firm_tenant_id",
|
||||
"partner_user_id",
|
||||
"referred_by_consultant_id",
|
||||
"primary_consultant_id",
|
||||
"referral_date",
|
||||
"referral_reference",
|
||||
"referral_status",
|
||||
"communication_routing_mode",
|
||||
"branch_id",
|
||||
"client_code",
|
||||
"client_name",
|
||||
@@ -104,6 +111,9 @@ def build_client_import_template_bytes(*, current_user, tenant_id: int, partner_
|
||||
ref.append(['firm_tenant_id', 'Must match the active firm/tenant context of the upload.'])
|
||||
ref.append(['partner_user_id', 'Must be an active Partner user mapped to the same firm.'])
|
||||
ref.append(['branch_id', 'Optional. If blank, uploader branch or partner branch will be used.'])
|
||||
ref.append(['referred_by_consultant_id', 'Optional active consultant profile id who introduced the client.'])
|
||||
ref.append(['primary_consultant_id', 'Optional active consultant profile id for the operational client link.'])
|
||||
ref.append(['communication_routing_mode', 'client_direct, consultant_primary, client_and_consultant, or firm_only.'])
|
||||
ref.append(['email', 'Used as the client frontend login email.'])
|
||||
ref.append(['portal_password', 'Minimum 8 characters.'])
|
||||
ref.append(['portal_password_confirm', 'Must match portal_password.'])
|
||||
@@ -174,10 +184,27 @@ def build_preview(db: Session, *, current_user, scope, role_names: set[str], upl
|
||||
if not branch_id:
|
||||
msgs.append('branch_id is required when uploader and partner have no branch mapped.')
|
||||
|
||||
for consultant_field in ("referred_by_consultant_id", "primary_consultant_id"):
|
||||
raw_consultant_id = cleaned.get(consultant_field)
|
||||
if raw_consultant_id:
|
||||
try:
|
||||
consultant_id = int(raw_consultant_id)
|
||||
except Exception:
|
||||
consultant_id = 0
|
||||
consultant = get_consultant(db, tenant_id=firm_tenant_id, consultant_id=consultant_id) if consultant_id else None
|
||||
if not consultant or not consultant.is_active:
|
||||
msgs.append(f"{consultant_field} must be an active consultant profile id in the same firm.")
|
||||
|
||||
payload = {
|
||||
'tenant_id': firm_tenant_id,
|
||||
'branch_id': branch_id,
|
||||
'partner_id': partner_user_id or None,
|
||||
'referred_by_consultant_id': int(cleaned.get('referred_by_consultant_id')) if cleaned.get('referred_by_consultant_id') else None,
|
||||
'primary_consultant_id': int(cleaned.get('primary_consultant_id')) if cleaned.get('primary_consultant_id') else None,
|
||||
'referral_date': cleaned.get('referral_date'),
|
||||
'referral_reference': cleaned.get('referral_reference'),
|
||||
'referral_status': cleaned.get('referral_status') or 'active',
|
||||
'communication_routing_mode': cleaned.get('communication_routing_mode') or 'client_and_consultant',
|
||||
'engagement_mode': cleaned.get('engagement_mode') or 'internal_managed',
|
||||
'client_code': cleaned.get('client_code') or '',
|
||||
'client_name': cleaned.get('client_name') or '',
|
||||
|
||||
Reference in New Issue
Block a user