import frappe import requests import json from invoice_az.auth import record_etaxes_activity, get_default_asan_login # Constants BASE_URL = "https://new.e-taxes.gov.az" FIND_BY_FIN_URL = f"{BASE_URL}/api/po/profile/public/v1/taxpayer/findByFinAndPassport" DEFAULT_HEADERS = { "Accept": "application/json, text/plain, */*", "Accept-Language": "en-US,en;q=0.9", "Content-Type": "application/json", "Cache-Control": "no-cache", "Pragma": "no-cache" } @frappe.whitelist() def fetch_supplier_data_from_etaxes(supplier_name): """ Fetch Individual supplier data from E-Taxes by FIN and Passport Serial Number Args: supplier_name: Name of Supplier document Returns: dict: { "success": bool, "data": { "fin": str, "fullName": str, "phone": str, "dateOfBirth": str, "firstname": str, "lastname": str, "patronimyc": str }, "message": str } """ try: # Record activity for token renewal record_etaxes_activity() # Get Supplier document supplier = frappe.get_doc("Supplier", supplier_name) # Validate supplier type if supplier.supplier_type != "Individual": return { "success": False, "message": "This function only works for Individual suppliers" } # Check required fields if not supplier.fin: return { "success": False, "message": "FIN is required. Please fill FIN field first." } if not supplier.passport_serial_number: return { "success": False, "message": "Passport Serial Number is required. Please fill Passport Serial Number field first." } # Get authentication token asan_login = get_default_asan_login() if not asan_login.get("found") or not asan_login.get("main_token"): return { "success": False, "message": "E-Taxes authentication not found. Please login via ASAN." } token = asan_login.get("main_token") # Build headers headers = DEFAULT_HEADERS.copy() headers["x-authorization"] = f"Bearer {token}" # Build payload payload = { "fin": supplier.fin, "passportSerialNumber": supplier.passport_serial_number } # Make API request response = requests.post( FIND_BY_FIN_URL, data=json.dumps(payload), headers=headers, timeout=30 ) # Handle 401 Unauthorized if response.status_code == 401: return { "success": False, "message": "Authentication expired. Please login again via ASAN." } # Handle 500 Server Error if response.status_code == 500: return { "success": False, "message": "E-Taxes service error. Please try again later." } # Handle 404 Not Found (person not found) if response.status_code == 404: return { "success": False, "message": "Person not found in E-Taxes system. Please check FIN and Passport Serial Number." } # Handle errors with E-Taxes message format # Accept both 200 (OK) and 201 (Created) as success if response.status_code not in [200, 201]: try: error_data = response.json() # Try to get Azərbaycan message first if isinstance(error_data, dict) and "message" in error_data: if isinstance(error_data["message"], dict) and "az" in error_data["message"]: return { "success": False, "message": error_data["message"]["az"] } elif isinstance(error_data["message"], str): return { "success": False, "message": error_data["message"] } except: pass return { "success": False, "message": f"E-Taxes error (status {response.status_code})" } response.raise_for_status() # Parse response result = response.json() return { "success": True, "data": result } except requests.exceptions.RequestException as e: frappe.log_error( f"Error fetching supplier data from E-Taxes: {str(e)}", "Fetch Supplier Data Error" ) return { "success": False, "message": f"Network error: {str(e)}" } except Exception as e: frappe.log_error( f"Unexpected error fetching supplier data: {str(e)}\n{frappe.get_traceback()}", "Fetch Supplier Data Error" ) return { "success": False, "message": f"Error: {str(e)}" } @frappe.whitelist() def update_supplier_from_etaxes(supplier_name): """ Fetch data from E-Taxes and update Supplier fields Args: supplier_name: Name of Supplier document Returns: dict: Success/error response with update details """ try: # Fetch data from E-Taxes fetch_result = fetch_supplier_data_from_etaxes(supplier_name) if not fetch_result.get("success"): return fetch_result data = fetch_result.get("data") # Get Supplier document supplier = frappe.get_doc("Supplier", supplier_name) # Update fields from E-Taxes response updated_fields = [] # Date of birth if data.get("dateOfBirth") and not supplier.date_of_birth: supplier.date_of_birth = data.get("dateOfBirth") updated_fields.append("Date of Birth") # First name if data.get("firstname"): supplier.first_name_individual = data.get("firstname") updated_fields.append("First Name") # Last name if data.get("lastname"): supplier.last_name_individual = data.get("lastname") updated_fields.append("Last Name") # Patronymic (middle name / father's name) if data.get("patronimyc"): supplier.patronimyc = data.get("patronimyc") updated_fields.append("Patronymic") # Phone number (optional) if data.get("phone") and not supplier.phone_number_individual: supplier.phone_number_individual = data.get("phone") updated_fields.append("Phone Number") # Note: Supplier Name is not updated to preserve user's custom name # Save supplier supplier.save() frappe.db.commit() return { "success": True, "message": f"Supplier data updated successfully. Updated fields: {', '.join(updated_fields)}", "updated_fields": updated_fields } except Exception as e: frappe.log_error( f"Error updating supplier from E-Taxes: {str(e)}\n{frappe.get_traceback()}", "Update Supplier Error" ) return { "success": False, "message": f"Error: {str(e)}" }