.
This commit is contained in:
parent
a951be5b87
commit
634d04dc10
26
.env
26
.env
@ -1,5 +1,6 @@
|
||||
ENVIRONMENT = development
|
||||
LOCAL_TZ = Europe/Madrid
|
||||
LAST_RUN_PATH = ./app.last_run.txt
|
||||
#LOG_PATH = ./app.log
|
||||
|
||||
#DESARROLLO ACANA
|
||||
@ -9,20 +10,6 @@ FACTUGES_DATABASE = C:\Codigo Acana\Output\Debug\Database\FACTUGES.FDB
|
||||
FACTUGES_USER = sysdba
|
||||
FACTUGES_PASSWORD = masterkey
|
||||
|
||||
# PRODUCCION RODAX FACTUGES FIREBIRD
|
||||
#FACTUGES_HOST = 192.168.0.101
|
||||
#FACTUGES_PORT = 3050
|
||||
#FACTUGES_DATABASE = C:\FactuGES\FACTUGES.FDB
|
||||
#FACTUGES_USER = sysdba
|
||||
#FACTUGES_PASSWORD = masterkey
|
||||
|
||||
# PRODUCCION RODAX MYSQL
|
||||
#UECKO_MYSQL_HOST = 192.168.0.250
|
||||
#UECKO_MYSQL_PORT = 3306
|
||||
#UECKO_MYSQL_DATABASE = rodax_db
|
||||
#UECKO_MYSQL_USER = rodax_usr
|
||||
#UECKO_MYSQL_PASSWORD = supersecret
|
||||
|
||||
#DESARROLLO
|
||||
UECKO_MYSQL_HOST = localhost
|
||||
UECKO_MYSQL_PORT = 3306
|
||||
@ -35,24 +22,15 @@ CTE_COMPANY_ID = '019a9667-6a65-767a-a737-48234ee50a3a'
|
||||
CTE_SERIE = 'F25/'
|
||||
CTE_STATUS_INVOICE = 'issued'
|
||||
CTE_IS_PROFORMA = 0
|
||||
CTE_STATUS_VERIFACTU = 'pendiente'
|
||||
CTE_STATUS_VERIFACTU = 'Pendiente'
|
||||
CTE_LANGUAGE_CODE = 'es' #En uecko vendrá de su ficha
|
||||
CTE_COUNTRY_CODE = 'es' #En uecko vendrá de su ficha
|
||||
CTE_IS_COMPANY = 1
|
||||
|
||||
#CONFIGURACION RODAX
|
||||
#CTE_COMPANY_ID = '5e4dc5b3-96b9-4968-9490-14bd032fec5f'
|
||||
#CTE_SERIE = 'F25/'
|
||||
#CTE_STATUS_INVOICE = 'approved'
|
||||
#CTE_IS_PROFORMA = 1
|
||||
#CTE_STATUS_VERIFACTU = 'Pendiente'
|
||||
|
||||
|
||||
VERIFACTU_BASE_URL = https://api.verifacti.com/
|
||||
VERIFACTU_API_KEY = vf_test_ei8WYAvEq5dhSdEyQVjgCS8NZaNpEK2BljSHSUXf+Y0=
|
||||
VERIFACTU_NIFS_API_KEY = vfn_osYpNdqSzAdTAHpazXG2anz4F3o0gfbSb5FFrCBZcno=
|
||||
|
||||
|
||||
#BREVO_API_KEY = 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
|
||||
#BREVO_EMAIL_TEMPLATE = 1
|
||||
#MAIL_FROM = 'no-reply@presupuestos.uecko.com'
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
ENVIRONMENT = production
|
||||
LOCAL_TZ = Europe/Madrid
|
||||
#LOG_PATH = /var/log/uecko_sync_app/uecko_sync_app.log
|
||||
|
||||
FACTUGES_HOST = 83.48.36.692
|
||||
FACTUGES_PORT = 3050
|
||||
FACTUGES_DATABASE = D:\RODAX\FACTUGES\BD\FACTUGES_FABRICA.FDB
|
||||
FACTUGES_USER = sysdba
|
||||
FACTUGES_PASSWORD = abeto2010
|
||||
|
||||
# DESARROLLO ALISO FACTUGES FIREBIRD
|
||||
#FACTUGES_HOST = 192.168.0.105
|
||||
#FACTUGES_PORT = 3050
|
||||
#FACTUGES_DATABASE = C:\Codigo Acana\Output\Debug\Database\FACTUGES.FDB
|
||||
#FACTUGES_USER = sysdba
|
||||
#FACTUGES_PASSWORD = masterkey
|
||||
|
||||
# PRODUCCION RODAX FACTUGES FIREBIRD
|
||||
#FACTUGES_HOST = 192.168.0.101
|
||||
#FACTUGES_PORT = 3050
|
||||
#FACTUGES_DATABASE = C:\FactuGES\FACTUGES.FDB
|
||||
#FACTUGES_USER = sysdba
|
||||
#FACTUGES_PASSWORD = masterkey
|
||||
|
||||
# PRODUCCION RODAX MYSQL
|
||||
#UECKO_MYSQL_HOST = 192.168.0.250
|
||||
#UECKO_MYSQL_PORT = 3306
|
||||
#UECKO_MYSQL_DATABASE = rodax_db
|
||||
#UECKO_MYSQL_USER = rodax_usr
|
||||
#UECKO_MYSQL_PASSWORD = supersecret
|
||||
|
||||
UECKO_MYSQL_HOST = mariadb2
|
||||
UECKO_MYSQL_PORT = 3306
|
||||
UECKO_MYSQL_DATABASE = uecko
|
||||
UECKO_MYSQL_USER = uecko
|
||||
UECKO_MYSQL_PASSWORD = u8Ax5Nw3%sjd
|
||||
|
||||
|
||||
BREVO_API_KEY = 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
|
||||
BREVO_EMAIL_TEMPLATE = 1
|
||||
MAIL_FROM = 'no-reply@presupuestos.uecko.com'
|
||||
MAIL_TO = 'pedidos@uecko.com'
|
||||
|
||||
VERIFACTU_BASE_URL = https://api.verifacti.com/
|
||||
VERIFACTU_API_KEY = vf_test_kY9FoI86dH+g1a5hmEnb/0YcLTlMFlu+tpp9iMZp020=
|
||||
VERIFACTU_NIFS_API_KEY = vfn_osYpNdqSzAdTAHpazXG2anz4F3o0gfbSb5FFrCBZcno=
|
||||
|
||||
#VERIFACTU_RODAX_TEST_API_KEY = vf_test_C03HL2F0X5OXSDRunjNFoMxD4IrRfK3kCC8PfcvCENI=
|
||||
#VERIFACTU_RODAX_PROD_API_KEY = vf_prod_yfjonNPv2E4Fij+5J0hct0zCgUeFYT2dZzb23UZlM+Q=
|
||||
|
||||
#VERIFACTU_ALISO_TEST_API_KEY = vf_test_ei8WYAvEq5dhSdEyQVjgCS8NZaNpEK2BljSHSUXf+Y0=
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
33
.env.production.sync.factuges
Normal file
33
.env.production.sync.factuges
Normal file
@ -0,0 +1,33 @@
|
||||
ENVIRONMENT = development
|
||||
LOCAL_TZ = Europe/Madrid
|
||||
LAST_RUN_PATH = ./app.last_run.txt
|
||||
#LOG_PATH = ./app.log
|
||||
|
||||
#DESARROLLO ACANA
|
||||
FACTUGES_HOST = 192.168.0.105
|
||||
FACTUGES_PORT = 3050
|
||||
FACTUGES_DATABASE = C:\Codigo Acana\Output\Debug\Database\FACTUGES.FDB
|
||||
FACTUGES_USER = sysdba
|
||||
FACTUGES_PASSWORD = masterkey
|
||||
|
||||
#DESARROLLO
|
||||
UECKO_MYSQL_HOST = localhost
|
||||
UECKO_MYSQL_PORT = 3306
|
||||
UECKO_MYSQL_DATABASE = uecko_erp_sync
|
||||
UECKO_MYSQL_USER = rodax
|
||||
UECKO_MYSQL_PASSWORD = rodax
|
||||
|
||||
#CONFIGURACION ACANA
|
||||
CTE_COMPANY_ID = '019a9667-6a65-767a-a737-48234ee50a3a'
|
||||
CTE_SERIE = 'F25/'
|
||||
CTE_STATUS_INVOICE = 'issued'
|
||||
CTE_IS_PROFORMA = 0
|
||||
CTE_STATUS_VERIFACTU = 'Pendiente'
|
||||
CTE_LANGUAGE_CODE = 'es' #En uecko vendrá de su ficha
|
||||
CTE_COUNTRY_CODE = 'es' #En uecko vendrá de su ficha
|
||||
CTE_IS_COMPANY = 1
|
||||
|
||||
#BREVO_API_KEY = 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
|
||||
#BREVO_EMAIL_TEMPLATE = 1
|
||||
#MAIL_FROM = 'no-reply@presupuestos.uecko.com'
|
||||
#MAIL_TO = 'soporte@rodax-software.com'
|
||||
21
.env_V
Normal file
21
.env_V
Normal file
@ -0,0 +1,21 @@
|
||||
ENVIRONMENT = development
|
||||
LOCAL_TZ = Europe/Madrid
|
||||
LAST_RUN_PATH = ./app.last_run.txt
|
||||
#LOG_PATH = ./app.log
|
||||
|
||||
#DESARROLLO
|
||||
UECKO_MYSQL_HOST = localhost
|
||||
UECKO_MYSQL_PORT = 3306
|
||||
UECKO_MYSQL_DATABASE = uecko_erp_sync
|
||||
UECKO_MYSQL_USER = rodax
|
||||
UECKO_MYSQL_PASSWORD = rodax
|
||||
|
||||
VERIFACTU_BASE_URL = https://api.verifacti.com/
|
||||
VERIFACTU_API_KEY = vf_test_ei8WYAvEq5dhSdEyQVjgCS8NZaNpEK2BljSHSUXf+Y0=
|
||||
VERIFACTU_NIFS_API_KEY = vfn_osYpNdqSzAdTAHpazXG2anz4F3o0gfbSb5FFrCBZcno=
|
||||
|
||||
|
||||
#BREVO_API_KEY = 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
|
||||
#BREVO_EMAIL_TEMPLATE = 1
|
||||
#MAIL_FROM = 'no-reply@presupuestos.uecko.com'
|
||||
#MAIL_TO = 'soporte@rodax-software.com'
|
||||
1
app.last_run.txt
Normal file
1
app.last_run.txt
Normal file
@ -0,0 +1 @@
|
||||
2025-11-27 18:58:46
|
||||
1
app/__version_sync_verifactu__.py
Normal file
1
app/__version_sync_verifactu__.py
Normal file
@ -0,0 +1 @@
|
||||
__version__ = "1.0.0"
|
||||
@ -10,6 +10,7 @@ def load_config():
|
||||
return {
|
||||
'ENVIRONMENT': os.getenv('ENVIRONMENT'),
|
||||
'LOCAL_TZ': os.getenv('LOCAL_TZ', 'Europe/Madrid'),
|
||||
'LAST_RUN_PATH': os.getenv('LAST_RUN_PATH'),
|
||||
# 'LOG_PATH': os.getenv('LOG_PATH', 'app.log'),
|
||||
|
||||
'FACTUGES_HOST': os.getenv('FACTUGES_HOST'),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from .db_connection import get_factuges_connection
|
||||
from .db_connection import get_mysql_connection
|
||||
from .sync_invoices import sync_invoices
|
||||
from .sync_invoices_factuges import sync_invoices_factuges
|
||||
from .sync_invoices_verifactu import sync_invoices_verifactu
|
||||
|
||||
@ -121,14 +121,16 @@ SELECT_FACTUGES_FACTURAS_CLIENTE = (
|
||||
f"LEFT JOIN TIPOS_IVA AS ti ON fac.ID_TIPO_IVA = ti.ID "
|
||||
f"LEFT JOIN FACTURAS_CLIENTE_DETALLES as facdet ON fac.ID = facdet.ID_FACTURA "
|
||||
f"WHERE "
|
||||
f"(fac.VERIFACTU > 0) "
|
||||
f"(fac.VERIFACTU = 1) "
|
||||
f"AND (fac.ID_VERIFACTU is null)"
|
||||
f"ORDER BY (fac.ID)"
|
||||
)
|
||||
|
||||
UPDATE_FACTUGES_LINK = (
|
||||
"UPDATE FACTURAS_CLIENTE "
|
||||
"SET ID_VERIFACTU=? "
|
||||
"SET VERIFACTU=?, "
|
||||
"ID_VERIFACTU=?, "
|
||||
"VERIFACTU_NOTES =? "
|
||||
"WHERE ID=?"
|
||||
)
|
||||
|
||||
|
||||
@ -4,9 +4,10 @@ from uuid6 import uuid7
|
||||
from config import load_config
|
||||
from . import sql_sentences as SQL
|
||||
from . import normalizations as NORMALIZA
|
||||
from utils import validar_nif
|
||||
|
||||
|
||||
def sync_invoices(conn_factuges, conn_mysql, last_execution_date):
|
||||
def sync_invoices_factuges(conn_factuges, conn_mysql, last_execution_date):
|
||||
config = load_config()
|
||||
|
||||
# LIMPIAMOS LAS FACTURAS DE FACTUGES QUE HAYAN SIDO ELIMINADAS DEL PROGRAMA NUEVO DE FACTURACION, PARA QUE PUEDAN SER MODIFICADAS
|
||||
@ -67,7 +68,7 @@ def sync_invoices(conn_factuges, conn_mysql, last_execution_date):
|
||||
conn_mysql, tuplas_seleccionadas, conn_factuges, config)
|
||||
else:
|
||||
logging.info(
|
||||
"There are no new FACTURAS rows since the last run.")
|
||||
"There are NOT new FACTURAS rows since the last run.")
|
||||
|
||||
|
||||
def sync_delete_invoices(conn_factuges, ids_verifactu_deleted, config):
|
||||
@ -101,6 +102,8 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
cursor_FactuGES = None
|
||||
factuges_id_anterior = None
|
||||
num_fac_procesed = 0
|
||||
customer_valid = True
|
||||
invoice_id = None
|
||||
|
||||
try:
|
||||
cursorMySQL = conn_mysql.cursor()
|
||||
@ -120,6 +123,10 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
factuges_id = int(factura_detalle['ID_FACTURA'])
|
||||
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
|
||||
sync_result = 1
|
||||
customer_valid = validar_nif(customer_fields["tin"], customer_fields["name"], config)
|
||||
if customer_valid:
|
||||
# Comprobamos si existe el cliente del primer item de la factura
|
||||
customer_id = get_or_create_customer(
|
||||
cursorMySQL,
|
||||
@ -150,17 +157,22 @@ def sync_invoices_from_FACTUGES(conn_mysql, filas, conn_factuges, config):
|
||||
insert_verifactu_record(
|
||||
cursorMySQL, header_invoice_fields, invoice_id, config)
|
||||
|
||||
else:
|
||||
sync_result = 2
|
||||
cadena = (f">>> Factura {header_invoice_fields['reference']} no cumple requisitos para ser mandada a Verifactu: "
|
||||
f">>>>>> El NIF/NOMBRE ({customer_fields['tin']}/{customer_fields['name']}) no está registrado en la AEAT. "
|
||||
f"El NIF/CIF debe estar registrado en la AEAT y el nombre debe ser suficientemente parecido al nombre registrado en la AEAT")
|
||||
logging.info(cadena)
|
||||
|
||||
# Guardamos en Factuges el id de la customer_invoice
|
||||
logging.info(
|
||||
f"Updating FACTURAS_CLIENTE {invoice_id} {factuges_id}")
|
||||
cursor_FactuGES.execute(
|
||||
SQL.UPDATE_FACTUGES_LINK, (invoice_id, factuges_id))
|
||||
f"Updating FACTURAS_CLIENTE {sync_result} {invoice_id} {factuges_id} {cadena}")
|
||||
cursor_FactuGES.execute(SQL.UPDATE_FACTUGES_LINK, (sync_result, invoice_id, cadena, factuges_id))
|
||||
num_fac_procesed += 1
|
||||
|
||||
# Insertamos detalles y taxes correspondientes siempre
|
||||
# Siempre insertamos la línea
|
||||
insert_item_and_taxes(cursorMySQL, invoice_id,
|
||||
details_invoice_fields)
|
||||
# Insertamos detalles y taxes correspondientes siempre que hayamos insertado cabecera
|
||||
if customer_valid:
|
||||
insert_item_and_taxes(cursorMySQL, invoice_id, details_invoice_fields)
|
||||
|
||||
# Asignamos el id factura anterior para no volver a inserta cabecera
|
||||
factuges_id_anterior = factuges_id
|
||||
@ -240,7 +252,7 @@ def insert_invoice_header(cur: str, cf: Dict[str, Any], hif: Dict[str, Any], cus
|
||||
"""
|
||||
invoice_id = str(uuid7())
|
||||
|
||||
logging.info("Inserting invoice %s %s %s %s",
|
||||
logging.info("Inserting invoice %s %s %s %s %s",
|
||||
invoice_id, hif.get('reference'), hif.get('invoice_date'), hif.get('operation_date'), config['CTE_STATUS_INVOICE'])
|
||||
cur.execute(
|
||||
SQL.INSERT_INVOICE,
|
||||
@ -298,8 +310,7 @@ def insert_item_and_taxes(cur, invoice_id: str, fields: Dict[str, Any]) -> None:
|
||||
"""
|
||||
item_id = str(uuid7())
|
||||
|
||||
logging.info("Inserting item %s pos=%s qty=%s",
|
||||
item_id, fields.get('position'), fields.get('quantity_value'))
|
||||
# logging.info("Inserting item %s pos=%s qty=%s", item_id, fields.get('position'), fields.get('quantity_value'))
|
||||
cur.execute(
|
||||
SQL.INSERT_INVOICE_ITEM,
|
||||
(item_id, invoice_id, fields.get('position'), fields.get('description'), fields.get('quantity_value'),
|
||||
@ -1,12 +1,12 @@
|
||||
import sys
|
||||
import logging
|
||||
import __version__
|
||||
|
||||
from __version_sync_factuges__ import __version__
|
||||
from datetime import datetime
|
||||
from dateutil import tz
|
||||
from config import setup_logging, load_config
|
||||
from db import get_mysql_connection, get_factuges_connection, sync_invoices, sync_invoices_verifactu
|
||||
from utils import obtener_fecha_ultima_ejecucion, actualizar_fecha_ultima_ejecucion, log_system_metrics, send_orders_mail, limpiar_cadena
|
||||
from db import get_mysql_connection, get_factuges_connection, sync_invoices_factuges
|
||||
from utils import obtener_fecha_ultima_ejecucion, actualizar_fecha_ultima_ejecucion, log_system_metrics, send_orders_mail
|
||||
|
||||
|
||||
def main():
|
||||
@ -19,8 +19,8 @@ def main():
|
||||
# Logging
|
||||
setup_logging()
|
||||
|
||||
logging.info("== START ==")
|
||||
logging.info(f"Version: {__version__.__version__}")
|
||||
logging.info("== START SYNC FACTUGES ==")
|
||||
logging.info(f"Version: {__version__}")
|
||||
logging.info(f"Environment: {config['ENVIRONMENT']}")
|
||||
log_system_metrics()
|
||||
|
||||
@ -28,7 +28,7 @@ def main():
|
||||
conn_mysql = None
|
||||
try:
|
||||
# Obtener la fecha de la última ejecución del programa
|
||||
last_execution_date_utc = obtener_fecha_ultima_ejecucion()
|
||||
last_execution_date_utc = obtener_fecha_ultima_ejecucion(config['LAST_RUN_PATH'])
|
||||
last_execution_date_local_tz = last_execution_date_utc.astimezone(
|
||||
tz=local_tz).strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
@ -41,31 +41,19 @@ def main():
|
||||
conn_factuges = get_factuges_connection(config)
|
||||
conn_mysql = get_mysql_connection(config)
|
||||
|
||||
# Sync invoices
|
||||
# Sincronizamos
|
||||
logging.info(
|
||||
f">>>>>>>>>>> Sync invoices FactuGES escritorio to FactuGES web")
|
||||
sync_invoices(conn_factuges, conn_mysql, last_execution_date_local_tz)
|
||||
f">>>>>>>>>>> INI Sync invoices FactuGES escritorio to FactuGES web")
|
||||
sync_invoices_factuges(conn_factuges, conn_mysql, last_execution_date_local_tz)
|
||||
|
||||
# Confirmar los cambios
|
||||
conn_mysql.commit()
|
||||
conn_factuges.commit()
|
||||
conn_factuges.close()
|
||||
conn_mysql.close()
|
||||
logging.info(f"FIN Sync FactuGES web >>>>>>>>>>")
|
||||
logging.info(f">>>>>>>>>>> FIN Sync invoices FactuGES escritorio to FactuGES web")
|
||||
|
||||
# ESTO OTRO DEBERIA SER OTRA TRANSACCION POR LO QUE HACEMOS NUEVA CONEXION
|
||||
# Vamos que deberia ir en otro lado
|
||||
conn_mysql = get_mysql_connection(config)
|
||||
|
||||
# Sync Verifactu
|
||||
logging.info(
|
||||
f">>>>>>>>>> Sync facturas emitidas en FactuGES web to Verifactu")
|
||||
sync_invoices_verifactu(conn_mysql, last_execution_date_local_tz)
|
||||
conn_mysql.commit()
|
||||
conn_mysql.close()
|
||||
logging.info(f"FIN Sync Verifactu >>>>>>>>>>")
|
||||
|
||||
# actualizar_fecha_ultima_ejecucion()
|
||||
actualizar_fecha_ultima_ejecucion(config['LAST_RUN_PATH'])
|
||||
|
||||
# Enviar email
|
||||
# send_orders_mail(inserted_orders)
|
||||
81
app/sync_verifactu_main.py
Normal file
81
app/sync_verifactu_main.py
Normal file
@ -0,0 +1,81 @@
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from __version_sync_factuges__ import __version__
|
||||
from datetime import datetime
|
||||
from dateutil import tz
|
||||
from config import setup_logging, load_config
|
||||
from db import get_mysql_connection, get_factuges_connection, sync_invoices_verifactu
|
||||
from utils import obtener_fecha_ultima_ejecucion, actualizar_fecha_ultima_ejecucion, log_system_metrics, send_orders_mail
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
# Cargar la configuración
|
||||
config = load_config()
|
||||
|
||||
local_tz = tz.gettz(config['LOCAL_TZ'])
|
||||
|
||||
# Logging
|
||||
setup_logging()
|
||||
|
||||
logging.info("== START SYNC VERIFACTU ==")
|
||||
logging.info(f"Version: {__version__}")
|
||||
logging.info(f"Environment: {config['ENVIRONMENT']}")
|
||||
log_system_metrics()
|
||||
|
||||
conn_factuges = None
|
||||
conn_mysql = None
|
||||
try:
|
||||
# Obtener la fecha de la última ejecución del programa
|
||||
last_execution_date_utc = obtener_fecha_ultima_ejecucion()
|
||||
last_execution_date_local_tz = last_execution_date_utc.astimezone(
|
||||
tz=local_tz).strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
logging.info("Last execution (UTC): %s",
|
||||
last_execution_date_utc.strftime("%Y-%m-%d %H:%M:%S %Z"))
|
||||
logging.info("Last execution (Local time): %s",
|
||||
last_execution_date_local_tz)
|
||||
|
||||
# Abrimos conexión con una única transacción para que todo esté controlado
|
||||
conn_mysql = get_mysql_connection(config)
|
||||
|
||||
# Sync Verifactu
|
||||
logging.info(
|
||||
f">>>>>>>>>> INI Sync facturas emitidas to Verifactu")
|
||||
sync_invoices_verifactu(conn_mysql, last_execution_date_local_tz)
|
||||
conn_mysql.commit()
|
||||
conn_mysql.close()
|
||||
logging.info(f">>>>>>>>>> FIN Sync facturas emitidas to Verifactu")
|
||||
|
||||
actualizar_fecha_ultima_ejecucion()
|
||||
|
||||
# Enviar email
|
||||
# send_orders_mail(inserted_orders)
|
||||
|
||||
logging.info("== END (0) ==")
|
||||
sys.exit(0)
|
||||
|
||||
except Exception as e:
|
||||
logging.error("Se ha producido un error en la última ejecución.")
|
||||
logging.error(e)
|
||||
logging.error("Traceback:", exc_info=True)
|
||||
logging.info("== END (1) ==")
|
||||
|
||||
if conn_mysql is not None:
|
||||
conn_mysql.rollback()
|
||||
|
||||
if conn_factuges is not None:
|
||||
conn_factuges.rollback()
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
finally:
|
||||
if conn_factuges:
|
||||
conn_factuges.close()
|
||||
if conn_mysql:
|
||||
conn_mysql.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -1,21 +1,60 @@
|
||||
from __future__ import annotations
|
||||
from datetime import datetime, timezone
|
||||
from dateutil import tz
|
||||
from typing import Optional
|
||||
import os
|
||||
|
||||
# Función para obtener la fecha de la última ejecución del programa desde un archivo de texto
|
||||
DEFAULT_PATH = "./last_execution.txt"
|
||||
FMT = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
|
||||
def obtener_fecha_ultima_ejecucion():
|
||||
def obtener_fecha_ultima_ejecucion(
|
||||
path: str = DEFAULT_PATH,
|
||||
*,
|
||||
fallback: Optional[datetime] = None,
|
||||
) -> datetime:
|
||||
"""
|
||||
Lee la última fecha de ejecución desde `path` y la devuelve como aware (UTC).
|
||||
Si no existe o hay error de parseo, devuelve `fallback` (por defecto 2024-01-01 UTC).
|
||||
"""
|
||||
if fallback is None:
|
||||
fallback = datetime(2024, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
try:
|
||||
with open('./last_execution.txt', 'r', encoding="utf8") as f:
|
||||
with open(path, "r", encoding="utf8") as f:
|
||||
fecha_str = f.read().strip()
|
||||
return datetime.strptime(fecha_str, '%Y-%m-%d %H:%M:%S').astimezone(tz=tz.UTC)
|
||||
# Se guarda como texto sin tz; interpretamos como UTC
|
||||
dt_naive = datetime.strptime(fecha_str, FMT)
|
||||
return dt_naive.replace(tzinfo=timezone.utc)
|
||||
except FileNotFoundError:
|
||||
# Si el archivo no existe, se asume que el programa nunca se ha ejecutado antes
|
||||
return datetime(2024, 1, 1, 0, 0, 0).astimezone(tz=tz.UTC)
|
||||
|
||||
# Función para actualizar la fecha de la última ejecución del programa en el archivo de texto
|
||||
return fallback
|
||||
except ValueError:
|
||||
# Formato inválido en el archivo -> usar fallback
|
||||
return fallback
|
||||
|
||||
|
||||
def actualizar_fecha_ultima_ejecucion():
|
||||
with open('./last_execution.txt', 'w', encoding="utf8") as f:
|
||||
f.write(datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S'))
|
||||
def actualizar_fecha_ultima_ejecucion(
|
||||
path: str = DEFAULT_PATH,
|
||||
*,
|
||||
momento: Optional[datetime] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Escribe en `path` la fecha/hora (UTC) en formato YYYY-MM-DD HH:MM:SS.
|
||||
Si `momento` es None, usa ahora en UTC.
|
||||
Crea directorios intermedios si no existen.
|
||||
"""
|
||||
if momento is None:
|
||||
momento = datetime.now(timezone.utc)
|
||||
else:
|
||||
# Normalizamos a UTC si viene con tz; si es naive, asumimos UTC
|
||||
if momento.tzinfo is None:
|
||||
momento = momento.replace(tzinfo=timezone.utc)
|
||||
else:
|
||||
momento = momento.astimezone(timezone.utc)
|
||||
|
||||
# Asegurar carpeta si `path` incluye directorios
|
||||
folder = os.path.dirname(os.path.abspath(path))
|
||||
if folder and not os.path.exists(folder):
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
|
||||
with open(path, "w", encoding="utf8") as f:
|
||||
f.write(momento.strftime(FMT))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user