Профиль: валидация, календарь, ИНН 12 цифр, email, DaData адреса, банки из BANK_IP, подсказка ИНН (ФНС)
- Backend: N8N_AUTH_WEBHOOK из env (fallback), банки из BANK_IP, эндпоинт /api/v1/profile/dadata/address для подсказок адресов (FORMA_DADATA_*). - Config: bank_ip, bank_api_url, forma_dadata_api_key, forma_dadata_secret. - Frontend Profile: DatePicker для даты рождения, ИНН 12 цифр + ссылка на ФНС, валидация email, чекбокс «Совпадает с адресом регистрации», AutoComplete адресов через DaData, Select банков из /api/v1/banks/nspk (bankId/bankName). Подробности в CHANGELOG_PROFILE_VALIDATION.md.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from typing import Optional, Any, Dict
|
||||
from typing import Optional, Any, Dict, Union
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, HTTPException
|
||||
@@ -37,6 +37,27 @@ class AuthUniversalResponse(BaseModel):
|
||||
phone: Optional[str] = None
|
||||
contact_id: Optional[str] = None
|
||||
has_drafts: Optional[bool] = None
|
||||
need_profile_confirm: Optional[bool] = None
|
||||
profile_needs_attention: Optional[bool] = None
|
||||
|
||||
|
||||
def _to_bool(v: Any) -> Optional[bool]:
|
||||
if v is None:
|
||||
return None
|
||||
if isinstance(v, bool):
|
||||
return v
|
||||
if isinstance(v, (int, float)):
|
||||
if v == 1:
|
||||
return True
|
||||
if v == 0:
|
||||
return False
|
||||
if isinstance(v, str):
|
||||
s = v.strip().lower()
|
||||
if s in ("1", "true", "yes", "y", "да"):
|
||||
return True
|
||||
if s in ("0", "false", "no", "n", "нет", ""):
|
||||
return False
|
||||
return None
|
||||
|
||||
|
||||
@router.post("", response_model=AuthUniversalResponse)
|
||||
@@ -152,6 +173,20 @@ async def auth_universal(request: AuthUniversalRequest):
|
||||
|
||||
logger.info("[AUTH] data: success=%s, need_contact=%s, unified_id=%s", data.get("success"), data.get("need_contact"), data.get("unified_id"))
|
||||
|
||||
# Флаг «профиль требует внимания»: приходит из n8n, прокидываем в сессию и на фронт
|
||||
need_profile_confirm = _to_bool(
|
||||
data.get("need_profile_confirm")
|
||||
if "need_profile_confirm" in data
|
||||
else data.get("needProfileConfirm")
|
||||
)
|
||||
profile_needs_attention = _to_bool(
|
||||
data.get("profile_needs_attention")
|
||||
if "profile_needs_attention" in data
|
||||
else data.get("profileNeedsAttention")
|
||||
)
|
||||
if profile_needs_attention is None:
|
||||
profile_needs_attention = need_profile_confirm
|
||||
|
||||
# 3) need_contact — только если n8n явно вернул need_contact (закрыть приложение и попросить контакт в чате)
|
||||
need_contact = (
|
||||
data.get("need_contact") is True
|
||||
@@ -198,6 +233,8 @@ async def auth_universal(request: AuthUniversalRequest):
|
||||
"contact_id": _contact_id,
|
||||
"has_drafts": data.get("has_drafts", False) or (data.get("result") or {}).get("has_drafts", False) if isinstance(data.get("result"), dict) else False,
|
||||
"chat_id": channel_user_id,
|
||||
"need_profile_confirm": need_profile_confirm,
|
||||
"profile_needs_attention": profile_needs_attention,
|
||||
}
|
||||
logger.info("[AUTH] session_data: unified_id=%s, phone=%s", unified_id, session_data.get("phone"))
|
||||
try:
|
||||
@@ -222,4 +259,6 @@ async def auth_universal(request: AuthUniversalRequest):
|
||||
phone=session_data.get("phone"),
|
||||
contact_id=session_data.get("contact_id"),
|
||||
has_drafts=session_data.get("has_drafts", False),
|
||||
need_profile_confirm=need_profile_confirm,
|
||||
profile_needs_attention=profile_needs_attention,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user