invoice_az/invoice_az/supplier_api.py

245 lines
7.4 KiB
Python

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)}"
}