from afip import Afip
from datetime import datetime

afip = Afip({ "CUIT": 20409378472 })

# URL al archivo WSDL de test (Homologación)
WSDL_TEST = "https://wswhomo.afip.gov.ar/wsfexv1/service.asmx?WSDL"

# URL al archivo WSDL de producción
WSDL = "https://servicios1.afip.gov.ar/wsfexv1/service.asmx?WSDL"

# URL del Web Service de producción
URL = "https://servicios1.afip.gov.ar/wsfexv1/service.asmx"

# URL del Web Service de test (Homologación)
URL_TEST = "https://wswhomo.afip.gov.ar/wsfexv1/service.asmx"

# Se debe usar SOAP 1.1 (por el namespace usado en los ejemplos del manual)
soapV1_2 = False

# Nombre del Web Service (para Factura de Exportación se utiliza "wsfex")
servicio = "wsfex"

# Preparamos las opciones para el web service
options = {
  "WSDL": WSDL,
  "WSDL_TEST": WSDL_TEST,
  "URL": URL,
  "URL_TEST": URL_TEST,
  "soapV1_2": soapV1_2
}

# Creamos el web service
genericWebService = afip.webService(servicio, options)

# Obtenemos el Token Authorization mediante WSAA
ta = genericWebService.getTokenAuthorization()

# Preparamos los datos que requiere el método FEXAuthorize según el manual
data = {
  "Auth": {
    "Token": ta["token"],
    "Sign": ta["sign"],
    "Cuit": afip.CUIT
  },
  "Cmp": {
    "Id": 123456789,                       # Identificador único del requerimiento (ejemplo)
    "Fecha_cbte": datetime.today().strftime("%Y%m%d"), # Fecha del comprobante en formato YYYYMMDD
    "Cbte_Tipo": 19,                         # Tipo de comprobante: 19 = Factura de Exportación
    "Punto_vta": 1,                          # Punto de venta asignado
    "Cbte_nro": 1,                           # Número de comprobante (se puede generar secuencialmente)
    "Tipo_expo": 1,                          # Tipo de exportación: 1 = Exportación definitiva de bienes
    "Permiso_existente": "N",                # Indica que aún no se dispone del permiso de embarque
    "Dst_cmp": 212,                            # Código del país de destino (consultar FEXGetPARAM_DST_pais)
    "Cliente": "Empresa de Exportación S.A.",
    "Cuit_pais_cliente": 0,                  # Se puede omitir si se completa Id_impositivo
    "Domicilio_cliente": "Calle Exportación 123, Ciudad, País",
    "Id_impositivo": "12345678901",          # Identificación tributaria del comprador
    "Moneda_Id": "DOL",                      # Código de moneda (por ejemplo, "DOL" para dólares)
    "Moneda_ctz": 1090,                       # Cotización de la moneda (según FEXGetPARAM_Ctz)
    "Obs_comerciales": "Observaciones de prueba",
    "Imp_total": 1000.00,                    # Importe total del comprobante
    "Obs": "Observaciones generales",
    "Cmps_asoc": {"Cmp_asoc": []},           # Comprobantes asociados (vacío en este ejemplo)
    "Forma_pago": "Contado",
    "Incoterms": "FOB",                      # Cláusula de venta (según FEXGetPARAM_Incoterms)
    "Incoterms_Ds": "Free on Board",         # Descripción complementaria del incoterm
    "Idioma_cbte": 1,                        # Idioma del comprobante: 1 = Español
    "Items": {
      "Item": [
        {
          "Pro_codigo": "PRD001",          # Código del producto
          "Pro_ds": "Producto de Exportación",  # Descripción del producto
          "Pro_qty": 10,                   # Cantidad
          "Pro_umed": 1,                   # Unidad de medida (consultar FEXGetPARAM_UMed)
          "Pro_precio_uni": 100.00,        # Precio unitario
          "Pro_bonificacion": 0.00,        # Bonificación (si aplica)
          "Pro_total_item": 1000.00        # Total del ítem (10 * 100.00)
        }
      ]
    },
    "Opcionales": {"Opcional": []},          # Datos opcionales (se llena según corresponda)
    "Fecha_pago": "20230315",                # Fecha de pago en formato YYYYMMDD (si corresponde)
    "Actividades": {"Actividad": [           # Actividades asociadas (según FEXGetPARAM_Actividades)
      {"Id": 1234}
    ]}
  }
}

try:
  # Ejecutamos la request al web service con el método FEXAuthorize
  result = genericWebService.executeRequest("FEXAuthorize", data)['FEXAuthorizeResult']

  # Si se retorna error, se extrae y se lanza la excepción
  if result.get("FEXErr") and result["FEXErr"].get("ErrCode", 0) != 0:
    err = result["FEXErr"]
    raise Exception("(%s) %s" % (err["ErrCode"], err["ErrMsg"]))

  # Mostramos el resultado obtenido (CAE, fechas, etc.)
  print(result)

except Exception as e:
  # En caso de error, se imprime la excepción
  print(e)
