pFacturas for WooCommerce

Përshkrim

pFacturas es el plugin oficial para integrar la plataforma de facturación electrónica pFacturas con WooCommerce en Uruguay. Permite la emisión automática de Comprobantes Fiscales Electrónicos (CFE) cumpliendo con las normativas de la Dirección General Impositiva (DGI) de Uruguay.

Características principales

  • Emisión automática de CFE: Genera automáticamente e-Ticket, e-Factura y Notas de Crédito al procesar pedidos
  • Cumplimiento DGI: 100% conforme a las especificaciones técnicas de DGI Uruguay
  • Múltiples ambientes: Soporte para Demo, Testing y Producción
  • Facturación con/sin RUT: Factura tanto a consumidores finales como a empresas
  • Validación en tiempo real: Validación de RUT uruguayo con dígito verificador
  • Envío automático de PDF: El cliente recibe el comprobante fiscal por email
  • Compatible con WooCommerce Blocks: Funciona con el nuevo checkout de WooCommerce
  • Logs detallados: Sistema de logging para depuración y auditoría
  • Configuración flexible: Múltiples opciones para adaptar el plugin a tus necesidades

Requisitos

  • Cuenta activa en pFacturas (https://www.pfacturas.com)
  • WooCommerce instalado y activo
  • WordPress 6.0 o superior
  • PHP 7.4 o superior

Configuración rápida

  1. Instalar y activar el plugin
  2. Ir a WooCommerce pFacturas para revisar los settings y ajustar el comportamiento del plugin según tus necesidades
  3. Realizar un pedido de prueba (el plugin viene en modo Demo por defecto, no requiere credenciales)
  4. Verificar en WooCommerce Pedidos que el CFE se emitió correctamente y consultarlo desde el botón “Ver CFE” en el detalle del pedido

Nota: Para usar el ambiente de Testing o Producción, necesitarás credenciales de pFacturas obtenidas al contratar el servicio.

Servicios de terceros

Este plugin utiliza el servicio externo pFacturas para generar comprobantes fiscales electrónicos conforme a las regulaciones de DGI Uruguay.

Servicio: API de Facturación Electrónica pFacturas
Proveedor: PuntoExe Consultores
URL del servicio: https://www.pfacturas.com

Qué datos se envían:
– Información del cliente (nombre, RUT, dirección) desde pedidos de WooCommerce
– Detalles del pedido (artículos, precios, impuestos)
– Información de la tienda (RUT, sucursal)
– Estos datos se envían cuando se realiza un pedido y el plugin está configurado para emitir comprobantes electrónicos

Cuándo se envían los datos:
– Automáticamente después de completar el pedido (cuando está configurado)
– Manualmente cuando el administrador activa la generación de factura
– Solo para pedidos que requieren comprobantes fiscales electrónicos

Propósito: Generar comprobantes fiscales electrónicos (CFE) legalmente conformes según lo requiere la ley tributaria uruguaya (DGI)

Política de privacidad: https://efactura.puntoexe.com.uy/facturaci%C3%B3n-electr%C3%B3nica/woocommerce-integrado/pol%C3%ADtica-de-privacidad
Términos de servicio: https://efactura.puntoexe.com.uy/facturaci%C3%B3n-electr%C3%B3nica/woocommerce-integrado/t%C3%A9rminos-y-condiciones-de-servicio

Al usar este plugin, aceptas compartir datos de pedidos con el servicio pFacturas para fines de facturación electrónica.

Soporte técnico

Para consultas y soporte técnico, contactar a efactura@puntoexe.com.uy

Plugin desarrollado y mantenido por Punto Exe Consultores.

Dependencies

Este plugin requiere que WooCommerce esté instalado y activo.

Support

¿Preguntas o problemas? Escribe a efactura@puntoexe.com.uy.

Foto ekrani

  • Pestaña Conexión del plugin: selección de modalidad (Demo, Testing, Producción) y configuración de credenciales de pFacturas. En modo Demo no se requieren credenciales ya que el plugin solicita unas temporales automáticamente.
  • Pestaña Documento: configuración general del CFE (forma de pago por defecto, tipo de cambio comercial, adenda libre) y sección “Datos del Receptor” con la opción para incluir los datos del cliente del Billing Address en el receptor del CFE de consumo final, y el umbral de identificación en Unidades Indexadas.
  • Pestaña Emisión: habilitación de emisión automática de CFE al cambiar el estado de la orden, emisión automática de Nota de Crédito al crear un Refund, y textos personalizables que se muestran al cliente en la página de order-received en caso de error de emisión.
  • Pestaña Checkout: textos personalizables del checkout, ubicación visual de los campos fiscales con detección automática del modo de checkout (clásico o Blocks), y sincronización opcional con campos billing estándar de WooCommerce para compatibilidad con flujos previos al plugin.
  • Pestaña Backoffice/POS: integración con sistemas de Punto de Venta como YITH POS. Soporta dos modos de identificación del receptor (explícito con dos campos separados o heurístico con un único campo de documento), y permite usar la Nota del Cliente como Adenda.
  • Pestaña Avanzado: registro de logs de depuración, emisión asíncrona de CFE vía Action Scheduler (recomendado cuando hay plugins de pago con webhooks de timeout corto como Mercado Pago), y visualización del caché de cotizaciones (Unidad Indexada y Dólar).
  • Campos fiscales en el checkout: cuando el cliente elige “Factura con RUT = Sí”, se solicitan RUT y Razón Social con validación de dígito verificador del lado del cliente y del servidor.
  • Campos fiscales en el checkout: cuando el monto de la orden supera el umbral de identificación configurado en Unidades Indexadas, se solicitan Tipo y Número de Documento del cliente (Cédula de Identidad uruguaya, Pasaporte, DNI Mercosur u Otros).
  • Metabox de pFacturas en la pantalla de edición de orden: muestra el tipo de CFE emitido (eTicket, eFactura), el número fiscal asignado por DGI, el estado de emisión y el enlace al PDF del comprobante.
  • Emisión automática de Nota de Crédito al hacer un Refund de la orden: el metabox muestra tanto el CFE original como la NC asociada, ambos con sus números fiscales y enlaces al PDF, y las notas de la orden documentan el proceso.

Instalim

  1. Ir a Plugins Añadir nuevo Subir plugin
  2. Seleccionar el archivo ZIP y hacer clic en “Instalar ahora”
  3. Activar el plugin
  4. Ir a WooCommerce pFacturas
  5. Para pruebas rápidas: Seleccionar Modo “Demo” (no requiere configuración adicional)
  6. Para uso en producción: Configurar RUT, Sucursal, Usuario y Contraseña con credenciales de pFacturas

Shqyrtime

25 Maj, 2026
PFacturas para WooCommerce me sorprendió para bien porque resuelve una de las partes más molestas de vender online en Uruguay: la facturación electrónica. El plugin se integra directamente con el checkout de WooCommerce y adapta automáticamente el formulario según si el cliente compra como consumidor final o como empresa, pidiendo datos como RUT y razón social cuando corresponde. Además, hace validaciones adicionales con DGI para evitar errores en los datos de facturación, lo que da mucha más tranquilidad! Algo que me gustó mucho es que no requiere configuración inicial para empezar a probarlo. Apenas instalás el plugin ya queda funcionando en modo demo y empieza a generar facturas de prueba automáticamente, así que podés probar todo el flujo sin tener que configurar certificados ni perder tiempo tocando opciones complicadas. Se nota que está pensado para que cualquiera pueda empezar rápido! En general quedé muy conforme con el plugin. Para quienes usan WooCommerce y necesitan integrar facturación electrónica en Uruguay, me parece una solución súper práctica, cómoda y mucho más simple de lo que esperaba.
Lexoni 1 shqyrtimin e vetëm

Kontribues & Zhvillues

“pFacturas for WooCommerce” është software me burim të hapur. Në këtë shtojcë kanë dhënë ndihmesë personat vijues.

Kontribues

Regjistër ndryshimesh

1.2.5.4

  • Corrección crítica: El parseo del subtotal del carrito en ambos checkouts (Clásico y Block) ahora extrae solamente la primera secuencia numérica del texto, en lugar de limpiar todo el texto y quedarse con dígitos, puntos y comas. Antes, si el texto del subtotal contenía palabras adicionales como “(incl. VAT)”, “(I.V.A. incluido)” o similares con un punto, el punto contaminaba el parseo: por ejemplo, “$ 61,00 (incl. VAT)” se interpretaba como 6100 USD (porque el “.” de “incl.” se sumaba al string). Resultado: los campos de Persona Física aparecían incorrectamente en órdenes muy por debajo del umbral. Ahora se usa una regex que captura solo la primera secuencia numérica con sus separadores.
  • Corrección: Los campos “Tipo de documento” y “Documento” del Checkout Clásico ya no muestran un asterisco rojo duplicado. Antes WooCommerce agregaba un asterisco automáticamente (porque estos campos estaban definidos con required => true) y el plugin agregaba otro mediante JavaScript. Ahora ambos campos están definidos con required => false para que la obligatoriedad y el asterisco se gestionen solo desde el JavaScript del plugin (igual que ya se hacía con RUT y Razón Social), evitando la duplicación.
  • Corrección crítica: El JavaScript inline del Checkout Clásico ahora se inyecta directamente en el HTML junto con los campos del plugin (vía echo PHP), en lugar de usar wp_add_inline_script(). Esto resuelve un bug detectado en algunos sitios donde el script inline simplemente no se cargaba aunque los campos del plugin sí aparecían — el listener change del select “¿Factura con RUT?” no se disparaba y los campos RUT/Razón Social nunca se mostraban. La causa raíz era que algunos plugins de optimización/caché de WordPress (o ciertos temas) descartaban el handle vacío pfwc-checkout-inline antes de que se inyectara el contenido inline asociado. Ahora el script va directamente en el HTML, sin depender del lifecycle de enqueue/print de WordPress.
  • Mejora: El enqueue de los assets del Checkout Clásico ahora también detecta automáticamente páginas que usen el shortcode [woocommerce_checkout] o el bloque “Classic Checkout” de WooCommerce, aunque no estén configuradas como la página oficial de checkout en WooCommerce Ajustes Avanzado Páginas de pago. Útil para páginas de prueba o casos donde el admin usa el checkout en múltiples páginas.
  • Mejora: Las versiones de los assets (CSS y JS externos) ahora usan la constante PFWC_VERSION en lugar de un número hardcoded 1.0.6. Esto fuerza a los navegadores a actualizar la caché de los assets cuando el usuario actualiza el plugin, evitando situaciones donde el JS quedaba con código viejo aún después de actualizar.
  • Mejora UX: Las etiquetas de los campos “RUT”, “Razón social”, “Tipo de documento” y “Documento” del Checkout Clásico ya no muestran el texto “(opcional)” de WooCommerce. En su lugar, cuando el campo es realmente obligatorio (porque se respondió “Sí” a “¿Factura con RUT?” o porque el monto supera el umbral de identificación), se muestra un asterisco rojo. La pregunta “¿Factura con RUT?” sigue marcada como opcional porque la decisión de facturar con RUT sí lo es.
  • Mejora UX: Al cambiar “¿Factura con RUT?” a “Sí”, ahora el campo RUT vacío se marca con borde rojo inmediatamente (igual que la Razón Social). Antes el borde rojo del RUT solo aparecía al ingresar el primer dígito, generando una inconsistencia visual con Razón Social.
  • Mejora UX: Al hacer click en “Realizar pedido” con un RUT vacío, RUT inválido, Razón Social vacía, Tipo de Documento vacío, Documento vacío o CI inválida, el campo correspondiente se marca con borde rojo (además del mensaje de error y el focus que ya existían). Antes solo se mostraba el mensaje sin marcar el campo.
  • Mejora UX: Validación pre-submit de Razón Social vacía y RUT vacío como mensajes separados y específicos. Antes mostraba “RUT inválido. Verifique el dígito verificador.” aunque el RUT estuviera completamente vacío, lo cual era confuso.

1.2.5.3

  • Corrección crítica: Bug heredado en pFacturas.php que generaba un Fatal Error (HTTP 500) al actualizar el plugin desde el admin de WordPress. La función pf_log() fue renombrada a pfwc_log() hace varias versiones, pero quedó una llamada a pf_log() huérfana en el callback del hook upgrader_process_complete. Resultado: cada vez que un admin actualizaba el plugin desde “Plugins Hay actualizaciones disponibles”, veía un error visual (“Actualización fallida”) aunque los archivos del plugin sí se reemplazaban correctamente (el fatal ocurría DESPUÉS de copiar los archivos). Al reintentar la actualización, WordPress detectaba que ya tenía la versión nueva y no mostraba el error. Bug presente desde 1.x. Ahora la llamada se corrigió a pfwc_log() y las actualizaciones futuras (de 1.2.5.3 en adelante) serán limpias sin errores visibles.
  • Corrección crítica: La validación del dígito verificador de RUT en el servidor (Checkout Clásico) usaba un algoritmo distinto al del cliente JavaScript: tenía solo 9 factores cíclicos en vez de los 11 correctos. Resultado: RUTs válidos eran rechazados al hacer click en “Realizar pedido” con el mensaje “RUT inválido. Verifique el dígito verificador.”. Ahora ambos lados (cliente y servidor) usan el mismo helper pfwc_validar_rut() ya existente en helpers.php (factor cíclico 29 idéntico al de Checkout Block).
  • Mejora de seguridad: Validación server-side de RUT y CI también en el flujo del Checkout Block (Store API). Antes solo se validaba en JavaScript del cliente; si un atacante deshabilitaba el JS, podía enviar datos fiscales inválidos al servidor. Ahora cualquier intento de checkout con RUT/CI inválidos via Block es rechazado con error HTTP 400. Misma función helper que el flujo Clásico (pfwc_validar_rut y pfwc_validar_ci).
  • Mejora: Validación en tiempo real de Razón Social en el Checkout Clásico — borde rojo cuando “¿Factura con RUT?” está en Sí y el campo está vacío. Antes solo se validaba al hacer click en “Realizar pedido”.
  • Mejora: Validación en tiempo real de Tipo de Documento y Documento en el Checkout Clásico — borde rojo cuando estos campos son obligatorios (subtotal supera el umbral de identificación) y están vacíos. Si el tipo es Cédula uruguaya (3), el campo Documento también valida el dígito verificador en tiempo real.
  • Mejora: Al cambiar el Tipo de Documento (por ejemplo de “Cédula” a “Pasaporte”) se re-valida automáticamente el campo Documento. Al cambiar “¿Factura con RUT?” se re-validan Razón Social, Tipo de Documento y Documento según corresponda.
  • Refactor interno: Eliminadas las funciones privadas PFWC_Checkout::valid_rut() y PFWC_Checkout::valid_ci() que duplicaban (con bugs en el caso de RUT) las funciones correctas pfwc_validar_rut() y pfwc_validar_ci() ya existentes en helpers.php. Ahora hay una sola fuente de verdad para la validación de DV en todo el plugin.

1.2.5.2

  • Mejora: Validación en tiempo real del dígito verificador en los campos “RUT” y “Documento” (cuando el tipo es Cédula uruguaya) del Checkout Clásico. Antes la validación solo se hacía al hacer click en “Realizar pedido”, obligando al usuario a llegar al final para enterarse del error. Ahora a medida que el cliente escribe, el campo se marca con borde rojo si el algoritmo de DV falla, dando feedback inmediato. Si el usuario cambia el “Tipo de documento” después de haber escrito en el campo Documento, se re-valida automáticamente (el DV solo aplica a Cédula Uruguaya; Pasaporte, DNI Mercosur y Otros no tienen DV verificable y nunca muestran rojo). El Checkout Block ya tenía esta validación en tiempo real; este cambio empareja el comportamiento entre ambos checkouts.

1.2.5.1

  • Corrección de documentación: Sección “Configuración rápida” del readme actualizada. El paso 2 ahora indica que el admin debe revisar y ajustar los settings según sus necesidades (antes solo decía “Ir a WooCommerce pFacturas” sin explicar para qué). El paso de seleccionar modo Demo se eliminó porque el plugin ya viene en Demo por defecto. Y se reemplazó “Verificar recepción del PDF por email” por “Verificar el CFE desde WooCommerce Pedidos”, porque en modo Demo el envío de PDF por email está deshabilitado.

1.2.5.0

  • Funcionalidad: Nuevo setting “Omitir emisión de CFE en órdenes con total cero” en el tab Emisión. Activado por default. Evita emitir comprobantes de monto 0 en casos como cupones 100% off, productos gratuitos o pedidos de prueba (no aportan valor fiscal y consumen crédito de la cuenta pFacturas). Si se desactiva, el plugin emite igualmente un CFE de monto 0 para estas órdenes.
  • Corrección: El label “¿Factura con RUT?” del Checkout Clásico aparecía desplazado horizontalmente hacia el centro en algunos sitios. Causa: WooCommerce inserta pseudo-elementos ::before y ::after en cada <p class="form-row"> como clearfix legacy (de la era pre-flexbox cuando el layout usaba floats). Al haber convertido el <p> de “¿Factura con RUT?” a display: flex para mostrar el label y el select inline, esos pseudo-elementos pasaron a ser flex items y empujaban el contenido hacia el centro. Ahora se desactivan con content: none específicamente para .pf-rut-inline. No afecta al Checkout Block (que no usa <p class="form-row">) ni al resto de los campos del Checkout Clásico.

1.2.4.2

  • Corrección crítica: El JavaScript del checkout que parsea el subtotal del carrito para comparar contra el umbral de identificación ahora detecta automáticamente el formato del monto según el orden de los separadores (formato americano 1,234.56 para USD o formato europeo/uruguayo 1.234,56 para UYU/EUR). Antes asumía siempre formato europeo, por lo que un monto en USD como “U$S 90.00” se parseaba erróneamente como 9000 (al borrar el punto pensando que era separador de miles). Resultado del bug: en tiendas con moneda USD, los campos de Persona Física (Tipo de Documento y Documento) se mostraban en el checkout aunque el monto estuviera muy por debajo del umbral de identificación. Aplicado en los 3 lugares con el mismo problema: parseo principal del Checkout Clásico, fallback del Checkout Clásico, y fallback del Checkout Blocks.
  • Mejora: Agregado un listener de evento input además del change existente para detectar cambios en el select “¿Factura con RUT?”. Necesario en sitios que tienen plugins de Checkout adicionales como Direct Checkout for WooCommerce, que reemplazan el <select> nativo por widgets custom que no siempre disparan eventos change estándar del DOM.
  • Mejora: Agregado un polling defensivo cada 500ms del valor del select de RUT en el Checkout Clásico. Última línea de defensa para sitios donde ni el evento change ni el input se disparan correctamente debido a interferencia de otros plugins. Si el valor cambia respecto al último observado, se dispara el toggle de campos. Bajo overhead (un querySelector + comparación de string por intervalo).
  • Corrección crítica: El checkout ahora detecta correctamente si el cliente seleccionó “Sí” en “¿Factura con RUT?” aunque algún plugin del sitio reescriba el atributo value de los <option> con el texto visible (“Sí”/”No”) en vez de los valores "1"/"0" que el plugin emite. Antes la comparación era estricta contra "1" tanto en JavaScript como en PHP, por lo que en sitios con TranslatePress, Google Tag Manager mal configurado, Direct Checkout u otros plugins que manipulan los selects, el plugin nunca mostraba los campos de RUT y Razón Social aunque el cliente eligiera “Sí”. Ahora se acepta "1", "si", "sí", "yes" o "true" en el value O en el texto de la option seleccionada, y al guardar el meta se normaliza siempre a "1"/"0" para que el resto del backend (mapper, sincronización con billing, panel admin) siga funcionando sin cambios.
  • Corrección: El dropdown “Tipo de documento” del Checkout Clásico ya no muestra la opción “Seleccione…” duplicada. El plugin definía manualmente una opción vacía con texto “Seleccione…” como primer item del array de options, y WooCommerce también inserta automáticamente su propio placeholder cuando el campo es required=true. Ahora se delega el placeholder al atributo placeholder del form field para evitar la duplicación.

1.2.4.1

  • Corrección crítica: Los selects de la página de Settings con keys numéricas (Ubicación de campos en checkout, Forma de pago por defecto) no preservaban visualmente el valor guardado al refrescar la página. Causa: comparación con === strict en self::f() fallaba porque PHP convierte automáticamente las keys numéricas de string a int en arrays, y '1' === 1 siempre da false. Resultado: ningún option recibía selected y el browser mostraba el primero por default. El valor en la base de datos se guardaba correctamente; el bug era solo de visualización. Fix: cast explícito a string en la comparación.
  • Mejora: Pestaña Documento reorganizada con nueva sección “Datos del Receptor” que agrupa los dos settings relacionados con la identificación del receptor: “Para consumo final, incluir datos del cliente en el receptor del CFE” y “Umbral de identificación de consumidor (en Unidades Indexadas)”. La sección “Configuración del documento” queda con: forma de pago por defecto, tipo de cambio comercial, adenda. El checkbox de envío de PDF al receptor mantiene su posición al final.
  • Mejora: Eliminado el setting “Permitir actualizaciones automáticas desde pFacturas” del tab Avanzado. El setting estaba inerte (no tenía ningún efecto en runtime), probablemente vestigio de una funcionalidad que nunca se implementó. Para instalaciones existentes que tuvieran el valor guardado, el valor persiste en la base de datos pero se ignora.

1.2.4.0

  • Funcionalidad: Nuevo setting “Para consumo final, incluir datos del cliente en el receptor del CFE” en el tab Documento (desactivado por default). Cuando se activa, los CFE de consumo final (sin RUT y por debajo del umbral de identificación) incluyen en la sección Receptor el nombre completo del cliente, dirección, ciudad y país tomados del Billing Address de WooCommerce. Sin esta opción el receptor queda vacío en consumo final (comportamiento por default según normativa DGI). Útil para comercios que prefieren tener visibilidad del cliente en el CFE aunque la normativa no lo exija.

1.2.3.0

  • Funcionalidad: Nuevo setting “Emisión asíncrona de CFE” en el tab Avanzado (desactivado por default). Cuando se activa, la emisión del CFE de órdenes del checkout web se encola y procesa en background vía Action Scheduler en lugar de ejecutarse durante el request del cambio de estado de la orden. Útil cuando hay plugins de pago con timeout corto en su webhook (típicamente Mercado Pago) que podrían cancelar la operación si el WebService de pFacturas demora en responder. Action Scheduler reintenta automáticamente si la emisión falla. Las órdenes de Backoffice/POS y las creadas manualmente desde admin se mantienen síncronas para que el operador vea el ticket emitido al instante.
  • Mejora: Agregado timeout de conexión de 10 segundos a los clientes SOAP (envío de CFE, consultas, eCommerce Demo). Antes los clientes usaban el default de PHP (típicamente 60 segundos) lo que podía generar cuelgues largos si el WebService no respondía. Aplica al flujo síncrono también — protección complementaria a la emisión asíncrona.
  • Mejora: En modo Demo, la sección de Notificaciones del CFE ahora queda vacía y no se cargan los emails al WebService aunque el setting “Enviar PDF al receptor” esté activado. Las credenciales Demo son compartidas y los CFE generados son de prueba — enviar notificaciones a clientes reales con tickets demo puede causar confusión. En ambientes Testing y Producción se sigue notificando normalmente.

1.2.2.0

  • Funcionalidad: Adenda con fuentes diferenciadas según origen de la orden. Nuevo meta key checkout_adenda_meta_key en el tab Checkout (solo para órdenes del checkout web) y nuevo checkbox pos_use_customer_note_for_adenda en el tab Backoffice/POS (activado por default) para usar la Nota del Cliente como Adenda. Útil para YITH POS y sistemas similares que no exponen meta keys custom: el operador escribe en la nota y se incluye automáticamente en el CFE. Si no se desea este comportamiento, desmarcar el checkbox después de actualizar.
  • Mejora: Todas las fuentes de Adenda (texto estático, meta key del checkout, customer_note, meta key del POS) ahora se concatenan en un único elemento Adenda1, separadas por salto de línea. Antes generaban Adenda1, Adenda2, Adenda3 como elementos separados.
  • Mejora: El setting pos_adenda_meta_key ahora solo se lee para órdenes que NO vienen del checkout web (antes se aplicaba a todas, generando comportamiento engañoso).
  • Corrección crítica: Compatibilidad con HPOS (High Performance Order Storage) de WooCommerce. Las funciones internas read_pos_meta() y la lectura de meta keys de Adenda ahora usan $order->get_meta() en vez de get_post_meta(), que es la API correcta para sitios con HPOS habilitado. Sin este fix, en sitios con HPOS habilitado el plugin no podía leer el meta key del documento (típicamente billing_vat o _billing_vat) ni los meta keys de adenda, y emitía todas las órdenes POS como consumo final, aunque el operador hubiera ingresado un RUT o CI válido. Sigue funcionando correctamente en instalaciones sin HPOS (legacy wp_postmeta).
  • Corrección: El setting “Habilitar registro de logs de depuración” ahora persiste correctamente al guardar (antes se desmarcaba al refrescar la página). El bug era una inconsistencia interna de nomenclatura del setting (log_enabled vs enable_logging) entre el sanitizador y la lectura.
  • Corrección crítica: El receptor del CFE ahora se construye correctamente cuando hay datos de Persona Física resueltos (RUT, Tipo+Doc) aunque el total de la orden NO supere el umbral de identificación en Unidades Indexadas. Antes, las órdenes POS por debajo del umbral con CI o documento válido detectado se emitían como consumo final ignorando los datos. El umbral solo aplica al checkout web (controla cuándo SE EXIGEN los datos); si los datos ya existen, siempre se identifica al receptor.
  • Corrección: El “País del Receptor” del CFE ahora respeta el billing_country del cliente en vez de forzar “UY” cuando el tipo de documento es 3 (CI uruguaya). El “País del Tipo de Documento” sigue siendo “UY” para CI (la CI es uruguaya por definición), pero el país donde vive el receptor puede ser distinto.
  • Corrección: La URL del WebService de Consultas (cotizaciones, estados) en ambiente de Producción ahora usa HTTPS en vez de HTTP. El WS de envío de CFE ya estaba en HTTPS para Producción; este corrige la inconsistencia.
  • Corrección crítica: El botón “Reintentar emisión” en el metabox de pFacturas (CFE) ahora funciona correctamente. Antes el handler AJAX llamaba a un método inexistente (on_payment_complete) que producía un Error fatal de PHP no atrapado por el primer try/catch, por lo que el botón nunca llegaba a hacer la conexión al WebService de pFacturas. Ahora invoca correctamente emit_if_needed().

1.2.1.1

  • Mejora: Changelog traducido al español (el público objetivo del plugin son empresas uruguayas)
  • Nota: Esta versión solo modifica la documentación, no hay cambios de código

1.2.1.0

  • Mejora: Nuevo botón “Restablecer defaults de POS” al final de la pestaña de configuración Backoffice/POS — rellena los campos vacíos con sus valores por defecto sin sobrescribir configuraciones personalizadas
  • Mejora: Facilita la migración desde versiones anteriores en las que pos_doc_meta_key quedaba guardado como string vacío (el nuevo default billing_vat no se aplica automáticamente a configuraciones ya guardadas)

1.2.0.0

  • Funcionalidad: Detección heurística del tipo de documento en órdenes que no provienen del checkout estándar (típicamente sistemas POS integrados via REST API)
  • Funcionalidad: Detección automática de RUT (12 dígitos con dígito verificador válido), Cédula uruguaya (8 dígitos con dígito verificador válido) u “Otros” a partir de un único campo de documento
  • Funcionalidad: Bloqueo de la creación de la orden via REST cuando el documento es inválido pero la razón social termina en SA/SAS/SRL/LTDA (se presume RUT mal tipeado y se exige corrección)
  • Funcionalidad: Nuevo default billing_vat para el meta key del documento — funciona out-of-the-box con la mayoría de plugins POS
  • Mejora: Pestaña Backoffice/POS reorganizada con texto de ayuda explícito para los dos modos (explícito de 2 campos vs heurístico de campo único)
  • Mejora: Nuevo helper pfwc_nombre_parece_empresa() para detectar sufijos SA/S.A./SAS/S.A.S./SRL/S.R.L./LTDA/Ltda (con o sin puntos)
  • Mejora: Nuevo código de error pf_rut_invalido_empresa para órdenes POS bloqueadas por inconsistencia entre documento y sufijo empresarial

1.1.3.2

  • Corrección: La página de settings ahora siempre abre en la primera pestaña al navegar de vuelta
  • Corrección: La posición de la pestaña activa solo se preserva durante la recarga por guardado de settings, no entre navegaciones

1.1.3.1

  • Corrección: Aviso en settings de POS cuando los meta keys de identificación fiscal no están configurados
  • Corrección: La validación previa a la emisión detecta cuando billing_company está presente pero los meta keys fiscales no están configurados, evitando la emisión silenciosa como consumo final
  • Corrección: El aviso dinámico en la pestaña POS se actualiza en tiempo real mientras el usuario completa o borra los campos de meta keys

1.1.3.0

  • Mejora: Página de settings reorganizada con navegación por pestañas (Conexión, Documento, Emisión, Checkout, Backoffice/POS, Avanzado)
  • Mejora: Pestaña activa persistida en localStorage entre recargas de página
  • Mejora: Todo el JavaScript consolidado en un único bloque inline

1.1.2.0

  • Refactor: Settings de POS simplificados — se eliminaron pos_rut_meta_key y pos_razon_social_meta_key
  • Funcionalidad: POS ahora usa el campo tipo_doc (2=RUT, 3=CI, etc.) alineado con los códigos de tipo de documento de DGI
  • Funcionalidad: Campos de billing POS configurables (pos_billing_first_name, pos_billing_last_name, pos_billing_company) con defaults estándar de WooCommerce
  • Funcionalidad: Todos los campos de meta keys POS cambiados de combos a inputs de texto para compatibilidad universal con cualquier plugin
  • Funcionalidad: Sincronización checkout — nuevos settings para copiar RUT y Razón Social a los campos billing estándar de WooCommerce
  • Funcionalidad: checkout_razon_social_meta_key (default: billing_company) sincroniza la Razón Social en el checkout

1.1.1.0

  • Corrección: IndicadorDeFacturacion ahora se infiere a partir de la tasa efectiva de impuestos en vez del nombre de la tax class
  • Corrección: Los productos exentos de IVA (ej: libros al 0%) ahora usan correctamente el indicador 1 (Exento) en vez del 3 (IVA Básica)
  • Corrección: El indicador de la línea de envío también usa el cálculo por tasa efectiva
  • Refactor: Mapeo centralizado de tasa de impuesto a indicador en el método indicador_por_tasa()

1.1.0.0

  • Funcionalidad: Compatibilidad con sistemas de Backoffice/POS (YITH Point of Sale y plugins similares)
  • Funcionalidad: Resolución automática de datos fiscales desde los campos billing cuando los campos del checkout están vacíos
  • Funcionalidad: Mapeo configurable de campos billing para RUT, Razón Social, Tipo Documento, Documento
  • Funcionalidad: Combos de settings populados dinámicamente desde los billing fields registrados por WooCommerce
  • Funcionalidad: Validación en dos niveles — hook de creación de orden via REST API + validación previa a la emisión
  • Funcionalidad: Funciones de validación de dígito verificador para RUT y CI (Cédula de Identidad) del lado del servidor
  • Funcionalidad: Soporte para Adenda multi-línea con un meta key extra configurable
  • Funcionalidad: Datos fiscales auto-persistidos en los meta de la orden para consistencia en notas de crédito
  • Corrección: El campo Id de MediosPago se trunca a 20 caracteres para cumplir con el límite del WSDL

1.0.27.64

  • Corrección: Modo Demo — el RUT y la Sucursal del Emisor se enviaban vacíos cuando las credenciales demo estaban expiradas
  • Corrección: El constructor del Client ahora se ejecuta antes que el Mapper para que las credenciales demo se renueven antes de construir la sección Emisor del CFE
  • Corrección: Mismo fix aplicado al flujo de emisión de notas de crédito (NC)
  • Corrección: Bloqueo de la página de checkout por loop infinito de MutationObserver/toggle en blocks.js
  • Corrección: Debounce agregado al callback del MutationObserver y se omite el dispatch al Store API cuando el payload no cambió
  • Limpieza: Removidos los console.log verbosos de debug en blocks.js

1.0.27.63

  • Seguridad: Corregido el orden de verificación del nonce AJAX — ahora el nonce se verifica ANTES de extraer order_id de $_POST
  • Seguridad: Migrado a verificación estática de nonce con check_ajax_referer() en vez de nonces específicos por orden
  • Seguridad: El nonce ahora usa el nombre de acción estático pfwc_emit_cfe en lugar del dinámico pf_emit_ . $order_id
  • Corrección: ob_start() y ob_get_clean() separados en líneas individuales para manejo explícito del buffer
  • Mejora: El handler AJAX ahora usa wp_localize_script() para pasar nonce y ajaxUrl al JavaScript
  • Cumplimiento: Todas las correcciones de seguridad siguen los requerimientos del WordPress.org Plugin Directory

1.0.27.62

  • Corrección: Renombradas todas las funciones helper del prefijo pf_ al prefijo pfwc_ (WordPress.org requiere 4 caracteres o más)
  • Corrección: Comentarios phpcs:ignore agregados para el uso de $_GET en el enqueueing de scripts del admin (solo para mostrar mensaje, no procesa datos)
  • Cumplimiento: Todos los nombres de funciones ahora cumplen con los estándares de naming de WordPress.org

1.0.27.61

  • Corrección: Cambiados todos los prefijos de clases de PF_ a PFWC_ (WordPress.org requiere 4 caracteres o más)
  • Corrección: Constantes PF_PLUGIN_DIR y PF_PLUGIN_URL cambiadas a PFWC_PLUGIN_DIR y PFWC_PLUGIN_URL
  • Corrección: Tags <script> inline convertidos a wp_add_inline_script() para enqueueing correcto
  • Seguridad: Agregada verificación de nonce y de capability en el método ajax_emit()
  • Seguridad: Agregada verificación de permisos en el método emit_if_needed() y removido el procesamiento directo de $_POST
  • Seguridad: Removidos los var_export() y print_r() inseguros de datos de $_POST en el logging
  • Seguridad: Agregado el escapado correcto con esc_html() a todas las variables echoeadas
  • Cumplimiento: Todos los scripts ahora están correctamente enqueueados siguiendo los WordPress Coding Standards

1.0.27.60

  • Corrección: Toda la descripción del plugin traducida al inglés (readme.txt y headers del plugin)
  • Documentación: Agregada sección completa de Servicios de Terceros documentando la integración con la API de pFacturas
  • Cumplimiento: Documentación completa de transmisión de datos, política de privacidad y términos de servicio

1.0.27.59

  • Corrección: Corregido el método de compresión del ZIP (cambiado a Compress-Archive para compatibilidad con WordPress.org)

1.0.27.58

  • Corrección: Corregido el nombre del plugin en readme.txt para que coincida con pFacturas.php (ambos usan ahora “pFacturas for WooCommerce”)

1.0.27.57

  • Corrección: Plugin URI corregido para cumplir con los requerimientos de WordPress.org (no puede ser una URL de WordPress.org, debe ser del sitio del desarrollador)

1.0.27.56

  • Corrección: Corregido el nombre del autor de “Punto Exe Consultores” a “PuntoExe Consultores” (sin espacio)

1.0.27.55

  • Corrección: Header completamente reescrito siguiendo el formato exacto de la documentación oficial de WordPress.org (nombre en inglés, campos adicionales requeridos, License en el formato exacto)

1.0.27.54

  • Corrección: Acentos removidos del header del plugin para evitar problemas de encoding (WordPress.org requiere ASCII puro en headers)

1.0.27.53

  • Corrección: Agregados los campos Plugin URI y Author URI al header (requeridos por WordPress.org)

1.0.27.52

  • Corrección: Formato del bloque de comentarios cambiado de /* a /** (estándar PHPDoc DocBlock)

1.0.27.51

  • Corrección: Formato del header del plugin corregido (asterisco * agregado al inicio de cada línea según el estándar de WordPress.org)

1.0.27.50

  • Corrección: Formato del header del plugin corregido (changelog interno removido, se mantiene solo en readme.txt)

1.0.27.49

  • Corrección: Restaurados los acentos en Plugin Name y Description

1.0.27.48

  • Corrección: Restaurados los acentos en los tags de readme.txt

1.0.27.47

  • Corrección: Cambiado el enfoque de phpcs:ignore inline a un bloque phpcs:disable/phpcs:enable en class-pf-emitter.php líneas 588-590

1.0.27.46

  • Corrección: Actualizado el comentario phpcs:ignore inline en class-pf-emitter.php línea 589

1.0.27.45

  • Corrección: Agregado comentario phpcs:ignore inline en class-pf-emitter.php línea 589 para NonceVerification.Missing

1.0.27.44

  • Corrección: Cambiado el slug del plugin de “woocommerce-pfacturas” a “pfacturas-for-woocommerce”
  • Corrección: Ahora cumple con las reglas de trademark de WordPress.org (termina en “for-woocommerce”)
  • Corrección: Agregado sanitize_text_field() en class-pf-emitter.php línea 606 para el nonce
  • IMPORTANTE: Requiere desinstalar y reinstalar el plugin (cambio de slug)

1.0.27.43

  • Corrección: Corregido el nombre del plugin para cumplir con las reglas de trademark de WordPress.org
  • Corrección: El nombre ahora termina en “for WooCommerce” en vez de “para WooCommerce”
  • Corrección: Removidos caracteres acentuados del nombre y la descripción para evitar problemas de encoding
  • Corrección: readme.txt reducido a un máximo de 5 tags y la descripción corta a menos de 150 caracteres
  • Corrección: Agregado wp_unslash() en class-pf-emitter.php línea 606 para $_POST['_wpnonce']

1.0.27.42

  • Corrección: Actualizado el Stable tag de readme.txt a 1.0.27.42
  • Corrección: Completados los comentarios phpcs:ignore faltantes en class-pf-checkout.php (líneas 18-20, 37-39)
  • Corrección: Agregado phpcs:ignore para var_export en class-pf-emitter.php línea 155
  • Corrección: Agregados phpcs:ignore para $_POST en class-pf-emitter.php líneas 588, 592, 605
  • Corrección: Agregados phpcs:ignore para var_export y print_r en class-pf-mapper.php líneas 17, 20, 25

1.0.27.41

  • Corrección: Agregado sanitize_callback a register_setting() para cumplir con los estándares de WordPress
  • Corrección: Actualizado “Tested up to” a WordPress 6.8
  • Corrección: Agregados comentarios phpcs:ignore para los warnings de verificación de nonce en hooks de WooCommerce
  • Corrección: Agregados comentarios phpcs:ignore para las funciones de debug (var_export, print_r) usadas solo para logging

1.0.27.39

  • Arquitectura: Implementado el sistema de builds dual (oficial vs desarrollo)
  • Archivo nuevo: class-pf-manual-updater.php con la funcionalidad de actualización manual
  • Corrección: La actualización manual se movió a un archivo separado para evitar errores en Plugin Check
  • Builds oficiales: Excluyen class-pf-manual-updater.php para pasar Plugin Check sin errores
  • Builds de desarrollo: Incluyen class-pf-manual-updater.php para funcionalidad completa
  • Documentación: Actualizada en _dev/ para explicar el sistema de builds dual

1.0.27.38

  • Corrección: Agregados comentarios phpcs:ignore a todos los print_r() y var_export() usados en logging
  • Corrección: La funcionalidad de actualización manual ahora requiere el archivo de flag _dev/enable-manual-updates.flag
  • Mejora: Actualización manual deshabilitada por defecto en versiones oficiales para cumplir con los estándares de WordPress.org
  • Plugin Check: Resueltos todos los warnings de DevelopmentFunctions en class-pf-blocks.php y class-pf-emitter.php

1.0.27.37

  • Corrección: Todos los usos de date() reemplazados por gmdate() para evitar problemas de timezone
  • Corrección: Agregado esc_html() al mensaje de error de wp_die() en class-pf-settings.php
  • WordPress.DateTime.RestrictedFunctions: Todos los date() cambiados a gmdate() en helpers.php, class-pf-client.php y class-pf-mapper.php

1.0.27.36

  • Corrección: Tercera ronda de correcciones para el Plugin Check de WordPress.org
  • Aplicado esc_attr() a todas las salidas de self::OPTION_KEY en class-pf-settings.php
  • Aplicados esc_html(), esc_attr(), esc_textarea() a los parámetros dinámicos de la función f()
  • Agregados comentarios phpcs:ignore para print_r() y var_export() usados en logging
  • Cambiado date() por current_time('mysql') en helpers.php para consistencia con WordPress
  • Mejorada la función in_array() con el parámetro de comparación estricta

1.0.27.35

  • Corrección: Correcciones adicionales para el Plugin Check de WordPress.org (segunda ronda)
  • Agregados comentarios phpcs:ignore con justificación para variables seguras
  • Corregidos 15 errores de output escaping en class-pf-checkout.php, class-pf-emitter.php