Numérotation de facture conditionelle

  • Posts: 508
  • Thank you received: 36
  • Hikaserial Subscription Hikashop Business
1 week 1 hour ago #370295

-- HikaShop version -- : 6.0.0
-- Joomla version -- : 5.3.1
-- PHP version -- : 8.3.16

Bonjour,

J'ai besoin, dans certains cas, de ne pas incrémenter la numérotation de facture même si la commande est confirmée.

Pouvez vous m'indiquer la meilleure piste svp :
1. Remettre order_invoice_id à 0 après la validation et vider order_invoice_number pour que la suivante reprenne sans trou de numérotation, risques de bugs selon la facon dont est généré l'id ? (MAX(invoice_id)+1 est t'il utilisé ?)
2. Dissocier order_invoice_id et order_invoice_number dans onBeforeInvoiceNumberGenerate pour ne me servir que de order_invoice_number dans les documents
3. Une meilleure solution ?

Merci d'avance

Last edit: 1 week 1 hour ago by Minie.

Please Log in or Create an account to join the conversation.

  • Posts: 85103
  • Thank you received: 13871
  • MODERATOR
6 days 21 hours ago #370300

Bonjour,

Pour vous conseiller la meilleure solution, il faudrait que vous m'en disiez plus sur la situation. Quel est le but ? Quelle condition voulez-vous appliquer ?
MAX(invoice_id)+1 est en effet utilisé, mais l'option "invoice reset frequency" permet de ne prendre en compte que les order_invoice_id à partir d'un certain moment.
onBeforeInvoiceNumberGenerate est en effet utilisable.
onBeforeOrderUpdate est également utilisable.

Please Log in or Create an account to join the conversation.

  • Posts: 508
  • Thank you received: 36
  • Hikaserial Subscription Hikashop Business
6 days 20 hours ago #370305

Merci pour votre retour.

Contexte précis :
Sur notre marketplace, une commande peut contenir des produits de deux types de producteurs (manufacturer chacun attaché à un warehouse) :
1. Producteurs “warehouse = 1” : les produits sont facturés par la marketplace (facture client unique).
2. Producteurs “warehouse ≠ 1” : chaque producteur doit émettre sa propre facture client pour ses produits. (géré par mon code pas de souci la dessus)

Cas à gérer :
1. Commande 100 % warehouse = 1
→ 1 facture client marketplace, numérotation normale native
2. Commande 100 % warehouse ≠ 1
→ Aucune facture marketplace ne doit être créée
→ uniquement des factures clients producteur gérées par mon code sans toucher au champ invoice_id ou invoice number
3. Commande mixte (warehouse = 1 + warehouse ≠ 1)
→ 1 facture client marketplace, comportement natif hikashop
→ + factures clients producteur pour les produits non-warehouse (gérées par mon code)

Problème :
Dans le cas 2, la commande est confirmée mais ne doit pas consommer de numéro de facture marketplace, afin d’éviter des trous dans la numérotation légale de la marketplace.

Constat :
- onBeforeInvoiceNumberGenerate permet bien de remplacer le numéro, mais l’order_invoice_id est quand même généré (MAX+1).
- Modifier order_invoice_id a posteriori fonctionne en test, mais semble risqué car c’est un identifiant interne qui pourrait être appelé ailleurs par hikashop ?

Question :
Quelle est selon vous la meilleure approche propre et supportable pour :
- empêcher la consommation d’un numéro de facture marketplace dans le cas 2
- tout en conservant une numérotation continue pour les factures marketplace,
- sans risquer d’effets de bord internes ?

Merci d’avance.

Please Log in or Create an account to join the conversation.

  • Posts: 85103
  • Thank you received: 13871
  • MODERATOR
6 days 7 hours ago #370308

Bonjour,

J'ai bien étudié votre cas d'utilisation et voici, je pense la meilleure approche pour votre marketplace.

