feat: complete Tier 2 onboarding - KYC, Private Fleet, and Wallet creation fully functional

This commit is contained in:
2026-02-06 23:43:01 +00:00
parent 9d06be4f87
commit 8020bbd394
9 changed files with 114 additions and 58 deletions

View File

@@ -1,13 +1,15 @@
from datetime import datetime, timedelta, timezone
import uuid
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, text
from sqlalchemy import select, text, cast, String
from app.models.identity import User, Person, UserRole, VerificationToken, Wallet
from app.models.organization import Organization
from app.schemas.auth import UserLiteRegister, UserKYCComplete
from app.core.security import get_password_hash, verify_password
from app.services.email_manager import email_manager
from app.core.config import settings
from sqlalchemy.orm import joinedload # <--- EZT ADD HOZZÁ AZ IMPORTOKHOZ!
class AuthService:
@staticmethod
@@ -94,47 +96,64 @@ class AuthService:
@staticmethod
async def complete_kyc(db: AsyncSession, user_id: int, kyc_in: UserKYCComplete):
"""Step 2: KYC adatok, Telefon, Privát Flotta és Wallet aktiválása."""
"""Step 2: KYC adatok rögzítése JSON-biztos dátumkezeléssel."""
try:
# 1. User és Person lekérése
stmt = select(User).where(User.id == user_id).join(User.person)
# 1. User és Person lekérése joinedload-dal (a korábbi hiba javítása)
stmt = (
select(User)
.options(joinedload(User.person))
.where(User.id == user_id)
)
result = await db.execute(stmt)
user = result.scalar_one_or_none()
if not user:
if not user or not user.person:
return None
# 2. Személyes adatok rögzítése (tábla szinten)
# 2. Előkészítjük a JSON-kompatibilis adatokat
# A mode='json' átalakítja a date objektumokat string-gé!
kyc_data_json = kyc_in.model_dump(mode='json')
p = user.person
p.phone = kyc_in.phone_number
p.birth_place = kyc_in.birth_place
# A sima DATE oszlopba mehet a Python date objektum
p.birth_date = datetime.combine(kyc_in.birth_date, datetime.min.time())
p.mothers_name = kyc_in.mothers_name
# JSONB mezők mentése Pydantic modellekből
p.identity_docs = {k: v.dict() for k, v in kyc_in.identity_docs.items()}
p.ice_contact = kyc_in.ice_contact.dict()
# A JSONB mezőkbe a már stringesített adatokat tesszük
p.identity_docs = kyc_data_json["identity_docs"]
p.ice_contact = kyc_data_json["ice_contact"]
p.is_active = True
# 3. PRIVÁT FLOTTA (Organization) automata generálása
new_org = Organization(
name=f"{p.last_name} {p.first_name} - Privát Flotta",
owner_id=user.id,
is_active=True,
org_type="individual"
# 3. PRIVÁT FLOTTA (Organization)
# Megnézzük, létezik-e már (idempotencia)
org_stmt = select(Organization).where(
Organization.owner_id == user.id,
cast(Organization.org_type, String) == "individual"
)
db.add(new_org)
await db.flush()
org_res = await db.execute(org_stmt)
existing_org = org_res.scalar_one_or_none()
if not existing_org:
new_org = Organization(
name=f"{p.last_name} {p.first_name} - Privát Flotta",
owner_id=user.id,
is_active=True,
org_type="individual",
is_verified=True,
is_transferable=True
)
db.add(new_org)
# 4. WALLET automata generálása
new_wallet = Wallet(
user_id=user.id,
coin_balance=0.00,
xp_balance=0
)
db.add(new_wallet)
# 4. WALLET
wallet_stmt = select(Wallet).where(Wallet.user_id == user.id)
wallet_res = await db.execute(wallet_stmt)
if not wallet_res.scalar_one_or_none():
new_wallet = Wallet(user_id=user.id, coin_balance=0.0, xp_balance=0)
db.add(new_wallet)
# 5. USER TELJES AKTIVÁLÁSA
# 5. USER AKTIVÁLÁSA
user.is_active = True
await db.commit()
@@ -142,6 +161,7 @@ class AuthService:
return user
except Exception as e:
await db.rollback()
print(f"CRITICAL KYC ERROR: {str(e)}")
raise e
@staticmethod