Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
029f0c1396 | |||
e19a9b5820 | |||
7513a2d2fb | |||
dcb4caacc6 | |||
bb7d96e5e0 | |||
32300d81e4 | |||
cf625f5398 | |||
5cf50a04dd | |||
ad2c7de563 | |||
9ab362fd29 | |||
5d76b1f584 | |||
a1beec5cd1 | |||
f3f86c43a6 | |||
1dffdbeecd | |||
a500e22678 | |||
3dbb48d7fc | |||
d651a4973a | |||
0ce5ed334c | |||
d5c4ee5997 | |||
56ea8c83bc |
6
.gitignore
vendored
6
.gitignore
vendored
@ -5,4 +5,8 @@ Clients_IFPass_backup.csv
|
||||
IFPass.conf
|
||||
Templates/IFPass_PDF_Template.pdf
|
||||
Templates/IFPass_PNG_Template.png
|
||||
build
|
||||
build/x86/*
|
||||
build/x64/*
|
||||
# Except builds:
|
||||
!build/x86/*x86.exe
|
||||
!build/x64/*x64.exe
|
||||
|
266
IFPass.py
266
IFPass.py
@ -15,6 +15,7 @@ from pywinauto.findwindows import find_window
|
||||
from pywinauto.win32functions import SetForegroundWindow
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from PyPDF2 import PdfFileReader, PdfFileWriter
|
||||
import fitz # = PyMuPDF : To convert pdf to png
|
||||
import subprocess
|
||||
from shutil import copyfile, move
|
||||
from pyfiglet import Figlet
|
||||
@ -22,7 +23,7 @@ from colorama import init
|
||||
from termcolor import colored
|
||||
|
||||
|
||||
version = '2.5' # dev/devnocam
|
||||
version = '3.0-1' # dev/devnocam
|
||||
|
||||
configdir = os.path.join(os.getenv('PROGRAMDATA'), 'IFPass')
|
||||
config = os.path.join(configdir, 'IFPass.conf')
|
||||
@ -85,7 +86,13 @@ def initialisation():
|
||||
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":
|
||||
firstname = input("Prénom : ").strip()
|
||||
if len(firstname) == 0:
|
||||
@ -102,21 +109,29 @@ def get_fullname():
|
||||
pos = firstname.find(" ")
|
||||
firstname = firstname[:pos + 1] + firstname[pos + 1].upper() + \
|
||||
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":
|
||||
surname = input("Nom : ").upper().strip()
|
||||
surname = input("Nom : ").strip()
|
||||
if len(surname) == 0:
|
||||
os.system('cls')
|
||||
print(colored("\nLe Nom ne peut pas être vide.", 'red'))
|
||||
else:
|
||||
break
|
||||
surname = surname.upper()
|
||||
docteur = yes_or_no('Est-ce un Docteur ?')
|
||||
if docteur:
|
||||
titre = 'Dr.'
|
||||
fullname = titre + ' ' + surname + ' ' + firstname
|
||||
titrename = titre + ' ' + surname
|
||||
else:
|
||||
titre = ''
|
||||
fullname = surname + ' ' + firstname
|
||||
return titre, firstname, surname, fullname
|
||||
titrename = surname
|
||||
return titre, firstname, surname, titrename
|
||||
|
||||
|
||||
def yes_or_no(question):
|
||||
@ -137,7 +152,6 @@ def getclientID():
|
||||
else:
|
||||
clientID = str(int(lastID) + 1).zfill(10)
|
||||
|
||||
writeindb(clientID)
|
||||
return clientID
|
||||
|
||||
|
||||
@ -202,19 +216,38 @@ def getpic():
|
||||
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="")
|
||||
with open(clientsfile, 'a', newline='', encoding='utf-8') as csvfile:
|
||||
writer = csv.writer(csvfile, delimiter=';')
|
||||
writer.writerow([titre, firstname, surname, clientID, dateinsc, dateexp])
|
||||
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():
|
||||
copyfile(clientsfile, clientsbkpfile)
|
||||
|
||||
|
||||
def fillcard(barcode):
|
||||
def fillcard(clientID, titrename, firstname, dateexp, barcode, picture):
|
||||
print("Création de la carte avec les informations...", end='')
|
||||
try:
|
||||
im = Image.open(pngtemplate)
|
||||
@ -228,12 +261,13 @@ def fillcard(barcode):
|
||||
draw = ImageDraw.Draw(im)
|
||||
|
||||
# Name embedding :
|
||||
font = ImageFont.truetype(fonttemplate, 45)
|
||||
draw.text((401, 310), fullname, fill=(0, 0, 0), font=font)
|
||||
font = ImageFont.truetype(fonttemplate, 40)
|
||||
draw.text((401, 296), titrename, fill=(0, 0, 0), font=font)
|
||||
draw.text((401, 334), firstname, fill=(0, 0, 0), font=font)
|
||||
|
||||
# Date embedding :
|
||||
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 :
|
||||
font = ImageFont.truetype('arial.ttf', 30)
|
||||
@ -252,7 +286,7 @@ def fillcard(barcode):
|
||||
print(colored('[OK]', 'green'))
|
||||
|
||||
|
||||
def mergepdf():
|
||||
def mergepdf(clientID):
|
||||
cartefilename = os.path.join(imgdir, clientID + '.pdf')
|
||||
output = PdfFileWriter()
|
||||
|
||||
@ -277,10 +311,52 @@ def printcard(cartefilename):
|
||||
subprocess.Popen('"' + AcrobatReader + '"' + ' /h /n /t ' + cartefilename + ' ' + printername, shell=False)
|
||||
|
||||
|
||||
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:
|
||||
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':
|
||||
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():
|
||||
with open(clientsfile, 'r', newline='', encoding='utf-8') as csvfile:
|
||||
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...)
|
||||
research = input('Entrez une partie du nom, prénom, ou numéro de carte (ou flashez) : ').lower()
|
||||
os.system('cls')
|
||||
@ -312,6 +388,7 @@ def membersearch():
|
||||
print(colored('Choix invalide ! Veillez bien à sélectionner le numéro de la colonne "Choix"', 'red', attrs=['bold']))
|
||||
os.system('cls')
|
||||
|
||||
while 'Choix incorect':
|
||||
print("Titre : ", colored(member[0], 'green'))
|
||||
print("Prénom : ", colored(member[1], 'green'))
|
||||
print("Nom : ", colored(member[2], 'green'))
|
||||
@ -327,12 +404,124 @@ def membersearch():
|
||||
elif diff == 0:
|
||||
print(colored("Il s'agit du dernier jour de l'abonnement, il expirera demain.", 'yellow', attrs=['bold']))
|
||||
|
||||
print('\n1 - Modifier', "2 - Renouveller l'abonnement", '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:
|
||||
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
|
||||
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():
|
||||
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":
|
||||
init() # Initialisation of colorama
|
||||
IFPassDBdir, printername, AcrobatReader, clientsfile, clientsbkpfile, imgdir, templatesdir, pdftemplate, pngtemplate, fonttemplate = initialisation()
|
||||
@ -343,57 +532,18 @@ def main():
|
||||
print('Version : ', version)
|
||||
if version in ('dev', 'devnocam'):
|
||||
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('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 : ')
|
||||
if choix == '1':
|
||||
while "the informations are incorrect": # Loop Filling informations
|
||||
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
|
||||
newmember()
|
||||
|
||||
elif choix == '2':
|
||||
os.system('cls')
|
||||
membersearch()
|
||||
os.system("pause")
|
||||
|
||||
elif choix == '3':
|
||||
elif choix == '0':
|
||||
sys.exit()
|
||||
|
||||
else:
|
||||
|
BIN
build/x64/IFPass_3.0-1-x64.exe
Normal file
BIN
build/x64/IFPass_3.0-1-x64.exe
Normal file
Binary file not shown.
BIN
build/x86/IFPass_3.0-1-x86.exe
Normal file
BIN
build/x86/IFPass_3.0-1-x86.exe
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
[Application]
|
||||
name=IFPass
|
||||
version=2.5
|
||||
version=3.0-1
|
||||
entry_point=IFPass:main
|
||||
icon=IF.ico
|
||||
console=true
|
||||
@ -16,17 +16,18 @@ bitness=64
|
||||
pypi_wheels=code128==0.3
|
||||
colorama==0.4.1
|
||||
pyfiglet==0.8.post1
|
||||
numpy==1.16.1
|
||||
numpy==1.16.2
|
||||
opencv-python==4.0.0.21
|
||||
Pillow==5.4.1
|
||||
pywin32==224
|
||||
six==1.12.0
|
||||
setuptools==40.7.3
|
||||
setuptools==40.8.0
|
||||
PyMuPDF==1.14.8
|
||||
pywinauto==0.6.6
|
||||
# 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
[Application]
|
||||
name=IFPass
|
||||
version=2.5
|
||||
version=3.0-1
|
||||
entry_point=IFPass:main
|
||||
icon=IF.ico
|
||||
console=true
|
||||
@ -16,17 +16,18 @@ bitness=32
|
||||
pypi_wheels=code128==0.3
|
||||
colorama==0.4.1
|
||||
pyfiglet==0.8.post1
|
||||
numpy==1.16.1
|
||||
numpy==1.16.2
|
||||
opencv-python==4.0.0.21
|
||||
Pillow==5.4.1
|
||||
pywin32==224
|
||||
six==1.12.0
|
||||
setuptools==40.7.3
|
||||
setuptools==40.8.0
|
||||
PyMuPDF==1.14.8
|
||||
pywinauto==0.6.6
|
||||
# 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
|
||||
|
Reference in New Issue
Block a user