Ir al contenido

QuickBooks Online y la actualización que borra

Eloquent envía los atributos que cambiaron. QuickBooks Online quiere el objeto en el que debe convertirse. Entre esas dos frases hay un proveedor sin dirección.

6 min de lectura

Una integración con QuickBooks Online entra en producción. Tres semanas después un registro de proveedor no tiene dirección de facturación, ni condiciones de pago, ni código fiscal, y el registro de auditoría dice que la última persona que lo tocó solo cambió un correo electrónico.

Nada está roto. La integración hizo exactamente lo que se le dijo, y lo que se le dijo fue el comportamiento por defecto de dos sistemas que no se ponen de acuerdo sobre qué significa una actualización.

Eloquent envía cambios, la API quiere el objeto

Un save() envía los atributos que están sucios. Para una base de datos eso es correcto y para esta API es la carga equivocada, porque trata el cuerpo de una actualización como el registro en el que debe convertirse. Los campos que omites no quedan intactos - quedan vacíos.

Así que la capa de mapeo no puede ser una traducción fina de los atributos cambiados de un modelo. Tiene que producir un objeto completo, lo que en la práctica significa leer el registro actual de QuickBooks, aplicarle el cambio y enviar el resultado.

La API admite una actualización parcial y conviene usarla. No conviene depender solo de ella, porque es un parámetro que alguien puede olvidar en la única llamada que importaba. Leer antes de escribir cuesta una petición y elimina toda una clase de pérdida silenciosa de datos, y en código que edita la contabilidad de alguien ese intercambio no necesita discusión.

La conclusión estructural es que esta integración necesita su propio mapeador en vez de un método en el modelo. El objeto que va al sistema contable no es el modelo, es un documento montado a partir de él, y tratarlos como lo mismo es el origen de este fallo.

La versión hace que un reintento ciego sea incorrecto

Cada registro lleva una versión, y una actualización tiene que enviar la versión sobre la que se basó. Si el registro se movió entretanto, se rechaza.

Eso es buen comportamiento y rompe el reintento por defecto. Un trabajo en cola que guarda una carga terminada y la reenvía tras un fallo está enviando una versión ya obsoleta, así que falla otra vez, y otra, hasta agotar los intentos - y el cambio acaba en una tabla de trabajos fallidos en vez de en la contabilidad.

El trabajo tiene que guardar la intención y no la carga. Lo que guarda es «pon el correo de este cliente en este valor», no un cuerpo de petición serializado. En cada intento lee el registro actual, aplica la intención y envía el resultado con la versión que acaba de leer.

Eso hace que el trabajo sea de verdad seguro de ejecutar dos veces, y aquí importa más que de costumbre, porque la cola de Laravel reintenta lo haya previsto alguien o no.

La otra mitad de la cuestión de la versión es qué hacer con un conflicto real, cuando alguien de contabilidad cambió el mismo campo. Sobrescribir es una decisión, no un valor por defecto. Para la mayoría de los campos la respuesta honesta es que gana el sistema contable y tu aplicación registra que su cambio fue rechazado, porque sobrescribir en silencio la corrección de una persona de contabilidad es el comportamiento que acaba con la credibilidad de una integración en una sola reunión.

La conexión es una empresa y no el usuario

La autorización se concede para un archivo de empresa concreto, y un mismo acceso puede conceder varias. Así que lo que guardas es una conexión - identificador de empresa, tokens, cuándo se renovaron y si está sana ahora mismo - en su propia tabla.

No columnas en un usuario. No una fila en una tabla de ajustes. El identificador de empresa es la clave de búsqueda, porque cada petición posterior se hace en nombre de una empresa y la aplicación tiene que saber de cuál.

La renovación del token tiene el mismo peligro que cualquier otra API contable: dos workers renovando en el mismo instante y anulándose entre sí. Ese fallo y su remedio están en el texto sobre Xero, y la mecánica es lo bastante parecida como para que repetirla aquí te hiciera perder el tiempo. Las duraciones difieren - consulta las actuales en la documentación de Intuit en vez de fijar lo que dijo un artículo - la forma del problema no.

Vale la pena conocer una particularidad de QuickBooks: el token de refresco caduca también por desuso, no solo por antigüedad. Una integración para un cliente que dejó de usar tu aplicación unos meses vuelve desconectada sin que nada haya ido mal. Un estado desconectado tiene que ser un estado real en tu esquema, con algo en la interfaz que lo explique, y no una excepción que sorprenda a alguien.