L'événement onBeforeInvoiceNumberGenerate ne peut effectivement que modifier le numéro de facture, mais pas empêcher la génération de l'order_invoice_id. C'est pourquoi vous constatez que l'ID est consommé.

La solution recommandée est d'utiliser l'événement onBeforeOrderUpdate pour empêcher complètement la génération de l'invoice_id dans le cas 2 (100% warehouse ≠ 1).

Voici comment procéder :

Dans votre plugin, implémentez la fonction onBeforeOrderUpdate :

function onBeforeOrderUpdate(&$order, &$do) {
    // Vérifiez d'abord si on est sur un changement de statut vers un statut de facturation
    $config = hikashop_config();
    $valid_statuses = explode(',', $config->get('invoice_order_statuses','confirmed,shipped'));
    
    // Si le nouveau statut n'est pas un statut de facturation, on ne fait rien
    if(empty($order->order_status) || !in_array($order->order_status, $valid_statuses))
        return;
    
    // Vérifiez si on a déjà un invoice_id (rien à faire dans ce cas)
    if(!empty($order->order_invoice_id) || !empty($order->old->order_invoice_id))
        return;
    
    // Chargez les produits de la commande si nécessaire
    $orderClass = hikashop_get('class.order');
    $fullOrder = $orderClass->loadFullOrder($order->order_id, false, false);
    
    // Vérifiez si tous les produits sont warehouse ≠ 1
    $all_external = true;
    if(!empty($fullOrder->products)) {
        foreach($fullOrder->products as $product) {
            // Récupérez le warehouse du produit (adaptez selon votre logique)
            if($product->product_warehouse_id == 1) {
                $all_external = false;
                break;
            }
        }
    }
    
    // Si 100% externe (warehouse ≠ 1), empêchez la facturation HikaShop
    if($all_external) {
        // Définir ces valeurs empêche la génération automatique de l'invoice
        $order->order_invoice_id = -1; // Valeur spéciale pour marquer "pas de facture"
        $order->order_invoice_number = ''; // Ou une valeur vide
        $order->order_invoice_created = 0;
    }
}
Après la sauvegarde de la commande, vous pouvez utiliser onAfterOrderUpdate pour remettre order_invoice_id à 0 si vous avez utilisé -1 :
function onAfterOrderUpdate(&$order, &$send_email) {
    if(isset($order->order_invoice_id) && $order->order_invoice_id == -1) {
        // Réinitialisez dans la base de données
        $db = JFactory::getDBO();
        $db->setQuery('UPDATE '.hikashop_table('order').' SET order_invoice_id = 0, order_invoice_number = "", order_invoice_created = 0 WHERE order_id = '.(int)$order->order_id);
        $db->execute();
        
        // Mettez à jour l'objet ordre aussi
        $order->order_invoice_id = 0;
        $order->order_invoice_number = '';
        $order->order_invoice_created = 0;
    }
}
Pourquoi cette approche ?
1. Elle empêche la consommation d'un numéro de facture pour les commandes 100% externes
2. Elle conserve la numérotation continue pour les factures marketplace
3. Elle n'a pas d'effets de bord car order_invoice_id = 0 est le comportement attendu pour une commande sans facture

Alternative plus simple :
Si vous préférez, vous pouvez simplement définir order_invoice_number (via onBeforeInvoiceNumberGenerate) à une valeur spéciale comme "EXTERNE" pour les commandes 100% warehouse ≠ 1, et les exclure de votre comptabilité marketplace. L'invoice_id sera consommé mais au moins vous aurez une trace claire.

Please Log in or Create an account to join the conversation.

  • Posts: 508
  • Thank you received: 36
  • Hikaserial Subscription Hikashop Business
4 days 8 hours ago #370336

Bonjour Nicolas,

Merci beaucoup, donc effectivement les deux approches sont possibles sans effet de bord c’est parfait.

Merci encore, belle journée

Please Log in or Create an account to join the conversation.

Time to create page: 0.060 seconds
Powered by Kunena Forum