
| Current Path : /home/cgabriel/20_dev/12_procpy/fibu/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //home/cgabriel/20_dev/12_procpy/fibu/sync.py |
# coding: utf8
import os,sys,re,glob,time,sqlite3,hashlib,time,base64,datetime,random
import procpy
import procpy.fibu
addpath = ".."
while len(addpath) < 30:
addpath
sys.path.append(addpath)
addpath = addpath + "/.."
import fibu
#******************************************************************************
class Sync (object):
def __init__ (self):
self.pythoncall = "python3"
try:
self.sortfkt = fibu.sortfkt
except:
self.sortfkt = None
try:
self.synchronized = fibu.synchronized
print("SYNCHRONIZED")
except:
self.synchronized = False
self.kontenrahmen = {}
try:
self.database_mode = fibu.db
except:
self.database_mode = ""
try:
for kto in fibu.kontenrahmen.split("\n"):
m = re.search(r"^(.*?) +(.*?) *$",kto)
if m:
self.kontenrahmen[m.group(1)] = m.group(2)
except:
pass
#******************************************************************************
def generate_db (self,database_file):
if self.database_mode == "file":
return(self.file_generate_db(database_file))
self.dbh = sqlite3.connect(database_file)
self.dbh.row_factory = sqlite3.Row
cursor = self.dbh.cursor()
self.pythoncall = "python3"
cursor.execute("create table if not exists buchungen " +
"(DATUM,BETRAG,KTOA,KTOB,REMARK,ID default '')")
try:
cursor.execute("create index DATUM_IDX on buchungen (DATUM)" )
cursor.execute("create index KTOA_IDX on buchungen (KTOA)" )
cursor.execute("create index KTOB_IDX on buchungen (KTOB)" )
self.database_empty = True
except Exception as e:
self.database_empty = False
#******************************************************************************
def file_generate_db (self,database_file):
if not os.path.isfile(database_file):
open(database_file,"w").write("")
self.dbh = database_file
#******************************************************************************
def mark (self,remark=""):
t = time.clock()
if 't0' in vars(self):
print ( ("%9.2f" % ((t-self.t0)*1000)) + " ms for: " + remark )
self.t0 = t
#******************************************************************************
def liqui (self,templatefile,ktofiles,jahr="2019"):
# 1. Einlesen der Kontenfiles
ktolist = {}
for ktofile in ktofiles:
print(ktofile)
ktotext = open(ktofile).read()
betraege = []
for zeile in ktotext.split("\n"):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if not m:
continue
betraege.append( [m.group(1),float(m.group(2)),m.group(3),m.group(4)] )
m = re.search(r"^(.*)[\\\/](.*)$","./"+ktofile)
ktolist[m.group(2)] = betraege
# 2. Die Zeile feststellen, aus der die Zeitraeume stammen
template = open(templatefile).read()
template = re.sub(r" JJJJ"," "+jahr,template,9999)
# template = re.sub(r"^(.*)\s*$","\\1",template,re.DOTALL)
# template = re.sub(r" *; *",";",template,99999999)
zeitraeume = []
text = []
gesamt = []
for zeile0 in template.split("\n"):
mode = ""
summe = ""
zeile = re.sub(r"; *$","",zeile0)
if len(zeitraeume) == 0:
text.append(zeile)
lastentry = None
entries = zeile.split(";")
for entry in entries:
erg = self.zeitraum(entry.strip())
if lastentry and not erg:
break
lastentry = erg
zeitraeume.append(entry.strip())
if not ( len(zeitraeume) == len(entries) and not lastentry == None):
zeitraeume = []
else:
# 3. Jetzt jede Zeile durchgehen
entries = zeile.split(";")
if len(entries) < 2:
text.append(zeile)
gesamt = []
continue
ktopattern = entries[0].strip()
ukto = ":-" + re.sub( r"_","-",entries[1].strip(),9999 )
summe = entries[3].strip()
# print(zeile,ukto+"|")
zaehler = -1
zeile1 = []
for entry in entries:
if entry.strip() == "Summe":
mode = "sum"
zaehler = zaehler + 1
try:
gesamt[zaehler]
except:
gesamt.append(0.00)
erg = None
if zaehler < len(zeitraeume) :
erg = self.zeitraum(zeitraeume[zaehler])
# print(zeile,erg,entry)
if erg:
entry1 = 0.00
startdatum = erg[0]
enddatum = erg[1]
buchungen = []
if mode == "sum":
entry1 = gesamt[zaehler]
else:
for ktofile in ktolist:
print(ktofile)
if ktopattern.lower() in ktofile.lower():
buchungen.append( ktolist[ktofile] )
if len(buchungen) == 0:
entry1 = entry
else:
if not len(buchungen) == 1:
print("Fehler!",len(buchungen)) # Ktofile ist nicht eindeutig
return()
buchungen = buchungen[0]
for buchungszeile in buchungen:
datum = buchungszeile[0]
betrag = buchungszeile[1]
ukto1 = ":" + buchungszeile[2]
ukto2 = ":" + buchungszeile[3]
if datum > enddatum:
break
if datum < startdatum and summe == "":
continue
if ukto in ukto1:
entry1 = entry1 + betrag
if ukto in ukto2:
entry1 = entry1 - betrag
gesamt[zaehler] = gesamt[zaehler] + entry1
format1 = "%" + str(len(entry)) + ".2f"
print("XX",entry1)
entry1 = format1 % entry1
else:
entry1 = entry
zeile1.append(entry1)
zeile2 = ";".join(zeile1)
text.append(zeile2)
text5 = ""
for zeile in text:
if not "#" in zeile:
text5 = text5 + zeile + "\n"
print(text5)
#******************************************************************************
def zeitraum (self,entry):
m = re.search(r"^(\d\d\d\d)(\d\d)$",entry)
if m:
return([entry+"00",entry+"99"])
m = re.search(r"^(\d\d\d\d)$",entry)
if m:
return([entry+"0000",entry+"9999"])
return(None)
#******************************************************************************
def sync3 (self,ktodirs0):
bezeichner = {}
print("")
self.mark("")
self.mark("A. Start sync")
ktodirs = []
for ktodir in ktodirs0:
if "EXCLUDE" in ktodir:
continue
ktodirs.append(re.sub(r"([^\\\/])$","\\1/",ktodir))
# return()
main_dir = self.common_string(ktodirs) # das tiefste uebergeordnete Directory ermitteln
db_status = 0
db_dir = re.sub(r"^(.*)[\\\/].*?$","\\1",main_dir) # das erste gemeinsam erreichbare Datenbankfile ermitteln
while (0 == 0):
db_file = glob.glob(db_dir+"/*.db")
if os.path.isfile(db_dir + "/fibu.py"): # auf der obersten Ebene auch suchen
db_file = db_file + glob.glob(db_dir+"/*.kto") # nach einem kto-file als Datenbank
print(db_file,db_dir)
if len(db_file) == 1:
if not self.database_mode == "file" and os.path.getsize(db_file[0]) < 50:
os.unlink(db_file[0])
db_file = None # [db_dir + "/__cache__.db"]
db_status = 1
main_dir = db_dir
print("DB",db_status)
# return()
break
if len(db_file) > 1:
fehler = "ERROR: dbfile in " + db_dir + " is ambiguous"
print(fehler)
return(fehler)
if os.path.isfile(db_dir + "/fibu.py"): # oberstes Directory erreicht
db_file = None # kein Datenbankfile
break
db_dir = os.path.abspath(db_dir+"/..")
print("DB_DIR",db_dir)
self.generated_in = None
# print("DB_DIR",db_dir)
if not db_file:
print(" ... no database found, so create it here ...")
db_dir = main_dir
db_file = [main_dir+"/__cache__.db"]
self.generated_in = db_dir
if db_dir in ktodirs:
ktodirs.remove(db_dir)
ktodirs.insert(0,db_dir)
self.generate_db(db_file[0])
self.mark("B. DB-File " + db_file[0])
ktolist = []
for dir in ktodirs: # jetzt die Kontoobjekte erzeugen
if not os.path.isdir(dir) or os.path.isfile(dir + "/fibu.py"):
continue
print(dir)
kto = procpy.fibu.kto.Kto() # jeweils ein Konto-Objekt daraus machen
kto.find_ukto_and_interval(dir) # aus dem Pfad die Konto-ID und das Gueltigkeitsintervall herauslesen
kto.rulenr = 0 # Anzahl der Runden, die das Konto durchlaeuft
kto.rule = glob.glob(dir+"/rule.py")
kto.dir = dir
kto.point = ""
if os.path.abspath(db_dir) == os.path.abspath(kto.dir):
if not os.path.isfile(db_dir + "/fibu.py"):
kto.point = "."
ktolist.append(kto)
# print(kto.point,kto.ukto)
# print(11,os.path.abspath(db_dir))
# print(22,os.path.abspath(kto.dir))
if self.generated_in == main_dir:
self.generated_in = kto
self.mark("C. Generate Kto objects")
for kto in ktolist:
ktofile = glob.glob(kto.dir+"/*.kto") # jetzt den jeweiligen Kontotext einlesen
if len(ktofile) == 1: # es darf hoechstens ein kto-File im Konto-Verzeichnis geben
kto.file = kto.dir + "/" + kto.filename + ".kto"
try:
ktotext = open(ktofile[0]).read()
except:
print(ktofile[0] + " could not be opened.")
if not ktofile[0] == kto.file:
os.rename(ktofile[0],kto.file)
elif len(ktofile) == 0:
kto.file = kto.dir + "/" + kto.filename + ".kto"
if not os.path.isdir(kto.dir):
os.mkdir(kto.dir)
open(kto.file,"w").write("NEWKTO\n")
ktotext = "NEWKTO\n"
else: # im Fehlerfall mit einer Fehlermeldung Funktion beenden
fehler = "ERROR: ktofile in " + kto.dir + " is ambiguous"
print(fehler)
return(fehler)
kto.parse_ktotext(ktotext,bezeichner) # wenn das so ist, den Kontotext ins Konto-Objekt einlesen
self.mark(" > " + os.path.relpath(kto.file,"."))
self.mark("D. Parse kto files")
if self.generated_in:
print("generated in: " + self.generated_in.ukto)
self.generated_in.import_to_db(self.dbh)
# self.generated_in.db0 = self.generated_in.db
for kto in ktolist:
kto.id_new = kto.kto_id(kto.dir)
m = re.search(r"^[^\n]+\(([A-Za-z0-9\_\+\-]{6})([A-Za-z0-9\_\+\-]{6})(\.?)\)",kto.ktotext)
kto.id = "xxxxxx"
if m and m.group(3) == "." and not kto == self.generated_in:
kto.db = kto.db_id ( kto.export_from_db(self.dbh) )
m = None
continue
if m:
kto.id = m.group(1) # der abgespeicherte Kto-Hash
if self.generated_in == kto:
kto.db = kto.db_id ( kto.export_from_db(self.dbh) )
else:
kto.db = m.group(2) # der Kto-Hash des Parents
continue
if kto.ktotext[0:6] == "NEWKTO":
kto.id = kto.id_new
kto.db = "yyyyyy"
continue
buchungen = kto.export_from_db(self.dbh) # Kontoinhalt aus der Datenbank auslesen
kto.buchungen = buchungen
kto.db = kto.db_id(buchungen)
# print("A",m,kto.ukto,kto.id,kto.db,"---",kto.id_new)
self.mark("E. Evaluate kto hashes")
fehlerliste = []
rounds = 0
while (0 == 0):
rounds = rounds + 1
print("\n\n*****************************\nROUND: " + ("%2u" % rounds) + "\n---------\n\n")
all_synced = True
for kto in ktolist:
if kto in fehlerliste:
continue
# print(kto.ukto,kto.rule)
buchungen = kto.export_from_db(self.dbh)
# print(buchungen)
# return()
kto.db_new = kto.db_id(buchungen)
print(kto.ukto,"---",kto.id,kto.db,"---",kto.id_new,kto.db_new)
if kto.db_new == kto.db and kto.id_new == kto.id:
continue
elif not kto.db_new == kto.db and kto.id_new == kto.id: # or self.synchronized:
print(" ... write " + kto.ukto + " from db")
kto.buchungen = buchungen
saldo = kto.write_ktotext(bezeichner,self.sortfkt) # Kontotext erzeugen
# print(kto.ukto,"KTOTEXT:",kto.ktotext)
kto.db = kto.db_new
kto.id = kto.kto_id(kto.dir)
open(kto.file,"w").write(
("%-40s" % kto.filename) + " (" + kto.id + kto.db_new + kto.point + ")" +
# " Saldo: " +
("%15.2f" % saldo) +
"\n\n" + kto.ktotext )
if os.path.isfile(kto.filename+".csv"):
open(kto.filename+".csv","w").write(kto.write_csv(kto.filename))
if len(kto.rule) == 1:
m = re.search(r"^(.*)[\\\/](.*)$","/"+kto.rule[0])
if m:
rule1 = m.group(2)
print(" ... run rule " + str(kto.rulenr) +" for " + kto.ukto)
os.system("chdir " + kto.dir + "; cd " + kto.dir + "; " +
self.pythoncall + " " + rule1 + " " + str(kto.rulenr) )
kto.rulenr = kto.rulenr + 1
text1 = open(kto.file).read() + "\n X"+str(random.randint(100000,999999))+"\n"
# the random string is appended to avoid that the rule can hang in a loop
# because it reproduces always the same faulty file
kto.parse_ktotext( text1, bezeichner )
kto.id_new = kto.kto_id(kto.dir)
all_synced = False
if not kto.id_new == kto.id: # gleich kto neu schreiben
kto.delete_from_db(self.dbh)
kto.import_to_db(self.dbh)
kto.db = "yyyyyy" #
kto.id = kto.id_new #
# return()
elif kto.db_new == kto.db and not kto.id_new == kto.id or self.synchronized:
print(" ... update db from " + kto.ukto)
kto.delete_from_db(self.dbh)
kto.parse_ktotext( open(kto.file).read(), bezeichner )
kto.import_to_db(self.dbh)
if not self.database_mode == "file":
self.dbh.commit()
kto.db = "yyyyyy"
kto.id = kto.id_new
all_synced = False
elif not kto.db_new == kto.db and not kto.id_new == kto.id:
fehler = "ERROR: Conflict in " + kto.dir
print(fehler)
fehlerliste.append(kto)
if not self.database_mode == "file":
self.dbh.commit()
self.mark("F"+str(rounds)+". Round " + str(rounds) + " finished.")
if all_synced:
print(" ... all accounts synced")
break
if not self.database_mode == "file":
self.dbh.commit()
self.mark("G. All accounts synced. DB Commit")
print("")
if db_status == 0:
os.unlink(main_dir+"/__cache__.db")
if os.path.isfile(main_dir+"/rounds"):
open(main_dir+"/rounds","w").write(str(rounds)+"\n")
return(fehlerliste)
#******************************************************************************
def sync7 (self,ktodirs0):
bezeichner = {}
print("")
self.mark("")
self.mark("A. Start sync")
ktodirs = []
for ktodir in ktodirs0:
if "EXCLUDE" in ktodir:
continue
ktodirs.append(re.sub(r"([^\\\/])$","\\1/",ktodir))
main_dir = self.common_string(ktodirs) # das tiefste uebergeordnete Directory ermitteln
db_status = 0
db_dir = re.sub(r"^(.*)[\\\/].*?$","\\1",main_dir) # das erste gemeinsam erreichbare Datenbankfile ermitteln
while (0 == 0):
db_file = glob.glob(db_dir+"/*.db")
if os.path.isfile(db_dir + "/fibu.py"): # auf der obersten Ebene auch suchen
db_file = db_file + glob.glob(db_dir+"/*.kto") # nach einem kto-file als Datenbank
# print(db_dir,db_file,len(db_file))
if len(db_file) == 1:
if os.path.getsize(db_file[0]) < 50:
os.unlink(db_file[0])
db_file = None
db_status = 1
break
if len(db_file) > 1:
fehler = "ERROR: dbfile in " + db_dir + " is ambiguous"
print(fehler)
return(fehler)
if os.path.isfile(db_dir + "/fibu.py"): # oberstes Directory erreicht
db_file = None # kein Datenbankfile
break
db_dir = os.path.abspath(db_dir+"/..")
print(db_dir)
self.generated_in = None
# print("DB_DIR",db_dir)
if not db_file:
print(" ... no database found, so create it here ...")
db_dir = main_dir
db_file = [main_dir+"/__cache__.db"]
self.generated_in = db_dir
if db_dir in ktodirs:
ktodirs.remove(db_dir)
ktodirs.insert(0,db_dir)
self.generate_db(db_file[0])
self.mark("B. DB-File " + db_file[0])
ktolist = []
for dir in ktodirs: # jetzt die Kontoobjekte erzeugen
if not os.path.isdir(dir) or os.path.isfile(dir + "/fibu.py"):
continue
print(dir)
kto = procpy.fibu.kto.Kto() # jeweils ein Konto-Objekt daraus machen
kto.find_ukto_and_interval(dir) # aus dem Pfad die Konto-ID und das Gueltigkeitsintervall herauslesen
kto.rulenr = 0 # Anzahl der Runden, die das Konto durchlaeuft
kto.rule = glob.glob(dir+"/rule.py")
kto.dir = dir
kto.point = ""
if os.path.abspath(db_dir) == os.path.abspath(kto.dir):
if not os.path.isfile(db_dir + "/fibu.py"):
kto.point = "."
ktolist.append(kto)
# print(kto.point,kto.ukto)
# print(11,os.path.abspath(db_dir))
# print(22,os.path.abspath(kto.dir))
if self.generated_in == main_dir:
self.generated_in = kto
self.mark("C. Generate Kto objects")
for kto in ktolist:
ktofile = glob.glob(kto.dir+"/*.kto") # jetzt den jeweiligen Kontotext einlesen
if len(ktofile) == 1: # es darf hoechstens ein kto-File im Konto-Verzeichnis geben
kto.file = kto.dir + "/" + kto.filename + ".kto"
try:
ktotext = open(ktofile[0]).read()
except:
print(ktofile[0] + " could not be opened.")
if not ktofile[0] == kto.file:
os.rename(ktofile[0],kto.file)
elif len(ktofile) == 0:
kto.file = kto.dir + "/" + kto.filename + ".kto"
if not os.path.isdir(kto.dir):
os.mkdir(kto.dir)
open(kto.file,"w").write("NEWKTO\n")
ktotext = "NEWKTO\n"
else: # im Fehlerfall mit einer Fehlermeldung Funktion beenden
fehler = "ERROR: ktofile in " + kto.dir + " is ambiguous"
print(fehler)
return(fehler)
kto.parse_ktotext(ktotext,bezeichner) # wenn das so ist, den Kontotext ins Konto-Objekt einlesen
self.mark(" > " + os.path.relpath(kto.file,"."))
self.mark("D. Parse kto files")
if self.generated_in:
print("generated in: " + self.generated_in.ukto)
self.generated_in.import_to_db(self.dbh)
# self.generated_in.db0 = self.generated_in.db
for kto in ktolist:
kto.id_new = kto.kto_id(kto.dir)
m = re.search(r"^[^\n]+\(([A-Za-z0-9\_\+\-]{6})([A-Za-z0-9\_\+\-]{6})(\.?)\)",kto.ktotext)
kto.id = "xxxxxx"
if m and m.group(3) == "." and not kto == self.generated_in:
kto.db = kto.db_id ( kto.export_from_db(self.dbh) )
m = None
continue
if m:
kto.id = m.group(1) # der abgespeicherte Kto-Hash
if self.generated_in == kto:
kto.db = kto.db_id ( kto.export_from_db(self.dbh) )
else:
kto.db = m.group(2) # der Kto-Hash des Parents
continue
if kto.ktotext[0:6] == "NEWKTO":
kto.id = kto.id_new
kto.db = "yyyyyy"
continue
buchungen = kto.export_from_db(self.dbh) # Kontoinhalt aus der Datenbank auslesen
kto.buchungen = buchungen
kto.db = kto.db_id(buchungen)
# print("A",m,kto.ukto,kto.id,kto.db,"---",kto.id_new)
self.mark("E. Evaluate kto hashes")
fehlerliste = []
rounds = 0
while (0 == 0):
rounds = rounds + 1
print("\n\n*****************************\nROUND: " + ("%2u" % rounds) + "\n---------\n\n")
all_synced = True
for kto in ktolist:
if kto in fehlerliste:
continue
# print(kto.ukto,kto.rule)
buchungen = kto.export_from_db(self.dbh)
# print(buchungen)
kto.db_new = kto.db_id(buchungen)
print(kto.ukto,"---",kto.id,kto.db,"---",kto.id_new,kto.db_new)
if kto.db_new == kto.db and kto.id_new == kto.id:
continue
elif not kto.db_new == kto.db and kto.id_new == kto.id: # or self.synchronized:
print(" ... write " + kto.ukto + " from db")
kto.buchungen = buchungen
saldo = kto.write_ktotext(bezeichner,self.sortfkt) # Kontotext erzeugen
# print(kto.ukto,"KTOTEXT:",kto.ktotext)
kto.db = kto.db_new
kto.id = kto.kto_id(kto.dir)
open(kto.file,"w").write(
("%-40s" % kto.filename) + " (" + kto.id + kto.db_new + kto.point + ")" +
# " Saldo: " +
("%15.2f" % saldo) +
"\n\n" + kto.ktotext )
if os.path.isfile(kto.filename+".csv"):
open(kto.filename+".csv","w").write(kto.write_csv(kto.filename))
if len(kto.rule) == 1:
m = re.search(r"^(.*)[\\\/](.*)$","/"+kto.rule[0])
if m:
rule1 = m.group(2)
print(" ... run rule " + str(kto.rulenr) +" for " + kto.ukto)
os.system("chdir " + kto.dir + "; cd " + kto.dir + "; " +
self.pythoncall + " " + rule1 + " " + str(kto.rulenr) )
kto.rulenr = kto.rulenr + 1
text1 = open(kto.file).read() + "\n X"+str(random.randint(100000,999999))+"\n"
# the random string is appended to avoid that the rule can hang in a loop
# because it reproduces always the same faulty file
kto.parse_ktotext( text1, bezeichner )
kto.id_new = kto.kto_id(kto.dir)
all_synced = False
if not kto.id_new == kto.id: # gleich kto neu schreiben
kto.delete_from_db(self.dbh)
kto.import_to_db(self.dbh)
kto.db = "yyyyyy" #
kto.id = kto.id_new #
elif kto.db_new == kto.db and not kto.id_new == kto.id or self.synchronized:
print(" ... update db from " + kto.ukto)
kto.delete_from_db(self.dbh)
kto.parse_ktotext( open(kto.file).read(), bezeichner )
kto.import_to_db(self.dbh)
self.dbh.commit()
kto.db = "yyyyyy"
kto.id = kto.id_new
all_synced = False
elif not kto.db_new == kto.db and not kto.id_new == kto.id:
fehler = "ERROR: Conflict in " + kto.dir
print(fehler)
fehlerliste.append(kto)
self.dbh.commit()
self.mark("F"+str(rounds)+". Round " + str(rounds) + " finished.")
if all_synced:
print(" ... all accounts synced")
break
self.dbh.commit()
self.mark("G. All accounts synced. DB Commit")
print("")
if db_status == 0:
os.unlink(main_dir+"/__cache__.db")
if os.path.isfile(main_dir+"/rounds"):
open(main_dir+"/rounds","w").write(str(rounds)+"\n")
return(fehlerliste)
#******************************************************************************
def common_string (self,elements):
main_el = elements[0]
for el in elements: # jetzt das tiefste uebergeordnete Directory ermitteln
main_el = main_el[0:len(el)]
el1 = el[0:len(main_el)]
while (0 == 0):
if el1 == main_el:
break
el1 = el1[:-1]
main_el = main_el[:-1]
return(main_el)
#******************************************************************************
def sort (self,pattern,file):
if pattern == "..":
self.sort_numbers(file)
return()
if pattern == "kto":
self.sort_numbers1(file)
return()
text = open(file).read()
text_match = []
text_rest = []
for zeile in text.split("\n"):
if re.search(pattern,zeile,re.IGNORECASE):
text_match.append(zeile)
else:
text_rest.append(zeile)
text = "\n".join(text_rest) + "\n" + "\n".join(text_match) + "\n"
if os.path.isfile(file+"~"):
os.unlink(file+"~")
# os.rename(file,file+"~")
open(file,"w").write(text)
#******************************************************************************
def sort_numbers (self,file):
text = open(file).read()
text_match = []
text_rest = []
for zeile in text.split("\n"):
m = re.search(r"\d\d\d\d\d\d\d\d +\-?(\d+\.\d\d) ",zeile)
if m:
text_match.append([zeile,float(m.group(1))])
else:
text_rest.append(zeile)
text_match.sort(key=lambda x:x[1])
text_match1 = []
for tt in text_match:
text_match1.append(tt[0])
text = "\n".join(text_rest) + "\n" + "\n".join(text_match1) + "\n"
if os.path.isfile(file+"~"):
os.unlink(file+"~")
# os.rename(file,file+"~")
open(file,"w").write(text)
#******************************************************************************
def sort_numbers1 (self,file):
text = open(file).read()
text_match = []
text_rest = []
for zeile in text.split("\n"):
m = re.search(r"(\d\d\d\d\d\d\d\d) +\-?(\d+\.\d\d) +(\d+?)\-(\S+?)\-(\S+) ",zeile)
if m:
text_match.append([zeile,m.group(5)])
else:
text_rest.append(zeile)
text_match.sort(key=lambda x:x[1])
text_match1 = []
for tt in text_match:
text_match1.append(tt[0])
text = "\n".join(text_rest) + "\n" + "\n".join(text_match1) + "\n"
if os.path.isfile(file+"~"):
os.unlink(file+"~")
# os.rename(file,file+"~")
open(file,"w").write(text)
#*************************************************************************************
def find_quittung (self,daydiff,file,pattern=""):
buchungen = []
text = []
text1 = []
ktotext = open(file).read()
for zeile in ktotext.split("\n"):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\-?\d+\.\d\d) +(\S+) +(\S+) +(\-?\d+\.\d\d) +(.*)",zeile)
if not m:
text.append(zeile)
continue
else:
datum = m.group(1)
betrag = m.group(2)
ktoa = m.group(3)
ktob = m.group(4)
remark = m.group(6)
buchungen.append([0,datum,betrag,ktoa,ktob,remark,zeile])
day0 = datetime.datetime.strptime("19700101","%Y%m%d")
try:
day = datetime.datetime.strptime(datum,"%Y%m%d")
except:
day = datetime.datetime.strptime(datum[0:6]+"28","%Y%m%d")
buchungen[-1][0] = (day-day0).days
while (0 == 0):
if buchungen[-1][0] - buchungen[0][0] < int(daydiff):
break
text.append(buchungen.pop(0)[-1])
'''
if abs(float(buchung[2])) == abs(float(buchungen[-1][2])):
buchung1 = buchung
buchung2 = buchungen[-1]
common_kto1 = ""
common_kto2 = ""
m1 = re.search("("+pattern+")",buchung1[-1])
if m1:
common_kto1 = m1.group(1)
m2 = re.search("("+pattern+")",buchung2[-1])
if m2:
common_kto2 = m2.group(1)
print(common_kto1,common_kto2)
print(buchung1[-1])
print(buchung2[-1])
if not common_kto1 == common_kto2: # matching!
text1.append("")
if pattern in buchung2[-1]:
buchung0 = buchung1
buchung1 = buchung2
buchung2 = buchung0
betrag1 = buchung1[2]
ktoa1 = buchung1[3]
ktob1 = buchung1[4]
if not betrag1[0] == "-":
betrag1 = "-" + betrag1
ktox = ktoa1
ktoa1 = ktob1
ktob1 = ktox
betrag2 = buchung1[2]
ktoa2 = buchung1[3]
ktob2 = buchung1[4]
if not betrag2[0] == "-":
betrag2 = "-" + betrag2
ktox = ktoa2
ktoa2 = ktob2
ktob2 = ktox
if ktob1 == standard_kto:
ktob1 = ktob2
if ktob2 == standard_kto:
ktob2 = ktob1
ktob2 = ktoa1
zeile1 = buchung1[1] + " " + betrag1 + " " + ktoa1 + " " + ktob1 + " 0.00 " + buchung1[5]
zeile2 = buchung2[1] + " " + betrag2 + " " + ktoa2 + " " + ktob2 + " 0.00 " + buchung2[5]
text1.append(zeile1)
text1.append(zeile2)
'''
standard_kto = "-13-9999"
for buchung in buchungen[:-1]:
if abs(float(buchung[2])) == abs(float(buchungen[-1][2])):
buchung1 = buchung
buchung2 = buchungen[-1]
common_kto1 = ""
common_kto2 = ""
m1 = re.search("("+pattern+")",buchung1[-1])
if m1:
common_kto1 = m.group(1)
m2 = re.search("("+pattern+")",buchung2[-1])
if m2:
common_kto2 = m.group(1)
if not common_kto1 == common_kto2:
text1.append("")
if pattern in buchung2[-1]:
buchung0 = buchung1
buchung1 = buchung2
buchung2 = buchung0
betrag1 = buchung1[2]
ktoa1 = buchung1[3]
ktob1 = buchung1[4]
if not betrag1[0] == "-":
betrag1 = "-" + betrag1
ktox = ktoa1
ktoa1 = ktob1
ktob1 = ktox
betrag2 = buchung2[2]
ktoa2 = buchung2[3]
ktob2 = buchung2[4]
if not betrag2[0] == "-":
betrag2 = "-" + betrag2
ktox = ktoa2
ktoa2 = ktob2
ktob2 = ktox
if ktob1 == standard_kto:
ktob1 = ktob2
if ktob2 == standard_kto:
ktob2 = ktob1
ktob2 = re.sub("QUIT","ZAHL",ktoa1)
zeile1 = buchung1[1] + " " + betrag1 + " " + ktoa1 + " " + ktob1 + " 0.00 " + buchung1[5]
zeile2 = buchung2[1] + " " + betrag2 + " " + ktoa2 + " " + ktob2 + " 0.00 " + buchung2[5]
if ktoa1 == ktob1 or ktoa2 == ktob2:
text1.append(buchung1[-1])
text1.append(buchung2[-1])
else:
text1.append("# " + buchung1[-1])
text1.append("# " + buchung2[-1])
text1.append(zeile1)
text1.append(zeile2)
else:
text.append(buchung1[-1])
text.append(buchung2[-1])
buchungen.pop()
buchungen.remove(buchung)
break
for buchung in buchungen:
text.append(buchung[-1])
ktotext = "\n".join(text) + "\n" + "\n".join(text1) + "\n"
open(file,"w").write(ktotext)
#*************************************************************************************
def find_vergleich (self,ktotext1,ktotext2):
buchungen1 = []
for zeile in ktotext1.split("\n"):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if m:
buchungen1.append([m.group(1),m.group(5),zeile])
for zeile in ktotext2.split("\n"):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if m:
vergleichsbuchung = buchungen1.pop(0)
if not vergleichsbuchung[1] == m.group(5):
print(zeile)
return(0)