system-prompts-and-models-o.../salesflow-saas/backend/app/services/zatca_compliance.py

227 lines
8.5 KiB
Python

"""
Dealix ZATCA Compliance Engine
================================
ضمان توافق جميع الصفقات مع:
- هيئة الزكاة والضريبة والجمارك
- الفاتورة الإلكترونية (e-Invoice) المرحلة الثانية
- أنظمة الوساطة العقارية
- مكافحة غسيل الأموال
"""
import hashlib
import json
import re
import uuid
from datetime import datetime
from typing import Optional
from groq import AsyncGroq
import os
import logging
logger = logging.getLogger(__name__)
class ZATCAInvoiceEngine:
"""Saudi ZATCA e-Invoice generation (Phase 2 compliant)."""
def __init__(self):
self.vat_rate = 0.15 # 15% VAT in Saudi Arabia
self.seller_vat = os.getenv("SELLER_VAT_NUMBER", "")
self.seller_cr = os.getenv("SELLER_CR_NUMBER", "")
def generate_invoice(self, deal: dict) -> dict:
"""Generate ZATCA Phase 2 compliant e-invoice."""
invoice_id = f"DLX-{datetime.now().strftime('%Y%m%d')}-{uuid.uuid4().hex[:6].upper()}"
amount = deal.get("amount", 0)
vat_amount = round(amount * self.vat_rate, 2)
total = round(amount + vat_amount, 2)
invoice = {
"invoice_id": invoice_id,
"type": "standard", # Standard Tax Invoice
"issue_date": datetime.now().strftime("%Y-%m-%d"),
"issue_time": datetime.now().strftime("%H:%M:%S"),
"seller": {
"name": "ديليكس للذكاء الاصطناعي",
"name_en": "Dealix AI",
"vat_number": self.seller_vat,
"cr_number": self.seller_cr,
"country": "SA",
"city": "الرياض"
},
"buyer": {
"name": deal.get("company_name", ""),
"vat_number": deal.get("buyer_vat", ""),
"cr_number": deal.get("buyer_cr", ""),
"country": "SA",
"city": deal.get("city", "الرياض")
},
"line_items": [
{
"description": deal.get("service_description", "خدمات ذكاء اصطناعي للمبيعات"),
"quantity": 1,
"unit_price": amount,
"vat_rate": 15,
"vat_amount": vat_amount,
"total": total
}
],
"totals": {
"subtotal": amount,
"vat_total": vat_amount,
"grand_total": total,
"currency": "SAR"
},
"compliance": {
"zatca_phase": 2,
"qr_code": self._generate_qr_data(invoice_id, amount, vat_amount),
"cryptographic_stamp": self._generate_stamp(invoice_id, str(total)),
"uuid": str(uuid.uuid4())
},
"status": "generated",
"generated_at": datetime.utcnow().isoformat()
}
return invoice
def _generate_qr_data(self, invoice_id: str, amount: float, vat: float) -> str:
"""Generate ZATCA QR code data (TLV format simplified)."""
data = f"1=ديليكس AI|2={self.seller_vat}|3={datetime.now().isoformat()}|4={amount}|5={vat}"
return hashlib.sha256(data.encode()).hexdigest()[:32]
def _generate_stamp(self, invoice_id: str, amount: str) -> str:
"""Generate cryptographic stamp for ZATCA compliance."""
content = f"{invoice_id}:{amount}:{datetime.now().date()}"
return hashlib.sha256(content.encode()).hexdigest()
def validate_vat_number(self, vat_number: str) -> dict:
"""Validate Saudi VAT number format."""
pattern = r'^3\d{14}$'
valid = bool(re.match(pattern, vat_number)) if vat_number else False
return {
"valid": valid,
"vat_number": vat_number,
"format": "15 digits starting with 3" if not valid else "✅ Valid",
"message": "صحيح" if valid else "رقم ضريبي غير صحيح — يجب أن يبدأ بـ 3 ويكون 15 رقم"
}
class RealEstateComplianceChecker:
"""Saudi Real Estate Brokerage compliance."""
def __init__(self, groq_client: AsyncGroq):
self.groq = groq_client
async def check_deal_compliance(self, deal: dict) -> dict:
"""Check deal compliance with Saudi real estate regulations."""
prompt = f"""أنت خبير قانوني في أنظمة الوساطة العقارية السعودية.
افحص هذه الصفقة:
{json.dumps(deal, ensure_ascii=False)}
تحقق من التوافق مع:
1. نظام الوساطة العقارية 2023 (لوائح هيئة العقار)
2. اشتراطات عقد الوساطة
3. حقوق المستهلك (nzaq)
4. متطلبات التسجيل في فال
{{
"compliant": true,
"compliance_score": 90,
"issues": [
{{"issue": "المشكلة", "severity": "high/medium/low", "action": "الإجراء المطلوب"}}
],
"required_documents": ["وثيقة مطلوبة"],
"commission_compliance": {{
"allowed_max": "2.5% للبيع / شهر للإيجار",
"current": "...",
"compliant": true
}},
"recommendations": ["توصية للامتثال"],
"zatca_required": true,
"fal_registration_needed": false
}}"""
response = await self.groq.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=1000,
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
class AMLChecker:
"""Anti-Money Laundering checks for high-value deals."""
SUSPICIOUS_THRESHOLD = 375000 # SAR (≈ $100K)
def __init__(self):
self.groq = AsyncGroq(api_key=os.getenv("GROQ_API_KEY", ""))
async def screen_transaction(self, deal: dict) -> dict:
"""AML screening for large transactions."""
amount = deal.get("amount", 0)
requires_enhanced = amount >= self.SUSPICIOUS_THRESHOLD
screening = {
"deal_id": deal.get("id", "unknown"),
"amount": amount,
"currency": "SAR",
"risk_level": "high" if amount >= 1_000_000 else "medium" if requires_enhanced else "low",
"requires_enhanced_due_diligence": requires_enhanced,
"requires_str": amount >= 375_000, # Suspicious Transaction Report
"checks": {
"pep_screening": "pending", # Politically Exposed Person
"sanctions_list": "clear",
"source_of_funds_documented": deal.get("source_of_funds_documented", False),
},
"compliance_actions": []
}
if requires_enhanced:
screening["compliance_actions"].extend([
"التحقق من مصدر الأموال",
"الحصول على وثائق إثبات الهوية",
"استشارة المسؤول عن الامتثال",
])
if amount >= 375_000:
screening["compliance_actions"].append("إعداد تقرير معاملة مشبوهة (STR) إن لزم")
return screening
class DealixComplianceOrchestrator:
"""Master compliance orchestrator for all Dealix deals."""
def __init__(self):
self.groq = AsyncGroq(api_key=os.getenv("GROQ_API_KEY", ""))
self.zatca = ZATCAInvoiceEngine()
self.real_estate = RealEstateComplianceChecker(self.groq)
self.aml = AMLChecker()
async def full_compliance_check(self, deal: dict) -> dict:
"""Run all compliance checks in parallel."""
real_estate_check, aml_check = await asyncio.gather(
self.real_estate.check_deal_compliance(deal),
self.aml.screen_transaction(deal)
)
invoice = self.zatca.generate_invoice(deal) if deal.get("generate_invoice") else None
overall_score = real_estate_check.get("compliance_score", 100)
overall_compliant = real_estate_check.get("compliant", True) and aml_check.get("risk_level") != "high"
return {
"deal_id": deal.get("id"),
"overall_compliant": overall_compliant,
"compliance_score": overall_score,
"real_estate_compliance": real_estate_check,
"aml_screening": aml_check,
"invoice": invoice,
"timestamp": datetime.utcnow().isoformat(),
"summary": "✅ الصفقة متوافقة" if overall_compliant else "⚠️ تحتاج مراجعة"
}
import asyncio