PHP / MariaDB - Numéros de facture

a marqué ce sujet comme résolu.

Bonjour à tous.

Je voudrai avoir quelques conseils SVP car je vais bientôt attaquer mon 1er site e-commerce (en PHP / MariaDB).

Quel est le meilleur moyen de générer les numéros de facture (pour qu’il n’y ai jamais de conflit dans la BDD) ?

J’avais dans un premier temps pensé mettre dans ma table des factures (order_invoices) une colonne int number. Et en PHP lors de la création d’une nouvelle facture faire comme ceci (exemple avec Eloquent de Laravel) :

$lastNumber = OrderInvoice::whereRaw(
        'number = (
            SELECT MAX(number) FROM order_invoices
        )'
    )
    ->first()
    ->number;

// et ensuite je fait un INSERT de la nouvelle facture en assigneant à "number" le résultat "$lastNumber + 1".

Mais après réflexion, je ne suis pas certain que ça soit la meilleure solution (j’utilise les transactions donc si fort trafic sur le site et que plusieurs membres valident une commande en même temps… risque de conflit dans l’incrémentation des numéros de facturation ?).

Un développeur que je connais, m’avais conseillé de par exemple créer une table compteurs. Et dans cette table :

Mettre comme colonne : id, number (c’est cette colonne qui sera incrémenté afin de savoir où on en est dans la numérotation), type (exemple : 'facture' pour incrémenter les numéros de facture, ou 'membres’ pour incrémenter les numéros de référence client, etc.)

Mettre une ligne pour "factures", et mettre un ligne pour "clients", etc.

Et dans mon programme (action de mon controller), pour la création d’une nouvelle facture :

De faire un lock row (sur la ligne de type type de la table compteurs) lors du début de la génération de la facture;

De récupérer number de la table compteurs, et cette valeur l’insérer (avec un +1) dans number de la table des factures (order_invoices);

Et de délocker la table compteurs;

Qu’en pensez-vous ? Et avez-vous d’autres idées et conseils SVP ?

Merci beaucoup.

+0 -0

Pour le côté comptable :

Numéro unique basé sur une séquence chronologique continue, sans rupture.

Exemple : facture 01, 02, 03

Il est cependant possible d’émettre des séries distinctes lorsque les conditions d’exercice de l’activité le justifient. L’entreprise peut utiliser un préfixe par année (2018-XX) ou par année et mois (2018–01-XX).

Par exemple, si celle-ci termine le mois de janvier avec une facture numérotée 25 :

Janvier : facture n°2018–01–025

Février : facture n°2018–02–026

À faire figurer sur toutes les pages de la facture

Service public

AUTO_INCREMENT ne te conviens pas?

Pour le côté comptable :

Numéro unique basé sur une séquence chronologique continue, sans rupture.

Exemple : facture 01, 02, 03

Il est cependant possible d’émettre des séries distinctes lorsque les conditions d’exercice de l’activité le justifient. L’entreprise peut utiliser un préfixe par année (2018-XX) ou par année et mois (2018–01-XX).

Par exemple, si celle-ci termine le mois de janvier avec une facture numérotée 25 :

Janvier : facture n°2018–01–025

Février : facture n°2018–02–026

À faire figurer sur toutes les pages de la facture

Service public

AUTO_INCREMENT ne te conviens pas?

A-312

Merci pour ta réponse, mais non ça ne me convient pas pour plusieurs raisons :

A chaque début de nouvelle année, le client veux recommencer la numérotation à zéro (du moins, à 1).

Et les membres pourront passer des commandes à plusieurs magasins (et chaque magasin aura un numéro distinct de facturation). Et dans la table compteurs je penser ajouter une ligne par magasin pour le type "facture".

+0 -0

Mais après réflexion, je ne suis pas certain que ça soit la meilleure solution (j’utilise les transactions donc si fort trafic sur le site et que plusieurs membres valident une commande en même temps… risque de conflit dans l’incrémentation des numéros de facturation ?).

stephweb

Les transactions sont l’une des forces d’une BDD relationnelle, ça serait vraiment dommage de s’en priver. C’est justement grâce à elles que tu peux éviter les conflits car elles peuvent éventuellement bloquer au besoin, et ainsi éviter les race.

En cas de fort trafic, tu n’as pas à t’en faire en principe, mais il y a quelques règles à respecter :

  • s’assurer d’avoir les bons tunings my.cnf, personne n’a de règles précises là-dessus malheureusement… C’est à tester avec ta charge typique, en jouant avec les valeurs et en benchmarquant… C’est fastidieux, mais tu peux t’en occuper quand tu auras de la charge ;
  • ne pas bloquer une transaction inutilement, entre le BEGIN TANSACTION et le COMMIT. Plus tôt tu COMMIT (ou ROLLBACK), mieux tu te portes. Concrètement, entre le BEGIN et le COMMIT, c’est pas une bonne idée que ton code PHP aille requêter une API externe par exemple ;) ;
  • Enfin, le niveau d’isolation est à prendre en compte, surtout si éviter les conflits est primordial. Certain seront bloquants, d’autres non : https://mariadb.com/kb/en/library/set-transaction/#isolation-levels

J’espère que ça t’apporte quelques pistes !

+0 -0

Salut,

Le soucis avec de l’incrémentation pour un numéro de commande, c’est le fait de pouvoir "deviner" des numéros de commande, en plus de savoir à la louche combien de commandes ont été faites. Ce qui n’est jamais très bon.

Pour moi le mieux c’est de générer un numéro de commande pseudo aléatoirement, en respectant toujours le même pattern. C’est une problématique que j’ai rencontré au boulot, et c’est ce que j’ai fait. Cela me permet d’avoir des numéros de commande ayant toujours le même nombre de caractères, contenant des blocks séparés par des "-". Je trouve ça plus propre pour le client qu’une simple incrémentation.

