This commit is contained in:
David Arranz 2026-03-17 11:33:37 +01:00
parent 666c36e6f6
commit 9fefcd93ca
6 changed files with 85 additions and 13 deletions

View File

@ -47,6 +47,7 @@ def normalize_customer_fields(fd: Dict[str, Any]) -> Dict[str, Any]:
"is_company": config["CTE_IS_COMPANY"],
"tin": clean_tin(str(fd.get("NIF_CIF"))),
"name": str(fd.get("NOMBRE")),
"street": str(fd.get("CALLE")),
"city": str(fd.get("POBLACION")),
"province": str(fd.get("PROVINCIA")),
@ -96,6 +97,9 @@ def normalize_header_invoice_fields(fd: Dict[str, Any]) -> Dict[str, Any]:
"company_id": config['CTE_COMPANY_ID'],
"is_proforma": config["CTE_IS_PROFORMA"],
"status": config["CTE_STATUS_INVOICE"],
#
"series": config['CTE_SERIE'],
"factuges_id": int(fd['ID_FACTURA']),

View File

@ -128,7 +128,7 @@ SELECT_FACTUGES_FACTURAS_CLIENTE = (
"WHERE "
"(fac.VERIFACTU = 1) "
"AND (fac.ID_VERIFACTU is null)"
"ORDER BY (fac.ID)"
"ORDER BY (fac.ID, facdet.POSICION)"
)
UPDATE_FACTUGES_LINK = (

View File

@ -3,7 +3,9 @@ from typing import Any, Dict
from uuid6 import uuid7
from app.config import load_config, logger
from app.utils import validar_nif
from app.utils import (
validar_nif_verifacti,
)
from . import normalizations as NORMALIZA
from . import sql_sentences as SQL
@ -130,7 +132,7 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
# Validamos que el cif de la factura exista en la AEAT si no es así no se hace la sincro de la factura
sync_result = int(config["CTE_SYNC_RESULT_OK"])
sync_notes = None
customer_valid = validar_nif(
customer_valid = validar_nif_verifacti(
customer_fields["tin"], customer_fields["name"], config
)
if customer_valid:
@ -141,7 +143,6 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
str(factura_detalle["ID_CLIENTE"]),
customer_fields,
)
# ---- forma de pago
pm_id = get_or_create_payment_method(
cursorMySQL,
@ -161,14 +162,12 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
str(factura_detalle["DES_FORMA_PAGO"]),
config,
)
# ---- impuestos cabecera
insert_header_taxes_if_any(
cursorMySQL,
invoice_id,
header_invoice_fields,
)
# ---- registro verifactu
insert_verifactu_record(
cursorMySQL, header_invoice_fields, invoice_id, config

View File

@ -1,7 +1,12 @@
from typing import Any, Dict, Iterable, List, Optional, Tuple
from app.config import load_config, logger
from app.utils import TaxCatalog, crear_factura, estado_factura, unscale_to_str
from app.utils import (
TaxCatalog,
crear_factura_verifacti,
estado_factura,
unscale_to_str,
)
from . import sql_sentences as SQL
@ -115,7 +120,7 @@ def procesar_factura_verifactu(
# Creamos registro de factura en verifactu
if factura.get('uuid') == '':
# logger.info(f"Send to create Verifactu: {factura}")
respuesta = crear_factura(factura, config)
respuesta = crear_factura_verifacti(factura, config)
if respuesta.get("status") == 200 and respuesta.get("ok"):
data = respuesta.get("data") or {}

View File

@ -12,8 +12,17 @@ from .last_execution_helper import (
)
from .mails_helper import corregir_y_validar_email
from .password import hashPassword
from .payloads_factuges import (
create_invoice_header,
insert_item_and_taxes,
)
from .send_orders_mail import send_orders_mail
from .send_rest_api import crear_factura, estado_factura, validar_nif
from .send_rest_api import (
crear_factura_verifacti,
estado_factura,
insert_invoice_REST_API_FACTUGES,
validar_nif_verifacti,
)
from .tax_catalog_helper import (
TaxCatalog,
calc_item_tax_amount,

View File

@ -60,9 +60,9 @@ def estado_factura(uuid_str: str,
return {"ok": False, "status": 500, "error": "Respuesta no es JSON válido"}
def crear_factura(payload,
config,
) -> Dict[str, Any]:
def crear_factura_verifacti(payload,
config,
) -> Dict[str, Any]:
"""
Llama al endpoint de Verifacti para crear una factura.
@ -115,7 +115,7 @@ def crear_factura(payload,
return {"ok": False, "status": 500, "error": "Respuesta no es JSON válido"}
def validar_nif(
def validar_nif_verifacti(
nif: str,
nombre: str,
config,
@ -157,3 +157,58 @@ def validar_nif(
except ValueError as e:
logger.error("Respuesta no es JSON válido: %s", e)
return False, None, "Respuesta no es JSON válido"
def insert_invoice_REST_API_FACTUGES(
payload
) -> Dict[str, Any]:
"""
Llama a la REST API de FACTUGES para insertar una proforma aprobada.
Retorna:
"""
url = "http://192.168.0.104:3002/api/v1/proformas"
timeout: int = 10
headers = {"Content-Type": "application/json",
"Accept": "application/json"}
"""headers["Authorization"] = "Bearer " + config['VERIFACTU_NIFS_API_KEY']
payload = {"nif": nif,
"nombre": nombre,
}
"""
try:
resp = requests.post(
url, json=payload, headers=headers, timeout=timeout)
if resp.status_code == 200:
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}
if resp.status_code == 400:
try:
body = resp.json()
msg = body.get(
"error") or "Error de validación (400) sin detalle"
except ValueError:
msg = f"Error de validación (400): {resp.text}"
return {"ok": False, "status": 400, "error": msg}
# Otros códigos: devuelve mensaje genérico, intenta extraer JSON si existe
try:
body = resp.json()
msg = body.get("error") or body
return {"ok": False, "status": resp.status_code, "error": str(msg)}
except ValueError:
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)
return {"ok": False, "status": 500, "error": str(e)}
except ValueError as e:
logger.error("Respuesta no es JSON válido: %s", e)
return {"ok": False, "status": 500, "error": "Respuesta no es JSON válido"}