Tienes un plugin que pone precios de mayorista por grupo de cliente. Tienes otro que aplica el recargo de equivalencia y la inversión del sujeto pasivo. Cada uno funciona bien por separado. Juntos, el total de algunos pedidos no cuadra con lo que dice tu gestoría, y nadie sabe cuál de los dos tiene la culpa.
No es mala suerte. Es una consecuencia previsible de cómo WooCommerce calcula un precio, y por eso se puede diagnosticar en vez de adivinar.
Los dos quieren decidir el precio, y solo puede decidirlo uno
WooCommerce no guarda un precio final por cliente. Guarda un precio en el producto y luego deja que quien quiera lo modifique, a través de filtros. Los dos que importan aquí son woocommerce_product_get_price y woocommerce_product_get_regular_price.
Tu plugin B2B se engancha ahí para devolver el precio del grupo. Y el plugin fiscal, según cómo esté hecho, puede engancharse al mismo sitio o actuar más tarde, cuando WooCommerce ya está calculando impuestos.
El orden lo decide la prioridad con la que cada uno se registró:
add_filter( 'woocommerce_product_get_price', 'precio_b2b', 10, 2 );
add_filter( 'woocommerce_product_get_price', 'ajuste_fiscal', 20, 2 );
El de prioridad 20 recibe lo que devolvió el de prioridad 10 y puede pisarlo. Ninguno de los dos autores escribió su plugin pensando en el otro, así que ese número lo eligieron por costumbre, no por acuerdo. Cuando el resultado sale mal, cada uno puede demostrar que su función hace exactamente lo que promete.
Tres sitios donde se rompe de verdad
1. El recargo depende del cliente, no del producto
Aquí está la incompatibilidad de fondo, y es de diseño. Las clases de impuesto de WooCommerce viven en el producto. El recargo de equivalencia depende del régimen fiscal del comprador: el mismo producto lleva recargo para un minorista acogido al régimen y no lo lleva para otro que no lo está.
Un plugin fiscal resuelve eso interceptando los tipos que WooCommerce ha encontrado, con filtros como woocommerce_find_rates o woocommerce_matched_tax_rates, y añadiendo la línea del recargo según quién esté comprando.
El problema aparece cuando el plugin B2B, además de cambiar el precio, cambia el rol del usuario o la dirección de cálculo. El plugin fiscal decide sobre información que el otro ha modificado hace un momento, y el 5,2 % acaba aplicándose sobre una base que no es la que debía.
2. Precios con impuestos incluidos
Si en los ajustes de WooCommerce tienes «he introducido los precios con impuestos incluidos», cada precio que devuelve un filtro se interpreta como precio con IVA dentro. WooCommerce lo desglosa hacia atrás para saber la base.
Casi todos los plugins de mayorista trabajan en neto, porque es como piensa un mayorista. Si devuelven 80 en una tienda configurada con impuestos incluidos, WooCommerce entiende que esos 80 ya llevan el 21 % dentro y calcula una base de 66,12.
El pedido no falla. No hay ningún aviso. Simplemente estás declarando menos IVA del que corresponde, y lo descubres cuando alguien cuadra el trimestre.
3. Inversión del sujeto pasivo sobre un precio que ya venía tocado
En una venta intracomunitaria a empresa con NIF-IVA válido, el impuesto es cero y lo liquida el comprador. El plugin fiscal quita el IVA.
Pero si el plugin B2B ya había entregado un precio pensando en un escenario con impuestos, quitar el IVA después no devuelve el precio de partida. Lo típico es un céntimo o dos de diferencia por línea, por el redondeo. En un pedido de cuatro artículos no lo ve nadie. En uno de trescientas líneas, la factura y el albarán no coinciden, y quien lo nota es tu cliente.
Cómo saber cuál de los dos lo está haciendo
Esto se puede comprobar en diez minutos, sin tocar nada en producción.
Mira quién está enganchado y en qué orden. Pon esto en el functions.php de un entorno de pruebas y carga cualquier ficha de producto:
add_action( 'wp_footer', function () {
global $wp_filter;
foreach ( array( 'woocommerce_product_get_price', 'woocommerce_find_rates' ) as $hook ) {
if ( empty( $wp_filter[ $hook ] ) ) {
continue;
}
echo "<!-- $hook\n";
foreach ( $wp_filter[ $hook ]->callbacks as $prioridad => $funciones ) {
foreach ( $funciones as $id => $f ) {
echo " $prioridad: $id\n";
}
}
echo "-->";
}
} );
En el código fuente de la página verás los dos plugins en la lista y con qué prioridad entra cada uno. El que tenga el número más alto es el que manda.
Comprueba el ajuste de impuestos incluidos. En Ajustes, Impuestos, mira si «he introducido los precios con impuestos incluidos» está activado. Si lo está y tu plugin de mayorista trabaja en neto, ya tienes localizado el caso 2 sin buscar más.
Haz un pedido de prueba de cada tipo. Uno nacional a minorista, uno nacional a mayorista con recargo, y uno intracomunitario con NIF-IVA válido. Compara base, cuota y total con lo que tu gestoría espera. Con tres pedidos sabes si el fallo es general o solo de un escenario, que es lo que de verdad acota el problema.
Qué se puede hacer
Hay tres salidas y ninguna es gratis.
La primera es coordinar las prioridades. Fuerzas que el fiscal corra después del de mayorista con un add_filter de prioridad alta en un plugin propio. Funciona, y se rompe en cuanto cualquiera de los dos publique una actualización que cambie sus números.
La segunda es configurar la tienda en neto y desactivar los precios con impuestos incluidos. Es lo correcto para una tienda mayorista de todas formas. Si además vendes a particulares, tendrás que revisar cómo se muestran los precios en la parte pública.
La tercera es usar un solo plugin que resuelva el descuento de grupo, la exención y el recargo en el mismo sitio. Entonces no hay orden que coordinar porque no hay dos funciones compitiendo.
Nosotros hacemos Entrepo, que es de los del tercer grupo, así que léelo sabiendo de dónde viene el consejo. Pero si tu montaje actual funciona, no lo cambies por esto: cambia solo si has reconocido tu caso en alguno de los tres de arriba.
Una advertencia que no me voy a saltar: esto explica el mecanismo, no sustituye a tu asesoría. Quién tiene que llevar recargo y qué tipo se aplica lo decide tu gestoría. Lo que aquí se resuelve es que la tienda haga lo que ella diga.
Si has llegado hasta aquí porque estás en medio del problema y quieres que alguien lo mire, reviso el IVA de una tienda por un precio cerrado. Y si prefieres arreglarlo tú, con los tres pedidos de prueba de arriba tienes casi todo lo que hace falta.