Compare commits

..

34 Commits

Author SHA1 Message Date
Ambulance Clerc
e4c075f6ef Ajout de la comparaison de l'adresse de livraison 2023-06-16 16:17:10 +02:00
Ambulance Clerc
f05a56bc5a Ajout de la comparaison de l'adresse de livraison 2023-06-16 16:16:49 +02:00
Ambulance Clerc
b19340e149 Changement de version 2023-04-26 11:14:47 +02:00
Ambulance Clerc
d313ddefac Changement du message de log, lors des comparaisons d'adresse 2023-04-26 11:14:08 +02:00
Ambulance Clerc
f3d94d330c Supression des options depreciate avec adaptation du code
Ajout de la persistance des otpions
2023-04-26 11:03:20 +02:00
Ambulance Clerc
c198410cd3 Ajout dans les log après chaque popup d'adresse 2023-04-25 16:37:06 +02:00
Ambulance Clerc
48353c6f98 Débug comparaison date 2023-04-25 14:07:43 +02:00
Ambulance Clerc
a94b2cc0d6 Changement sur la comparaison d'adresse. 2023-04-25 13:55:42 +02:00
Ambulance Clerc
9ba8998c32 Debug load config with outfile 2023-04-21 07:57:00 +02:00
Ambulance Clerc
513556f0a3 Copie automatique et lecture du fichier adresses.dbf 2023-04-21 00:32:05 +02:00
Ambulance Clerc
81a9717716 Changement sur la comparaison d'adresse. 2023-04-20 22:23:26 +02:00
Ambulance Clerc
3ff3416b39 Changement sur la comparaison d'adresse. 2023-04-20 20:44:38 +02:00
Ambulance Clerc
e430117d40 Changement de la longueur de l'HUID de 15 à 10 en raison de bug Winbiz 2023-03-01 18:56:40 +01:00
Ambulance Clerc
5060490ac4 Ajout d'un script pour compter les caractères du projet 2023-03-01 18:55:34 +01:00
Ambulance Clerc
d4e5ff6f1b nettoyage du code débiteur 2023-01-24 16:12:08 +01:00
Ambulance Clerc
894a8bbfbb nettoyage du code débiteur 2023-01-24 15:47:51 +01:00
Ambulance Clerc
4d2e2f2351 supression de "(facturation)" 2023-01-24 15:10:03 +01:00
Ambulance Clerc
6f09de76ab Divers débug sur erreur de saisi lors d'un code débiteur 3 et si code débiteur pas encore connu 2023-01-03 16:18:16 +01:00
Ambulance Clerc
eee31f3a1d Ajout d'une captation de bug si débiteur n'existe pas. 2023-01-03 15:15:11 +01:00
Ambulance Clerc
bf1533ccdb Changement de version 2022-09-07 18:10:27 +02:00
Ambulance Clerc
36ce8a2488 Strip et replace \n en "" sur le numéro opale 2022-09-07 18:05:53 +02:00
Ambulance Clerc
891a29e39b Changement de version 2022-09-07 11:17:48 +02:00
Ambulance Clerc
2f9d8c1da8 Changement de version 2022-09-07 11:12:46 +02:00
Ambulance Clerc
191821d81d Changement de version 2022-09-02 15:13:13 +02:00
Ambulance Clerc
99a89585b5 Changement de version 2022-09-02 15:09:10 +02:00
Ambulance Clerc
e60ed4b5fa Arrêt critique si la saisi du débiteur est à nouveau faux 2022-09-02 15:08:37 +02:00
Ambulance Clerc
4c75a6167b Ajout d'un focus sur l'input dans popup de saisi 2022-09-02 14:57:58 +02:00
Ambulance Clerc
842ae5fb69 Adaptation du fonctionnement de la progessbar 2022-09-02 14:39:11 +02:00
Ambulance Clerc
355d17810f Débug génération nom du fichier d'export 2022-09-02 14:13:14 +02:00
Ambulance Clerc
510587d3eb Ajout du complément d'adresse dans le check adresse 2022-08-22 17:36:03 +02:00
Ambulance Clerc
ff22572e56 Ajout du complément d'adresse dans le check adresse 2022-08-22 17:35:46 +02:00
Ambulance Clerc
54873a2715 Print all debs et ajout barre de menu 2022-08-22 11:43:15 +02:00
Ambulance Clerc
1ce77f4e08 Débug des code débiteur saisi manuellement concidéré comme int à la place de str 2022-08-20 11:35:38 +02:00
Ambulance Clerc
7be1f15c63 Débug des code débiteur saisi manuellement concidéré comme int à la place de str 2022-08-20 11:30:17 +02:00
8 changed files with 301 additions and 309 deletions

View File

@@ -18,5 +18,7 @@ class cls_addresse:
firstName = None
birth = None
street = None
street_cpl = None
npa = None
city = None
city = None
addr_2 = None

View File

@@ -17,13 +17,23 @@ class cls_debitors:
shutil.copy("debitors_src.bin", os.path.join(self.file_path, f"debitors.bin"))
self.load_debitors()
def print_all_debs(self):
for elem in self.items:
print(f"Débiteur:{elem.code} {elem.names}")
def get_deb_by_code(self, code):
for deb in self.items:
if deb.code == int(code):
return deb
return None
def get_names_by_code(self, code):
default = []
if int(code) < 100:
return default
for deb in self.items:
if deb.code == int(code):
return deb.names
return None
return default
def is_in_debitor_name(self, code, search_name):
names = self.get_names_by_code(code)

16
counter.py Normal file
View File

