Add user location support and tax analysis enhancements
- Introduced user location extraction from user tax info for improved matching. - Normalized user location to province codes for tax calculations. - Updated MatchResponse schema to include tax analysis data. - Enhanced LLMTaxAnalyzer to handle various location formats and provide fallback logic.
This commit is contained in:
@@ -87,7 +87,13 @@ class LLMTaxAnalyzer:
|
||||
|
||||
# Extract location information
|
||||
receipt_location = self._extract_receipt_location(receipt)
|
||||
user_province = user_location.upper()
|
||||
|
||||
# Normalize user_location to province code (handle "Canada", "Ontario", "ON", etc.)
|
||||
user_province = self._normalize_location_to_province(user_location)
|
||||
|
||||
logger.info(
|
||||
f"Building tax analysis context - User Location: {user_location} → Province Code: {user_province}"
|
||||
)
|
||||
|
||||
# Build tax rates reference
|
||||
tax_rates_info = json.dumps(self.PROVINCIAL_TAX_RATES, indent=2)
|
||||
@@ -130,6 +136,47 @@ CCA DEPRECIATION RATES BY ASSET CLASS:
|
||||
"""
|
||||
return context
|
||||
|
||||
def _normalize_location_to_province(self, location: str) -> str:
|
||||
"""
|
||||
Normalize various location formats to province code.
|
||||
Handles: "ON", "Ontario", "Canada", etc.
|
||||
"""
|
||||
location_upper = location.upper().strip()
|
||||
|
||||
# Direct province code match
|
||||
if location_upper in self.PROVINCIAL_TAX_RATES:
|
||||
return location_upper
|
||||
|
||||
# Map full province names to codes
|
||||
province_name_map = {
|
||||
"ONTARIO": "ON",
|
||||
"QUEBEC": "QC",
|
||||
"BRITISH COLUMBIA": "BC",
|
||||
"ALBERTA": "AB",
|
||||
"SASKATCHEWAN": "SK",
|
||||
"MANITOBA": "MB",
|
||||
"NOVA SCOTIA": "NS",
|
||||
"NEW BRUNSWICK": "NB",
|
||||
"NEWFOUNDLAND AND LABRADOR": "NL",
|
||||
"NEWFOUNDLAND": "NL",
|
||||
"PRINCE EDWARD ISLAND": "PE",
|
||||
"NORTHWEST TERRITORIES": "NT",
|
||||
"NUNAVUT": "NU",
|
||||
"YUKON": "YT",
|
||||
}
|
||||
|
||||
if location_upper in province_name_map:
|
||||
return province_name_map[location_upper]
|
||||
|
||||
# Default to Ontario if country is Canada or unspecified
|
||||
if location_upper in ["CANADA", "CAN", "CA", ""]:
|
||||
logger.warning(f"Location '{location}' is too generic, defaulting to ON")
|
||||
return "ON"
|
||||
|
||||
# If nothing matches, default to Ontario
|
||||
logger.warning(f"Could not parse location '{location}', defaulting to ON")
|
||||
return "ON"
|
||||
|
||||
def _extract_receipt_location(self, receipt: Receipt) -> str:
|
||||
"""Extract and format receipt location information"""
|
||||
|
||||
@@ -276,6 +323,7 @@ b) **CCA Depreciation** (for tax purposes - Canada):
|
||||
Provide a structured JSON response with the following format:
|
||||
|
||||
{{
|
||||
"final_tax_amount": XX.XX,
|
||||
"sales_tax": {{
|
||||
"applicable_province": "XX",
|
||||
"applicable_rate": 0.XX,
|
||||
@@ -321,6 +369,8 @@ Provide a structured JSON response with the following format:
|
||||
"overall_assessment": "Comprehensive summary: which rules applied, why, what location used for what purpose, and any required actions"
|
||||
}}
|
||||
|
||||
**IMPORTANT**: The "final_tax_amount" field at the top level must contain the final calculated tax amount. This should be the calculated_tax from sales_tax analysis. If this is a meals & entertainment expense, ensure you return the FULL tax amount here (not the 50% adjusted amount).
|
||||
|
||||
**Critical Reminders**:
|
||||
- Sales tax uses RECEIPT location (or user location if receipt has none)
|
||||
- Depreciation ALWAYS uses USER location
|
||||
@@ -356,6 +406,7 @@ Provide a structured JSON response with the following format:
|
||||
"""Return fallback analysis if LLM fails"""
|
||||
return json.dumps(
|
||||
{
|
||||
"final_tax_amount": 0.0,
|
||||
"sales_tax": {
|
||||
"applicable_province": "ON",
|
||||
"applicable_rate": 0.13,
|
||||
@@ -424,6 +475,7 @@ Provide a structured JSON response with the following format:
|
||||
|
||||
# Return structured fallback
|
||||
return {
|
||||
"final_tax_amount": receipt.tax if receipt.tax else 0.0,
|
||||
"sales_tax": {
|
||||
"requires_review": True,
|
||||
"reason": "Failed to parse LLM response",
|
||||
|
||||
Reference in New Issue
Block a user