""" Standardized Response Formatter for Kaanta AI. Provides consistent output formats for WhatsApp, Web, and API responses. Ensures all tax calculations include proper citations and validation. """ from dataclasses import dataclass, field from typing import Dict, List, Optional, Any, Union from datetime import date from enum import Enum import json class OutputFormat(Enum): """Available output formats.""" WHATSAPP = "whatsapp" WEB = "web" API = "api" REPORT = "report" @dataclass class LegalCitation: """Legal citation for tax calculations.""" document: str section: Optional[str] = None page: Optional[str] = None def format(self) -> str: parts = [self.document] if self.section: parts.append(f"s.{self.section}") if self.page: parts.append(f"p.{self.page}") return ", ".join(parts) @dataclass class KeyPoint: """A key point in the response.""" text: str citation: Optional[LegalCitation] = None @dataclass class ActionItem: """An action item for the user.""" action: str priority: str = "normal" # high, normal, low deadline: Optional[str] = None @dataclass class StandardResponse: """ Standardized response structure for all Kaanta outputs. This ensures consistency across WhatsApp, Web, and API. """ # Summary (always present) headline: str summary: str # Key points key_points: List[KeyPoint] = field(default_factory=list) # Action items (optional) action_items: List[ActionItem] = field(default_factory=list) # Detailed data (optional) data: Optional[Dict[str, Any]] = None # Legal basis (always present) citations: List[LegalCitation] = field(default_factory=list) # Metadata calculation_date: date = field(default_factory=date.today) regime: str = "NTA 2026" confidence: float = 1.0 warnings: List[str] = field(default_factory=list) class ResponseFormatter: """ Formats StandardResponse for different output targets. """ @staticmethod def to_whatsapp(response: StandardResponse) -> str: """Format for WhatsApp (plain text, clean formatting).""" lines = [] # Headline lines.append(f"*{response.headline}*") lines.append("") # Summary lines.append(response.summary) lines.append("") # Key points if response.key_points: lines.append("*Key Points:*") for point in response.key_points: lines.append(f"- {point.text}") lines.append("") # Action items if response.action_items: lines.append("*Next Steps:*") for action in response.action_items: priority_marker = "[!]" if action.priority == "high" else "" lines.append(f"- {priority_marker} {action.action}") lines.append("") # Legal citations if response.citations: citation_strs = [c.format() for c in response.citations] lines.append(f"*Legal Basis:* {'; '.join(citation_strs)}") lines.append("") # Warnings if response.warnings: lines.append("*Notes:*") for warning in response.warnings: lines.append(f"- {warning}") lines.append("") # Footer lines.append("_Powered by Kaanta_") return "\n".join(lines) @staticmethod def to_web(response: StandardResponse) -> Dict[str, Any]: """Format for Web (structured JSON).""" return { "summary": { "headline": response.headline, "text": response.summary, }, "key_points": [ { "text": p.text, "citation": p.citation.format() if p.citation else None } for p in response.key_points ], "action_items": [ { "action": a.action, "priority": a.priority, "deadline": a.deadline } for a in response.action_items ], "data": response.data, "legal": { "regime": response.regime, "citations": [c.format() for c in response.citations], "calculation_date": response.calculation_date.isoformat() }, "meta": { "confidence": response.confidence, "warnings": response.warnings } } @staticmethod def to_api(response: StandardResponse) -> Dict[str, Any]: """Format for API (complete JSON with all details).""" return { "status": "success", "response": { "headline": response.headline, "summary": response.summary, "key_points": [p.text for p in response.key_points], "action_items": [ {"action": a.action, "priority": a.priority} for a in response.action_items ], "data": response.data, }, "legal": { "regime": response.regime, "citations": [ {"document": c.document, "section": c.section, "page": c.page} for c in response.citations ], }, "meta": { "calculation_date": response.calculation_date.isoformat(), "confidence": response.confidence, "warnings": response.warnings, } } @staticmethod def to_report(response: StandardResponse) -> str: """Format for PDF/Report (detailed plain text).""" lines = [] lines.append("=" * 60) lines.append(response.headline.upper()) lines.append(f"Calculated on: {response.calculation_date.isoformat()}") lines.append(f"Tax Regime: {response.regime}") lines.append("=" * 60) lines.append("") # Summary lines.append("SUMMARY") lines.append("-" * 40) lines.append(response.summary) lines.append("") # Key points if response.key_points: lines.append("KEY POINTS") lines.append("-" * 40) for i, point in enumerate(response.key_points, 1): lines.append(f"{i}. {point.text}") if point.citation: lines.append(f" Reference: {point.citation.format()}") lines.append("") # Action items if response.action_items: lines.append("RECOMMENDED ACTIONS") lines.append("-" * 40) for i, action in enumerate(response.action_items, 1): priority_label = f"[{action.priority.upper()}]" if action.priority != "normal" else "" lines.append(f"{i}. {priority_label} {action.action}") lines.append("") # Legal citations lines.append("LEGAL BASIS") lines.append("-" * 40) for citation in response.citations: lines.append(f"- {citation.format()}") lines.append("") # Warnings if response.warnings: lines.append("IMPORTANT NOTES") lines.append("-" * 40) for warning in response.warnings: lines.append(f"* {warning}") lines.append("") lines.append("=" * 60) lines.append("Prepared by Kaanta AI - Nigerian Tax Assistant") lines.append("=" * 60) return "\n".join(lines) @classmethod def format(cls, response: StandardResponse, output_format: OutputFormat) -> Union[str, Dict]: """Format response to specified output format.""" formatters = { OutputFormat.WHATSAPP: cls.to_whatsapp, OutputFormat.WEB: cls.to_web, OutputFormat.API: cls.to_api, OutputFormat.REPORT: cls.to_report, } return formatters[output_format](response) def create_tax_calculation_response( monthly_tax: float, monthly_income: float, monthly_net: float, effective_rate: float, deductions: Dict[str, float], bands: List[Dict[str, Any]], regime: str = "NTA 2026", citations: List[str] = None ) -> StandardResponse: """ Create a standardized response for tax calculations. Helper function for common tax calculation outputs. """ headline = f"Tax: N{monthly_tax:,.0f}/month on N{monthly_income:,.0f} income" summary = ( f"Your monthly tax is N{monthly_tax:,.2f} on a gross income of N{monthly_income:,.2f}. " f"After tax and statutory deductions, your take-home pay is N{monthly_net:,.2f}. " f"Your effective tax rate is {effective_rate:.1f}%." ) key_points = [ KeyPoint(text=f"First N800,000 annually is tax-free under {regime}"), KeyPoint(text=f"Pension contribution (8%) is deducted: N{deductions.get('pension', 0):,.0f}"), ] if deductions.get('rent_relief', 0) > 0: key_points.append( KeyPoint(text=f"Rent relief applied: N{deductions['rent_relief']:,.0f}") ) action_items = [ ActionItem(action="Verify your payslip shows correct deductions", priority="high"), ActionItem(action="Keep records for annual tax filing"), ] legal_citations = [ LegalCitation(document=citation) for citation in (citations or [regime]) ] data = { "income": {"monthly": monthly_income, "annual": monthly_income * 12}, "tax": {"monthly": monthly_tax, "annual": monthly_tax * 12}, "net": {"monthly": monthly_net, "annual": monthly_net * 12}, "effective_rate": effective_rate, "deductions": deductions, "bands": bands, } return StandardResponse( headline=headline, summary=summary, key_points=key_points, action_items=action_items, data=data, citations=legal_citations, regime=regime, )