Casar clientes es una tabla, no una búsqueda

QuickBooks exige que el nombre visible de un cliente sea único dentro de una empresa. Esa única restricción causa la mayor parte del dolor de estos proyectos.

Tu base de datos tiene «Acme S.L.». La suya tiene «Acme SL», y además «ACME SL - NO USAR» de 2019, y además «Acme » con un espacio al final. Casar por nombre crea un duplicado la primera vez que alguien escribe la forma jurídica de otra manera, y los duplicados en un sistema contable son trabajo de limpieza para una persona de contabilidad, no un bug que puedas arreglar.

Así que la pareja vive en una tabla de correspondencia - tu identificador, el suyo, la empresa a la que pertenece - y se rellena con un emparejamiento que alguien revisa una vez, no con una comparación de cadenas que se ejecuta para siempre.

Ese ejercicio no es trabajo de ingeniería y es la mayor parte del tiempo transcurrido. También saca a la luz la pregunta que nadie hizo: qué sistema es dueño del nombre de un cliente, y qué pasa cuando cambia en el otro lado.

Decidir quién numera las facturas

La última decisión es comercial y hay que tomarla antes de escribir nada.

Si QuickBooks asigna los números, tu aplicación no puede mostrar un número hasta que el envío haya funcionado, lo que cambia lo que ve un cliente y lo que pasa cuando el sistema contable no está disponible.

Si los asigna tu aplicación, alguien tiene que desactivar la numeración automática en QuickBooks y los huecos de la secuencia pasan a ser tu responsabilidad.

Las dos cosas funcionan. Lo que no funciona es que numeren las dos, porque produce dos facturas por una venta y una conciliación que nadie puede cerrar. Es una conversación de cinco minutos en la semana uno y dos semanas de desenredo en el mes cuatro.

Cuándo no construir esto

Si las facturas tienen que aparecer en QuickBooks, nada tiene que volver, y el volumen son decenas al mes, un conector gestionado es la respuesta correcta y funciona esta tarde.

Una integración construida se gana su sitio cuando la correspondencia es específica de cómo trabaja tu negocio, cuando el volumen hace caro corregir a mano, o cuando los datos contables tienen que poder consultarse dentro de tu propio sistema. No se lo gana como forma de evitar una cuota, porque el coste está en las reglas de conciliación y esas son las mismas en ambos casos.

Preguntas relacionadas

¿Podemos mapear nuestro modelo Customer directamente a los clientes de QuickBooks?
No por el nombre, que es la correspondencia a la que todo el mundo recurre primero. QuickBooks exige que el nombre visible sea único dentro de una empresa, así que tus registros y los suyos van a diferir en puntuación, formas jurídicas y una década de escritura inconsistente - y casar por cadena crea un duplicado cada vez que alguien escribe SL en vez de S.L. Lo que funciona es una tabla de correspondencia con tu identificador, el suyo y la empresa a la que pertenece la pareja, rellenada una vez con un emparejamiento que revisa una persona.
¿Qué pasa cuando un trabajo en cola se reintenta con una versión obsoleta?
Falla una y otra vez hasta agotar los intentos, porque la versión que envía ya quedó superada. Un reintento que reenvía la misma carga es incorrecto por construcción aquí. El trabajo tiene que volver a pedir el registro actual, aplicar el cambio previsto y enviar eso, lo que significa que el trabajo guarda el cambio y no la carga terminada. Esa es la diferencia entre una integración que se recupera y una que llena una tabla de trabajos fallidos.
¿Quién numera las facturas?
Un solo sistema, decidido antes de escribir nada, y es una pregunta comercial más que técnica. Si numera QuickBooks, tu aplicación no puede mostrar un número hasta que el envío tenga éxito, y eso cambia lo que ve el cliente. Si numera tu aplicación, alguien tiene que desactivar la numeración automática en QuickBooks y aceptar que los huecos son cosa tuya. Las dos opciones valen. Que numeren las dos produce dos facturas por una venta.
¿Cuánto se tarda en construirlo?
La autorización, la primera factura correcta y el handler de webhooks son unas dos semanas. El resto es la correspondencia - qué cliente es cuál, qué pasa con un abono, cómo se aplica un pago parcial, qué lado gana cuando los dos cambiaron algo. Esa parte es una serie de decisiones con el equipo financiero, y es la que determina si alguien se fía del resultado.

← Volver a todos los artículos

Llamar+1 848 272 7583WhatsApp+90 850 308 5436Correoinfo@codefacture.comPágina de contacto