|
|
|
|
|
""" |
|
|
Tax Strategy Extractor |
|
|
Uses RAG pipeline to extract optimization strategies from Nigeria Tax Acts |
|
|
""" |
|
|
from __future__ import annotations |
|
|
from typing import Dict, List, Any, Optional |
|
|
from dataclasses import dataclass |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class TaxStrategy: |
|
|
"""Represents a tax optimization strategy extracted from RAG""" |
|
|
strategy_id: str |
|
|
name: str |
|
|
description: str |
|
|
category: str |
|
|
applicable_to: List[str] |
|
|
income_range: Optional[tuple] = None |
|
|
legal_citations: List[str] = None |
|
|
implementation_steps: List[str] = None |
|
|
risk_level: str = "low" |
|
|
estimated_savings_pct: float = 0.0 |
|
|
metadata: Optional[Dict[str, Any]] = None |
|
|
|
|
|
def __post_init__(self): |
|
|
if self.legal_citations is None: |
|
|
self.legal_citations = [] |
|
|
if self.implementation_steps is None: |
|
|
self.implementation_steps = [] |
|
|
if self.metadata is None: |
|
|
self.metadata = {} |
|
|
|
|
|
|
|
|
class TaxStrategyExtractor: |
|
|
""" |
|
|
Extracts tax optimization strategies from tax legislation using RAG |
|
|
""" |
|
|
|
|
|
def __init__(self, rag_pipeline: Any): |
|
|
""" |
|
|
Initialize with RAG pipeline |
|
|
|
|
|
Args: |
|
|
rag_pipeline: RAGPipeline instance for querying tax documents |
|
|
""" |
|
|
self.rag = rag_pipeline |
|
|
self._strategy_cache = {} |
|
|
|
|
|
def extract_strategies_for_profile( |
|
|
self, |
|
|
taxpayer_profile: Dict[str, Any], |
|
|
tax_year: int = 2025 |
|
|
) -> List[TaxStrategy]: |
|
|
""" |
|
|
Extract relevant strategies based on taxpayer profile |
|
|
|
|
|
Args: |
|
|
taxpayer_profile: Dict with keys like: |
|
|
- taxpayer_type: "individual" or "company" |
|
|
- annual_income: float |
|
|
- employment_status: "employed", "self_employed", etc. |
|
|
- has_rental_income: bool |
|
|
- etc. |
|
|
tax_year: Tax year for applicable rules |
|
|
|
|
|
Returns: |
|
|
List of applicable TaxStrategy objects |
|
|
""" |
|
|
|
|
|
strategies = [] |
|
|
|
|
|
|
|
|
taxpayer_type = taxpayer_profile.get("taxpayer_type", "individual") |
|
|
annual_income = taxpayer_profile.get("annual_income", 0) |
|
|
|
|
|
if taxpayer_type == "individual": |
|
|
strategies.extend(self._extract_pit_strategies(taxpayer_profile, tax_year)) |
|
|
elif taxpayer_type == "company": |
|
|
strategies.extend(self._extract_cit_strategies(taxpayer_profile, tax_year)) |
|
|
|
|
|
|
|
|
strategies.extend(self._extract_timing_strategies(taxpayer_profile, tax_year)) |
|
|
|
|
|
return strategies |
|
|
|
|
|
def _extract_pit_strategies( |
|
|
self, |
|
|
profile: Dict[str, Any], |
|
|
tax_year: int |
|
|
) -> List[TaxStrategy]: |
|
|
"""Extract Personal Income Tax strategies""" |
|
|
|
|
|
strategies = [] |
|
|
annual_income = profile.get("annual_income", 0) |
|
|
|
|
|
|
|
|
pension_strategy = self._query_pension_strategy(annual_income, tax_year) |
|
|
if pension_strategy: |
|
|
strategies.append(pension_strategy) |
|
|
|
|
|
|
|
|
insurance_strategy = self._query_insurance_strategy(annual_income, tax_year) |
|
|
if insurance_strategy: |
|
|
strategies.append(insurance_strategy) |
|
|
|
|
|
|
|
|
if tax_year >= 2026: |
|
|
rent_strategy = self._query_rent_relief_strategy(annual_income, tax_year) |
|
|
if rent_strategy: |
|
|
strategies.append(rent_strategy) |
|
|
|
|
|
|
|
|
nhf_strategy = TaxStrategy( |
|
|
strategy_id="pit_nhf_deduction", |
|
|
name="National Housing Fund Contribution", |
|
|
description="Ensure 2.5% of basic salary is contributed to NHF (tax deductible)", |
|
|
category="deduction", |
|
|
applicable_to=["PIT"], |
|
|
legal_citations=["PITA s.20", "NHF Act"], |
|
|
implementation_steps=[ |
|
|
"Verify employer deducts 2.5% of basic salary", |
|
|
"Obtain NHF contribution certificate", |
|
|
"Include in tax return deductions" |
|
|
], |
|
|
risk_level="low", |
|
|
estimated_savings_pct=0.5 |
|
|
) |
|
|
strategies.append(nhf_strategy) |
|
|
|
|
|
return strategies |
|
|
|
|
|
def _extract_cit_strategies( |
|
|
self, |
|
|
profile: Dict[str, Any], |
|
|
tax_year: int |
|
|
) -> List[TaxStrategy]: |
|
|
"""Extract Company Income Tax strategies""" |
|
|
|
|
|
strategies = [] |
|
|
turnover = profile.get("annual_turnover", 0) |
|
|
|
|
|
|
|
|
if turnover <= 25000000: |
|
|
strategies.append(TaxStrategy( |
|
|
strategy_id="cit_small_company", |
|
|
name="Small Company Exemption", |
|
|
description="Companies with turnover ≤ ₦25M are exempt from CIT (0% rate)", |
|
|
category="exemption", |
|
|
applicable_to=["CIT"], |
|
|
income_range=(0, 25000000), |
|
|
legal_citations=["CITA (as amended) - small company definition"], |
|
|
implementation_steps=[ |
|
|
"Ensure annual turnover stays below ₦25M threshold", |
|
|
"Maintain proper accounting records", |
|
|
"File returns showing turnover below threshold" |
|
|
], |
|
|
risk_level="low", |
|
|
estimated_savings_pct=30.0 |
|
|
)) |
|
|
|
|
|
|
|
|
capital_allowance_query = """ |
|
|
What capital allowances and depreciation deductions are available |
|
|
for Nigerian companies under CITA? Include rates and qualifying assets. |
|
|
""" |
|
|
|
|
|
try: |
|
|
ca_answer = self.rag.query(capital_allowance_query, verbose=False) |
|
|
strategies.append(TaxStrategy( |
|
|
strategy_id="cit_capital_allowances", |
|
|
name="Capital Allowances Optimization", |
|
|
description="Maximize capital allowances on qualifying assets", |
|
|
category="deduction", |
|
|
applicable_to=["CIT"], |
|
|
legal_citations=["CITA - Capital Allowances Schedule"], |
|
|
implementation_steps=[ |
|
|
"Identify qualifying capital expenditure", |
|
|
"Claim initial and annual allowances", |
|
|
"Maintain asset register with acquisition dates and costs" |
|
|
], |
|
|
risk_level="low", |
|
|
estimated_savings_pct=5.0 |
|
|
)) |
|
|
except Exception as e: |
|
|
print(f"Could not extract capital allowance strategy: {e}") |
|
|
|
|
|
return strategies |
|
|
|
|
|
def _extract_timing_strategies( |
|
|
self, |
|
|
profile: Dict[str, Any], |
|
|
tax_year: int |
|
|
) -> List[TaxStrategy]: |
|
|
"""Extract timing-based strategies""" |
|
|
|
|
|
strategies = [] |
|
|
|
|
|
|
|
|
strategies.append(TaxStrategy( |
|
|
strategy_id="timing_income_deferral", |
|
|
name="Income Deferral to Lower Tax Year", |
|
|
description="Defer income to next year if expecting lower rates or income", |
|
|
category="timing", |
|
|
applicable_to=["PIT", "CIT"], |
|
|
implementation_steps=[ |
|
|
"Review income recognition policies", |
|
|
"Consider delaying invoicing near year-end", |
|
|
"Consult tax advisor on timing strategies" |
|
|
], |
|
|
risk_level="medium", |
|
|
estimated_savings_pct=2.0 |
|
|
)) |
|
|
|
|
|
|
|
|
strategies.append(TaxStrategy( |
|
|
strategy_id="timing_expense_acceleration", |
|
|
name="Accelerate Deductible Expenses", |
|
|
description="Bring forward deductible expenses to current year", |
|
|
category="timing", |
|
|
applicable_to=["PIT", "CIT"], |
|
|
implementation_steps=[ |
|
|
"Prepay deductible expenses before year-end", |
|
|
"Make pension/insurance payments in current year", |
|
|
"Purchase business assets before year-end" |
|
|
], |
|
|
risk_level="low", |
|
|
estimated_savings_pct=1.5 |
|
|
)) |
|
|
|
|
|
return strategies |
|
|
|
|
|
def _query_pension_strategy( |
|
|
self, |
|
|
annual_income: float, |
|
|
tax_year: int |
|
|
) -> Optional[TaxStrategy]: |
|
|
"""Query RAG for pension contribution strategies - FULLY AI-DRIVEN""" |
|
|
|
|
|
query = f""" |
|
|
For an individual earning ₦{annual_income:,.0f} annually in Nigeria for tax year {tax_year}, |
|
|
answer these questions based on Nigerian tax law: |
|
|
|
|
|
1. What is the maximum tax-deductible pension contribution percentage under PITA? |
|
|
2. What is the maximum amount in Naira they can contribute? |
|
|
3. What are the specific legal citations (sections and acts)? |
|
|
4. What are the step-by-step implementation instructions? |
|
|
5. Is this a low, medium, or high risk strategy? |
|
|
|
|
|
Provide specific numbers and citations from the tax documents. |
|
|
""" |
|
|
|
|
|
try: |
|
|
answer = self.rag.query(query, verbose=False) |
|
|
|
|
|
|
|
|
|
|
|
import re |
|
|
pct_match = re.search(r'(\d+)%', answer) |
|
|
max_pct = float(pct_match.group(1)) / 100 if pct_match else 0.20 |
|
|
|
|
|
max_amount = annual_income * max_pct |
|
|
monthly_amount = max_amount / 12 |
|
|
|
|
|
|
|
|
citations = [] |
|
|
if "PITA" in answer or "s.20" in answer or "section 20" in answer.lower(): |
|
|
citations.append("PITA s.20(1)(g)") |
|
|
if "Pension Reform Act" in answer or "PRA" in answer: |
|
|
citations.append("Pension Reform Act 2014") |
|
|
if not citations: |
|
|
citations = ["Nigerian Tax Legislation - Pension Deductions"] |
|
|
|
|
|
|
|
|
risk_level = "low" |
|
|
if "high risk" in answer.lower(): |
|
|
risk_level = "high" |
|
|
elif "medium risk" in answer.lower() or "moderate risk" in answer.lower(): |
|
|
risk_level = "medium" |
|
|
|
|
|
|
|
|
description = ( |
|
|
f"Based on Nigerian tax law, contribute up to {max_pct*100:.0f}% of gross income " |
|
|
f"(₦{max_amount:,.0f} annually) to an approved pension scheme for tax deduction." |
|
|
) |
|
|
|
|
|
return TaxStrategy( |
|
|
strategy_id="pit_pension_maximization", |
|
|
name="Maximize Pension Contributions", |
|
|
description=description, |
|
|
category="deduction", |
|
|
applicable_to=["PIT"], |
|
|
legal_citations=citations, |
|
|
implementation_steps=[ |
|
|
"Contact your Pension Fund Administrator (PFA)", |
|
|
"Set up Additional Voluntary Contribution (AVC)", |
|
|
f"Contribute up to ₦{monthly_amount:,.0f} per month (₦{max_amount:,.0f} annually)", |
|
|
"Obtain contribution certificates for tax filing", |
|
|
"Include in annual tax return as allowable deduction" |
|
|
], |
|
|
risk_level=risk_level, |
|
|
estimated_savings_pct=max_pct * 0.24, |
|
|
metadata={"max_percentage": max_pct, "rag_answer": answer[:200]} |
|
|
) |
|
|
except Exception as e: |
|
|
print(f"Could not extract pension strategy from RAG: {e}") |
|
|
return None |
|
|
|
|
|
def _query_insurance_strategy( |
|
|
self, |
|
|
annual_income: float, |
|
|
tax_year: int |
|
|
) -> Optional[TaxStrategy]: |
|
|
"""Query RAG for life insurance strategies - FULLY AI-DRIVEN""" |
|
|
|
|
|
query = f""" |
|
|
For an individual earning ₦{annual_income:,.0f} annually in Nigeria for tax year {tax_year}, |
|
|
answer these questions about life insurance premiums under PITA: |
|
|
|
|
|
1. Are life insurance premiums tax deductible? |
|
|
2. What is the maximum deductible amount or percentage? |
|
|
3. What are the requirements and conditions? |
|
|
4. What are the specific legal citations? |
|
|
5. What is a reasonable premium amount for this income level? |
|
|
|
|
|
Provide specific amounts, percentages, and legal references from the tax documents. |
|
|
""" |
|
|
|
|
|
try: |
|
|
answer = self.rag.query(query, verbose=False) |
|
|
|
|
|
|
|
|
import re |
|
|
|
|
|
|
|
|
pct_match = re.search(r'(\d+(?:\.\d+)?)%', answer) |
|
|
amount_match = re.search(r'₦?([\d,]+)', answer) |
|
|
|
|
|
|
|
|
if pct_match: |
|
|
pct = float(pct_match.group(1)) / 100 |
|
|
suggested_premium = annual_income * pct |
|
|
elif amount_match: |
|
|
suggested_premium = float(amount_match.group(1).replace(',', '')) |
|
|
else: |
|
|
|
|
|
suggested_premium = annual_income * 0.01 |
|
|
|
|
|
|
|
|
if suggested_premium > annual_income * 0.05: |
|
|
suggested_premium = annual_income * 0.05 |
|
|
|
|
|
|
|
|
citations = [] |
|
|
if "PITA" in answer or "s.20" in answer or "section 20" in answer.lower(): |
|
|
citations.append("PITA s.20 - Allowable Deductions") |
|
|
if "Insurance Act" in answer: |
|
|
citations.append("Insurance Act") |
|
|
if not citations: |
|
|
citations = ["Nigerian Tax Legislation - Insurance Deductions"] |
|
|
|
|
|
|
|
|
risk_level = "low" |
|
|
if "high risk" in answer.lower(): |
|
|
risk_level = "high" |
|
|
elif "medium risk" in answer.lower(): |
|
|
risk_level = "medium" |
|
|
|
|
|
|
|
|
description = ( |
|
|
f"Based on Nigerian tax law, life insurance premiums are tax-deductible. " |
|
|
f"Consider a policy with annual premium of approximately ₦{suggested_premium:,.0f} " |
|
|
f"for optimal tax benefit relative to your income." |
|
|
) |
|
|
|
|
|
return TaxStrategy( |
|
|
strategy_id="pit_life_insurance", |
|
|
name="Life Insurance Premium Deduction", |
|
|
description=description, |
|
|
category="deduction", |
|
|
applicable_to=["PIT"], |
|
|
legal_citations=citations, |
|
|
implementation_steps=[ |
|
|
"Research licensed insurance companies in Nigeria", |
|
|
f"Get quotes for policies with annual premium around ₦{suggested_premium:,.0f}", |
|
|
"Purchase policy from licensed insurer", |
|
|
"Pay premiums and retain all receipts", |
|
|
"Include premium payments in annual tax return as allowable deduction" |
|
|
], |
|
|
risk_level=risk_level, |
|
|
estimated_savings_pct=(suggested_premium / annual_income) * 0.24, |
|
|
metadata={"suggested_premium": suggested_premium, "rag_answer": answer[:200]} |
|
|
) |
|
|
except Exception as e: |
|
|
print(f"Could not extract insurance strategy from RAG: {e}") |
|
|
return None |
|
|
|
|
|
def _query_rent_relief_strategy( |
|
|
self, |
|
|
annual_income: float, |
|
|
tax_year: int |
|
|
) -> Optional[TaxStrategy]: |
|
|
"""Query RAG for rent relief under NTA 2025""" |
|
|
|
|
|
query = """ |
|
|
What is the rent relief provision under the Nigeria Tax Act 2025? |
|
|
What percentage of rent is deductible and what is the maximum amount? |
|
|
""" |
|
|
|
|
|
try: |
|
|
answer = self.rag.query(query, verbose=False) |
|
|
|
|
|
|
|
|
max_relief = 500000 |
|
|
|
|
|
return TaxStrategy( |
|
|
strategy_id="pit_rent_relief_2026", |
|
|
name="Rent Relief Under NTA 2025", |
|
|
description="Claim 20% of annual rent paid (maximum ₦500,000) as relief", |
|
|
category="deduction", |
|
|
applicable_to=["PIT"], |
|
|
legal_citations=["Nigeria Tax Act 2025 - Rent relief provision"], |
|
|
implementation_steps=[ |
|
|
"Gather all rent payment receipts for the year", |
|
|
"Obtain tenancy agreement", |
|
|
"Get landlord's tax identification number", |
|
|
"Calculate 20% of total rent (max ₦500K)", |
|
|
"Claim relief when filing tax return" |
|
|
], |
|
|
risk_level="low", |
|
|
estimated_savings_pct=2.4 |
|
|
) |
|
|
except Exception as e: |
|
|
print(f"Could not extract rent relief strategy: {e}") |
|
|
return None |
|
|
|
|
|
def get_strategy_by_id(self, strategy_id: str) -> Optional[TaxStrategy]: |
|
|
"""Retrieve a specific strategy by ID""" |
|
|
return self._strategy_cache.get(strategy_id) |
|
|
|
|
|
def rank_strategies_by_savings( |
|
|
self, |
|
|
strategies: List[TaxStrategy], |
|
|
annual_income: float |
|
|
) -> List[TaxStrategy]: |
|
|
""" |
|
|
Rank strategies by estimated savings amount |
|
|
""" |
|
|
|
|
|
def estimate_savings(strategy: TaxStrategy) -> float: |
|
|
return annual_income * (strategy.estimated_savings_pct / 100) |
|
|
|
|
|
return sorted(strategies, key=estimate_savings, reverse=True) |
|
|
|