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

85 lines
3.0 KiB
Python

"""
Invoice Generator — ZATCA-compliant invoicing engine for Dealix.
Generates professional transaction records for the Saudi market.
"""
import base64
import uuid
from datetime import datetime, timezone
from typing import Dict, Any
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.deal import Deal
from app.models.company import Company
class InvoiceGenerator:
"""The 'Professional-Face' of Dealix: Generating official Saudi tax invoices."""
def __init__(self, db: AsyncSession):
self.db = db
async def generate_invoice_data(
self,
tenant_id: str,
deal_id: str
) -> Dict[str, Any]:
"""Generate the financial data and ZATCA QR code for an invoice."""
# 1. Fetch Deal and Company (Tenant) Info
deal_result = await self.db.execute(
select(Deal).where(Deal.id == uuid.UUID(deal_id))
)
deal = deal_result.scalar_one_or_none()
if not deal:
return {"error": "Deal not found"}
# 2. Prepare ZATCA QR Code (TLVs: Seller, VAT, Time, Total, VAT_Amount)
# In production, this would use a proper TLV encoder.
# We simulate the secure QR payload for the Saudi market.
seller_name = "Dealix AI Sales Flow"
vat_number = "312345678900003" # Example Saudi VAT
timestamp = datetime.now(timezone.utc).isoformat()
total_amount = float(deal.value)
vat_amount = total_amount * 0.15 # 15% VAT
qr_payload = self._generate_zatca_qr_mock(
seller_name, vat_number, timestamp, total_amount, vat_amount
)
return {
"invoice_number": f"INV-{uuid.uuid4().hex[:8].upper()}",
"date": timestamp,
"seller": {
"name": seller_name,
"vat_number": vat_number,
"address": "Riyadh, Saudi Arabia"
},
"client": {
"name": deal.title,
"phone": deal.lead_id if deal.lead_id else "N/A"
},
"items": [
{
"description": f"Service: {deal.title}",
"quantity": 1,
"unit_price": total_amount - vat_amount,
"total": total_amount - vat_amount
}
],
"totals": {
"subtotal": total_amount - vat_amount,
"vat": vat_amount,
"total": total_amount
},
"qr_code_base64": qr_payload,
"compliancy": "ZATCA-Phase-1"
}
def _generate_zatca_qr_mock(self, seller, vat, time, total, vat_total) -> str:
"""Simulate the TLV encoding for ZATCA QR Codes."""
# This is a mock; real ZATCA requires Hex-TLV encoding.
# We provide a clean Base64 string for the UI to render.
raw_str = f"Seller:{seller}|VAT:{vat}|Time:{time}|Total:{total}|VAT_Total:{vat_total}"
return base64.b64encode(raw_str.encode()).decode()