Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
793eeab5ca | |||
962977774b | |||
0d94358f10 | |||
ff1a88c85b | |||
d879cf389d | |||
a93c05bcc3 | |||
ad2c7de563 | |||
9ab362fd29 | |||
5d76b1f584 | |||
a1beec5cd1 | |||
f3f86c43a6 | |||
a500e22678 | |||
3dbb48d7fc | |||
d651a4973a | |||
0ce5ed334c | |||
d5c4ee5997 |
282
IFPass.py
282
IFPass.py
@ -15,6 +15,7 @@ from pywinauto.findwindows import find_window
|
|||||||
from pywinauto.win32functions import SetForegroundWindow
|
from pywinauto.win32functions import SetForegroundWindow
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
from PyPDF2 import PdfFileReader, PdfFileWriter
|
from PyPDF2 import PdfFileReader, PdfFileWriter
|
||||||
|
import fitz # = PyMuPDF : To convert pdf to png
|
||||||
import subprocess
|
import subprocess
|
||||||
from shutil import copyfile, move
|
from shutil import copyfile, move
|
||||||
from pyfiglet import Figlet
|
from pyfiglet import Figlet
|
||||||
@ -22,7 +23,7 @@ from colorama import init
|
|||||||
from termcolor import colored
|
from termcolor import colored
|
||||||
|
|
||||||
|
|
||||||
version = '2.5' # dev/devnocam
|
version = '3.1-1' # dev/devnocam
|
||||||
|
|
||||||
configdir = os.path.join(os.getenv('PROGRAMDATA'), 'IFPass')
|
configdir = os.path.join(os.getenv('PROGRAMDATA'), 'IFPass')
|
||||||
config = os.path.join(configdir, 'IFPass.conf')
|
config = os.path.join(configdir, 'IFPass.conf')
|
||||||
@ -85,7 +86,13 @@ def initialisation():
|
|||||||
return IFPassDBdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, templatesdir, pdftemplate, pngtemplate, fonttemplate
|
return IFPassDBdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, templatesdir, pdftemplate, pngtemplate, fonttemplate
|
||||||
|
|
||||||
|
|
||||||
def get_fullname():
|
def get_fullname(**kwargs): # **kwargs => Optionnal arguments
|
||||||
|
if 'firstname' in kwargs:
|
||||||
|
firstname = kwargs['firstname']
|
||||||
|
newfirstname = input("Prénom (" + firstname + "): ").strip()
|
||||||
|
if len(newfirstname) != 0:
|
||||||
|
firstname = newfirstname
|
||||||
|
else:
|
||||||
while "Empty firstname":
|
while "Empty firstname":
|
||||||
firstname = input("Prénom : ").strip()
|
firstname = input("Prénom : ").strip()
|
||||||
if len(firstname) == 0:
|
if len(firstname) == 0:
|
||||||
@ -102,21 +109,29 @@ def get_fullname():
|
|||||||
pos = firstname.find(" ")
|
pos = firstname.find(" ")
|
||||||
firstname = firstname[:pos + 1] + firstname[pos + 1].upper() + \
|
firstname = firstname[:pos + 1] + firstname[pos + 1].upper() + \
|
||||||
firstname[pos + 2:] # Check if compound name
|
firstname[pos + 2:] # Check if compound name
|
||||||
|
|
||||||
|
if 'surname' in kwargs:
|
||||||
|
surname = kwargs['surname']
|
||||||
|
newsurname = input("Nom (" + surname + "): ").strip()
|
||||||
|
if len(newsurname) != 0:
|
||||||
|
surname = newsurname
|
||||||
|
else:
|
||||||
while "Empty surname":
|
while "Empty surname":
|
||||||
surname = input("Nom : ").upper().strip()
|
surname = input("Nom : ").strip()
|
||||||
if len(surname) == 0:
|
if len(surname) == 0:
|
||||||
os.system('cls')
|
os.system('cls')
|
||||||
print(colored("\nLe Nom ne peut pas être vide.", 'red'))
|
print(colored("\nLe Nom ne peut pas être vide.", 'red'))
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
surname = surname.upper()
|
||||||
docteur = yes_or_no('Est-ce un Docteur ?')
|
docteur = yes_or_no('Est-ce un Docteur ?')
|
||||||
if docteur:
|
if docteur:
|
||||||
titre = 'Dr.'
|
titre = 'Dr.'
|
||||||
fullname = titre + ' ' + surname + ' ' + firstname
|
titrename = titre + ' ' + surname
|
||||||
else:
|
else:
|
||||||
titre = ''
|
titre = ''
|
||||||
fullname = surname + ' ' + firstname
|
titrename = surname
|
||||||
return titre, firstname, surname, fullname
|
return titre, firstname, surname, titrename
|
||||||
|
|
||||||
|
|
||||||
def yes_or_no(question):
|
def yes_or_no(question):
|
||||||
@ -137,7 +152,6 @@ def getclientID():
|
|||||||
else:
|
else:
|
||||||
clientID = str(int(lastID) + 1).zfill(10)
|
clientID = str(int(lastID) + 1).zfill(10)
|
||||||
|
|
||||||
writeindb(clientID)
|
|
||||||
return clientID
|
return clientID
|
||||||
|
|
||||||
|
|
||||||
@ -202,20 +216,39 @@ def getpic():
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
def writeindb(clientID):
|
def writeindb(titre, firstname, surname, clientID, dateinsc, dateexp, new):
|
||||||
|
if new is True:
|
||||||
print("Ajout dans la base de données... ", end="")
|
print("Ajout dans la base de données... ", end="")
|
||||||
with open(clientsfile, 'a', newline='', encoding='utf-8') as csvfile:
|
with open(clientsfile, 'a', newline='', encoding='utf-8') as csvfile:
|
||||||
writer = csv.writer(csvfile, delimiter=';')
|
writer = csv.writer(csvfile, delimiter=';')
|
||||||
writer.writerow([titre, firstname, surname, clientID, dateinsc, dateexp])
|
writer.writerow([titre, firstname, surname, clientID, dateinsc, dateexp])
|
||||||
print(colored('[OK]', 'green'))
|
print(colored('[OK]', 'green'))
|
||||||
|
elif new is False:
|
||||||
|
print("Modification de la base de données... ", end="")
|
||||||
|
with open(clientsfile, 'r+', newline='', encoding='utf-8') as csvfile:
|
||||||
|
content = csvfile.readlines()
|
||||||
|
for index, member in enumerate(content):
|
||||||
|
member = member.split(';')
|
||||||
|
if member[3] == clientID:
|
||||||
|
tochange = index
|
||||||
|
break
|
||||||
|
content.pop(tochange)
|
||||||
|
changewith = ";".join([titre, firstname, surname, clientID, dateinsc, dateexp]) + '\n'
|
||||||
|
content.insert(tochange, changewith)
|
||||||
|
content = "".join(content)
|
||||||
|
csvfile.seek(0)
|
||||||
|
csvfile.truncate(0)
|
||||||
|
csvfile.write(content)
|
||||||
|
|
||||||
|
print(colored('[OK]', 'green'))
|
||||||
|
|
||||||
|
|
||||||
def bkpdb():
|
def bkpdb():
|
||||||
copyfile(clientsfile, clientsbkpfile)
|
copyfile(clientsfile, clientsbkpfile)
|
||||||
|
|
||||||
|
|
||||||
def fillcard(barcode):
|
def fillcard(clientID, titrename, firstname, dateexp, barcode, picture):
|
||||||
print("Création de la carte avec les informations...", end='')
|
print("Création du verso de la carte avec les informations...", end='')
|
||||||
try:
|
try:
|
||||||
im = Image.open(pngtemplate)
|
im = Image.open(pngtemplate)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
@ -228,12 +261,13 @@ def fillcard(barcode):
|
|||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
# Name embedding :
|
# Name embedding :
|
||||||
font = ImageFont.truetype(fonttemplate, 45)
|
font = ImageFont.truetype(fonttemplate, 40)
|
||||||
draw.text((401, 310), fullname, fill=(0, 0, 0), font=font)
|
draw.text((401, 296), titrename, fill=(0, 0, 0), font=font)
|
||||||
|
draw.text((401, 334), firstname, fill=(0, 0, 0), font=font)
|
||||||
|
|
||||||
# Date embedding :
|
# Date embedding :
|
||||||
font = ImageFont.truetype(fonttemplate, 30)
|
font = ImageFont.truetype(fonttemplate, 30)
|
||||||
draw.text((401, 390), dateexp, fill=(0, 0, 0), font=font)
|
draw.text((401, 400), dateexp, fill=(0, 0, 0), font=font)
|
||||||
|
|
||||||
# ID embedding :
|
# ID embedding :
|
||||||
font = ImageFont.truetype('arial.ttf', 30)
|
font = ImageFont.truetype('arial.ttf', 30)
|
||||||
@ -252,7 +286,8 @@ def fillcard(barcode):
|
|||||||
print(colored('[OK]', 'green'))
|
print(colored('[OK]', 'green'))
|
||||||
|
|
||||||
|
|
||||||
def mergepdf():
|
def mergepdf(clientID):
|
||||||
|
print("Fusion du recto et du verso de la carte...", end='')
|
||||||
cartefilename = os.path.join(imgdir, clientID + '.pdf')
|
cartefilename = os.path.join(imgdir, clientID + '.pdf')
|
||||||
output = PdfFileWriter()
|
output = PdfFileWriter()
|
||||||
|
|
||||||
@ -268,6 +303,7 @@ def mergepdf():
|
|||||||
output.write(f)
|
output.write(f)
|
||||||
|
|
||||||
os.remove(imgdir + clientID + '_Front.pdf')
|
os.remove(imgdir + clientID + '_Front.pdf')
|
||||||
|
print(colored('[OK]', 'green'))
|
||||||
|
|
||||||
return cartefilename
|
return cartefilename
|
||||||
|
|
||||||
@ -277,10 +313,57 @@ def printcard(cartefilename):
|
|||||||
subprocess.Popen('"' + AcrobatReader + '"' + ' /h /n /t ' + cartefilename + ' ' + printername, shell=False)
|
subprocess.Popen('"' + AcrobatReader + '"' + ' /h /n /t ' + cartefilename + ' ' + printername, shell=False)
|
||||||
|
|
||||||
|
|
||||||
|
def getdateexp():
|
||||||
|
while True:
|
||||||
|
dateexp = input("Quelle date d'expiration voulez-vous mettre (Format : JJ/MM/AAAA)? : ")
|
||||||
|
match = re.fullmatch(r'^(0[1-9]|1[0-9]|2[0-9]|3[0-1])/(0[1-9]|1[0-2])/([0-9]){4}$', dateexp)
|
||||||
|
if match:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print('Mauvais format ! JJ/MM/AAAA, exemple : 01/08/2042')
|
||||||
|
return dateexp
|
||||||
|
|
||||||
|
|
||||||
|
def newmember():
|
||||||
|
while "the informations are incorrect": # Loop Filling informations
|
||||||
|
os.system('cls')
|
||||||
|
titre, firstname, surname, titrename = get_fullname()
|
||||||
|
dateinsc = date.today()
|
||||||
|
dateexp = dateinsc + timedelta(days=365)
|
||||||
|
|
||||||
|
dateinsc = dateinsc.strftime('%d/%m/%Y')
|
||||||
|
dateexp = dateexp.strftime('%d/%m/%Y')
|
||||||
|
changeexp = yes_or_no("Voulez-vous choisir la date d'expiration ?")
|
||||||
|
if changeexp:
|
||||||
|
dateexp = getdateexp()
|
||||||
|
|
||||||
|
os.system('cls')
|
||||||
|
print("Titre : ", colored(titre, 'green'))
|
||||||
|
print("Prénom : ", colored(firstname, 'green'))
|
||||||
|
print("Nom : ", colored(surname, 'green'))
|
||||||
|
print("Date d'inscription :", colored(dateinsc, 'green'))
|
||||||
|
print("Date d'expiration : ", colored(dateexp, 'green'))
|
||||||
|
correct = yes_or_no("Ces informations sont elles correctes ?")
|
||||||
|
|
||||||
|
if correct:
|
||||||
|
os.system('cls')
|
||||||
|
if version != 'devnocam':
|
||||||
|
picture = getpic()
|
||||||
|
clientID = getclientID()
|
||||||
|
barcode = barcode_gen(clientID)
|
||||||
|
fillcard(clientID, titrename, firstname, dateexp, barcode, picture)
|
||||||
|
cartefilename = mergepdf(clientID)
|
||||||
|
if version not in ('dev', 'devnocam'):
|
||||||
|
bkpdb()
|
||||||
|
printcard(cartefilename)
|
||||||
|
writeindb(titre, firstname, surname, clientID, dateinsc, dateexp, new=True)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
def membersearch():
|
def membersearch():
|
||||||
with open(clientsfile, 'r', newline='', encoding='utf-8') as csvfile:
|
with open(clientsfile, 'r', newline='', encoding='utf-8') as csvfile:
|
||||||
reader = csv.reader(csvfile, delimiter=';')
|
reader = csv.reader(csvfile, delimiter=';')
|
||||||
csvlist = list(map(tuple, reader))
|
csvlist = list(map(list, reader))
|
||||||
del csvlist[0] # We dele the first line (Prénom, Nom...)
|
del csvlist[0] # We dele the first line (Prénom, Nom...)
|
||||||
research = input('Entrez une partie du nom, prénom, ou numéro de carte (ou flashez) : ').lower()
|
research = input('Entrez une partie du nom, prénom, ou numéro de carte (ou flashez) : ').lower()
|
||||||
os.system('cls')
|
os.system('cls')
|
||||||
@ -312,6 +395,7 @@ def membersearch():
|
|||||||
print(colored('Choix invalide ! Veillez bien à sélectionner le numéro de la colonne "Choix"', 'red', attrs=['bold']))
|
print(colored('Choix invalide ! Veillez bien à sélectionner le numéro de la colonne "Choix"', 'red', attrs=['bold']))
|
||||||
os.system('cls')
|
os.system('cls')
|
||||||
|
|
||||||
|
while 'Choix incorect':
|
||||||
print("Titre : ", colored(member[0], 'green'))
|
print("Titre : ", colored(member[0], 'green'))
|
||||||
print("Prénom : ", colored(member[1], 'green'))
|
print("Prénom : ", colored(member[1], 'green'))
|
||||||
print("Nom : ", colored(member[2], 'green'))
|
print("Nom : ", colored(member[2], 'green'))
|
||||||
@ -323,16 +407,132 @@ def membersearch():
|
|||||||
if diff > 0:
|
if diff > 0:
|
||||||
print(colored(f"L'abonnement est encore valable {diff} jours.", 'green', attrs=['bold']))
|
print(colored(f"L'abonnement est encore valable {diff} jours.", 'green', attrs=['bold']))
|
||||||
elif diff < 0:
|
elif diff < 0:
|
||||||
print(colored("L'abonnement est expiré depuis {abs(diff)} jours.", 'red', attrs=['bold'])) # abs() to remove minus sign
|
print(colored(f"L'abonnement est expiré depuis {abs(diff)} jours.", 'red', attrs=['bold'])) # abs() to remove minus sign
|
||||||
elif diff == 0:
|
elif diff == 0:
|
||||||
print(colored("Il s'agit du dernier jour de l'abonnement, il expirera demain.", 'yellow', attrs=['bold']))
|
print(colored("Il s'agit du dernier jour de l'abonnement, il expirera demain.", 'yellow', attrs=['bold']))
|
||||||
|
|
||||||
|
print('\n1 - Modifier', "2 - Renouveller l'abonnement / Choisir un nouvelle date d'expiration", '3 - Imprimer la carte', '0 - Menu principal', sep='\n')
|
||||||
|
choix = input('Choix : ')
|
||||||
|
if choix == '0':
|
||||||
|
os.system('cls')
|
||||||
|
return
|
||||||
|
# We update values with new (edited) values :
|
||||||
|
newtitre, newfirstname, newsurname, newdateexp = memberdo(choix, member)
|
||||||
|
member[0], member[1], member[2], member[5] = newtitre, newfirstname, newsurname, newdateexp
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(colored("Aucun membre n'a été trouvé.", 'red', attrs=['bold']))
|
print(colored("Aucun membre n'a été trouvé.", 'red', attrs=['bold']))
|
||||||
|
os.system("pause")
|
||||||
|
|
||||||
|
|
||||||
|
def memberdo(choix, member):
|
||||||
|
titre = member[0]
|
||||||
|
firstname = member[1]
|
||||||
|
surname = member[2]
|
||||||
|
clientID = member[3]
|
||||||
|
dateinsc = member[4]
|
||||||
|
dateexp = member[5]
|
||||||
|
|
||||||
|
os.system('cls')
|
||||||
|
if choix == '1': # Edit member
|
||||||
|
titre, firstname, surname, dateexp = memberedit(titre, firstname, surname, clientID, dateinsc, dateexp)
|
||||||
|
|
||||||
|
elif choix == '2': # Renew subscription
|
||||||
|
changeexp = yes_or_no("Voulez-vous choisir la date d'expiration ?")
|
||||||
|
if changeexp:
|
||||||
|
dateexp = getdateexp()
|
||||||
|
else:
|
||||||
|
dateexp = datetime.strptime(dateexp, '%d/%m/%Y').date()
|
||||||
|
diff = (dateexp - date.today()).days
|
||||||
|
if diff >= 0:
|
||||||
|
dateexp = dateexp + timedelta(days=365)
|
||||||
|
elif diff < 0:
|
||||||
|
dateexp = date.today() + timedelta(days=365)
|
||||||
|
dateexp = dateexp.strftime('%d/%m/%Y')
|
||||||
|
|
||||||
|
if titre == 'Dr.':
|
||||||
|
titrename = titre + ' ' + surname
|
||||||
|
else:
|
||||||
|
titrename = surname
|
||||||
|
|
||||||
|
wantnewpic = yes_or_no("Voulez-vous prendre une nouvelle photo ?")
|
||||||
|
os.system('cls')
|
||||||
|
if wantnewpic:
|
||||||
|
os.system('cls')
|
||||||
|
if version != 'devnocam':
|
||||||
|
picture = getpic()
|
||||||
|
else:
|
||||||
|
# We crop pic from the previous card
|
||||||
|
cartefilename = os.path.join(imgdir, clientID + '.pdf')
|
||||||
|
pdf = fitz.open(cartefilename)
|
||||||
|
page = pdf.loadPage(0)
|
||||||
|
mat = fitz.Matrix(4.165, 4.165) # To obtain good resolution
|
||||||
|
pix = page.getPixmap(matrix=mat)
|
||||||
|
pageimg = Image.frombytes("RGBA", [pix.width, pix.height], pix.samples)
|
||||||
|
picture = pageimg.crop((47, 49, 343, 378))
|
||||||
|
|
||||||
|
barcode = barcode_gen(clientID)
|
||||||
|
fillcard(clientID, titrename, firstname, dateexp, barcode, picture)
|
||||||
|
cartefilename = mergepdf(clientID)
|
||||||
|
|
||||||
|
if version not in ('dev', 'devnocam'):
|
||||||
|
bkpdb()
|
||||||
|
printcard(cartefilename)
|
||||||
|
writeindb(titre, firstname, surname, clientID, dateinsc, dateexp, new=False)
|
||||||
|
os.system('cls')
|
||||||
|
print(colored("La date d'expiration a bien été mise à jour !\n", 'blue', attrs=['bold']))
|
||||||
|
|
||||||
|
elif choix == '3': # Print card
|
||||||
|
cartefilename = os.path.join(imgdir, clientID + '.pdf')
|
||||||
|
printcard(cartefilename)
|
||||||
|
else:
|
||||||
|
print(colored('Choix incorrect !\n', 'red', attrs=['bold']))
|
||||||
|
return titre, firstname, surname, dateexp
|
||||||
|
|
||||||
|
|
||||||
|
def memberedit(titre, firstname, surname, clientID, dateinsc, dateexp):
|
||||||
|
while "the informations are incorrect": # Loop Filling informations
|
||||||
|
titre, firstname, surname, titrename = get_fullname(titre=titre, firstname=firstname, surname=surname)
|
||||||
|
|
||||||
|
print("Titre : ", colored(titre, 'green'))
|
||||||
|
print("Prénom : ", colored(firstname, 'green'))
|
||||||
|
print("Nom : ", colored(surname, 'green'))
|
||||||
|
|
||||||
|
correct = yes_or_no("Ces informations sont elles correctes ?")
|
||||||
|
os.system('cls')
|
||||||
|
|
||||||
|
if correct:
|
||||||
|
wantnewpic = yes_or_no("Voulez-vous prendre une nouvelle photo ?")
|
||||||
|
os.system('cls')
|
||||||
|
if wantnewpic:
|
||||||
|
os.system('cls')
|
||||||
|
if version != 'devnocam':
|
||||||
|
picture = getpic()
|
||||||
|
else:
|
||||||
|
# We crop pic from the previous card
|
||||||
|
cartefilename = os.path.join(imgdir, clientID + '.pdf')
|
||||||
|
pdf = fitz.open(cartefilename)
|
||||||
|
page = pdf.loadPage(0)
|
||||||
|
mat = fitz.Matrix(4.165, 4.165) # To obtain good resolution
|
||||||
|
pix = page.getPixmap(matrix=mat)
|
||||||
|
|
||||||
|
pageimg = Image.frombytes("RGBA", [pix.width, pix.height], pix.samples)
|
||||||
|
picture = pageimg.crop((47, 49, 343, 378))
|
||||||
|
|
||||||
|
barcode = barcode_gen(clientID)
|
||||||
|
fillcard(clientID, titrename, firstname, dateexp, barcode, picture)
|
||||||
|
cartefilename = mergepdf(clientID)
|
||||||
|
if version not in ('dev', 'devnocam'):
|
||||||
|
bkpdb()
|
||||||
|
printcard(cartefilename)
|
||||||
|
writeindb(titre, firstname, surname, clientID, dateinsc, dateexp, new=False)
|
||||||
|
os.system('cls')
|
||||||
|
break
|
||||||
|
return titre, firstname, surname, dateexp
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global titre, firstname, surname, fullname, dateinsc, dateexp, clientID, clientsfile, IFPassDBdir, clientsfile, imgdir, clientsbkpfile, templatesdir, pngtemplate, fonttemplate, picture, pdftemplate, printername, AcrobatReader
|
global IFPassDBdir, clientsfile, imgdir, clientsbkpfile, templatesdir, pngtemplate, fonttemplate, pdftemplate, printername, AcrobatReader
|
||||||
while "The program is running":
|
while "The program is running":
|
||||||
init() # Initialisation of colorama
|
init() # Initialisation of colorama
|
||||||
IFPassDBdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, templatesdir, pdftemplate, pngtemplate, fonttemplate = initialisation()
|
IFPassDBdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, templatesdir, pdftemplate, pngtemplate, fonttemplate = initialisation()
|
||||||
@ -343,57 +543,19 @@ def main():
|
|||||||
print('Version : ', version)
|
print('Version : ', version)
|
||||||
if version in ('dev', 'devnocam'):
|
if version in ('dev', 'devnocam'):
|
||||||
print(colored("\nATTENTION : Il s'agit d'une version en cours de développement, potentiellement instable !", 'red'))
|
print(colored("\nATTENTION : Il s'agit d'une version en cours de développement, potentiellement instable !", 'red'))
|
||||||
print("\nLe programme IFPass à été écrit par Jordan ERNST Q1 2018 pour l'Institut Français en Hongrie.")
|
print("\nCe programme est developpé par par Jordan ERNST pour l'Institut Français en Hongrie.")
|
||||||
|
print("Il est disponible sou licence MIT à cette addresse : https://framagit.org/SecT0uch/IFPass\n")
|
||||||
print('Pour toute question, problème ou requête contactez-moi à pro.ernst@gmail.com.\n')
|
print('Pour toute question, problème ou requête contactez-moi à pro.ernst@gmail.com.\n')
|
||||||
print('1 - Nouveau membre', '2 - Rechercher un membre', '3 - Quitter', sep='\n')
|
print('1 - Nouveau membre', '2 - Rechercher un membre', '0 - Quitter', sep='\n')
|
||||||
choix = input('Choix : ')
|
choix = input('Choix : ')
|
||||||
if choix == '1':
|
if choix == '1':
|
||||||
while "the informations are incorrect": # Loop Filling informations
|
newmember()
|
||||||
os.system('cls')
|
|
||||||
titre, firstname, surname, fullname = get_fullname()
|
|
||||||
dateinsc = date.today()
|
|
||||||
dateexp = dateinsc + timedelta(days=365)
|
|
||||||
|
|
||||||
dateinsc = dateinsc.strftime('%d/%m/%Y')
|
|
||||||
dateexp = dateexp.strftime('%d/%m/%Y')
|
|
||||||
changeexp = yes_or_no("Voulez-vous choisir la date d'expiration ?")
|
|
||||||
if changeexp:
|
|
||||||
while True:
|
|
||||||
dateexp = input("Quelle date d'expiration voulez-vous mettre (Format : JJ/MM/AAAA)? : ")
|
|
||||||
match = re.fullmatch(r'^(0[1-9]|1[0-9]|2[0-9]|3[0-1])/(0[1-9]|1[0-2])/([0-9]){4}$', dateexp)
|
|
||||||
if match:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print('Mauvais format ! JJ/MM/AAAA, exemple : 01/08/2042')
|
|
||||||
|
|
||||||
os.system('cls')
|
|
||||||
print("Titre : ", colored(titre, 'green'))
|
|
||||||
print("Prénom : ", colored(firstname, 'green'))
|
|
||||||
print("Nom : ", colored(surname, 'green'))
|
|
||||||
print("Date d'inscription :", colored(dateinsc, 'green'))
|
|
||||||
print("Date d'expiration : ", colored(dateexp, 'green'))
|
|
||||||
correct = yes_or_no("Ces informations sont elles correctes ?")
|
|
||||||
|
|
||||||
if correct:
|
|
||||||
os.system('cls')
|
|
||||||
if version != 'devnocam':
|
|
||||||
global picture
|
|
||||||
picture = getpic()
|
|
||||||
clientID = getclientID()
|
|
||||||
barcode = barcode_gen(clientID)
|
|
||||||
fillcard(barcode)
|
|
||||||
cartefilename = mergepdf()
|
|
||||||
if version not in ('dev', 'devnocam'):
|
|
||||||
bkpdb()
|
|
||||||
printcard(cartefilename)
|
|
||||||
break
|
|
||||||
|
|
||||||
elif choix == '2':
|
elif choix == '2':
|
||||||
os.system('cls')
|
os.system('cls')
|
||||||
membersearch()
|
membersearch()
|
||||||
os.system("pause")
|
|
||||||
|
|
||||||
elif choix == '3':
|
elif choix == '0':
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1,189 +0,0 @@
|
|||||||
!define PRODUCT_NAME "[[ib.appname]]"
|
|
||||||
!define PRODUCT_VERSION "[[ib.version]]"
|
|
||||||
!define PY_VERSION "[[ib.py_version]]"
|
|
||||||
!define PY_MAJOR_VERSION "[[ib.py_major_version]]"
|
|
||||||
!define BITNESS "[[ib.py_bitness]]"
|
|
||||||
!define ARCH_TAG "[[arch_tag]]"
|
|
||||||
!define INSTALLER_NAME "[[ib.installer_name]]"
|
|
||||||
!define PRODUCT_ICON "[[icon]]"
|
|
||||||
|
|
||||||
; Marker file to tell the uninstaller that it's a user installation
|
|
||||||
!define USER_INSTALL_MARKER _user_install_marker
|
|
||||||
|
|
||||||
Unicode true
|
|
||||||
InstallDir "C:\IFPass"
|
|
||||||
|
|
||||||
SetCompressor lzma
|
|
||||||
|
|
||||||
[% block modernui %]
|
|
||||||
; Modern UI installer stuff
|
|
||||||
!include "MUI2.nsh"
|
|
||||||
!define MUI_ABORTWARNING
|
|
||||||
!define MUI_ICON "[[icon]]"
|
|
||||||
!define MUI_UNICON "[[icon]]"
|
|
||||||
|
|
||||||
; UI pages
|
|
||||||
[% block ui_pages %]
|
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
|
||||||
[% if license_file %]
|
|
||||||
!insertmacro MUI_PAGE_LICENSE [[license_file]]
|
|
||||||
[% endif %]
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
|
||||||
!insertmacro MUI_PAGE_FINISH
|
|
||||||
[% endblock ui_pages %]
|
|
||||||
!insertmacro MUI_LANGUAGE "French"
|
|
||||||
[% endblock modernui %]
|
|
||||||
|
|
||||||
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
|
|
||||||
OutFile "${INSTALLER_NAME}"
|
|
||||||
ShowInstDetails show
|
|
||||||
|
|
||||||
Section -SETTINGS
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
SetOverwrite ifnewer
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
[% block sections %]
|
|
||||||
|
|
||||||
Section "!${PRODUCT_NAME}" sec_app
|
|
||||||
SetRegView [[ib.py_bitness]]
|
|
||||||
SetShellVarContext all
|
|
||||||
SectionIn RO
|
|
||||||
File ${PRODUCT_ICON}
|
|
||||||
SetOutPath "$INSTDIR\pkgs"
|
|
||||||
File /r "pkgs\*.*"
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
|
|
||||||
[% block install_files %]
|
|
||||||
; Install files
|
|
||||||
[% for destination, group in grouped_files %]
|
|
||||||
SetOutPath "[[destination]]"
|
|
||||||
[% for file in group %]
|
|
||||||
File "[[ file ]]"
|
|
||||||
[% endfor %]
|
|
||||||
[% endfor %]
|
|
||||||
|
|
||||||
; Install directories
|
|
||||||
[% for dir, destination in ib.install_dirs %]
|
|
||||||
SetOutPath "[[ pjoin(destination, dir) ]]"
|
|
||||||
File /r "[[dir]]\*.*"
|
|
||||||
[% endfor %]
|
|
||||||
[% endblock install_files %]
|
|
||||||
|
|
||||||
[% block install_shortcuts %]
|
|
||||||
; Install shortcuts
|
|
||||||
; The output path becomes the working directory for shortcuts
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
[% if single_shortcut %]
|
|
||||||
[% for scname, sc in ib.shortcuts.items() %]
|
|
||||||
CreateShortCut "$SMPROGRAMS\[[scname]].lnk" "[[sc['target'] ]]" \
|
|
||||||
'[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
|
|
||||||
CreateShortCut "$DESKTOP\[[scname]].lnk" "[[sc['target'] ]]" \
|
|
||||||
'[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
|
|
||||||
[% endfor %]
|
|
||||||
[% else %]
|
|
||||||
[# Multiple shortcuts: create a directory for them #]
|
|
||||||
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
|
||||||
[% for scname, sc in ib.shortcuts.items() %]
|
|
||||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\[[scname]].lnk" "[[sc['target'] ]]" \
|
|
||||||
'[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
|
|
||||||
[% endfor %]
|
|
||||||
[% endif %]
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
[% endblock install_shortcuts %]
|
|
||||||
|
|
||||||
[% block install_commands %]
|
|
||||||
[% if has_commands %]
|
|
||||||
DetailPrint "Setting up command-line launchers..."
|
|
||||||
nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_assemble_launchers.py" "$INSTDIR\bin"'
|
|
||||||
[% endif %]
|
|
||||||
[% endblock install_commands %]
|
|
||||||
|
|
||||||
; Byte-compile Python files.
|
|
||||||
DetailPrint "Byte-compiling Python modules..."
|
|
||||||
nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"'
|
|
||||||
WriteUninstaller $INSTDIR\uninstall.exe
|
|
||||||
; Add ourselves to Add/remove programs
|
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"DisplayName" "${PRODUCT_NAME}"
|
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"UninstallString" '"$INSTDIR\uninstall.exe"'
|
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"InstallLocation" "$INSTDIR"
|
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"DisplayIcon" "$INSTDIR\${PRODUCT_ICON}"
|
|
||||||
[% if ib.publisher is not none %]
|
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"Publisher" "[[ib.publisher]]"
|
|
||||||
[% endif %]
|
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"DisplayVersion" "${PRODUCT_VERSION}"
|
|
||||||
WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"NoModify" 1
|
|
||||||
WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
||||||
"NoRepair" 1
|
|
||||||
|
|
||||||
; Check if we need to reboot
|
|
||||||
IfRebootFlag 0 noreboot
|
|
||||||
MessageBox MB_YESNO "A reboot is required to finish the installation. Do you wish to reboot now?" \
|
|
||||||
/SD IDNO IDNO noreboot
|
|
||||||
Reboot
|
|
||||||
noreboot:
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
Section "Uninstall"
|
|
||||||
SetRegView [[ib.py_bitness]]
|
|
||||||
SetShellVarContext all
|
|
||||||
|
|
||||||
Delete $INSTDIR\uninstall.exe
|
|
||||||
Delete "$INSTDIR\${PRODUCT_ICON}"
|
|
||||||
RMDir /r "$INSTDIR\pkgs"
|
|
||||||
|
|
||||||
; Remove ourselves from %PATH%
|
|
||||||
[% block uninstall_commands %]
|
|
||||||
[% if has_commands %]
|
|
||||||
nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" remove "$INSTDIR\bin"'
|
|
||||||
[% endif %]
|
|
||||||
[% endblock uninstall_commands %]
|
|
||||||
|
|
||||||
[% block uninstall_files %]
|
|
||||||
; Uninstall files
|
|
||||||
[% for file, destination in ib.install_files %]
|
|
||||||
Delete "[[pjoin(destination, file)]]"
|
|
||||||
[% endfor %]
|
|
||||||
; Uninstall directories
|
|
||||||
[% for dir, destination in ib.install_dirs %]
|
|
||||||
RMDir /r "[[pjoin(destination, dir)]]"
|
|
||||||
[% endfor %]
|
|
||||||
[% endblock uninstall_files %]
|
|
||||||
|
|
||||||
[% block uninstall_shortcuts %]
|
|
||||||
; Uninstall shortcuts
|
|
||||||
[% if single_shortcut %]
|
|
||||||
[% for scname in ib.shortcuts %]
|
|
||||||
Delete "$SMPROGRAMS\[[scname]].lnk"
|
|
||||||
Delete "$DESKTOP\[[scname]].lnk"
|
|
||||||
[% endfor %]
|
|
||||||
[% else %]
|
|
||||||
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
|
|
||||||
[% endif %]
|
|
||||||
[% endblock uninstall_shortcuts %]
|
|
||||||
RMDir $INSTDIR
|
|
||||||
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
[% endblock sections %]
|
|
||||||
|
|
||||||
; Functions
|
|
||||||
|
|
||||||
Function .onMouseOverSection
|
|
||||||
; Find which section the mouse is over, and set the corresponding description.
|
|
||||||
FindWindow $R0 "#32770" "" $HWNDPARENT
|
|
||||||
GetDlgItem $R0 $R0 1043 ; description item (must be added to the UI)
|
|
||||||
|
|
||||||
[% block mouseover_messages %]
|
|
||||||
StrCmp $0 ${sec_app} "" +2
|
|
||||||
SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}"
|
|
||||||
|
|
||||||
[% endblock mouseover_messages %]
|
|
||||||
FunctionEnd
|
|
11
README.md
11
README.md
@ -1,4 +1,13 @@
|
|||||||
# IFPass
|
# IFPass
|
||||||
|
|
||||||
IFPass is a python project developped for the "Institut Français en Hongrie" and published under MIT license.
|
IFPass is a python project developped for the "Institut Français en Hongrie" and published under [MIT license](https://framagit.org/SecT0uch/IFPass/blob/master/LICENSE).
|
||||||
It allows to manage a subscriber database and print member cards.
|
It allows to manage a subscriber database and print member cards.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
1. Install [NSIS](http://nsis.sourceforge.net/Download).
|
||||||
|
2. Install python 3 and pip.
|
||||||
|
3. Install the modules with `sudo -H pip install pynsist PyPDF2 termcolor`
|
||||||
|
4. If pynsist version < 2.4, replace `/usr/lib/python3.*/site-packages/nsist/__init__.py` with https://raw.githubusercontent.com/takluyver/pynsist/master/nsist/__init__.py
|
||||||
|
5. Run `./build.sh`
|
||||||
|
|
||||||
|
3
build.sh
3
build.sh
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/bash
|
|
||||||
pynsist installer-x86.cfg
|
|
||||||
pynsist installer-x64.cfg
|
|
@ -1,46 +0,0 @@
|
|||||||
[Application]
|
|
||||||
name=IFPass
|
|
||||||
version=2.5
|
|
||||||
entry_point=IFPass:main
|
|
||||||
icon=IF.ico
|
|
||||||
console=true
|
|
||||||
license_file=LICENSE
|
|
||||||
|
|
||||||
[Python]
|
|
||||||
version=3.7.1
|
|
||||||
bitness=64
|
|
||||||
|
|
||||||
[Include]
|
|
||||||
# Packages from PyPI that your application requires, one per line
|
|
||||||
# These must have wheels on PyPI:
|
|
||||||
pypi_wheels=code128==0.3
|
|
||||||
colorama==0.4.1
|
|
||||||
pyfiglet==0.8.post1
|
|
||||||
numpy==1.16.1
|
|
||||||
opencv-python==4.0.0.21
|
|
||||||
Pillow==5.4.1
|
|
||||||
pywin32==224
|
|
||||||
six==1.12.0
|
|
||||||
setuptools==40.7.3
|
|
||||||
# Must check if future updates of the following packages provide .whl files
|
|
||||||
# pywinauto needs to be downloaded manually and edit setup to match platform=win32
|
|
||||||
# Packages without wheels (Must be installed locally):
|
|
||||||
packages=PyPDF2
|
|
||||||
pywinauto
|
|
||||||
termcolor
|
|
||||||
|
|
||||||
# Other files and folders that should be installed
|
|
||||||
files = LICENSE
|
|
||||||
Templates
|
|
||||||
|
|
||||||
# This optional section adds a command which can be run from the Windows
|
|
||||||
# command prompt.
|
|
||||||
[Command IFPass]
|
|
||||||
entry_point=IFPass:main
|
|
||||||
|
|
||||||
[Build]
|
|
||||||
directory=build/x64
|
|
||||||
installer_name=${PRODUCT_NAME}_${PRODUCT_VERSION}-x64.exe
|
|
||||||
# Custom Installer :
|
|
||||||
# Added Desktop shortcut, modified working directory, modified default install and utf-8...
|
|
||||||
nsi_template=Installer_Template.nsi
|
|
@ -1,46 +0,0 @@
|
|||||||
[Application]
|
|
||||||
name=IFPass
|
|
||||||
version=2.5
|
|
||||||
entry_point=IFPass:main
|
|
||||||
icon=IF.ico
|
|
||||||
console=true
|
|
||||||
license_file=LICENSE
|
|
||||||
|
|
||||||
[Python]
|
|
||||||
version=3.7.1
|
|
||||||
bitness=32
|
|
||||||
|
|
||||||
[Include]
|
|
||||||
# Packages from PyPI that your application requires, one per line
|
|
||||||
# These must have wheels on PyPI:
|
|
||||||
pypi_wheels=code128==0.3
|
|
||||||
colorama==0.4.1
|
|
||||||
pyfiglet==0.8.post1
|
|
||||||
numpy==1.16.1
|
|
||||||
opencv-python==4.0.0.21
|
|
||||||
Pillow==5.4.1
|
|
||||||
pywin32==224
|
|
||||||
six==1.12.0
|
|
||||||
setuptools==40.7.3
|
|
||||||
# Must check if future updates of the following packages provide .whl files
|
|
||||||
# pywinauto needs to be downloaded manually and edit setup to match platform=win32
|
|
||||||
# Packages without wheels (Must be installed locally):
|
|
||||||
packages=PyPDF2
|
|
||||||
pywinauto
|
|
||||||
termcolor
|
|
||||||
|
|
||||||
# Other files and folders that should be installed
|
|
||||||
files = LICENSE
|
|
||||||
Templates
|
|
||||||
|
|
||||||
# This optional section adds a command which can be run from the Windows
|
|
||||||
# command prompt.
|
|
||||||
[Command IFPass]
|
|
||||||
entry_point=IFPass:main
|
|
||||||
|
|
||||||
[Build]
|
|
||||||
directory=build/x86
|
|
||||||
installer_name=${PRODUCT_NAME}_${PRODUCT_VERSION}-x86.exe
|
|
||||||
# Custom Installer :
|
|
||||||
# Added Desktop shortcut, modified working directory, modified default install and utf-8...
|
|
||||||
nsi_template=Installer_Template.nsi
|
|
Reference in New Issue
Block a user