File size: 7,677 Bytes
877e000 ebb3d5e 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 ebb3d5e 877e000 ebb3d5e 9860c76 877e000 ebb3d5e 877e000 9860c76 ebb3d5e 877e000 9860c76 877e000 ebb3d5e 877e000 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 877e000 ebb3d5e 877e000 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 877e000 ebb3d5e 9860c76 ebb3d5e 9860c76 ebb3d5e 9860c76 7ac74a0 877e000 ebb3d5e 9860c76 ebb3d5e 9860c76 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# models/address_verification.py
import requests
import time
from geopy.geocoders import Nominatim
from .logging_config import logger
geocoder = Nominatim(user_agent="indian_property_verifier", timeout=10)
def verify_address(data):
try:
address_results = {
'address_exists': False,
'pincode_valid': False,
'city_state_match': False,
'coordinates_match': False,
'confidence': 0.0,
'issues': [],
'verification_score': 0.0
}
# Validate input fields
zip_code = str(data.get('zip', '')).strip()
city = str(data.get('city', '')).strip()
state = str(data.get('state', '')).strip()
address = str(data.get('address', '')).strip()
country = str(data.get('country', 'India')).strip()
latitude = data.get('latitude', None)
longitude = data.get('longitude', None)
# Basic validation - give more points for having required fields
basic_score = 0.0
if zip_code:
basic_score += 0.25 # Increased from 0.2
if city:
basic_score += 0.25 # Increased from 0.2
if state:
basic_score += 0.25 # Increased from 0.2
if address:
basic_score += 0.15 # Reduced from 0.2 since address is less critical
if latitude and longitude:
basic_score += 0.10 # Reduced from 0.2 since coordinates are optional
# Pincode validation with much more lenient fallback
if zip_code:
try:
response = requests.get(f"https://api.postalpincode.in/pincode/{zip_code}", timeout=5)
if response.status_code == 200:
pin_data = response.json()
if pin_data[0]['Status'] == 'Success':
address_results['pincode_valid'] = True
post_offices = pin_data[0]['PostOffice']
cities = {po['Name'].lower() for po in post_offices}
states = {po['State'].lower() for po in post_offices}
if city.lower() in cities or state.lower() in states:
address_results['city_state_match'] = True
else:
address_results['issues'].append("City/state may not match pincode")
else:
address_results['issues'].append(f"Invalid pincode: {zip_code}")
else:
address_results['issues'].append("Pincode API error")
except Exception as e:
logger.error(f"Pincode API error: {str(e)}")
# Much more lenient fallback - give credit for having pincode
if zip_code and len(zip_code) == 6 and zip_code.isdigit():
address_results['pincode_valid'] = True
address_results['issues'].append("Pincode validation failed (API error)")
else:
address_results['issues'].append("Pincode validation failed")
# Geocoding with much more lenient fallback
full_address = ', '.join(filter(None, [address, city, state, country, zip_code]))
geocoding_success = False
for attempt in range(2): # Reduced attempts from 3 to 2
try:
location = geocoder.geocode(full_address)
if location:
address_results['address_exists'] = True
address_results['confidence'] = 0.9
geocoding_success = True
if latitude and longitude:
try:
provided_coords = (float(latitude), float(longitude))
geocoded_coords = (location.latitude, location.longitude)
from geopy.distance import distance
dist = distance(provided_coords, geocoded_coords).km
address_results['coordinates_match'] = dist < 2.0 # Increased from 1.0 to 2.0
if not address_results['coordinates_match']:
address_results['issues'].append(f"Coordinates {dist:.2f}km off")
except Exception as e:
logger.warning(f"Invalid coordinates: {str(e)}")
address_results['issues'].append("Invalid coordinates")
break
time.sleep(1)
except Exception as e:
logger.error(f"Geocoding error on attempt {attempt + 1}: {str(e)}")
time.sleep(1)
if not geocoding_success:
# Much more lenient fallback: if we have basic address components, give good credit
if address and city and state:
address_results['address_exists'] = True
address_results['confidence'] = 0.8 # Increased from 0.6
address_results['issues'].append("Address geocoding failed (using fallback validation)")
elif city and state: # Even more lenient - just city and state
address_results['address_exists'] = True
address_results['confidence'] = 0.7 # Good score for city/state
address_results['issues'].append("Address geocoding failed (using fallback validation)")
else:
address_results['issues'].append("Address geocoding failed")
# Calculate verification score with much more lenient fallback
try:
verification_points = (
float(address_results['address_exists']) * 0.4 +
float(address_results['pincode_valid']) * 0.3 +
float(address_results['city_state_match']) * 0.2 +
float(address_results['coordinates_match']) * 0.1
)
# Much more lenient fallback scoring
if verification_points == 0.0 and basic_score > 0.0:
verification_points = basic_score * 0.8 # Increased from 0.5 to 0.8
except Exception as e:
logger.warning(f"Error calculating verification points: {str(e)}")
verification_points = basic_score * 0.8 # Increased fallback to basic score
# Much more lenient minimum score for valid data
if verification_points == 0.0 and (zip_code or city or state or address):
verification_points = 0.4 # Increased from 0.2 to 0.4 (40% minimum)
# Additional bonus for having multiple address components
if zip_code and city and state:
verification_points = min(1.0, verification_points + 0.1) # 10% bonus
elif city and state:
verification_points = min(1.0, verification_points + 0.05) # 5% bonus
# Ensure verification score is properly capped at 100%
verification_score = min(100.0, verification_points * 100) # Convert to percentage and cap at 100%
address_results['verification_score'] = verification_score
return address_results
except Exception as e:
logger.error(f"Error verifying address: {str(e)}")
# Return much higher minimum score instead of 0
return {
'address_exists': False,
'pincode_valid': False,
'city_state_match': False,
'coordinates_match': False,
'confidence': 0.0,
'issues': [f"Address verification error: {str(e)}"],
'verification_score': 30.0 # Increased from 10.0 to 30.0
}
|