209 lines
6.5 KiB
Python
209 lines
6.5 KiB
Python
"""
|
||
Public GraphQL Schema for KYC profile data.
|
||
|
||
This endpoint provides:
|
||
- kycProfileTeaser: public data (no auth required)
|
||
- kycProfileFull: full data (requires authentication)
|
||
|
||
Data is read from MongoDB company_documents collection.
|
||
Queries are by KYC Profile UUID.
|
||
"""
|
||
|
||
import graphene
|
||
from django.conf import settings
|
||
from pymongo import MongoClient
|
||
|
||
from ..models import KYCProfile, KYCDetailsRussia
|
||
|
||
|
||
def get_mongo_client():
|
||
"""Get MongoDB client."""
|
||
if not settings.MONGODB_URI:
|
||
return None
|
||
return MongoClient(settings.MONGODB_URI)
|
||
|
||
|
||
def get_company_documents(inn: str) -> list:
|
||
"""Get all documents for a company by INN."""
|
||
client = get_mongo_client()
|
||
if not client:
|
||
return []
|
||
|
||
try:
|
||
db = client[settings.MONGODB_DB]
|
||
collection = db["company_documents"]
|
||
return list(collection.find({"inn": inn}))
|
||
finally:
|
||
client.close()
|
||
|
||
|
||
def get_inn_by_profile_uuid(profile_uuid: str) -> str | None:
|
||
"""Get INN from KYCProfile by its UUID."""
|
||
try:
|
||
profile = KYCProfile.objects.get(uuid=profile_uuid)
|
||
# Get country details (KYCDetailsRussia) via GenericForeignKey
|
||
if profile.country_details and isinstance(profile.country_details, KYCDetailsRussia):
|
||
return profile.country_details.inn
|
||
return None
|
||
except KYCProfile.DoesNotExist:
|
||
return None
|
||
|
||
|
||
def aggregate_company_data(documents: list) -> dict:
|
||
"""Aggregate data from multiple source documents into summary."""
|
||
if not documents:
|
||
return {}
|
||
|
||
summary = {
|
||
"inn": None,
|
||
"ogrn": None,
|
||
"name": None,
|
||
"company_type": None,
|
||
"registration_year": None,
|
||
"is_active": True,
|
||
"address": None,
|
||
"director": None,
|
||
"capital": None,
|
||
"activities": [],
|
||
"sources": [],
|
||
"last_updated": None,
|
||
}
|
||
|
||
for doc in documents:
|
||
source = doc.get("source", "unknown")
|
||
summary["sources"].append(source)
|
||
|
||
data = doc.get("data", {})
|
||
|
||
# Extract common fields
|
||
if not summary["inn"]:
|
||
summary["inn"] = doc.get("inn")
|
||
|
||
if not summary["ogrn"] and data.get("ogrn"):
|
||
summary["ogrn"] = data["ogrn"]
|
||
|
||
if not summary["name"] and data.get("name"):
|
||
summary["name"] = data["name"]
|
||
|
||
# Parse company type from name
|
||
if not summary["company_type"] and summary["name"]:
|
||
name = summary["name"].upper()
|
||
if "ООО" in name or "ОБЩЕСТВО С ОГРАНИЧЕННОЙ" in name:
|
||
summary["company_type"] = "ООО"
|
||
elif "АО" in name or "АКЦИОНЕРНОЕ ОБЩЕСТВО" in name:
|
||
summary["company_type"] = "АО"
|
||
elif "ИП" in name or "ИНДИВИДУАЛЬНЫЙ ПРЕДПРИНИМАТЕЛЬ" in name:
|
||
summary["company_type"] = "ИП"
|
||
elif "ПАО" in name:
|
||
summary["company_type"] = "ПАО"
|
||
|
||
# Track last update
|
||
collected_at = doc.get("collected_at")
|
||
if collected_at:
|
||
if not summary["last_updated"] or collected_at > summary["last_updated"]:
|
||
summary["last_updated"] = collected_at
|
||
|
||
return summary
|
||
|
||
|
||
class CompanyTeaserType(graphene.ObjectType):
|
||
"""Public company data (teaser)."""
|
||
|
||
company_type = graphene.String(description="Company type: ООО, АО, ИП, etc.")
|
||
registration_year = graphene.Int(description="Year of registration")
|
||
is_active = graphene.Boolean(description="Is company active")
|
||
sources_count = graphene.Int(description="Number of data sources")
|
||
|
||
|
||
class CompanyFullType(graphene.ObjectType):
|
||
"""Full company data (requires auth)."""
|
||
|
||
inn = graphene.String()
|
||
ogrn = graphene.String()
|
||
name = graphene.String()
|
||
company_type = graphene.String()
|
||
registration_year = graphene.Int()
|
||
is_active = graphene.Boolean()
|
||
address = graphene.String()
|
||
director = graphene.String()
|
||
capital = graphene.String()
|
||
activities = graphene.List(graphene.String)
|
||
sources = graphene.List(graphene.String)
|
||
last_updated = graphene.DateTime()
|
||
|
||
|
||
class PublicQuery(graphene.ObjectType):
|
||
"""Public queries - no authentication required."""
|
||
|
||
# Query by KYC Profile UUID (preferred - used by frontend)
|
||
kyc_profile_teaser = graphene.Field(
|
||
CompanyTeaserType,
|
||
profile_uuid=graphene.String(required=True),
|
||
description="Get public KYC profile teaser data by UUID",
|
||
)
|
||
|
||
kyc_profile_full = graphene.Field(
|
||
CompanyFullType,
|
||
profile_uuid=graphene.String(required=True),
|
||
description="Get full KYC profile data by UUID (requires auth)",
|
||
)
|
||
|
||
health = graphene.String()
|
||
|
||
def resolve_health(self, info):
|
||
return "ok"
|
||
|
||
def resolve_kyc_profile_teaser(self, info, profile_uuid: str):
|
||
"""Return public teaser data by KYC Profile UUID."""
|
||
inn = get_inn_by_profile_uuid(profile_uuid)
|
||
if not inn:
|
||
return None
|
||
|
||
documents = get_company_documents(inn)
|
||
if not documents:
|
||
return None
|
||
|
||
summary = aggregate_company_data(documents)
|
||
|
||
return CompanyTeaserType(
|
||
company_type=summary.get("company_type"),
|
||
registration_year=summary.get("registration_year"),
|
||
is_active=summary.get("is_active", True),
|
||
sources_count=len(summary.get("sources", [])),
|
||
)
|
||
|
||
def resolve_kyc_profile_full(self, info, profile_uuid: str):
|
||
"""Return full KYC profile data by UUID (requires auth)."""
|
||
# Check authentication
|
||
user_id = getattr(info.context, 'user_id', None)
|
||
if not user_id:
|
||
return None # Not authenticated
|
||
|
||
inn = get_inn_by_profile_uuid(profile_uuid)
|
||
if not inn:
|
||
return None
|
||
|
||
documents = get_company_documents(inn)
|
||
if not documents:
|
||
return None
|
||
|
||
summary = aggregate_company_data(documents)
|
||
|
||
return CompanyFullType(
|
||
inn=summary.get("inn"),
|
||
ogrn=summary.get("ogrn"),
|
||
name=summary.get("name"),
|
||
company_type=summary.get("company_type"),
|
||
registration_year=summary.get("registration_year"),
|
||
is_active=summary.get("is_active", True),
|
||
address=summary.get("address"),
|
||
director=summary.get("director"),
|
||
capital=summary.get("capital"),
|
||
activities=summary.get("activities", []),
|
||
sources=summary.get("sources", []),
|
||
last_updated=summary.get("last_updated"),
|
||
)
|
||
|
||
|
||
public_schema = graphene.Schema(query=PublicQuery)
|