From bf6655a534a6775d30cafa67bd801276bda1d98d Mon Sep 17 00:00:00 2001 From: polo Date: Tue, 13 Aug 2024 23:45:21 +0200 Subject: =?UTF-8?q?VERSION=200.2=20doctrine=20ORM=20et=20entit=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Latex.php | 19 +- src/files.php | 82 ++++---- src/functions.php | 123 ------------ src/latex_templates/location.php | 6 +- src/main.php | 53 ++++-- src/main_loop.php | 48 ++--- src/model/CESU.php | 66 ------- src/model/Clients.php | 168 ----------------- src/model/DB.php | 48 ----- src/model/DevisFactures.php | 215 --------------------- src/model/Locations.php | 127 ------------- src/model/Model.php | 313 ------------------------------ src/model/Prestations.php | 165 ---------------- src/model/StructTablesDB.php | 36 ---- src/model/doctrine-bootstrap.php | 31 +++ src/model/entities/CESU.php | 131 +++++++++++++ src/model/entities/Client.php | 314 +++++++++++++++++++++++++++++++ src/model/entities/Devis.php | 241 ++++++++++++++++++++++++ src/model/entities/Facture.php | 261 +++++++++++++++++++++++++ src/model/entities/Location.php | 209 ++++++++++++++++++++ src/model/entities/Prestation.php | 252 +++++++++++++++++++++++++ src/model/version 0.1/CESU.php | 66 +++++++ src/model/version 0.1/Clients.php | 168 +++++++++++++++++ src/model/version 0.1/DB.php | 48 +++++ src/model/version 0.1/DevisFactures.php | 215 +++++++++++++++++++++ src/model/version 0.1/Locations.php | 127 +++++++++++++ src/model/version 0.1/Model.php | 313 ++++++++++++++++++++++++++++++ src/model/version 0.1/Prestations.php | 159 ++++++++++++++++ src/model/version 0.1/StructTablesDB.php | 36 ++++ src/sections/1_customer.php | 46 ++--- src/sections/2_service.php | 103 +++++----- src/sections/3-1_windows.php | 6 +- src/sections/3_modify_data.php | 113 ++++++----- src/sections/4_get_document.php | 14 +- src/view/Zenity.php | 32 ++-- src/view/ZenitySetup.php | 37 ++-- 36 files changed, 2869 insertions(+), 1522 deletions(-) delete mode 100644 src/model/CESU.php delete mode 100644 src/model/Clients.php delete mode 100644 src/model/DB.php delete mode 100644 src/model/DevisFactures.php delete mode 100644 src/model/Locations.php delete mode 100644 src/model/Model.php delete mode 100644 src/model/Prestations.php delete mode 100644 src/model/StructTablesDB.php create mode 100644 src/model/doctrine-bootstrap.php create mode 100644 src/model/entities/CESU.php create mode 100644 src/model/entities/Client.php create mode 100644 src/model/entities/Devis.php create mode 100644 src/model/entities/Facture.php create mode 100644 src/model/entities/Location.php create mode 100644 src/model/entities/Prestation.php create mode 100644 src/model/version 0.1/CESU.php create mode 100644 src/model/version 0.1/Clients.php create mode 100644 src/model/version 0.1/DB.php create mode 100644 src/model/version 0.1/DevisFactures.php create mode 100644 src/model/version 0.1/Locations.php create mode 100644 src/model/version 0.1/Model.php create mode 100644 src/model/version 0.1/Prestations.php create mode 100644 src/model/version 0.1/StructTablesDB.php (limited to 'src') diff --git a/src/Latex.php b/src/Latex.php index f7f18ea..b254551 100644 --- a/src/Latex.php +++ b/src/Latex.php @@ -5,12 +5,12 @@ abstract class Latex { - protected $type = ''; - protected $file_name = ''; - protected $latex_path = ''; - protected $pdf_path = ''; - protected $data = []; // données à insérer dans le template - protected $latex = ''; // latex pur + protected string $type; + protected string $file_name; + protected string $latex_path; + protected string $pdf_path; + protected array $data = []; // données à insérer dans le template + protected string $latex; // latex pur static function makeInstance(string $type) { @@ -98,16 +98,13 @@ abstract class Latex abstract class PrestaLatex extends Latex { - protected $Date; // sera un type "Dates" - - //~ public function __construct() - //~ {} + protected Dates $Date; public function setData(Object $Object): self { $this->data = array_merge($this->data, $Object->getAll()); // nécessite des tableaux associatifs - if(get_class($Object) === 'Prestations') + if(get_class($Object) === 'Prestation') { $this->file_name = $Object->getCodePresta() . '.tex'; $this->makeDateInstance($Object->getDate()); // paramètre = int diff --git a/src/files.php b/src/files.php index 0bda901..ad20ee0 100644 --- a/src/files.php +++ b/src/files.php @@ -5,53 +5,58 @@ function makeFile($path, $file_name, $data) { - //~ if(is_writable('../' . $path)) + //~ if(is_writable('../' . $path)) //~ { - file_put_contents($path. $file_name, $data); - chmod($path . $file_name, 0644); // droits en octal - //~ } - + file_put_contents($path. $file_name, $data); + chmod($path . $file_name, 0644); // droits en octal + //~ } + //~ protected function createFile(string $latex, string $file_name, string $latexPath) //~ { - //~ // nom du fichier créé = nom.tex - //~ // pour les devis, factures et enveloppes, le nom est le code la prestation - //~ // pour les livre de recettes et registres des achats mensuels: - //~ // le nom du fichier suit cet exemple: "Recettes-2022-06-Juin.tex" - //~ // pour le livre de recette ou le registre des achats annuel, même principe: "Achats-2022.tex" - //~ // pour le bilan comptable annuel, ça donne: "Bilan-2022.tex" - //~ $fichier = fopen($latexPath . $file_name, "w+"); - //~ fputs($fichier, $latex); - //~ fclose($fichier); + //~ // nom du fichier créé = nom.tex + //~ // pour les devis, factures et enveloppes, le nom est le code la prestation + //~ // pour les livre de recettes et registres des achats mensuels: + //~ // le nom du fichier suit cet exemple: "Recettes-2022-06-Juin.tex" + //~ // pour le livre de recette ou le registre des achats annuel, même principe: "Achats-2022.tex" + //~ // pour le bilan comptable annuel, ça donne: "Bilan-2022.tex" + //~ $fichier = fopen($latexPath . $file_name, "w+"); + //~ fputs($fichier, $latex); + //~ fclose($fichier); //~ } } +//~ function deleteFile($path, $file_name) +//~ { + //~ unlink() +//~ } + function makeFolder(string $path) { - $rights = 0755; // droits en octal - + $rights = 0755; // droits en octal + if(!file_exists($path)) { - //~ if(is_writable('../' . $path)) - //~ { - mkdir($path); - chmod($path, $rights); - //~ } - //~ else - //~ { - //~ echo "debug: la création du dossier " . $path . " est impossible\n"; - //~ } + //~ if(is_writable('../' . $path)) + //~ { + mkdir($path); + chmod($path, $rights); + //~ } + //~ else + //~ { + //~ echo "debug: la création du dossier " . $path . " est impossible\n"; + //~ } } else { - //~ if(is_writable($path)) - //~ { - chmod($path, $rights); - //~ } - //~ else - //~ { - //~ echo "debug: la modification des droits du dossier " . $path . " est impossible\n"; - //~ } - } + //~ if(is_writable($path)) + //~ { + chmod($path, $rights); + //~ } + //~ else + //~ { + //~ echo "debug: la modification des droits du dossier " . $path . " est impossible\n"; + //~ } + } } // commande système pdflatex @@ -75,6 +80,15 @@ function latexToPdf(string $latex_path, string $file_name, string $pdf_path) unlink($pdf_path . $basename . '.log'); } +// équivalent de la commande mv +function renameFiles(Object $Object, string $old_code, string $new_code) +{ + rename($Object->getLatexPath() . $old_code . '.tex', + $Object->getLatexPath() . $new_code . '.tex'); + rename($Object->getPdfPath() . $old_code . '.pdf', + $Object->getPdfPath() . $new_code . '.pdf'); +} + function makeTexAndPdf(Object $Object) // paramètre = enfant de Latex { if(get_class($Object) !== 'EnveloppeVersoLatex') diff --git a/src/functions.php b/src/functions.php index 47cea42..d9fbfca 100644 --- a/src/functions.php +++ b/src/functions.php @@ -1,7 +1,5 @@ stdout pour cacher un message inutile return $command; } - -function enterCustomer($Client): bool -{ - // fenêtre - $NouveauClient = new ZenityForms(ZenitySetup::$nouveau_client['text'], ZenitySetup::$nouveau_client['entrees']); - - $input = exec($NouveauClient->get()); - if($input == '') - { - echo "debug: annulation lors de l'enregistrement d'un nouveau client\n"; - return false; - } - if(!$Client->hydrateFromForm($input)) - { - // messages d'erreur dans hydrateFromForm() - return false; - } - unset($input); - - $Client->create(); // écrire dans la base - $Client->setId(); // sans paramètre, exécute un $this->db->lastInsertId() - - return true; -} - -function makeObjectClient() -{ - // fenêtres - $RechercheClient = new zenityEntry(ZenitySetup::$recherche_client_text); - $ResultatsRechercheClient = new ZenityList(ZenitySetup::$resultats_recherche_client_text, []); - - $Client = new Clients; - - $input = exec($RechercheClient->get()); - if($input == '') - { - echo "debug: recherche annulée ou saisie vide\n"; - return 0; - } - - echo "debug: recherche effectuée\n"; - $ResultatsRechercheClient->setListRows( - searchCustomer($input, $Client), - count(StructTablesDB::$structureOfTables[$Client->getTable()])); // 2è paramètre = nombre de colonnes - - // sélection parmi les résultats - $input = exec($ResultatsRechercheClient->get()); // renvoie l'ID de la table 'clients' - $ResultatsRechercheClient->cleanCommand(); - - if($input == '') - { - echo "debug: client pas trouvé ou pas sélectionné\n"; - return 0; - } - - echo "debug: client sélectionné\n"; - $Client->setId($input); - $Client->hydrate($Client->findById()); - - return $Client; -} - -// NOTE 1: en PHP les objets sont passés aux fonctions par référence par défaut, toutefois ce n'est pas entièrement vrai -// NOTE 2: PHP n'a pas de pointeur mais des références, une référence est un alias qui ne contient pas l'objet lui-même -// NOTE 3: la variable créée lors d'un "new" est elle-même une référence contenant un identifiant (= le pointeur?) -// NOTE 4: l'objet est détruit lorsque la dernière référence est supprimée - -function searchCustomer(string $input, Clients $Client): array -{ - $input_array = explode(' ', $input); // si plusieurs mot, on les recherche tous l'un après l'autre - $result = $Client->findByKeywords($input_array, 'prenom_nom'); // on obtient un tableau à deux dimensions avec les entrées trouvées - //var_dump($result); - return($result); -} - - -function getServices(Clients $Client, string $type = '') -{ - echo "debug: recherche d'une prestation\n"; - - // on recherche les ID des prestas dans la table 'prestations' avec 'id_client' - $Presta = new Prestations($Client->getId()); - $Presta->setTypePresta($type); - $IDs = $Presta->getIdsByIdClient(); // comportement différent si le type est connu - unset($Presta); - - // mettres toutes les données dans un tableau - $PrestaList = []; - foreach($IDs as $id) - { - $PrestaList[$id] = new Prestations($Client->getId()); // renseigne 'id_client' - $PrestaList[$id]->setId($id); // ID de la prestation = clé du tableau - $PrestaList[$id]->hydrate($PrestaList[$id]->findById()); // données copiés de la table à l'objet - } - - // fenêtre - $entrees = []; - foreach($PrestaList as $Presta) - { - $id = $Presta->getId(); - $entrees[$id][] = $id; - $Date = new Dates((int)$Presta->getDate()); // envoi du timestamp, (int) est là par sécurité - $entrees[$id][] = $Date->getDate(); - $entrees[$id][] = $Presta->getTypePresta(); - $entrees[$id][] = $Presta->getCodePresta(); - } - $ResultatsRecherchePresta = new ZenityList(ZenitySetup::$resultats_recherche_presta_text, []); - $ResultatsRecherchePresta->setListRows($entrees, 4); - - // choix de l'utilisateur - $input = exec($ResultatsRecherchePresta->get()); // $input est l'ID de la prestation - if($input == '') - { - echo "debug: recherche annulée ou saisie vide\n"; - return 0; - } - else - { - return $PrestaList[$input]; - } -} diff --git a/src/latex_templates/location.php b/src/latex_templates/location.php index 4b6cfcb..3c9eefc 100644 --- a/src/latex_templates/location.php +++ b/src/latex_templates/location.php @@ -5,9 +5,9 @@ if($data['valeur'] != 0) { $data['valeur'] = ((string) $data['valeur']) . '€'; } -if($data['loyer_mensuel'] != 0) +if($data['loyer_hebdo'] != 0) { - $data['loyer_mensuel'] = ((string) $data['loyer_mensuel']) . '€'; + $data['loyer_hebdo'] = ((string) $data['loyer_hebdo']) . '€'; } ob_start(); @@ -74,7 +74,7 @@ ob_start(); CLAUSES\\ Durée du prêt : \textcolor{vert}{}\\ - Loyer mensuel : \textcolor{vert}{}\\ + Loyer mensuel : \textcolor{vert}{}\\ \textbf{Le bénéficiaire de cette location s’engage à prendre soin du bien désigné et à en faire un usage strictement personnel.}\\ diff --git a/src/main.php b/src/main.php index 4dfdaab..45f6c43 100644 --- a/src/main.php +++ b/src/main.php @@ -2,11 +2,10 @@ // src/main.php //require('model/File.php'); // utilité d'une classe File? -require('src/files.php'); -require('src/functions.php'); +require 'src/files.php'; // configuration de l'utilisateur -require('src/Config.php'); // lit le config.ini et gère certaines erreurs (exemple les / aux chemins manquants) +require 'src/Config.php'; // lit le config.ini et gère certaines erreurs (exemple les / aux chemins manquants) Config::readFile('config/config.ini'); Config::hydrate(); // et à coder peut-être plus tard @@ -27,11 +26,32 @@ $sqlitebrowser_enable = false; $sqlite_cli = ''; // commande sqlite ou sqlite3 $x_term_command = ''; // commande terminal en mode graphique -require('src/dependances.php'); // vérification des dépendances -require('src/Dates.php'); // gère dates et timestamps +require 'src/dependances.php'; // vérification des dépendances +require 'src/Dates.php'; // gère dates et timestamps Dates::$date_format = Config::$date_format; // dates européennes ou américaines -require('src/model/DB.php'); // connexion en héritant de PDO +// entités doctrine +require 'src/model/doctrine-bootstrap.php'; +include 'src/model/entities/Client.php'; +include 'src/model/entities/Prestation.php'; +include 'src/model/entities/Devis.php'; +include 'src/model/entities/Facture.php'; +include 'src/model/entities/CESU.php'; +include 'src/model/entities/Location.php'; + +// utiliser plus tard de nouvelles classes Manager au lieu des entités +// ET les faire hériter d'un unique parent +Client::$entityManager = $entityManager; +Prestation::$entityManager = $entityManager; +Devis::$entityManager = $entityManager; +Facture::$entityManager = $entityManager; +CESU::$entityManager = $entityManager; +Location::$entityManager = $entityManager; + +require 'src/functions.php'; + + +/*require('src/model/DB.php'); // connexion en héritant de PDO // création du DSN à mettre ailleurs (dans Model?) DB::$dsn = 'sqlite:' . Config::$db_path; // Data Source Name = 1er paramètre du constructeur de PDO: $bdd = new PDO($dsn); @@ -43,17 +63,18 @@ require('src/model/Clients.php'); require('src/model/Prestations.php'); require('src/model/DevisFactures.php'); require('src/model/CESU.php'); -require('src/model/Locations.php'); +require('src/model/Locations.php');*/ + -require('src/view/Zenity.php'); // générer ler commandes système zenity -require('src/view/ZenitySetup.php'); // texte dans les fenêtres ET instanciation (un objet = une commande) +require 'src/view/Zenity.php'; // générer ler commandes système zenity +require 'src/view/ZenitySetup.php'; // texte dans les fenêtres ET instanciation (un objet = une commande) -require('src/Latex.php'); // générer le code LaTeX +require 'src/Latex.php'; // générer le code LaTeX // boucle principale -require('src/sections/1_customer.php'); -require('src/sections/2_service.php'); -require('src/sections/3_modify_data.php'); -require('src/sections/4_get_document.php'); -require('src/sections/5_view_data.php'); -require('src/main_loop.php'); // action !! +require 'src/sections/1_customer.php'; +require 'src/sections/2_service.php'; +require 'src/sections/3_modify_data.php'; +require 'src/sections/4_get_document.php'; +require 'src/sections/5_view_data.php'; +require 'src/main_loop.php'; // action !! diff --git a/src/main_loop.php b/src/main_loop.php index 645a7ee..8dac901 100644 --- a/src/main_loop.php +++ b/src/main_loop.php @@ -12,7 +12,7 @@ while($main_loop) if($section[0] === 0) { echo("Menu principal\n"); - $MenuPrincipal = new ZenityList(ZenitySetup::$menu_principal_text, ZenitySetup::$menu_principal_entrees); + $MenuPrincipal = new ZenityList(ZenitySetup::$menu_principal['text'], ZenitySetup::$menu_principal['entrees']); $choix_niv1 = exec($MenuPrincipal->get()); } else @@ -23,58 +23,58 @@ while($main_loop) // comparaison du retour de $MenuPrincipal->get() avec les noms des entrées du même menu // -- SECTION 1: Clients et prospects -- - if($choix_niv1 === ZenitySetup::$menu_principal_entrees[0] || $section[0] === 1) + if($choix_niv1 === ZenitySetup::$menu_principal['entrees'][0] || $section[0] === 1) { - echo("choix: ". ZenitySetup::$menu_principal_entrees[0] . "\n"); + echo("choix: ". ZenitySetup::$menu_principal['entrees'][0] . "\n"); $section = newCustomer(); } // -- SECTION 2: Prestations et devis -- - elseif($choix_niv1 === ZenitySetup::$menu_principal_entrees[1] || $section[0] === 2) + elseif($choix_niv1 === ZenitySetup::$menu_principal['entrees'][1] || $section[0] === 2) { - echo("choix: ". ZenitySetup::$menu_principal_entrees[1] . "\n"); - $section = newService($section[1]); // $section[1] vaut un type Clients ou null + echo("choix: ". ZenitySetup::$menu_principal['entrees'][1] . "\n"); + $section = newService($section[1]); // $section[1] vaut un type Client ou null } // -- SECTION 3: Modifier un enregistrement -- - elseif($choix_niv1 === ZenitySetup::$menu_principal_entrees[2] || $section[0] === 3) + elseif($choix_niv1 === ZenitySetup::$menu_principal['entrees'][2] || $section[0] === 3) { - echo("choix: " . ZenitySetup::$menu_principal_entrees[2] . "\n"); - $section = modifyData($section[1]); // $section[1] vaut un type Clients ou null + echo("choix: " . ZenitySetup::$menu_principal['entrees'][2] . "\n"); + $section = modifyData($section[1]); // $section[1] vaut un type Client ou null } // -- SECTION 4: Consulter, Imprimer un document -- - elseif($choix_niv1 === ZenitySetup::$menu_principal_entrees[3] || $section[0] === 4) // = Imprimer un document + elseif($choix_niv1 === ZenitySetup::$menu_principal['entrees'][3] || $section[0] === 4) // = Imprimer un document { - echo("choix: ". ZenitySetup::$menu_principal_entrees[3] . "\n"); + echo("choix: ". ZenitySetup::$menu_principal['entrees'][3] . "\n"); $section = getOrPrintDocument(); } // -- SECTION 5: Consulter/analyser les données -- - elseif($choix_niv1 === ZenitySetup::$menu_principal_entrees[4] || $section[0] === 5) + elseif($choix_niv1 === ZenitySetup::$menu_principal['entrees'][4] || $section[0] === 5) { - echo("choix: ". ZenitySetup::$menu_principal_entrees[4] . "\n"); + echo("choix: ". ZenitySetup::$menu_principal['entrees'][4] . "\n"); // quel affichage? des tableaux avec zenity? LaTeX? une page web? un autre outil servant à faire des tableaux et graphiques $section = viewData(); } // -- SECTION 6: Supports de communication -- - elseif($choix_niv1 === ZenitySetup::$menu_principal_entrees[5] || $section[0] === 6) // = Communication + elseif($choix_niv1 === ZenitySetup::$menu_principal['entrees'][5] || $section[0] === 6) // = Communication { - echo("choix: ". ZenitySetup::$menu_principal_entrees[5] . "\n"); - $MenuCommunication = new ZenityList(ZenitySetup::$menu_communication_text, ZenitySetup::$menu_communication_entrees); + echo("choix: ". ZenitySetup::$menu_principal['entrees'][5] . "\n"); + $MenuCommunication = new ZenityList(ZenitySetup::$menu_communication['text'], ZenitySetup::$menu_communication['entrees']); $choix_niv2 = exec($MenuCommunication->get()); - if($choix_niv2 === ZenitySetup::$menu_communication_entrees[0]) // = Flyer (nécessite gimp) + if($choix_niv2 === ZenitySetup::$menu_communication['entrees'][0]) // = Flyer (nécessite gimp) { - exec(windowAppCommand($image_editor, $flyer)); + exec(windowAppCommand(Config::$image_editor, $flyer)); } - elseif($choix_niv2 === ZenitySetup::$menu_communication_entrees[1]) // = Carte de visite (nécessite scribus) + elseif($choix_niv2 === ZenitySetup::$menu_communication['entrees'][1]) // = Carte de visite (nécessite scribus) { - exec(windowAppCommand($publishing, $business_card)); + exec(windowAppCommand(Config::$publishing, $business_card)); } - elseif($choix_niv2 === ZenitySetup::$menu_communication_entrees[2]) // = Explorateur de fichiers + elseif($choix_niv2 === ZenitySetup::$menu_communication['entrees'][2]) // = Explorateur de fichiers { - exec(windowAppCommand($file_explorer, $pub)); + exec(windowAppCommand($file_explorer, Config::$pub_path)); } else { @@ -83,9 +83,9 @@ while($main_loop) } // -- SECTION 7: BDD -- - elseif($choix_niv1 === ZenitySetup::$menu_principal_entrees[6] || $section[0] === 7) // = Base de données + elseif($choix_niv1 === ZenitySetup::$menu_principal['entrees'][6] || $section[0] === 7) // = Base de données { - echo("choix: ". ZenitySetup::$menu_principal_entrees[6] . "\n"); + echo("choix: ". ZenitySetup::$menu_principal['entrees'][6] . "\n"); if($sqlitebrowser_enable) { exec(windowAppCommand(Config::$sqlite_gui, Config::$db_path)); diff --git a/src/model/CESU.php b/src/model/CESU.php deleted file mode 100644 index 2768b8f..0000000 --- a/src/model/CESU.php +++ /dev/null @@ -1,66 +0,0 @@ -table = strtolower(__CLASS__); // cesu - } - - public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) - { - return [ - "Tâche effectuée:" => $this->taches, - "Durée du travail:" => $this->duree_travail, - "Salaire:" => $this->salaire]; - } - public function set(string $entry, string $input) - { - $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide - switch($entry) - { - case "Tâche effectuée:": - $this->setTaches($input); - break; - case "Durée du travail:": - $this->setDureeTravail($input); - break; - case "Salaire:": - $this->setSalaire($input); - break; - } - } - - // setters - public function setIdPresta(int $value) - { - $this->id_presta = $value; - return($this); - } - public function setTaches(string $value) - { - $this->taches = $value; - return($this); - } - public function setDureeTravail(string $value) - { - $this->duree_travail = $value; - return($this); - } - public function setSalaire($value) - { - $value = str_replace(',', '.', $value); - $this->salaire = (float) $value; - return($this); - } -} diff --git a/src/model/Clients.php b/src/model/Clients.php deleted file mode 100644 index 32cf0c5..0000000 --- a/src/model/Clients.php +++ /dev/null @@ -1,168 +0,0 @@ -table = strtolower(__CLASS__); // clients - } - - // getters - public function getId(): int - { - return $this->id; - } - public function getCodeClient(): string - { - return $this->code_client; - } - public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) - { - return [ - "Prénom Nom:" => $this->prenom_nom, - "Code client (J.C.Dusse):" => $this->code_client, - "Adresse:" => $this->adresse, - "Code postal:" => $this->code_postal, - "Ville:" => $this->ville, - "Telephone:" => $this->telephone, - "Courriel:" => $this->courriel, - "À propos:" => $this->apropos, - "Client ou Prospect?" => $this->type]; - } - public function set(string $entry, string $input) - { - $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide - switch($entry) - { - case "Prénom Nom:": - $this->setPrenomNom($input); - break; - case "Code client (J.C.Dusse):": - $this->setCodeClient($input); - break; - case "Adresse:": - $this->setAdresse($input); - break; - case "Code postal:": - $this->setCodePostal($input); - break; - case "Ville:": - $this->setVille($input); - break; - case "Telephone:": - $this->setTelephone($input); - break; - case "Courriel:": - $this->setCourriel($input); - break; - case "À propos:": - $this->setApropos($input); - break; - case "Client ou Prospect?": - $this->setType($input); - break; - } - } - - // setters - public function setPrenomNom($value) - { - $this->prenom_nom = (string) $value; - return $this; - } - public function setCodeClient($value) - { - $this->code_client = (string) $value; - return $this; - } - public function setAdresse($value) - { - $this->adresse = (string) $value; - return $this; - } - public function setCodePostal($value) - { - $this->code_postal = (string) $value; - return $this; - } - public function setVille($value) - { - $this->ville = (string) $value; - return $this; - } - public function setTelephone($value) - { - // type string parce que: - // - zenity renvoie une chaine - // - permet de garder le 0 au début et d'inscrire plusieurs numéros - $this->telephone = (string) $value; - return $this; - } - public function setCourriel($value) - { - $this->courriel = (string) $value; - return $this; - } - public function setApropos($value) - { - $this->apropos = (string) $value; - return $this; - } - public function setType($value) - { - $this->type = (string) $value; - return $this; - } - - public function typeToClient(): bool - { - if($this->type != 'client') - { - $this->type = 'client'; - return true; - } - else - { - return false; - } - } - - public function findByKeywords(array $keywords, string $field): array // n'hydrate pas les variables, on doit choisir un client et hydrater ensuite - { - $result = []; - for($i = 0; $i < count($keywords); $i++) - { - // tableau à deux dimensions obtenu pour un mot clé - $query_result = $this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field . ' LIKE "%' . $keywords[$i] . '%"')->fetchAll(); - foreach($query_result as $one_array) // pour chaque sous tableau - { - $already_exist = false; - for($j = 0; $j < count($result); $j++) // pour chaque tableau déjà enregistré dans le tableau $result - { - if($result[$j]['id'] === $one_array['id']) - { - $already_exist = true; - } - } - if(!$already_exist) - { - $result[] = $one_array; - } - } - } - return $result; - } -} diff --git a/src/model/DB.php b/src/model/DB.php deleted file mode 100644 index 47407ba..0000000 --- a/src/model/DB.php +++ /dev/null @@ -1,48 +0,0 @@ - PDO::$dsn - //$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8'); // pour mysql/mariadb - $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // $this pour la méthode du parent PDO - $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // pour PDO:fetch() et PDO::fetchAll() - // avec PDO::FETCH_ASSOC on obtient un tableau associatif, marche très bien puisqu'on utilise déjà des ID avec incrémentation automatique - // avec PDO::FETCH_BOTH (par défaut) on récupère les données en double (identifiants partant de 0 + tableau associatif) - } - catch(PDOException $e) - { - die("Impossible de se connecter à la base de données.\n" . $e->getMessage()); - } - } - - // créer son objet depuis Model avec: $db = parent::getInstance(); - public static function getInstance(): self - { - if(self::$Instance === null) - { - self::$Instance = new self; - } - return self::$Instance; - } -} diff --git a/src/model/DevisFactures.php b/src/model/DevisFactures.php deleted file mode 100644 index 06a0a59..0000000 --- a/src/model/DevisFactures.php +++ /dev/null @@ -1,215 +0,0 @@ -table = $table; // deux tables séparées devis et factures - } - - public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) - { - $taches = ["Tâches:" => $this->taches]; - $champs_communs = [ - "Total Main d'oeuvre:" => $this->total_main_d_oeuvre, - "Pièces:" => $this->pieces, - "Total des pièces:" => $this->total_pieces, - "Déplacement:" => $this->deplacement, - "Total HT:" => $this->total_HT]; - - if($this->table === 'factures') - { - $champs_facture = [ - "PC:" => $this->machine, - "OS:" => $this->OS, - "Données:" => $this->donnees, - "Clés de licences:" => $this->cles_licences]; - - return $taches + $champs_facture + $champs_communs; - } - elseif($this->table === 'devis') - { - $champs_devis = [ - "Delai de livraison:" => $this->delai_livraison, - "Durée de validité:" => $this->validite_devis, - "Devis signé:" => $this->signature_devis]; - - return $champs_communs + $champs_devis; - } - else - { - return []; - } - } - - public function set(string $entry, string $input) // trouve la bonne méthode - { - $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide - switch($entry) - { - case "Tâches:": - $this->setTaches($input); - break; - case "PC:": - $this->setMachine($input); - break; - case "OS:": - $this->setOS($input); - break; - case "Données:": - $this->setDonnees($input); - break; - case "Clés de licences:": - $this->setClesLicences($input); - break; - case "Total Main d'oeuvre:": - $this->setTotalMainDOeuvre($input); - break; - case "Pièces:": - $this->setPieces($input); - break; - case "Total des pièces:": - $this->setTotalPieces($input); - break; - case "Déplacement:": - $this->setDeplacement($input); - break; - case "Prix du devis:": - $this->setPrixDevis($input); - break; - case "Total HT:": - $this->setTotalHT($input); - break; - case "Delai de livraison:": - $this->setDelaiLivraison($input); - break; - case "Durée de validité:": - $this->setValiditedevis($input); - break; - case "Devis signé:": - $this->setSignatureDevis($input); - break; - } - } - - // setters - //~ public function setId(int $value = 0) - //~ { - //~ $this->id = $value; - //~ return($this); - //~ } - public function setIdPresta(int $value) - { - $this->id_presta = $value; - return($this); - } - public function setTaches(string $value) - { - $this->taches = $value; - return($this); - } - public function setMachine(string $value) - { - $this->machine = $value; - return($this); - } - public function setOS(string $value) - { - $this->OS = $value; - return($this); - } - public function setDonnees(string $value) - { - $this->donnees = $value; - return($this); - } - public function setClesLicences(string $value) - { - $this->cles_licences = $value; - return($this); - } - public function setTotalMainDOeuvre($value) - { - $value = str_replace(',', '.', $value); - $this->total_main_d_oeuvre = (float) $value; // float "nettoie" tous les caractères après le dernier chiffre trouvé (ex: 50€ => 50, abc => 0) - return($this); - } - public function setPieces(string $value) - { - $this->pieces = $value; - return($this); - } - public function setTotalPieces($value) - { - $value = str_replace(',', '.', $value); - $this->total_pieces = (float) $value; - return($this); - } - public function setDeplacement($value) - { - $value = str_replace(',', '.', $value); - $this->deplacement = (float) $value; - return($this); - } - public function setTotalHT($value) - { - $value = str_replace(',', '.', $value); - $this->total_HT = (float) $value; - return($this); - } - public function setPrixDevis($value) - { - $value = str_replace(',', '.', $value); - $this->prix_devis = (float) $value; - return($this); - } - public function setDelaiLivraison(string $value) - { - $this->delai_livraison = $value; - return($this); - } - public function setValiditedevis(string $value) - { - $this->validite_devis = $value; - return($this); - } - public function setSignatureDevis(string $value) - { - $this->signature_devis = $value; - return($this); - } - - // création d'une facture à partir d'un devis - public function hydrateReceiptWithQuotation($ReceiptDetails) - { - $ReceiptDetails->hydrate([ - 'taches' => $this->taches, - 'total_main_d_oeuvre' => $this->total_main_d_oeuvre, - 'pieces' => $this->pieces, - 'total_pieces' => $this->total_pieces, - 'deplacement' => $this->deplacement, - 'total_HT' => $this->total_HT - ]); - } -} diff --git a/src/model/Locations.php b/src/model/Locations.php deleted file mode 100644 index c6b8deb..0000000 --- a/src/model/Locations.php +++ /dev/null @@ -1,127 +0,0 @@ -table = strtolower(__CLASS__); // locations - } - - public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) - { - return [ - "Désignation:" => $this->designation, - "Description du modèle:" => $this->modele_description, - "Valeur:" => $this->valeur, - "État des lieux de début:" => $this->etat_des_lieux_debut, - "État des lieux de fin:" => $this->etat_des_lieux_fin, - "Durée de la location:" => $this->duree_location, - "Loyer Mensuel:" => $this->loyer_mensuel, - "Loyers Payés:" => $this->loyers_payes, - "Caution:" => $this->caution]; - } - public function set(string $entry, string $input) - { - $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide - switch($entry) - { - case "Désignation:": - $this->setDesignation($input); - break; - case "Description du modèle:": - $this->setModeleDescription($input); - break; - case "Valeur:": - $this->setValeur($input); - break; - case "État des lieux de début:": - $this->setEtatDesLieuxDebut($input); - break; - case "État des lieux de fin:": - $this->setEtatDesLieuxFin($input); - break; - case "Durée de la location:": - $this->setDureeLocation($input); - break; - case "Loyer Mensuel:": - $this->setLoyerMensuel($input); - break; - case "Loyers Payés:": - $this->setLoyersPayes($input); - break; - case "Caution:": - $this->setCaution($input); - break; - } - } - - // setters - public function setIdPresta(int $value) - { - $this->id_presta = $value; - return($this); - } - public function setDesignation(string $value) - { - $this->designation = $value; - return($this); - } - public function setModeleDescription(string $value) - { - $this->modele_description = $value; - return($this); - } - public function setValeur($value) - { - $value = str_replace(',', '.', $value); - $this->valeur = (float) $value; - return($this); - } - public function setEtatDesLieuxDebut(string $value) - { - $this->etat_des_lieux_debut = $value; - return($this); - } - public function setEtatDesLieuxFin(string $value) - { - $this->etat_des_lieux_fin = $value; - return($this); - } - public function setDureeLocation(string $value) - { - $this->duree_location = $value; - return($this); - } - public function setLoyerMensuel($value) - { - $value = str_replace(',', '.', $value); - $this->loyer_mensuel = (float) $value; - return($this); - } - public function setLoyersPayes($value) - { - $value = str_replace(',', '.', $value); - $this->loyers_payes = (float) $value; - return($this); - } - public function setCaution($value) - { - $value = str_replace(',', '.', $value); - $this->caution = (float) $value; - return($this); - } -} diff --git a/src/model/Model.php b/src/model/Model.php deleted file mode 100644 index b3d157d..0000000 --- a/src/model/Model.php +++ /dev/null @@ -1,313 +0,0 @@ -table; - } - - public function getAll(): array // à améliorer pour ne pas renvoyer $db et $table - { - return get_object_vars($this); // retourne les propriétés de l'objet - } - - // setters - public function setId(int $value = 0) - { - if($value === 0) - { - $this->id = $this->db->lastInsertId(); // méthode de PDO, attention lastInsertId() ne gère pas la concurence - } - else - { - $this->id = $value; - } - return $this; - } - public function setTable(string $value) - { - $this->table = $value; - return($this); - } - - public function hydrate(array $data): bool // $data = tableau associatif en entrée: nom_du_champ => valeur - { - foreach($data as $key => $value) - { - // nom du setter - // nom_propriete => setPropriete - // on sépare les mots par des espaces, ucwords met la première lettre de chaque mot en majuscule, puis on supprime les espaces - $setter_name = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); // ucwords: première lettre de chaque mot en majuscule - if(method_exists($this, $setter_name)) - { - $this->$setter_name($value); - } - else - { - echo "debug: la méthode $setter_name n'existe pas\n"; - return false; - } - } - return true; - } - - // cette fonction reçoit des données d'un tableau simple, permettant d'associer des champs de formulaires aux noms différents des champs de la BDD - // méthode lancée par des objets de type enfants - function hydrateFromForm(string $data_string, Object $Presta = NULL): bool // quand l'objet est $Details, on hydrate aussi $Presta - { - $data_string = $this->cleanSpecialChars($data_string); // possibilité que $data_string devienne une chaine vide - if($data_string !== '') - { - $data_array = explode('|', $data_string); // array - $check = false; - switch($this->getTable()) - { - case 'clients'; - if($data_array[0] == '') - { - echo "debug: données insuffisantes, le nom du client doit au minimum être renseigné\n"; - return false; - } - else - { - $check = $this->hydrate(['prenom_nom' => $data_array[0], 'code_client' => $data_array[1], 'adresse' => $data_array[2], 'code_postal' => $data_array[3], 'ville' => $data_array[4], 'telephone' => $data_array[5], 'courriel' => $data_array[6], 'apropos' => $data_array[7]]); - } - break; - case 'prestations'; // inutilisé - break; - case 'devis'; - $check = $this->hydrate(['taches' => $data_array[0], 'total_main_d_oeuvre' => $data_array[1], 'pieces' => $data_array[2], 'total_pieces' => $data_array[3], 'deplacement' => $data_array[4], 'prix_devis' => $data_array[5], 'total_HT' => $data_array[6], 'delai_livraison' => $data_array[7], 'validite_devis' => $data_array[8]]); - break; - case 'factures'; - if(count($data_array) === 11) - { - $check = $Presta->hydrate(['mode_paiement' => $data_array[10]]); - if($check) - { - $check = $this->hydrate(['taches' => $data_array[0], 'machine' => $data_array[1], 'OS' => $data_array[2], 'donnees' => $data_array[3], 'cles_licences' => $data_array[4], 'total_main_d_oeuvre' => $data_array[5], 'pieces' => $data_array[6], 'total_pieces' => $data_array[7], 'deplacement' => $data_array[8], 'total_HT' => $data_array[9]]); - } - } - elseif(count($data_array) === 5) // facture à partir d'un devis - { - $check = $this->hydrate(['machine' => $data_array[0], 'OS' => $data_array[1], 'donnees' => $data_array[2], 'cles_licences' => $data_array[3]]); - if($check) - { - $check = $Presta->hydrate(['mode_paiement' => $data_array[4]]); - } - } - else - { - echo "debug: le tableau \$data_array n'a pas la taille attendue.\n"; - return false; - } - break; - case 'cesu'; - $check = $Presta->hydrate(['mode_paiement' => $data_array[3]]); - if($check) - { - $check = $this->hydrate(['taches' => $data_array[0], 'duree_travail' => $data_array[1], 'salaire' => $data_array[2]]); - } - break; - case 'locations'; - $check = $this->hydrate(['designation' => $data_array[0], 'modele_description' => $data_array[1], 'valeur' => $data_array[2], 'etat_des_lieux_debut' => $data_array[3], 'etat_des_lieux_fin' => $data_array[4], 'duree_location' => $data_array[5], 'loyer_mensuel' => $data_array[6], 'loyers_payes' => $data_array[7], 'caution' => $data_array[8]]); - break; - default: // inutilisé - echo "debug: table inconnue hydrateFromForm()"; - return false; - } - return $check; - } - else - { - echo "debug: annulation lors du formulaire\n"; - return false; - } - } - - protected function cleanSpecialChars(string $data): string - { - $search = ['"']; - return str_replace($search, '', $data); - } - - - // exécuter le SQL - // les $attributs correspondent aux ? dans les requêtes préparées - // ne pas surcharger la méthode PDO::query() qui n'est pas compatible - protected function execQuery(string $sql, array $attributes = null) - { - $this->db = parent::getInstance(); // parent::, self:: et DB:: sont équivalents - - if($attributes !== null) // requête préparée - { - //~ var_dump($sql); - //~ var_dump($attributes); - $query = $this->db->prepare($sql); - $query->execute($attributes); - return $query; - } - else // requête simple - { - return $this->db->query($sql); - } - } - - - // méthodes CRUD - - // create INSERT - public function create() // = write - { - $fields = []; - $question_marks = []; // ? - $values = []; - //~ var_dump($this); - foreach($this as $field => $value) - { - //~ var_dump($field); var_dump($value); - // champs non renseignées et variables de l'objet qui ne sont pas des champs - // note: avec le !== (au lieu de !=) une valeur 0 est différente de null - if($value !== null && $field != 'db' && $field != 'table') - { - $value = $this->clean_for_bash($value); // pour la BDD - $this->$field = $value; // pour latex - - $fields[] = $field; // push - $question_marks[] = '?'; - $values[] = $value; - } - } - $field_list = implode(', ', $fields); - $question_mark_list = implode(', ', $question_marks); - - // INSERT INTO annonces (titre, description, actif) VALUES (?, ?, ?) - return($this->execQuery('INSERT INTO ' . $this->table . ' (' . $field_list . ') VALUES (' . $question_mark_list . ')', $values)); - } - - - // read SELECT - protected function readAll(): array // obtenir une table - { - return($this->execQuery('SELECT * FROM ' . $this->table)->fetchAll()); // fonctionne aussi sans le point virgule dans le SQL!! - } - - public function findById() // obtenir une entrée grace à son ID - { - return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id = ' . $this->id)->fetch()); - } - public function getDetailsByIdPresta() - { - if($this->table == 'prestations') - { - // à l'occaz, créer une classe NonVendue et rendre Prestations abstraite - echo 'erreur: ne pas appeler Model::getDetailsByIdPresta() si la table ciblée est "prestations".'; - return 0; - } - else - { - return $this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id_Presta = ' . $this->id_presta)->fetch(); // type array - } - } - - protected function find(array $criteria): array // obtenir une entrée avec un tableau associatif 'champ' => 'valeur' - { - $fields = []; - $values = []; - - // change "'id' => 2" en "'id' = ?" et "2" - foreach($criteria as $field => $value) - { - $fields[] = "$field = ?"; // même chose que: $field . " = ?" - $values[] = $value; - } - $field_list = implode(' AND ', $fields); // créer une chaîne reliant les morceaux avec le morceau AND en paramètre: 'adresse = ? AND id = ?' - - // SELECT * FROM annonces WHERE actif = 1; - return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field_list, $values)->fetchAll()); - } - - - // update UPDATE - public function update() - { - $fields = []; - $values = []; - foreach($this as $field => $value) - { - if($value !== null && $field != 'db' && $field != 'table') // champs non renseignées et variables de l'objet qui ne sont pas des champs - { - $value = $this->clean_for_bash($value); // pour la BDD - $this->$field = $value; // pour latex - - $fields[] = $field . ' = ?'; - $values[] = $value; - } - } - $values[] = $this->id; // cette syntaxe ajoute une valeur au tableau - $field_list = implode(', ', $fields); - - // UPDATE annonces SET titre = ?, description = ?, actif = ? WHERE id = ? - return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field_list . ' WHERE id = ?', $values)); - } - - public function updateOneValue(string $field, $value) - { - return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field . ' = ? WHERE id = ?', [$value, $this->id])); - } - - - // delete DELETE - protected function delete(int $id) - { - return($this->execQuery("DELETE FROM {$this->table} WHERE id = ?", [$id])); // double quotes "" pour insertion de variable, paramètre [$id] parce qu'on veut un tableau - } - - - private function clean_for_bash($value) - { - if(is_string($value) && $value != '') - { - do - { - $value = trim($value); - $value = preg_replace('#^-#','' , $value); // en bash une chaîne commençant par un tiret est un paramètre - } while($value[0] == ' '|| $value[0] == '-'); // chaîne commençant par un tiret puis un espace, ou même - - - - - - } - return $value; - } - - - static public function createTables() - { - static $first_time = true; - - if($first_time) // fonction normallement appelée qu'une seule fois - { - foreach(StructTablesDB::$structureOfTables as $tableName => $oneTable) - { - $query = 'CREATE TABLE IF NOT EXISTS ' . $tableName . ' ('; - foreach($oneTable as $key => $value) - { - $query .= $key . ' ' . $value . ', '; - } - $query .= 'PRIMARY KEY(ID AUTOINCREMENT));'; - parent::getInstance()->exec($query); - } - - $first_time = false; - } - else - { - echo "Model::createTables() a déjà été appelée et ne fera rien.\n"; - } - } -} diff --git a/src/model/Prestations.php b/src/model/Prestations.php deleted file mode 100644 index 3a415be..0000000 --- a/src/model/Prestations.php +++ /dev/null @@ -1,165 +0,0 @@ -id_client = $id_client; - $this->table = strtolower(__CLASS__); // prestations - } - - // getters - public function getId(): int - { - return $this->id; - } - public function getIdClient(): int - { - return $this->id_client; - } - public function getIdsByIdClient() // obtenir une entrée avec son id_client, comportement différent si le type est connu - { - $sql = 'SELECT id FROM ' . $this->table . ' WHERE id_client = ' . $this->id_client; - if($this->type_presta != '') - { - $sql .= " AND type_presta = '" . $this->type_presta . "'"; - } - $data = $this->execQuery($sql)->fetchAll(); // tableau de tableaux - - $IDs = []; // si $IDs reste vide, ne pas être de type NULL - for($i = 0; $i < count($data); $i++) - { - $IDs[$i] = $data[$i]['id']; // tableau simple - } - return($IDs); - } - public function getCodePresta(): string - { - return $this->code_presta; - } - public function getDate(): int // timestamp unix - { - return $this->date; - } - public function getTypePresta(): string - { - return $this->type_presta; - } - public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) - { - $code_presta_tableau = explode('-', $this->code_presta); - $Date = new Dates($this->date); - - return [ - "Numéro prestation:" => end($code_presta_tableau), // dernière case - "Date:" => $Date->getDate(), - //"Type de Presta:" => $this->type_presta, // choix impossible pour le moment - "Mode de paiement:" => $this->mode_paiement, // non pertinent pour un devis - "Commentaires:" => $this->commentaires]; - } - public function set(string $entry, string $input) - { - $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide - switch($entry) - { - case "Numéro prestation:": - $this->setNumeroPresta($input); - break; - //~ case "Date:": // inutile, setDate() est appelé directement après choix fenêtre calendrier - //~ $this->setDate($input); - //~ break; - //~ case "Type de Presta:": // choix impossible pour le moment - //~ $this->setTypePresta($input); - //~ break; - case "Mode de paiement:": - $this->setModePaiement($input); - break; - case "Commentaires:": - $this->setCommentaires($input); - break; - } - } - - // setters - public function setIdClient(int $value) - { - $this->id_client = $value; - return $this; - } - //~ public function setCombientiemeFois(int $value) - //~ { - //~ $this->combientieme_fois = $value; - //~ return($this); - //~ } - public function setCodePresta(string $value) - { - $this->code_presta = $value; - return $this; - } - public function setDate($value, bool $set_code_presta = false) // attend un timestamp - { - $this->date = (int) $value; - - if($set_code_presta) - { - $code_presta_tableau = explode('-', $this->code_presta); - $Date = new Dates($value); - $code_presta_tableau[0] = $Date->getYear(); - $code_presta_tableau[1] = $Date->getMonth(); - $code_presta_tableau[2] = $Date->getDay(); - $this->code_presta = implode('-', $code_presta_tableau); - } - - return $this; - } - public function setTypePresta(string $value) - { - $this->type_presta = $value; - return $this; - } - public function setModePaiement(string $value) - { - $this->mode_paiement = $value; - return $this; - } - public function setCommentaires(string $value) - { - $this->commentaires = $this->cleanSpecialChars($value); // nettoyage ici parce que pas possible ailleurs - return $this; - } - public function setNumeroPresta($value) - { - // modifier le code presta, on pourrait aussi utiliser une regex - $code_presta_tableau = explode('-', $this->code_presta); - $code_presta_tableau[count($code_presta_tableau) - 1] = (int) $value; - $this->code_presta = implode('-', $code_presta_tableau); - return $this; - } - - // code client = année-mois-jour-codeclient-typedepresta-combientièmefois - public function makeCodePresta(Dates $Date, string $code_client) - { - // on récupère un tableau contenant toutes les prestations d'un client tous types confondus (devis, facture, cesu, location, enregistrement sans vente) - // inconvénient: il peut y avoir plusieurs prestations avec le même numéro au compteur, à améliorer - $combientieme_fois = count($this->find(['id_client' => $this->id_client])) + 1; - - $array_code = [$Date->getYear(), $Date->getMonth(), $Date->getDay(), $code_client, $this->type_presta, $combientieme_fois]; - $this->code_presta = implode('-', $array_code); - } -} - -//~ class CodePresta extends Prestations -//~ { - //~ protected $numero_presta; -//~ } diff --git a/src/model/StructTablesDB.php b/src/model/StructTablesDB.php deleted file mode 100644 index 303af46..0000000 --- a/src/model/StructTablesDB.php +++ /dev/null @@ -1,36 +0,0 @@ - ['id' => 'INTEGER', 'prenom_nom' => 'TEXT', 'code_client' => 'TEXT', 'adresse' => 'TEXT', 'code_postal' => 'TEXT', 'ville' => 'TEXT', 'telephone' => 'TEXT', 'courriel' => 'TEXT', 'apropos' => 'TEXT', 'type' => 'TEXT DEFAULT prospect'], - 'prestations' => ['id' => 'INTEGER', 'id_client' => 'INTEGER', 'code_presta' => 'TEXT', 'date' => 'INTEGER', 'type_presta' => 'TEXT', 'mode_paiement' => 'TEXT', 'commentaires' => 'TEXT'], - 'devis' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'taches' => 'TEXT', 'total_main_d_oeuvre' => 'REAL', 'pieces' => 'TEXT', 'total_pieces' => 'REAL', 'deplacement' => 'REAL', 'prix_devis' => 'REAL', 'total_HT' => 'REAL', 'delai_livraison' => 'TEXT', 'validite_devis' => 'TEXT', 'signature_devis' => 'TEXT DEFAULT non'], - 'factures' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'taches' => 'TEXT', 'machine' => 'TEXT', 'OS' => 'TEXT', 'donnees' => 'TEXT', 'cles_licences' => 'TEXT', 'total_main_d_oeuvre' => 'REAL', 'pieces' => 'TEXT', 'total_pieces' => 'REAL', 'deplacement' => 'REAL', 'total_HT' => 'REAL'], - 'cesu' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'taches' => 'TEXT', 'duree_travail' => 'TEXT', 'salaire' => 'REAL'], - 'locations' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'designation' => 'TEXT', 'modele_description' => 'TEXT', 'valeur' => 'REAL', 'etat_des_lieux_debut' => 'TEXT', 'etat_des_lieux_fin' => 'TEXT', 'duree_location' => 'TEXT', 'loyer_mensuel' => 'REAL', 'loyers_payes' => 'INTEGER', 'caution' => 'INTEGER'] - ]; - - // les types de variables de sqlite sont peu nombreux et autorisent un typage automatique - // le "type indiqué" est indiqué dans l'instruction CREATE TABLE - // https://www.leppf.com/site/spip.php?article89 - - // || type indiqué || type choisi automatiquement || autre types possibles || - // --------------------------------------------------------------------------- - // || TEXT || TEXT || BLOB, NULL || - // || INTEGER || INTEGER (de 1 à 8 octets) || REAL, TEXT, BLOB, NULL || - // || REAL || REAL (flottant sur 9 octets) || TEXT, BLOB, NULL || - // || NUMERIC || INTEGER ou REAL || TEXT, BLOB, NULL || - // || NONE || indéfini || dépend des données || - - // du code SQL écrit pour d'autres SGBD devrait fonctionner, - // sqlite fera des conversions dans ses propres types avec les problèmes qu'on peut imaginer - - // pour les dates, on stockera à priori le timestamp -} diff --git a/src/model/doctrine-bootstrap.php b/src/model/doctrine-bootstrap.php new file mode 100644 index 0000000..029b1b1 --- /dev/null +++ b/src/model/doctrine-bootstrap.php @@ -0,0 +1,31 @@ + 'pdo_sqlite', + //'path' => __DIR__ . '/../../data/' . Config::$db_name . '.sqlite', + 'path' => 'data/' . Config::$db_name . '.sqlite', +], $config); + +// obtaining the entity manager +$entityManager = new EntityManager($connection, $config); + diff --git a/src/model/entities/CESU.php b/src/model/entities/CESU.php new file mode 100644 index 0000000..09a2542 --- /dev/null +++ b/src/model/entities/CESU.php @@ -0,0 +1,131 @@ +setPresta($presta); + } + } + + // getters + public function getPresta(): Prestation + { + return $this->presta; + } + + public function getAllWithWindowFields(): array + { + return [ + "Tâche effectuée:" => $this->taches, + "Durée du travail:" => $this->duree_travail, + "Salaire:" => $this->salaire]; + } + + // setters + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaîne vide + switch($entry) + { + case "Tâche effectuée:": + $this->setTaches($input); + break; + case "Durée du travail:": + $this->setDureeTravail($input); + break; + case "Salaire:": + $this->setSalaire($input); + break; + } + } + private function setPresta(Prestation $input) // private? + { + $this->presta = $input; + } + public function setTaches(string $value) + { + $this->taches = $value; + return($this); + } + public function setDureeTravail(string $value) + { + $this->duree_travail = $value; + return($this); + } + public function setSalaire($value) + { + $value = str_replace(',', '.', $value); + $this->salaire = (float) $value; + return($this); + } + + private function setAll(array $input) // private? + { + $this->taches = $input[0]; + $this->duree_travail = $input[1]; + $this->salaire = (float)$input[2]; + } + + // à mettre plus tard dans une classe mère + protected function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } + // à mettre plus tard dans une classe mère + public function hydrate(string $answers) + { + $answers = $this->cleanSpecialChars($answers); // possibilité que $answers devienne une chaine vide + if($answers == '') + { + echo "erreur de CESU::hydrate(), la chaine \$answers est vide.\n"; + return false; + } + $data_array = explode('|', $answers); // array + + $check = false; + if(count($data_array) === 4) // facture normale + { + $this->getPresta()->setModePaiement($data_array[3]); + //array_pop($data_array); // supprime la dernière case + unset($data_array[3]); + $this->setAll($data_array); + } + else + { + echo "erreur de CESU::hydrate(), le tableau \$data_array n'a pas la taille attendue.\n"; + return false; + } + + //self::$entityManager->persist('Prestation'); + self::$entityManager->persist($this); // $Presta avec en cascade! + self::$entityManager->flush(); + } +} diff --git a/src/model/entities/Client.php b/src/model/entities/Client.php new file mode 100644 index 0000000..7dd3be6 --- /dev/null +++ b/src/model/entities/Client.php @@ -0,0 +1,314 @@ + 'prospect'])] + private string $type = 'prospect'; // valeur par défaut utilisée à l'instanciation, pas par doctrine + + public static EntityManager $entityManager; + + /*public function __construct() + { + global $entityManager; + self::$entityManager = $entityManager; + }*/ + + + // getters + public function getId(): int + { + return $this->id; + } + public function getPrenomNom(): string + { + return $this->prenom_nom; + } + public function getCodeClient(): string + { + return $this->code_client; + } + public function getAll(): array + { + // n'utiliser get_object_vars() qu'avec une entité parce qu'on maîtrise le nombre de propriétés + return get_object_vars($this); + } + + // pour le GUI + public function getAllWithWindowFields(): array // différent de getAll() + { + return [ + "Prénom Nom:" => $this->prenom_nom, + "Code client (J.C.Dusse):" => $this->code_client, + "Adresse:" => $this->adresse, + "Code postal:" => $this->code_postal, + "Ville:" => $this->ville, + "Telephone:" => $this->telephone, + "Courriel:" => $this->courriel, + "À propos:" => $this->apropos, + "Client ou Prospect?" => $this->type]; + } + + // setters + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + switch($entry) + { + case "Prénom Nom:": + $this->setPrenomNom($input); + break; + case "Code client (J.C.Dusse):": + $this->setCodeClient($input); + break; + case "Adresse:": + $this->setAdresse($input); + break; + case "Code postal:": + $this->setCodePostal($input); + break; + case "Ville:": + $this->setVille($input); + break; + case "Telephone:": + $this->setTelephone($input); + break; + case "Courriel:": + $this->setCourriel($input); + break; + case "À propos:": + $this->setApropos($input); + break; + case "Client ou Prospect?": + $this->setType($input); + break; + } + //self::$entityManager->flush(); + } + public function setPrenomNom($value) + { + $this->prenom_nom = (string) $value; + return $this; + } + public function setCodeClient($value) + { + $this->code_client = (string) $value; + return $this; + } + public function setAdresse($value) + { + $this->adresse = (string) $value; + return $this; + } + public function setCodePostal($value) + { + $this->code_postal = (string) $value; + return $this; + } + public function setVille($value) + { + $this->ville = (string) $value; + return $this; + } + public function setTelephone($value) + { + // type string parce que: + // - zenity renvoie une chaine + // - permet de garder le 0 au début et d'inscrire plusieurs numéros + $this->telephone = (string) $value; + return $this; + } + public function setCourriel($value) + { + $this->courriel = (string) $value; + return $this; + } + public function setApropos($value) + { + $this->apropos = (string) $value; + return $this; + } + public function setType($value) + { + $this->type = (string) $value; + return $this; + } + + public function typeToClient() + { + if($this->type != 'client') + { + $this->type = 'client'; + } + } + + private function setAll(array $input) + { + $this->prenom_nom = $input[0]; + $this->code_client = $input[1]; + $this->adresse = $input[2]; + $this->code_postal = $input[3]; + $this->ville = $input[4]; + $this->telephone = $input[5]; + $this->courriel = $input[6]; + $this->apropos = $input[7]; + } + + // à mettre dans une classe mère Model? + protected function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } + + // une partie du code vient de Model::hydrateFromForm() + // à mettre dans une classe ClientManager? + public function enterCustomer(ZenityForms $Form): bool + { + $input = exec($Form->get()); + if($input == '') + { + echo "debug: annulation lors de l'enregistrement d'un nouveau client\n"; + return false; + } + + $data_array = explode('|', $input); // array + if($data_array[0] == '') + { + echo "debug: données insuffisantes, le nom du client doit au minimum être renseigné\n"; + return false; + } + else + { + $this->setAll($data_array); + } + + self::$entityManager->persist($this); + self::$entityManager->flush(); + + //$this->id = $this->db->lastInsertId(); // synchro automatique avec doctrine + + return true; + } + + public static function getObject(ZenityEntry $SearchCustomerForm, ZenityList $SearchCustomerResults) // renvoie un Client ou 0 + { + // fenêtres + /*$SearchCustomerForm = new ZenityEntry(ZenitySetup::$recherche_client_text); + $SearchCustomerResults = new ZenityList(ZenitySetup::$resultats_recherche_client_text, []);*/ + + $Customer = new self; // se serait bien d'hériter d'EntityManager? + + $input = exec($SearchCustomerForm->get()); + if($input == '') // commenter ce if pour qu'une saisie vide permette d'obtenir tous les clients + { + echo "debug: recherche annulée ou saisie vide\n"; + return 0; + } + echo "debug: recherche effectuée\n"; + + $MatchedObjects = self::searchCustomer($input, $Customer); + if(count($MatchedObjects) === 0) // si aucun client ne correspond, les prendre tous! + { + $repository = self::$entityManager->getRepository('Client'); + $MatchedObjects = $repository->findAll(); + + if(count($MatchedObjects) === 0) // toujours rien + { + echo "debug: aucun client dans la base de données\n"; + return 0; + } + } + + $clients_array = []; + foreach($MatchedObjects as $object) // d'objets en tableaux + { + $clients_array[] = get_object_vars($object); + } + + $SearchCustomerResults->setListRows( + $clients_array, + //count($clients_array[$id])); + count($clients_array[0])); + + // sélection parmi les résultats + $input = exec($SearchCustomerResults->get()); // renvoie l'id de la table 'clients' + if($input == '') + { + echo "debug: client pas trouvé ou pas sélectionné\n"; + return 0; + } + + echo "debug: client sélectionné\n"; + //$Customer->setId($input); + //$Customer->hydrate($Customer->findById()); + $Customer = $MatchedObjects[$input]; + //var_dump($Customer); + + return $Customer; + } + + private static function searchCustomer(string $input, Client $Customer): array + { + $input_array = explode(' ', $input); // si plusieurs mot, on les recherche tous l'un après l'autre + return $Customer->findByKeywords($input_array, 'prenom_nom'); // on obtient un tableau à deux dimensions avec les entrées trouvées + } + + private function findByKeywords(array $keywords, string $field): array // renvoie un tableau d'objets + { + $results = []; + for($i = 0; $i < count($keywords); $i++) + { + // tableau à deux dimensions obtenu pour un mot clé + //$query_result = $this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field . ' LIKE "%' . $keywords[$i] . '%"')->fetchAll(); + $query = self::$entityManager->createQuery('SELECT u FROM Client u WHERE u.' . $field . ' LIKE :expression'); + $query->setParameter('expression', '%' . $keywords[$i] . '%'); + $query_result = $query->getResult(); + + foreach($query_result as $object) + { + $id = $object->getId(); + $already_exist = false; + //for($j = 0; $j < count($results); $j++) + foreach($results as $one_result) // pour chaque tableau déjà enregistré dans le tableau $results + { + if($one_result->getId() === $id) + { + $already_exist = true; + } + } + if(!$already_exist) + { + $results[$id] = $object; + } + } + } + //var_dump($results); + return $results; + } +} diff --git a/src/model/entities/Devis.php b/src/model/entities/Devis.php new file mode 100644 index 0000000..7383410 --- /dev/null +++ b/src/model/entities/Devis.php @@ -0,0 +1,241 @@ + 'non'])] + private string $signature_devis = 'non'; + + public static EntityManager $entityManager; + + public function __construct(Prestation $presta = null) + { + if($presta != null) + { + $this->setPresta($presta); + } + } + + // getters + public function getPresta(): Prestation + { + return $this->presta; + } + public function getAll(): array + { + // n'utiliser get_object_vars() qu'avec une entité parce qu'on maîtrise le nombre de propriétés + return get_object_vars($this); + } + + public function getAllWithWindowFields(): array + { + //~ $taches = ["Tâches:" => $this->taches]; + //~ $champs_communs = [ + //~ "Total Main d'oeuvre:" => $this->total_main_d_oeuvre, + //~ "Pièces:" => $this->pieces, + //~ "Total des pièces:" => $this->total_pieces, + //~ "Déplacement:" => $this->deplacement, + //~ "Total HT:" => $this->total_HT]; + //~ $champs_devis = [ + //~ "Delai de livraison:" => $this->delai_livraison, + //~ "Durée de validité:" => $this->validite_devis, + //~ "Devis signé:" => $this->signature_devis]; + //~ return $champs_communs + $champs_devis; + return [ + "Tâches:" => $this->taches, // JUSTE AJOUTÉ + "Total Main d'oeuvre:" => $this->total_main_d_oeuvre, + "Pièces:" => $this->pieces, + "Total des pièces:" => $this->total_pieces, + "Déplacement:" => $this->deplacement, + "Total HT:" => $this->total_HT, + "Delai de livraison:" => $this->delai_livraison, + "Durée de validité:" => $this->validite_devis, + "Devis signé:" => $this->signature_devis]; + } + + // setters + public function set(string $entry, string $input) // trouve la bonne méthode + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaîne vide + switch($entry) + { + case "Tâches:": + $this->setTaches($input); + break; + case "Total Main d'oeuvre:": + $this->setTotalMainDOeuvre($input); + break; + case "Pièces:": + $this->setPieces($input); + break; + case "Total des pièces:": + $this->setTotalPieces($input); + break; + case "Déplacement:": + $this->setDeplacement($input); + break; + case "Prix du devis:": + $this->setPrixDevis($input); + break; + case "Total HT:": + $this->setTotalHT($input); + break; + case "Delai de livraison:": + $this->setDelaiLivraison($input); + break; + case "Durée de validité:": + $this->setValiditedevis($input); + break; + case "Devis signé:": + $this->setSignatureDevis($input); + break; + } + } + private function setPresta(Prestation $input) // private? + { + $this->presta = $input; + } + public function setTaches(string $value) + { + $this->taches = $value; + return($this); + } + public function setTotalMainDOeuvre($value) + { + $value = str_replace(',', '.', $value); + $this->total_main_d_oeuvre = (float) $value; // float "nettoie" tous les caractères après le dernier chiffre trouvé (ex: 50€ => 50, abc => 0) + return($this); + } + public function setPieces(string $value) + { + $this->pieces = $value; + return($this); + } + public function setTotalPieces($value) + { + $value = str_replace(',', '.', $value); + $this->total_pieces = (float) $value; + return($this); + } + public function setDeplacement($value) + { + $value = str_replace(',', '.', $value); + $this->deplacement = (float) $value; + return($this); + } + public function setTotalHT($value) + { + $value = str_replace(',', '.', $value); + $this->total_HT = (float) $value; + return($this); + } + public function setPrixDevis($value) + { + $value = str_replace(',', '.', $value); + $this->prix_devis = (float) $value; + return($this); + } + public function setDelaiLivraison(string $value) + { + $this->delai_livraison = $value; + return($this); + } + public function setValiditedevis(string $value) + { + $this->validite_devis = $value; + return($this); + } + public function setSignatureDevis(string $value) + { + $this->signature_devis = $value; + return($this); + } + + private function setAll(array $input) // private? + { + $this->taches = $input[0]; + $this->total_main_d_oeuvre = (float)$input[1]; + $this->pieces = $input[2]; + $this->total_pieces = (float)$input[3]; + $this->deplacement = (float)$input[4]; + $this->prix_devis = (float)$input[5]; + $this->total_HT = (float)$input[6]; + $this->delai_livraison = $input[7]; + $this->validite_devis = $input[8]; + + // $signature_devis est renseigné plus tard en modifiant le devis + } + + // à mettre plus tard dans une classe mère + protected function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } + // à mettre plus tard dans une classe mère + public function hydrate(string $answers) + { + $answers = $this->cleanSpecialChars($answers); // possibilité que $answers devienne une chaine vide + if($answers == '') + { + echo "erreur de Devis::hydrate(), la chaine \$answers est vide.\n"; + return false; + } + $data_array = explode('|', $answers); // array + + $check = false; + if(count($data_array) === 9) // facture normale + { + $this->getPresta()->setModePaiement(''); // sécurité, doctrine plante si "null" + $this->setAll($data_array); + } + else + { + echo "erreur de Devis::hydrate(), le tableau \$data_array n'a pas la taille attendue.\n"; + return false; + } + + //self::$entityManager->persist('Prestation'); + self::$entityManager->persist($this); // $Presta avec en cascade! + self::$entityManager->flush(); + } + + // création d'une facture à partir d'un devis + public static function getQuotation(Prestation $Quotation) + { + $repository = self::$entityManager->getRepository('Devis'); + return $repository->findOneBy(['presta' => $Quotation->getId()]); // ne peut y en avoir deux + } +} diff --git a/src/model/entities/Facture.php b/src/model/entities/Facture.php new file mode 100644 index 0000000..3a8a551 --- /dev/null +++ b/src/model/entities/Facture.php @@ -0,0 +1,261 @@ +setPresta($presta); + } + } + + // getters + public function getPresta(): Prestation + { + return $this->presta; + } + public function getAll(): array + { + // n'utiliser get_object_vars() qu'avec une entité parce qu'on maîtrise le nombre de propriétés + return get_object_vars($this); + } + + public function getAllWithWindowFields(): array + { + //~ $taches = ["Tâches:" => $this->taches]; + //~ $champs_facture = [ + //~ "PC:" => $this->machine, + //~ "OS:" => $this->OS, + //~ "Données:" => $this->donnees, + //~ "Clés de licences:" => $this->cles_licences]; + //~ $champs_communs = [ + //~ "Total Main d'oeuvre:" => $this->total_main_d_oeuvre, + //~ "Pièces:" => $this->pieces, + //~ "Total des pièces:" => $this->total_pieces, + //~ "Déplacement:" => $this->deplacement, + //~ "Total HT:" => $this->total_HT]; + //return $taches + $champs_facture + $champs_communs; + return [ + "Tâches:" => $this->taches, + "PC:" => $this->machine, + "OS:" => $this->OS, + "Données:" => $this->donnees, + "Clés de licences:" => $this->cles_licences, + "Total Main d'oeuvre:" => $this->total_main_d_oeuvre, + "Pièces:" => $this->pieces, + "Total des pièces:" => $this->total_pieces, + "Déplacement:" => $this->deplacement, + "Total HT:" => $this->total_HT]; + } + + // setters + public function set(string $entry, string $input) // trouve la bonne méthode + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaîne vide + switch($entry) + { + case "Tâches:": + $this->setTaches($input); + break; + case "PC:": + $this->setMachine($input); + break; + case "OS:": + $this->setOS($input); + break; + case "Données:": + $this->setDonnees($input); + break; + case "Clés de licences:": + $this->setClesLicences($input); + break; + case "Total Main d'oeuvre:": + $this->setTotalMainDOeuvre($input); + break; + case "Pièces:": + $this->setPieces($input); + break; + case "Total des pièces:": + $this->setTotalPieces($input); + break; + case "Déplacement:": + $this->setDeplacement($input); + break; + case "Total HT:": + $this->setTotalHT($input); + break; + } + } + public function setPresta(Prestation $input) // private? + { + $this->presta = $input; + } + public function setTaches(string $value) + { + $this->taches = $value; + return($this); + } + public function setMachine(string $value) + { + $this->machine = $value; + return($this); + } + public function setOS(string $value) + { + $this->OS = $value; + return($this); + } + public function setDonnees(string $value) + { + $this->donnees = $value; + return($this); + } + public function setClesLicences(string $value) + { + $this->cles_licences = $value; + return($this); + } + public function setTotalMainDOeuvre($value) + { + $value = str_replace(',', '.', $value); + $this->total_main_d_oeuvre = (float) $value; // float "nettoie" tous les caractères après le dernier chiffre trouvé (ex: 50€ => 50, abc => 0) + return($this); + } + public function setPieces(string $value) + { + $this->pieces = $value; + return($this); + } + public function setTotalPieces($value) + { + $value = str_replace(',', '.', $value); + $this->total_pieces = (float) $value; + return($this); + } + public function setDeplacement($value) + { + $value = str_replace(',', '.', $value); + $this->deplacement = (float) $value; + return($this); + } + public function setTotalHT($value) + { + $value = str_replace(',', '.', $value); + $this->total_HT = (float) $value; + return($this); + } + + private function setAll(array $input) // private? + { + $this->taches = $input[0]; + $this->machine = $input[1]; + $this->OS = $input[2]; + $this->donnees = $input[3]; + $this->cles_licences = $input[4]; + $this->total_main_d_oeuvre = (float)$input[5]; + $this->pieces = $input[6]; + $this->total_pieces = (float)$input[7]; + $this->deplacement = (float)$input[8]; + $this->total_HT = (float)$input[9]; + } + private function setServiceFromQuotation(array $input) // private? + { + $this->machine = $input[0]; + $this->OS = $input[1]; + $this->donnees = $input[2]; + $this->cles_licences = $input[3]; + } + + // à mettre plus tard dans une classe mère + protected function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } + // à mettre plus tard dans une classe mère + public function hydrate(string $answers) + { + $answers = $this->cleanSpecialChars($answers); // possibilité que $answers devienne une chaine vide + if($answers == '') + { + echo "erreur de Facture::hydrate(), la chaine \$answers est vide.\n"; + return false; + } + $data_array = explode('|', $answers); // array + + $check = false; + if(count($data_array) === 11) // facture normale + { + $this->getPresta()->setModePaiement($data_array[10]); + //array_pop($data_array); // supprime la dernière case + unset($data_array[10]); + $this->setAll($data_array); + } + elseif(count($data_array) === 5) // facture à partir d'un devis + { + $this->getPresta()->setModePaiement($data_array[4]); + unset($data_array[4]); + $this->setServiceFromQuotation($data_array); + } + else + { + echo "erreur de Facture::hydrate(), le tableau \$data_array n'a pas la taille attendue.\n"; + return false; + } + + //self::$entityManager->persist('Prestation'); + self::$entityManager->persist($this); // $Presta avec en cascade! + self::$entityManager->flush(); + } + + public function hydrateWithQuotation(Devis $QuotationDetails) + { + $data = $QuotationDetails->getAll(); + //var_dump($data);die; + $this->taches = $data['taches']; + $this->total_main_d_oeuvre = $data['total_main_d_oeuvre']; + $this->pieces = $data['pieces']; + $this->total_pieces = $data['total_pieces']; + $this->deplacement = $data['deplacement']; + $this->total_HT = $data['total_HT']; + } +} diff --git a/src/model/entities/Location.php b/src/model/entities/Location.php new file mode 100644 index 0000000..7ce6f0d --- /dev/null +++ b/src/model/entities/Location.php @@ -0,0 +1,209 @@ +setPresta($presta); + } + } + + // getters + public function getPresta(): Prestation + { + return $this->presta; + } + public function getAll(): array + { + // n'utiliser get_object_vars() qu'avec une entité parce qu'on maîtrise le nombre de propriétés + return get_object_vars($this); + } + + public function getAllWithWindowFields(): array + { + return [ + "Désignation:" => $this->designation, + "Description du modèle:" => $this->modele_description, + "Valeur:" => $this->valeur, + "État des lieux de début:" => $this->etat_des_lieux_debut, + "État des lieux de fin:" => $this->etat_des_lieux_fin, + "Durée de la location:" => $this->duree_location, + "Loyer Hebdomadaire:" => $this->loyer_hebdo, + "Loyers Payés:" => $this->loyers_payes, + "Caution:" => $this->caution]; + } + + // setters + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaîne vide + switch($entry) + { + case "Désignation:": + $this->setDesignation($input); + break; + case "Description du modèle:": + $this->setModeleDescription($input); + break; + case "Valeur:": + $this->setValeur($input); + break; + case "État des lieux de début:": + $this->setEtatDesLieuxDebut($input); + break; + case "État des lieux de fin:": + $this->setEtatDesLieuxFin($input); + break; + case "Durée de la location:": + $this->setDureeLocation($input); + break; + case "Loyer Hebdomadaire:": + $this->setLoyerHebdo($input); + break; + case "Loyers Payés:": + $this->setLoyersPayes($input); + break; + case "Caution:": + $this->setCaution($input); + break; + } + } + private function setPresta(Prestation $input) // private? + { + $this->presta = $input; + } + public function setDesignation(string $value) + { + $this->designation = $value; + return($this); + } + public function setModeleDescription(string $value) + { + $this->modele_description = $value; + return($this); + } + public function setValeur($value) + { + $value = str_replace(',', '.', $value); + $this->valeur = (float) $value; + return($this); + } + public function setEtatDesLieuxDebut(string $value) + { + $this->etat_des_lieux_debut = $value; + return($this); + } + public function setEtatDesLieuxFin(string $value) + { + $this->etat_des_lieux_fin = $value; + return($this); + } + public function setDureeLocation(string $value) + { + $this->duree_location = $value; + return($this); + } + public function setLoyerMensuel($value) + { + $value = str_replace(',', '.', $value); + $this->loyer_mensuel = (float) $value; + return($this); + } + public function setLoyersPayes($value) + { + $value = str_replace(',', '.', $value); + $this->loyers_payes = (float) $value; + return($this); + } + public function setCaution($value) + { + $value = str_replace(',', '.', $value); + $this->caution = (float) $value; + return($this); + } + + private function setAll(array $input) // private? + { + $this->designation = $input[0]; + $this->modele_description = $input[1]; + $this->valeur = (float)$input[2]; + $this->etat_des_lieux_debut = $input[3]; + $this->etat_des_lieux_fin = ''; // sécurité + $this->duree_location = $input[4]; + $this->loyer_hebdo = (float)$input[5]; + $this->loyers_payes = (int)$input[6]; + $this->caution = (int)$input[7]; + } + + // à mettre plus tard dans une classe mère + protected function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } + // à mettre plus tard dans une classe mère + public function hydrate(string $answers) + { + $answers = $this->cleanSpecialChars($answers); // possibilité que $answers devienne une chaine vide + if($answers == '') + { + echo "erreur de Location::hydrate(), la chaine \$answers est vide.\n"; + return false; + } + $data_array = explode('|', $answers); // array + + $check = false; + if(count($data_array) === 8) + { + $this->getPresta()->setModePaiement(''); // sécurité, doctrine plante si "null" + $this->setAll($data_array); + } + else + { + echo "erreur de Location::hydrate(), le tableau \$data_array n'a pas la taille attendue.\n"; + return false; + } + + //self::$entityManager->persist('Prestation'); + self::$entityManager->persist($this); // $Presta avec en cascade! + self::$entityManager->flush(); + } +} diff --git a/src/model/entities/Prestation.php b/src/model/entities/Prestation.php new file mode 100644 index 0000000..6d014d8 --- /dev/null +++ b/src/model/entities/Prestation.php @@ -0,0 +1,252 @@ +setClient($client); + } + } + + // getters + public function getId(): int + { + return $this->id; + } + public function getCodePresta(): string + { + return $this->code_presta; + } + public function getDate(): int + { + return $this->date; + } + public function getTypePresta(): string + { + return $this->type_presta; + } + public function getClient(): Client + { + return $this->client; + } + public function getAll(): array + { + // n'utiliser get_object_vars() qu'avec une entité parce qu'on maîtrise le nombre de propriétés + return get_object_vars($this); + } + + public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) + { + $code_presta_tableau = explode('-', $this->code_presta); + $Date = new Dates($this->date); + + return [ + //"Numéro prestation:" => end($code_presta_tableau), // crée des conflits, calcul automatique par setCodePresta() + "Date:" => $Date->getDate(), + //"Type de Presta:" => $this->type_presta, // choix impossible pour le moment + "Mode de paiement:" => $this->mode_paiement, // non pertinent pour un devis + "Commentaires:" => $this->commentaires]; + } + + // setters + //~ public function setCodePresta(string $value) + //~ { + //~ $this->code_presta = $value; + //~ return $this; + //~ } + //public function setDate(int $value) + public function setDate(Dates $Date) + { + //$this->date = (int)$value; // attend un timestamp + $this->date = $Date->getTimestamp(); + return $this; + /*if($set_code_presta) + { + $code_presta_tableau = explode('-', $this->code_presta); + $Date = new Dates($value); + $code_presta_tableau[0] = $Date->getYear(); + $code_presta_tableau[1] = $Date->getMonth(); + $code_presta_tableau[2] = $Date->getDay(); + $this->code_presta = implode('-', $code_presta_tableau); + }*/ + } + + public function setTypePresta(string $value) // appelée dans la section 2 uniquement, pour la 3 on verra plus tard + { + $this->type_presta = $value; + return $this; + } + public function setModePaiement(string $value) + { + $this->mode_paiement = $value; + return $this; + } + public function setCommentaires(string $input) + { + $this->commentaires = $input; + } + /*public function setAll(array $input) + { + $this->code_presta = $input[0]; + $this->date = $input[1]; + $this->type_presta = $input[2]; + $this->mode_paiement = $input[3]; + $this->commentaires = $input[4]; + }*/ + + private function setClient(Client $input) // private? + { + $this->client = $input; + //$input->typeToClient(); // on modifie $client ici (merci les références PHP) + } + + public function set(string $entry, $input) // $input = chaîne ou entier + { + if(gettype($input) === 'string') + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + } + switch($entry) + { + // pas de cas "code presta" qui généré par setCodePresta, on peut modifier la date (ici) et le code client (ailleurs) + //~ case "Numéro prestation:": + //~ $this->setNumeroPresta($input); + //~ // modifier le code presta en conséquence + //~ break; + case "Date:": // inutile, setDate() est appelé directement après choix fenêtre calendrier + $this->setDate($input); + break; + //~ case "Type de Presta:": // choix impossible pour le moment + //~ $this->setTypePresta($input); + //~ break; + case "Mode de paiement:": + $this->setModePaiement($input); + break; + case "Commentaires:": + $this->setCommentaires($input); + break; + } + } + + // code presta = année-mois-jour-codeclient-typedepresta-combientièmefois + public function setCodePresta(int $increment) // 0 pour modif, 1 pour nouvelle presta + { + $Date = new Dates($this->date); + $repository = self::$entityManager->getRepository('Prestation'); // prestas de tout type d'un client + // attention: il peut y avoir plusieurs prestations avec le même numéro au compteur, à améliorer + $combientieme_fois = count($repository->findBy(['client' => $this->client->getId()])) + $increment; + //var_dump($combientieme_fois); + $array_code = [$Date->getYear(), $Date->getMonth(), $Date->getDay(), $this->client->getCodeClient(), $this->type_presta, $combientieme_fois]; + //~ $array_code[0] = $Date->getYear(); + //~ $array_code[1] = $Date->getMonth(); + //~ $array_code[2] = $Date->getDay(); + //~ $array_code[3] = $this->client->getCodeClient(); // mise à jour éventuelle + //~ $array_code[4] = $this->type_presta; + $this->code_presta = implode('-', $array_code); + return $this; + } + // combientième fois au choix (ne fonctionne pas avec setCodePresta qui recalculera ce numéro automatiquement à la prochaine modification) + //~ public function setNumeroPresta($value) + //~ { + //~ // modifier le code presta, on pourrait aussi utiliser une regex + //~ $code_presta_tableau = explode('-', $this->code_presta); + //~ $code_presta_tableau[count($code_presta_tableau) - 1] = (int) $value; // dernière case du tableau + //~ $this->code_presta = implode('-', $code_presta_tableau); + //~ return $this; + //~ } + + public static function getServices(Client $Customer, string $type = '') + { + echo "debug: recherche d'une prestation\n"; + + // requête DQL qui fait la même chose que le findBy plus bas + /*$query = self::$entityManager->createQuery('SELECT u FROM Prestation u WHERE u.client = :id_client AND u.type_presta = :type_presta'); + $query->setParameter('id_client', $Customer->getId()); + $query->setParameter('type_presta', $type); + $query_result = $query->getResult(); + var_dump($query_result);die;*/ + + $repository = self::$entityManager->getRepository('Prestation'); + $find_by = ['client' => $Customer->getId()]; + if($type != '') + { + $find_by['type_presta'] = 'devis'; + } + $PrestaList = $repository->findBy($find_by); + + // le même tableau avec pour clés les id des objets + $PrestaListIdKeys = []; + foreach($PrestaList as $Presta) + { + $id = $Presta->getId(); + $PrestaListIdKeys[$id] = $Presta; + } + + // fenêtre + $entrees = []; + foreach($PrestaListIdKeys as $Presta) + { + $id = $Presta->getId(); + $entrees[$id][] = $id; + $Date = new Dates((int)$Presta->getDate()); // envoi du timestamp, (int) est là par sécurité + $entrees[$id][] = $Date->getDate(); + $entrees[$id][] = $Presta->getTypePresta(); + $entrees[$id][] = $Presta->getCodePresta(); + } + + // pas à la bonne place, couper la fonction en deux et mettre ça ailleurs! + $ResultatsRecherchePresta = new ZenityList(ZenitySetup::$resultats_recherche_presta['text'], []); + $ResultatsRecherchePresta->setListRows($entrees, 4); + + // choix de l'utilisateur + $input = exec($ResultatsRecherchePresta->get()); // $input est l'ID de la prestation + //echo "input = " . $input . "\n"; + if($input == '') + { + echo "debug: recherche annulée ou saisie vide\n"; + return 0; + } + else + { + return $PrestaListIdKeys[$input]; + } + } + + // à mettre plus tard dans une classe mère + private function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } +} diff --git a/src/model/version 0.1/CESU.php b/src/model/version 0.1/CESU.php new file mode 100644 index 0000000..2768b8f --- /dev/null +++ b/src/model/version 0.1/CESU.php @@ -0,0 +1,66 @@ +table = strtolower(__CLASS__); // cesu + } + + public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) + { + return [ + "Tâche effectuée:" => $this->taches, + "Durée du travail:" => $this->duree_travail, + "Salaire:" => $this->salaire]; + } + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + switch($entry) + { + case "Tâche effectuée:": + $this->setTaches($input); + break; + case "Durée du travail:": + $this->setDureeTravail($input); + break; + case "Salaire:": + $this->setSalaire($input); + break; + } + } + + // setters + public function setIdPresta(int $value) + { + $this->id_presta = $value; + return($this); + } + public function setTaches(string $value) + { + $this->taches = $value; + return($this); + } + public function setDureeTravail(string $value) + { + $this->duree_travail = $value; + return($this); + } + public function setSalaire($value) + { + $value = str_replace(',', '.', $value); + $this->salaire = (float) $value; + return($this); + } +} diff --git a/src/model/version 0.1/Clients.php b/src/model/version 0.1/Clients.php new file mode 100644 index 0000000..32cf0c5 --- /dev/null +++ b/src/model/version 0.1/Clients.php @@ -0,0 +1,168 @@ +table = strtolower(__CLASS__); // clients + } + + // getters + public function getId(): int + { + return $this->id; + } + public function getCodeClient(): string + { + return $this->code_client; + } + public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) + { + return [ + "Prénom Nom:" => $this->prenom_nom, + "Code client (J.C.Dusse):" => $this->code_client, + "Adresse:" => $this->adresse, + "Code postal:" => $this->code_postal, + "Ville:" => $this->ville, + "Telephone:" => $this->telephone, + "Courriel:" => $this->courriel, + "À propos:" => $this->apropos, + "Client ou Prospect?" => $this->type]; + } + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + switch($entry) + { + case "Prénom Nom:": + $this->setPrenomNom($input); + break; + case "Code client (J.C.Dusse):": + $this->setCodeClient($input); + break; + case "Adresse:": + $this->setAdresse($input); + break; + case "Code postal:": + $this->setCodePostal($input); + break; + case "Ville:": + $this->setVille($input); + break; + case "Telephone:": + $this->setTelephone($input); + break; + case "Courriel:": + $this->setCourriel($input); + break; + case "À propos:": + $this->setApropos($input); + break; + case "Client ou Prospect?": + $this->setType($input); + break; + } + } + + // setters + public function setPrenomNom($value) + { + $this->prenom_nom = (string) $value; + return $this; + } + public function setCodeClient($value) + { + $this->code_client = (string) $value; + return $this; + } + public function setAdresse($value) + { + $this->adresse = (string) $value; + return $this; + } + public function setCodePostal($value) + { + $this->code_postal = (string) $value; + return $this; + } + public function setVille($value) + { + $this->ville = (string) $value; + return $this; + } + public function setTelephone($value) + { + // type string parce que: + // - zenity renvoie une chaine + // - permet de garder le 0 au début et d'inscrire plusieurs numéros + $this->telephone = (string) $value; + return $this; + } + public function setCourriel($value) + { + $this->courriel = (string) $value; + return $this; + } + public function setApropos($value) + { + $this->apropos = (string) $value; + return $this; + } + public function setType($value) + { + $this->type = (string) $value; + return $this; + } + + public function typeToClient(): bool + { + if($this->type != 'client') + { + $this->type = 'client'; + return true; + } + else + { + return false; + } + } + + public function findByKeywords(array $keywords, string $field): array // n'hydrate pas les variables, on doit choisir un client et hydrater ensuite + { + $result = []; + for($i = 0; $i < count($keywords); $i++) + { + // tableau à deux dimensions obtenu pour un mot clé + $query_result = $this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field . ' LIKE "%' . $keywords[$i] . '%"')->fetchAll(); + foreach($query_result as $one_array) // pour chaque sous tableau + { + $already_exist = false; + for($j = 0; $j < count($result); $j++) // pour chaque tableau déjà enregistré dans le tableau $result + { + if($result[$j]['id'] === $one_array['id']) + { + $already_exist = true; + } + } + if(!$already_exist) + { + $result[] = $one_array; + } + } + } + return $result; + } +} diff --git a/src/model/version 0.1/DB.php b/src/model/version 0.1/DB.php new file mode 100644 index 0000000..47407ba --- /dev/null +++ b/src/model/version 0.1/DB.php @@ -0,0 +1,48 @@ + PDO::$dsn + //$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8'); // pour mysql/mariadb + $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // $this pour la méthode du parent PDO + $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // pour PDO:fetch() et PDO::fetchAll() + // avec PDO::FETCH_ASSOC on obtient un tableau associatif, marche très bien puisqu'on utilise déjà des ID avec incrémentation automatique + // avec PDO::FETCH_BOTH (par défaut) on récupère les données en double (identifiants partant de 0 + tableau associatif) + } + catch(PDOException $e) + { + die("Impossible de se connecter à la base de données.\n" . $e->getMessage()); + } + } + + // créer son objet depuis Model avec: $db = parent::getInstance(); + public static function getInstance(): self + { + if(self::$Instance === null) + { + self::$Instance = new self; + } + return self::$Instance; + } +} diff --git a/src/model/version 0.1/DevisFactures.php b/src/model/version 0.1/DevisFactures.php new file mode 100644 index 0000000..06a0a59 --- /dev/null +++ b/src/model/version 0.1/DevisFactures.php @@ -0,0 +1,215 @@ +table = $table; // deux tables séparées devis et factures + } + + public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) + { + $taches = ["Tâches:" => $this->taches]; + $champs_communs = [ + "Total Main d'oeuvre:" => $this->total_main_d_oeuvre, + "Pièces:" => $this->pieces, + "Total des pièces:" => $this->total_pieces, + "Déplacement:" => $this->deplacement, + "Total HT:" => $this->total_HT]; + + if($this->table === 'factures') + { + $champs_facture = [ + "PC:" => $this->machine, + "OS:" => $this->OS, + "Données:" => $this->donnees, + "Clés de licences:" => $this->cles_licences]; + + return $taches + $champs_facture + $champs_communs; + } + elseif($this->table === 'devis') + { + $champs_devis = [ + "Delai de livraison:" => $this->delai_livraison, + "Durée de validité:" => $this->validite_devis, + "Devis signé:" => $this->signature_devis]; + + return $champs_communs + $champs_devis; + } + else + { + return []; + } + } + + public function set(string $entry, string $input) // trouve la bonne méthode + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + switch($entry) + { + case "Tâches:": + $this->setTaches($input); + break; + case "PC:": + $this->setMachine($input); + break; + case "OS:": + $this->setOS($input); + break; + case "Données:": + $this->setDonnees($input); + break; + case "Clés de licences:": + $this->setClesLicences($input); + break; + case "Total Main d'oeuvre:": + $this->setTotalMainDOeuvre($input); + break; + case "Pièces:": + $this->setPieces($input); + break; + case "Total des pièces:": + $this->setTotalPieces($input); + break; + case "Déplacement:": + $this->setDeplacement($input); + break; + case "Prix du devis:": + $this->setPrixDevis($input); + break; + case "Total HT:": + $this->setTotalHT($input); + break; + case "Delai de livraison:": + $this->setDelaiLivraison($input); + break; + case "Durée de validité:": + $this->setValiditedevis($input); + break; + case "Devis signé:": + $this->setSignatureDevis($input); + break; + } + } + + // setters + //~ public function setId(int $value = 0) + //~ { + //~ $this->id = $value; + //~ return($this); + //~ } + public function setIdPresta(int $value) + { + $this->id_presta = $value; + return($this); + } + public function setTaches(string $value) + { + $this->taches = $value; + return($this); + } + public function setMachine(string $value) + { + $this->machine = $value; + return($this); + } + public function setOS(string $value) + { + $this->OS = $value; + return($this); + } + public function setDonnees(string $value) + { + $this->donnees = $value; + return($this); + } + public function setClesLicences(string $value) + { + $this->cles_licences = $value; + return($this); + } + public function setTotalMainDOeuvre($value) + { + $value = str_replace(',', '.', $value); + $this->total_main_d_oeuvre = (float) $value; // float "nettoie" tous les caractères après le dernier chiffre trouvé (ex: 50€ => 50, abc => 0) + return($this); + } + public function setPieces(string $value) + { + $this->pieces = $value; + return($this); + } + public function setTotalPieces($value) + { + $value = str_replace(',', '.', $value); + $this->total_pieces = (float) $value; + return($this); + } + public function setDeplacement($value) + { + $value = str_replace(',', '.', $value); + $this->deplacement = (float) $value; + return($this); + } + public function setTotalHT($value) + { + $value = str_replace(',', '.', $value); + $this->total_HT = (float) $value; + return($this); + } + public function setPrixDevis($value) + { + $value = str_replace(',', '.', $value); + $this->prix_devis = (float) $value; + return($this); + } + public function setDelaiLivraison(string $value) + { + $this->delai_livraison = $value; + return($this); + } + public function setValiditedevis(string $value) + { + $this->validite_devis = $value; + return($this); + } + public function setSignatureDevis(string $value) + { + $this->signature_devis = $value; + return($this); + } + + // création d'une facture à partir d'un devis + public function hydrateReceiptWithQuotation($ReceiptDetails) + { + $ReceiptDetails->hydrate([ + 'taches' => $this->taches, + 'total_main_d_oeuvre' => $this->total_main_d_oeuvre, + 'pieces' => $this->pieces, + 'total_pieces' => $this->total_pieces, + 'deplacement' => $this->deplacement, + 'total_HT' => $this->total_HT + ]); + } +} diff --git a/src/model/version 0.1/Locations.php b/src/model/version 0.1/Locations.php new file mode 100644 index 0000000..c6b8deb --- /dev/null +++ b/src/model/version 0.1/Locations.php @@ -0,0 +1,127 @@ +table = strtolower(__CLASS__); // locations + } + + public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) + { + return [ + "Désignation:" => $this->designation, + "Description du modèle:" => $this->modele_description, + "Valeur:" => $this->valeur, + "État des lieux de début:" => $this->etat_des_lieux_debut, + "État des lieux de fin:" => $this->etat_des_lieux_fin, + "Durée de la location:" => $this->duree_location, + "Loyer Mensuel:" => $this->loyer_mensuel, + "Loyers Payés:" => $this->loyers_payes, + "Caution:" => $this->caution]; + } + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + switch($entry) + { + case "Désignation:": + $this->setDesignation($input); + break; + case "Description du modèle:": + $this->setModeleDescription($input); + break; + case "Valeur:": + $this->setValeur($input); + break; + case "État des lieux de début:": + $this->setEtatDesLieuxDebut($input); + break; + case "État des lieux de fin:": + $this->setEtatDesLieuxFin($input); + break; + case "Durée de la location:": + $this->setDureeLocation($input); + break; + case "Loyer Mensuel:": + $this->setLoyerMensuel($input); + break; + case "Loyers Payés:": + $this->setLoyersPayes($input); + break; + case "Caution:": + $this->setCaution($input); + break; + } + } + + // setters + public function setIdPresta(int $value) + { + $this->id_presta = $value; + return($this); + } + public function setDesignation(string $value) + { + $this->designation = $value; + return($this); + } + public function setModeleDescription(string $value) + { + $this->modele_description = $value; + return($this); + } + public function setValeur($value) + { + $value = str_replace(',', '.', $value); + $this->valeur = (float) $value; + return($this); + } + public function setEtatDesLieuxDebut(string $value) + { + $this->etat_des_lieux_debut = $value; + return($this); + } + public function setEtatDesLieuxFin(string $value) + { + $this->etat_des_lieux_fin = $value; + return($this); + } + public function setDureeLocation(string $value) + { + $this->duree_location = $value; + return($this); + } + public function setLoyerMensuel($value) + { + $value = str_replace(',', '.', $value); + $this->loyer_mensuel = (float) $value; + return($this); + } + public function setLoyersPayes($value) + { + $value = str_replace(',', '.', $value); + $this->loyers_payes = (float) $value; + return($this); + } + public function setCaution($value) + { + $value = str_replace(',', '.', $value); + $this->caution = (float) $value; + return($this); + } +} diff --git a/src/model/version 0.1/Model.php b/src/model/version 0.1/Model.php new file mode 100644 index 0000000..b3d157d --- /dev/null +++ b/src/model/version 0.1/Model.php @@ -0,0 +1,313 @@ +table; + } + + public function getAll(): array // à améliorer pour ne pas renvoyer $db et $table + { + return get_object_vars($this); // retourne les propriétés de l'objet + } + + // setters + public function setId(int $value = 0) + { + if($value === 0) + { + $this->id = $this->db->lastInsertId(); // méthode de PDO, attention lastInsertId() ne gère pas la concurence + } + else + { + $this->id = $value; + } + return $this; + } + public function setTable(string $value) + { + $this->table = $value; + return($this); + } + + public function hydrate(array $data): bool // $data = tableau associatif en entrée: nom_du_champ => valeur + { + foreach($data as $key => $value) + { + // nom du setter + // nom_propriete => setPropriete + // on sépare les mots par des espaces, ucwords met la première lettre de chaque mot en majuscule, puis on supprime les espaces + $setter_name = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); // ucwords: première lettre de chaque mot en majuscule + if(method_exists($this, $setter_name)) + { + $this->$setter_name($value); + } + else + { + echo "debug: la méthode $setter_name n'existe pas\n"; + return false; + } + } + return true; + } + + // cette fonction reçoit des données d'un tableau simple, permettant d'associer des champs de formulaires aux noms différents des champs de la BDD + // méthode lancée par des objets de type enfants + function hydrateFromForm(string $data_string, Object $Presta = NULL): bool // quand l'objet est $Details, on hydrate aussi $Presta + { + $data_string = $this->cleanSpecialChars($data_string); // possibilité que $data_string devienne une chaine vide + if($data_string !== '') + { + $data_array = explode('|', $data_string); // array + $check = false; + switch($this->getTable()) + { + case 'clients'; + if($data_array[0] == '') + { + echo "debug: données insuffisantes, le nom du client doit au minimum être renseigné\n"; + return false; + } + else + { + $check = $this->hydrate(['prenom_nom' => $data_array[0], 'code_client' => $data_array[1], 'adresse' => $data_array[2], 'code_postal' => $data_array[3], 'ville' => $data_array[4], 'telephone' => $data_array[5], 'courriel' => $data_array[6], 'apropos' => $data_array[7]]); + } + break; + case 'prestations'; // inutilisé + break; + case 'devis'; + $check = $this->hydrate(['taches' => $data_array[0], 'total_main_d_oeuvre' => $data_array[1], 'pieces' => $data_array[2], 'total_pieces' => $data_array[3], 'deplacement' => $data_array[4], 'prix_devis' => $data_array[5], 'total_HT' => $data_array[6], 'delai_livraison' => $data_array[7], 'validite_devis' => $data_array[8]]); + break; + case 'factures'; + if(count($data_array) === 11) + { + $check = $Presta->hydrate(['mode_paiement' => $data_array[10]]); + if($check) + { + $check = $this->hydrate(['taches' => $data_array[0], 'machine' => $data_array[1], 'OS' => $data_array[2], 'donnees' => $data_array[3], 'cles_licences' => $data_array[4], 'total_main_d_oeuvre' => $data_array[5], 'pieces' => $data_array[6], 'total_pieces' => $data_array[7], 'deplacement' => $data_array[8], 'total_HT' => $data_array[9]]); + } + } + elseif(count($data_array) === 5) // facture à partir d'un devis + { + $check = $this->hydrate(['machine' => $data_array[0], 'OS' => $data_array[1], 'donnees' => $data_array[2], 'cles_licences' => $data_array[3]]); + if($check) + { + $check = $Presta->hydrate(['mode_paiement' => $data_array[4]]); + } + } + else + { + echo "debug: le tableau \$data_array n'a pas la taille attendue.\n"; + return false; + } + break; + case 'cesu'; + $check = $Presta->hydrate(['mode_paiement' => $data_array[3]]); + if($check) + { + $check = $this->hydrate(['taches' => $data_array[0], 'duree_travail' => $data_array[1], 'salaire' => $data_array[2]]); + } + break; + case 'locations'; + $check = $this->hydrate(['designation' => $data_array[0], 'modele_description' => $data_array[1], 'valeur' => $data_array[2], 'etat_des_lieux_debut' => $data_array[3], 'etat_des_lieux_fin' => $data_array[4], 'duree_location' => $data_array[5], 'loyer_mensuel' => $data_array[6], 'loyers_payes' => $data_array[7], 'caution' => $data_array[8]]); + break; + default: // inutilisé + echo "debug: table inconnue hydrateFromForm()"; + return false; + } + return $check; + } + else + { + echo "debug: annulation lors du formulaire\n"; + return false; + } + } + + protected function cleanSpecialChars(string $data): string + { + $search = ['"']; + return str_replace($search, '', $data); + } + + + // exécuter le SQL + // les $attributs correspondent aux ? dans les requêtes préparées + // ne pas surcharger la méthode PDO::query() qui n'est pas compatible + protected function execQuery(string $sql, array $attributes = null) + { + $this->db = parent::getInstance(); // parent::, self:: et DB:: sont équivalents + + if($attributes !== null) // requête préparée + { + //~ var_dump($sql); + //~ var_dump($attributes); + $query = $this->db->prepare($sql); + $query->execute($attributes); + return $query; + } + else // requête simple + { + return $this->db->query($sql); + } + } + + + // méthodes CRUD + + // create INSERT + public function create() // = write + { + $fields = []; + $question_marks = []; // ? + $values = []; + //~ var_dump($this); + foreach($this as $field => $value) + { + //~ var_dump($field); var_dump($value); + // champs non renseignées et variables de l'objet qui ne sont pas des champs + // note: avec le !== (au lieu de !=) une valeur 0 est différente de null + if($value !== null && $field != 'db' && $field != 'table') + { + $value = $this->clean_for_bash($value); // pour la BDD + $this->$field = $value; // pour latex + + $fields[] = $field; // push + $question_marks[] = '?'; + $values[] = $value; + } + } + $field_list = implode(', ', $fields); + $question_mark_list = implode(', ', $question_marks); + + // INSERT INTO annonces (titre, description, actif) VALUES (?, ?, ?) + return($this->execQuery('INSERT INTO ' . $this->table . ' (' . $field_list . ') VALUES (' . $question_mark_list . ')', $values)); + } + + + // read SELECT + protected function readAll(): array // obtenir une table + { + return($this->execQuery('SELECT * FROM ' . $this->table)->fetchAll()); // fonctionne aussi sans le point virgule dans le SQL!! + } + + public function findById() // obtenir une entrée grace à son ID + { + return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id = ' . $this->id)->fetch()); + } + public function getDetailsByIdPresta() + { + if($this->table == 'prestations') + { + // à l'occaz, créer une classe NonVendue et rendre Prestations abstraite + echo 'erreur: ne pas appeler Model::getDetailsByIdPresta() si la table ciblée est "prestations".'; + return 0; + } + else + { + return $this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id_Presta = ' . $this->id_presta)->fetch(); // type array + } + } + + protected function find(array $criteria): array // obtenir une entrée avec un tableau associatif 'champ' => 'valeur' + { + $fields = []; + $values = []; + + // change "'id' => 2" en "'id' = ?" et "2" + foreach($criteria as $field => $value) + { + $fields[] = "$field = ?"; // même chose que: $field . " = ?" + $values[] = $value; + } + $field_list = implode(' AND ', $fields); // créer une chaîne reliant les morceaux avec le morceau AND en paramètre: 'adresse = ? AND id = ?' + + // SELECT * FROM annonces WHERE actif = 1; + return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field_list, $values)->fetchAll()); + } + + + // update UPDATE + public function update() + { + $fields = []; + $values = []; + foreach($this as $field => $value) + { + if($value !== null && $field != 'db' && $field != 'table') // champs non renseignées et variables de l'objet qui ne sont pas des champs + { + $value = $this->clean_for_bash($value); // pour la BDD + $this->$field = $value; // pour latex + + $fields[] = $field . ' = ?'; + $values[] = $value; + } + } + $values[] = $this->id; // cette syntaxe ajoute une valeur au tableau + $field_list = implode(', ', $fields); + + // UPDATE annonces SET titre = ?, description = ?, actif = ? WHERE id = ? + return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field_list . ' WHERE id = ?', $values)); + } + + public function updateOneValue(string $field, $value) + { + return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field . ' = ? WHERE id = ?', [$value, $this->id])); + } + + + // delete DELETE + protected function delete(int $id) + { + return($this->execQuery("DELETE FROM {$this->table} WHERE id = ?", [$id])); // double quotes "" pour insertion de variable, paramètre [$id] parce qu'on veut un tableau + } + + + private function clean_for_bash($value) + { + if(is_string($value) && $value != '') + { + do + { + $value = trim($value); + $value = preg_replace('#^-#','' , $value); // en bash une chaîne commençant par un tiret est un paramètre + } while($value[0] == ' '|| $value[0] == '-'); // chaîne commençant par un tiret puis un espace, ou même - - - - - + } + return $value; + } + + + static public function createTables() + { + static $first_time = true; + + if($first_time) // fonction normallement appelée qu'une seule fois + { + foreach(StructTablesDB::$structureOfTables as $tableName => $oneTable) + { + $query = 'CREATE TABLE IF NOT EXISTS ' . $tableName . ' ('; + foreach($oneTable as $key => $value) + { + $query .= $key . ' ' . $value . ', '; + } + $query .= 'PRIMARY KEY(ID AUTOINCREMENT));'; + parent::getInstance()->exec($query); + } + + $first_time = false; + } + else + { + echo "Model::createTables() a déjà été appelée et ne fera rien.\n"; + } + } +} diff --git a/src/model/version 0.1/Prestations.php b/src/model/version 0.1/Prestations.php new file mode 100644 index 0000000..18bc787 --- /dev/null +++ b/src/model/version 0.1/Prestations.php @@ -0,0 +1,159 @@ +id_client = $id_client; + $this->table = strtolower(__CLASS__); // prestations + } + + // getters + public function getId(): int + { + return $this->id; + } + public function getIdClient(): int + { + return $this->id_client; + } + public function getIdsByIdClient() // obtenir une entrée avec son id_client, comportement différent si le type est connu + { + $sql = 'SELECT id FROM ' . $this->table . ' WHERE id_client = ' . $this->id_client; + if($this->type_presta != '') + { + $sql .= " AND type_presta = '" . $this->type_presta . "'"; + } + $data = $this->execQuery($sql)->fetchAll(); // tableau de tableaux + + $IDs = []; // si $IDs reste vide, ne pas être de type NULL + for($i = 0; $i < count($data); $i++) + { + $IDs[$i] = $data[$i]['id']; // tableau simple + } + return($IDs); + } + public function getCodePresta(): string + { + return $this->code_presta; + } + public function getDate(): int // timestamp unix + { + return $this->date; + } + public function getTypePresta(): string + { + return $this->type_presta; + } + public function getAllWithWindowFields(): array // différent de Model::getAll() qui retourne get_object_vars($this) + { + $code_presta_tableau = explode('-', $this->code_presta); + $Date = new Dates($this->date); + + return [ + "Numéro prestation:" => end($code_presta_tableau), // dernière case + "Date:" => $Date->getDate(), + //"Type de Presta:" => $this->type_presta, // choix impossible pour le moment + "Mode de paiement:" => $this->mode_paiement, // non pertinent pour un devis + "Commentaires:" => $this->commentaires]; + } + public function set(string $entry, string $input) + { + $input = $this->cleanSpecialChars($input); // possibilité que $input devienne une chaine vide + switch($entry) + { + case "Numéro prestation:": + $this->setNumeroPresta($input); + break; + //~ case "Date:": // inutile, setDate() est appelé directement après choix fenêtre calendrier + //~ $this->setDate($input); + //~ break; + //~ case "Type de Presta:": // choix impossible pour le moment + //~ $this->setTypePresta($input); + //~ break; + case "Mode de paiement:": + $this->setModePaiement($input); + break; + case "Commentaires:": + $this->setCommentaires($input); + break; + } + } + + // setters + public function setIdClient(int $value) + { + $this->id_client = $value; + return $this; + } + //~ public function setCombientiemeFois(int $value) + //~ { + //~ $this->combientieme_fois = $value; + //~ return($this); + //~ } + public function setCodePresta(string $value) + { + $this->code_presta = $value; + return $this; + } + public function setDate($value, bool $set_code_presta = false) // attend un timestamp + { + $this->date = (int) $value; + + if($set_code_presta) + { + $code_presta_tableau = explode('-', $this->code_presta); + $Date = new Dates($value); + $code_presta_tableau[0] = $Date->getYear(); + $code_presta_tableau[1] = $Date->getMonth(); + $code_presta_tableau[2] = $Date->getDay(); + $this->code_presta = implode('-', $code_presta_tableau); + } + + return $this; + } + public function setTypePresta(string $value) + { + $this->type_presta = $value; + return $this; + } + public function setModePaiement(string $value) + { + $this->mode_paiement = $value; + return $this; + } + public function setCommentaires(string $value) + { + $this->commentaires = $this->cleanSpecialChars($value); // nettoyage ici parce que pas possible ailleurs + return $this; + } + public function setNumeroPresta($value) + { + // modifier le code presta, on pourrait aussi utiliser une regex + $code_presta_tableau = explode('-', $this->code_presta); + $code_presta_tableau[count($code_presta_tableau) - 1] = (int) $value; + $this->code_presta = implode('-', $code_presta_tableau); + return $this; + } + + // code presta = année-mois-jour-codeclient-typedepresta-combientièmefois + public function makeCodePresta(Dates $Date, string $code_client) + { + // on récupère un tableau contenant toutes les prestations d'un client tous types confondus (devis, facture, cesu, location, enregistrement sans vente) + // inconvénient: il peut y avoir plusieurs prestations avec le même numéro au compteur, à améliorer + $combientieme_fois = count($this->find(['id_client' => $this->id_client])) + 1; + + $array_code = [$Date->getYear(), $Date->getMonth(), $Date->getDay(), $code_client, $this->type_presta, $combientieme_fois]; + $this->code_presta = implode('-', $array_code); + } +} diff --git a/src/model/version 0.1/StructTablesDB.php b/src/model/version 0.1/StructTablesDB.php new file mode 100644 index 0000000..303af46 --- /dev/null +++ b/src/model/version 0.1/StructTablesDB.php @@ -0,0 +1,36 @@ + ['id' => 'INTEGER', 'prenom_nom' => 'TEXT', 'code_client' => 'TEXT', 'adresse' => 'TEXT', 'code_postal' => 'TEXT', 'ville' => 'TEXT', 'telephone' => 'TEXT', 'courriel' => 'TEXT', 'apropos' => 'TEXT', 'type' => 'TEXT DEFAULT prospect'], + 'prestations' => ['id' => 'INTEGER', 'id_client' => 'INTEGER', 'code_presta' => 'TEXT', 'date' => 'INTEGER', 'type_presta' => 'TEXT', 'mode_paiement' => 'TEXT', 'commentaires' => 'TEXT'], + 'devis' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'taches' => 'TEXT', 'total_main_d_oeuvre' => 'REAL', 'pieces' => 'TEXT', 'total_pieces' => 'REAL', 'deplacement' => 'REAL', 'prix_devis' => 'REAL', 'total_HT' => 'REAL', 'delai_livraison' => 'TEXT', 'validite_devis' => 'TEXT', 'signature_devis' => 'TEXT DEFAULT non'], + 'factures' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'taches' => 'TEXT', 'machine' => 'TEXT', 'OS' => 'TEXT', 'donnees' => 'TEXT', 'cles_licences' => 'TEXT', 'total_main_d_oeuvre' => 'REAL', 'pieces' => 'TEXT', 'total_pieces' => 'REAL', 'deplacement' => 'REAL', 'total_HT' => 'REAL'], + 'cesu' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'taches' => 'TEXT', 'duree_travail' => 'TEXT', 'salaire' => 'REAL'], + 'locations' => ['id' => 'INTEGER', 'id_presta' => 'INTEGER', 'designation' => 'TEXT', 'modele_description' => 'TEXT', 'valeur' => 'REAL', 'etat_des_lieux_debut' => 'TEXT', 'etat_des_lieux_fin' => 'TEXT', 'duree_location' => 'TEXT', 'loyer_mensuel' => 'REAL', 'loyers_payes' => 'INTEGER', 'caution' => 'INTEGER'] + ]; + + // les types de variables de sqlite sont peu nombreux et autorisent un typage automatique + // le "type indiqué" est indiqué dans l'instruction CREATE TABLE + // https://www.leppf.com/site/spip.php?article89 + + // || type indiqué || type choisi automatiquement || autre types possibles || + // --------------------------------------------------------------------------- + // || TEXT || TEXT || BLOB, NULL || + // || INTEGER || INTEGER (de 1 à 8 octets) || REAL, TEXT, BLOB, NULL || + // || REAL || REAL (flottant sur 9 octets) || TEXT, BLOB, NULL || + // || NUMERIC || INTEGER ou REAL || TEXT, BLOB, NULL || + // || NONE || indéfini || dépend des données || + + // du code SQL écrit pour d'autres SGBD devrait fonctionner, + // sqlite fera des conversions dans ses propres types avec les problèmes qu'on peut imaginer + + // pour les dates, on stockera à priori le timestamp +} diff --git a/src/sections/1_customer.php b/src/sections/1_customer.php index b0e3283..db5c448 100644 --- a/src/sections/1_customer.php +++ b/src/sections/1_customer.php @@ -3,42 +3,46 @@ // // -- SECTION 1: Fichier clients et propects -- +use Doctrine\ORM\EntityManager; + function newCustomer(): array { // fenêtres - $TypeDeClient = new ZenityList(ZenitySetup::$type_client['text'], ZenitySetup::$type_client['entrees']); + //$TypeDeClient = new ZenityList(ZenitySetup::$type_client['text'], ZenitySetup::$type_client['entrees']); + $NouveauClient = new ZenityForms(ZenitySetup::$nouveau_client['text'], ZenitySetup::$nouveau_client['entrees']); $FinSection1 = new ZenityList(ZenitySetup::$fin_section_1['text'], ZenitySetup::$fin_section_1['entrees']); - + + $Customer = new Client; + // -- partie 1: client ou prospect? -- - $Client = new Clients; - $choix_niv2 = exec($TypeDeClient->get()); - if($choix_niv2 === ZenitySetup::$type_client['entrees'][0]) - { - echo "choix: " . $choix_niv2 . "\n"; - $Client->setType('client'); - } - elseif($choix_niv2 === ZenitySetup::$type_client['entrees'][1]) - { - echo "choix: " . $choix_niv2 . "\n"; - $Client->setType('prospect'); - } - else - { - return [0, null]; // menu principal - } + //~ $choix_niv2 = exec($TypeDeClient->get()); + //~ if($choix_niv2 === ZenitySetup::$type_client['entrees'][0]) + //~ { + //~ echo "choix: " . $choix_niv2 . "\n"; + //~ $Customer->setType('client'); + //~ } + //~ elseif($choix_niv2 === ZenitySetup::$type_client['entrees'][1]) + //~ { + //~ echo "choix: " . $choix_niv2 . "\n"; + //~ $Customer->setType('prospect'); + //~ } + //~ else + //~ { + //~ return [0, null]; // menu principal + //~ } // -- partie 2: saisie des infos -- - if(enterCustomer($Client)) + if($Customer->enterCustomer($NouveauClient)) { // -- partie 3: on fait quoi maintenant -- $choix_niv3 = exec($FinSection1->get()); if($choix_niv3 === ZenitySetup::$fin_section_1['entrees'][0]) { - return [2, $Client]; // section 2: newService() + return [2, $Customer]; // section 2: newService() } elseif($choix_niv3 === ZenitySetup::$fin_section_1['entrees'][1]) { - return [3, $Client]; // section 3: modifyData() + return [3, $Customer]; // section 3: modifyData() } elseif($choix_niv3 === ZenitySetup::$fin_section_1['entrees'][2]) { diff --git a/src/sections/2_service.php b/src/sections/2_service.php index 3dd620d..e25d677 100644 --- a/src/sections/2_service.php +++ b/src/sections/2_service.php @@ -3,26 +3,33 @@ // // -- SECTION 2: Prestation et devis -- +use Doctrine\ORM\EntityManager; + function newService($Client): array // $Client est un Client ou null { + // fenêtres recherche d'un client + $RechercheClient = new zenityEntry(ZenitySetup::$recherche_client['text']); + $ResultatsRechercheClient = new ZenityList(ZenitySetup::$resultats_recherche_client['text'], []); + // fenêtres - $MenuEnregistrement = new ZenityList(ZenitySetup::$menu_enregistrement_text, ZenitySetup::$menu_enregistrement_entrees); + $MenuEnregistrement = new ZenityList(ZenitySetup::$menu_enregistrement['text'], ZenitySetup::$menu_enregistrement['entrees']); $Calendrier = new ZenityCalendar(ZenitySetup::$calendar['section2']); $FormulaireDevis = new ZenityForms(ZenitySetup::$formulaire['text'], ZenitySetup::$formulaire['devis_entrees']); $FormulaireFacture = new ZenityForms(ZenitySetup::$formulaire['text'], ZenitySetup::$formulaire['facture_entrees']); $FormulaireFactureReduit = new ZenityForms(ZenitySetup::$formulaire['text'], ZenitySetup::$formulaire['facture_entrees_reduit']); $FormulaireCesu = new ZenityForms(ZenitySetup::$formulaire['text'], ZenitySetup::$formulaire['cesu_entrees']); $FormulaireLocation = new ZenityForms(ZenitySetup::$formulaire['text'], ZenitySetup::$formulaire['location_entrees']); - $CommentairePrestation = new ZenityEntry(ZenitySetup::$commentaire_prestation_text); + $CommentairePrestation = new ZenityEntry(ZenitySetup::$commentaire_prestation['text']); //$Recapitulatif = new ZenityList(ZenitySetup::$recapitulatif_text, ZenitySetup::$recapitulatif_entrees); // tableau à multiples colonnes $FinSection2 = new ZenityList(ZenitySetup::$fin_section_2['text'], ZenitySetup::$fin_section_2['entrees']); // -- partie 1: le client -- - if($Client == null || get_class($Client) !== 'Clients') + if($Client == null || get_class($Client) !== 'Client') { - $Client = makeObjectClient(); // retourne 0 ou un objet "Clients" - if($Client == 0) + $Client = Client::getObject($RechercheClient, $ResultatsRechercheClient); // retourne un Client ou 0 + //$ResultatsRechercheClient->cleanCommand(); // inutile parce qu'on ne boucle pas dans cette fonction + if($Client === 0) { echo "debug: annulation sélection client\n"; return [0, null]; // menu principal @@ -48,49 +55,50 @@ function newService($Client): array // $Client est un Client ou null return [0, null]; // menu principal } - $Presta = new Prestations($Client->getId()); - $Presta->setDate($Date->getTimestamp()); // un entier pour la BDD + $Presta = new Prestation($Client); + //var_dump($Client);die; + //$Presta->setDate($Date->getTimestamp()); + $Presta->setDate($Date); // envoi d'un objet, la BDD gardera le timestamp // formulaire - étape 2/3 switch($choix_niv2) { // comparaison retour de $MenuEnregistrement->get() avec les noms des entrées du même menu - case ZenitySetup::$menu_enregistrement_entrees[0]: // "Devis" - $PrestaDetails = new DevisFactures('devis'); + case ZenitySetup::$menu_enregistrement['entrees'][0]: // "Devis" + $PrestaDetails = new Devis($Presta); $Presta->setTypePresta('devis'); $answers = exec($FormulaireDevis->get()); break; - case ZenitySetup::$menu_enregistrement_entrees[1]: // "Facture" - $PrestaDetails = new DevisFactures('factures'); // attention! type "facture" mais table "factures" + case ZenitySetup::$menu_enregistrement['entrees'][1]: // "Facture" + $PrestaDetails = new Facture($Presta); $Presta->setTypePresta('facture'); $answers = exec($FormulaireFacture->get()); break; - case ZenitySetup::$menu_enregistrement_entrees[2]: // "Facture à partir d'un devis" + case ZenitySetup::$menu_enregistrement['entrees'][2]: // "Facture à partir d'un devis" // recherche du devis - $Quotation = getServices($Client, 'devis'); // rechercher un devis, type 'devis' spécifié pour $Presta->getIdsByIdClient() - if(!is_object($Quotation) || get_class($Quotation) != 'Prestations' || $Quotation->getTypePresta() != 'devis') + $Quotation = Prestation::getServices($Client, 'devis'); // rechercher un devis, type 'devis' spécifié + if(!is_object($Quotation) || get_class($Quotation) != 'Prestation' || $Quotation->getTypePresta() != 'devis') { echo "debug: annulation sélection client\n"; return [2, $Client]; // menu précédent } - $QuotationDetails = new DevisFactures('devis'); - // facture: objet vide et formulaire - $PrestaDetails = new DevisFactures('factures'); + $QuotationDetails = Devis::getQuotation($Quotation); + $PrestaDetails = new Facture($Presta); + $PrestaDetails->hydrateWithQuotation($QuotationDetails); // du devis à la facture $Presta->setTypePresta('facture'); $answers = exec($FormulaireFactureReduit->get()); - //var_dump($answers); break; - case ZenitySetup::$menu_enregistrement_entrees[3]: // "CESU" - $PrestaDetails = new CESU(); + case ZenitySetup::$menu_enregistrement['entrees'][3]: // "CESU" + $PrestaDetails = new CESU($Presta); $Presta->setTypePresta('cesu'); $answers = exec($FormulaireCesu->get()); break; - case ZenitySetup::$menu_enregistrement_entrees[4]: // "Location" - $PrestaDetails = new Locations(); + case ZenitySetup::$menu_enregistrement['entrees'][4]: // "Location" + $PrestaDetails = new Location($Presta); $Presta->setTypePresta('location'); $answers = exec($FormulaireLocation->get()); break; - case ZenitySetup::$menu_enregistrement_entrees[5]: // "Prestation non vendue" + case ZenitySetup::$menu_enregistrement['entrees'][5]: // "Prestation non vendue" $Presta->setTypePresta('non_vendue'); break; default: // inutile normallement, cas déjà géré avant @@ -98,7 +106,9 @@ function newService($Client): array // $Client est un Client ou null return [0, null]; } - $Presta->makeCodePresta($Date, $Client->getCodeClient()); // d'un objet à l'autre + //$Presta->makeCodePresta($Date, $Client->getCodeClient()); // d'un objet à l'autre + //$Presta->makeCodePresta($Client->getCodeClient()); // d'un objet à l'autre + $Presta->setCodePresta(1); // d'un objet à l'autre // commentaire - étape 3/3 $comment = exec($CommentairePrestation->get()); @@ -120,48 +130,27 @@ function newService($Client): array // $Client est un Client ou null //~ } $Presta->setCommentaires($comment); - // hydratation d'une facture à partir d'un devis - if($choix_niv2 === ZenitySetup::$menu_enregistrement_entrees[2]) // cas: facture à partir d'un devis - { - // devis retrouvé ($Quotation est déjà hydraté) - $QuotationDetails->setIdPresta($Quotation->getId()); - $QuotationDetails->hydrate($QuotationDetails->getDetailsByIdPresta()); - - // facture avec le devis - $QuotationDetails->hydrateReceiptWithQuotation($PrestaDetails); - } - // hydratation avec la saisie du formulaire - if($choix_niv2 != ZenitySetup::$menu_enregistrement_entrees[5]) // cas: tous les cas sauf presta non vendue + if($choix_niv2 != ZenitySetup::$menu_enregistrement['entrees'][5]) // cas: tous les cas sauf presta non vendue { + //var_dump($answers); + $Client->typeToClient(); if($answers == '') // annulation { echo "debug: annulation lors de l'enregistrement des détails de la prestation\n"; return [0, null]; } - elseif(isset($PrestaDetails) && !$PrestaDetails->hydrateFromForm($answers, $Presta)) // echec de l'hydratation - { - echo "debug: erreur de hydrateFromForm()\n"; // messages d'erreur à mettre ici ou dans hydrateFromForm()? - return [0, null]; - } - } - - // mise à jour base de données - $Presta->create(); - $Presta->setId(); // sans paramètre, exécute un $this->db->lastInsertId() - - if(isset($PrestaDetails)) // presta vendue - { - $PrestaDetails->setIdPresta($Presta->getId()); // d'un objet à l'autre - $PrestaDetails->create(); - $PrestaDetails->setId(); // sans paramètre, exécute un $this->db->lastInsertId() + $PrestaDetails->hydrate($answers); + + // déléguer la synchronisation (flush) avec la BDD à une classe "Manager" } // si encore de type prospect, devient un type client - if($Client->typeToClient()) // utile si $Client est renvoyé dans le "return" + // déjà fait ailleurs je crois! + /*if($Client->typeToClient()) // utile si $Client est renvoyé dans le "return" { $Client->updateOneValue('type', 'client'); // base synchronisée - } + }*/ // -- partie 3: LaTeX -- @@ -213,7 +202,11 @@ function newService($Client): array // $Client est un Client ou null { return [3, $Client]; // section 3: modifyData() } - elseif($choix_niv2 === ZenitySetup::$fin_section_2['entrees'][2]) // enregistrer une autre prestation + elseif($choix_niv2 === ZenitySetup::$fin_section_2['entrees'][2]) // enregistrer une autre prestation (même client) + { + return [2, $Client]; // relancer section 2: newService() + } + elseif($choix_niv2 === ZenitySetup::$fin_section_2['entrees'][3]) // enregistrer une autre prestation (autre client) { return [2, null]; // relancer section 2: newService() } diff --git a/src/sections/3-1_windows.php b/src/sections/3-1_windows.php index 31c6cee..76d01dd 100644 --- a/src/sections/3-1_windows.php +++ b/src/sections/3-1_windows.php @@ -1,9 +1,9 @@ cleanCommand(); // inutile parce qu'on ne boucle pas dans cette fonction + //if(!is_object($Client) || !get_class($Client) == 'Client') + if($Client === 0) { echo "debug: annulation sélection client\n"; return [0, null]; // menu principal @@ -26,7 +34,7 @@ function modifyData($Client): array // -- partie 2: modifier un client -- - // fenêtre + // fenêtre dynamique $ModificationClientMenu = makeModifyCustomerWindow($Client); $choix_niv2 = exec($ModificationClientMenu->get()); @@ -53,20 +61,22 @@ function modifyData($Client): array { echo "choix: annulation\n"; } - $Client->update(); + Client::$entityManager->flush(); // à mettre dans une classe Manager + return [3, $Client]; // menu précédent } - elseif(is_string($choix_niv2) && $choix_niv2 != '') // autres choix, modifier une valeur + elseif(is_string($choix_niv2) && $choix_niv2 != '') // modifier autre chose chez le client { - echo "choix: modifier" . $choix_niv2 . "\n"; + echo "choix: modifier " . $choix_niv2 . "\n"; $ModificationClient = new ZenityEntry($choix_niv2); $input = exec($ModificationClient->get()); if(is_string($input) && $input != '') { + // entités et BDD $Client->set($choix_niv2, $input); - $Client->update(); + $Client::$entityManager->flush(); - // mettre à jour les documents (il faudrait modifier tous les documents!!) + // documents (les factures, etc, ne sont pas modifiées ici) $EnveloppeRecto = Latex::makeInstance('enveloppe_recto'); $EnveloppeRecto->setData($Client); $EnveloppeRecto->makeLatex(); @@ -86,36 +96,35 @@ function modifyData($Client): array // -- partie 3: rechercher une prestation -- - $Presta = getServices($Client); // = 0 ou type "Prestations" - if(!is_object($Presta) || !get_class($Presta) == 'Prestations') + $Presta = Prestation::getServices($Client); // = 0 ou type "Prestation" + if(!is_object($Presta) || !get_class($Presta) == 'Prestation') { - echo "debug: annulation sélection client\n"; + echo "debug: annulation sélection d'une prestation\n"; return [3, $Client]; // menu précédent } - - $type = $Presta->getTypePresta(); - switch($type) + $type_presta = $Presta->getTypePresta(); + switch($type_presta) { case 'facture': - $PrestaDetails = new DevisFactures('factures'); + $classe = 'Facture'; break; case 'devis': - $PrestaDetails = new DevisFactures('devis'); + $classe = 'Devis'; break; case 'cesu': - $PrestaDetails = new CESU(); + $classe = 'CESU'; break; case 'location': - $PrestaDetails = new Locations(); + $classe = 'Location'; break; case 'non_vendue': $PrestaDetails = null; break; } - if($type != 'non_vendue') + if($type_presta != 'non_vendue') { - $PrestaDetails->setIdPresta($Presta->getId()); - $PrestaDetails->hydrate($PrestaDetails->getDetailsByIdPresta()); + $repository = $classe::$entityManager->getRepository($classe); + $PrestaDetails = $repository->findOneBy(['presta' => $Presta->getId()]); } @@ -125,11 +134,7 @@ function modifyData($Client): array $ModificationPrestaMenu = makeModifyServiceWindow($Presta, $PrestaDetails); $choix_niv3 = exec($ModificationPrestaMenu->get()); - //~ if($choix_niv3 === ZenitySetup::$modification_presta['devis_facture']) // devis -> facture - //~ { - //~ echo "choix: changer un devis en facture\n"; - //~ return [2, $Client]; // menu "client" - //~ } + if($choix_niv3 === 'Date:') { $Date = new Dates(exec($Calendrier->get())); // exec() renvoie soit une chaîne soit un false @@ -139,50 +144,60 @@ function modifyData($Client): array } else { - // mettre à jour la base de données - $Presta->setDate($Date->getTimestamp(), true); // un entier pour la BDD, "true" pour modifier le code_presta - $Presta->update(); + // entités et BDD + $Presta->set($choix_niv3, $Date); + $old_code = $Presta->getCodePresta(); + $Presta->setCodePresta(0); + $Presta::$entityManager->flush(); - // mettre à jour les documents - if($type === 'devis' || $type === 'facture' || $type === 'location') + // documents + if($type_presta === 'devis' || $type_presta === 'facture' || $type_presta === 'location') { $DocumentPresta = Latex::makeInstance($Presta->getTypePresta()); // $type = facture, devis, location $DocumentPresta->setData($Client)->setData($Presta)->setData($PrestaDetails); - $DocumentPresta->makeLatex(); - makeTexAndPdf($DocumentPresta); + $DocumentPresta->makeLatex(); // en mémoire + + renameFiles($DocumentPresta, $old_code, $Presta->getCodePresta()); + makeTexAndPdf($DocumentPresta); // une nouvelle facture est créée, supprimer l'ancienne ou la renommer avec la nouvelle date } } return [3, $Client]; // menu précédent } - //~ elseif($choix_niv3 === 'Type de Presta:') // choix impossible pour le moment + //~ elseif($choix_niv3 === 'Type de Presta:') // compliqué! choix impossible pour le moment //~ { //~ echo "choix: changer le type de prestation (devis, facture, etc)\n"; //~ return [3, $Client]; // menu "client" //~ } elseif(is_string($choix_niv3) && $choix_niv3 != '') // modifier une valeur { - echo "choix: modifier" . $choix_niv3 . "\n"; + echo "choix: modifier " . $choix_niv3 . "\n"; $ModificationPrestaForm = new ZenityEntry($choix_niv3); $input = shell_exec($ModificationPrestaForm->get()); // shell_exec() retourne null si la commande échoue, exec() retourne la dernière ligne de texte en sortie ou null si aucune commande ne réussit - if(is_string($input)) // chaine vide autorisée + if(is_string($input)) // chaîne vide autorisée { - // mettre à jour la base de données + // entités et BDD $Presta->set($choix_niv3, $input); - $Presta->update(); - - if($type != 'non_vendue') + $old_code = $Presta->getCodePresta(); + $Presta->setCodePresta(0); + if($type_presta != 'non_vendue') { $PrestaDetails->set($choix_niv3, $input); - $PrestaDetails->update(); + $PrestaDetails::$entityManager->flush(); + } + else + { + $Presta::$entityManager->flush(); } - // mettre à jour les documents - if($type === 'devis' || $type === 'facture' || $type === 'location') + // documents + if($type_presta === 'devis' || $type_presta === 'facture' || $type_presta === 'location') { - $DocumentPresta = Latex::makeInstance($type); + $DocumentPresta = Latex::makeInstance($type_presta); $DocumentPresta->setData($Client)->setData($Presta)->setData($PrestaDetails); $DocumentPresta->makeLatex(); + + renameFiles($DocumentPresta, $old_code, $Presta->getCodePresta()); makeTexAndPdf($DocumentPresta); } } diff --git a/src/sections/4_get_document.php b/src/sections/4_get_document.php index baad117..e682d26 100644 --- a/src/sections/4_get_document.php +++ b/src/sections/4_get_document.php @@ -5,32 +5,32 @@ function getOrPrintDocument(): array { - $MenuDocuments = new ZenityList(ZenitySetup::$menu_documents_text, ZenitySetup::$menu_documents_entrees); + $MenuDocuments = new ZenityList(ZenitySetup::$menu_documents['text'], ZenitySetup::$menu_documents['entrees']); // -- partie 1: type de document -- $choix_niv2 = exec($MenuDocuments->get()); - if($choix_niv2 === ZenitySetup::$menu_documents_entrees[0]) + if($choix_niv2 === ZenitySetup::$menu_documents['entrees'][0]) { } - elseif($choix_niv2 === ZenitySetup::$menu_documents_entrees[1]) // = Facture + elseif($choix_niv2 === ZenitySetup::$menu_documents['entrees'][1]) // = Facture, devis, etc { } - elseif($choix_niv2 === ZenitySetup::$menu_documents_entrees[2]) // = Lettre avec adresse + elseif($choix_niv2 === ZenitySetup::$menu_documents['entrees'][2]) // = Lettre avec adresse { } - elseif($choix_niv2 === ZenitySetup::$menu_documents_entrees[3]) // = Livre des recettes + elseif($choix_niv2 === ZenitySetup::$menu_documents['entrees'][3]) // = Livre des recettes { } - elseif($choix_niv2 === ZenitySetup::$menu_documents_entrees[4]) // = Registre des achats + elseif($choix_niv2 === ZenitySetup::$menu_documents['entrees'][4]) // = Registre des achats { } - elseif($choix_niv2 === ZenitySetup::$menu_documents_entrees[5]) // = Bilan annuel + elseif($choix_niv2 === ZenitySetup::$menu_documents['entrees'][5]) // = Bilan annuel { } diff --git a/src/view/Zenity.php b/src/view/Zenity.php index 858dfa9..9e0fd1c 100644 --- a/src/view/Zenity.php +++ b/src/view/Zenity.php @@ -6,12 +6,12 @@ abstract class ZenityCmd { - protected $command = 'zenity'; - protected $command_type = ''; - protected $rows = []; - protected $text = ''; - protected $width = 300; - protected $height = 200; // recalculée en fonction du contenu, vaut au minimum 150 + protected string $command = 'zenity'; + protected string $command_type; + protected array $rows; + protected string $text; + protected int $width = 300; + protected int $height = 200; // recalculée en fonction du contenu, vaut au minimum 150 protected function __construct(string $text, array $rows = []) // $rows est optionnel { @@ -22,15 +22,11 @@ abstract class ZenityCmd $this->command .= ' --text="' . $this->text . '"'; } - public function get() + public function get(): string { + //echo $this->command . "\n"; return($this->command); } - // pré-remlir un formulaire zenity --forms - //~ public function formSet() - //~ { - //~ return($this->command); - //~ } } @@ -46,7 +42,7 @@ class ZenityList extends ZenityCmd $this->command .= ' --hide-header'; // ligne inutile, il y a déjà le --text if($this->rows !== []) { - $this->command .= ' --width=' . $this->width; + $this->command .= ' --width=' . (string)$this->width; $this->height = 80 + count($this->rows) * 25; $this->command .= ' --height=' . $this->height; $this->fillZenityList(); @@ -65,8 +61,8 @@ class ZenityList extends ZenityCmd $this->width = $this->columns * 120 * $widen; $this->height = 91 + count($this->rows) * 25; // inclut les lignes et la barre de défilement horizontale - $this->command .= ' --width=' . $this->width; - $this->command .= ' --height=' . $this->height; + $this->command .= ' --width=' . (string)$this->width; + $this->command .= ' --height=' . (string)$this->height; $this->fillZenityList(); } @@ -103,11 +99,11 @@ class ZenityList extends ZenityCmd $this->command .= $output; } - public function cleanCommand() + /*public function cleanCommand() { $this->command = 'zenity'; $this->__construct($this->text); - } + }*/ } class ZenityQuestion extends ZenityCmd @@ -131,7 +127,7 @@ class ZenityForms extends ZenityCmd $this->command_type = ' --forms'; parent::__construct($text, $rows); //$this->height = 80 + count($this->rows) * 25; // à tester, mais devrait produire le rendu attendu - self::entriesZenityForms($this->rows); + $this->entriesZenityForms($this->rows); } private function entriesZenityForms(array $input) diff --git a/src/view/ZenitySetup.php b/src/view/ZenitySetup.php index 88621bf..956c4f0 100644 --- a/src/view/ZenitySetup.php +++ b/src/view/ZenitySetup.php @@ -6,29 +6,24 @@ // $MenuPrincipal = new ZenityList(ZenitySetup::$menu_principal_text, ZenitySetup::$menu_principal_entrees); // pense-bête -// rassembler les 'text' et 'entrées' +// améliorer les noms "resultats_recherche" // ce serait plus logique que ce fichier soit en JSON class ZenitySetup { - static public $menu_principal_text = "Gestion d'une micro-entreprise"; - static public $menu_principal_entrees = ["Clients et prospects", "Prestations et devis", "Modifier un enregistrement", "Consulter, imprimer un document", "Consulter/analyser les données", "Communication", "Base de données"]; - static public $type_client = ['text' => "Client ou prospect?", - 'entrees' => ["Client", "Prospect"]]; - static public $menu_enregistrement_text = "Type d\'enregistrement?"; - static public $menu_enregistrement_entrees = ["Devis", "Facture", "Facture à partir d'un devis", "CESU", "Location", "Prestation non vendue"]; - //~ static public $menu_enregistrement_entrees = ["Devis", "Facture", "CESU", "Location", "Prestation non vendue"]; - static public $menu_documents_text = "Consulter, imprimer un document LaTeX"; - static public $menu_documents_entrees = ["Devis", "Facture", "Lettre avec adresse", "Livre des recettes", "Registre des achats", "Bilan annuel"]; - static public $menu_communication_text = "Imprimer un support de communication"; - static public $menu_communication_entrees = ["Flyer (nécessite gimp)", "Carte de visite (nécessite scribus)", "Explorateur de fichiers"]; - static public $recherche_client_text = "Recherche d'un client avec son nom ou son code client"; - static public $resultats_recherche_client_text = "Résultats de la recherche, sélectionner un client"; - static public $resultats_recherche_presta_text = "Sélectionner une prestation"; + static public $menu_principal = ['text' => "Gestion d'une micro-entreprise", + 'entrees' => ["Clients et prospects", "Prestations et devis", "Modifier un enregistrement", "Consulter, imprimer un document", "Consulter, analyser les données", "Communication", "Base de données"]]; + static public $menu_enregistrement = ['text' => "Type d\'enregistrement?", + 'entrees' => ["Devis", "Facture", "Facture à partir d'un devis", "CESU", "Location", "Prestation non vendue"]]; + static public $menu_documents = ['text' => "Consulter, imprimer un document LaTeX", + 'entrees' => ["Devis", "Facture", "Lettre avec adresse", "Livre des recettes", "Registre des achats", "Bilan annuel"]]; + static public $menu_communication = ['text' => "Imprimer un support de communication", + 'entrees' => ["Flyer (nécessite gimp)", "Carte de visite (nécessite scribus)", "Explorateur de fichiers"]]; + static public $recherche_client = ['text' => "Recherche d'un client avec son nom ou son code client"]; + static public $resultats_recherche_client = ['text' => "Résultats de la recherche, sélectionner un client"]; + static public $resultats_recherche_presta = ['text' => "Sélectionner une prestation"]; static public $nouveau_client = ['text' => "Nouveau client", 'entrees' => ["Prénom Nom:", "Code client (J.C.Dusse):", "Adresse:", "Code postal:", "Ville:", "Telephone:", "Courriel:", "À propos:"]]; - //~ static public $nouveau_client_text = "Nouveau client"; - //~ static public $nouveau_client_entrees = ["Prénom Nom:", "Code client (J.C.Dusse):", "Adresse:", "Code postal:", "Ville:", "Telephone:", "Courriel:", "À propos:"]; static public $calendar = ['section2' => 'Nouvelle prestation étape 1/3 - Choisir une date', 'section3' => 'Choisir une nouvelle date']; static public $formulaire = ['text' => 'Nouvelle prestation 2/3 - Détail des travaux', @@ -36,11 +31,13 @@ class ZenitySetup 'facture_entrees' => ["Tâches effectuées:", "Modèle du PC:", "OS:", "Données sauvegardées:", "Clés d\'activation:", "Total main d\'oeuvre (euros):", "Détail des pièces:", "Total pièces (euros):", "Déplacement (euros)", "Total HT (euros):", "Mode de paiement:"], 'facture_entrees_reduit' => ["Modèle du PC:", "OS:", "Données sauvegardées:", "Clés d\'activation:", "Mode de paiement:"], 'cesu_entrees' => ["Tâches effectuées:", "Duree de travail:", "Salaire net:", "Mode de paiement:"], // en fait je pourrais ajouter plein d'autres trucs - 'location_entrees' => ["Désignation du bien:", "Modèle, numéro de série, description:", "Valeur:", "État des lieux du début:", "État des lieux de fin:", "Durée de la location en mois:", "Loyer mensuel:", "Nombre de loyers déjà payés:", "Montant du chèque de caution:"]]; - static public $commentaire_prestation_text = 'Nouvelle prestation 3/3 - Commentaires'; + 'location_entrees' => ["Désignation du bien:", "Modèle, numéro de série, description:", "Valeur:", "État des lieux du début:", "Durée de la location en semaines:", "Loyer hebdomadaire:", "Nombre de loyers déjà payés:", "Montant du chèque de caution:"]]; + static public $commentaire_prestation = ['text' => 'Nouvelle prestation 3/3 - Commentaires']; static public $modification_client = ['text' => 'Modifier une information concernant un client', 'service' => "Modifier une prestation"]; //'return' => "Retour menu principal"]; + static public $type_client = ['text' => "Client ou prospect?", + 'entrees' => ["Client", "Prospect"]]; static public $modification_presta = ['text' => 'Modifier une prestation']; //'devis_facture' => "Créer une facture à partir d'un devis"]; //'service' => "Modifier une autre prestation", @@ -52,5 +49,5 @@ class ZenitySetup static public $fin_section_1 = ['text' => "Client enregistré", 'entrees' => ["Ajouter une prestation pour ce client", "Modifier les informations", "Enregistrer un autre client", "Menu principal"]]; static public $fin_section_2 = ['text' => "Prestation/devis enregistré(e)", - 'entrees' => ["Afficher le document", "Modifier les informations", "Enregistrer une autre prestation/devis", "Menu principal"]]; + 'entrees' => ["Afficher le document", "Modifier les informations", "Enregistrer une autre prestation (même client)", "Enregistrer une autre prestation (autre client)", "Menu principal"]]; } -- cgit v1.2.3