# WooCommerce HPOS et une extension de comptabilité tierce : ce qui a cassé

> Le passage aux tables de commandes personnalisées a silencieusement changé le comportement de plusieurs hooks utilisés par un connecteur comptable. Inventaire des correctifs appliqués.

- Auteur : Clément Hadrot
- Publié le : 2025-11-02
- Mis à jour le : 2025-11-02
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/woocommerce-hpos-extension-comptabilite-hooks/

## L’essentiel

- save_post ne se déclenche plus sur les mises à jour de commande en HPOS
- wc_get_orders() remplace les WP_Query directes sur les commandes
- Les meta de commande passent par une table dédiée, pas wp_postmeta

« Aucune facture synchronisée depuis hier » : c'est le ticket qui a déclenché l'audit. Le client, un cabinet comptable qui synchronise les commandes WooCommerce vers son logiciel de gestion via une extension maison, avait simplement mis à jour WooCommerce vers une version où le stockage des commandes en tables personnalisées (High-Performance Order Storage, HPOS) était activé par défaut sur les nouvelles installations. Ce billet recense les hooks qui ont changé de comportement ; la migration HPOS elle-même, ses étapes et sa bascule progressive, a déjà été traitée dans un article dédié.

## Symptôme : la synchronisation s'arrête net

Le connecteur comptable s'appuyait sur le hook `save_post`, filtré sur le type de post `shop_order`, pour déclencher l'envoi de chaque commande modifiée vers l'API du logiciel comptable. En HPOS, les commandes ne sont plus des objets `post` : elles vivent dans des tables dédiées (`wp_wc_orders` et consorts), et `save_post` ne se déclenche donc plus du tout à leur sauvegarde.

## Diagnostic : quatre hooks à remplacer

| Ancien hook (post-based) | Équivalent HPOS | Remarque |
| --- | --- | --- |
| `save_post_shop_order` | `woocommerce_new_order` / `woocommerce_update_order` | Deux hooks distincts à couvrir, contre un seul auparavant. |
| `WP_Query` avec `post_type => shop_order` | `wc_get_orders()` | Fonctionne dans les deux modes, à privilégier systématiquement. |
| `get_post_meta( $order_id, ... )` | `$order->get_meta( ... )` | La lecture directe en base échoue silencieusement en HPOS. |
| `delete_post_meta` | `$order->delete_meta_data()` + `save()` | Nécessite un appel explicite à `save()` pour persister. |

> L'essentiel à retenir : save_post ne se déclenche plus sur les mises à jour de commande en HPOS ; wc_get_orders() remplace les WP_Query directes sur les commandes ; Les meta de commande passent par une table dédiée, pas wp_postmeta

## Correctif appliqué

Le connecteur a été réécrit autour des hooks natifs WooCommerce plutôt que des hooks WordPress génériques, ce qui a l'avantage de fonctionner que HPOS soit activé ou non, tant que la compatibilité est correctement déclarée par ailleurs :

```
add_action( 'woocommerce_update_order', 'wpm_sync_order_to_accounting' );
add_action( 'woocommerce_new_order', 'wpm_sync_order_to_accounting' );

function wpm_sync_order_to_accounting( int $order_id ): void {
    $order = wc_get_order( $order_id );

    if ( ! $order ) {
        return;
    }

    $payload = array(
        'reference' => $order->get_order_number(),
        'total'     => $order->get_total(),
        'client'    => $order->get_billing_email(),
        'vat'       => $order->get_meta( '_wpm_vat_number' ),
    );

    wpm_push_to_accounting_api( $payload );
}
```

La lecture des meta personnalisées, notamment le numéro de TVA intracommunautaire stocké par une autre extension, posait un problème supplémentaire : cette donnée était toujours écrite via `update_post_meta` par l'extension tierce, non mise à jour pour HPOS, ce qui l'envoyait dans `wp_postmeta` alors que la commande elle-même vivait désormais dans les nouvelles tables. La méthode `get_meta()` de WooCommerce gère heureusement cette compatibilité descendante de façon transparente, à condition que la déclaration de compatibilité HPOS de cette extension tierce soit correcte.

## Vérifier la compatibilité déclarée avant de migrer

Avant toute bascule HPOS sur un site avec des extensions tierces critiques, l'écran `WooCommerce > Réglages > Avancé > Fonctionnalités` affiche la liste des extensions incompatibles déclarées. Un connecteur qui n'a pas explicitement déclaré son support via `FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__ )` est traité par défaut comme potentiellement incompatible, ce qui bloque l'activation du mode HPOS tant que ce n'est pas corrigé ou ignoré manuellement.

> Sur un connecteur comptable, mieux vaut casser l'activation de HPOS que de laisser passer silencieusement une commande non synchronisée : la première option se voit immédiatement, la seconde coûte un rapprochement bancaire raté en fin de mois.

## Prévention pour les prochaines montées de version

1. Grep systématique de `shop_order`, `save_post` et `get_post_meta` sur tout connecteur avant chaque montée majeure de WooCommerce.
2. Ajout d'un environnement de recette avec HPOS activé, distinct de l'environnement de production encore en mode legacy.
3. Déclaration explicite de compatibilité dans l'extension, même si aucun problème n'est identifié immédiatement.

## En résumé

HPOS ne casse rien pour l'utilisateur final, mais déplace silencieusement le sol sous les pieds de toute extension qui accédait directement aux données de commande via les mécanismes WordPress génériques. Le passage par l'API WooCommerce officielle (`wc_get_order()`, méthodes de l'objet `WC_Order`) reste, et restera, le seul chemin réellement pérenne.