+0 -0

Merci à tous pour vos réponses.

Salut,

Le soucis avec de l’incrémentation pour un numéro de commande, c’est le fait de pouvoir "deviner" des numéros de commande, en plus de savoir à la louche combien de commandes ont été faites. Ce qui n’est jamais très bon.

Pour moi le mieux c’est de générer un numéro de commande pseudo aléatoirement, en respectant toujours le même pattern. C’est une problématique que j’ai rencontré au boulot, et c’est ce que j’ai fait. Cela me permet d’avoir des numéros de commande ayant toujours le même nombre de caractères, contenant des blocks séparés par des "-". Je trouve ça plus propre pour le client qu’une simple incrémentation.

John

Ok merci, et pour les numéros de facture, tu y gère comment ?

Et utiliser l’id n’est vraiment pas bon pour des numérotations (surtout pour des factures). Imaginons qu’on utilise MySQL ou MariaDB et qu’on utilise les transaction (ce que je fait), et qu’un membre valide une commande et que la transaction échoue pour lui, et que juste après un autre membre valide sa commande et qu’avec lui la transaction n’échoue pas : le résultat est qu’on aura un trou dans le numérotation (exemple : l’id passera de 100 à 102, la facture numéro 101 sera donc manquant, et en France on a pas le droit d’avoir des trous).

Et même, si un client veux importer (via Excel par exemple) dans la BDD des factures déjà existante et qu’il souhaite garder sa série de numérotation avec le même préfixe, en utilisant l’ID on est grillé.

+0 -0

Imaginons qu’on utilise MySQL ou MariaDB et qu’on utilise les transaction (ce que je fait), et qu’un membre valide une commande et que la transaction échoue pour lui, et que juste après un autre membre valide sa commande et qu’avec lui la transaction n’échoue pas : le résultat est qu’on aura un trou dans le numérotation (exemple : l’id passera de 100 à 102, la facture numéro 101 sera donc manquant, et en France on a pas le droit d’avoir des trous).

Si tu commences ta transaction avant d’aller chercher le numéro de facture, tu n’auras pas ce soucis.

Imaginons qu’on utilise MySQL ou MariaDB et qu’on utilise les transaction (ce que je fait), et qu’un membre valide une commande et que la transaction échoue pour lui, et que juste après un autre membre valide sa commande et qu’avec lui la transaction n’échoue pas : le résultat est qu’on aura un trou dans le numérotation (exemple : l’id passera de 100 à 102, la facture numéro 101 sera donc manquant, et en France on a pas le droit d’avoir des trous).

Si tu commences ta transaction avant d’aller chercher le numéro de facture, tu n’auras pas ce soucis.

A-312

Je disais ceci pour ceux qui utilisent l’ID (auto incrément) comme numéro de facture. Et qui affichent l’ID en tant que numéro de facture.

+0 -0

Merci à tous pour vos réponses.

Salut,

Le soucis avec de l’incrémentation pour un numéro de commande, c’est le fait de pouvoir "deviner" des numéros de commande, en plus de savoir à la louche combien de commandes ont été faites. Ce qui n’est jamais très bon.

Pour moi le mieux c’est de générer un numéro de commande pseudo aléatoirement, en respectant toujours le même pattern. C’est une problématique que j’ai rencontré au boulot, et c’est ce que j’ai fait. Cela me permet d’avoir des numéros de commande ayant toujours le même nombre de caractères, contenant des blocks séparés par des "-". Je trouve ça plus propre pour le client qu’une simple incrémentation.

John

Ok merci, et pour les numéros de facture, tu y gère comment ?

stephweb

En gros, je prends l’année au format YYYY, le mois au format MM, le jour au format DD, je tire x lettres en aléatoire. Je mélange un peu tout ça (par exemple les commandes commencent toujours par le 1er chiffre de l’année, suivi du premier chiffre du jour et d’un caractère alphabétique random, un tiret, ensuite le 4e chiffre de l’année suivi de…1). Avec un peu de réflexion, il est possible de sortir un numéro unique (si tant est qu’on n’a pas 1 million de commandes par jour…).


  1. Je ne mets volontairement pas mon algorithme exact, mais c’est l’idée.

+0 -0

Merci à tous pour vos réponses.

Salut,

Le soucis avec de l’incrémentation pour un numéro de commande, c’est le fait de pouvoir "deviner" des numéros de commande, en plus de savoir à la louche combien de commandes ont été faites. Ce qui n’est jamais très bon.

Pour moi le mieux c’est de générer un numéro de commande pseudo aléatoirement, en respectant toujours le même pattern. C’est une problématique que j’ai rencontré au boulot, et c’est ce que j’ai fait. Cela me permet d’avoir des numéros de commande ayant toujours le même nombre de caractères, contenant des blocks séparés par des "-". Je trouve ça plus propre pour le client qu’une simple incrémentation.

John

Ok merci, et pour les numéros de facture, tu y gère comment ?

stephweb

En gros, je prends l’année au format YYYY, le mois au format MM, le jour au format DD, je tire x lettres en aléatoire. Je mélange un peu tout ça (par exemple les commandes commencent toujours par le 1er chiffre de l’année, suivi du premier chiffre du jour et d’un caractère alphabétique random, un tiret, ensuite le 4e chiffre de l’année suivi de…1). Avec un peu de réflexion, il est possible de sortir un numéro unique (si tant est qu’on n’a pas 1 million de commandes par jour…).

1: Je ne mets volontairement pas mon algorithme exact, mais c’est l’idée.

John

Ok. Mais les numéros de factures doivent obligatoirement se suivre (de manière incrémenté sans trou) en France.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte