Besoin de conseil pour une appli de facture en PHP Mysql [Résolu]

Signaler
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020
-
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020
-
Bonjour a tous,

Pour mes besoin personnel, j'ai eu a développer une application de facture. elle fonctionne très bien pour mon utilisation personnelle.

Cependant je souhaiterais trouver une solution pour une gestion multi-utilisateurs.

En gros je cherche une méthode pour pouvoir avoir plusieurs utilisateurs, qui auront a chaque fois un id qui commence a 0 pour leur factures.

Dois-je créer une basse de données pour chaque nouvelle personne? ça me semble compliqué.

je peux faire en sorte que chaque utilisateurs ne peut voir que ce qui lui appartient une fois connecté en filtrant par la session. Mais comment faire pour que chaque personne a un numéro de facture qui commence a 1. Dans la version actuelle peut importe le nom de l'utilisateur, les numéros s'incrémente a la suite vu qu'ils sont tous sur la même base.

ma base de données et faites comme ceci

Table Facture(c'est elle qui crée le numéro de facture)
ensuite d'autres table lui sont liés, (item, prix, accompte, promo, commentaires etc...) est c'est ce numéro "id_facture" qui relie les tables entre elle pour avoir les informations concernant chaque factures.

D'autres id relie par exemple la table item et la table prix, en plus de l'id_facture

J'ai pas trouvé sur internet de piste, pour avoir un compteur a "0" pour chaque nouveau utilisateur

Si quelqu'un pouvait m'aider je l'en remercie d'avance.

7 réponses

Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020
683
bonjour,
moi je ferais ainsi:
- id_facture globalement unique, utilisé en interne dans la base
- reference_facture, unique pour chaque utilisateur, visible sur les factures

if_facture peut être automatiquement assigné par le logiciel de base de données
reference_facture sera assigné par le programme qui crée la facture, par exemple, en cherchant d'abord la dernière valeur reference_facture pour cet utilisateur, ou sur base d'un champ de la table utilisateur. reference_facture pourrait être un texte, par exemple ABC2019-001.
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020

Sur un forum j'ai trouvé ça comme réponse.

"d'un point de vue légal, les numéros des factures doivent être séquentiels et uniques dans l'ensemble du système, et non une séquence pour chaque utilisateur/client. "

Faut voir par rapport a la loi, si ce n'est pas une obligation pour un utilisateur que les numéros de facture se suivent dans une applications mutualisés, si c'est le cas alors le problème ne se pose plus.

Le débat reste ouvert
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020

Merci je vais regarder ça, même si je suis pas sur d'avoir tout compris.
Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020
683
nous pourrions être plus précis si tu partageais ton code PHP de création d'une facture.
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020
>
Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020

Voila la page pour créer une facture

<?php
require_once('../inc/connexion.php');


if(isset($_POST['createInvoices'])) {
 $customers_id = ($_POST['id_customers']);
 $date_ouverture = htmlspecialchars($_POST['date_ouverture']);
 $titre = htmlspecialchars($_POST['titre']);
 $comments = htmlspecialchars($_POST['comments']);
 $type = ($_POST['type']);
 $annee = ($_POST['annee']);




 if(!empty($_POST['id_customers'])   AND !empty($_POST['date_ouverture'])  AND !empty($_POST['date_debut']) AND !empty($_POST['date_echeance']) AND !empty($_POST['titre']) AND !empty($_POST['comments'])AND !empty($_POST['type'])AND !empty($_POST['annee']));


 $db = getDB();


    // insertion dans la table invoice pour avoir l'id et y inclure l'id client (customers_id)
 $insertmbr = $db->prepare("INSERT INTO invoice ( customers_id ) VALUES(:customers_id)");
 $insertmbr->bindParam("customers_id", $customers_id,PDO::PARAM_INT) ;    
 $insertmbr->execute();
    
    // récupérations de l'id inséré précédemment
 $insertmbr = $db->query("  SELECT id_invoice  FROM invoice WHERE id_invoice = (SELECT MAX(id_invoice) FROM invoice)  ");
 $donnees = $insertmbr->fetch();
                  //  echo $donnees['id_invoice'];

    //insertion de l'id récupérer
 $accompte_id=$donnees['id_invoice'];
 $insertmbr = $db->prepare("INSERT INTO accompte (accompte_id) VALUES(:accompte_id)");
 $insertmbr->bindParam("accompte_id", $accompte_id,PDO::PARAM_INT) ;
 $insertmbr->execute(); 

    //insertion de l'id récupérer
 $comments_id=$donnees['id_invoice'];
 $insertmbr = $db->prepare("INSERT INTO comments (comments_id , titre, comments) VALUES(:comments_id, :titre, :comments)");
 $insertmbr->bindParam("comments_id", $comments_id,PDO::PARAM_INT) ;
 $insertmbr->bindParam("titre", $titre,PDO::PARAM_STR) ;
 $insertmbr->bindParam("comments", $comments,PDO::PARAM_STR) ;
 $insertmbr->execute(); 

    //insertion de l'id récupérer
 $statut_id=$donnees['id_invoice'];
 $insertmbr = $db->prepare("INSERT INTO statut (statut_id, type, date_ouverture, annee) VALUES(:statut_id, :type, :date_ouverture, :annee )");
 $insertmbr->bindParam("statut_id", $statut_id,PDO::PARAM_INT) ;
 $insertmbr->bindParam("type", $type,PDO::PARAM_INT) ;
 $insertmbr->bindParam("date_ouverture", $date_ouverture,PDO::PARAM_STR) ;
 $insertmbr->bindParam("annee", $annee,PDO::PARAM_INT) ;
 $insertmbr->execute();

 
 header('Location: ../form/facture.php?id_invoice='.$donnees["id_invoice"].'');

}

Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020
683 >
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020

dans ton explication, tu parles de table nommée facture, tandis que dans ton code, elle semble s'appeler invoice.
merci d'être factuel et précis.

je pense utile que tu décides ce que tu fais avec ma suggestion en #2 avant d"aller plus loin.
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020

je suis en train d'angliciser petit a petit mon appli, au début la table invoice s'apellait facture.
Je ne suis pas contre d'utiliser ta suggestion en#2, mais j'ai pas tout compris.

Pour être clair, il faudrait que le id_invoice démarre a 1 pour chaque nouvel utilisateur et qu'il s'insère dans les autres tables, cela voudrait dire qu'il y aurait plusieurs fois le même id_invoice dans les autres tables, mais ça ce n'est pas le pb, le filtrage pourra se faire par la session (je n'ai pas encore fait cette partie, je n'ai pas encore fait le système authentification).

mon problème c'est comment depuis la table Invoice je pourrais avoir l' id_invoice qui recommence a 1 pour chaque nouvel utilisateur vu que le numéro s'incrémente automatiquement. Je pourrais pour chaque nouvel utilisateur la vider pour qu'elle recommence, mais c'est la table référence de l'appli c'est sur id_invoice de la table Invoice que tout est relié, je ne peut pas la vider ou l'effacer. Il faudrait peut-être une table d'appoint
Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020
683
j'explique autrement ma suggestion:
chaque facture aurait une identification technique, id_invoice, globalement unique, utilisée en interne dans la base, invisible pour les utilisateurs, un numéro qui s'incrémente automatiquement. ce champ sera la clé primaire de la table.

chaque facture a aussi un numéro de facture, invoice_number, unique pour chaque utilisateur, visible par les utilisateurs.
n°_facture n'est pas un champ qui s'incrémente automatiquement. quand le programme crée une nouvelle facture, il fait une requête pour déterminer le plus grand numéro de facture utilisé pour cet utilisateur, et, ensuite, calcule et enregistre le nouveau numéro de facture. pour garantir l'unicité, je suggère de créer une clé unique sur la combinaison des champs (customers_id, invoice_number). une autre solution serait d'avoir un champ next_invoice_number dans la table des utilisateurs.
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020
>
Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020

C'est une bonne idée, je préfère avoir un champs next_invoice_number dans la table des utilisateurs. la table Invoice aura son numéro qui s'incrémente que je n’utiliserais pas, il y aura aussi id_customers et next_invoice_number plus un identifiant de session utilisateurs.

Merci je vais tester tout ça
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020
>
Messages postés
12159
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
14 septembre 2020

Merci a toi ça fonctionne.
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020

Peut-être passer par une fonction PHP qui donne le numéro de référence l'équivalent de id_invoice au lieu que ce soit la table Invoice qui le donne et l'id_invoice de la table continue de s'incrémenter a l'infini? Ce sera pas lui qui sera utilisé mais c'est pas très clair
à éviter puisque ça complique le code et qu'il n'y a pas de raison pour laquelle un tel calcul (attribuer une id numérique) ne puisse se faire sur la base!
Et bon imaginez surtout la complexité(inutile puisque n'apporte rien) si dans le programme une facture est identifié une fois par un numéro(id de la table) et une autre fois par un autre(id qui n'a aucune valeur à part celle d'être arbitraire).
Bref votre solution Jules_2569 ne semble pas en être une puisque rajoute des opérations inutiles et ajoute un doublon d'une valeur déjà existante.

Côté base de données 2 choses -importantes- sont à prendre en compte(je pense que la question portant dessus la solution doit-être de la base):

_Une table comporte un champ unique et identifiant; sans ça impossible de le repérer (= pas de base si on sait pas comment identifier et ne pas confondre 2 lignes différentes d'une table).
Donc un identifiant numérique (à ne pas confondre avec l'identifiant naturel) me semble tout =à fait recommandé et je vois mal pourquoi il y aurait d'autres identifiants pour une facture(certes l'identifiant naturel pourrais être : date, article de la facture, acheteur de la facture....heure et secondes... mais cela fait beaucoup de clés étrangère pour un identifiant donc autant avoir ID facture un nombre entier unique et identifiant-(auto-incrémenté ou pas c'est un détail tant que chaque facture à un seul numéro et qu'il suffit à l'identifier!!!)- ).
Donc aucun soucis et pas besoin (surtout pas) d'ajouter de nouveaux numéros qui feraient perdre la valeur identifiants du champ!


_Un champ est(où doit-être) unique , indivisible(il ne peut être composé de 2 valeurs qui vont ensemble ou pas). Pour le rendre unique il est possible d'utiliser une clé étrangère(jointure de table) ainsi pour identifier une client son ID pourrais être :
nom + prénom + date de naissance(aucun n'est identifiant mais les 3 oui, sauf exception : la personne avec même nom prénom et date de naissance, ce qui est un autre débat: identifiant naturel VS numérique incrémenté ).

Ainsi pour identifier chaque client et ses factures il suffit de croiser les données:
  • Une table facture retient id et autres champs de la table
  • Une table client qui retient les informations des clients
  • Une table facture client qui associe à chaque facture un client, éventuellement compris/inclus dans les autres tables ce qui applique une contrainte dans un sens ou dans l'autre:
1/La table facture associe un client: un client peut exister sans facture, une facture ne peut pas exister sans client(id facture + id client sont des identifiants sur la table qui regroupe(joint) facture avec son client )
2/La table client associe une facture. Chaque client aura aussi les IDs des factures qui lui sont associés dans la table. Pour une infinité de calcul chaque client aura une infinité associé à sa table(risque important performance). Un client ne peut exister s'il n'a pas de facture. Une facture ne peut exister sans client puisque chaque client est associé à chaque facture.
3/ Une table qui regroupe facture et clients.
Inconvénient : une table de plus sinon aucun puisque à chaque facture il suffit d'ajouter l'identifiant client dans la table: des factures peuvent exister sans client et des clients sans facture. Passer par cette table sera obligatoire pour obtenir soit la facture soit le client selon ce que l'on veut.
Bref avant de partir sur du code il vaut mieux avoir une analyse (et conception) S.I. bien faite :)
Cela détermine les choix et nécessités à faire du côté technique. Bien sûr sur la base de données repose une partie importante du S.I. Ne pas alourdir le développement et garder l'intégrité des données se font en passant par une bonne conception de la base(MCD, MLD en méthode Merise) et en explorant toutes les potentialités du système.

On voit clairement que votre volonté de ne pas changer le programme vous freine dans une conception de la base de qualité:
"
En gros je cherche une méthode pour pouvoir avoir plusieurs utilisateurs, qui auront a chaque fois un id qui commence a 0 pour leur factures.

Dois-je créer une basse de données pour chaque nouvelle personne? ça me semble compliqué. "

Une table peut-être non ne base! Quel est le problème? Au contraire une base de données sert justement à ça: retenir des informations de matières sérielles et relationnelles mais ça vous force à refaire le programme derrière.
Hors comme l'ensemble(base et programme) ne sont pas optimisés(pour pas dire mal fait/propice à erreur et complexité/incomplet) vous gagnez en qualité.


Considérez l'univers du discours avec importance(les nécessités, fonctions pratiques et choix catégoriques pris pour votre base) et surtout définissez votre S.I. avec précision(sans oublier la persistance dans le temps et la capacité de pouvoir évoluer , toujours sur Merise c'est la dernière étape après des choix logiques/informatiques sur lesquels on n'a pas son mot à dire et la réflexion sur la portée du programme par rapport à la réalité humaine).

Vous avez des utilisateurs à retenir dans votre système en quoi rajouter une table est contraignant, ça me semblerais plutôt l'inverse d'une contrainte puisque pour retenir une liste d'utilisateur une base me paraît indispensable. La façon (table ou regroupements d'entités) dont vous le faites ne doit pas s'appuyer sur des bribes de programmes non faits pour évoluer et devenus obsolètes mais bien sur l'analyse de votre système d'information (SI) et de vos besoins , rien que ça.
Bon après il est absurde de ne pas avoir au moins 2 tables une client et une facture(voire 3) pour retenir ces 2 types d'informations. Comme décrit dans mon exemple la façon dont vous les retenez aura un impact sur tout votre S.I. : le choix de table de l'ex. 1) privilégie le champ client(son importance par rapport à l'organisation de vos données) , l'ex. 2)rend toute facture préalable à l'existence d'un client, et dans le cas 3)aucun n'est privilégié et chacun peut exister séparément(un client sans facture, une facture sans client ou être relié en étant enregistré dans la 3ème table).

Je n'ai pas décris le cas où client et facture serais retenus dans une même et unique table. Si ça peut paraître un avantage c'est une erreur manifeste(avec beaucoup de contraintes mais surtout d'autres problèmes liés à l'absence de logique qui doit être mise en place par plus de programmation donc une mauvaise façon de faire). Sinon on voit que pour 1, 2 et 3 les solutions sont porches mais correspondent chacune à un parti pris humain et une nécessité pratique (peut-on enregistrer des factures et des clients indépendamment et que cela implique t'il ? idem pour l'inverse?)...et là c'est à vous de voir selon vos nécessités et contraintes d'utilisation de données.

La solution 3 malgré ses contraintes opérationnelle me semble la mieux puisque permet une évolution des tables client et factures et permet de trier client comme facture indépendamment de l'autre mais si dans votre SI il convient d'avoir une obligation forte de l'un ou l'autre(client doit toujours avoir facture/facture à toujours un client) les autres choix peuvent être adaptés. Cela compliquera (ou plus précisément forcera à refaire tout le programme) en cas de perte de cette contrainte ou modification nécessité dans la table.


bref si vous pensez table PHP n'a pas grand chose à voir....au contraire c'est à lui de s'adapter et non l'inverse!
Messages postés
52
Date d'inscription
vendredi 13 décembre 2019
Statut
Membre
Dernière intervention
28 juillet 2020

