.
This commit is contained in:
parent
a032383be3
commit
a8e4f76df2
@ -7,6 +7,7 @@ from app.utils import (
|
||||
create_invoice_header,
|
||||
insert_invoice_REST_API_FACTUGES,
|
||||
insert_item_and_taxes,
|
||||
validar_nif_verifacti,
|
||||
)
|
||||
|
||||
from . import normalizations as NORMALIZA
|
||||
@ -58,10 +59,15 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
cursorMySQL = None
|
||||
cursor_FactuGES = None
|
||||
factuges_id_anterior = None
|
||||
tin_anterior = None
|
||||
num_fac_procesed = 0
|
||||
customer_valid = True
|
||||
customer_valid = False
|
||||
invoice_id: str | None = None
|
||||
factura_payload: dict | None = None
|
||||
sync_result: str | None = None
|
||||
sync_notes: str | None = None
|
||||
sync_result_anterior: str | None = None
|
||||
sync_notes_anterior: str | None = None
|
||||
|
||||
try:
|
||||
cursorMySQL = conn_mysql.cursor()
|
||||
@ -79,27 +85,52 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
)
|
||||
|
||||
factuges_id = int(facturas["ID"])
|
||||
if factuges_id_anterior is None or factuges_id_anterior != factuges_id:
|
||||
# Validamos que el cif de la factura exista en la AEAT si no es así no se hace la sincro de la factura
|
||||
logger.info(">>>PASO")
|
||||
logger.info(str(factuges_id_anterior))
|
||||
logger.info(str(factuges_id))
|
||||
|
||||
# --- Si cambia la factura, primero persistimos la anterior
|
||||
if factuges_id_anterior is not None and factuges_id_anterior != factuges_id:
|
||||
if factura_payload is not None:
|
||||
logger.info(">>>> Se cambia de factura y vamos a insertar la anterior")
|
||||
|
||||
resultado_rest = insert_invoice_REST_API_FACTUGES(factura_payload)
|
||||
logger.info(resultado_rest)
|
||||
num_fac_procesed += 1
|
||||
|
||||
if not resultado_rest.get("ok"):
|
||||
logger.info(resultado_rest.get("error"))
|
||||
else:
|
||||
data = resultado_rest.get("data") or {}
|
||||
invoice_id = data.get("proforma_id")
|
||||
|
||||
logger.info("Updating FACTURAS_CLIENTE %s %s %s",
|
||||
sync_result_anterior, invoice_id, factuges_id_anterior,)
|
||||
cursor_FactuGES.execute(
|
||||
SQL.UPDATE_FACTUGES_LINK,
|
||||
(
|
||||
sync_result_anterior,
|
||||
invoice_id,
|
||||
sync_notes_anterior,
|
||||
factuges_id_anterior,
|
||||
),
|
||||
)
|
||||
|
||||
factura_payload = None
|
||||
|
||||
# --- Si no hay payload, estamos arrancando una nueva factura
|
||||
if factura_payload is None:
|
||||
sync_result = int(config["CTE_SYNC_RESULT_OK"])
|
||||
sync_notes = None
|
||||
customer_valid = True # validar_nif_verifacti(
|
||||
# customer_fields["tin"], customer_fields["name"], config
|
||||
# )
|
||||
|
||||
if customer_valid:
|
||||
# Validamos que el cif de la factura exista en la AEAT si no es así no se hace la sincro de la factura
|
||||
if tin_anterior is None or tin_anterior != customer_fields["tin"]:
|
||||
logger.info("VALIDO NIF>>>>>>>>>>>")
|
||||
customer_valid = validar_nif_verifacti(
|
||||
customer_fields["tin"], customer_fields["name"], config)
|
||||
tin_anterior = customer_fields["tin"]
|
||||
|
||||
# ---- cabecera factura
|
||||
factura_payload = create_invoice_header(
|
||||
customer_fields, header_invoice_fields, facturas["ID_FORMA_PAGO"], str(facturas["DES_FORMA_PAGO"]))
|
||||
# ---- detalles factura
|
||||
factura_payload["items"].append(insert_item_and_taxes(details_invoice_fields))
|
||||
logger.info(f"PAYLOAD {factura_payload}")
|
||||
# InsertamosREST
|
||||
Resultado_REST = insert_invoice_REST_API_FACTUGES(factura_payload)
|
||||
logger.info(Resultado_REST)
|
||||
|
||||
else:
|
||||
if not customer_valid:
|
||||
sync_result = int(config["CTE_SYNC_RESULT_FAIL"])
|
||||
sync_notes = (
|
||||
f">>> Factura {header_invoice_fields['reference']} no cumple requisitos para ser mandada a Verifactu: "
|
||||
@ -107,21 +138,50 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
f"El NIF/CIF debe estar registrado en la AEAT y el nombre debe ser suficientemente parecido al nombre registrado en la AEAT"
|
||||
)
|
||||
logger.info(sync_notes)
|
||||
cursor_FactuGES.execute(SQL.UPDATE_FACTUGES_LINK, (sync_result,
|
||||
invoice_id, sync_notes, factuges_id),)
|
||||
continue
|
||||
|
||||
num_fac_procesed += 1
|
||||
# ---- cabecera factura
|
||||
logger.info("Creo cabecera>>>>>>")
|
||||
factura_payload = create_invoice_header(
|
||||
customer_fields, header_invoice_fields, facturas["ID_FORMA_PAGO"], str(facturas["DES_FORMA_PAGO"]))
|
||||
|
||||
# Guardamos en Factuges el id de la customer_invoice
|
||||
logger.info(
|
||||
f"Updating FACTURAS_CLIENTE {sync_result} {invoice_id} {factuges_id} {sync_notes}: ")
|
||||
# cursor_FactuGES.execute(
|
||||
# SQL.UPDATE_FACTUGES_LINK,
|
||||
# (sync_result, invoice_id, sync_notes, factuges_id),
|
||||
# )
|
||||
# Guardamos el estado asociado al payload actual
|
||||
sync_result_anterior = sync_result
|
||||
sync_notes_anterior = sync_notes
|
||||
|
||||
# Asignamos el id factura anterior para no volver a inserta cabecera
|
||||
factuges_id_anterior = factuges_id
|
||||
# ---- detalles factura
|
||||
logger.info("Creo detalle>>>>")
|
||||
factura_payload["items"].append(insert_item_and_taxes(details_invoice_fields))
|
||||
# Asignamos el id factura anterior para no volver a inserta cabecera
|
||||
factuges_id_anterior = factuges_id
|
||||
|
||||
logger.info(f"FACTURAS_CLIENTE rows to be processed: {str(num_fac_procesed)}")
|
||||
# --- Insertar última factura pendiente
|
||||
if factura_payload is not None:
|
||||
logger.info(">>>> Última factura y vamos a insertar")
|
||||
|
||||
resultado_rest = insert_invoice_REST_API_FACTUGES(factura_payload)
|
||||
logger.info(resultado_rest)
|
||||
num_fac_procesed += 1
|
||||
|
||||
if not resultado_rest.get("ok"):
|
||||
logger.info(resultado_rest.get("error"))
|
||||
else:
|
||||
data = resultado_rest.get("data") or {}
|
||||
invoice_id = data.get("proforma_id")
|
||||
|
||||
cursor_FactuGES.execute(
|
||||
SQL.UPDATE_FACTUGES_LINK,
|
||||
(
|
||||
sync_result_anterior,
|
||||
invoice_id,
|
||||
sync_notes_anterior,
|
||||
factuges_id_anterior,
|
||||
),
|
||||
)
|
||||
|
||||
logger.info("FACTURAS_CLIENTE rows to be processed: %s", num_fac_procesed)
|
||||
|
||||
except Exception as e:
|
||||
# Escribir el error en el archivo de errores
|
||||
@ -136,6 +196,57 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
cursor_FactuGES.close()
|
||||
|
||||
|
||||
'''
|
||||
if factuges_id_anterior is not None and factuges_id_anterior != factuges_id:
|
||||
logger.info(">>>>Se cambia de factura y vamos a insertar")
|
||||
# InsertamosREST
|
||||
Resultado_REST = insert_invoice_REST_API_FACTUGES(factura_payload)
|
||||
logger.info(Resultado_REST)
|
||||
num_fac_procesed += 1
|
||||
|
||||
if not Resultado_REST.get("ok"):
|
||||
# Solo informamos en logger porque al cliente final este error no le interesa saldría la causa en notes de FactuGES antiguo
|
||||
logger.info(Resultado_REST.get("error"))
|
||||
else:
|
||||
logger.info(Resultado_REST)
|
||||
data = Resultado_REST.get("data")
|
||||
invoice_id = data.get("proforma_id")
|
||||
# Guardamos en Factuges el id de la customer_invoice
|
||||
logger.info(
|
||||
f"Updating FACTURAS_CLIENTE {sync_result} {invoice_id} {factuges_id} {sync_notes}: ")
|
||||
cursor_FactuGES.execute(SQL.UPDATE_FACTUGES_LINK, (sync_result,
|
||||
invoice_id, sync_notes, factuges_id),)
|
||||
|
||||
# Quitamos payload de la factura insertada
|
||||
factura_payload = None
|
||||
|
||||
|
||||
|
||||
if factura_payload is not None:
|
||||
logger.info(">>>>Ultima factura y vamos a insertar")
|
||||
# InsertamosREST
|
||||
Resultado_REST = insert_invoice_REST_API_FACTUGES(factura_payload)
|
||||
logger.info(Resultado_REST)
|
||||
num_fac_procesed += 1
|
||||
|
||||
if not Resultado_REST.get("ok"):
|
||||
# Solo informamos en logger porque al cliente final este error no le interesa saldría la causa en notes de FactuGES antiguo
|
||||
logger.info(Resultado_REST.get("error"))
|
||||
else:
|
||||
logger.info(Resultado_REST)
|
||||
data = Resultado_REST.get("data")
|
||||
invoice_id = data.get("proforma_id")
|
||||
# Guardamos en Factuges el id de la customer_invoice
|
||||
logger.info(
|
||||
f"Updating FACTURAS_CLIENTE {sync_result} {invoice_id} {factuges_id} {sync_notes}: ")
|
||||
cursor_FactuGES.execute(SQL.UPDATE_FACTUGES_LINK, (sync_result,
|
||||
invoice_id, sync_notes, factuges_id),)
|
||||
|
||||
logger.info(f"FACTURAS_CLIENTE rows to be processed: {str(num_fac_procesed)}")
|
||||
factura_payload = None
|
||||
'''
|
||||
|
||||
|
||||
def insert_verifactu_record(
|
||||
cur: str, hif: Dict[str, Any], invoice_id: str, config) -> str:
|
||||
"""
|
||||
|
||||
@ -15,7 +15,7 @@ def create_invoice_header(
|
||||
) -> Dict[str, Any]:
|
||||
return {
|
||||
"id": str(uuid7()),
|
||||
"factuges_id": hif.get("factuges_id"),
|
||||
"factuges_id": str(hif.get("factuges_id")),
|
||||
"company_id": hif.get("company_id"),
|
||||
"is_proforma": hif.get("is_proforma"),
|
||||
"status": hif.get("status"),
|
||||
@ -27,13 +27,13 @@ def create_invoice_header(
|
||||
"notes": none_to_empty(hif.get("notes")),
|
||||
"language_code": cf.get("language_code"),
|
||||
|
||||
"subtotal_amount_value": none_to_empty(hif.get("subtotal_amount_value")),
|
||||
"global_discount_percentage": none_to_empty(hif.get("discount_percentage_val")),
|
||||
"discount_amount_value": none_to_empty(hif.get("discount_amount_value")),
|
||||
"taxable_amount_value": hif.get("taxable_amount_value"),
|
||||
"taxes_amount_value": hif.get("taxes_amount_value"),
|
||||
"total_amount_value": hif.get("total_amount_value"),
|
||||
"payment_method_id": payment_method_id,
|
||||
"subtotal_amount_value": str(none_to_empty(hif.get("subtotal_amount_value"))),
|
||||
"global_discount_percentage": str(none_to_empty(hif.get("discount_percentage_val"))),
|
||||
"discount_amount_value": str(none_to_empty(hif.get("discount_amount_value"))),
|
||||
"taxable_amount_value": str(hif.get("taxable_amount_value")),
|
||||
"taxes_amount_value": str(hif.get("taxes_amount_value")),
|
||||
"total_amount_value": str(hif.get("total_amount_value")),
|
||||
"payment_method_id": str(payment_method_id),
|
||||
"payment_method_description": payment_method_description,
|
||||
|
||||
"customer": {
|
||||
@ -52,7 +52,7 @@ def create_invoice_header(
|
||||
"mobile_secondary": none_to_empty(cf["mobile_secondary"]),
|
||||
"email_primary": none_to_empty(cf["email_primary"]),
|
||||
"email_secondary": none_to_empty(cf["email_secondary"]),
|
||||
"website": cf["website"],
|
||||
"website": str(none_to_empty(cf["website"])),
|
||||
},
|
||||
|
||||
"items": [],
|
||||
@ -65,24 +65,24 @@ def insert_item_and_taxes(fields) -> Dict[str, Any]:
|
||||
return {
|
||||
"item_id": str(uuid7()),
|
||||
"position": str(fields.get("position")),
|
||||
"description": fields.get("description"),
|
||||
"quantity_value": str(fields.get("quantity_value")),
|
||||
"unit_value": str(fields.get("unit_value")),
|
||||
"subtotal_amount_value": fields.get("subtotal_amount_value"),
|
||||
"item_discount_percentage_value": none_to_empty(fields.get("item_discount_percentage_value")),
|
||||
"item_discount_amount_value": none_to_empty(fields.get("item_discount_amount_value")),
|
||||
"global_discount_percentage_value": none_to_empty(fields.get("global_discount_percentage_value")),
|
||||
"global_discount_amount_value": none_to_empty(fields.get("global_discount_amount_value")),
|
||||
"total_discount_amount_value": fields.get("total_discount_amount_value"),
|
||||
"taxable_amount_value": fields.get("taxable_amount_value"),
|
||||
"total_value": fields.get("total_value"),
|
||||
"iva_code": fields.get("iva_code"),
|
||||
"iva_percentage_value": str(fields.get("iva_percentage_value")),
|
||||
"iva_amount_value": fields.get("iva_amount_value"),
|
||||
"rec_code": none_to_empty(fields.get("rec_code")),
|
||||
"rec_percentage_value": none_to_empty(fields.get("rec_percentage_value")),
|
||||
"rec_amount_value": fields.get("rec_amount_value"),
|
||||
"taxes_amount_value": fields.get("taxes_amount_value"),
|
||||
"description": str(none_to_empty(fields.get("description"))),
|
||||
"quantity_value": str(none_to_empty(fields.get("quantity_value"))),
|
||||
"unit_value": str(none_to_empty(fields.get("unit_value"))),
|
||||
"subtotal_amount_value": str(fields.get("subtotal_amount_value")),
|
||||
"item_discount_percentage_value": str(none_to_empty(fields.get("item_discount_percentage_value"))),
|
||||
"item_discount_amount_value": str(none_to_empty(fields.get("item_discount_amount_value"))),
|
||||
"global_discount_percentage_value": str(none_to_empty(fields.get("global_discount_percentage_value"))),
|
||||
"global_discount_amount_value": str(none_to_empty(fields.get("global_discount_amount_value"))),
|
||||
"total_discount_amount_value": str(fields.get("total_discount_amount_value")),
|
||||
"taxable_amount_value": str(fields.get("taxable_amount_value")),
|
||||
"total_value": str(fields.get("total_value")),
|
||||
"iva_code": str(fields.get("iva_code")),
|
||||
"iva_percentage_value": str(str(fields.get("iva_percentage_value"))),
|
||||
"iva_amount_value": str(fields.get("iva_amount_value")),
|
||||
"rec_code": str(none_to_empty(fields.get("rec_code"))),
|
||||
"rec_percentage_value": str(none_to_empty(fields.get("rec_percentage_value"))),
|
||||
"rec_amount_value": str(fields.get("rec_amount_value")),
|
||||
"taxes_amount_value": str(fields.get("taxes_amount_value")),
|
||||
}
|
||||
|
||||
# logger.info("Inserting item tax %s code=%s base=%s tax=%s",
|
||||
|
||||
@ -4,6 +4,9 @@ import requests
|
||||
|
||||
from app.config import logger
|
||||
|
||||
SUCCESS_CODES = {200, 201}
|
||||
VALIDATION_ERROR_CODES = {400, 422}
|
||||
|
||||
|
||||
def estado_factura(uuid_str: str,
|
||||
config,
|
||||
@ -142,13 +145,11 @@ def validar_nif_verifacti(
|
||||
resp = requests.post(
|
||||
url, json=payload, headers=headers, timeout=timeout)
|
||||
if resp.status_code != 200:
|
||||
logger.info("ERRRRRROOOOOOORRRRR LLAMADA REST API")
|
||||
# return False, None, f"HTTP {resp.status_code}: {resp.text}"
|
||||
return False, None, f"HTTP {resp.status_code}: {resp.text}"
|
||||
|
||||
data = resp.json()
|
||||
resultado = data.get("resultado", "NO IDENTIFICADO")
|
||||
logger.info(f"Resultado Verifacti: {resultado}")
|
||||
|
||||
return resultado == "IDENTIFICADO"
|
||||
|
||||
except requests.RequestException as e:
|
||||
@ -177,26 +178,30 @@ def insert_invoice_REST_API_FACTUGES(
|
||||
"nombre": nombre,
|
||||
}
|
||||
"""
|
||||
logger.info("-----------------------------------------------------------------------------")
|
||||
logger.info(payload)
|
||||
logger.info("-----------------------------------------------------------------------------")
|
||||
|
||||
try:
|
||||
resp = requests.post(
|
||||
url, json=payload, headers=headers, timeout=timeout)
|
||||
|
||||
if resp.status_code == 200:
|
||||
if resp.status_code in SUCCESS_CODES:
|
||||
location = resp.headers.get("Location")
|
||||
try:
|
||||
data = resp.json()
|
||||
logger.info(data)
|
||||
except ValueError:
|
||||
return {"ok": False, "status": 200, "error": "Respuesta 200 sin JSON válido", "raw": resp.text}
|
||||
return {"ok": True, "status": 200, "data": data}
|
||||
data = None
|
||||
return {"ok": True, "status": resp.status_code, "data": data, "location": location}
|
||||
|
||||
if resp.status_code == 400:
|
||||
if resp.status_code in VALIDATION_ERROR_CODES:
|
||||
try:
|
||||
body = resp.json()
|
||||
msg = body.get(
|
||||
"error") or "Error de validación (400) sin detalle"
|
||||
msg = (body.get("title") + str(body.get("errors"))
|
||||
or f"Error de validación ({resp.status_code}) sin detalle")
|
||||
except ValueError:
|
||||
msg = f"Error de validación (400): {resp.text}"
|
||||
return {"ok": False, "status": 400, "error": msg}
|
||||
return {"ok": False, "status": resp.status_code, "error": msg}
|
||||
|
||||
# Otros códigos: devuelve mensaje genérico, intenta extraer JSON si existe
|
||||
try:
|
||||
@ -207,7 +212,7 @@ def insert_invoice_REST_API_FACTUGES(
|
||||
return {"ok": False, "status": resp.status_code, "error": f"HTTP {resp.status_code}", "raw": resp.text}
|
||||
|
||||
except requests.RequestException as e:
|
||||
logger.error("Error de conexión con la API Verifacti: %s", e)
|
||||
logger.error("Error de conexión con la API Factuges: %s", e)
|
||||
return {"ok": False, "status": 500, "error": str(e)}
|
||||
except ValueError as e:
|
||||
logger.error("Respuesta no es JSON válido: %s", e)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user