@@ -0,0 +1,16 @@
import os
def count_chars_in_folder(folder_path):
total_chars = 0
for filename in os.listdir(folder_path):
filepath = os.path.join(folder_path, filename)
if os.path.isfile(filepath):
with open(filepath, 'r') as file:
content = file.read()
total_chars += len(content)
print(f"fichier {filepath} = { len(content)}")
return total_chars
folder_path = '.' # mettre le chemin absolu vers le dossier ici
total_chars = count_chars_in_folder(folder_path)
print(f"Le nombre total de caractères dans les fichiers du dossier {folder_path} est : {total_chars}")

View File

@@ -9,7 +9,10 @@ class Check_addresses_popup(Toplevel):
def __init__(self, parent, item_1=None, item_2=None, debitor=None, factureID=""):
super().__init__(parent)
self.geometry(f"700x300+{parent.winfo_x() + 25 }+{parent.winfo_y() +25 }")
if(item_1["complement"] is None):
item_1["complement"] = ""
self.geometry(f"700x450+{parent.winfo_x() + 25 }+{parent.winfo_y() +25 }")
self.resizable(True,True)
self.iconbitmap("./logo_clerc_03X_icon.ico")
self.title(f"Choix de l'adresse à conserver {item_1['fip_number']} / {factureID}. Code débiteur: {debitor['code']}")
@@ -23,6 +26,12 @@ class Check_addresses_popup(Toplevel):
lbf_old = LabelFrame(self, text="Données Winbiz")
lbf_old.grid(row=0, column=1, sticky='NSEW', padx=5, pady=5)
lbf_addr_2_new = LabelFrame(self, text="Livraison Attrib")
lbf_addr_2_new.grid(row=1, column=0, sticky='WE', padx=5, pady=5)
lbf_addr_2_old = LabelFrame(self, text="Livraison Winbiz")
lbf_addr_2_old.grid(row=1, column=1, sticky='NSEW', padx=5, pady=5)
str_address_1 = ""
fonts = []
@@ -32,15 +41,57 @@ class Check_addresses_popup(Toplevel):
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="Nom:", str1=item_1['lastname'], str2=item_2.lastName)
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="Prénom:", str1=item_1['firstname'], str2=item_2.firstName)
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="Date de naissance:", str1=datetime.strptime(item_1['birthdate'], "%Y-%m-%d").strftime("%d.%m.%Y"), str2=item_2.birth)
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="Adresse:", str1=f"{item_1['street']} {item_1['street_number']}", str2=item_2.street)
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="Adresse:", str1=f"{item_1['street'].strip()} {item_1['street_number'].strip()}", str2=item_2.street.strip())
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="Complément:", str1=f"{item_1['complement'].strip()}", str2=item_2.street_cpl.strip())
self.add_compares_element(new_frame=lbf_new, old_frame=lbf_old, label="NPA/Localité:", str1=f"{item_1['postal_code']} {item_1['city']}", str2=f"{item_2.npa} {item_2.city}")
con = ""
concat_str = ""
if "name" in debitor.keys():
if debitor["name"] is not None:
concat_str += con + debitor["name"]
#con = "#chr(13)##chr(10)#"
con = "\r\n"
if debitor["gender"] is not None:
concat_str += con + "Monsieur" if debitor["gender"] == "Masculin" else con + "Madame"
#con = "#chr(13)##chr(10)#"
con = "\r\n"
if debitor["lastname"] is not None:
concat_str += con + self.ifNotNull(debitor["lastname"]) + " " + self.ifNotNull(
debitor["firstname"])
#con = "#chr(13)##chr(10)#"
con = "\r\n"
if debitor["complement"] is not None:
concat_str += con + debitor["complement"]
#con = "#chr(13)##chr(10)#"
con = "\r\n"
if debitor["street"] is not None:
concat_str += con + self.ifNotNull(debitor["street"]) + " " + self.ifNotNull(
debitor["street_number"])
#con = "#chr(13)##chr(10)#"
con = "\r\n"
if debitor["city"] is not None:
concat_str += con + self.ifNotNull(debitor["postal_code"]) + " " + self.ifNotNull(
debitor["city"])
#con = "#chr(13)##chr(10)#"
con = "\r\n"
if debitor["country_name"] != "Suisse":
concat_str += con + debitor["country_name"]
#con = "#chr(13)##chr(10)#"
con = "\r\n"
self.add_compares_element(new_frame=lbf_addr_2_new, old_frame=lbf_addr_2_old, label="Adresse livraison:", str1=concat_str,
str2=self.ifNotNull(item_2.addr_2))
str_address_1 += item_1['insurance_policy_number'].replace('.', '')
str_address_1 += item_1['lastname'].strip()
str_address_1 += item_1['firstname'].strip()
str_address_1 += datetime.strptime(item_1['birthdate'], "%Y-%m-%d").strftime("%d.%m.%Y")
str_address_1 += f"{item_1['street']} {item_1['street_number']}"
str_address_1 += f"{item_1['street'].strip()} {item_1['street_number'].strip()}"
str_address_1 += f"{item_1['complement'].strip()}"
str_address_1 += f"{item_1['postal_code']} {item_1['city']}"
@@ -54,13 +105,14 @@ class Check_addresses_popup(Toplevel):
str_address_2 += item_2.firstName
str_address_2 += item_2.birth
str_address_2 += f"{item_2.street.strip()}"
str_address_2 += f"{item_2.street_cpl.strip()}"
str_address_2 += f"{item_2.npa} {item_2.city}"
self.listbox = Listbox(self, height=3, width=35)
self.listbox.grid(row=1,column=0, columnspan= 2, pady=15,padx=15, sticky='NSEW')
self.listbox.grid(row=2,column=0, columnspan= 2, pady=15,padx=15, sticky='NSEW')
self.btn = Button(self, text="Valider", command=self.select)
self.btn.grid(row=2,columnspan=2 , pady=10,padx=10, sticky='NSEW')
self.btn.grid(row=3,columnspan=2 , pady=10,padx=10, sticky='NSEW')
for (idd, info) in ((0, "Winbiz"), (1, "Attrib")) :
self.listbox.insert(END, info)
@@ -82,8 +134,10 @@ class Check_addresses_popup(Toplevel):
self.listbox.selection_set(1)
print(f"adresse différente [{str_address_1}] ({str_address_2})")
def ifNotNull(self, value, ret=""):
if value == None or value == "None":
return ret
return value.strip()
def add_compares_element(self,new_frame, old_frame,str1, str2, label):
label_font = font.Font(weight='bold', size=9)
@@ -94,10 +148,10 @@ class Check_addresses_popup(Toplevel):
value_color = "red"
con = "*"
Label(new_frame, text=label, font=label_font).grid(row=self.x_row, column=0, sticky="W")
Label(new_frame, text=con + str1 + con, fg=value_color).grid(row=self.x_row, column=1, sticky="W")
Label(old_frame, text=label, font=label_font).grid(row=self.x_row, column=0, sticky="W")
Label(old_frame, text=con + str2 + con, fg=value_color).grid(row=self.x_row, column=1, sticky="W")
Label(new_frame, text=str(label), font=label_font).grid(row=self.x_row, column=0, sticky="W")
Label(new_frame, text=con + str(str1) + con, fg=value_color).grid(row=self.x_row, column=1, sticky="W")
Label(old_frame, text=str(label), font=label_font).grid(row=self.x_row, column=0, sticky="W")
Label(old_frame, text=con + str(str2) + con, fg=value_color).grid(row=self.x_row, column=1, sticky="W")
self.x_row += 1
@@ -134,7 +188,7 @@ class Check_debitor_popup(Toplevel):
self.inp_code = StringVar()
self.inp_code.set(debitor['code'])
self.geometry(f"850x300+{parent.winfo_x() + 25 }+{parent.winfo_y() +25 }")
self.geometry(f"900x275+{parent.winfo_x() + 25 }+{parent.winfo_y() +25 }")
self.resizable(True,True)
self.iconbitmap("./logo_clerc_03X_icon.ico")
self.title(f"Incohérence sur les débiteurs {fip} / {factureID}. Code débiteur: {debitor['code']}")
@@ -142,8 +196,10 @@ class Check_debitor_popup(Toplevel):
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
Label(self,text="Une incohérence a été trouvée entre le code débiteur saisi dans Attrib et le code débiteur saisi dans Attrib. \nIls ne correspondent pas.Le code débiteur présent dans le champs Code Saisi sera utiliser pour la facture winbiz \nMerci de vérifier et modifier le code débiteur puis cliquer sur Valider.", wraplength= 950, justify=LEFT).grid(row=0,column=0, columnspan=2, sticky="W")
lbf_new = LabelFrame(self, text="Données Attrib")
lbf_new.grid(row=0, column=0, sticky='WE', padx=5, pady=5)
lbf_new.grid(row=1, column=0, sticky='WE', padx=5, pady=5)
label_font = font.Font(weight='bold', size=9)
Label(lbf_new, text="Code saisi", font=label_font).grid(row=0, column=0, sticky="W")
@@ -151,15 +207,15 @@ class Check_debitor_popup(Toplevel):
Label(lbf_new, text="Débiteur sélectionné", font=label_font).grid(row=1, column=0, sticky="W")
Label(lbf_new, text="Débiteur sélectionné dans Attrib", font=label_font).grid(row=1, column=0, sticky="W")
text_name = Text(lbf_new, fg="red", height=3,width= 30)
text_name.grid(row=1, column=1, sticky="W")
text_name.insert(END,debitor['name'])
text_name.configure(state='disabled')
lbf_old = LabelFrame(self, text="Nom possible")
lbf_old.grid(row=0, column=1, sticky='NSEW', padx=5, pady=5)
lbf_old = LabelFrame(self, text="Noms possibles")
lbf_old.grid(row=1, column=1, sticky='NSEW', padx=5, pady=5)
@@ -172,8 +228,12 @@ class Check_debitor_popup(Toplevel):
self.listbox.configure(state='disabled')
self.no_selection_possible = True
self.btn = Button(lbf_old, text="Ajouter", command=self.add)
self.btn.grid(row=2, column=0, columnspan= 2, pady=10, padx=10, sticky='NSEW')
menu_bar = Menu(self)
menu_param = Menu(menu_bar, tearoff=0)
menu_param.add_command(label="Ajouter à la liste", command=self.add)
menu_bar.add_cascade(label="Paramètre", menu=menu_param)
self.config(menu=menu_bar)
self.btn = Button(self, text="Valider", command=self.destroy)
self.btn.grid(row=2,column=0, columnspan= 2, pady=10,padx=10, sticky='NSEW')
@@ -223,7 +283,10 @@ class Input_popup(Toplevel):
label_font = font.Font(weight='bold', size=9)
Label(lbf_new, text="", font=label_font).grid(row=0, column=0, sticky="W")
Entry(lbf_new, textvariable=self.inp_value, width=100).grid(row=0, column=1, sticky="W", pady=10)
input_entry = Entry(lbf_new, textvariable=self.inp_value, width=100)
input_entry.grid(row=0, column=1, sticky="W", pady=10)
input_entry.focus()
self.after(0,input_entry.focus)
self.btn = Button(self, text="Valider", command=self.destroy)

