Dory/dory_sort_out.py

305 lines
9.7 KiB
Python

"""
Sert a créer l'arborescence pour le dossier CNIG, renommer et ranger les .pdf
"""
import os
import re
import glob
import shutil
import unicodedata
from datetime import datetime
import openpyxl as xls
from openpyxl.styles import PatternFill
# Les noms de tous les dossier a créer
FOLDERNAMES = [
"0_Procedure",
"1_Rapport_de_presentation",
"2_PADD",
"3_Reglement",
"4_Annexes",
"5_Orientations_amenagement",
"6_POA",
"7_Plans_de_secteur",
]
ANNEXE_FOLDER_ID = 4
# Les mots clef associés à chaque dossier
KEYWORDS = {
"Jugement": FOLDERNAMES[0],
"Procedure": FOLDERNAMES[0],
"Rapport": FOLDERNAMES[1],
"PADD": FOLDERNAMES[2],
"Prescription": FOLDERNAMES[3],
"Reglement_graphique": FOLDERNAMES[3],
"Reglement": FOLDERNAMES[3],
"Orientations_amenagement": FOLDERNAMES[5],
"POA": FOLDERNAMES[6],
"Plan_de_secteur": FOLDERNAMES[7],
}
def confirm_choice(choice) -> bool:
"""
Demande confirmation du choix de l'utilisateur
"""
print(f"vous avez choisi {choice} est-ce correct ?")
answer = int(input("[1] - Oui \n[2] - Non \nReponse : "))
return answer == 1
def test_date(date_input: str):
"""teste si la date donnée est valide"""
# Pattern pour vérifier qu'il y a bien 8 chiffres, 4pour l'année, 2 pour le mois, 2 pour le jour
# permet d'exclure les erreurs de frappes, comme les "." les " " ou les lettres
pattern = r"^\d{4}\d{2}\d{2}$"
if re.match(pattern, date_input):
try:
datetime.strptime(date_input, "%Y%m%d")
return True
except ValueError:
print(
"Erreur dans le format de la date, veuillez la saisir comme suit AAAAMMJJ"
)
return False
else:
print("Erreur de frappe, la date ne noit contenir que 8 chiffres")
return False
def test_siren_insee(is_plu: bool, number: str):
"""teste si le numero Siren ou Insee donné est valide"""
if is_plu:
if len(number) == 5 and number.isdigit():
return True
print("Le numero INSEE est invalide")
return False
else:
if len(number) == 9 and number.isdigit():
return True
print("Le numero siren est invalide")
return False
def create_folders(is_plu: bool, prefixe, suffixe):
"""Crée l'arborescence"""
main_path = f"{prefixe}_PLU{"i" if not is_plu else ""}_{suffixe}"
try:
os.mkdir(main_path)
except FileExistsError:
print("Ce dossier suivant existe déjà : " + main_path)
return ""
os.mkdir(main_path + "/Donnees_geographiques")
os.mkdir(main_path + "/Pieces_ecrites")
main_path += "/Pieces_ecrites"
for folder_name in FOLDERNAMES:
try:
if (
not folder_name == "6_POA" and not folder_name == "7_Plans_de_secteur"
) or (
not is_plu
and (folder_name == "6_POA" or folder_name == "7_Plans_de_secteur")
):
os.mkdir(main_path + "/" + folder_name)
except FileExistsError:
print("Le dossier suivant existe déjà : " + folder_name)
return main_path
def correct_file_name(file):
"""
Corrige les erreurs de nomage des fichiers
espaces et tirets deviennent des underscore
"""
basename = os.path.basename(file)
correct_file = basename.replace(" ", "_").replace("-", "_")
# Supprime les accents et les convertis en minuscules
correct_file = "".join(
(c if unicodedata.category(c) != "Mn" else "")
for c in unicodedata.normalize("NFD", correct_file)
)
correct_file = os.path.join(os.path.dirname(file), correct_file)
os.rename(file, correct_file)
return correct_file
def sort_files(prefixe, suffixe, sort_path):
"""
Range les fichiers dans l'arborescence, selon des mots clefs
Renvoi un dictionaire avec tous les noms de fichiers trouvés et leur compte
"""
# cherche tous les fichiers pdf présents dans l'arborescence
# à partir du Current working directory,
# y compris ceux dans des dossiers
files = glob.glob(os.getcwd() + "/**/*.pdf", recursive=True)
# compte le nombre de fois mot clef apparait
keyword_count = {key: 0 for key in KEYWORDS}
folders_file_count = [0] * len(FOLDERNAMES)
for file in files:
no_keyword = True
# corrige les erreur de nommage de fichiers
file = correct_file_name(file)
for keyword, folder in KEYWORDS.items():
# Si le mot clef (en minuscule) est dans le nom du fichier (en minuscule)
if keyword.lower() in file.lower():
keyword_count[keyword] += 1
filename = keyword
if keyword_count[keyword] > 1:
# Le nouveau nom du fichier
filename += "_" + str(keyword_count[keyword] - 1)
# Le dossier de destination du fichier
new_path = sort_path + "/" + folder
# Le nouveau nom du fichier
renamed = os.path.join(
os.path.dirname(file),
prefixe + "_" + filename + "_" + suffixe + ".pdf",
)
folders_file_count[int(folder[0])] += 1
os.rename(file, renamed)
shutil.move(renamed, new_path)
no_keyword = False
break
# si aucun mot clef n'a été trouvé dans le nom du fichier,
# on l'envoi dans le dossier Annexes
if no_keyword:
# on s'assure que le nom commence par une majuscule
filename = os.path.splitext(os.path.basename(file))[0].capitalize()
# on ajoute le nom du fichier dans le dictionnaire
if not filename in keyword_count:
keyword_count.update({filename: 1})
else:
keyword_count[filename] += 1
filename += "_" + str(keyword_count[filename] - 1)
renamed = os.path.join(
os.path.dirname(file),
prefixe + "_" + filename + "_" + suffixe + ".pdf",
)
os.rename(file, renamed)
shutil.move(renamed, sort_path + "/" + FOLDERNAMES[ANNEXE_FOLDER_ID])
folders_file_count[ANNEXE_FOLDER_ID] += 1
return folders_file_count
# return True
def error_report(folder_data):
"""
Crée le rapport d'utilisation du script
"""
# Couleurs de cellules
error_color = PatternFill(patternType="solid", fgColor="00cb4335")
column_name_color = PatternFill(patternType="solid", fgColor="0085929e")
row_color = PatternFill(patternType="solid", fgColor="00ccd1d1")
report = xls.Workbook()
report_worsheet = report.active
# Nomme la worksheet et les colonnes du tableau
report_worsheet.title = "Compte rendu"
report_worsheet["B1"] = "Dossiers"
report_worsheet["C1"] = "NB Fichiers"
report_worsheet["D1"] = "Rapport d'erreur"
# Triple la largeur des colonnes pour plus de clarté
report_worsheet.column_dimensions["B"].width *= 3
report_worsheet.column_dimensions["C"].width *= 3
report_worsheet.column_dimensions["D"].width *= 3
# Applique la couleur de fond aux cellules titres de colonnes
report_worsheet["B1"].fill = report_worsheet["C1"].fill = report_worsheet[
"D1"
].fill = column_name_color
#on commence à la cellule 2
currrent_cell = 2
# Pour chaque dossiers
# On écrit son nom dans la colonne B
# On écris le nombre de fichier contenus dans la colonne C
# Si vide Erreur Colonne D
for i, content in enumerate(folder_data):
report_worsheet["B" + str(currrent_cell)] = FOLDERNAMES[i]
report_worsheet["C" + str(currrent_cell)] = content
# 1 ligne sur 2 change de couleur
if i % 2 == 0:
report_worsheet["B" + str(currrent_cell)].fill = report_worsheet[
"C" + str(currrent_cell)
].fill = report_worsheet["D" + str(currrent_cell)].fill = row_color
if content == 0:
report_worsheet["D" + str(currrent_cell)] = (
"/!\\ aucun fichier dans le dossier /!\\"
)
report_worsheet["D" + str(currrent_cell)].fill = error_color
currrent_cell += 1
report.save("Rapport.xlsx")
def sortout():
"""Classe le dossier voulu selon les donées renseignées par l'utilisateur"""
is_plu = True
# demande si c'est un PLU ou un PLUi tant que l'input ne correspond pas à ce que l'on attend
while True:
answer = int(
input("[1] - PLU \n[2] - PLUi \nQuel type de dossier est a étudier ? : ")
)
if answer > 2 or answer < 1:
print("erreur dans la saisie du choix")
# print("\033[A\033[K", end="") #supprime la dernière ligne
else:
is_plu = answer == 1
if confirm_choice("PLU" if answer == 1 else "PLUi"):
break
# On demande le numero INSEE ou SIREN tant que l'input est invalide
while True:
print(
(
"numero INSEE (Format 5 chiffres): "
if is_plu
else "numero siren (Format 9 chiffres): "
),
end="",
)
prefixe = input()
if test_siren_insee(is_plu, prefixe) and confirm_choice(prefixe):
break
# On demande la date d'approbation tant que l'input est invalide
while True:
print("Date d'approbation (Format AAAAMMJJ): ", end="")
suffixe = input()
if test_date(suffixe) and confirm_choice(suffixe):
break
main_path = create_folders(is_plu, prefixe, suffixe)
donnees_dossiers = sort_files(prefixe, suffixe, main_path)
error_report(donnees_dossiers)