From 4c4f70bf6eb88a419add86e182d3080674196433 Mon Sep 17 00:00:00 2001 From: Debulois Date: Wed, 20 Apr 2022 13:17:36 +0200 Subject: Mis en place de la structure orientée objet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app_alphajob/database/__init__.py | 1 - app_alphajob/database/dbadmin.py | 177 ------------------------------ app_alphajob/database/dbmain.py | 217 ------------------------------------- app_alphajob/database/dbmission.py | 160 --------------------------- app_alphajob/database/dbsearch.py | 140 ------------------------ app_alphajob/database/dbuser.py | 171 ----------------------------- app_alphajob/main.py | 119 -------------------- app_alphajob/ressources/icon.ico | Bin 41662 -> 0 bytes src/core/__init__.py | 0 src/core/user.py | 25 +++++ src/database/__init__.py | 1 + src/database/dbadmin.py | 177 ++++++++++++++++++++++++++++++ src/database/dbmain.py | 217 +++++++++++++++++++++++++++++++++++++ src/database/dbmission.py | 160 +++++++++++++++++++++++++++ src/database/dbsearch.py | 140 ++++++++++++++++++++++++ src/database/dbuser.py | 171 +++++++++++++++++++++++++++++ src/gui/__init__.py | 0 src/gui/aPropos.py | 14 +++ src/gui/home.py | 24 ++++ src/gui/login.py | 42 +++++++ src/gui/menu.py | 17 +++ src/gui/ressources/icon.ico | Bin 0 -> 41662 bytes src/main.py | 29 +++++ 23 files changed, 1017 insertions(+), 985 deletions(-) delete mode 100644 app_alphajob/database/__init__.py delete mode 100644 app_alphajob/database/dbadmin.py delete mode 100644 app_alphajob/database/dbmain.py delete mode 100644 app_alphajob/database/dbmission.py delete mode 100644 app_alphajob/database/dbsearch.py delete mode 100644 app_alphajob/database/dbuser.py delete mode 100644 app_alphajob/main.py delete mode 100644 app_alphajob/ressources/icon.ico create mode 100644 src/core/__init__.py create mode 100644 src/core/user.py create mode 100644 src/database/__init__.py create mode 100644 src/database/dbadmin.py create mode 100644 src/database/dbmain.py create mode 100644 src/database/dbmission.py create mode 100644 src/database/dbsearch.py create mode 100644 src/database/dbuser.py create mode 100644 src/gui/__init__.py create mode 100644 src/gui/aPropos.py create mode 100644 src/gui/home.py create mode 100644 src/gui/login.py create mode 100644 src/gui/menu.py create mode 100644 src/gui/ressources/icon.ico create mode 100644 src/main.py diff --git a/app_alphajob/database/__init__.py b/app_alphajob/database/__init__.py deleted file mode 100644 index 03b0cc7..0000000 --- a/app_alphajob/database/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# https://realpython.com/python-import/#basic-python-import \ No newline at end of file diff --git a/app_alphajob/database/dbadmin.py b/app_alphajob/database/dbadmin.py deleted file mode 100644 index dd6b4d0..0000000 --- a/app_alphajob/database/dbadmin.py +++ /dev/null @@ -1,177 +0,0 @@ - -############################################################################ -# # -# Description: Ensemble de méthodes pour étendre dbmain # -# afin de gérer l'administration du site # -# # -############################################################################ - -# Import de dbmain -from . import dbmain - -# Extension de cette classe avec dbmain -class DbAdmin(dbmain.DbMain): - - # **************************************************************************** - # GESTION DES UTILISATEURS DANS L'ADMIN - # **************************************************************************** - # Récupérer toutes les infos de la table userAccount - def get_all_users_account(self): - reqGetAll = """ - SELECT - * - FROM - """ + self.TABLEUSERACCOUNT - # https:#www.php.net/manual/fr/pdostatement.fetch.php - # "PDO::FETCH_ASSOC: retourne un tableau indexé - # par le nom de la colonne comme retourné dans le jeu de résultats" - self.exec_cmd(reqGetAll) - result = self.cur.fetchall() - return result - - # https:#stackoverflow.com/questions/1361340/how-can-i-do-insert-if-not-exists-in-mysql - # Suppresion d'un utilisateur - def del_user_by_userid(self, userId): - # Préparation de la requète pour voir si l'utilisateur existe - # https:#stackoverflow.com/questions/1676551/best-way-to-test-if-a-row-exists-in-a-mysql-table - reqCheckExistId = """ - SELECT EXISTS( - SELECT 1 FROM - """ + self.TABLEUSERACCOUNT + """ - WHERE - userId = ? - LIMIT 1 - )""" - # Exécution de la requète, fetchall pour avoir le résultat - # https:#www.php.net/manual/fr/pdostatement.fetch.php - # struct par défaut req et index (fetch_both) = arr([0] => arr("req" => BOOL, [0] => BOOL]) - # PDO::FETCH_NUM : retourne un tableau indexé par le numéro de la colonne comme elle - # est retourné dans votre jeu de résultat, commençant à 0 - self.exec_cmd(reqCheckExistId, [userId]) - reqResult = self.cur.fetchall() - # Si il existe - if (reqResult[0][0]): - # Préparation de la requète pour suppression - reqDelUser = """DELETE FROM """ + self.TABLEUSERACCOUNT + """ WHERE userId = ?""" - # Exécution de la requète - self.exec_cmd(reqDelUser, [userId]) - # Retourne 1 pour réussite - return 1 - else: - # Retourne 0 pour échec - return 0 - - - # **************************************************************************** - # GESTION DES EMPLOIS DANS L'ADMIN - # **************************************************************************** - # Ajout d'une categorie - def register_job_category(self, jobNameEn, jobNameFr): - # Préparation et execution de la requète pour voir si la categorie existe en anglais - reqCheckjobCategoryNameEn = """ - SELECT EXISTS( - SELECT 1 FROM - """ + self.TABLEJOBCATEGORY + """ - WHERE - jobCategoryNameEn = ? - LIMIT 1 - )""" - self.exec_cmd(reqCheckjobCategoryNameEn, [jobNameEn]) - reqResultEn = self.cur.fetchall() - # Si il n'existe pas en anglais - if not reqResultEn[0][0]: - # Préparation et execution de la requète pour voir si la categorie existe en Français - reqCheckjobCategoryNameFr = """ - SELECT EXISTS( - SELECT 1 FROM - """ + self.TABLEJOBCATEGORY + """ - WHERE - jobCategoryNameFr = ? - LIMIT 1 - )""" - self.exec_cmd(reqCheckjobCategoryNameFr, [jobNameFr]) - reqResultFr = self.cur.fetchall() - # Si il n'existe pas en Français non plus - if not reqResultFr[0][0]: - # Préparation de la requète pour l'ajout - reqjobCategoryNameAdd = """ - INSERT INTO - """ + self.TABLEJOBCATEGORY + """ - (jobCategoryNameEn, jobCategoryNameFr) - VALUES - (? ,?)""" - # Exécution de la requète - self.exec_cmd(reqjobCategoryNameAdd, [jobNameEn, jobNameFr]) - # Retourne 1 pour réussite - return 1 - else: - # Retourne 0 pour échec - return 0 - else: - # Retourne 0 pour échec - return 0 - - # Suppresion d'un utilisateur - def del_job_category_by_jobid(self, jobId): - # Préparation de la requète pour voir si l'utilisateur existe - reqCheckExistId = """ - SELECT EXISTS( - SELECT 1 FROM - """ + self.TABLEJOBCATEGORY + """ - WHERE - jobCategoryId = ? - LIMIT 1 - )""" - # Exécution de la requète, fetchall pour avoir le résultat - # struct par défaut req et index (fetch_both) = arr([0] => arr("req" => BOOL, [0] => BOOL]) - # fetch_num pour casser l'index "req" en chiffre, dict -> list - self.exec_cmd(reqCheckExistId, [jobId]) - reqResult = self.cur.fetchall() - # Si il existe - if (reqResult[0][0]): - # Préparation de la requète pour suppression - reqDelJobCategory = """ - DELETE FROM - """ + self.TABLEJOBCATEGORY + """ - WHERE - jobCategoryId = ?""" - # Exécution de la requète - self.exec_cmd(reqDelJobCategory, [jobId]) - # Retourne 1 pour réussite - return 1 - else: - # Retourne 0 pour échec - return 0 - - # **************************************************************************** - # GESTION DES MISSIONS DANS L'ADMIN - # **************************************************************************** - # Suppresion d'une mission - def del_mission_by_missionid(self, missionId): - # Préparation de la requète pour voir si l'utilisateur existe - reqCheckExistId = """ - SELECT EXISTS( - SELECT 1 FROM - """ + self.TABLEMISSION + """ - WHERE - missionId = ? - LIMIT 1 - )""" - # Exécution de la requète - self.exec_cmd(reqCheckExistId, [missionId]) - reqResult = self.cur.fetchall() - # Si il existe - if (reqResult[0][0]): - # Préparation de la requète pour suppression - reqDelMission = """ - DELETE FROM - """ + self.TABLEMISSION + """ - WHERE - missionId = ?""" - # Exécution de la requète - self.exec_cmd(reqDelMission, [missionId]) - # Retourne 1 pour réussite - return 1 - else: - # Retourne 0 pour échec - return 0 diff --git a/app_alphajob/database/dbmain.py b/app_alphajob/database/dbmain.py deleted file mode 100644 index 602cec6..0000000 --- a/app_alphajob/database/dbmain.py +++ /dev/null @@ -1,217 +0,0 @@ - -############################################################################ -# # -# Description: Partie commune des deux ensembles de méthodes # -# pour la gestion de la BDD # -# # -############################################################################ - -import mysql.connector -from passlib.hash import sha512_crypt - -# const si CAPS -# https://www.w3schools.com/python/python_mysql_getstarted.asp -# https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html -# https://stackoverflow.com/questions/11565487/python-equivalent-of-php-mysql-fetch-array - - -class DbMain(): - # **************************************************************************** - # INFOS GLOBAL ET DE CONNEXION - # **************************************************************************** - # Pour gérer si "en production" - DEBUG = False - # Configuration du serveur MYSQL / MARIADB - HOST = "127.0.0.1" - USER = "root" - PASSWORD = "" - DATABASE = "alphajob" - - # **************************************************************************** - # DECLARATION DES TABLES - # **************************************************************************** - # UserAccount, infos du compte nécessaire à la connection - CREATETABLEUSERACCOUNT = """CREATE TABLE IF NOT EXISTS `alphajob`.`userAccount` ( - `userId` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `email` VARCHAR(128) NOT NULL, - `password` VARCHAR(128) NOT NULL, - `tokenAutoLogin` VARCHAR(128) NULL DEFAULT NULL, - `inscriptionDate` TIMESTAMP NOT NULL, - `userStatus` TINYINT(1) UNSIGNED NOT NULL, - PRIMARY KEY (`userId`) - ) - ENGINE = InnoDB - DEFAULT CHARACTER SET = utf8;""" - - # Infos complémentaires des utilisateur, liée à userAccount par userId - CREATETABLEUSERINFO = """CREATE TABLE IF NOT EXISTS `alphajob`.`userInfo` ( - `lastname` VARCHAR(128) NOT NULL, - `firstname` VARCHAR(128) NOT NULL, - `phoneNumber` VARCHAR(10) NOT NULL, - `adress` VARCHAR(128) NOT NULL, - `zipCode` VARCHAR(6) NOT NULL, - `city` VARCHAR(128) NOT NULL, - `degree` VARCHAR(128) NULL DEFAULT NULL, - `capability` VARCHAR(256) NULL DEFAULT NULL, - `description` VARCHAR(256) NULL DEFAULT NULL, - `userId` INT UNSIGNED NOT NULL, - PRIMARY KEY (`userId`), - INDEX `fk_userinfo_userId_idx` (`userId` ASC) VISIBLE, - CONSTRAINT `fk_userinfo_userId` - FOREIGN KEY (`userId`) - REFERENCES `alphajob`.`userAccount` (`userId`) - ON DELETE CASCADE - ON UPDATE CASCADE - ) - ENGINE = InnoDB - DEFAULT CHARACTER SET = utf8;""" - - # Liste des categories d'emploie possible - CREATETABLEJOBCATEGORY = """CREATE TABLE IF NOT EXISTS `alphajob`.`jobCategory` ( - `jobCategoryId` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `jobCategoryNameEn` VARCHAR(128) NOT NULL, - `jobCategoryNameFr` VARCHAR(128) NOT NULL, - PRIMARY KEY (`jobCategoryId`) - ) - ENGINE = InnoDB - DEFAULT CHARACTER SET = utf8;""" - - # Assosications des emploies à un utilisateur - CREATETABLEUSERJOB = """CREATE TABLE IF NOT EXISTS `alphajob`.`userJob` ( - `userId` INT UNSIGNED NOT NULL, - `jobCategoryId` INT UNSIGNED NOT NULL, - INDEX `fk_userInfo_userId_idx` (`userId` ASC) VISIBLE, - INDEX `fk_jobCategory_jobCategoryId_idx` (`jobCategoryId` ASC) VISIBLE, - CONSTRAINT `fk_userJob_userId` - FOREIGN KEY (`userId`) - REFERENCES `alphajob`.`userAccount` (`userId`) - ON DELETE CASCADE - ON UPDATE CASCADE, - CONSTRAINT `fk_userJob_jobCategoryId` - FOREIGN KEY (`jobCategoryId`) - REFERENCES `alphajob`.`jobCategory` (`jobCategoryId`) - ON DELETE CASCADE - ON UPDATE CASCADE - ) - ENGINE = InnoDB - DEFAULT CHARACTER SET = utf8;""" - - # Infos sur les missions effectuées, liée à userAccount par userId et consultantId - CREATETABLEMISSION = """CREATE TABLE IF NOT EXISTS `alphajob`.`mission` ( - `missionId` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `date` TIMESTAMP NOT NULL, - `subject` VARCHAR(128) NULL DEFAULT NULL, - `note` TINYINT(1) UNSIGNED NULL DEFAULT NULL, - `review` VARCHAR(256) NULL DEFAULT NULL, - `acceptedByPro` TIMESTAMP NULL DEFAULT NULL, - `validatedByClient` TIMESTAMP NULL DEFAULT NULL, - `validatedByPro` TIMESTAMP NULL DEFAULT NULL, - `clientId` INT UNSIGNED NOT NULL, - `proId` INT UNSIGNED NOT NULL, - `jobCategoryId` INT UNSIGNED NOT NULL, - PRIMARY KEY (`missionId`), - INDEX `fk_mission_clientId_idx` (`clientId` ASC) VISIBLE, - INDEX `fk_mission_proId_idx` (`proId` ASC) VISIBLE, - INDEX `fk_mission_jobCategoryId_idx` (`jobCategoryId` ASC) VISIBLE, - CONSTRAINT `fk_mission_clientId` - FOREIGN KEY (`clientId`) - REFERENCES `alphajob`.`userAccount` (`userId`) - ON DELETE CASCADE - ON UPDATE CASCADE, - CONSTRAINT `fk_mission_proId` - FOREIGN KEY (`proId`) - REFERENCES `alphajob`.`userAccount` (`userId`) - ON DELETE CASCADE - ON UPDATE CASCADE, - CONSTRAINT `fk_mission_jobCategoryId` - FOREIGN KEY (`jobCategoryId`) - REFERENCES `alphajob`.`jobCategory` (`jobCategoryId`) - ON DELETE CASCADE - ON UPDATE CASCADE - ) - ENGINE = InnoDB - DEFAULT CHARACTER SET = utf8""" - - # Noms des tables - TABLEUSERACCOUNT = "userAccount" - TABLEUSERINFO = "userInfo" - TABLEJOBCATEGORY = "jobCategory" - TABLEUSERJOB = "userJob" - TABLEMISSION = "mission" - - # **************************************************************************** - # FONCTIONS PRINCIPALES - # **************************************************************************** - # Constructeur, fonction "auto" déclenchée à l'instanciation - def __init__(self): - if self.DEBUG: - self.conn = mysql.connector.connect( - host=self.HOST, - user=self.USER, - password=self.PASSWORD, - database=self.DATABASE, - raise_on_warnings=self.DEBUG - ) - else: - self.conn = mysql.connector.connect( - host=self.HOST, - user=self.USER, - password=self.PASSWORD, - database=self.DATABASE - ) - self.cur = self.conn.cursor() - - # Création de la DB si elle n'existe pas - def create_db(self): - reqInitDb = "CREATE DATABASE IF NOT EXISTS " + self.DATABASE - self.cur.execute(reqInitDb) - - # Sélection de la DB - def select_db(self): - reqSelectDb = "USE " + self.DATABASE - self.cur.execute(reqSelectDb) - - # Création des tables si elles n'existent pas - def create_table(self): - # userAccount - reqInitUserAccount = self.CREATETABLEUSERACCOUNT - self.cur.execute(reqInitUserAccount) - # userInfo - reqInitUserInfo = self.CREATETABLEUSERINFO - self.cur.execute(reqInitUserAccount) - # jobCategory - reqInitJobCategory = self.CREATETABLEJOBCATEGORY - self.cur.execute(reqInitJobCategory) - # userJob - reqInitUserJob = self.CREATETABLEUSERJOB - self.cur.execute(reqInitUserJob) - # mission - reqInitMission = self.CREATETABLEMISSION - self.cur.execute(reqInitMission) - - # Déclenche les méthodes pour créer la BDD - def init(self): - self.create_db() - self.select_db() - self.create_table() - - # Chiffre la data reçue - def crypt_pass(self, password): - return sha512_crypt.hash(password, rounds=10000) - - # Prépare la requète pour mitiger (se protéger) les injections SQL et - # initialise si nécessaire la BDD à chaque requète - def exec_cmd(self, req, arg=None): - self.init() - if arg: - self.cur.execute(req, arg) - else: - self.cur.execute(req) - - # Vérifie si l'email existe dans la table userAccount de la BDD - def check_exist_email(self, email): - reqCheckEmailExist = "SELECT EXISTS(SELECT * FROM " + \ - self.TABLEUSERACCOUNT + " WHERE email = %s)" - self.exec_cmd(reqCheckEmailExist, [email]) - # Retourne 1 si existe, sinon 0 - return self.cur.fetchall()[0][0] diff --git a/app_alphajob/database/dbmission.py b/app_alphajob/database/dbmission.py deleted file mode 100644 index 0a33a12..0000000 --- a/app_alphajob/database/dbmission.py +++ /dev/null @@ -1,160 +0,0 @@ - -# ############################################################################ -# # # -# # Description: Ensemble de méthodes pour étendre dbmain afin # -# # d'effectuer des recherches dans la bdd # -# # # -# ############################################################################ - -# Infos pour les "join": -# https:#www.freecodecamp.org/news/sql-joins-tutorial/ - -# Import de dbmain -from . import dbmain -from datetime import datetime - - -# Extension de cette classe avec dbmain -class DbMission(dbmain.DbMain): - - # **************************************************************************** - # ENREGISTREMENT ET VALIDATION DES MISSIONS - # **************************************************************************** - # Enregistrement d'une mission - def register_mission(self, subject, clientId, proId, jobId): - # Préparation de la requète pour enregistrement de la mission - reqAddMission = """ - INSERT INTO """ + self.TABLEMISSION + """ - (date, subject, clientId, proId, jobCategoryId) - VALUES - (?, ?, ?, ?, ?)""" - # Exécution de la requète - self.exec_cmd(reqAddMission, - [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - subject, - clientId, - proId, - jobId - ] - ) - return 1 - - # Enregistrement d'une mission - def accept_mission_by_missionid(self, missionId): - # Préparation de la requète pour enregistrement de la mission - reqAddMission = """ - UPDATE - """ + self.TABLEMISSION + """ - SET - acceptedByPro = ? - WHERE - missionId = ?""" - # Exécution de la requète - self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId]) - return 1 - - def validate_mission_pro_by_missionid(self, missionId): - # Préparation de la requète pour enregistrement de la mission - reqAddMission = """ - UPDATE - """ + self.TABLEMISSION + """ - SET - validatedByPro = ? - WHERE - missionId = ?""" - # Exécution de la requète - self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId]) - return 1 - - def validate_mission_client_by_missionid(self, missionId): - # Préparation de la requète pour enregistrement de la mission - reqAddMission = """ - UPDATE - """ + self.TABLEMISSION + """ - SET - validatedByClient = ? - WHERE - missionId = ?""" - # Exécution de la requète - self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId]) - return 1 - - def review_mission(self, missionId, review, note): - # Préparation de la requète pour enregistrement de la mission - reqAddMission = """ - UPDATE - """ + self.TABLEMISSION + """ - SET - review = ?, note = ? - WHERE - missionId = ?""" - # Exécution de la requète - self.exec_cmd(reqAddMission, [review, note, missionId]) - return 1 - - # **************************************************************************** - # RECUPERATION DES INFORMATIONS RELATIVES AUX MISSIONS - # **************************************************************************** - # Récupérations des missions d'un pro par son id - def get_mission_by_proid(self, proId): - reqGetMissionsProId = """ - SELECT - missionId, date, subject, note, review, - acceptedByPro, validatedByClient, - validatedByPro, jobCategoryId, proId, lastname - FROM - """ + self.TABLEMISSION + """ - LEFT JOIN - """ + self.TABLEUSERINFO + """ - ON - """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId - WHERE - proId = ?""" - self.exec_cmd(reqGetMissionsProId, [proId]) - result = self.cur.fetchall() - return result - - # Récupérations des missions d'un client par son id - def get_mission_by_clientid(self, clientId): - reqGetMissionsClientId = """ - SELECT - missionId, date, subject, note, review, - acceptedByPro, validatedByClient, - validatedByPro, jobCategoryId, proId, lastname - FROM - """ + self.TABLEMISSION + """ - LEFT JOIN - """ + self.TABLEUSERINFO + """ - ON - """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId - WHERE - clientId = ?""" - self.exec_cmd(reqGetMissionsClientId, [clientId]) - result = self.cur.fetchall() - return result - - # Récupérations des missions d'un client par son id - def get_all_missions(self): - reqGetAllMission = """ - SELECT - * - FROM - """ + self.TABLEMISSION - self.exec_cmd(reqGetAllMission) - result = self.cur.fetchall() - return result - - # Compte le nombre de mission d'un consultant par son nom - def count_pro_missions_by_proid(self, proId): - reqCountMission = """ - SELECT COUNT(*) FROM - """ + self.TABLEMISSION + """ - INNER JOIN - """ + self.TABLEUSERINFO + """ - ON - """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId - WHERE - proId = ?""" - self.exec_cmd(reqCountMission, [proId]) - result = self.cur.fetchall() - return result diff --git a/app_alphajob/database/dbsearch.py b/app_alphajob/database/dbsearch.py deleted file mode 100644 index 15d4a24..0000000 --- a/app_alphajob/database/dbsearch.py +++ /dev/null @@ -1,140 +0,0 @@ -############################################################################ -# # -# Description: Ensemble de méthodes pour étendre dbmain afin # -# d'effectuer des recherches dans la bdd # -# # -############################################################################ - -# Infos pour les """join""": -# https:#www.freecodecamp.org/news/sql-joins-tutorial/ - -# Import de dbmain -from . import dbmain - - -# Extension de cette classe avec dbmain -class DbSearch(dbmain.DbMain): - # **************************************************************************** - # RECUPERATION DES INFORMATIONS RELATIVES AUX UTILISATEURS - # **************************************************************************** - # Récupération des infos d'un compte par son id - def get_user_account_by_userid(self, userId): - reqSearchUser = """ - SELECT - userId, email, inscriptionDate, userStatus - FROM - """ + self.TABLEUSERACCOUNT + """ - WHERE - userId = %s""" - self.exec_cmd(reqSearchUser, [userId]) - return self.cur.fetchall() - - # Récupération des infos d'un utilisateur par son id - def get_user_info_by_userid(self, userId): - reqGetUserInfo = """ - SELECT - userId, lastname, firstname, degree, - capability, description, phoneNumber, - adress, zipCode, city - FROM - """ + self.TABLEUSERINFO + """ - WHERE - userId = %s""" - self.exec_cmd(reqGetUserInfo, [userId]) - return self.cur.fetchall() - - # **************************************************************************** - # RECUPERATION DES INFORMATIONS RELATIVES AUX PROS - # **************************************************************************** - def get_all_pro_by_jobid(self, jobId): - reqSearchConsultant = """ - SELECT - """ + self.TABLEUSERINFO + """.userId, - lastname, firstname, capability - FROM - """ + self.TABLEUSERINFO + """ - INNER JOIN - """ + self.TABLEUSERJOB + """ - ON - """ + self.TABLEUSERINFO + """.userId = """ + self.TABLEUSERJOB + """.userId - WHERE - jobCategoryId = %s""" - self.exec_cmd(reqSearchConsultant, [jobId]) - return self.cur.fetchall() - - # Récupération des infos d'un pro par son nom - def get_pro_info_by_lastname(self, lastname): - reqSearchConsultant = """ - SELECT - """ + self.TABLEUSERINFO + """.userId, - lastname, firstname, capability - FROM - """ + self.TABLEUSERINFO + """ - INNER JOIN - """ + self.TABLEUSERACCOUNT + """ - ON - """ + self.TABLEUSERINFO + """.userId = """ + self.TABLEUSERACCOUNT + """.userId - WHERE - userStatus = '1' - AND - lastname LIKE CONCAT('%', %s, '%')""" - self.exec_cmd(reqSearchConsultant, [lastname]) - return self.cur.fetchall() - - # Récupération des emploies associés à un pro - def get_pro_job_by_proid(self, proId): - reqGetAll = """ - SELECT - """ + self.TABLEUSERJOB + """.jobCategoryId, - jobCategoryNameEn, jobCategoryNameFr - FROM - """ + self.TABLEUSERJOB + """ - INNER JOIN - """ + self.TABLEJOBCATEGORY + """ - ON - """ + self.TABLEUSERJOB + """.jobCategoryId = """ + self.TABLEJOBCATEGORY + """.jobCategoryId - WHERE - userId = %s""" - self.exec_cmd(reqGetAll, [proId]) - return self.cur.fetchall() - - # Récupération des notes d'un consultant par son nom - def get_pro_note_by_proid(self, proId): - reqCountMission = """ - SELECT - note - FROM - """ + self.TABLEMISSION + """ - INNER JOIN - """ + self.TABLEUSERINFO + """ - ON - """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId - WHERE - proId = %s""" - self.exec_cmd(reqCountMission, [proId]) - return self.cur.fetchall() - - # **************************************************************************** - # RECUPERATION DES INFORMATIONS RELATIVES AUX EMPLOIS - # **************************************************************************** - # Récupérer toutes les infos de la table jobCategory - def get_job_all(self): - reqGetAllJobs = """ - SELECT - * - FROM - """ + self.TABLEJOBCATEGORY - self.exec_cmd(reqGetAllJobs) - return self.cur.fetchall() - - # Récupérer toutes les infos de la table jobCategory - def get_job_by_jobid(self, jobId): - reqGetJobinfo = """ - SELECT - * - FROM - """ + self.TABLEJOBCATEGORY + """ - WHERE - jobCategoryId = %s""" - self.exec_cmd(reqGetJobinfo, [jobId]) - return self.cur.fetchall() diff --git a/app_alphajob/database/dbuser.py b/app_alphajob/database/dbuser.py deleted file mode 100644 index e0a62fb..0000000 --- a/app_alphajob/database/dbuser.py +++ /dev/null @@ -1,171 +0,0 @@ - - -############################################################################ -# # -# Description: Ensemble de méthodes pour étendre dbmain # -# afin de gérer les utilisateurs # -# # -############################################################################ - -from datetime import datetime -from passlib.hash import sha512_crypt -# Import de dbmain -from . import dbmain - -# Extension de cette classe avec dbmain -class DbUser(dbmain.DbMain): - - # **************************************************************************** - # GESTION DES UTILISATEURS - # **************************************************************************** - # Enregistrement d'un nouvel utilisateur - def register_user(self, email, password, userStatus): - # On vérifie si l'email existe deja dans la bdd - exist = self.check_exist_email(email) - # Si non - if not exist: - # Chiffrement du pass - hash = self.crypt_pass(password) - # Préparation de la requète - reqAddUser = """"" - INSERT INTO - """ + self.TABLEUSERACCOUNT + """ - (email, password, inscriptionDate, userStatus) - VALUES - (%s, %s, %s, %s)""" - # Execution de la requète - self.exec_cmd(reqAddUser, - [email, - hash, - datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - userStatus - ] - ) - # Retourne 1 pour réussite - return 1 - else: - # Retourne 0 pour échec - return 0 - - # Vérification de la combinaison email - pass pour authentification - def check_user_credential(self, email, password): - # Préparation de la requète pour récupérer les infos ou l'email est présent - reqCheckCredential = """ - SELECT - userId, password - FROM - """ + self.TABLEUSERACCOUNT + """ - WHERE - email = %s """ - # Execution de la requète - self.exec_cmd(reqCheckCredential, [email]) - result = self.cur.fetchone() - # Vérifiaction de correspondance email & pass - if result and sha512_crypt.verify(password, result[1]): - return result[0] - - # Mise à jour des infos d'un utilisateur - def update_user_infos(self, userInfos, userId, isPro, userJobs=None): - # Préparation de la requète pour mise à jour des infos - # J'ai préféré faire deux requètes distinctes et ne pas utiliser des valeurs - # passées par POST (key => value) pour gérer les noms des colonnes - # car je préfère les passer en "dur" dans mes requêtes (risque d'injection SQL%s). - reqAddInfoClient = """ - REPLACE INTO - """ + self.TABLEUSERINFO + """ - (lastname, firstname, phoneNumber, - adress, zipCode, city, userId) - VALUES - (%s, %s, %s, %s, %s, %s, %s)""" - reqAddInfoPro = """ - REPLACE INTO - """ + self.TABLEUSERINFO + """ - (lastname, firstname, phoneNumber, - adress, zipCode, city, degree, - capability, description, userId) - VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" - reqAddInfoProJobs = """ - INSERT INTO - """ + self.TABLEUSERJOB + """ - (jobCategoryId, userId) - VALUES - (%s, %s)""" - reqRemoveInfoProJobs = """ - DELETE FROM - """ + self.tableUserJob + """ - WHERE - jobCategoryId = %s - AND - userId = %s""" - # if not isPro: - # # Exécution de la requète - # # https:#www.php.net/manual/fr/function.array-values.php - # # Pour passer de "dict" a "list" -> array_values() - # args = [i for i in userInfos] - # args.push(userId) - # self.exec_cmd(reqAddInfoClient, args) - # else: - # # https:#stackoverflow.com/questions/15986235/how-to-use-json-stringify-and-json-decode-properly - # # Récupération des emplois dans le JSON et supression de ces derniers de la liste - # selectedJobs = json_decode(html_entity_decode(userInfos["jobs"])) - # unset(userInfos["jobs"]) - # # array_value -> Qu'est ce qui est présent dans 1 mais pas dans 2 %s - # # Comparaison des jobs anciennement présent avec ceux sélectionnés, donc ajoutés. - # jobsAdded = array_values(array_diff(selectedJobs, userJobs)) - # # Comparaison des jobs deja présent avec ceux sélectionnés, donc ajoutés. - # jobsRemoved = array_values(array_diff(userJobs, selectedJobs)) - # # on continue classiquement avec les autres éléments - # args = array_values(userInfos) - # array_push(args, userId) - # self.exec_cmd(reqAddInfoPro, args) - # for i in jobsAdded: - # self.exec_cmd(reqAddInfoProJobs, array(jobsAdded[i], userId)) - # for i in jobsRemoved: - # self.exec_cmd(reqRemoveInfoProJobs, array(jobsRemoved[i], userId)) - - # **************************************************************************** - # GESTION DU TOKEN AUTOLOGIN - # **************************************************************************** - # Vérification de la combinaison email - jeton d'auto-login pour authentification - def check_token_autologin(self, email, token): - # Préparation de la requète pour récupérer les infos ou l'email est présent - reqCheckToken = """ - SELECT - userId, tokenAutoLogin - FROM - """ + self.TABLEUSERACCOUNT + """ - WHERE - email = %s""" - # Exécution de la requète - self.exec_cmd(reqCheckToken, [email]) - result = self.cur.fetchone() - # Vérifiaction de correspondance email & jeton d'auto-connection - if result and result[1] == token: - return result[0] - - # Mise à jour du jeton d'auto-login - def update_token_autologin(self, email, token): - # Préparation de la requète pour mise à jour du jeton d'auto-connection - reqUpdateToken = """ - UPDATE - """ + self.TABLEUSERACCOUNT + """ - SET - tokenAutoLogin = %s - WHERE - email = %s""" - # Execution de la requète - self.exec_cmd(reqUpdateToken, [token, email]) - - # Supression du jeton d'auto-login - def del_token_autologin(self, email): - # Préparation de la requète pour supression du jeton d'auto-connection - reqDeleteToken = """ - UPDATE - """ + self.TABLEUSERACCOUNT + """ - SET - tokenAutoLogin = NULL - WHERE - email = %s""" - # Execution de la requète - self.exec_cmd(reqDeleteToken, [email]) diff --git a/app_alphajob/main.py b/app_alphajob/main.py deleted file mode 100644 index 11f4cc1..0000000 --- a/app_alphajob/main.py +++ /dev/null @@ -1,119 +0,0 @@ - - -import sys -from os.path import join -from PyQt5 import QtWidgets, QtGui -from database import dbuser - -class mainWindow(QtWidgets.QMainWindow): - - VERSION = 0.1 - - def __init__(self): - super(mainWindow, self).__init__() - logo = join("./ressources", "icon.ico") - self.setWindowIcon(QtGui.QIcon(logo)) - menu = self.menuBar() - menu_options = menu.addMenu("Options") - btn_apropos = QtWidgets.QAction("A propos", self) - btn_apropos.triggered.connect(self.a_propos) - menu_options.addAction(btn_apropos) - self.setWindowTitle("Alphajob") - self.home() - - def home(self): - self.label1 = QtWidgets.QLabel("Home page") - btn1 = QtWidgets.QPushButton("Aller à la page de connexion") - btn1.clicked.connect(self.page_login) - - self.layoutMain = QtWidgets.QVBoxLayout() - - self.layoutMain.addWidget(self.label1) - self.layoutMain.addWidget(btn1) - - if hasattr(self, "mainWidget"): - self.mainWidget.deleteLater() - self.mainWidget = QtWidgets.QWidget() - self.mainWidget.setLayout(self.layoutMain) - self.setCentralWidget(self.mainWidget) - self.show() - - def page_login(self): - btnAccueil = QtWidgets.QPushButton("Accueil") - btnAccueil.clicked.connect(self.home) - self.emailConnexion = QtWidgets.QLineEdit("Email") - self.passwordConnexion = QtWidgets.QLineEdit("Password") - btnConnexion = QtWidgets.QPushButton("Connexion") - btnConnexion.clicked.connect(self.login) - - self.layoutMain = QtWidgets.QVBoxLayout() - self.layoutNavigation = QtWidgets.QHBoxLayout() - self.layoutPassword = QtWidgets.QHBoxLayout() - self.layoutPasswordWidgets = QtWidgets.QVBoxLayout() - - self.layoutMain.addLayout(self.layoutNavigation) - self.layoutNavigation.addWidget(btnAccueil) - self.layoutNavigation.addStretch() - - self.layoutMain.addLayout(self.layoutPassword) - self.layoutPassword.addStretch() - self.layoutPassword.addLayout(self.layoutPasswordWidgets) - self.layoutPassword.addStretch() - - self.layoutPasswordWidgets.addWidget(self.emailConnexion) - self.layoutPasswordWidgets.addWidget(self.passwordConnexion) - self.layoutPasswordWidgets.addWidget(btnConnexion) - - self.mainWidget.deleteLater() - self.mainWidget = QtWidgets.QWidget() - self.mainWidget.setLayout(self.layoutMain) - self.setCentralWidget(self.mainWidget) - - def login(self): - user = dbuser.DbUser() - if user.check_exist_email(self.emailConnexion.text()): - res = user.check_user_credential( - self.emailConnexion.text(), - self.passwordConnexion.text() - ) - if res: - QtWidgets.QMessageBox.information( - self, - "Connexion", - "Vous êtes connecté" - ) - else: - QtWidgets.QMessageBox.warning( - self, - "Connexion", - "Mauvaise combinaison mail & mot de passe" - ) - else: - QtWidgets.QMessageBox.warning( - self, - "Connexion", - "Mauvais email" - ) - - - def a_propos(self): - QtWidgets.QMessageBox.information( - self, - "A propos", - "Logiciel pour mon dossier professionnel.\ -
Version: %s\ -
Auteur: Debulois Quentin\ -
Code source: \ - git.debulois.fr/" % self.VERSION - ) - - -if __name__ == "__main__": - def main(): - """Démarrage de l'app - """ - app = QtWidgets.QApplication(sys.argv) - GUI = mainWindow() - sys.exit(app.exec_()) - - main() \ No newline at end of file diff --git a/app_alphajob/ressources/icon.ico b/app_alphajob/ressources/icon.ico deleted file mode 100644 index 7c550a3..0000000 Binary files a/app_alphajob/ressources/icon.ico and /dev/null differ diff --git a/src/core/__init__.py b/src/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/user.py b/src/core/user.py new file mode 100644 index 0000000..1d9db8d --- /dev/null +++ b/src/core/user.py @@ -0,0 +1,25 @@ +from src.database import dbuser +from PyQt5.QtWidgets import QMessageBox + +def login(mainWindow, email, password): + user = dbuser.DbUser() + if user.check_exist_email(email): + res = user.check_user_credential(email, password) + if res: + QMessageBox.information( + mainWindow, + "Connexion", + "Vous êtes connecté" + ) + else: + QMessageBox.warning( + mainWindow, + "Connexion", + "Mauvaise combinaison mail & mot de passe" + ) + else: + QMessageBox.warning( + mainWindow, + "Connexion", + "Mauvais email" + ) diff --git a/src/database/__init__.py b/src/database/__init__.py new file mode 100644 index 0000000..03b0cc7 --- /dev/null +++ b/src/database/__init__.py @@ -0,0 +1 @@ +# https://realpython.com/python-import/#basic-python-import \ No newline at end of file diff --git a/src/database/dbadmin.py b/src/database/dbadmin.py new file mode 100644 index 0000000..dd6b4d0 --- /dev/null +++ b/src/database/dbadmin.py @@ -0,0 +1,177 @@ + +############################################################################ +# # +# Description: Ensemble de méthodes pour étendre dbmain # +# afin de gérer l'administration du site # +# # +############################################################################ + +# Import de dbmain +from . import dbmain + +# Extension de cette classe avec dbmain +class DbAdmin(dbmain.DbMain): + + # **************************************************************************** + # GESTION DES UTILISATEURS DANS L'ADMIN + # **************************************************************************** + # Récupérer toutes les infos de la table userAccount + def get_all_users_account(self): + reqGetAll = """ + SELECT + * + FROM + """ + self.TABLEUSERACCOUNT + # https:#www.php.net/manual/fr/pdostatement.fetch.php + # "PDO::FETCH_ASSOC: retourne un tableau indexé + # par le nom de la colonne comme retourné dans le jeu de résultats" + self.exec_cmd(reqGetAll) + result = self.cur.fetchall() + return result + + # https:#stackoverflow.com/questions/1361340/how-can-i-do-insert-if-not-exists-in-mysql + # Suppresion d'un utilisateur + def del_user_by_userid(self, userId): + # Préparation de la requète pour voir si l'utilisateur existe + # https:#stackoverflow.com/questions/1676551/best-way-to-test-if-a-row-exists-in-a-mysql-table + reqCheckExistId = """ + SELECT EXISTS( + SELECT 1 FROM + """ + self.TABLEUSERACCOUNT + """ + WHERE + userId = ? + LIMIT 1 + )""" + # Exécution de la requète, fetchall pour avoir le résultat + # https:#www.php.net/manual/fr/pdostatement.fetch.php + # struct par défaut req et index (fetch_both) = arr([0] => arr("req" => BOOL, [0] => BOOL]) + # PDO::FETCH_NUM : retourne un tableau indexé par le numéro de la colonne comme elle + # est retourné dans votre jeu de résultat, commençant à 0 + self.exec_cmd(reqCheckExistId, [userId]) + reqResult = self.cur.fetchall() + # Si il existe + if (reqResult[0][0]): + # Préparation de la requète pour suppression + reqDelUser = """DELETE FROM """ + self.TABLEUSERACCOUNT + """ WHERE userId = ?""" + # Exécution de la requète + self.exec_cmd(reqDelUser, [userId]) + # Retourne 1 pour réussite + return 1 + else: + # Retourne 0 pour échec + return 0 + + + # **************************************************************************** + # GESTION DES EMPLOIS DANS L'ADMIN + # **************************************************************************** + # Ajout d'une categorie + def register_job_category(self, jobNameEn, jobNameFr): + # Préparation et execution de la requète pour voir si la categorie existe en anglais + reqCheckjobCategoryNameEn = """ + SELECT EXISTS( + SELECT 1 FROM + """ + self.TABLEJOBCATEGORY + """ + WHERE + jobCategoryNameEn = ? + LIMIT 1 + )""" + self.exec_cmd(reqCheckjobCategoryNameEn, [jobNameEn]) + reqResultEn = self.cur.fetchall() + # Si il n'existe pas en anglais + if not reqResultEn[0][0]: + # Préparation et execution de la requète pour voir si la categorie existe en Français + reqCheckjobCategoryNameFr = """ + SELECT EXISTS( + SELECT 1 FROM + """ + self.TABLEJOBCATEGORY + """ + WHERE + jobCategoryNameFr = ? + LIMIT 1 + )""" + self.exec_cmd(reqCheckjobCategoryNameFr, [jobNameFr]) + reqResultFr = self.cur.fetchall() + # Si il n'existe pas en Français non plus + if not reqResultFr[0][0]: + # Préparation de la requète pour l'ajout + reqjobCategoryNameAdd = """ + INSERT INTO + """ + self.TABLEJOBCATEGORY + """ + (jobCategoryNameEn, jobCategoryNameFr) + VALUES + (? ,?)""" + # Exécution de la requète + self.exec_cmd(reqjobCategoryNameAdd, [jobNameEn, jobNameFr]) + # Retourne 1 pour réussite + return 1 + else: + # Retourne 0 pour échec + return 0 + else: + # Retourne 0 pour échec + return 0 + + # Suppresion d'un utilisateur + def del_job_category_by_jobid(self, jobId): + # Préparation de la requète pour voir si l'utilisateur existe + reqCheckExistId = """ + SELECT EXISTS( + SELECT 1 FROM + """ + self.TABLEJOBCATEGORY + """ + WHERE + jobCategoryId = ? + LIMIT 1 + )""" + # Exécution de la requète, fetchall pour avoir le résultat + # struct par défaut req et index (fetch_both) = arr([0] => arr("req" => BOOL, [0] => BOOL]) + # fetch_num pour casser l'index "req" en chiffre, dict -> list + self.exec_cmd(reqCheckExistId, [jobId]) + reqResult = self.cur.fetchall() + # Si il existe + if (reqResult[0][0]): + # Préparation de la requète pour suppression + reqDelJobCategory = """ + DELETE FROM + """ + self.TABLEJOBCATEGORY + """ + WHERE + jobCategoryId = ?""" + # Exécution de la requète + self.exec_cmd(reqDelJobCategory, [jobId]) + # Retourne 1 pour réussite + return 1 + else: + # Retourne 0 pour échec + return 0 + + # **************************************************************************** + # GESTION DES MISSIONS DANS L'ADMIN + # **************************************************************************** + # Suppresion d'une mission + def del_mission_by_missionid(self, missionId): + # Préparation de la requète pour voir si l'utilisateur existe + reqCheckExistId = """ + SELECT EXISTS( + SELECT 1 FROM + """ + self.TABLEMISSION + """ + WHERE + missionId = ? + LIMIT 1 + )""" + # Exécution de la requète + self.exec_cmd(reqCheckExistId, [missionId]) + reqResult = self.cur.fetchall() + # Si il existe + if (reqResult[0][0]): + # Préparation de la requète pour suppression + reqDelMission = """ + DELETE FROM + """ + self.TABLEMISSION + """ + WHERE + missionId = ?""" + # Exécution de la requète + self.exec_cmd(reqDelMission, [missionId]) + # Retourne 1 pour réussite + return 1 + else: + # Retourne 0 pour échec + return 0 diff --git a/src/database/dbmain.py b/src/database/dbmain.py new file mode 100644 index 0000000..602cec6 --- /dev/null +++ b/src/database/dbmain.py @@ -0,0 +1,217 @@ + +############################################################################ +# # +# Description: Partie commune des deux ensembles de méthodes # +# pour la gestion de la BDD # +# # +############################################################################ + +import mysql.connector +from passlib.hash import sha512_crypt + +# const si CAPS +# https://www.w3schools.com/python/python_mysql_getstarted.asp +# https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html +# https://stackoverflow.com/questions/11565487/python-equivalent-of-php-mysql-fetch-array + + +class DbMain(): + # **************************************************************************** + # INFOS GLOBAL ET DE CONNEXION + # **************************************************************************** + # Pour gérer si "en production" + DEBUG = False + # Configuration du serveur MYSQL / MARIADB + HOST = "127.0.0.1" + USER = "root" + PASSWORD = "" + DATABASE = "alphajob" + + # **************************************************************************** + # DECLARATION DES TABLES + # **************************************************************************** + # UserAccount, infos du compte nécessaire à la connection + CREATETABLEUSERACCOUNT = """CREATE TABLE IF NOT EXISTS `alphajob`.`userAccount` ( + `userId` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `email` VARCHAR(128) NOT NULL, + `password` VARCHAR(128) NOT NULL, + `tokenAutoLogin` VARCHAR(128) NULL DEFAULT NULL, + `inscriptionDate` TIMESTAMP NOT NULL, + `userStatus` TINYINT(1) UNSIGNED NOT NULL, + PRIMARY KEY (`userId`) + ) + ENGINE = InnoDB + DEFAULT CHARACTER SET = utf8;""" + + # Infos complémentaires des utilisateur, liée à userAccount par userId + CREATETABLEUSERINFO = """CREATE TABLE IF NOT EXISTS `alphajob`.`userInfo` ( + `lastname` VARCHAR(128) NOT NULL, + `firstname` VARCHAR(128) NOT NULL, + `phoneNumber` VARCHAR(10) NOT NULL, + `adress` VARCHAR(128) NOT NULL, + `zipCode` VARCHAR(6) NOT NULL, + `city` VARCHAR(128) NOT NULL, + `degree` VARCHAR(128) NULL DEFAULT NULL, + `capability` VARCHAR(256) NULL DEFAULT NULL, + `description` VARCHAR(256) NULL DEFAULT NULL, + `userId` INT UNSIGNED NOT NULL, + PRIMARY KEY (`userId`), + INDEX `fk_userinfo_userId_idx` (`userId` ASC) VISIBLE, + CONSTRAINT `fk_userinfo_userId` + FOREIGN KEY (`userId`) + REFERENCES `alphajob`.`userAccount` (`userId`) + ON DELETE CASCADE + ON UPDATE CASCADE + ) + ENGINE = InnoDB + DEFAULT CHARACTER SET = utf8;""" + + # Liste des categories d'emploie possible + CREATETABLEJOBCATEGORY = """CREATE TABLE IF NOT EXISTS `alphajob`.`jobCategory` ( + `jobCategoryId` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `jobCategoryNameEn` VARCHAR(128) NOT NULL, + `jobCategoryNameFr` VARCHAR(128) NOT NULL, + PRIMARY KEY (`jobCategoryId`) + ) + ENGINE = InnoDB + DEFAULT CHARACTER SET = utf8;""" + + # Assosications des emploies à un utilisateur + CREATETABLEUSERJOB = """CREATE TABLE IF NOT EXISTS `alphajob`.`userJob` ( + `userId` INT UNSIGNED NOT NULL, + `jobCategoryId` INT UNSIGNED NOT NULL, + INDEX `fk_userInfo_userId_idx` (`userId` ASC) VISIBLE, + INDEX `fk_jobCategory_jobCategoryId_idx` (`jobCategoryId` ASC) VISIBLE, + CONSTRAINT `fk_userJob_userId` + FOREIGN KEY (`userId`) + REFERENCES `alphajob`.`userAccount` (`userId`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_userJob_jobCategoryId` + FOREIGN KEY (`jobCategoryId`) + REFERENCES `alphajob`.`jobCategory` (`jobCategoryId`) + ON DELETE CASCADE + ON UPDATE CASCADE + ) + ENGINE = InnoDB + DEFAULT CHARACTER SET = utf8;""" + + # Infos sur les missions effectuées, liée à userAccount par userId et consultantId + CREATETABLEMISSION = """CREATE TABLE IF NOT EXISTS `alphajob`.`mission` ( + `missionId` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `date` TIMESTAMP NOT NULL, + `subject` VARCHAR(128) NULL DEFAULT NULL, + `note` TINYINT(1) UNSIGNED NULL DEFAULT NULL, + `review` VARCHAR(256) NULL DEFAULT NULL, + `acceptedByPro` TIMESTAMP NULL DEFAULT NULL, + `validatedByClient` TIMESTAMP NULL DEFAULT NULL, + `validatedByPro` TIMESTAMP NULL DEFAULT NULL, + `clientId` INT UNSIGNED NOT NULL, + `proId` INT UNSIGNED NOT NULL, + `jobCategoryId` INT UNSIGNED NOT NULL, + PRIMARY KEY (`missionId`), + INDEX `fk_mission_clientId_idx` (`clientId` ASC) VISIBLE, + INDEX `fk_mission_proId_idx` (`proId` ASC) VISIBLE, + INDEX `fk_mission_jobCategoryId_idx` (`jobCategoryId` ASC) VISIBLE, + CONSTRAINT `fk_mission_clientId` + FOREIGN KEY (`clientId`) + REFERENCES `alphajob`.`userAccount` (`userId`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_mission_proId` + FOREIGN KEY (`proId`) + REFERENCES `alphajob`.`userAccount` (`userId`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_mission_jobCategoryId` + FOREIGN KEY (`jobCategoryId`) + REFERENCES `alphajob`.`jobCategory` (`jobCategoryId`) + ON DELETE CASCADE + ON UPDATE CASCADE + ) + ENGINE = InnoDB + DEFAULT CHARACTER SET = utf8""" + + # Noms des tables + TABLEUSERACCOUNT = "userAccount" + TABLEUSERINFO = "userInfo" + TABLEJOBCATEGORY = "jobCategory" + TABLEUSERJOB = "userJob" + TABLEMISSION = "mission" + + # **************************************************************************** + # FONCTIONS PRINCIPALES + # **************************************************************************** + # Constructeur, fonction "auto" déclenchée à l'instanciation + def __init__(self): + if self.DEBUG: + self.conn = mysql.connector.connect( + host=self.HOST, + user=self.USER, + password=self.PASSWORD, + database=self.DATABASE, + raise_on_warnings=self.DEBUG + ) + else: + self.conn = mysql.connector.connect( + host=self.HOST, + user=self.USER, + password=self.PASSWORD, + database=self.DATABASE + ) + self.cur = self.conn.cursor() + + # Création de la DB si elle n'existe pas + def create_db(self): + reqInitDb = "CREATE DATABASE IF NOT EXISTS " + self.DATABASE + self.cur.execute(reqInitDb) + + # Sélection de la DB + def select_db(self): + reqSelectDb = "USE " + self.DATABASE + self.cur.execute(reqSelectDb) + + # Création des tables si elles n'existent pas + def create_table(self): + # userAccount + reqInitUserAccount = self.CREATETABLEUSERACCOUNT + self.cur.execute(reqInitUserAccount) + # userInfo + reqInitUserInfo = self.CREATETABLEUSERINFO + self.cur.execute(reqInitUserAccount) + # jobCategory + reqInitJobCategory = self.CREATETABLEJOBCATEGORY + self.cur.execute(reqInitJobCategory) + # userJob + reqInitUserJob = self.CREATETABLEUSERJOB + self.cur.execute(reqInitUserJob) + # mission + reqInitMission = self.CREATETABLEMISSION + self.cur.execute(reqInitMission) + + # Déclenche les méthodes pour créer la BDD + def init(self): + self.create_db() + self.select_db() + self.create_table() + + # Chiffre la data reçue + def crypt_pass(self, password): + return sha512_crypt.hash(password, rounds=10000) + + # Prépare la requète pour mitiger (se protéger) les injections SQL et + # initialise si nécessaire la BDD à chaque requète + def exec_cmd(self, req, arg=None): + self.init() + if arg: + self.cur.execute(req, arg) + else: + self.cur.execute(req) + + # Vérifie si l'email existe dans la table userAccount de la BDD + def check_exist_email(self, email): + reqCheckEmailExist = "SELECT EXISTS(SELECT * FROM " + \ + self.TABLEUSERACCOUNT + " WHERE email = %s)" + self.exec_cmd(reqCheckEmailExist, [email]) + # Retourne 1 si existe, sinon 0 + return self.cur.fetchall()[0][0] diff --git a/src/database/dbmission.py b/src/database/dbmission.py new file mode 100644 index 0000000..0a33a12 --- /dev/null +++ b/src/database/dbmission.py @@ -0,0 +1,160 @@ + +# ############################################################################ +# # # +# # Description: Ensemble de méthodes pour étendre dbmain afin # +# # d'effectuer des recherches dans la bdd # +# # # +# ############################################################################ + +# Infos pour les "join": +# https:#www.freecodecamp.org/news/sql-joins-tutorial/ + +# Import de dbmain +from . import dbmain +from datetime import datetime + + +# Extension de cette classe avec dbmain +class DbMission(dbmain.DbMain): + + # **************************************************************************** + # ENREGISTREMENT ET VALIDATION DES MISSIONS + # **************************************************************************** + # Enregistrement d'une mission + def register_mission(self, subject, clientId, proId, jobId): + # Préparation de la requète pour enregistrement de la mission + reqAddMission = """ + INSERT INTO """ + self.TABLEMISSION + """ + (date, subject, clientId, proId, jobCategoryId) + VALUES + (?, ?, ?, ?, ?)""" + # Exécution de la requète + self.exec_cmd(reqAddMission, + [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + subject, + clientId, + proId, + jobId + ] + ) + return 1 + + # Enregistrement d'une mission + def accept_mission_by_missionid(self, missionId): + # Préparation de la requète pour enregistrement de la mission + reqAddMission = """ + UPDATE + """ + self.TABLEMISSION + """ + SET + acceptedByPro = ? + WHERE + missionId = ?""" + # Exécution de la requète + self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId]) + return 1 + + def validate_mission_pro_by_missionid(self, missionId): + # Préparation de la requète pour enregistrement de la mission + reqAddMission = """ + UPDATE + """ + self.TABLEMISSION + """ + SET + validatedByPro = ? + WHERE + missionId = ?""" + # Exécution de la requète + self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId]) + return 1 + + def validate_mission_client_by_missionid(self, missionId): + # Préparation de la requète pour enregistrement de la mission + reqAddMission = """ + UPDATE + """ + self.TABLEMISSION + """ + SET + validatedByClient = ? + WHERE + missionId = ?""" + # Exécution de la requète + self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId]) + return 1 + + def review_mission(self, missionId, review, note): + # Préparation de la requète pour enregistrement de la mission + reqAddMission = """ + UPDATE + """ + self.TABLEMISSION + """ + SET + review = ?, note = ? + WHERE + missionId = ?""" + # Exécution de la requète + self.exec_cmd(reqAddMission, [review, note, missionId]) + return 1 + + # **************************************************************************** + # RECUPERATION DES INFORMATIONS RELATIVES AUX MISSIONS + # **************************************************************************** + # Récupérations des missions d'un pro par son id + def get_mission_by_proid(self, proId): + reqGetMissionsProId = """ + SELECT + missionId, date, subject, note, review, + acceptedByPro, validatedByClient, + validatedByPro, jobCategoryId, proId, lastname + FROM + """ + self.TABLEMISSION + """ + LEFT JOIN + """ + self.TABLEUSERINFO + """ + ON + """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId + WHERE + proId = ?""" + self.exec_cmd(reqGetMissionsProId, [proId]) + result = self.cur.fetchall() + return result + + # Récupérations des missions d'un client par son id + def get_mission_by_clientid(self, clientId): + reqGetMissionsClientId = """ + SELECT + missionId, date, subject, note, review, + acceptedByPro, validatedByClient, + validatedByPro, jobCategoryId, proId, lastname + FROM + """ + self.TABLEMISSION + """ + LEFT JOIN + """ + self.TABLEUSERINFO + """ + ON + """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId + WHERE + clientId = ?""" + self.exec_cmd(reqGetMissionsClientId, [clientId]) + result = self.cur.fetchall() + return result + + # Récupérations des missions d'un client par son id + def get_all_missions(self): + reqGetAllMission = """ + SELECT + * + FROM + """ + self.TABLEMISSION + self.exec_cmd(reqGetAllMission) + result = self.cur.fetchall() + return result + + # Compte le nombre de mission d'un consultant par son nom + def count_pro_missions_by_proid(self, proId): + reqCountMission = """ + SELECT COUNT(*) FROM + """ + self.TABLEMISSION + """ + INNER JOIN + """ + self.TABLEUSERINFO + """ + ON + """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId + WHERE + proId = ?""" + self.exec_cmd(reqCountMission, [proId]) + result = self.cur.fetchall() + return result diff --git a/src/database/dbsearch.py b/src/database/dbsearch.py new file mode 100644 index 0000000..15d4a24 --- /dev/null +++ b/src/database/dbsearch.py @@ -0,0 +1,140 @@ +############################################################################ +# # +# Description: Ensemble de méthodes pour étendre dbmain afin # +# d'effectuer des recherches dans la bdd # +# # +############################################################################ + +# Infos pour les """join""": +# https:#www.freecodecamp.org/news/sql-joins-tutorial/ + +# Import de dbmain +from . import dbmain + + +# Extension de cette classe avec dbmain +class DbSearch(dbmain.DbMain): + # **************************************************************************** + # RECUPERATION DES INFORMATIONS RELATIVES AUX UTILISATEURS + # **************************************************************************** + # Récupération des infos d'un compte par son id + def get_user_account_by_userid(self, userId): + reqSearchUser = """ + SELECT + userId, email, inscriptionDate, userStatus + FROM + """ + self.TABLEUSERACCOUNT + """ + WHERE + userId = %s""" + self.exec_cmd(reqSearchUser, [userId]) + return self.cur.fetchall() + + # Récupération des infos d'un utilisateur par son id + def get_user_info_by_userid(self, userId): + reqGetUserInfo = """ + SELECT + userId, lastname, firstname, degree, + capability, description, phoneNumber, + adress, zipCode, city + FROM + """ + self.TABLEUSERINFO + """ + WHERE + userId = %s""" + self.exec_cmd(reqGetUserInfo, [userId]) + return self.cur.fetchall() + + # **************************************************************************** + # RECUPERATION DES INFORMATIONS RELATIVES AUX PROS + # **************************************************************************** + def get_all_pro_by_jobid(self, jobId): + reqSearchConsultant = """ + SELECT + """ + self.TABLEUSERINFO + """.userId, + lastname, firstname, capability + FROM + """ + self.TABLEUSERINFO + """ + INNER JOIN + """ + self.TABLEUSERJOB + """ + ON + """ + self.TABLEUSERINFO + """.userId = """ + self.TABLEUSERJOB + """.userId + WHERE + jobCategoryId = %s""" + self.exec_cmd(reqSearchConsultant, [jobId]) + return self.cur.fetchall() + + # Récupération des infos d'un pro par son nom + def get_pro_info_by_lastname(self, lastname): + reqSearchConsultant = """ + SELECT + """ + self.TABLEUSERINFO + """.userId, + lastname, firstname, capability + FROM + """ + self.TABLEUSERINFO + """ + INNER JOIN + """ + self.TABLEUSERACCOUNT + """ + ON + """ + self.TABLEUSERINFO + """.userId = """ + self.TABLEUSERACCOUNT + """.userId + WHERE + userStatus = '1' + AND + lastname LIKE CONCAT('%', %s, '%')""" + self.exec_cmd(reqSearchConsultant, [lastname]) + return self.cur.fetchall() + + # Récupération des emploies associés à un pro + def get_pro_job_by_proid(self, proId): + reqGetAll = """ + SELECT + """ + self.TABLEUSERJOB + """.jobCategoryId, + jobCategoryNameEn, jobCategoryNameFr + FROM + """ + self.TABLEUSERJOB + """ + INNER JOIN + """ + self.TABLEJOBCATEGORY + """ + ON + """ + self.TABLEUSERJOB + """.jobCategoryId = """ + self.TABLEJOBCATEGORY + """.jobCategoryId + WHERE + userId = %s""" + self.exec_cmd(reqGetAll, [proId]) + return self.cur.fetchall() + + # Récupération des notes d'un consultant par son nom + def get_pro_note_by_proid(self, proId): + reqCountMission = """ + SELECT + note + FROM + """ + self.TABLEMISSION + """ + INNER JOIN + """ + self.TABLEUSERINFO + """ + ON + """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId + WHERE + proId = %s""" + self.exec_cmd(reqCountMission, [proId]) + return self.cur.fetchall() + + # **************************************************************************** + # RECUPERATION DES INFORMATIONS RELATIVES AUX EMPLOIS + # **************************************************************************** + # Récupérer toutes les infos de la table jobCategory + def get_job_all(self): + reqGetAllJobs = """ + SELECT + * + FROM + """ + self.TABLEJOBCATEGORY + self.exec_cmd(reqGetAllJobs) + return self.cur.fetchall() + + # Récupérer toutes les infos de la table jobCategory + def get_job_by_jobid(self, jobId): + reqGetJobinfo = """ + SELECT + * + FROM + """ + self.TABLEJOBCATEGORY + """ + WHERE + jobCategoryId = %s""" + self.exec_cmd(reqGetJobinfo, [jobId]) + return self.cur.fetchall() diff --git a/src/database/dbuser.py b/src/database/dbuser.py new file mode 100644 index 0000000..e0a62fb --- /dev/null +++ b/src/database/dbuser.py @@ -0,0 +1,171 @@ + + +############################################################################ +# # +# Description: Ensemble de méthodes pour étendre dbmain # +# afin de gérer les utilisateurs # +# # +############################################################################ + +from datetime import datetime +from passlib.hash import sha512_crypt +# Import de dbmain +from . import dbmain + +# Extension de cette classe avec dbmain +class DbUser(dbmain.DbMain): + + # **************************************************************************** + # GESTION DES UTILISATEURS + # **************************************************************************** + # Enregistrement d'un nouvel utilisateur + def register_user(self, email, password, userStatus): + # On vérifie si l'email existe deja dans la bdd + exist = self.check_exist_email(email) + # Si non + if not exist: + # Chiffrement du pass + hash = self.crypt_pass(password) + # Préparation de la requète + reqAddUser = """"" + INSERT INTO + """ + self.TABLEUSERACCOUNT + """ + (email, password, inscriptionDate, userStatus) + VALUES + (%s, %s, %s, %s)""" + # Execution de la requète + self.exec_cmd(reqAddUser, + [email, + hash, + datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + userStatus + ] + ) + # Retourne 1 pour réussite + return 1 + else: + # Retourne 0 pour échec + return 0 + + # Vérification de la combinaison email - pass pour authentification + def check_user_credential(self, email, password): + # Préparation de la requète pour récupérer les infos ou l'email est présent + reqCheckCredential = """ + SELECT + userId, password + FROM + """ + self.TABLEUSERACCOUNT + """ + WHERE + email = %s """ + # Execution de la requète + self.exec_cmd(reqCheckCredential, [email]) + result = self.cur.fetchone() + # Vérifiaction de correspondance email & pass + if result and sha512_crypt.verify(password, result[1]): + return result[0] + + # Mise à jour des infos d'un utilisateur + def update_user_infos(self, userInfos, userId, isPro, userJobs=None): + # Préparation de la requète pour mise à jour des infos + # J'ai préféré faire deux requètes distinctes et ne pas utiliser des valeurs + # passées par POST (key => value) pour gérer les noms des colonnes + # car je préfère les passer en "dur" dans mes requêtes (risque d'injection SQL%s). + reqAddInfoClient = """ + REPLACE INTO + """ + self.TABLEUSERINFO + """ + (lastname, firstname, phoneNumber, + adress, zipCode, city, userId) + VALUES + (%s, %s, %s, %s, %s, %s, %s)""" + reqAddInfoPro = """ + REPLACE INTO + """ + self.TABLEUSERINFO + """ + (lastname, firstname, phoneNumber, + adress, zipCode, city, degree, + capability, description, userId) + VALUES + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + reqAddInfoProJobs = """ + INSERT INTO + """ + self.TABLEUSERJOB + """ + (jobCategoryId, userId) + VALUES + (%s, %s)""" + reqRemoveInfoProJobs = """ + DELETE FROM + """ + self.tableUserJob + """ + WHERE + jobCategoryId = %s + AND + userId = %s""" + # if not isPro: + # # Exécution de la requète + # # https:#www.php.net/manual/fr/function.array-values.php + # # Pour passer de "dict" a "list" -> array_values() + # args = [i for i in userInfos] + # args.push(userId) + # self.exec_cmd(reqAddInfoClient, args) + # else: + # # https:#stackoverflow.com/questions/15986235/how-to-use-json-stringify-and-json-decode-properly + # # Récupération des emplois dans le JSON et supression de ces derniers de la liste + # selectedJobs = json_decode(html_entity_decode(userInfos["jobs"])) + # unset(userInfos["jobs"]) + # # array_value -> Qu'est ce qui est présent dans 1 mais pas dans 2 %s + # # Comparaison des jobs anciennement présent avec ceux sélectionnés, donc ajoutés. + # jobsAdded = array_values(array_diff(selectedJobs, userJobs)) + # # Comparaison des jobs deja présent avec ceux sélectionnés, donc ajoutés. + # jobsRemoved = array_values(array_diff(userJobs, selectedJobs)) + # # on continue classiquement avec les autres éléments + # args = array_values(userInfos) + # array_push(args, userId) + # self.exec_cmd(reqAddInfoPro, args) + # for i in jobsAdded: + # self.exec_cmd(reqAddInfoProJobs, array(jobsAdded[i], userId)) + # for i in jobsRemoved: + # self.exec_cmd(reqRemoveInfoProJobs, array(jobsRemoved[i], userId)) + + # **************************************************************************** + # GESTION DU TOKEN AUTOLOGIN + # **************************************************************************** + # Vérification de la combinaison email - jeton d'auto-login pour authentification + def check_token_autologin(self, email, token): + # Préparation de la requète pour récupérer les infos ou l'email est présent + reqCheckToken = """ + SELECT + userId, tokenAutoLogin + FROM + """ + self.TABLEUSERACCOUNT + """ + WHERE + email = %s""" + # Exécution de la requète + self.exec_cmd(reqCheckToken, [email]) + result = self.cur.fetchone() + # Vérifiaction de correspondance email & jeton d'auto-connection + if result and result[1] == token: + return result[0] + + # Mise à jour du jeton d'auto-login + def update_token_autologin(self, email, token): + # Préparation de la requète pour mise à jour du jeton d'auto-connection + reqUpdateToken = """ + UPDATE + """ + self.TABLEUSERACCOUNT + """ + SET + tokenAutoLogin = %s + WHERE + email = %s""" + # Execution de la requète + self.exec_cmd(reqUpdateToken, [token, email]) + + # Supression du jeton d'auto-login + def del_token_autologin(self, email): + # Préparation de la requète pour supression du jeton d'auto-connection + reqDeleteToken = """ + UPDATE + """ + self.TABLEUSERACCOUNT + """ + SET + tokenAutoLogin = NULL + WHERE + email = %s""" + # Execution de la requète + self.exec_cmd(reqDeleteToken, [email]) diff --git a/src/gui/__init__.py b/src/gui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/gui/aPropos.py b/src/gui/aPropos.py new file mode 100644 index 0000000..49cb663 --- /dev/null +++ b/src/gui/aPropos.py @@ -0,0 +1,14 @@ + +from PyQt5.QtWidgets import QMessageBox + + +def a_propos(mainWindow): + QMessageBox.information( + mainWindow, + "A propos", + "Logiciel pour mon dossier professionnel.\ +
Version: %s\ +
Auteur: Debulois Quentin\ +
Code source: \ + git.debulois.fr/" % mainWindow.VERSION + ) diff --git a/src/gui/home.py b/src/gui/home.py new file mode 100644 index 0000000..554d561 --- /dev/null +++ b/src/gui/home.py @@ -0,0 +1,24 @@ + +from PyQt5 import QtWidgets +from src.gui import login + +def home_page(mainWindow): + label1 = QtWidgets.QLabel("Home page") + btnConnexion = QtWidgets.QPushButton("Connexion") + btnConnexion.clicked.connect(lambda: login.login_page(mainWindow)) + + inputRecherche = QtWidgets.QLineEdit("Nom d'un pro") + comboRecherche = QtWidgets.QComboBox() + + layoutMain = QtWidgets.QVBoxLayout() + + layoutMain.addWidget(btnConnexion) + layoutMain.addWidget(label1) + layoutMain.addWidget(inputRecherche) + layoutMain.addWidget(comboRecherche) + + if hasattr(mainWindow, "mainWidget"): + mainWindow.mainWidget.deleteLater() + mainWindow.mainWidget = QtWidgets.QWidget() + mainWindow.mainWidget.setLayout(layoutMain) + mainWindow.setCentralWidget(mainWindow.mainWidget) diff --git a/src/gui/login.py b/src/gui/login.py new file mode 100644 index 0000000..601cd18 --- /dev/null +++ b/src/gui/login.py @@ -0,0 +1,42 @@ + +from PyQt5 import QtWidgets +from src.core import user +from src.gui import home + + +def login_page(mainWindow): + btnAccueil = QtWidgets.QPushButton("Accueil") + btnAccueil.clicked.connect(lambda: home.home_page(mainWindow)) + leditMail = QtWidgets.QLineEdit("Email") + leditPassword = QtWidgets.QLineEdit("Password") + btnConnexion = QtWidgets.QPushButton("Connexion") + btnConnexion.clicked.connect( + lambda: user.login( + mainWindow, + leditMail.text(), + leditPassword.text() + ) + ) + + layoutMain = QtWidgets.QVBoxLayout() + layoutNavigation = QtWidgets.QHBoxLayout() + layoutPassword = QtWidgets.QHBoxLayout() + layoutPasswordWidgets = QtWidgets.QVBoxLayout() + + layoutMain.addLayout(layoutNavigation) + layoutNavigation.addWidget(btnAccueil) + layoutNavigation.addStretch() + + layoutMain.addLayout(layoutPassword) + layoutPassword.addStretch() + layoutPassword.addLayout(layoutPasswordWidgets) + layoutPassword.addStretch() + + layoutPasswordWidgets.addWidget(leditMail) + layoutPasswordWidgets.addWidget(leditPassword) + layoutPasswordWidgets.addWidget(btnConnexion) + + mainWindow.mainWidget.deleteLater() + mainWindow.mainWidget = QtWidgets.QWidget() + mainWindow.mainWidget.setLayout(layoutMain) + mainWindow.setCentralWidget(mainWindow.mainWidget) \ No newline at end of file diff --git a/src/gui/menu.py b/src/gui/menu.py new file mode 100644 index 0000000..90dffcf --- /dev/null +++ b/src/gui/menu.py @@ -0,0 +1,17 @@ + +from os.path import join +from pathlib import Path +from PyQt5.QtWidgets import QAction +from PyQt5.QtGui import QIcon +from src.gui import aPropos + +def init_menu(mainWindow): + logo = join(Path(__file__).parent, "ressources", "icon.ico") + print(logo) + mainWindow.setWindowIcon(QIcon(logo)) + menu = mainWindow.menuBar() + menuOptions = menu.addMenu("Options") + btnApropos = QAction("A propos", mainWindow) + btnApropos.triggered.connect(lambda: aPropos.a_propos(mainWindow)) + menuOptions.addAction(btnApropos) + mainWindow.setWindowTitle("Alphajob") diff --git a/src/gui/ressources/icon.ico b/src/gui/ressources/icon.ico new file mode 100644 index 0000000..7c550a3 Binary files /dev/null and b/src/gui/ressources/icon.ico differ diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..693964e --- /dev/null +++ b/src/main.py @@ -0,0 +1,29 @@ + +from sys import argv +from sys import exit as ex +from PyQt5.QtWidgets import QMainWindow, QApplication +from src.gui import menu, home + + +""" +https://peps.python.org/pep-0008/ +'python a = lambda a, b: truc' = 'js a = (a, b) => {truc}' = Fonction anonyme +""" +class mainWindow(QMainWindow): + VERSION = 0.1 + def __init__(self): + super(mainWindow, self).__init__() + menu.init_menu(self) + home.home_page(self) + + +if __name__ == "__main__": + def main(): + """Démarrage de l'app + """ + app = QApplication(argv) + GUI = mainWindow() + GUI.show() + ex(app.exec_()) + + main() -- cgit v1.2.3