Bonjour Lopard et merci d'avoir pris le temps de répondre.

La solution que je propose comme vous dites, n'en est pas a proprement parler une, c'était une réflexion. J'ai ouvert le sujet, si j'avais une solution je n'aurais pas eu besoin d'ouvrir le sujet sur un forum.

J'ai une table client, et une table facture (Invoice sur mon code), donc la situation correspond dans votre texte :

"Ainsi pour identifier chaque client et ses factures il suffit de croiser les données:

Une table facture retient id et autres champs de la table
Une table client qui retient les informations des clients"

C'est déjà le cas.

ça fonctionne bien pour une utilisation personnelle, dans ma table Invoice j'ai le numéro de facture et le numéro client, le numéro de facture est répercuter dans la table articles, promotions, acompte, paiements etc... le liens entre tout ça se fait par des croisements et ça fonctionne sans problèmes. Certes ce n'est pas en (MCD, MLD en méthode Merise) comme vous dites, mais ça fait le boulot, ça ne me dérange pas d'apprendre a le faire. Je reste tout a fait ouvert au discours.

Je pense que vous n'avez pas compris mon problème.

1 . Utilisation multi-utilisateur (ou chaque utilisateurs a ses propres clients).
2 . Chaque utilisateur facture ses clients
3 . Chaque nouvel utilisateur a besoin de commencer sa facturation par la facture N°1 pour des raisons légales
4 . La table référence c'est la table Invoice

Tout ça dans la même base de données.

Ne pas confondre utilisateurs et client.

Quand vous dites :

"On voit clairement que votre volonté de ne pas changer le programme vous freine dans une conception de la base de qualité"

parce que j'aurais écris cette phrase ci-dessous :

"En gros je cherche une méthode pour pouvoir avoir plusieurs utilisateurs, qui auront a chaque fois un id qui commence a 0 (c'est pas a 0 mais à 1 plutôt) pour leur factures.

Dois-je créer une base de données pour chaque nouvelle personne? ça me semble compliqué. "

Dans cette phrase je voulais dire, est-ce que pour chaque nouvel utilisateur, je dois créer une base de données avec toutes ses tables qui y sont associés, ma base de données a une quinzaine de table déja. C'est de ça que je parlais, c'est ingérable.

Je vous assure que n'ai aucune volonté de ne pas vouloir changer le programme.