Version pré-prod
This commit is contained in:
BIN
convert.xlsm
Normal file
BIN
convert.xlsm
Normal file
Binary file not shown.
334
main.py
334
main.py
@@ -1,17 +1,22 @@
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
import shutil
|
||||
import time
|
||||
import tkinter
|
||||
from datetime import datetime
|
||||
|
||||
import tkinter.filedialog
|
||||
from tkinter import *
|
||||
from tkinter import messagebox
|
||||
from tkinter.ttk import Progressbar
|
||||
from tkinter.scrolledtext import ScrolledText
|
||||
from threading import *
|
||||
|
||||
from class_invoices import *
|
||||
|
||||
VERSION = 1.1
|
||||
VERSION = "20220304-1546"
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +24,173 @@ src_dir = os.getenv('APPDATA') + "\Attrib2Biz\src"
|
||||
dest_dir = os.getenv('APPDATA') + "\Attrib2Biz\output"
|
||||
file_path ="" #os.path.dirname(__file__)
|
||||
|
||||
code_debiteur = [
|
||||
{
|
||||
"ID": 100,
|
||||
"NAME": "Hôpital Riviera-Chablais Vaud-Valais - Fournisseurs "
|
||||
},
|
||||
{
|
||||
"ID": 101,
|
||||
"NAME": "Hôpital du Valais - Direction des Finances/Service des fournisseurs "
|
||||
},
|
||||
{
|
||||
"ID": 102,
|
||||
"NAME": "Clinique Bernoise Montana - Secrétariat médical "
|
||||
},
|
||||
{
|
||||
"ID": 103,
|
||||
"NAME": "Clinique Genevoise de Montana - Comptabilité "
|
||||
},
|
||||
{
|
||||
"ID": 104,
|
||||
"NAME": "Clinique SUVA - Comptabilité "
|
||||
},
|
||||
{
|
||||
"ID": 105,
|
||||
"NAME": "Fondation de Nant - Comptabilité "
|
||||
},
|
||||
{
|
||||
"ID": 106,
|
||||
"NAME": "Service de l'action sociale - Office de l'asile - Administration RAValais"
|
||||
},
|
||||
{
|
||||
"ID": 107,
|
||||
"NAME": "OCVS - Comptabilité"
|
||||
},
|
||||
{
|
||||
"ID": 108,
|
||||
"NAME": "Suva Aarau - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 109,
|
||||
"NAME": "Suva Basel - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 110,
|
||||
"NAME": "Suva Bellinzona - Assicurazione militare - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 111,
|
||||
"NAME": "Suva Bellinzona - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 112,
|
||||
"NAME": "Suva Bern - Militärversicherung - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 113,
|
||||
"NAME": "Suva Chur - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 114,
|
||||
"NAME": "Suva Delémont - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 115,
|
||||
"NAME": "Suva Fribourg - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 116,
|
||||
"NAME": "Suva Genčve - Assurance militaire - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 117,
|
||||
"NAME": "Suva Genčve - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 118,
|
||||
"NAME": "Suva La Chaux-de-Fonds - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 119,
|
||||
"NAME": "Suva Lausanne - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 120,
|
||||
"NAME": "Suva Luzern - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 121,
|
||||
"NAME": "Suva Sion - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 122,
|
||||
"NAME": "Suva Solothurn - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 123,
|
||||
"NAME": "Suva St-Gallen - Militärversicherung - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 124,
|
||||
"NAME": "Suva Zurich - Service Center"
|
||||
},
|
||||
{
|
||||
"ID": 125,
|
||||
"NAME": "Antaé - Allianz Worldwide Care"
|
||||
},
|
||||
{
|
||||
"ID": 126,
|
||||
"NAME": "Terre des Hommes - Soins aux Enfants "
|
||||
},
|
||||
{
|
||||
"ID": 127,
|
||||
"NAME": "Schweizerische Rettungsflugwacht (Rega) - Medizinischoperationnelle Dienstleistungszentrale"
|
||||
},
|
||||
{
|
||||
"ID": 128,
|
||||
"NAME": "Clinique Valmont - Comptabilité "
|
||||
},
|
||||
{
|
||||
"ID": 129,
|
||||
"NAME": "Clinique Lucernoise Montana - Comptabilité "
|
||||
},
|
||||
{
|
||||
"ID": 130,
|
||||
"NAME": "AAA Alpine Air Ambulance AG"
|
||||
},
|
||||
{
|
||||
"ID": 131,
|
||||
"NAME": "CHUV - coordination transferts de patients - ŕ l'att. de Monsieur Meylan - BH8, porte 104"
|
||||
},
|
||||
{
|
||||
"ID": 132,
|
||||
"NAME": "Clinique CIC Collombey SA - c/o Clinique CIC Suisse SA "
|
||||
},
|
||||
{
|
||||
"ID": 133,
|
||||
"NAME": "Clinique CIC Montreux SA "
|
||||
},
|
||||
{
|
||||
"ID": 134,
|
||||
"NAME": "Clinique CIC Saxon SA - c/o Clinique CIC Saxon SA "
|
||||
},
|
||||
{
|
||||
"ID": 135,
|
||||
"NAME": "Clinique CIC Suisse SA "
|
||||
},
|
||||
{
|
||||
"ID": 136,
|
||||
"NAME": "MedSTAR - Swiss Mobile Healthcare Alliance Sŕrl"
|
||||
},
|
||||
{
|
||||
"ID": 137,
|
||||
"NAME": "RFSM - Réseau fribourgeois de santé mentale "
|
||||
}
|
||||
]
|
||||
|
||||
def get_debitor_code(str):
|
||||
for obj in code_debiteur:
|
||||
try:
|
||||
if obj["NAME"] in str:
|
||||
#print(f"pass code débiteur {str}")
|
||||
return obj["ID"]
|
||||
except:
|
||||
print("error code_debiteur")
|
||||
|
||||
return 5
|
||||
|
||||
|
||||
Elements = []
|
||||
export_csv = "";
|
||||
con_csv = "";
|
||||
@@ -31,17 +203,45 @@ if not os.path.exists(dest_dir):
|
||||
os.makedirs(dest_dir)
|
||||
|
||||
|
||||
class TextHandler(logging.Handler):
|
||||
"""This class allows you to log to a Tkinter Text or ScrolledText widget"""
|
||||
def __init__(self, text):
|
||||
# run the regular Handler __init__
|
||||
logging.Handler.__init__(self)
|
||||
# Store a reference to the Text it will log to
|
||||
self.text = text
|
||||
|
||||
def emit(self, record):
|
||||
msg = self.format(record)
|
||||
print("pass 1 " + msg)
|
||||
def append():
|
||||
self.text.configure(state='normal')
|
||||
self.text.insert(tkinter.END, msg + '\n')
|
||||
self.text.configure(state='disabled')
|
||||
# Autoscroll to the bottom
|
||||
self.text.yview(tkinter.END)
|
||||
# This is necessary because we can't modify the Text from other threads
|
||||
self.text.after(0, append)
|
||||
|
||||
|
||||
class ClercAttrib2Biz():
|
||||
def __init__(self):
|
||||
self.count_facture = 0
|
||||
self.a_index = {"invoice": [], "intervention": [], "patient": [], "debtor": [], "articles": [], "global": []}
|
||||
self.index_counter = 0
|
||||
|
||||
self.a_listings = {}
|
||||
|
||||
|
||||
self.fenetre = Tk()
|
||||
|
||||
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.export_one_file.set(True)
|
||||
self.run_excel_after_export.set(True)
|
||||
|
||||
self.draw_mainWindows()
|
||||
|
||||
@@ -65,11 +265,12 @@ class ClercAttrib2Biz():
|
||||
|
||||
self.fenetre.iconbitmap("./logo_clerc_03X_icon.ico")
|
||||
self.fenetre.title("Clerc Attrib2Biz v" + str(VERSION))
|
||||
self.fenetre.resizable(True, False)
|
||||
self.fenetre.geometry("700x250")
|
||||
self.fenetre.resizable(True, True)
|
||||
self.fenetre.geometry("700x475")
|
||||
|
||||
self.fenetre.columnconfigure(0, weight=3)
|
||||
self.fenetre.columnconfigure(1, weight=1)
|
||||
self.fenetre.rowconfigure(3,weight=1)
|
||||
|
||||
|
||||
|
||||
@@ -114,7 +315,23 @@ class ClercAttrib2Biz():
|
||||
self.txt_progress.columnconfigure(0,weight=1)
|
||||
|
||||
self.progress_bar = Progressbar(self.txt_progress, orient=HORIZONTAL, mode='determinate')
|
||||
self.progress_bar.grid( sticky='WE')
|
||||
self.progress_bar.grid(sticky='WE')
|
||||
|
||||
|
||||
self.frame_logs = LabelFrame(self.fenetre, text="Log")
|
||||
self.frame_logs.grid(row=3, column=0, sticky='WENS', columnspan=2, padx=5, pady=5)
|
||||
self.frame_logs.columnconfigure(0, weight=1)
|
||||
self.frame_logs.rowconfigure(0, weight=1)
|
||||
|
||||
st = ScrolledText( self.frame_logs, state='disabled', height=10)
|
||||
st.grid(row=0, column=0, sticky="WENS", pady=5)
|
||||
|
||||
|
||||
text_handler = TextHandler(st)
|
||||
self.logger = logging.getLogger()
|
||||
self.logger.addHandler(text_handler)
|
||||
|
||||
|
||||
|
||||
|
||||
lbf_3 = LabelFrame(self.fenetre, text="Options")
|
||||
@@ -122,7 +339,11 @@ class ClercAttrib2Biz():
|
||||
|
||||
Checkbutton(lbf_3, text="Supprimer fichiers après conversion", variable= self.delete_after_parse, onvalue=True, offvalue=False).grid(row=0, sticky='W')
|
||||
Checkbutton(lbf_3, text="Export au format .biz", variable= self.export_format_biz, onvalue=True, offvalue=False).grid(row=1, sticky='W')
|
||||
Checkbutton(lbf_3, text="Export en 1 seul fichier", variable= self.export_one_file, onvalue=True, offvalue=False, state="disabled").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=2, 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=3, sticky='W')
|
||||
|
||||
|
||||
|
||||
|
||||
self.var_file_count = StringVar(self.fenetre)
|
||||
@@ -130,6 +351,13 @@ class ClercAttrib2Biz():
|
||||
|
||||
self.thread = Thread(target=self.start_parsing)
|
||||
|
||||
def refresh_ui(self):
|
||||
print("pass refresh UI")
|
||||
if self.export_one_file.get():
|
||||
self.cb_run['state'] = "active"
|
||||
else:
|
||||
self.cb_run['state'] = "disabled"
|
||||
self.run_excel_after_export.set(False)
|
||||
|
||||
|
||||
|
||||
@@ -138,6 +366,11 @@ class ClercAttrib2Biz():
|
||||
dir = src_dir
|
||||
self.count_facture = 0
|
||||
x = 0
|
||||
|
||||
if self.export_one_file.get() and os.path.exists(os.path.join(dest_dir, f"src.csv")):
|
||||
os.remove(os.path.join(dest_dir, f"src.csv"))
|
||||
|
||||
|
||||
for filename in os.listdir(dir):
|
||||
x += 1
|
||||
if ".json" in filename:
|
||||
@@ -155,6 +388,9 @@ class ClercAttrib2Biz():
|
||||
self.fenetre.update_idletasks()
|
||||
self.nb_facture_var.set(self.count_facture)
|
||||
|
||||
if self.run_excel_after_export.get():
|
||||
self.open_export_file()
|
||||
|
||||
|
||||
|
||||
def parseFile(self, data, filename):
|
||||
@@ -267,6 +503,7 @@ class ClercAttrib2Biz():
|
||||
|
||||
def convertFile(self, data, filename):
|
||||
self.count_facture += len(data["invoices"])
|
||||
self.a_listings["to_check"] = []
|
||||
|
||||
|
||||
|
||||
@@ -276,14 +513,58 @@ class ClercAttrib2Biz():
|
||||
data = cls_Invoice()
|
||||
data.parse_item(ele)
|
||||
|
||||
b_update_debitor = True
|
||||
|
||||
print()
|
||||
if data.Debtor["code"] != "1":
|
||||
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:
|
||||
if "name" in data.Debtor.keys():
|
||||
# print(f"{data.Patient['fip_number']} => {data.Debtor['name']}")
|
||||
data.data["comments"] = data.Debtor["code"] if data.Debtor["code"] != "2" else data.data["comments"]
|
||||
data.Debtor["code"] = get_debitor_code(data.Debtor["name"])
|
||||
break
|
||||
''' 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 patient: facture N°: {data.data['id']} / {data.Patient['fip_number']}")
|
||||
|
||||
|
||||
|
||||
b_HRF = False
|
||||
sHRF = ""
|
||||
for article in data.Articles:
|
||||
if "code" in article.keys():
|
||||
if article["code"] == "CLN.9431":
|
||||
if article["code"] == "HRF":
|
||||
b_HRF = True
|
||||
sHRF = article["line_1"].replace("h",":")
|
||||
print("pass HRF")
|
||||
print(f"pass HRF => {data.Patient['fip_number']}")
|
||||
break
|
||||
|
||||
|
||||
@@ -304,20 +585,22 @@ class ClercAttrib2Biz():
|
||||
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):
|
||||
csv_col.data.append("")
|
||||
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("pass Change end_time on 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"
|
||||
@@ -329,6 +612,10 @@ class ClercAttrib2Biz():
|
||||
self.addToIndexs(obj=csv_col, data=data.Patient[elem], cat="patient", key=elem)
|
||||
|
||||
for elem in data.Debtor:
|
||||
if "name" in data.Debtor.keys():
|
||||
#print(f"{data.Patient['fip_number']} => {data.Debtor['name']}")
|
||||
data.Debtor["code"] = get_debitor_code(data.Debtor["name"])
|
||||
|
||||
if elem != "name":
|
||||
csv_col.data.append(data.Debtor[elem])
|
||||
if "name" in data.Debtor.keys():
|
||||
@@ -341,10 +628,9 @@ class ClercAttrib2Biz():
|
||||
## Données prestations
|
||||
|
||||
if "code" in article.keys():
|
||||
if article["code"] == "CLN.9431":
|
||||
pass
|
||||
# csv_col = None
|
||||
# break
|
||||
if article["code"] == "HRF":
|
||||
csv_col = None
|
||||
break
|
||||
else:
|
||||
csv_col.data.append(article["code"])
|
||||
|
||||
@@ -378,12 +664,30 @@ class ClercAttrib2Biz():
|
||||
else:
|
||||
csv_col.data.append("")
|
||||
|
||||
|
||||
lines.append(csv_col.data)
|
||||
csv_col = None
|
||||
with open(os.path.join(dest_dir, f"bizexdoc_" + filename.replace(".json", "") + ".csv"), "w+", errors='replace',newline='') as csv_file:
|
||||
|
||||
|
||||
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):
|
||||
with open(os.path.join(dest_dir, f"src.csv"), "a+", errors='replace',newline='') as csv_file:
|
||||
wr = csv.writer(csv_file, delimiter=';')
|
||||
for cdr in lines:
|
||||
for cdr in lines:
|
||||
wr.writerow(cdr)
|
||||
def open_export_file(self):
|
||||
print("RUN EXCEL with open")
|
||||
os.startfile(os.path.join(dest_dir, f"src.csv"))
|
||||
shutil.copy(file_path + "convert.xlsm", os.path.join(dest_dir, f"convert.xlsm"))
|
||||
os.startfile(os.path.join(dest_dir, f"convert.xlsm"))
|
||||
|
||||
def open_src(self):
|
||||
os.startfile(file_path + src_dir)
|
||||
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user