View File

@@ -1 +1 @@
20220813-0700
20230616-1615

471
main.py
View File

@@ -1,4 +1,5 @@
import csv
import re
import json
import os
import logging
@@ -9,6 +10,7 @@ import time
import uuid
import tkinter
from datetime import datetime
import pickle
import tkinter.filedialog
from tkinter import *
@@ -17,6 +19,7 @@ from tkinter import messagebox
from tkinter.ttk import Progressbar
from tkinter.scrolledtext import ScrolledText
from threading import *
from dbfread import DBF
from class_invoices import *
from class_addresses import *
@@ -74,6 +77,7 @@ class ClercAttrib2Biz():
self.count_facture = 0
self.a_index = {"invoice": [], "intervention": [], "patient": [], "debtor": [], "articles": [], "global": []}
self.addresses = cls_Addresses()
self.o_debs = cls_debitors(filepath=temp_dir)
self.index_counter = 0
self.bs_counter = 70
@@ -86,22 +90,26 @@ class ClercAttrib2Biz():
self.prompt = None
self.b_prompt_open = False
self.config = {}
self.check_addresses = BooleanVar(self.fenetre)
self.delete_after_parse = BooleanVar(self.fenetre)
self.export_format_biz = BooleanVar(self.fenetre)
self.export_one_file = BooleanVar(self.fenetre)
self.run_excel_after_export = BooleanVar(self.fenetre)
self.winbiz_folder_path = StringVar(self.fenetre)
#Défault value for config
self.check_addresses.set(True)
self.export_one_file.set(True)
self.run_excel_after_export.set(False)
self.export_format_biz.set(True)
self.delete_after_parse.set(False)
self.winbiz_folder_path.set(temp_dir)
self.load_config()
self.draw_mainWindows()
self.refresh_ui()
self.read_addresses()
self.o_debs = cls_debitors(filepath=temp_dir)
self.timer = self.fenetre.after(1000, self.main_timer_fn)
@@ -114,10 +122,39 @@ class ClercAttrib2Biz():
def save_config(self, event=None):
self.config["cfg_check_adresses"] = self.check_addresses.get()
self.config["cfg_delete_after_parse"] = self.delete_after_parse.get()
self.config["cfg_export_one_file"] = self.export_one_file.get()
self.config["winbiz_folder_path"] = self.winbiz_folder_path.get()
with open(os.path.join(temp_dir,"config.dat"),"wb") as pickle_file:
pickle.dump(self.config,pickle_file, pickle.HIGHEST_PROTOCOL)
def load_config(self):
if not os.path.exists(os.path.join(temp_dir, "config.dat")):
self.save_config()
with open(os.path.join(temp_dir, "config.dat"), "rb") as pickle_file:
self.config = pickle.load(pickle_file)
self.check_addresses.set(self.read_config_element("cfg_check_adresses", True))
self.delete_after_parse.set(self.read_config_element("cfg_delete_after_parse", False))
self.export_one_file.set(self.read_config_element("cfg_export_one_file", True))
self.winbiz_folder_path.set(self.read_config_element("winbiz_folder_path", temp_dir))
def add_statistique(self, stat_name, stat_value):
a_stats = None
if "a_stats" in self.config:
a_stats = self.config[""]
def read_config_element(self,name, default):
val = self.config.get(name)
if val is not None:
return val
else:
return default
def main_timer_fn(self):
print("Pass tick timer main app")
#print("Pass tick timer main app")
self.timer = self.fenetre.after(5000, self.main_timer_fn)
self.nb_facture_var.set(self.count_facture)
@@ -202,12 +239,21 @@ class ClercAttrib2Biz():
lbf_3 = LabelFrame(self.fenetre, text="Options")
lbf_3.grid(row=0, column=1, rowspan=2, sticky='NSEW', padx=5, pady=5)
Checkbutton(lbf_3, text="Vérifier les Adresses", variable=self.check_addresses, onvalue=True, offvalue=False).grid(row=0, sticky='W')
Checkbutton(lbf_3, text="Supprimer fichiers après conversion", variable= self.delete_after_parse, onvalue=True, offvalue=False).grid(row=1, sticky='W')
Checkbutton(lbf_3, text="Export au format .biz", variable= self.export_format_biz, onvalue=True, offvalue=False, command=self.refresh_ui).grid(row=2, sticky='W')
Checkbutton(lbf_3, text="Export en 1 seul fichier", variable= self.export_one_file, onvalue=True, offvalue=False, command=self.refresh_ui).grid(row=3, sticky='W')
self.cb_run = Checkbutton(lbf_3, text="Lancer la conversion excel", variable=self.run_excel_after_export, onvalue=True, offvalue=False)
self.cb_run.grid(row=4, sticky='W')
Checkbutton(lbf_3, text="Vérifier les Adresses", variable=self.check_addresses, onvalue=True, offvalue=False, command=self.save_config).grid(row=0, sticky='W')
Checkbutton(lbf_3, text="Supprimer fichiers après conversion", variable= self.delete_after_parse, onvalue=True, offvalue=False, command=self.save_config).grid(row=1, sticky='W')
Checkbutton(lbf_3, text="Export en 1 seul fichier", variable=self.export_one_file, onvalue=True, offvalue=False,
command=self.save_config).grid(row=3, sticky='W')
textEntry = Entry(lbf_3, textvariable=self.winbiz_folder_path, validate="focusout", validatecommand=self.save_config)
textEntry.grid(row=5, sticky="WE", columnspan=3)
textEntry.bind("<KeyRelease>", self.save_config)
menu_bar = Menu(self.fenetre)
menu_param = Menu(menu_bar, tearoff=0)
menu_param.add_command(label="Affichage des débiteurs", command=self.o_debs.print_all_debs)
menu_bar.add_cascade(label="Paramètre", menu=menu_param)
self.fenetre.config(menu=menu_bar)
@@ -232,39 +278,34 @@ class ClercAttrib2Biz():
self.prompt.destroy()
self.b_prompt_open = False
def refresh_ui(self):
print("pass refresh UI")
if self.export_one_file.get() and not self.export_format_biz.get():
self.cb_run['state'] = "active"
else:
self.cb_run['state'] = "disabled"
self.run_excel_after_export.set(False)
if self.export_format_biz.get():
self.cb_run['state'] = "disabled"
self.run_excel_after_export.set(False)
def read_addresses(self):
file_addresses_path = os.path.join(dest_dir, f"adresses.txt")
if os.path.exists(os.path.join(self.winbiz_folder_path.get(),"adresses.dbf")):
shutil.copyfile(os.path.join(self.winbiz_folder_path.get(),"adresses.dbf"), os.path.join(temp_dir,"adresses.dbf"))
shutil.copyfile(os.path.join(self.winbiz_folder_path.get(), "adresses.FPT"),os.path.join(temp_dir, "adresses.FPT"))
else:
messagebox.showerror(title="Impossible d'ouvrir le fichier d'adresse existantes", message=f"Le fichier {self.winbiz_folder_path.get()} est introuvable. Aucune vérification des adresses possible")
file_addresses_path = os.path.join(temp_dir, f"adresses.dbf")
if os.path.exists(file_addresses_path):
file = open(file_addresses_path)
csvreader = csv.reader(file, delimiter=';')
rows = []
for row in csvreader:
rows.append(row)
for record in DBF(file_addresses_path, load=True):
o_addresse = cls_addresse()
o_addresse.AVS = row[5]
o_addresse.lastName = row[9]
o_addresse.firstName = row[10]
o_addresse.birth = row[38]
o_addresse.street = row[12]
o_addresse.npa = row[13]
o_addresse.city = row[15]
o_addresse.AVS = str(record["AD_CODE"])
o_addresse.lastName =str( record["AD_NOM"])
o_addresse.firstName = str(record["AD_PRENOM"])
if record["AD_NAISSAN"] is not None:
o_addresse.birth = datetime.strptime(str(record["AD_NAISSAN"]), "%Y-%m-%d").strftime("%d.%m.%Y")
else:
o_addresse.birth = ""
o_addresse.street =str( record["AD_RUE_2"])
o_addresse.street_cpl =str( record["AD_RUE_1"])
o_addresse.npa =str( record["AD_NPA"])
o_addresse.city = str(record["AD_VILLE"])
o_addresse.addr_2 = str(record["AD_ADR2"])
self.addresses.add_addresse(o_addresse)
file.close()
logging.warning(f"Chargement du fichier adresses.dbf terminé ! {len(self.addresses.items)} adresses trouvées ")
else:
messagebox.showwarning(title="Impossible d'ouvrir le fichier d'adresse existantes", message=f"Le fichier {file_addresses_path} est introuvable. Aucune vérification des adresses possible")
@@ -275,28 +316,19 @@ class ClercAttrib2Biz():
self.count_facture = 0
x = 0
self.export_filename = f"bizexdoc_export_Attrib_v{datetime.now().year}{datetime.now().month}{datetime.now().month}{datetime.now().hour}{datetime.now().minute}.csv"
self.export_filename = f"bizexdoc_export_Attrib_v{datetime.now().year}{datetime.now().month}{datetime.now().day}{datetime.now().hour}{datetime.now().minute}.csv"
if self.export_format_biz:
if self.export_one_file.get() and os.path.exists(os.path.join(dest_dir, self.export_filename)):
try:
os.remove(os.path.join(dest_dir, self.export_filename))
except:
messagebox.showerror(title="Erreur fichier déjà ouvert", message=f"Le fichier {self.export_filename} est déjà ouvert. Veuillez le fermer et recommencer")
return
if self.export_one_file.get() and os.path.exists(os.path.join(dest_dir, self.export_filename)):
try:
os.remove(os.path.join(dest_dir, self.export_filename))
except:
messagebox.showerror(title="Erreur fichier déjà ouvert", message=f"Le fichier {self.export_filename} est déjà ouvert. Veuillez le fermer et recommencer")
return
print(f"remove {self.export_filename} => {os.path.join(dest_dir, self.export_filename)}")
else:
if self.export_one_file.get() and os.path.exists(os.path.join(dest_dir, f"src.csv")):
try:
os.remove(os.path.join(dest_dir, f"src.csv"))
except:
messagebox.showerror(title="Erreur fichier déjà ouvert", message=f"Le fichier src.csv est déjà ouvert. Veuillez le fermer et recommencer")
return
print(f"remove src.csv => {os.path.join(dest_dir, 'src.csv')}")
print(f"remove {self.export_filename} => {os.path.join(dest_dir, self.export_filename)}")
self.progress_bar["value"] = 0
for filename in os.listdir(dir):
x += 1
if ".json" in filename:
@@ -304,18 +336,20 @@ class ClercAttrib2Biz():
with open(dir + "/" + filename, encoding="utf-8") as f:
data = json.load(f)
if self.export_format_biz.get():
self.parseFile(data, filename)
else:
self.convertFile(data, filename)
if self.delete_after_parse.get():
os.remove(dir + "/" + filename)
bRet = self.parseFile(data, filename)
if bRet:
messagebox.showinfo(title="Fin de conversion",
message="La conversion s'est terminée avec succès")
self.progress_bar["value"] = x / len(os.listdir(dir)) * 100
self.fenetre.update_idletasks()
self.nb_facture_var.set(self.count_facture)
if self.run_excel_after_export.get():
self.open_export_file()
if self.delete_after_parse.get():
os.remove(dir + "/" + filename)
def ifNotNull(self,value, ret=""):
if value == None:
@@ -335,6 +369,16 @@ class ClercAttrib2Biz():
data.Debtor["firstname"] = data.Debtor["firstname"].strip()
if data.Debtor["street"] is not None:
data.Debtor["street"] = data.Debtor["street"].strip()
if data.data["comments"] is not None:
data.data["comments"] = data.data["comments"].strip().replace("\n",'')
if data.Debtor["code"] is not None:
data.Debtor["code"] = data.Debtor["code"].strip()
data.Debtor["code"] = re.sub(r'[^0-9]', '', data.Debtor["code"])
if "name" in data.Debtor.keys() and data.Debtor["name"] is not None:
data.Debtor["name"] = data.Debtor["name"].replace("(facturation)","")
data.Debtor["name"] = data.Debtor["name"].strip()
def check_code_validity(self, code,data):
ret = True
@@ -363,7 +407,8 @@ class ClercAttrib2Biz():
return False
if datetime.strptime(new['birthdate'], "%Y-%m-%d").strftime("%d.%m.%Y") != old.birth:
return False
if f"{new['street']} {new['street_number']}" != old.street:
if f"{new['street'].strip()} {new['street_number'].strip()}" != f"{old.street.strip()}":
print(f"({new['street'].strip()} {new['street_number'].strip()}) != [" + old.street.strip()+"]")
return False
if f"{new['postal_code']} {new['city']}" != f"{old.npa} {old.city}":
return False
@@ -372,6 +417,7 @@ class ClercAttrib2Biz():
def parseFile(self, data, filename):
self.progress_bar["value"] = 0
self.index_counter += 1
lines = []
self.count_facture += len(data["invoices"])
@@ -383,32 +429,41 @@ class ClercAttrib2Biz():
csv_col.data[5] = f""
lines.append(csv_col.data)
cur_invoice_index = 0
x = 70
for ele in data["invoices"]:
cur_invoice_index += 1
self.progress_bar["value"] = cur_invoice_index / self.count_facture * 100
b_address_update = True
data = cls_Invoice()
data.parse_item(ele)
self.trim_all_data(data)
print(f"Code débiteur => {data.data['id']}: {data.Debtor['code']}")
if data.Debtor["code"] is None or '.' in str(data.Debtor["code"]):
if data.Debtor["code"] is None or '.' in data.Debtor["code"]:
print("ERROR code débiteur #1")
messagebox.showerror(title="Erreur code débiteur", message=f"Le code débiteur de la facture {data.data['id']} est faux: [{data.Debtor['code']}], merci de le corriger ")
inp_popup = Input_popup(self.fenetre, default=data.Debtor["code"], factureID=data.data['id'], fip=data.Patient['fip_number'])
data.Debtor["code"] = int(inp_popup.show())
data.Debtor["code"] = str(inp_popup.show())
if data.Debtor["code"] is None or '.' in data.Debtor["code"]:
messagebox.showerror(title="Erreur Critique",
message=f"Les informations de la factures [{data.data['id']}] comportes trop d'erreur arrêt du processus ")
return False
if data.Debtor["code"] == 1:
if int(data.Debtor["code"]) == 1:
if not self.check_code_validity(data.Debtor["code"],data):
messagebox.showerror(title="Erreur Critique",
message=f"Les informations de la factures [{data.data['id']}] comportes trop d'erreur arrêt du processus ")
return False
if int(data.Debtor["code"]) != "1" and data.Debtor["code"] != None and int(data.Debtor["code"]) < 100:
if data.Debtor["code"] != "1" and data.Debtor["code"] != None and int(data.Debtor["code"]) < 100:
if data.Patient["fip_number"] not in self.a_listings["to_check"]:
self.a_listings["to_check"].append(data.Patient["fip_number"])
self.logger.warning(f"Vérifier facture N°: {data.data['id']} / {data.Patient['fip_number']} {data.Debtor['code']} {data.Debtor['lastname']} {data.Debtor['firstname']}")
#self.logger.warning(f"Vérifier facture N°: {data.data['id']} / {data.Patient['fip_number']} {data.Debtor['code']} {data.Debtor['lastname']} {data.Debtor['firstname']}")
for elem in data.Debtor:
pass
@@ -429,24 +484,61 @@ class ClercAttrib2Biz():
self.logger.warn(f"Débiteur établissement facture N°: {data.data['id']} / {data.Patient['fip_number']} {data.Debtor['name']}")
'''
if int(data.Debtor["code"]) == 1 and data.Patient["lastname"] + data.Patient["firstname"] != data.Debtor["lastname"] + data.Debtor["firstname"]:
self.a_listings["to_check"].append(data.Patient["fip_number"])
print(data.Patient["complement"])
self.logger.warning(f"Débiteur différents: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
if int(data.Debtor["code"]) == 1:
b_check_debitor = False
if data.Debtor["lastname"] == None:
b_check_debitor = True
data.Debtor["lastname"] = ""
messagebox.showerror(title="Erreur",
message=f"Le débiteur n'a pas de nom, vérifier la facture ATTRIB et vérifier le code débiteur: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
if data.Debtor["firstname"] == None:
b_check_debitor = True
data.Debtor["firstname"] = ""
messagebox.showerror(title="Erreur",
message=f"Le débiteur n'a pas de prénom, vérifier la facture ATTRIB et vérifier le code débiteur: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
if b_check_debitor:
debitor_popup = Check_debitor_popup(self.fenetre, data.Debtor,
self.o_debs.get_names_by_code(data.Debtor['code']),
data.data['id'],
data.Patient['fip_number'], object=self.o_debs)
data.Debtor["code"] = debitor_popup.show()
if data.Patient["lastname"] + data.Patient["firstname"] != data.Debtor["lastname"] + data.Debtor["firstname"]:
self.a_listings["to_check"].append(data.Patient["fip_number"])
print(data.Patient["complement"])
self.logger.warning(f"Débiteur différents: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
if int(data.Debtor["code"]) >= 100:
if "name" not in data.Debtor.keys():
data.Debtor["name"] = "Invalide"
self.logger.warning(
f"Débiteur > 100 sans nom, vérifier la facture ATTRIB et vérifier le code débiteur: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
messagebox.showerror(title="Erreur",
message=f"Débiteur > 100 sans nom de débiteur ou d'établissement, vérifier la facture ATTRIB et vérifier le code débiteur: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
self.a_listings["to_check"].append(data.Patient["fip_number"])
if not self.o_debs.is_in_debitor_name(code=data.Debtor["code"],search_name=data.Debtor["name"]):
#messagebox.showerror(title="Erreur code débiteur erroné", message=f"Information débiteur incohérente: facture N°: {data.data['id']} / {data.Patient['fip_number']}.\nCode débiteur: {data.Debtor['code']}\nNom du débiteur: {data.Debtor['name']}. \nAurait dû être: {self.o_debs.get_names_by_code(data.Debtor['code'])}")
debitor_popup = Check_debitor_popup(self.fenetre,data.Debtor,self.o_debs.get_names_by_code(data.Debtor['code']),data.data['id'],data.Patient['fip_number'], object=self.o_debs)
data.Debtor["code"] = int(debitor_popup.show())
data.Debtor["code"] = debitor_popup.show()
if data.Debtor["code"] is None or '.' in data.Debtor["code"]:
messagebox.showerror(title="Erreur Critique",
message=f"Les informations de la factures [{data.data['id']}] comportes trop d'erreur arrêt du processus ")
return False
if data.Patient["complement"] != None:
'''
Désactivé, plus utile
if data.Patient["complement"] != None :
self.a_listings["to_check"].append(data.Patient["fip_number"])
print(data.Patient["complement"])
self.logger.warning(f"Complément patient: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
'''
if data.Patient['insurance_policy_number'] == None:
data.Patient['insurance_policy_number'] = f"{uuid.uuid4()}"[:15]
@@ -454,8 +546,12 @@ class ClercAttrib2Biz():
if self.check_addresses.get():
addresses_exist = self.addresses.get_item_by_AVS(data.Patient['insurance_policy_number'].replace(".", ""))
if addresses_exist is not None and not self.compare_old_and_new_adresses(new=data.Patient, old=addresses_exist):
popup = Check_addresses_popup(self.fenetre, item_1=data.Patient, item_2=addresses_exist, debitor=data.Debtor, factureID=data.data['id'])
b_address_update = popup.show()
mode_selected = "Attrib" if b_address_update else "Winbiz"
self.logger.warning(
f"Adresse connue donnée [{mode_selected}] conservé: : {data.data['id']} / {data.Patient['fip_number']} {data.Debtor['code']} {data.Debtor['lastname']} {data.Debtor['firstname']}")
print(f"Result Popup: {b_address_update}")
else:
b_address_update = True
@@ -603,7 +699,7 @@ class ClercAttrib2Biz():
csv_col.data[40] = datetime.strptime(data.Patient["birthdate"], "%Y-%m-%d").strftime("%d.%m.%Y")
else:
csv_col.data[40] = ""
messagebox.showerror(title="Erreur date de naissance", message=f"La date de naissance de la facture {data.data['id']} est faux: [{data.Patient['birthdate']}], merci de le corriger ")
messagebox.showerror(title="Erreur date de naissance", message=f"La date de naissance de la facture {data.data['id']} ({data.Patient['lastname']}) est faux: [{data.Patient['birthdate']}], merci de le corriger ")
csv_col.data[48] = 0
@@ -685,7 +781,10 @@ class ClercAttrib2Biz():
csv_col.data[116] = self.ifNotNull(data.Patient["category"]) + " - " + self.ifNotNull(data.Intervention["type"])
csv_col.data[118] = data.Intervention["kilometers"]
csv_col.data[135] = data.Intervention["base_name"]
csv_col.data[136] = 3 if data.Debtor["code"] != "101" else "EBILL" #code présentation de facture
if data.Debtor["code"] == "100" or data.Debtor["code"] == "101":
csv_col.data[136] = "EBILL" #code présentation de facture
else:
csv_col.data[136] = 3 #code présentation de facture
csv_col.data[146] = 3 #Code méthode de payement définit à 3
csv_col.data[168] = 1 if data.Intervention["team_name"] == "Planification" else 2
csv_col.data[169] = data.Patient['insurance_policy_number']
@@ -699,6 +798,9 @@ class ClercAttrib2Biz():
wr.writerow(cdr)
else:
self.save_file(lines,fileName=self.export_filename)
return True
def addToIndexs(self,obj,data,cat, key):
#self.a_index[cat].append({"key":key,"index":len(obj.data)})
if key not in self.a_index[cat]:
@@ -706,207 +808,6 @@ class ClercAttrib2Biz():
self.a_index["global"].append(key)
obj.data.append(data)
def convertFile(self, data, filename): #à utiliser pour un export avec fichier excel de Thomas
self.count_facture += len(data["invoices"])
self.a_listings["to_check"] = []
lines = []
for ele in data["invoices"]:
data = cls_Invoice()
data.parse_item(ele)
b_update_debitor = True
print(f"Code débiteur => {data.data['id']}: {data.Debtor['code']}" )
if data.Debtor["code"] == "None" or '.' in str(data.Debtor["code"]):
print("ERROR code débiteur")
messagebox.showerror(title="Erreur code débiteur", message=f"Le code débiteur de la facture {data.data['id']} est faux: [{data.Debtor['code']}], merci de le corriger ")
inp_popup = Input_popup(self.fenetre,default=data.Debtor["code"],factureID=data.data['id'], fip=data.Patient['fip_number'])
data.Debtor["code"] = str(inp_popup.show())
if data.Debtor["code"] != "1" and data.Debtor["code"] != None and int(data.Debtor["code"]) < 100:
if data.Patient["fip_number"] not in self.a_listings["to_check"] :
self.a_listings["to_check"].append(data.Patient["fip_number"])
self.logger.warning(f"Vérifier facture N°: {data.data['id']} / {data.Patient['fip_number']} {data.Debtor['code']} {data.Debtor['lastname']} {data.Debtor['firstname']}")
for elem in data.Debtor:
pass
''' TODO activer ce code quand les débiteur auront un bon numéro
try:
if int(data.Debtor["code"]) > 100:
print("code débiteur > 100 => no update data")
b_update_debitor = False
except:
messagebox.showerror(title="Erreur de code débiteur", message=f"il y a une erreur dans le code débiteur, il faut le vérifier. \n(n'est pas un chiffre) {data.Patient['fip_number']}")
exit()
'''
'''
if data.Debtor["type"] == "Établissement":
self.a_listings["to_check"].append(data.Patient["fip_number"])
print(data.Patient["complement"])
self.logger.warn(f"Débiteur établissement facture N°: {data.data['id']} / {data.Patient['fip_number']} {data.Debtor['name']}")
'''
if data.Debtor["code"] == 1 and data.Patient["lastname"] + data.Patient["firstname"] != data.Debtor["lastname"] + data.Debtor["firstname"]:
self.a_listings["to_check"].append(data.Patient["fip_number"])
print(data.Patient["complement"])
self.logger.warning(f"Débiteur différents: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
if data.Patient["complement"] != None :
self.a_listings["to_check"].append(data.Patient["fip_number"])
print(data.Patient["complement"])
self.logger.warning(f"Complément 22 patient: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
if data.Patient['insurance_policy_number'] == None:
data.Patient['insurance_policy_number'] = f"{uuid.uuid4()}"[:15]
b_HRF = False
sHRF = ""
for article in data.Articles:
if "code" in article.keys():
if article["code"] == "HRF":
b_HRF = True
sHRF = article["line_1"].replace("h",":")
print(f"pass HRF => {data.Patient['fip_number']}")
break
for article in data.Articles:
csv_col = cls_Col(False)
pass_article = False
##Donnée globales
self.addToIndexs(obj=csv_col,data=data.data["id"],cat="invoice",key="ID")
self.addToIndexs(obj=csv_col,data=data.data["date"],cat="invoice",key="date") # Date du document
self.addToIndexs(obj=csv_col, data=data.data["total_price"], cat="invoice", key="total_price")
self.addToIndexs(obj=csv_col, data=data.data["comments"], cat="invoice", key="comments")
whitout_transport = False
for elem in data.Intervention:
if elem == "without_transportation":
whitout_transport = True
print(f"without_transportation {data.Patient['fip_number']}")
break
self.addToIndexs(obj=csv_col, data=data.Intervention[elem], cat="intervention", key=elem)
if whitout_transport:
for x in range(8):
pass
#csv_col.data.append("")
self.addToIndexs(obj=csv_col, data="", cat="intervention", key=x)
self.addToIndexs(obj=csv_col, data=whitout_transport, cat="intervention", key="whitout_transport")
if b_HRF:
print(f"pass Change end_time on b_HRF")
dt = datetime.fromisoformat(csv_col.data[self.a_index["global"].index("end_time")])
month = "0" + str(dt.month) if dt.month < 10 else dt.month
csv_col.data[self.a_index["global"].index("end_time")] = f"{dt.year}-{month}-{dt.day}T"+sHRF+":00+01:00"
print( csv_col.data[self.a_index["global"].index("end_time")])
for elem in data.Patient:
if elem == "lastname":
if data.Patient[elem] == None:
data.Patient[elem] = "Patient inconnu"
if elem == "street_number":
print(f"ADRESS: data.Patient[elem]")
if data.Patient[elem] != None and "-" in data.Patient[elem] and "\t" not in data.Patient[elem]:
data.Patient[elem] = f"\t{data.Patient[elem]}"
print(f"ERROR DEBUG ADRESS: { data.Patient[elem]}")
self.addToIndexs(obj=csv_col, data=data.Patient[elem], cat="patient", key=elem)
for elem in data.Debtor:
if "name" in data.Debtor.keys():
pass
if elem == "street_number":
if data.Patient[elem] != None and "-" in data.Patient[elem] and "\t" not in data.Patient[elem]:
data.Patient[elem] = f"\t{data.Patient[elem]}"
if elem != "name":
csv_col.data.append(data.Debtor[elem])
if "name" in data.Debtor.keys():
csv_col.data.append(data.Debtor["name"])
else:
csv_col.data.append("")
# csv_col.data[126] = ' '.join(filter(None,temp_data)) # Débiteur nom
## Données prestations
if "code" in article.keys():
if article["code"] == "HRF":
csv_col = None
break
else:
csv_col.data.append(article["code"])
else:
csv_col.data.append("")
csv_col.data.append(article["line_1"])
csv_col.data.append(article["line_2"])
if "quantity" in article.keys():
csv_col.data.append(article["quantity"])
else:
csv_col.data.append("")
if "unit_price" in article.keys():
csv_col.data.append(article["unit_price"])
else:
csv_col.data.append("")
if "unit" in article.keys():
csv_col.data.append(article["unit"])
else:
csv_col.data.append("")
if "price" in article.keys():
csv_col.data.append(article["price"])
else:
csv_col.data.append("")
lines.append(csv_col.data)
csv_col = None
if not self.export_one_file.get():
with open(os.path.join(dest_dir, f"bizexdoc_" + filename.replace(".json", "") + ".csv"), "w+", errors='replace', newline='') as csv_file:
wr = csv.writer(csv_file, delimiter=';')
for cdr in lines:
wr.writerow(cdr)
else:
self.save_file(lines)
def save_file(self,lines, fileName = "src.csv"):
with open(os.path.join(dest_dir, fileName), "a+", errors='replace',newline='') as csv_file:
wr = csv.writer(csv_file, delimiter=';')

Binary file not shown.

View File

@@ -1 +1 @@
VERSION = "20220813-0700"
VERSION = "20230616-1615"