summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/latex/devis.tex79
-rw-r--r--data/latex/enveloppe_recto.tex21
-rw-r--r--data/latex/enveloppe_verso.tex13
-rw-r--r--data/latex/facture.tex80
-rw-r--r--data/latex/location.tex44
-rw-r--r--data/latex/ordipolo.pngbin0 -> 46751 bytes
-rw-r--r--src/Dates.php105
-rw-r--r--src/Latex.php84
-rw-r--r--src/dependances.php100
-rw-r--r--src/functions.php51
-rw-r--r--src/latex_templates/devis.php84
-rw-r--r--src/latex_templates/enveloppe_recto.php26
-rw-r--r--src/latex_templates/enveloppe_verso.php18
-rw-r--r--src/latex_templates/facture.php85
-rw-r--r--src/latex_templates/location.php49
-rwxr-xr-xsrc/main.php239
-rw-r--r--src/model/CESU.php46
-rw-r--r--src/model/Clients.php50
-rw-r--r--src/model/DB.php48
-rw-r--r--src/model/DevisFactures.php98
-rw-r--r--src/model/Locations.php74
-rw-r--r--src/model/Model.php162
-rw-r--r--src/model/Prestations.php62
-rw-r--r--src/model/StructTablesDB.php35
-rw-r--r--src/view/Zenity.php110
-rw-r--r--src/view/zenity_setup.php37
26 files changed, 1800 insertions, 0 deletions
diff --git a/data/latex/devis.tex b/data/latex/devis.tex
new file mode 100644
index 0000000..debcdc5
--- /dev/null
+++ b/data/latex/devis.tex
@@ -0,0 +1,79 @@
1\documentclass{report}
2
3\usepackage[french]{babel}
4\usepackage{lmodern} % police latin modern
5\usepackage[utf8]{inputenc} % encodage d'entrée (document)
6\usepackage[T1]{fontenc} % encodage de sortie (rendu)
7\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % marges
8\usepackage{graphicx} % insertions d'images
9\usepackage{textcomp} % pour N°
10\usepackage{xcolor} % texte en couleur
11\usepackage{tabularx} % dimensions des tableaux automatique
12\usepackage{tikz} % le rectangle
13
14\begin{document}
15 \setlength{\parindent}{0cm} % supprimer les alinéas
16 \large{}
17 \pagestyle{empty} % en-tête et pied de page vides
18 \definecolor{vert}{rgb}{0.07, 0.46, 0.13} % saisie en vert
19
20 \begin{center}
21 \includegraphics{ordipolo.png}\\
22 \Large\textbf{Dépannage informatique - Assistance à domicile}
23 \end{center}
24
25 2 A rue de l'île de Man, 29000 Quimper
26
27 SIRET : 814 320 610 00011
28
29 \begin{tabularx}{0.67\linewidth}{@{}X@{}@{}X@{}}
30 Tel : 06.63.85.48.82 & Courriel : ordipolo@gmx.fr
31 \end{tabularx}
32
33 Plus d'infos sur le site web: https\string://ordipolo.fr\\
34 % \string supprime l'espace devant les :
35
36 \begin{center}
37 \large\textbf{DEVIS}
38 \end{center}
39
40 CLIENT\\
41
42 \begin{tabularx}{\linewidth}{@{}X@{}@{}X@{}}
43 Mme, M : \textcolor{vert}{} &
44 Date du devis : \textcolor{vert}{}\\
45 Adresse : \textcolor{vert}{} &
46 Delai de livraison : \textcolor{vert}{}\\
47 \end{tabularx}\\\\
48
49 PRESTATION\\
50
51 \textcolor{vert}{}
52
53 Total main d'oeuvre : \textcolor{vert}{}\\
54
55 PIÈCES\\
56
57 \textcolor{vert}{}
58
59 Total pièces : \textcolor{vert}{}\\
60
61 TOTAL\\
62
63 Déplacement : \textcolor{vert}{}
64
65 Total HT : \textcolor{vert}{}
66
67 \textit{(TVA non applicable, article 293B du code général des impôts)}
68
69 Référence du devis : \textcolor{vert}{}\\
70
71 Devis reçu avant l'exécution des travaux, signature du client :\\
72 \begin{tikzpicture}
73 \draw (0,0) rectangle (4,2);
74 \end{tikzpicture}\\
75
76 \small{}NOTA BENE\\
77
78 Si le délai de livraison n’est pas précisé, c’est naturellement le délai légal de 30 jours qui est appliqué. Lorsqu'Ordi Polo garde (ou prête) un ordinateur le temps nécessaire à la réparation, le prêt peut être formalisé par un document signé par les deux parties. Le dépannage inclut principalement l'intervention sur les logiciels et si nécessaire le démontage et remontage de la machine nécessaires au nettoyage de la poussière ou au remplacement d'une pièce. Ordi Polo ne répare pas les composants électroniques défectueux et n'est pas responsable des dysfonctionnements de l'ordinateur dont l'origine est matérielle. Ordi Polo ne vend pas de matériel mais peut conseiller ou réaliser les démarches d’un achat.
79\end{document} \ No newline at end of file
diff --git a/data/latex/enveloppe_recto.tex b/data/latex/enveloppe_recto.tex
new file mode 100644
index 0000000..d1f3f43
--- /dev/null
+++ b/data/latex/enveloppe_recto.tex
@@ -0,0 +1,21 @@
1\documentclass[]{report}
2
3\usepackage[french]{babel}
4\usepackage{lmodern} % police latin modern
5\usepackage[utf8]{inputenc} % encodage d'entrée (document)
6\usepackage[T1]{fontenc} % encodage de sortie (rendu)
7\usepackage{graphicx} % insertions d'images
8\usepackage[papersize={22cm, 11cm}, top=1cm, left=1cm, bottom=1cm]{geometry}
9\pagestyle{empty}
10
11\begin{document}
12 \setlength{\parindent}{0cm}
13 \includegraphics{ordipolo.png}\\
14 \large\textbf{Dépannage informatique - Assistance à domicile}
15
16 \setlength{\parindent}{7,9cm}
17 \begin{minipage}[b][5,8cm]{12cm}
18 \LARGE{M. Truc\\3, rue Machin\\\\\\}
19 \LARGE{2 \ 9 \ 0 \ 0 \ 0 \ \ \ \ QUIMPER}
20 \end{minipage}
21\end{document} \ No newline at end of file
diff --git a/data/latex/enveloppe_verso.tex b/data/latex/enveloppe_verso.tex
new file mode 100644
index 0000000..24baa8a
--- /dev/null
+++ b/data/latex/enveloppe_verso.tex
@@ -0,0 +1,13 @@
1\documentclass[]{report}
2
3\usepackage[french]{babel}
4\usepackage{lmodern} % police latin modern
5\usepackage[utf8]{inputenc} % encodage d'entrée (document)
6\usepackage[T1]{fontenc} % encodage de sortie (rendu)
7\usepackage[papersize={22cm, 11cm}, top=0.6cm, left=4.5cm]{geometry}
8\pagestyle{empty}
9
10\begin{document}
11 \setlength{\parindent}{0cm}
12 \Large{Paul Jusot\\2A, rue de l'île de Man\\29000 QUIMPER}
13\end{document} \ No newline at end of file
diff --git a/data/latex/facture.tex b/data/latex/facture.tex
new file mode 100644
index 0000000..babb2ab
--- /dev/null
+++ b/data/latex/facture.tex
@@ -0,0 +1,80 @@
1\documentclass{report}
2
3\usepackage[french]{babel}
4\usepackage{lmodern} % police latin modern
5\usepackage[utf8]{inputenc} % encodage d'entrée (document)
6\usepackage[T1]{fontenc} % encodage de sortie (rendu)
7\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % marges
8\usepackage{graphicx} % insertions d'images
9\usepackage{textcomp} % pour N°
10\usepackage{xcolor} % texte en couleur
11\usepackage{tabularx} % dimensions des tableaux automatique
12
13\begin{document}
14 \setlength{\parindent}{0cm} % supprimer les alinéas
15 \large{}
16 \pagestyle{empty} % en-tête et pied de page vides
17 \definecolor{vert}{rgb}{0.07, 0.46, 0.13} % saisie en vert
18
19 \begin{center}
20 \includegraphics{ordipolo.png}\\
21 \Large\textbf{Dépannage informatique - Assistance à domicile}
22 \end{center}
23
24 2 A rue de l'île de Man, 29000 Quimper
25
26 SIRET : 814 320 610 00011
27
28 \begin{tabularx}{0.67\linewidth}{@{}X@{}@{}X@{}}
29 Tel : 06.63.85.48.82 & Courriel : ordipolo@gmx.fr
30 \end{tabularx}
31
32 Plus d'infos sur le site web: https\string://ordipolo.fr\\
33 % \string supprime l'espace devant les :
34
35 \begin{center}
36 \large\textbf{FACTURE}
37 \end{center}
38
39 CLIENT\\
40
41 \begin{tabularx}{\linewidth}{@{}X@{}@{}X@{}}
42 Mme, M : \textcolor{vert}{} &
43 Date : \textcolor{vert}{}\\
44 \end{tabularx}\\
45 Adresse : \textcolor{vert}{}\\
46
47 PRESTATION\\
48
49 \textcolor{vert}{}
50
51 Modèle de l'ordinateur : \textcolor{vert}{}
52
53 Système d'exploitation : \textcolor{vert}{}
54
55 Données à conserver : \textcolor{vert}{}
56
57 Clé d'activation : \textcolor{vert}{}\\
58
59 Total main d'oeuvre : \textcolor{vert}{}\\
60
61 PIÈCES\\
62
63 \textcolor{vert}{}
64
65 Total pièces : \textcolor{vert}{}\\
66
67 TOTAL\\
68
69 Déplacement : \textcolor{vert}{}
70
71 Total HT : \textcolor{vert}{}
72
73 \textit{(TVA non applicable, article 293B du code général des impôts)}
74
75 Référence de la facture : \textcolor{vert}{}\\
76
77 \small{}NOTA BENE\\
78
79 Lorsqu'Ordi Polo garde (ou prête) un ordinateur le temps nécessaire à la réparation, le prêt peut être formalisé par un document signé par les deux parties. Le dépannage inclut principalement l'intervention sur les logiciels et si nécessaire le démontage et remontage de la machine nécessaires au nettoyage de la poussière ou au remplacement d'une pièce. Ordi Polo ne répare pas les composants électroniques défectueux et n'est pas responsable des dysfonctionnements de l'ordinateur dont l'origine est matérielle. Ordi Polo ne vend pas de matériel mais peut conseiller ou réaliser les démarches d’un achat.
80\end{document} \ No newline at end of file
diff --git a/data/latex/location.tex b/data/latex/location.tex
new file mode 100644
index 0000000..bcfb1e5
--- /dev/null
+++ b/data/latex/location.tex
@@ -0,0 +1,44 @@
1\documentclass{report}
2
3\usepackage[french]{babel}
4\usepackage{lmodern} % police latin modern
5\usepackage[utf8]{inputenc} % encodage d'entrée (document)
6\usepackage[T1]{fontenc} % encodage de sortie (rendu)
7\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % marges
8\usepackage{graphicx} % insertions d'images
9\usepackage{textcomp} % pour N°
10\usepackage{xcolor} % texte en couleur
11%\usepackage{wrapfig} % placer texte et image côte-à-côte
12\usepackage{tabularx} % dimensions des tableaux automatique
13
14\begin{document}
15 \setlength{\parindent}{0cm} % supprimer les alinéas
16 \large{}
17 \pagestyle{empty} % en-tête et pied de page vides
18 \definecolor{vert}{rgb}{0.07, 0.46, 0.13} % saisie en vert
19
20 \begin{center}
21 \includegraphics{ordipolo.png}\\
22 \Large\textbf{Dépannage informatique - Assistance à domicile}
23 \end{center}
24
25 2 A rue de l'île de Man, 29000 Quimper
26
27 SIRET : 814 320 610 00011
28
29 \begin{tabularx}{0.67\linewidth}{@{}X@{}@{}X@{}}
30 Tel : 06.63.85.48.82 & Courriel : ordipolo@gmx.fr
31 \end{tabularx}
32
33 Plus d'infos sur le site web: https\string://ordipolo.fr\\
34 % \string supprime l'espace devant les :
35
36 CLIENT\\
37
38 \begin{tabularx}{\linewidth}{@{}X@{}@{}X@{}}
39 Mme, M : \textcolor{vert}{} &
40 Date : \textcolor{vert}{}\\
41 \end{tabularx}\\
42 Adresse : \textcolor{vert}{}\\
43
44\end{document} \ No newline at end of file
diff --git a/data/latex/ordipolo.png b/data/latex/ordipolo.png
new file mode 100644
index 0000000..2acd67d
--- /dev/null
+++ b/data/latex/ordipolo.png
Binary files differ
diff --git a/src/Dates.php b/src/Dates.php
new file mode 100644
index 0000000..de71b08
--- /dev/null
+++ b/src/Dates.php
@@ -0,0 +1,105 @@
1<?php
2// php/DateTimestamp.php
3
4class Dates
5{
6 private $date;
7 private $timestamp; // valeurs négatives autorisées => dates avant 1970
8 static public $date_format = 'EU'; // dates européennes jj-mm-aaaa (EU) ou américaines mm/dd/yyyy (US)
9
10
11 public function __construct($entry = NULL)
12 {
13 if(gettype($entry) === 'string') // une date est attendue
14 {
15 $this->setDate($entry);
16 }
17 elseif(gettype($entry) === 'integer')
18 {
19 $this->setTimestamp($entry);
20 }
21 }
22
23
24 public function setDate(string $entry)
25 {
26 $entry = $this->dashOrSlash($entry); // pour strtotime()
27
28 $splitedDate = preg_split('#\D#', $entry); // \D = tout sauf chiffre
29
30 if(self::$date_format === 'EU')
31 {
32 $tmp = $splitedDate[0];
33 $splitedDate[0] = $splitedDate[1];
34 $splitedDate[1] = $tmp;
35 }
36
37 if(checkdate($splitedDate[0], $splitedDate[1], $splitedDate[2]))
38 {
39 $this->date = $entry;
40 $this->timestamp = strtotime($entry); // date (string) -> timestamp (int)
41 // strtotime() devine le format en analysant la chaîne en entrée, on l'aide un peu
42 // avec des /, php considère que la date est américaine
43 // avec des - ou des ., php considère que la date est européenne
44 }
45 else
46 {
47 echo("Date incorrecte, le format de la date dans le fichier config.php est " . self::$date_format . ".\nLes choix possibles sont EU pour Europe et US pour États-Unis.");
48 die();
49 }
50 }
51
52 public function setTimestamp(int $entry)
53 {
54 $this->timestamp = $entry;
55 $this->date = $this->timestamp_to_date($entry); // timestamp (int) -> date (string)
56 }
57
58
59 public function getDate(): string
60 {
61 return($this->date);
62 }
63
64 public function getTimestamp(): int
65 {
66 return($this->timestamp);
67 }
68
69
70 private function dashOrSlash(string $date): string
71 {
72 if(self::$date_format === 'EU')
73 {
74 // change jj/mm/aaaa en jj-mm-aaaa
75 return(preg_replace('#\D#', '-', $date)); // \D = tout sauf chiffre
76 }
77 elseif(self::$date_format === 'US')
78 {
79 // change mm-dd.yyyy en mm/dd/yyyy
80 return(preg_replace('#\D#', '/', $date));
81 }
82 else
83 {
84 echo('Le fichier config.php comporte une erreur. La variable $date_format doit avoir pour valeur "EU" ou "US"');
85 die(); // brutal
86 }
87 }
88
89 private function timestamp_to_date(int $timestamp): string
90 {
91 if(self::$date_format === 'EU')
92 {
93 return(date("j-m-Y", $timestamp));
94 }
95 elseif(self::$date_format === 'US')
96 {
97 return(date("m/d/Y", $timestamp));
98 }
99 else
100 {
101 echo('Le fichier config.php comporte une erreur. La variable $date_format doit avoir pour valeur "EU" ou "US"');
102 die(); // brutal
103 }
104 }
105}
diff --git a/src/Latex.php b/src/Latex.php
new file mode 100644
index 0000000..c3d56af
--- /dev/null
+++ b/src/Latex.php
@@ -0,0 +1,84 @@
1<?php
2// php/Latex.php
3//
4// génération du code LaTeX
5
6abstract class Latex
7{
8 protected $fileName = '';
9 protected $latexPath = '';
10 protected $pdfPath = '';
11
12 protected function createFile(string $latex, string $fileName, string $latexPath)
13 {
14 // nom du fichier créé = nom.tex
15 // pour les devis, factures et enveloppes, le nom est le code la prestation
16 // pour les livre de recettes et registres des achats mensuels:
17 // le nom du fichier suit cet exemple: "Recettes-2022-06-Juin.tex"
18 // pour le livre de recette ou le registre des achats annuel, même principe: "Achats-2022.tex"
19 // pour le bilan comptable annuel, ça donne: "Bilan-2022.tex"
20 $fichier = fopen($latexPath . $fileName, "w+");
21 fputs($fichier, $latex);
22 fclose($fichier);
23 }
24}
25
26
27abstract class PrestaLatex extends Latex
28{
29 public function __construct(string $quoi, string $codePresta)
30 {
31 nameTheFile($quoi, $codePresta);
32 }
33
34 // forme = code-presta.tex
35 protected function nameTheFile(string $quoi, string $codePresta)
36 {
37 $this->fileName = $quoi . '-' . $codePresta . '.tex';
38 }
39}
40
41class DevisLatex extends PrestaLatex
42{}
43
44class FactureLatex extends PrestaLatex
45{}
46
47class LocationLatex extends PrestaLatex
48{}
49
50class EnveloppeRectoLatex extends PrestaLatex
51{}
52class EnveloppeVersoLatex extends PrestaLatex
53{}
54
55
56abstract class ComptaLatex extends Latex
57{
58 public function __construct(string $quoi, string $annee, int $numeroMois = 0)
59 {
60 nameTheFile($quoi, $annee, $numeroMois);
61 }
62
63 // forme = Recettes-2022-06-Juin.tex ou Recettes-2022.tex
64 // type de 'annee'?
65 protected function nameTheFile(string $quoi, string $annee, int $numeroMois = 0)
66 {
67 $this->fileName = $quoi . '-' . $annee;
68 $mois = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'];
69 if($numeroMois > 0 && $numeroMois <= 12)
70 {
71 $this->fileName .= '-' . $numeroMois . '-' . $mois[$numeroMois];
72 }
73 $this->fileName .= '.tex';
74 }
75}
76
77class LivreRecettesLatex extends ComptaLatex
78{}
79
80class RegistreAchatsLatex extends ComptaLatex
81{}
82
83class BilanLatex extends ComptaLatex
84{}
diff --git a/src/dependances.php b/src/dependances.php
new file mode 100644
index 0000000..66ce414
--- /dev/null
+++ b/src/dependances.php
@@ -0,0 +1,100 @@
1<?php
2// php/dependances.php
3// Vérification des dépendances nécessaires au fonctionnement de ce programmes.
4
5// Environnement dans lequel ce programmes a été créé:
6// - système archlinux avec l'interpréteur bash
7// - PHP 8.1 + paquet php-sqlite
8// - module pdo_sqlite activé dans le fichier php.ini
9// - sqlitebrowser (interface graphique pour sqlite)
10// - distribution LaTeX texlive
11// - zenity
12
13// zenity disponible
14if(exec("zenity --version 2> /dev/null") === '') // commande qui n'ouvre pas de fenêtre, erreur si la chaine est vide parce que la sortie d'erreur va dans /dev/null
15{
16 printf("Impossible de lancer zenity. Veuillez installer le paquet zenity\n");
17 exit();
18}
19
20// compilateur pdflatex disponible
21if(exec("pdflatex -version 2> /dev/null") === '') // erreur si la chaine est vide parce que la sortie d'erreur va dans /dev/null
22{
23 printf("Impossible de lancer pdflatex. Veuillez installer une distribution LaTeX.\n");
24 exit();
25}
26
27// test de la présence du paquet php-sqlite
28// compliqué? dépend de l'OS?
29// note: l'erreur se produit dès le démarrage de PHP si le php.ini est bon mais qu'il manque le paquet
30
31// module pdo_sqlite de PHP activé?
32if(!extension_loaded("pdo_sqlite"))
33{
34 printf("Impossible d'utiliser la base de données. Veuillez installer le paquet php-sqlite ET activer l'extension pdo_sqlite dans le fichier php.ini.\n");
35 exit();
36}
37
38
39// client sqlite
40if($exec_mode === 'gui')
41{
42 // sqlitebrowser disponible
43 if(exec("which sqlitebrowser 2> /dev/null") !== '') // which parcourt les dossiers du PATH et affiche les chemins trouvés, erreur si la chaine est vide parce que la sortie d'erreur va dans /dev/null
44 {
45 $sqlitebrowser_enable = true;
46 }
47 // terminal en mode graphique disponible, permettra d'y utiliser sqlite dans la console
48 else
49 {
50 printf("Sqlitebrowser n'est pas disponible. J'espère que vous maîtrisez le SQL.\n");
51
52 if(exec("which xterm 2> /dev/null") !== '' && exec("xterm -v 2> /dev/null") !== '')
53 {
54 $x_term_ccommand = 'xterm -e';
55 }
56 elseif(exec("which urxvt 2> /dev/null") !== '')
57 {
58 $x_term_ccommand = 'urxvt -e';
59 }
60 elseif(exec("which lxterminal 2> /dev/null") !== '' && exec("lxterminal -v 2> /dev/null") !== '')
61 {
62 $x_term_ccommand = 'lxterminal -e';
63 }
64 elseif(exec("which xfce4-terminal 2> /dev/null") !== '' && exec("xfce4-terminal -V 2> /dev/null") !== '')
65 {
66 $x_term_ccommand = 'xfce4-terminal -x';
67 }
68 elseif(exec("which gnome-terminal 2> /dev/null") !== '')
69 {
70 $x_term_ccommand = 'gnome-terminal --';
71 }
72 elseif(exec("which konsole 2> /dev/null") !== '' && exec("konsole -v 2> /dev/null") !== '')
73 {
74 $x_term_ccommand = 'konsole -e';
75 }
76 // pour MAC - NON TESTÉ !! (possibilité de détecter le système avec uname?)
77 //~ elseif(exec("which Terminal 2> /dev/null") !== '')
78 //~ {
79 //~ $x_term_ccommand = 'open -a Terminal -e'; // ne marche probablement pas
80 //~ }
81 else
82 {
83 printf("Impossible d'ouvrir un terminal pour y lancer sqlite. Veuillez installer un terminal en mode graphique (par exemple xterm).\n");
84 }
85 }
86}
87
88// sqlite CLI disponible
89if(exec("which sqlite 2> /dev/null") !== '' && exec("sqlite --version 2> /dev/null") !== '')
90{
91 $sqlite_cli = 'sqlite';
92}
93elseif(exec("which sqlite3 2> /dev/null") !== '' && exec("sqlite3 --version 2> /dev/null") !== '')
94{
95 $sqlite_cli = 'sqlite3';
96}
97else
98{
99 printf("Impossible de lancer sqlite dans le terminal en utilisant la commande ' . $sqlite_cli . '\n");
100}
diff --git a/src/functions.php b/src/functions.php
new file mode 100644
index 0000000..d67a05e
--- /dev/null
+++ b/src/functions.php
@@ -0,0 +1,51 @@
1<?php
2// php/functions.php
3//
4// gros fourre-tout, il faudra le ranger plus tard
5
6
7// commande pour lancer une application graphique en ouvrant un fichier
8function window_app_command(string $app, string $path = ''): string
9{
10 // attention, la syntaxe utilisée est la plus simple: "app fichier"
11 // ça fonctionne avec les logiciels choisis: gimp, scribus
12 // mais ça pourrait ne pas convenir
13
14 $command = 'nohup ' . $app; // détache l'appli du script PHP
15 if($path !== '')
16 {
17 $command .= ' ' . $path;
18 }
19 $command .= ' > /dev/null 2>&1 &';
20 // stdout > /dev/null et & permettent de rendre la main à PHP
21 // stderr > stdout pour cacher un message inutile
22 return $command;
23}
24
25function recherche_client(string $saisie): array
26{
27 $resultats = [];
28
29 // recherche dans la BDD
30
31
32 return($resultats);
33}
34
35// compilation à partir d'un fichier .tex
36function latexToPdf(string $fileName, string $latexPath, string $pdfPath)
37{
38 $outputDir = '';
39 if($pdfPath !== '')
40 {
41 $outputDir = '-output-directory=' . $pdfPath . ' ';
42 }
43
44 // compilation
45 exec('pdflatex ' . $outputDir . $latexPath . $fileName);
46
47 // nettoyage
48 $basename = basename($fileName, '.tex');
49 unlink($pdfPath . $basename . '.aux');
50 unlink($pdfPath . $basename . '.log');
51}
diff --git a/src/latex_templates/devis.php b/src/latex_templates/devis.php
new file mode 100644
index 0000000..7df98e8
--- /dev/null
+++ b/src/latex_templates/devis.php
@@ -0,0 +1,84 @@
1<?php
2ob_start();
3?>
4\documentclass{report}
5
6\usepackage[french]{babel}
7\usepackage{lmodern} % police latin modern
8\usepackage[utf8]{inputenc} % encodage d'entrée (document)
9\usepackage[T1]{fontenc} % encodage de sortie (rendu)
10\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % marges
11\usepackage{graphicx} % insertions d'images
12\usepackage{textcomp} % pour N°
13\usepackage{xcolor} % texte en couleur
14\usepackage{tabularx} % dimensions des tableaux automatique
15\usepackage{tikz} % le rectangle
16
17\begin{document}
18 \setlength{\parindent}{0cm} % supprimer les alinéas
19 \large{}
20 \pagestyle{empty} % en-tête et pied de page vides
21 \definecolor{vert}{rgb}{0.07, 0.46, 0.13} % saisie en vert
22
23 \begin{center}
24 \includegraphics{ordipolo.png}\\
25 \Large\textbf{Dépannage informatique - Assistance à domicile}
26 \end{center}
27
28 2 A rue de l'île de Man, 29000 Quimper
29
30 SIRET : 814 320 610 00011
31
32 \begin{tabularx}{0.67\linewidth}{@{}X@{}@{}X@{}}
33 Tel : 06.63.85.48.82 & Courriel : ordipolo@gmx.fr
34 \end{tabularx}
35
36 Plus d'infos sur le site web: https\string://ordipolo.fr\\
37 % \string supprime l'espace devant les :
38
39 \begin{center}
40 \large\textbf{DEVIS}
41 \end{center}
42
43 CLIENT\\
44
45 \begin{tabularx}{\linewidth}{@{}X@{}@{}X@{}}
46 Mme, M : \textcolor{vert}{} &
47 Date du devis : \textcolor{vert}{}\\
48 Adresse : \textcolor{vert}{} &
49 Delai de livraison : \textcolor{vert}{}\\
50 \end{tabularx}\\\\
51
52 PRESTATION\\
53
54 \textcolor{vert}{}
55
56 Total main d'oeuvre : \textcolor{vert}{}\\
57
58 PIÈCES\\
59
60 \textcolor{vert}{}
61
62 Total pièces : \textcolor{vert}{}\\
63
64 TOTAL\\
65
66 Déplacement : \textcolor{vert}{}
67
68 Total HT : \textcolor{vert}{}
69
70 \textit{(TVA non applicable, article 293B du code général des impôts)}
71
72 Référence du devis : \textcolor{vert}{}\\
73
74 Devis reçu avant l'exécution des travaux, signature du client :\\
75 \begin{tikzpicture}
76 \draw (0,0) rectangle (4,2);
77 \end{tikzpicture}\\
78
79 \small{}NOTA BENE\\
80
81 Si le délai de livraison n’est pas précisé, c’est naturellement le délai légal de 30 jours qui est appliqué. Lorsqu'Ordi Polo garde (ou prête) un ordinateur le temps nécessaire à la réparation, le prêt peut être formalisé par un document signé par les deux parties. Le dépannage inclut principalement l'intervention sur les logiciels et si nécessaire le démontage et remontage de la machine nécessaires au nettoyage de la poussière ou au remplacement d'une pièce. Ordi Polo ne répare pas les composants électroniques défectueux et n'est pas responsable des dysfonctionnements de l'ordinateur dont l'origine est matérielle. Ordi Polo ne vend pas de matériel mais peut conseiller ou réaliser les démarches d’un achat.
82\end{document}
83<?php
84$devisLatex = ob_get_clean();
diff --git a/src/latex_templates/enveloppe_recto.php b/src/latex_templates/enveloppe_recto.php
new file mode 100644
index 0000000..38003a1
--- /dev/null
+++ b/src/latex_templates/enveloppe_recto.php
@@ -0,0 +1,26 @@
1<?php
2ob_start();
3?>
4\documentclass[]{report}
5
6\usepackage[french]{babel}
7\usepackage{lmodern} % police latin modern
8\usepackage[utf8]{inputenc} % encodage d'entrée (document)
9\usepackage[T1]{fontenc} % encodage de sortie (rendu)
10\usepackage{graphicx} % insertions d'images
11\usepackage[papersize={22cm, 11cm}, top=1cm, left=1cm, bottom=1cm]{geometry}
12\pagestyle{empty}
13
14\begin{document}
15 \setlength{\parindent}{0cm}
16 \includegraphics{ordipolo.png}\\
17 \large\textbf{Dépannage informatique - Assistance à domicile}
18
19 \setlength{\parindent}{7,9cm}
20 \begin{minipage}[b][5,8cm]{12cm}
21 \LARGE{M. Truc\\3, rue Machin\\\\\\}
22 \LARGE{2 \ 9 \ 0 \ 0 \ 0 \ \ \ \ QUIMPER}
23 \end{minipage}
24\end{document}
25<?php
26$enveloppeRectoLatex = ob_get_clean();
diff --git a/src/latex_templates/enveloppe_verso.php b/src/latex_templates/enveloppe_verso.php
new file mode 100644
index 0000000..51f5f4d
--- /dev/null
+++ b/src/latex_templates/enveloppe_verso.php
@@ -0,0 +1,18 @@
1<?php
2ob_start();
3?>
4\documentclass[]{report}
5
6\usepackage[french]{babel}
7\usepackage{lmodern} % police latin modern
8\usepackage[utf8]{inputenc} % encodage d'entrée (document)
9\usepackage[T1]{fontenc} % encodage de sortie (rendu)
10\usepackage[papersize={22cm, 11cm}, top=0.6cm, left=4.5cm]{geometry}
11\pagestyle{empty}
12
13\begin{document}
14 \setlength{\parindent}{0cm}
15 \Large{Paul Jusot\\2A, rue de l'île de Man\\29000 QUIMPER}
16\end{document}
17<?php
18$enveloppeVersoLatex = ob_get_clean();
diff --git a/src/latex_templates/facture.php b/src/latex_templates/facture.php
new file mode 100644
index 0000000..409dd9a
--- /dev/null
+++ b/src/latex_templates/facture.php
@@ -0,0 +1,85 @@
1<?php
2ob_start();
3?>
4\documentclass{report}
5
6\usepackage[french]{babel}
7\usepackage{lmodern} % police latin modern
8\usepackage[utf8]{inputenc} % encodage d'entrée (document)
9\usepackage[T1]{fontenc} % encodage de sortie (rendu)
10\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % marges
11\usepackage{graphicx} % insertions d'images
12\usepackage{textcomp} % pour N°
13\usepackage{xcolor} % texte en couleur
14\usepackage{tabularx} % dimensions des tableaux automatique
15
16\begin{document}
17 \setlength{\parindent}{0cm} % supprimer les alinéas
18 \large{}
19 \pagestyle{empty} % en-tête et pied de page vides
20 \definecolor{vert}{rgb}{0.07, 0.46, 0.13} % saisie en vert
21
22 \begin{center}
23 \includegraphics{ordipolo.png}\\
24 \Large\textbf{Dépannage informatique - Assistance à domicile}
25 \end{center}
26
27 2 A rue de l'île de Man, 29000 Quimper
28
29 SIRET : 814 320 610 00011
30
31 \begin{tabularx}{0.67\linewidth}{@{}X@{}@{}X@{}}
32 Tel : 06.63.85.48.82 & Courriel : ordipolo@gmx.fr
33 \end{tabularx}
34
35 Plus d'infos sur le site web: https\string://ordipolo.fr\\
36 % \string supprime l'espace devant les :
37
38 \begin{center}
39 \large\textbf{FACTURE}
40 \end{center}
41
42 CLIENT\\
43
44 \begin{tabularx}{\linewidth}{@{}X@{}@{}X@{}}
45 Mme, M : \textcolor{vert}{} &
46 Date : \textcolor{vert}{}\\
47 \end{tabularx}\\
48 Adresse : \textcolor{vert}{}\\
49
50 PRESTATION\\
51
52 \textcolor{vert}{}
53
54 Modèle de l'ordinateur : \textcolor{vert}{}
55
56 Système d'exploitation : \textcolor{vert}{}
57
58 Données à conserver : \textcolor{vert}{}
59
60 Clé d'activation : \textcolor{vert}{}\\
61
62 Total main d'oeuvre : \textcolor{vert}{}\\
63
64 PIÈCES\\
65
66 \textcolor{vert}{}
67
68 Total pièces : \textcolor{vert}{}\\
69
70 TOTAL\\
71
72 Déplacement : \textcolor{vert}{}
73
74 Total HT : \textcolor{vert}{}
75
76 \textit{(TVA non applicable, article 293B du code général des impôts)}
77
78 Référence de la facture : \textcolor{vert}{}\\
79
80 \small{}NOTA BENE\\
81
82 Lorsqu'Ordi Polo garde (ou prête) un ordinateur le temps nécessaire à la réparation, le prêt peut être formalisé par un document signé par les deux parties. Le dépannage inclut principalement l'intervention sur les logiciels et si nécessaire le démontage et remontage de la machine nécessaires au nettoyage de la poussière ou au remplacement d'une pièce. Ordi Polo ne répare pas les composants électroniques défectueux et n'est pas responsable des dysfonctionnements de l'ordinateur dont l'origine est matérielle. Ordi Polo ne vend pas de matériel mais peut conseiller ou réaliser les démarches d’un achat.
83\end{document}
84<?php
85$factureLatex = ob_get_clean();
diff --git a/src/latex_templates/location.php b/src/latex_templates/location.php
new file mode 100644
index 0000000..dc4ea3e
--- /dev/null
+++ b/src/latex_templates/location.php
@@ -0,0 +1,49 @@
1<?php
2ob_start();
3?>
4\documentclass{report}
5
6\usepackage[french]{babel}
7\usepackage{lmodern} % police latin modern
8\usepackage[utf8]{inputenc} % encodage d'entrée (document)
9\usepackage[T1]{fontenc} % encodage de sortie (rendu)
10\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % marges
11\usepackage{graphicx} % insertions d'images
12\usepackage{textcomp} % pour N°
13\usepackage{xcolor} % texte en couleur
14%\usepackage{wrapfig} % placer texte et image côte-à-côte
15\usepackage{tabularx} % dimensions des tableaux automatique
16
17\begin{document}
18 \setlength{\parindent}{0cm} % supprimer les alinéas
19 \large{}
20 \pagestyle{empty} % en-tête et pied de page vides
21 \definecolor{vert}{rgb}{0.07, 0.46, 0.13} % saisie en vert
22
23 \begin{center}
24 \includegraphics{ordipolo.png}\\
25 \Large\textbf{Dépannage informatique - Assistance à domicile}
26 \end{center}
27
28 2 A rue de l'île de Man, 29000 Quimper
29
30 SIRET : 814 320 610 00011
31
32 \begin{tabularx}{0.67\linewidth}{@{}X@{}@{}X@{}}
33 Tel : 06.63.85.48.82 & Courriel : ordipolo@gmx.fr
34 \end{tabularx}
35
36 Plus d'infos sur le site web: https\string://ordipolo.fr\\
37 % \string supprime l'espace devant les :
38
39 CLIENT\\
40
41 \begin{tabularx}{\linewidth}{@{}X@{}@{}X@{}}
42 Mme, M : \textcolor{vert}{} &
43 Date : \textcolor{vert}{}\\
44 \end{tabularx}\\
45 Adresse : \textcolor{vert}{}\\
46
47\end{document}
48<?php
49$locationLatex = ob_get_clean();
diff --git a/src/main.php b/src/main.php
new file mode 100755
index 0000000..e890744
--- /dev/null
+++ b/src/main.php
@@ -0,0 +1,239 @@
1#!/bin/php
2<?php
3// php/main.php
4
5// configuration du programme par l'utilisateur
6require('../config.php'); // fichier de l'utilisateur: à déplacer peut-être dans un dossier config
7//require('config_window.php'); // configuration user-friendly et assistée avec des messages d'erreur et des indications
8//require('config_check.php'); // contrôle de config.php
9
10// variables diverses, certaines utilisent les variables de config.php
11$exec_mode = 'gui'; // les versions pure console (CLI) et serveur web (CGI) de ce programme ne sont pas prévues pour l'instant
12$file_explorer = 'xdg-open'; // ouvre l'explorateur de fichiers par défaut quand suivi d'un chemin en paramètre
13$flyer = $pub . $flyer;
14$business_card = $pub . $business_card;
15$db_place .= $db_name . '.sqlite';
16$sqlitebrowser_enable = false;
17$sqlite_cli = ''; // commande sqlite ou sqlite3
18$x_term_command = ''; // commande terminal en mode graphique
19
20require('dependances.php'); // vérification des dépendances
21require('functions.php');
22require('Dates.php'); // gère dates et timestamps
23Dates::$date_format = $date_format; // dates européennes ou américaines
24
25require('model/DB.php'); // connexion en héritant de PDO
26DB::$dsn = 'sqlite:' . $db_place; // Data Source Name = 1er paramètre du constructeur de PDO: $bdd = new PDO($dsn);
27
28require('model/Model.php'); // class Model extends DB, requêtes SQL
29require('model/StructTablesDB.php');
30Model::createTables();
31
32require('model/Clients.php');
33require('model/Prestations.php');
34require('model/DevisFactures.php');
35require('model/CESU.php');
36require('model/Locations.php');
37
38// instancier et supprimer à chaque fois quand nécessaire
39$Client = new Clients();
40$Client->setPrenom_nom('Jean Némar')->setAdresse('10, rue des douves')->setCode_client('464653476')->setCommentaires('un peu chiant');
41$Client->create();
42
43// même chose avec un tableau en entrée au lieu d'écrire toutes les méthodes
44$input = ['prenom_nom' => 'Eva Casquer', 'adresse' => "2, place d'Écosse", 'code_client' => '958465875', 'commentaires' => 'bonne vache à lait'];
45$Client->hydrate($input);
46$Client->create();
47
48$input = ['prenom_nom' => 'Eva Paparla', 'commentaires' => 'grosse nunuche'];
49$Client->hydrate($input);
50$Client->update(2);
51
52$Client->delete(3);
53
54//$Date = new Dates;
55
56
57require('view/Zenity.php'); // commande système zenity
58require('view/zenity_setup.php'); // texte dans les fenêtres ET instanciation (un objet = une commande)
59require('Latex.php'); // générer le code LaTeX
60
61// injection de variables dans le document
62// problème à régler: et si je veux faire une deuxième facture?
63//~ include('latex_templates/devis.php');
64//~ include('latex_templates/facture.php');
65//~ include('latex_templates/enveloppe_recto.php');
66//~ include('latex_templates/enveloppe_verso.php');
67//~ include('latex_templates/location.php');
68
69
70// boucle principale
71$boucle = true;
72while($boucle)
73{
74 // menu principal
75 $choix_niv1 = exec($MenuPrincipal->get());
76
77 // enregistrement
78 if($choix_niv1 === $menu_principal_entrees[0]) // = Nouvelle prestation
79 {
80 // est ce que le client est déjà dans la base?
81 if(exec($QuestionNouveauClient->get()) === 0) // $? = 0 signifie oui
82 {
83 // saisie du nom du client et recherche
84 $client_saisie = exec($RechercheClient->get());
85
86 // sélection parmi les résultats
87 $ResultatsRechercheClient->setEntries(recherche_client($client_saisie));
88 $choix_niv2 = exec($ResultatsRechercheClient->get());
89 if($choix_niv2 !== '')
90 {
91 echo "client trouvé\n";
92 }
93 else // chaîne vide
94 {
95 echo "client pas trouvé\n";
96 exec($NouveauClient->get());
97
98 // enregistrement dans la BDD
99
100 }
101
102 // récupération des infos dans la BDD
103
104 }
105 else
106 {
107 echo "nouveau client\n";
108 exec($NouveauClient->get());
109
110 // enregistrement dans la BDD
111
112 }
113
114 // choix type comptable: devis, facture, cesu
115 $choix_niv2 = exec($MenuEnregistrement->get());
116 $continuer = true;
117 if($choix_niv2 === $menu_enregistrement_entrees[0])
118 {
119 //
120 }
121 elseif($choix_niv2 === $menu_enregistrement_entrees[1])
122 {
123 //
124 }
125 elseif($choix_niv2 === $menu_enregistrement_entrees[2])
126 {
127 //
128 }
129 elseif($choix_niv2 === $menu_enregistrement_entrees[3])
130 {
131 //
132 }
133 else
134 {
135 $continuer = false; // retour menu principal
136 }
137
138 // détail de la prestation
139 if($continuer)
140 {
141 exec($Calendrier->get());
142 exec($FormulairePrestation->get());
143 // enregistrement date et prestation en BDD
144 exec($CommentairePrestation->get());
145 // enregistrement commentaire en BDD
146 // vérification?
147
148 // tableau récaptilatif et demande de confirmation des informations
149 // création fichiers LaTeX et PDF
150
151 // imprimer?
152 //~ $imprimer_facture = exec('zenity --question --width=250 --title="Base de données mise à jour" --text="Imprimer la facture?"');
153 //~ $imprimer_enveloppe = exec('zenity --question --width=250 --title="Base de données mise à jour" --text="Imprimer l\'adresse sur une enveloppe? (insérer une enveloppe DL sans fenêtre dans l\'imprimante"');
154 }
155 }
156
157 elseif($choix_niv1 === $menu_principal_entrees[1]) // = Modifier un enregistrement
158 {}
159
160 elseif($choix_niv1 === $menu_principal_entrees[2]) // = Fichier clients
161 {
162 // quel affichage? un grand tableau avec zenity? une page web? un document LaTeX?
163 }
164
165 // documents à imprimer
166 elseif($choix_niv1 === $menu_principal_entrees[3]) // = Créer/imprimer un document
167 {
168 $choix_niv2 = exec($MenuDocuments->get());
169 if($choix_niv2 === $menu_documents_entrees[0])
170 {
171
172 }
173 elseif($choix_niv2 === $menu_documents_entrees[1]) // = Facture
174 {
175
176 }
177 elseif($choix_niv2 === $menu_documents_entrees[2]) // = Lettre avec adresse
178 {
179
180 }
181 elseif($choix_niv2 === $menu_documents_entrees[3]) // = Livre des recettes
182 {
183
184 }
185 elseif($choix_niv2 === $menu_documents_entrees[4]) // = Registre des achats
186 {
187
188 }
189 elseif($choix_niv2 === $menu_documents_entrees[5]) // = Bilan annuel
190 {
191
192 }
193 else
194 {
195 // retour menu principal
196 }
197 }
198
199 // Supports de communication
200 elseif($choix_niv1 === $menu_principal_entrees[4]) // = Communication
201 {
202 $choix_niv2 = exec($MenuCommunication->get());
203 if($choix_niv2 === $menu_communication_entrees[0]) // = Flyer (nécessite gimp)
204 {
205 exec(window_app_command($image_editor, $flyer));
206 }
207 elseif($choix_niv2 === $menu_communication_entrees[1]) // = Carte de visite (nécessite scribus)
208 {
209 exec(window_app_command($publishing, $business_card));
210 }
211 elseif($choix_niv2 === $menu_communication_entrees[2]) // = Explorateur de fichiers
212 {
213 exec(window_app_command($file_explorer, $pub));
214 }
215 else
216 {
217 // retour menu principal
218 }
219 }
220
221 // BDD
222 elseif($choix_niv1 === $menu_principal_entrees[5]) // = Base de données
223 {
224 if($sqlitebrowser_enable)
225 {
226 exec(window_app_command($sqlite_gui, $db_place));
227 }
228 else
229 {
230 exec($x_term_command . ' ' . $sqlite_cli . ' ' . $db_place); // correpond à priori à: xterm -e sqlite3 ~/ORDIPOLO/Appli_PHP/ordipolo.sqlite
231 }
232 }
233
234 // arrêt
235 else
236 {
237 $boucle = false;
238 }
239}
diff --git a/src/model/CESU.php b/src/model/CESU.php
new file mode 100644
index 0000000..4679da2
--- /dev/null
+++ b/src/model/CESU.php
@@ -0,0 +1,46 @@
1<?php
2// model/CESU.php
3
4class CESU extends Model
5{
6 const TABLE = 'cesu';
7
8 // lecture des données ou hydratation
9 private $ID;
10 private $ID_presta;
11 private $taches;
12 private $duree_travail;
13 private $salaire;
14
15 public function __construct()
16 {
17 $this->table = self::TABLE; // => Model::$table
18 }
19
20 // setters
21 public function setID(int $value)
22 {
23 $this->ID = $value;
24 return($this);
25 }
26 public function setIDPresta(int $value)
27 {
28 $this->ID_presta = $value;
29 return($this);
30 }
31 public function setTaches(string $value)
32 {
33 $this->taches = $value;
34 return($this);
35 }
36 public function setDureeTravail(string $value)
37 {
38 $this->duree_travail = $value;
39 return($this);
40 }
41 public function setSalaire(float $value)
42 {
43 $this->salaire = $value;
44 return($this);
45 }
46}
diff --git a/src/model/Clients.php b/src/model/Clients.php
new file mode 100644
index 0000000..1256458
--- /dev/null
+++ b/src/model/Clients.php
@@ -0,0 +1,50 @@
1<?php
2// model/Clients.php
3
4class Clients extends Model
5{
6 // lecture des données ou hydratation
7 public $ID;
8 public $prenom_nom;
9 public $adresse;
10 public $code_client;
11 public $commentaires;
12
13 public function __construct()
14 {
15 $this->table = strtolower(__CLASS__); // simple parce que la classe a le nom de la table
16 }
17
18 //~ public function set(string $variable, $value)
19 //~ {
20 //~ $this->$variable = $value;
21 //~ return($this);
22 //~ }
23
24 // setters
25 public function setID(int $value) // inutile? il s'autoincrémente
26 {
27 $this->ID = $value;
28 return($this);
29 }
30 public function setPrenom_nom(string $value)
31 {
32 $this->prenom_nom = $value;
33 return($this);
34 }
35 public function setAdresse(string $value)
36 {
37 $this->adresse = $value;
38 return($this);
39 }
40 public function setCode_client(string $value)
41 {
42 $this->code_client = $value;
43 return($this);
44 }
45 public function setCommentaires(string $value)
46 {
47 $this->commentaires = $value;
48 return($this);
49 }
50}
diff --git a/src/model/DB.php b/src/model/DB.php
new file mode 100644
index 0000000..381623b
--- /dev/null
+++ b/src/model/DB.php
@@ -0,0 +1,48 @@
1<?php
2// php/DB.php
3
4// cette classe suit le pattern "singleton"
5// but: ne permettre qu'une seule instance de la classe (laquelle sera éventuellement globale)
6
7// comment?
8// - Un attribut privé et statique contiendra l'instance unique de la classe
9// - Un constructeur privé afin d'empêcher l'instanciation depuis l'extérieur de la classe
10// - Une méthode statique qui permet soit d'instancier la classe soit de retourner l'unique instance créée.
11
12class DB extends PDO
13{
14 // paramètres du constructeur de PDO (avec sqlite seul le premier est nécessaire)
15 public static $dsn = ''; // Data Source Name = 1er paramètre
16 //~ public static $dbms = 'sqlite';
17 //~ public static $user = '';
18 //~ public static $password = '';
19 //~ public static $options = '';
20 private static $Instance;
21
22 private function __construct() // exécuté une seul fois à cause du "if" dans getInstance()
23 {
24 try
25 {
26 parent::__construct(self::$dsn); // => PDO::$dsn
27 //$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES utf8'); // pour mysql/mariadb
28 $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // $this pour la méthode du parent PDO
29 $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // pour PDO:fetch() et PDO::fetchAll()
30 // avec PDO::FETCH_ASSOC on obtient un tableau associatif, marche très bien puisqu'on utilise déjà des ID avec incrémentation automatique
31 // avec PDO::FETCH_BOTH (par défaut) on récupère les données en double (identifiants partant de 0 + tableau associatif)
32 }
33 catch(PDOException $e)
34 {
35 die("Impossible de se connecter à la base de données.\n" . $e->getMessage());
36 }
37 }
38
39 // créer son objet avec: $Bdd = parent::getInstance();
40 public static function getInstance(): self
41 {
42 if(self::$Instance === null)
43 {
44 self::$Instance = new self();
45 }
46 return self::$Instance;
47 }
48}
diff --git a/src/model/DevisFactures.php b/src/model/DevisFactures.php
new file mode 100644
index 0000000..be733dd
--- /dev/null
+++ b/src/model/DevisFactures.php
@@ -0,0 +1,98 @@
1<?php
2// model/DevisFactures.php
3
4class DevisFactures extends Model
5{
6 // lecture des données ou hydratation
7 private $ID;
8 private $ID_presta;
9 private $validite_devis;
10 private $signature_devis;
11 private $taches;
12 private $machine;
13 private $OS;
14 private $donnees;
15 private $cles_licences;
16 private $total_main_d_oeuvre;
17 private $pieces;
18 private $total_pieces;
19 private $deplacement;
20 private $total_HT;
21
22 public function __construct()
23 {
24 $this->table = strtolower(__CLASS__);
25 }
26
27 // setters
28 public function setID(int $value)
29 {
30 $this->ID = $value;
31 return($this);
32 }
33 public function setIDPresta(int $value)
34 {
35 $this->ID_presta = $value;
36 return($this);
37 }
38 public function setValiditeDdevis(string $value)
39 {
40 $this->validite_devis = $value;
41 return($this);
42 }
43 public function setSignatureDevis(string $value)
44 {
45 $this->signature_devis = $value;
46 return($this);
47 }
48 public function setTaches(string $value)
49 {
50 $this->taches = $value;
51 return($this);
52 }
53 public function setMachine(string $value)
54 {
55 $this->machine = $value;
56 return($this);
57 }
58 public function setOS(string $value)
59 {
60 $this->OS = $value;
61 return($this);
62 }
63 public function setDonnees(string $value)
64 {
65 $this->donnees = $value;
66 return($this);
67 }
68 public function setClesLicences(string $value)
69 {
70 $this->cles_licences = $value;
71 return($this);
72 }
73 public function setTotalMainDOeuvre(float $value)
74 {
75 $this->total_main_d_oeuvre = $value;
76 return($this);
77 }
78 public function setPieces(string $value)
79 {
80 $this->pieces = $value;
81 return($this);
82 }
83 public function setTotalPieces(float $value)
84 {
85 $this->total_pieces = $value;
86 return($this);
87 }
88 public function setDeplacement(float $value)
89 {
90 $this->deplacement = $value;
91 return($this);
92 }
93 public function setTotalHT(float $value)
94 {
95 $this->total_HT = $value;
96 return($this);
97 }
98}
diff --git a/src/model/Locations.php b/src/model/Locations.php
new file mode 100644
index 0000000..2aa175a
--- /dev/null
+++ b/src/model/Locations.php
@@ -0,0 +1,74 @@
1<?php
2// model/Locations.php
3
4class Locations extends Model
5{
6 // lecture des données ou hydratation
7 private $ID;
8 private $ID_presta;
9 private $nature_bien;
10 private $modele;
11 private $valeur;
12 private $etat_des_lieux_debut;
13 private $etat_des_lieux_fin;
14 private $duree_location;
15 private $loyer_mensuel;
16 private $total_HT;
17
18 public function __construct()
19 {
20 $this->table = strtolower(__CLASS__);
21 }
22
23 // setters
24 public function setID(int $value)
25 {
26 $this->ID = $value;
27 return($this);
28 }
29 public function setIDPresta(int $value)
30 {
31 $this->ID_presta = $value;
32 return($this);
33 }
34 public function setNatureBien(string $value)
35 {
36 $this->nature_bien = $value;
37 return($this);
38 }
39 public function setModele(string $value)
40 {
41 $this->modele = $value;
42 return($this);
43 }
44 public function setValeur(float $value)
45 {
46 $this->valeur = $value;
47 return($this);
48 }
49 public function setEtatDesLieuxDebut(string $value)
50 {
51 $this->etat_des_lieux_debut = $value;
52 return($this);
53 }
54 public function setEtatDesLieuxFin(string $value)
55 {
56 $this->etat_des_lieux_fin = $value;
57 return($this);
58 }
59 public function setDureeLocation(string $value)
60 {
61 $this->duree_location = $value;
62 return($this);
63 }
64 public function setlLyerMensuel(float $value)
65 {
66 $this->loyer_mensuel = $value;
67 return($this);
68 }
69 public function setTotalHT(float $value)
70 {
71 $this->total_HT = $value;
72 return($this);
73 }
74}
diff --git a/src/model/Model.php b/src/model/Model.php
new file mode 100644
index 0000000..ad9e6c7
--- /dev/null
+++ b/src/model/Model.php
@@ -0,0 +1,162 @@
1<?php
2// php/Model.php
3
4class Model extends DB
5{
6 private $db; // instance de PDO
7 protected $table; // <= enfant
8 //static protected $tableStructure;
9
10 public function __construct()
11 {
12 $this->db = parent::getInstance(); // connexion
13 }
14
15
16 // setters (plusieurs en même temps)
17 public function hydrate(array $data) // $data = tableau associatif en entrée: nom_du_champ => valeur
18 {
19 foreach($data as $key => $value)
20 {
21 // nom d'un setter, forme "setMachin()"
22 $setterName = 'set' . ucfirst($key); // ucfirst met la première lettre en majuscule
23 // détection
24 if(method_exists($this, $setterName)) // on trouve aussi la méthode is_callable()
25 {
26 // on renseigne les propriétés des l'instance
27 $this->$setterName($value); // nom d'une méthode dans une variable
28 }
29 }
30 return($this);
31 }
32
33
34 // exécuter le SQL
35 // les attributs correspondent aux ? dans les requêtes préparées
36 // ne pas surcharger la méthode PDO::query() qui n'est pas compatible
37 protected function execQuery(string $sql, array $attributes = null)
38 {
39 $this->db = parent::getInstance(); // connexion
40
41 if($attributes !== null) // requête préparée
42 {
43 $query = $this->db->prepare($sql);
44 $query->execute($attributes);
45 return $query;
46 }
47 else // requête simple
48 {
49 return $this->db->query($sql);
50 }
51 }
52
53
54 // méthodes CRUD qui marchent (les spécifiques sont dans les classes enfant)
55
56 // create INSERT
57 public function create() // = write
58 {
59 $fields = [];
60 $question_marks = []; // ?
61 $values = [];
62 foreach($this as $field => $value)
63 {
64 // champs non renseignées et variables de l'objet qui ne sont pas des champs
65 // note: avec le !== (au lieu de !=) une valeur 0 passe le filtre
66 if($value !== null && $field != 'db' && $field != 'table')
67 {
68 $fields[] = $field; // push
69 $question_marks[] = '?';
70 $values[] = $value;
71 }
72 }
73 $field_list = implode(', ', $fields);
74 $question_mark_list = implode(', ', $question_marks);
75
76 // INSERT INTO annonces (titre, description, actif) VALUES (?, ?, ?)
77 return($this->execQuery('INSERT INTO ' . $this->table . ' (' . $field_list . ') VALUES (' . $question_mark_list . ')', $values));
78 }
79
80
81 // read SELECT
82 public function readAll()
83 {
84 $query = $this->execQuery('SELECT * FROM ' . $this->table . ';'); // fonctionne aussi sans le point virgule dans le SQL!!
85 return($query->fetchAll());
86 }
87 public function findById(int $id)
88 {
89 return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE id = ' . $id)->fetch());
90 }
91
92 public function find(array $criteria)
93 {
94 $fields = [];
95 $values = [];
96
97 // change "'ID' => 2" en "'ID' = ?" et "2"
98 foreach($criteria as $field => $value)
99 {
100 $fields[] = "$field = ?"; // même chose que: $field . " = ?"
101 $values[] = $value;
102 }
103 $field_list = implode(' AND ', $fields); // créer une chaîne reliant les morceaux avec le morceau AND en paramètre: 'adresse = ? AND ID = ?'
104
105 // SELECT * FROM annonces WHERE actif = 1;
106 return($this->execQuery('SELECT * FROM ' . $this->table . ' WHERE ' . $field_list, $values)->fetchAll());
107 }
108
109
110 // update UPDATE
111 public function update(int $id)
112 {
113 $fields = [];
114 $values = [];
115 foreach($this as $field => $value)
116 {
117 if($value !== null && $field != 'db' && $field != 'table') // champs non renseignées et variables de l'objet qui ne sont pas des champs
118 {
119 $fields[] = $field . ' = ?';
120 $values[] = $value;
121 }
122 }
123 $values[] = $id;
124 $field_list = implode(', ', $fields);
125
126 // UPDATE annonces SET titre = ?, description = ?, actif = ? WHERE id= ?
127 return($this->execQuery('UPDATE ' . $this->table . ' SET ' . $field_list . ' WHERE id = ?', $values));
128 }
129
130
131 // delete DELETE
132 public function delete(int $id)
133 {
134 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
135 }
136
137
138 // fonction appelée une seule fois pour chaque table
139 // le tableau nécessaire n'est pas copié en mémoire à l'instanciation (pas de fuite de mémoire), mais uniquement à l'appel de cette fonction statique, à la fin de la fonction la mémoire est libérée
140 // DBStructure::${self::$tableStructure} permet de nommer une variable statique de classe
141 static public function createTables()
142 {
143 //~ var_dump(StructTablesDB::$structureOfTables);
144 foreach(StructTablesDB::$structureOfTables as $tableName => $oneTable)
145 {
146 //var_dump(StructTablesDB::${self::$tableStructure}); => propriété statique de classe dans une variable
147 $fields_and_types = [];
148 $query = 'CREATE TABLE IF NOT EXISTS ' . $tableName . ' (';
149 foreach($oneTable as $key => $value)
150 {
151 $fields_and_types[] = $key . ' ' . $value;
152 }
153 $query .= implode(', ', $fields_and_types); // implode() convertit un tableau en une chaîne avec un séparateur entre chaque élément
154 $query .= ', PRIMARY KEY(ID AUTOINCREMENT));';
155 //echo($query . "\n\n");
156
157 parent::getInstance()->exec($query); // merci singleton!
158 }
159
160
161 }
162}
diff --git a/src/model/Prestations.php b/src/model/Prestations.php
new file mode 100644
index 0000000..4f58d70
--- /dev/null
+++ b/src/model/Prestations.php
@@ -0,0 +1,62 @@
1<?php
2// model/Prestations.php
3
4class Prestations extends Model
5{
6 // lecture des données ou hydratation
7 private $ID;
8 private $IDClient;
9 private $combientieme_fois;
10 private $code_presta;
11 private $date;
12 private $type;
13 private $mode_paiement;
14 private $commentaires;
15
16 public function __construct()
17 {
18 $this->table = strtolower(__CLASS__);
19 }
20
21 // setters
22 public function setID(int $value)
23 {
24 $this->ID = $value;
25 return($this);
26 }
27 public function setIDClient(int $value)
28 {
29 $this->ID_client = $value;
30 return($this);
31 }
32 public function setCombientiemeFois(int $value)
33 {
34 $this->combientieme_fois = $value;
35 return($this);
36 }
37 public function setCodePresta(string $value)
38 {
39 $this->code_presta = $value;
40 return($this);
41 }
42 public function setDate(int $value)
43 {
44 $this->date = $value;
45 return($this);
46 }
47 public function setType(string $value)
48 {
49 $this->type = $value;
50 return($this);
51 }
52 public function setModePaiement(string $value)
53 {
54 $this->mode_paiement = $value;
55 return($this);
56 }
57 public function setCommentaires(string $value)
58 {
59 $this->commentaires = $value;
60 return($this);
61 }
62}
diff --git a/src/model/StructTablesDB.php b/src/model/StructTablesDB.php
new file mode 100644
index 0000000..cf6de5d
--- /dev/null
+++ b/src/model/StructTablesDB.php
@@ -0,0 +1,35 @@
1<?php
2// model/StructTablesDB.php
3
4// structure de données façon C
5// créer les requêtes avec implode(', ', $DbStructure)
6class StructTablesDB
7{
8 // possibilité de lire un fichier JSON
9 static public $structureOfTables = [
10 // la table prestations est liée à la table clients
11 // les tables devis_factures, cesu et locations sont liées à la table prestations
12 'clients' => ['ID' => 'INTEGER', 'prenom_nom' => 'TEXT', 'adresse' => 'TEXT', 'code_client' => 'TEXT', 'commentaires' => 'TEXT'],
13 'prestations' => ['ID' => 'INTEGER', 'ID_client' => 'INTEGER', 'combientieme_fois' => 'INTEGER', 'code_presta' => 'TEXT', 'date' => 'INTEGER', 'type' => 'TEXT', 'mode_paiement' => 'TEXT', 'commentaires' => 'TEXT'],
14 'devisfactures' => ['ID' => 'INTEGER', 'ID_presta' => 'INTEGER', 'validite_devis' => 'TEXT', 'signature_devis' => 'TEXT', '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'],
15 'cesu' => ['ID' => 'INTEGER', 'ID_presta' => 'INTEGER', 'taches' => 'TEXT', 'duree_travail' => 'TEXT', 'salaire' => 'REAL'],
16 'locations' => ['ID' => 'INTEGER', 'ID_presta' => 'INTEGER', 'nature_bien' => 'TEXT', 'modele' => 'TEXT', 'valeur' => 'REAL', 'etat_des_lieux_debut' => 'TEXT', 'etat_des_lieux_fin' => 'TEXT', 'duree_location' => 'TEXT', 'loyer_mensuel' => 'REAL', 'total_HT' => 'REAL']
17 ];
18
19 // les types de variables de sqlite sont peu nombreux et autorisent un typage automatique
20 // le "type indiqué" est indiqué dans l'instruction CREATE TABLE
21 // https://www.leppf.com/site/spip.php?article89
22
23 // || type indiqué || type choisi automatiquement || autre types possibles ||
24 // ---------------------------------------------------------------------------
25 // || TEXT || TEXT || BLOB, NULL ||
26 // || INTEGER || INTEGER (de 1 à 8 octets) || REAL, TEXT, BLOB, NULL ||
27 // || REAL || REAL (flottant sur 9 octets) || TEXT, BLOB, NULL ||
28 // || NUMERIC || INTEGER ou REAL || TEXT, BLOB, NULL ||
29 // || NONE || indéfini || dépend des données ||
30
31 // du code SQL écrit pour d'autres SGBD devrait fonctionner,
32 // sqlite fera des conversions dans ses propres types avec les problèmes qu'on peut imaginer
33
34 // pour les dates, on stockera à priori le timestamp
35}
diff --git a/src/view/Zenity.php b/src/view/Zenity.php
new file mode 100644
index 0000000..a04b794
--- /dev/null
+++ b/src/view/Zenity.php
@@ -0,0 +1,110 @@
1<?php
2// php/Zenity.php
3//
4// commande système zenity
5
6abstract class ZenityCmd
7{
8 protected $command = 'zenity';
9 protected $command_type = '';
10 protected $rows = [];
11 private $title = 'ORDIPOLO';
12 private $text = '';
13 protected $width = 300;
14 protected $height = 200; // recalculée en fonction du contenu, vaut au minimum 150
15
16 protected function __construct($text, array $rows = []) // $rows est optionnel
17 {
18 $this->text = $text;
19 $this->rows= $rows;
20 $this->command .= $this->command_type;
21 $this->command .= ' --title="' . $this->title . '"';
22 $this->command .= ' --text="' . $this->text . '"';
23 }
24
25 public function get()
26 {
27 return($this->command);
28 }
29}
30
31
32class ZenityList extends ZenityCmd
33{
34 public function __construct($text, array $rows)
35 {
36 $this->command_type = ' --list';
37 parent::__construct($text, $rows);
38 $this->height = 80 + count($this->rows) * 25;
39 $this->command .= ' --width=' . $this->width;
40 $this->command .= ' --height=' . $this->height;
41 $this->command .= ' --hide-header'; // ligne inutile, il y a déjà le --text
42 self::one_column_zenity_list($this->rows);
43 }
44
45 public function set_entries($rows_set) // variable renseignée après la construction
46 {
47 $this->rows = $rows_set;
48 }
49
50 private function one_column_zenity_list($rows)
51 {
52 $output = ' --column=""';
53 foreach($rows as $entry)
54 {
55 $output .= ' "' . $entry . '"'; // forme: ' "choix 1" "choix 2"'
56 }
57 $this->command .= $output;
58 }
59}
60
61class ZenityQuestion extends ZenityCmd
62{
63 public function __construct($text)
64 {
65 $this->command_type = ' --question';
66 parent::__construct($text);
67 $this->command .= ' && echo $?';
68 // la sortie de "zenity --question" est le statut de sortie "$?"
69 // $? vaut 0 pour oui, 1 pour non, à ceci près que pour non zenity ne renvoie rien
70 }
71}
72
73class ZenityForms extends ZenityCmd
74{
75 public function __construct($text, array $rows)
76 {
77 $this->command_type = ' --forms';
78 parent::__construct($text, $rows);
79 //$this->height = 80 + count($this->rows) * 25; // à tester, mais devrait produire le rendu attendu
80 self::entries_zenity_forms($this->rows);
81 }
82
83 private function entries_zenity_forms($entries)
84 {
85 $output = '';
86 foreach($entries as $one_entry)
87 {
88 $output .= ' --add-entry="' . $one_entry . '"'; // forme: ' "choix 1" "choix 2"'
89 }
90 $this->command .= $output;
91 }
92}
93
94class ZenityCalendar extends ZenityCmd
95{
96 public function __construct($text)
97 {
98 $this->command_type = ' --calendar';
99 parent::__construct($text);
100 }
101}
102
103class ZenityEntry extends ZenityCmd
104{
105 public function __construct($text)
106 {
107 $this->command_type = ' --entry';
108 parent::__construct($text);
109 }
110}
diff --git a/src/view/zenity_setup.php b/src/view/zenity_setup.php
new file mode 100644
index 0000000..2f55cf2
--- /dev/null
+++ b/src/view/zenity_setup.php
@@ -0,0 +1,37 @@
1<?php
2// php/zenity_setup.php
3
4
5// contenu des fenêtres zenity
6$menu_principal_text = "Gestion d'une micro-entreprise";
7$menu_principal_entrees = ["Nouvelle prestation", "Modifier enregistrement", "Fichier clients", "Créer/imprimer un document", "Communication", "Base de données"];
8$question_nouveau_client_text = "Ce client figure t\'il déjà dans le fichier clients?";
9$menu_enregistrement_text = "Type d\'enregistrement?";
10$menu_enregistrement_entrees = ["Devis", "Facture", "CESU", "Pas de prestation"];
11$menu_documents_text = "Création de documents LaTeX";
12$menu_documents_entrees = ["Devis", "Facture", "Lettre avec adresse", "Livre des recettes", "Registre des achats", "Bilan annuel"];
13$menu_communication_text = "Imprimer un support de communication";
14$menu_communication_entrees = ["Flyer (nécessite gimp)", "Carte de visite (nécessite scribus)", "Explorateur de fichiers"];
15$recherche_client_text = "Recherche d'un client avec son nom ou son code client";
16$resultats_recherche_client_text = "Résultats de la recherche, sélectionner un client";
17$nouveau_client_text = "Nouveau client";
18$nouveau_client_entrees = ["Prénom Nom:", "Adresse:", "Code client, type: J.P.Duchmol"];
19$calendar_text = 'Nouvelle prestation étape 1/3 - Choisir une date';
20$formulaire_text = 'Nouvelle prestation 2/3 - Détail des travaux';
21$formulaire_entrees = ["Tâches effectuées:", "Modèle du PC:", "OS:", "Données sauvegardées:", "Clés d\'activation:", "Temps main d\'oeuvre (heures):", "Total main d\'oeuvre (euros):", "Total pièces (euros):", "Déplacement (euros)", "Total HT (euros):",];
22$commentaire_prestation_text = 'Nouvelle prestation 3/3 - Commentaires';
23
24
25// commandes système qui ouvrent les fenêtres zenity, un objet = une commande
26// s'utilisent comme ceci: exec($Objet->get());
27$MenuPrincipal = new ZenityList($menu_principal_text, $menu_principal_entrees);
28$QuestionNouveauClient = new ZenityQuestion($question_nouveau_client_text);
29$MenuEnregistrement = new ZenityList($menu_enregistrement_text, $menu_enregistrement_entrees);
30$MenuDocuments = new ZenityList($menu_documents_text, $menu_documents_entrees);
31$MenuCommunication = new ZenityList($menu_communication_text, $menu_communication_entrees);
32$RechercheClient = new zenityEntry($recherche_client_text);
33$ResultatsRechercheClient = new zenityList($resultats_recherche_client_text, []);
34$NouveauClient = new ZenityForms($nouveau_client_text, $nouveau_client_entrees);
35$Calendrier = new ZenityCalendar($calendar_text);
36$FormulairePrestation = new ZenityForms($formulaire_text, $formulaire_entrees);
37$CommentairePrestation = new ZenityEntry($commentaire_prestation_text);