Coverage for apps/accounts/tireless_api.py: 95%
35 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
1"""Tireless AI platform integration API: cross-launch context and deep-linking."""
3from __future__ import annotations
5from django.conf import settings
6from ninja import Query, Router
7from ninja.schema import Schema
9from apps.accounts.auth import StaffPrincipal, requires
10from apps.core_los.models import Loan
12router = Router(tags=["integrations"])
15class TirelessContextResponse(Schema):
16 has_access: bool
17 role: str
18 user_email: str
19 tireless_app_url: str
20 tireless_loan_url: str | None = None
21 arive_loan_no: str | None = None
24# Roles entitled to access Tireless processing workbench
25ENTITLED_ROLES: frozenset[str] = frozenset(
26 {
27 "Owner",
28 "Company Admin",
29 "Associate Admin",
30 "Branch Admin",
31 "Processor",
32 "Assistant Processor",
33 "Contract Processor Admin",
34 "Loan Officer",
35 "Loan Officer Assistant",
36 }
37)
40@router.get(
41 "/integrations/tireless/context",
42 response=TirelessContextResponse,
43 auth=requires("LOAN_VIEW"),
44)
45def get_tireless_context(
46 request,
47 loan_id: int | None = Query(None, description="Internal ID of the loan (optional)"),
48 arive_loan_no: str | None = Query(None, description="ARIVE loan number (optional)"),
49):
50 """Retrieve cross-launch context and deep-linking URLs for Tireless Processing."""
51 principal: StaffPrincipal = request.principal
53 # Determine user role name
54 from apps.accounts.models import UserRole
56 user_role = (
57 UserRole.objects.filter(user_id=principal.user_id).select_related("role").first()
58 )
59 role_name = (
60 user_role.role.name
61 if user_role and user_role.role
62 else ("Owner" if principal.is_hq else "Staff")
63 )
65 # Access check: user must belong to an entitled role
66 has_access = (
67 role_name in ENTITLED_ROLES
68 or principal.is_hq
69 or "VIEW_ALL_PIPELINE" in principal.permissions
70 )
72 base_app_url = getattr(
73 settings, "TIRELESS_WEB_BASE_URL", "https://app.tireless-ai.com"
74 ).rstrip("/")
75 tireless_loan_url = None
76 resolved_loan_no = None
78 if loan_id or arive_loan_no:
79 loan = None
80 if loan_id:
81 loan = Loan.objects.filter(id=loan_id).first()
82 elif arive_loan_no: 82 ↛ 85line 82 didn't jump to line 85 because the condition on line 82 was always true
83 loan = Loan.objects.filter(arive_loan_no=arive_loan_no).first()
85 if loan: 85 ↛ 89line 85 didn't jump to line 89 because the condition on line 85 was always true
86 resolved_loan_no = loan.arive_loan_no
87 tireless_loan_url = f"{base_app_url}/loans/{resolved_loan_no}/documents"
89 return TirelessContextResponse(
90 has_access=has_access,
91 role=role_name,
92 user_email=principal.email,
93 tireless_app_url=base_app_url,
94 tireless_loan_url=tireless_loan_url,
95 arive_loan_no=resolved_loan_no,
96 )