
| Current Path : /home/ift/52_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/ift/52_procpy/fibu/account5.py |
# coding: utf8
import os,sys,re,glob,time,sqlite3,hashlib,time
#******************************************************************************
#class Account5 (object):
#
# def __init__ (self):
# self.mark()
#
# def read_kto (self):
#
# open("report.kto").read()
#******************************************************************************
class Kto (object):
def __init__ (self,ktodir):
self.ktodir = re.sub(r"[\\\/]+$","",ktodir)
ktofile = self.find_ktofile()
if ktofile:
self.text = open(ktofile).read()
else:
self.text = ""
self.db = None
self.read_hash_keys_from_ktodir(ktofile)
self.read_ukto_and_name_from_ktodir()
self.read_monatsfilter()
self.read_interval()
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 find_ktofile (self):
ktofiles = glob.glob(self.ktodir+"/report_*.kto")
if len(ktofiles) == 1:
return ktofiles[0]
elif len(ktofiles) == 0:
return ""
else:
return None
def read_hash_keys_from_ktodir (self,ktofile):
m = re.search(r"^(.*)\_([a-z0-9]{8})\_([a-z0-9]{8})\.kto$",ktofile)
if m:
self.old_db = m.group(2)
self.old_key = m.group(3)
else:
self.old_db = ""
self.old_key = ""
def read_ukto_and_name_from_ktodir (self):
self.name = ""
m = re.search(r"^(.*)[\\\/](.*)",self.ktodir)
if m:
self.ukto = m.group(2)
else:
self.ukto = ""
m = re.search(r"^(.*?)\_\_(.*)$",self.ukto)
if m:
self.name = m.group(2)
self.ukto = m.group(1)
if not self.ukto == "":
self.ukto = self.ukto + "-"
def read_monatsfilter (self):
m = re.search(r"^(.*)([123456789IJKLMNPS])\-$",self.ukto)
if m:
self.ukto = m.group(1)
self.with_startsaldo = False
self.monatsfilter = {
"1" : ["01"],
"2" : ["02"],
"3" : ["03"],
"4" : ["04"],
"5" : ["05"],
"6" : ["06"],
"7" : ["07"],
"8" : ["08"],
"9" : ["09"],
"A" : ["10"],
"B" : ["11"],
"C" : ["12"],
"I" : ["01","02","03"],
"J" : ["04","05","06"],
"K" : ["07","08","09"],
"L" : ["10","11","12"],
"M" : ["01","02","03","04","05","06"],
"N" : ["07","08","09","10","11","12"],
"P" : ["01","02","03","04","05","06","07","08","09","10","11","12"] } [ m.group(2) ]
else:
self.with_startsaldo = True
self.monatsfilter = ["01","02","03","04","05","06","07","08","09","10","11","12"]
def read_interval (self):
self.startdatum = "00000000"
self.enddatum = "99999999"
m = re.search(r"^(.*\-)(\d\d\d\d)\_(\d\d\d\d)-$",self.ukto)
if m:
self.ukto = m.group(1)
self.startdatum = ( m.group(1) + "0000" )[0:8]
self.enddatum = ( m.group(2) + "9999" )[0:8]
return
m = re.search(r"^(.*\-)(20\d\d)-$",self.ukto)
if m:
self.ukto = m.group(1)
self.startdatum = m.group(2) + self.monatsfilter[0] + "00"
self.enddatum = m.group(2) + self.monatsfilter[-1] + "99"
return
if re.search(r"^(.*\-)(20\d\d)(01|02|03|04|05|06|07|08|09|10|11|12)-$",self.ukto):
self.ukto = m.group(1)
self.startdatum = m.group(2) + m.group(3) + "00"
self.enddatum = m.group(2) + m.group(3) + "99"
return
def reset (self,parent):
self.parent = parent
self.new_key = self.compute_ktokey()
self.new_db = self.compute_dbkey(parent.db)
if self.old_key == "":
self.old_db = self.new_db
def sync_unterkonten (self):
self.connect_to_db()
kontenliste = []
for entry in glob.glob(self.ktodir+"/*"):
if os.path.isdir(entry):
unterkonto = Kto(entry)
unterkonto.reset(self)
kontenliste.append( unterkonto )
while (0 == 0):
konten_have_changed = False
for konto in kontenliste:
# print (konto)
change_of_kto = konto.fit_to_parent(self.db)
if change_of_kto:
konten_have_changed = True
if not konten_have_changed:
break
self.db.commit()
def show_keys (self):
ktofile = self.find_ktofile()
anzeige = ("%-25s" % (ktofile+","))
anzeige = anzeige + " KEY: " + self.new_key + " / " + ("%-8s" % self.old_key)
anzeige = anzeige + ", PARENT: " + self.old_db + " / " + ("%-8s" % self.new_db)
print (anzeige)
def fit_to_parent (self,db): # State machine
self.new_db = self.compute_dbkey(db)
self.new_key = self.compute_ktokey()
self.show_keys()
if not self.new_key == self.old_key and self.new_db == self.old_db:
print (124)
self.write_to_parent()
self.new_key = self.compute_ktokey()
self.old_key = self.new_key
self.parent.mark( ("%-20s"%(self.ukto[:-1]+",")) + "Buchungen imported to parent.")
return True
if self.new_key == self.old_key and not self.new_db == self.old_db:
print (125)
adjusted = self.get_from_parent()
self.write_new_ktofile()
self.new_key = self.compute_ktokey()
self.old_db = self.new_db
if not adjusted:
print("MARKADD")
self.add_to_ktofile("\n---\n")
self.parent.mark( ("%-20s"%(self.ukto[:-1]+",")) + "Buchungen refreshed from parent. Parent key: " + self.old_db)
return True
return self.apply_rule()
def apply_rule (self):
self.description_of_recent_action = "Rule applied."
return False
def write_to_parent (self):
buchungs_ids = []
cursor = self.parent.db.cursor()
self.delete_buchungen_from_parent(cursor)
for zeile in self.text.split("\n"):
self.insert_buchung_to_parent(cursor,zeile,buchungs_ids)
ktofile = self.find_ktofile()
ktofile_new = self.ktodir + "/report_"+self.new_db+"_"+self.new_key+".kto"
os.rename(ktofile,ktofile_new)
return True
def delete_buchungen_from_parent (self,cursor):
cursor.execute("delete from buchungen where (KTOA like '" +
self.ukto + "%' OR " + " KTOB like '" + self.ukto + "%') " +
" and DATUM >= '" + self.startdatum + "' and DATUM <= '" + self.enddatum + "' ")
def insert_buchung_to_parent (self,cursor,zeile,buchungs_ids):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if not m:
return
datum = m.group(1)
betrag = "%3.2f" % eval(m.group(2))
ktoa = self.compute_db_ktoname(m.group(3))
ktob = self.compute_db_ktoname(m.group(4))
remark = m.group(6)
if ktoa > ktob:
ktoa, ktob, betrag = self.switch_ktoa_ktob(ktoa,ktob,betrag)
buchungs_id = self.compute_buchungs_id(ktoa,ktob,betrag,remark,datum)
if not buchungs_id in buchungs_ids:
buchungs_ids.append(buchungs_id)
qstr = ("insert into buchungen (DATUM,BETRAG,KTOA,KTOB,REMARK) values ('" + datum + "'," +
betrag + ",'" + ktoa + "','" + ktob + "','" + re.sub(r"'","",remark,9999) + "')")
cursor.execute(qstr)
def compute_buchungs_id (self,ktoa,ktob,betrag,remark,datum):
buchungs_id = ",".join([ktoa,ktob,betrag,remark,datum])
return buchungs_id
def switch_ktoa_ktob (self,ktoa,ktob,betrag):
o = ktoa # Hin- und Herschwingen zu Endlos-Loops kommen
ktoa = ktob
ktob = o
betrag = "%3.2f" % (- float(betrag))
return ktoa, ktob, betrag
def compute_ukto_ktoname (self,ktox):
ktoy = re.sub(self.ukto,"",ktox)
if ktoy == ktox:
return(ktoy[:-1])
else:
return("-"+ktoy[:-1])
def compute_db_ktoname (self,ktox):
if ktox[0] == "-":
ktox = self.ukto + ktox[1:] + "-"
return ktox
def extract_to_ukto (self,ukto):
self.connect_to_db()
new_ukto = Kto(self.ktodir+"/"+ukto)
new_ukto.reset(self)
while (0 == 0):
konto_has_changed = new_ukto.fit_to_parent(self.db)
if not konto_has_changed:
break
self.db.commit()
def get_from_parent (self):
cursor = self.parent.db.cursor()
qstr = " select DATUM,BETRAG,KTOA,KTOB,REMARK from buchungen "
qstr = qstr + " where (KTOA like '" + self.ukto + "%' or KTOB like '" + self.ukto + "%')"
qstr = qstr + " and DATUM >= '" + self.startdatum + "' and DATUM <= '" + self.enddatum + "' "
qstr = qstr + " order by DATUM,BETRAG,KTOA,KTOB"
# print (qstr)
cursor.execute(qstr)
try:
maxa_old = self.maxa
maxb_old = self.maxb
except:
maxa_old = 10
maxb_old = 10
self.format_maxa = "%-" + str(maxa_old) + "s"
self.format_maxb = "%-" + str(maxb_old) + "s"
print ( self.format_maxa, self.format_maxb )
self.maxa = 0
self.maxb = 0
self.salden = {}
text_intern, text_extern = self.compute_intern_and_extern_buchungen(cursor)
text_salden = self.compute_salden()
self.kontotext = []
gesamt = 0.00
for buchung in text_extern:
betrag = buchung[1]
gesamt = "%13.2f" % ( float(gesamt) + float(betrag) )
buchungszeile = self.format_buchung(buchung,gesamt)
self.kontotext.append(buchungszeile)
self.kontotext.append("")
for saldo in text_salden:
self.kontotext.append(saldo)
self.kontotext.append("")
for buchung in text_intern:
buchungszeile = self.format_buchung(buchung," 0.00")
self.kontotext.append(buchungszeile)
if maxa_old == self.maxa and maxb_old == self.maxb:
return True
else:
return False
def write_new_ktofile (self):
ktofile = self.find_ktofile()
if ktofile:
os.unlink(ktofile)
ktofile_new = self.ktodir + "/report_"+self.new_db+"_"+self.new_key+".kto"
with open(ktofile_new,"w") as ktofilehandle:
ktofilehandle.write("\n".join(self.kontotext))
def add_to_ktofile (self,addtext):
ktofile = self.find_ktofile()
if ktofile:
with open(ktofile,"a") as ktofilehandle:
ktofilehandle.write(addtext)
def format_buchung (self,buchung,gesamt):
zeile = buchung[0] + " " + buchung[1] + " " + buchung[2] + " " +buchung[3] + " " + gesamt + " " + buchung[4]
return zeile
def compute_intern_and_extern_buchungen (self,cursor):
text_intern = []
text_extern = []
while (0 == 0):
entry = cursor.fetchone()
if not entry:
break
buchung, anzahl_der_internen_konten = self.compile_buchung(entry)
if anzahl_der_internen_konten == 1:
text_extern.append(buchung)
else:
text_intern.append(buchung)
text_intern.sort(key=lambda x:x[5])
text_extern.sort(key=lambda x:x[5])
return text_intern, text_extern
def compile_buchung (self,entry):
datum = entry[0]
betrag = float(entry[1])
ktoa = self.compute_ukto_ktoname(entry[2])
ktob = self.compute_ukto_ktoname(entry[3])
if re.search(r"^\d\d? +v\.?H\.? ",entry[4]): # USt-Einrueckung
remark = " " + entry[4]
else:
remark = entry[4]
if self.kto_is_extern(ktoa) and self.kto_is_intern(ktob):
ktoa, ktob, betrag = self.switch_ktoa_ktob(ktoa,ktob,betrag)
anzahl_der_internen_konten = 0
if self.kto_is_intern(ktoa):
self.salden_update(ktoa, float(betrag))
anzahl_der_internen_konten = anzahl_der_internen_konten + 1
if self.kto_is_intern(ktob):
self.salden_update(ktob,-float(betrag))
anzahl_der_internen_konten = anzahl_der_internen_konten + 1
self.maxa = max(len(ktoa),self.maxa)
self.maxb = max(len(ktoa),self.maxb)
sortidx = datum
buchung = [
datum,
("%13.2f" % betrag),
(self.format_maxa % ktoa),
(self.format_maxb % ktob),
remark,
sortidx
]
return buchung, anzahl_der_internen_konten
def compute_salden (self):
text_salden = []
saldenliste = list(self.salden.keys())
saldenliste.sort()
for unterkonto in saldenliste:
einrueckung = " " * len(re.sub(r"[^\-]","",unterkonto,9999))
text_salden.append(("%-35s" % unterkonto[1:]) + einrueckung + ("%13.2f" % self.salden[unterkonto]))
return(text_salden)
def salden_update (self,ktox,betrag):
if ktox == "-":
ktox = ""
if ktox in self.salden:
self.salden[ktox] = self.salden[ktox] + betrag
else:
self.salden[ktox] = betrag
m = re.search(r"^(.*)\-(.*)$",ktox)
if m:
self.salden_update(m.group(1),betrag)
def xxformat_kto (self):
text_intern = []
text_extern = []
while (0 == 0): # Zeilen des Kontos schreiben
if len(saldovortrag) > 0:
entry = [ ktodata['START'], saldovortrag[0], ktodata['UKTO1'], "-11-1805", "Saldovortrag"]
saldovortrag = []
else:
entry = cursor.fetchone()
if not entry:
break
if t == "":
if not "Saldovortrag" in entry[4] :
t = "___CONTAINS___BUCHUNGEN___"
betrag = float(entry[1])
ktoa = entry[2]
ktob = entry[3]
anz = 0
if ktoa[0:ul] == ukto1:
ktoa = ktoa[ul:]
# self.compute_salden(ktoa,betrag)
if ktoa == "":
ktoa = "-"
anz = anz + 1
else:
ktoa = ktoa[1:]
if ktob[0:ul] == ukto1:
ktob = ktob[ul:]
# self.compute_salden(ktob,-betrag)
if ktob == "":
ktob = "-"
if anz == 0:
o = ktoa
ktoa = ktob
ktob = o
betrag = -betrag
anz = anz + 1
else:
ktob = ktob[1:]
datum = entry[0]
# if datum == datum0 and betrag == betrag0 and abs(betrag) > 0.001:
# print ("WARNING:",datum,("%13.2f"%betrag))
datum0 = datum
betrag0 = betrag
remark = entry[4]
sortidx = datum
m = re.search(r"^(.*)? *\{\{SORTIDX\: +(.*?) *\}\} *(.*)$",remark) # proprietaeren Sort-Index herauslesen
if m:
remark = (m.group(1) + " " + m.group(3)).strip()
sortidx = sortidx + (m.group(2) + " "*40)[0:40]
sortidx = sortidx + self.rules.sortidx(ktoa)
m = re.search(r"^(\d\d? v\.?H\.? +.*\()(.*)\)",remark)
if m:
sortidx = sortidx + (m.group(2)+" "*40)[0:40] + "-Z"
else:
sortidx = sortidx + (re.sub(r"^(\+\-|\+\+)","",remark) + " "*40)[0:40] + "-A"
sortidx = sortidx + ktob
ktoa = re.sub("^"+ukto1,"",ktoa)
if ktoa == "":
ktoa = "-"
maxa = max(maxa,len(ktoa))
maxb = max(maxb,len(ktob))
buchung = datum + " " + ("%13.2f" % betrag) + " " + (maxa0 % ktoa) + " " + (maxb0 % ktob) + " "
sp = ""
if re.search(r"^\d\d? +v\.?H\.? ",entry[4]): # USt-Einrueckung
sp = " "
if anz == 1:
text_extern.append([buchung," " + sp + remark,betrag,sortidx])
else:
text_intern.append([buchung + " 0.00 " + sp + remark,"","",sortidx])
text_intern.sort(key=lambda x: x[3])
text_extern.sort(key=lambda x: x[3])
# self.mark("Start Salden")
fac = 1
for kto in ("KTOA","KTOB"):
qstr = " select " + kto + ",sum(BETRAG) from buchungen "
qstr = qstr + " where " + kto + " like '" + ktodata['UKTO1'] + "%'"
qstr = qstr + " and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' "
qstr = qstr + " group by (" + kto + ")"
cursor.execute(qstr)
while (0 == 0):
entry = cursor.fetchone()
if not entry:
break
ukto = entry[0][ul:]
betrag = float(entry[1])
while (0 == 0):
if not ukto in salden:
salden[ukto] = 0.00000001
salden[ukto] = salden[ukto] + fac * betrag
m = re.search(r"^(.*)\-(.*)$",ukto)
if m:
ukto = m.group(1)
else:
break
fac = -1
# self.mark("Ende Salden")
# print (salden)
ktoliste = [] # Kontenliste sortieren
for kto in salden.keys():
ktoliste.append([kto,self.rules.sortidx(re.sub(r"^-","",kto))])
ktoliste.sort(key=lambda x: x[1])
konten = []
text = []
gesamt = 0.00
for o in text_extern:
gesamt = gesamt + float(o[2])
text.append(o[0]+("%13.2f" % gesamt)+o[1])
text.append("")
for kto0 in ktoliste:
kto = kto0[0]
kto2 = re.sub(r"^\-","",kto)
sp = re.sub(r"[^\-]","",kto)
name = self.get_ktoname(ktodata['UKTO1']+kto,ktodata['START'],ktodata['ENDE'])
if self.rules.empty_line_in_ktolist(kto2):
text.append("")
text.append( ("%-56s" % (("%-20s" % kto2) + name ) ) +
re.sub(r"\-"," ",sp,9999) + ("%13.2f" % salden[kto]) )
if not "-" in kto2:
if not name == "":
name = "__" + name
if not 'UKTODIRS' in ktodata:
ktodata['UKTODIRS'] = {}
ktodata['UKTODIRS'][kto2+name] =1
text.append("")
for o in text_intern:
text.append(o[0])
text.append("")
if not ktodata['INT'] == "":
o = "-" + ktodata['INT']
else:
o = ""
text1 = ktodata['HEADER']
text1 = text1 + ("%-30s" % (ktodata['UKTO'] + o)) + " "
text2 = " " + ktodata['INTERVAL'] + " " + ("%13.2f" % float(gesamt) ) + "\n\n"
text2 = text2 + "\n".join(text) + "\n"
ktodata['NEWHASH'] = self.compute_ktohash(ktodata,t+text1+text2+ktodata['ADDTEXT'])
# if ktodata['NEWHASH'] == "xxxxxx":
# ktodata['NEWHASH'] = ktodata['KTOHASH']
# print ("----->",123)
ktodata['CONTENT'] = text1 + "(" + ktodata['DBHASH'] + ktodata['NEWHASH'] + ")" + text2
if not ktodata['MAXA'] == maxa or not ktodata['MAXB'] == maxb:
ktodata['MAXA'] = maxa
ktodata['MAXB'] = maxb
ktodata['CONTENT'] = ktodata['CONTENT'] + " " # damit der KTOHASH nicht mehr stimmt und neu berechnet wird
def kto_is_intern (self,ktox):
if ktox[0] == "-" or len(ktox) == 0:
return True
else:
return False
def kto_is_extern (self,ktox):
if ktox[0] == "-" or len(ktox) == 0:
return False
else:
return True
def xxx1 (self):
self.maxa0
saldovortrag = []
salden = {}
if ktodata["INT"] == "":
saldovortrag = [0.0]
for kto in ("KTOA","KTOB"):
cursor = self.db.cursor()
qstr = " select sum(BETRAG) from buchungen "
qstr = qstr + " where (" + kto + " like '" + ktodata['UKTO1'] + "%')"
qstr = qstr + " and DATUM < '" + ktodata['START'] + "' "
cursor.execute(qstr)
o = cursor.fetchone()[0]
if o:
saldovortrag[0] = saldovortrag[0] + float(o)
saldovortrag[0] = -saldovortrag[0]
salden[""] = saldovortrag[0]
def xxx ():
ukto1 = ktodata['UKTO1']
ul = len(ukto1)
gesamt = 0.00
maxa = 9
maxb = 9
maxa0 = "%-" + str(ktodata['MAXA']) + "s"
maxb0 = "%-" + str(ktodata['MAXB']) + "s"
text_intern = []
text_extern = []
t = ""
datum0 = ""
betrag0 = ""
while (0 == 0): # Zeilen des Kontos schreiben
if len(saldovortrag) > 0:
entry = [ ktodata['START'], saldovortrag[0], ktodata['UKTO1'], "-11-1805", "Saldovortrag"]
saldovortrag = []
else:
entry = cursor.fetchone()
if not entry:
break
if t == "":
if not "Saldovortrag" in entry[4] :
t = "___CONTAINS___BUCHUNGEN___"
betrag = float(entry[1])
ktoa = entry[2]
ktob = entry[3]
anz = 0
if ktoa[0:ul] == ukto1:
ktoa = ktoa[ul:]
# self.compute_salden(ktoa,betrag)
if ktoa == "":
ktoa = "-"
anz = anz + 1
else:
ktoa = ktoa[1:]
if ktob[0:ul] == ukto1:
ktob = ktob[ul:]
# self.compute_salden(ktob,-betrag)
if ktob == "":
ktob = "-"
if anz == 0:
o = ktoa
ktoa = ktob
ktob = o
betrag = -betrag
anz = anz + 1
else:
ktob = ktob[1:]
datum = entry[0]
# if datum == datum0 and betrag == betrag0 and abs(betrag) > 0.001:
# print ("WARNING:",datum,("%13.2f"%betrag))
datum0 = datum
betrag0 = betrag
remark = entry[4]
sortidx = datum
m = re.search(r"^(.*)? *\{\{SORTIDX\: +(.*?) *\}\} *(.*)$",remark) # proprietaeren Sort-Index herauslesen
if m:
remark = (m.group(1) + " " + m.group(3)).strip()
sortidx = sortidx + (m.group(2) + " "*40)[0:40]
sortidx = sortidx + self.rules.sortidx(ktoa)
m = re.search(r"^(\d\d? v\.?H\.? +.*\()(.*)\)",remark)
if m:
sortidx = sortidx + (m.group(2)+" "*40)[0:40] + "-Z"
else:
sortidx = sortidx + (re.sub(r"^(\+\-|\+\+)","",remark) + " "*40)[0:40] + "-A"
sortidx = sortidx + ktob
ktoa = re.sub("^"+ukto1,"",ktoa)
if ktoa == "":
ktoa = "-"
maxa = max(maxa,len(ktoa))
maxb = max(maxb,len(ktob))
buchung = datum + " " + ("%13.2f" % betrag) + " " + (maxa0 % ktoa) + " " + (maxb0 % ktob) + " "
sp = ""
if re.search(r"^\d\d? +v\.?H\.? ",entry[4]): # USt-Einrueckung
sp = " "
if anz == 1:
text_extern.append([buchung," " + sp + remark,betrag,sortidx])
else:
text_intern.append([buchung + " 0.00 " + sp + remark,"","",sortidx])
text_intern.sort(key=lambda x: x[3])
text_extern.sort(key=lambda x: x[3])
# self.mark("Start Salden")
fac = 1
for kto in ("KTOA","KTOB"):
qstr = " select " + kto + ",sum(BETRAG) from buchungen "
qstr = qstr + " where " + kto + " like '" + ktodata['UKTO1'] + "%'"
qstr = qstr + " and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' "
qstr = qstr + " group by (" + kto + ")"
cursor.execute(qstr)
while (0 == 0):
entry = cursor.fetchone()
if not entry:
break
ukto = entry[0][ul:]
betrag = float(entry[1])
while (0 == 0):
if not ukto in salden:
salden[ukto] = 0.00000001
salden[ukto] = salden[ukto] + fac * betrag
m = re.search(r"^(.*)\-(.*)$",ukto)
if m:
ukto = m.group(1)
else:
break
fac = -1
# self.mark("Ende Salden")
# print (salden)
ktoliste = [] # Kontenliste sortieren
for kto in salden.keys():
ktoliste.append([kto,self.rules.sortidx(re.sub(r"^-","",kto))])
ktoliste.sort(key=lambda x: x[1])
konten = []
text = []
gesamt = 0.00
for o in text_extern:
gesamt = gesamt + float(o[2])
text.append(o[0]+("%13.2f" % gesamt)+o[1])
text.append("")
for kto0 in ktoliste:
kto = kto0[0]
kto2 = re.sub(r"^\-","",kto)
sp = re.sub(r"[^\-]","",kto)
name = self.get_ktoname(ktodata['UKTO1']+kto,ktodata['START'],ktodata['ENDE'])
if self.rules.empty_line_in_ktolist(kto2):
text.append("")
text.append( ("%-56s" % (("%-20s" % kto2) + name ) ) +
re.sub(r"\-"," ",sp,9999) + ("%13.2f" % salden[kto]) )
if not "-" in kto2:
if not name == "":
name = "__" + name
if not 'UKTODIRS' in ktodata:
ktodata['UKTODIRS'] = {}
ktodata['UKTODIRS'][kto2+name] =1
text.append("")
for o in text_intern:
text.append(o[0])
text.append("")
if not ktodata['INT'] == "":
o = "-" + ktodata['INT']
else:
o = ""
text1 = ktodata['HEADER']
text1 = text1 + ("%-20s" % (ktodata['UKTO'] + o)) + " "
text2 = " " + ktodata['INTERVAL'] + " " + ("%13.2f" % float(gesamt) ) + "\n\n"
text2 = text2 + "\n".join(text) + "\n"
ktodata['NEWHASH'] = self.compute_ktohash(ktodata,t+text1+text2+ktodata['ADDTEXT'])
# if ktodata['NEWHASH'] == "xxxxxx":
# ktodata['NEWHASH'] = ktodata['KTOHASH']
# print ("----->",123)
ktodata['CONTENT'] = text1 + "(" + ktodata['DBHASH'] + ktodata['NEWHASH'] + ")" + text2
if not ktodata['MAXA'] == maxa or not ktodata['MAXB'] == maxb:
ktodata['MAXA'] = maxa
ktodata['MAXB'] = maxb
ktodata['CONTENT'] = ktodata['CONTENT'] + " " # damit der KTOHASH nicht mehr stimmt und neu berechnet wird
if self.old_key == self.old_key:
return(False)
if parentkey == self.parentkey:
db.cursor().execute("delete from buchungen where (KTOA like '" +
self.ukto + "%' OR " + " KTOB like '" + self.ukto + "%') " +
" and DATUM >= '" + self.startdatum + "' and DATUM <= '" + self.enddatum + "' ")
unique_strings = {}
ul = len(self.ukto)
for zeile in self.text.split("\n"):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if not m:
return
datum = m.group(1)
betrag = "%3.2f" % eval(m.group(2))
remark = m.group(6)
uniqu = []
ktoa = "-" + m.group(3)
if ktoa == "--":
ktoa = self.ukto
elif ktoa[0:2] == "--":
ktoa = self.ukto + ktoa[1:]
elif not ktoa[0:ul] == self.ukto:
uniqu.append(ktoa)
ktob = "-" + m.group(3)
if ktob == "--":
ktob = self.ukto
elif ktob[0:2] == "--":
ktob = self.ukto + ktob[1:]
elif not ktob[0:ul] == self.ukto:
uniqu.append(ktob)
if ktoa > ktob: # um Eindeutigkeit zu schaffen. Sonst kann es durch
o = ktoa # Hin- und Herschwingen zu Endlos-Loops kommen
ktoa = ktob
ktob = o
betrag = re.sub(r"^--","","-"+betrag)
if uniqu == []:
uniqu = [ktoa,ktob]
uniqu1 = []
for k in uniqu:
uniqu1.append(re.sub(r"\-\d\d\d\d\d$","-BETRAG",k))
betrag1 = re.sub("\-","",betrag) + ","
remark1 = "," + re.sub(r"[\+\- ]","",remark,9999)
uniqu = betrag1 + ",".join(uniqu1) + remark1
if datum in unique_strings: # to avoid double entries
if uniqu in unique_strings[datum]:
continue
else:
unique_strings[datum].append(uniqu)
else:
unique_strings[datum] = [uniqu] # ,betrag1+"-13-9999"+remark1]
qstr = ("insert into buchungen (DATUM,BETRAG,KTOA,KTOB,REMARK,ID) values ('" + datum +
"'," + betrag + ",'" + ktoa + "','" + ktob + "','" +
re.sub(r"'","",remark,9999) + "','" + 'a' + "')")
db.cursor().execute(qstr)
def compute_dbkey (self,db):
qu_string = (" select DATUM,BETRAG,KTOB,REMARK " +
" from buchungen " +
" where (KTOA like '" + self.ukto + "%' or KTOB like '" + self.ukto + "%') " +
" and DATUM >= '" + self.startdatum + "' and DATUM <= '" + self.enddatum + "' " +
" order by DATUM,KTOA,KTOB,BETRAG,REMARK")
cursor = db.cursor()
cursor.execute(qu_string)
dbhash_new = [""]
while (0 == 0):
entry = cursor.fetchone()
if entry == None:
break
entry = list(entry)
entry[1] = "%3.2f" % entry[1]
dbhash_new.append(re.sub(r" +"," "," ".join(list(entry)),99999999))
db_key = hashlib.md5( "".join(dbhash_new).encode() ).hexdigest()[0:8]
return db_key
def connect_to_db (self):
if not self.db:
self.db = sqlite3.connect(self.ktodir+"/report.sql")
self.db.row_factory = sqlite3.Row
cursor = self.db.cursor()
cursor.execute("create table if not exists buchungen " +
"(DATUM,BETRAG,KTOA,KTOB,REMARK 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)" )
except Exception as e:
pass
def sync_kto_to_sql (self,ktodir):
self.db = sqlite3.connect(dbfile)
self.db.row_factory = sqlite3.Row
for zeile in open(self.ktodir+"/report_*.kto").read():
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if m:
self.db = sqlite3.connect(dbfile)
self.db.row_factory = sqlite3.Row
cursor = self.db.cursor()
cursor.execute("create table if not exists buchungen " +
"(DATUM,BETRAG,KTOA,KTOB,REMARK,ID default '')")
cursor.execute("create table if not exists ktoname " +
"(KTO,NAME,DATUMA,DATUMB)")
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)" )
except Exception as e:
pass
try:
cursor.execute("create index KTO_IDX on ktoname (KTO)" )
cursor.execute("create index DATUMA on ktoname (DATUMA)" )
except Exception as e:
pass
if not len(ktofile) == 1:
return("ERROR. No ktofile found or ambiguous in " + self.ktodir)
def read_kto (self): # Parse the ktofile
self.comment = []
self.buchungen = []
self.uktosalden = {}
self.uktonames = {}
ktofile = glob.glob(self.ktodir+"/report_*.kto")
if not len(ktofile) == 1:
return("ERROR. No ktofile found or ambiguous in " + self.ktodir)
self.ktofile = ktofile[0]
self.read_hash_keys()
self.compute_new_ktokey()
def compute_ktokey (self):
ktofiles = glob.glob(self.ktodir+"/*.*")
ktofiles.sort()
hashtext = []
for file in ktofiles:
if not os.path.isfile(file):
continue
if re.search(r"\.(jpg|pdf|xlsx?|docx?|sql|~)$",file):
continue
# print (file)
filecontent = open(file).read()
if re.search(r"\.kto$",file):
filecontent = re.sub(r" ","",filecontent,99999999)
filename = "report"
else:
filename = re.sub(r"^(.*)[\\\/](.*)$","\\2",file)
filehash = filename + "." + hashlib.md5( open(file).read().encode() ).hexdigest()
hashtext.append(filehash)
ktokey = hashlib.md5( "".join(hashtext).encode() ).hexdigest()[0:8]
return ktokey
def parse_zeile_for_comment (self,zeile):
m = re.search(r"( *)(\#.*)$",zeile)
if m:
self.comment.append(m.group(2))
return True
else:
return False
def parse_zeile_for_buchung (self,zeile):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if m:
self.buchungen.append([m.group(1),m.group(2),m.group(3),m.group(4),m.group(6)])
return True
else:
return False
def parse_zeile_for_uktosaldo (self,zeile):
m = re.search(r"^(\S+) (\S*) +(\-?\d+\.\d\d)$",zeile)
if m:
self.uktosalden[m.group(1)] = m.group(3)
if not m.group(2) == "":
self.uktonames[m.group(1)] = m.group(2)
return True
else:
return False
# def write_kto (self):
#
# text = self.comment + "\n\n" + self.interval + " (---PARENT------KTOID---)\n\n" +
def sort (self,pattern):
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)
for zeile in open(ktofile[0]).read().split("\n"):
if self.parse_zeile_for_comment(zeile):
continue
if self.parse_zeile_for_buchung(zeile):
continue
if self.parse_zeile_for_uktosaldo(zeile):
continue
#******************************************************************************
class Account3 (object):
def __init__ (self,dbfile):
self.mark()
if not dbfile == ":memory:":
dbfile = self.home+"/"+dbfile
self.db = sqlite3.connect(dbfile)
self.db.row_factory = sqlite3.Row
cursor = self.db.cursor()
cursor.execute("create table if not exists buchungen " +
"(DATUM,BETRAG,KTOA,KTOB,REMARK,ID default '')")
cursor.execute("create table if not exists ktoname " +
"(KTO,NAME,DATUMA,DATUMB)")
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)" )
except Exception as e:
pass
try:
cursor.execute("create index KTO_IDX on ktoname (KTO)" )
cursor.execute("create index DATUMA on ktoname (DATUMA)" )
except Exception as e:
pass
self.ktoname_reverse = {}
if 'ktoname' in vars(self.rules):
self.ktoname = {}
for o in self.rules.ktoname.split("\n"):
m = re.search(r"^(.*)__(.*)$",o.strip())
if m:
self.ktoname[m.group(1)] = m.group(2)
self.ktoname_reverse[m.group(2)] = m.group(1)
self.mark("0. Datenbank einrichten.")
#********************************************************************************
#********************************************************************************
def sort (self,pattern,file):
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 cx (self,ukto_new,chdir=True,interval=None):
ukto_new = re.sub(r"[\\\/]$","",ukto_new)
erg = None
if not interval:
m = re.search(r"(^|-|\\|\/)(19|2\d)(\d\d)(-|\/|\\|$)",os.path.relpath(".",self.home)+"/"+ukto_new)
if m:
interval = m.group(2)+m.group(3)
else:
interval = "1000,2999"
if re.search(r"^\d\d\d\d$",ukto_new) and 1900 < int(ukto_new) < 2999: # os.path.relpath(".",self.home) == ".":
interval = ukto_new
m = re.search(r"^(.*)\.(kto|xls|xlsx)$",ukto_new)
if m:
ending = m.group(2)
ukto_dir = m.group(1)
ukto_path = ukto_dir
else:
ending = ""
ukto_dir = ukto_new
ukto_new = ukto_new + ".kto"
ukto_path = self.ktopath(".") + ukto_dir
m = re.search(r"^(.*)(\_\_.*)$",ukto_dir)
if m:
ukto = m.group(1)
ukto_name = m.group(2)
else:
ukto = ukto_dir
ukto_name = ""
if re.search(ukto_name[2:]+"$",ukto):
ukto_name = ""
ukto_path = re.sub(r"(\_\_.*)$","",ukto_path)
ukto_path = re.sub(r"(^-|-$)","",ukto_path,9999)
ktotext = ukto_path
startdatum = "00000000"
enddatum = "99999999"
m = re.search(r"^(.*?)\-(.*)$",ukto_path)
if m:
ktotext = m.group(2)
if re.search(r"^[12]\d\d\d",m.group(1)):
startdatum = m.group(2) + "0000"
enddatum = m.group(2) + "9999"
ktotext = re.sub("-"+interval,"",ktotext)
ktotext = re.sub(r"^-","",ktotext)
name1 = self.get_ktoname("-"+ktotext,startdatum,enddatum)
if name1:
ukto_name = "__" + name1
ukto_dir = ukto + ukto_name
if ktotext == interval:
ktotext = " "
ktotext = self.rules.header + "\n" + ("=" * len(self.rules.header) ) + "\n\n" + ktotext
ktotext = ktotext + " () " + interval + " 0.00 \n"
if ending == "": # Directory ist addressiert
for dir in glob.glob(ukto+"*"):
if os.path.isdir(dir) and not "-" in re.sub("^"+ukto,"",dir):
if ukto_name == "":
ukto_dir = dir
os.rename(dir,ukto_dir)
break
if not os.path.isdir(ukto_dir):
os.mkdir(ukto_dir)
file1 = ukto_dir+"/"+ukto_path+ukto_name+".kto"
for file in glob.glob(ukto_dir+"/*.kto"):
m = re.search(r"^(.*)[\\\/](.*)$",file)
if os.path.isfile(file):
if m and len(interval) == 4 and not interval == m.group(2)[0:4]: # Datum muss passen
print ("REMOVE",file)
os.remove(file)
else:
if ukto_name == "":
file1 = file
os.rename(file,file1)
break
if not os.path.isfile(file1):
open(file1,"w").write(ktotext)
if chdir:
open(ukto_dir +"/__cd_dir__.sh","w").write('''
cd ''' + ukto_dir + ''' 2> /dev/null
# source_ea sync *.kto
rm __cd_dir__.* 2> /dev/null
''')
else:
file1 = ukto_path+ukto_name+"."+ending
for file in glob.glob(ukto_path+"*.kto"):
if os.path.isfile(file):
m = re.search(r"^(.*)[\\\/](.*)$",file)
if m and len(interval) == 4 and not interval == m.group(2)[0:4]: # Datum muss passen
print ("REMOVE",file)
os.remove(file)
else:
if ukto_name == "":
file1 = file
print(file1)
os.rename(file,file1)
break
if not os.path.isfile(file1):
open(file1,"w").write(ktotext)
return(file1)
#********************************************************************************
def ce (self,ukto_new,interval=None):
ukto_new = re.sub(r"[\\\/]$","",ukto_new)
self.cx(ukto_new)
os.system("joe " + self.tmp[0])
self.cx(ukto_new)
# os.unlink(self.tmp[0])
try:
os.rmdir(self.tmp[1])
except:
pass
#********************************************************************************
def cxx (self,*pars):
pars = ['*/*/*/*/*/*/*/*/*/*/*',
'*/*/*/*/*/*/*/*/*/*',
'*/*/*/*/*/*/*/*/*',
'*/*/*/*/*/*/*/*',
'*/*/*/*/*/*/*',
'*/*/*/*/*/*',
'*/*/*/*/*',
'*/*/*/*',
'*/*/*',
'*/*',
'*']
for pp in pars:
for ukto_new1 in glob.glob(pp):
if "EXCLUDE" in ukto_new1 or "NOTVALID" in ukto_new1:
continue
ukto_new1 = re.sub(r"[\\\/]$","",ukto_new1)
if os.path.isdir(ukto_new1):
m = re.search(r"^(.*)[\\\/](.*)",ukto_new1)
if m:
ukto_new2 = m.group(2)
dir2 = m.group(1)
else:
ukto_new2 = ukto_new1
dir2 = "."
homepath = os.path.abspath(".")
os.chdir(dir2)
self.cx(ukto_new2,False)
os.chdir(homepath)
#********************************************************************************
def xxallocate_names (self,aktdir=None):
if aktdir == None:
self.tmpnames = {}
self.allocate_names(".")
cursor = self.db.cursor()
cursor.execute("delete from ktoname")
for entry in self.tmpnames:
entry1 = entry.split(",")
cursor.execute("insert into ktoname (KTO,NAME,DATUMA,DATUMB) values ('" +
entry1[0] + "','" + self.tmpnames[entry] + "','" +
entry1[1] + "','" + entry1[2] + "')")
self.tmpnames = {}
self.db.commit()
return()
for entry in os.listdir(aktdir):
if not entry[0] == ".":
if os.path.isdir(aktdir+"/"+entry):
self.allocate_names(aktdir+"/"+entry)
# m = re.search(r"^(.*)\_\_(.*)$",entry)
# if m:
# self.tmpnames[ukto+",19000000,29990000"] = m.group(2)
else:
m = re.search(r"^(.*)\_\_(.*)\.(.*)$",entry)
if m:
text = open(aktdir+"/"+entry).read()[0:1000]
m1 = re.search(r"^(.*?)\n(\S+)[^\n]*?\) +(\S+)",text,re.DOTALL)
if m1:
ukto = re.sub(r"\-[123456789IJKLMNPS]$","",m1.group(2))
interval = re.sub(r"\-[123456789IJKLMNPS]$","",m1.group(3))
m2 = re.search(r"^(.*),(.*)$",interval)
if m2:
int_start = m2.group(1)
int_ende = m2.group(2)
else:
int_start = interval
int_ende = interval
int_start = (int_start+"00000000")[0:8]
int_ende = (int_ende+"99999999") [0:8]
self.tmpnames["-"+ukto+","+int_start+","+int_ende] = m.group(2)
#********************************************************************************
def clear (self,pattern):
zaehler = 0
while (0 == 0):
for file in (glob.glob(pattern+(("*/")*zaehler)+"*.kto")):
os.unlink(file)
zaehler = zaehler + 1
if zaehler > 15:
break
#********************************************************************************
def sync (self,*pars):
self.cxx()
pars1 = []
relhome = os.path.relpath(self.home,".")
if len(pars) == 0:
pars = ["****************.kto"]
for par in pars:
par = re.sub(r"\\","",par)
par = re.sub(r"^\.\.\.",relhome,par)
m = re.search(r"^(.*?)(\*\*+)(.*)$",par)
if m:
zaehler = 0
while (0 == 0):
zaehler = zaehler + 1
if zaehler > len(m.group(2)):
break
pars1.append(m.group(1)+"/".join(["*"]*zaehler)+m.group(3))
else:
pars1.append(par)
# 'print (pars,pars1)
if len(pars1) == 0:
pars1 = ['*.kto','*.xlsx']
ktofiles = []
for par in pars1:
files = glob.glob(par)
for file in files:
if not file in (ktofiles) and not "EXCLUDE" in file:
ktofiles.append(file) #os.path.relpath(file))
ktodatas = []
for ktofile in ktofiles:
if re.search(r"\.kto$",ktofile):
ktodatas.append( { "KTOFILE": ktofile, "ROUNDS": 10 } )
ktodatas.sort(key=lambda x:x['KTOFILE'])
rounds = 0
rtime1 = time.clock()
rtime0 = rtime1
while (0 == 0):
rounds = rounds + 1
maxsteps = 1
print ("")
print ("=========================================")
print ("START ROUND " + str(rounds))
print ("=========================================")
time.sleep( 0.03 * (rtime1 - rtime0) ) # kleine Atempause fuer die Anzeige
for ktodata in ktodatas:
print ("")
print (ktodata['KTOFILE'])
if 'FUNC' in ktodata:
del ktodata['FUNC']
ktodata["STEPS"] = 0
ktodata['RULES_APPLIED'] = False
while (0 == 0):
if 'KTODIR' in ktodata and os.path.isfile(ktodata['KTODIR'] + "/__skip__.txt"):
print ("Skip-File found!")
break
ktodata["STEPS"] = ktodata["STEPS"] + 1
self.read_kto(ktodata,rounds)
if not "PROCEED" in self.dbsync(ktodata,rounds):
break
if not ktodata["MERGE"] == "":
self.mark("Merge-Conflict: " + ktodata["MERGE"])
break
if ktodata["STEPS"] > 20:
time.sleep(1)
open(ktodata['KTODIR'] + "/__skip__.txt","w").write("skip\n")
break
if ktodata["STEPS"] > 30:
break
maxsteps = max(maxsteps,ktodata["STEPS"])
rtime0 = rtime1
rtime1 = time.clock()
print ("Benoetigte Zeit: " + ("%7.2f" % (rtime1 - rtime0)) + " Sekunden.")
if maxsteps < 2:
break
merge_conflict_files = []
for ktodata in ktodatas:
if not ktodata["MERGE"] == "": # and not ktodata['CONTENT'] == open(ktodata['KTOFILE']).read():
zaehler = "001"
while (0 == 0):
if os.path.isfile( ktodata["KTOFILE"] + "." + zaehler ):
zaehler = ("%03u" % (int(zaehler) + 1) )
else:
break
merge_conflict_files.append( ktodata['KTOFILE'] + "." + zaehler )
open( merge_conflict_files[-1] , "w").write( ktodata['CONTENT'] )
else:
open( ktodata['KTOFILE'], "w").write(ktodata['CONTENT'] )
# if len(glob.glob(ktodata['KTODIR']+"/*.kto") == 1:
# for udir in ktodata['UKTODIRS']:
#
# if not os.path.isdir(ktodata['KTODIR']+"/"+udir):
# os.mkdir(ktodata['KTODIR']+"/"+udir)
self.db.commit()
print ("=========================================")
if rounds == 1:
rounds = str(rounds) + " Round."
else:
rounds = str(rounds) + " Rounds."
self.mark("I. Datenbank Commit. " + rounds)
if len(merge_conflict_files) > 0:
print ("\n" + "\n".join(merge_conflict_files) + "\n\n")
#********************************************************************************
def read_kto (self,ktodata,rounds=0):
if ktodata['STEPS'] > 1:
self.mark("%-70s" % ("------------ " + ktodata['FILENAME'] + " " +
str(rounds) + " " + str(ktodata['STEPS']) + " -------------------") )
# else:
# self.mark(ktodata["KTOFILE"])
if not "KTODIR" in ktodata:
m = re.search(r"^(.*)[\\\/](.*)",ktodata['KTOFILE'])
if m:
ktodata['KTODIR'] = m.group(1)
ktodata['FILENAME'] = m.group(2)
else:
ktodata['KTODIR'] = "."
ktodata['FILENAME'] = ktodata['KTOFILE']
self.make_addtext(ktodata)
ktodata['CONTENT'] = open(ktodata['KTOFILE']).read()
ktodata['MAXA'] = 10
ktodata['MAXB'] = 10
ktodata['IMPORT1'] = ""
ktodata['DBCHANGED'] = True
ktodata['DBHASH'] = "-"
ktodata['KTOPATH'] = self.ktopath(ktodata['KTODIR'])
ktodata['RULES_APPLY'] = 0
self.mark("A. Einlesen Konto.")
else:
pass
if not 'INT' in ktodata:
self.rules.rule__raw(ktodata)
# print ("Apply",ktodata['RULES_APPLY'])
if 'FUNC' in ktodata and ktodata['DBCHANGED'] and ktodata['RULES_APPLY'] >= 1 and ktodata['RULES_APPLY'] < 2:
for func in (ktodata['FUNC'],ktodata['FUNC1'],ktodata['FUNC2'],ktodata['FUNC3']):
if func in self.rules.__class__.__dict__:
self.rules.__class__.__dict__[func](self.rules,ktodata)
self.mark("B. Rules anwenden: " + func)
ktodata['RULES_APPLIED'] = True
break
m = re.search(r"^(.*?)\((.*?)\)(.*)$",ktodata['CONTENT'],re.DOTALL)
text1 = m.group(1)
text2 = m.group(3)
ktodata['DBHASH'] = m.group(2)[0:6]
ktodata['KTOHASH'] = m.group(2)[6:]
text3 = re.sub("\n\d\d\d\d\d\d\d\d.*?Saldovortrag","",text2)
if re.search(r"\n\d\d\d\d\d\d\d\d +\-?\d",text3):
t = "___CONTAINS___BUCHUNGEN___"
else:
t = ""
t = t + text1 + text2 + ktodata['ADDTEXT']
ktodata['NEWHASH'] = self.compute_ktohash(ktodata,t)
ktodata['IMPORT0'] = ktodata['IMPORT1']
t = re.sub(" +","",t.strip(),99999999)
ktodata['IMPORT1'] = self.compute_ktohash(ktodata,t)
ktodata["INT"] = ""
m = re.search(r"^(.*?\n|)(\S*) +$",text1,re.DOTALL)
ktodata['HEADER'] = m.group(1)
ktodata['UKTO'] = m.group(2)
m1 = re.search(r"^(.*)\-([123456789ABCIJKLMNPS])$",ktodata['UKTO'])
if m1:
ktodata['INT'] = m1.group(2)
ktodata['UKTO'] = m1.group(1)
ktodata['UKTO1'] = "-" + ktodata['UKTO']
if ktodata["UKTO1"] == "-":
ktodata["UKTO1"] = ""
m = re.search(r"^ *([0123456789,]*)\s* +([^\n]*?)(\-?\d+\.\d\d) *\n\s*(.*)$",text2,re.DOTALL)
ktodata['INTERVAL'] = m.group(1)
m1 = re.search(r"^(.*)\-([123456789IJABCKLMNPS])$",ktodata['INTERVAL'])
if m1:
ktodata['INT'] = m1.group(2)
ktodata['INTERVAL'] = m1.group(1)
ktodata['NAME'] = m.group(2)
ktodata['SOLLWERT'] = m.group(3)
ktodata['BUCHUNGEN'] = m.group(4)
ktodata['MERGE'] = ''
# m = re.search(r"^(\d\d\d\d)\-$",ktodata['FILENAME'][0:5]) # Hack um Kontodateien kopieren zu koennen
# if m and re.search(r"^(\d\d\d\d)$",ktodata['INTERVAL']):
# if not m.group(1) == ktodata['INTERVAL']:
# ktodata['INTERVAL'] = m.group(1)
# ktodata['BUCHUNGEN'] = ""
m = re.search(r"^(.*),(.*)$",ktodata['INTERVAL'])
if m:
ktodata['START'] = m.group(1)
ktodata['ENDE'] = m.group(2)
else:
ktodata['START'] = ktodata['INTERVAL']
ktodata['ENDE'] = ktodata['INTERVAL']
ktodata['START'] = (ktodata['START'] + "00000000")[0:8]
ktodata['ENDE'] = (ktodata['ENDE'] + "99999999")[0:8]
if not ktodata['INT'] == "": # Zeitraum bestimmen
intv = { "1" : ["0101","0199"],
"2" : ["0201","0299"],
"3" : ["0301","0399"],
"4" : ["0401","0499"],
"5" : ["0501","0599"],
"6" : ["0601","0699"],
"7" : ["0701","0799"],
"8" : ["0801","0899"],
"9" : ["0901","0999"],
"A" : ["1001","1099"],
"B" : ["1101","1199"],
"C" : ["1201","1299"],
"I" : ["0101","0399"],
"J" : ["0401","0699"],
"K" : ["0701","0999"],
"L" : ["1001","1299"],
"M" : ["0101","0699"],
"N" : ["0701","1299"],
"P" : ["0101","1299"] } [ ktodata['INT'] ]
ktodata["START"] = ktodata["START"][0:4] + intv[0]
ktodata["ENDE"] = ktodata["ENDE"][0:4] + intv[1]
# print (ktodata["START"],ktodata["ENDE"])
ktodata['FUNC'] = "rule__" + re.sub(r"-","_",re.sub(r"_","__",ktodata['UKTO'],99),99)
ktodata['FUNC1'] = re.sub(r"^(.*)\_(.*)$", "\\1"+"_xxx", ktodata['FUNC'])
ktodata['FUNC2'] = re.sub(r"^(.*)\_(.*\_.*)$", "\\1"+"_xxx_xxx", ktodata['FUNC'])
ktodata['FUNC3'] = re.sub(r"^(.*)\_(.*\_.*\_.*)$","\\1"+"_xxx_xxx_xxx",ktodata['FUNC'])
while not 'FILENAME1' in ktodata:
ktodata['FILENAME1'] = ktodata['FILENAME']
pathnew = ktodata['INTERVAL']+"-"+ktodata['UKTO']+'-'+ktodata['INT'] + "-"
ul = min(len(ktodata['KTOPATH']),len(pathnew))
if ul > 0 and ktodata['KTOPATH'][0:ul] == pathnew[0:ul]:
m1 = re.search(r"^(.*)\.(kto|xls|xlsx)$",ktodata['FILENAME'])
if m1:
filename = m1.group(1)
ending = m1.group(2)
filename = re.sub(r"^(.*)\_\_(.*)$","\\2",filename)
if not ktodata['INT'] == "":
ktodata['FILENAME1'] = ktodata['INTERVAL']+"-"+ktodata['UKTO']
print (filename)
if ktodata['INT']:
ktodata['FILENAME1'] = ktodata['FILENAME1'] + "-" + ktodata['INT']
if re.search(filename+"$",ktodata['INTERVAL'] + "-" + ktodata['UKTO']) or "-" in filename:
filename = ""
if not filename == "":
ktodata['FILENAME1'] = ktodata['FILENAME1'] + "__" + filename
if ktodata['FILENAME1'] == ktodata['INT'] + "-__" + ktodata['INT']:
ktodata['FILENAME1'] = ktodata['FILENAME']
ktodata['FILENAME1'] = ktodata['FILENAME1'] + "." + ending
try:
os.rename(ktodata['KTODIR']+"/"+ktodata['FILENAME'],ktodata['KTODIR']+"/"+ktodata['FILENAME1'])
ktodata['FILENAME'] = ktodata['FILENAME1']
ktodata['KTOFILE'] = ktodata['KTODIR']+"/"+ktodata['FILENAME']
except:
pass
break
o = ""
if not ktodata['FILENAME'] == ktodata['FILENAME1']:
o = " ---> Neuer Kontoname: " + ktodata['FILENAME1']
self.mark("C. Analysieren Kontotext." + o)
ktodata['RULES_APPLY'] = ktodata['RULES_APPLY'] + 1
#*************************************************************************************
def make_addtext (self,ktodata):
addfiles = glob.glob(ktodata['KTODIR']+"/*")
addfiles.sort()
addtext = self.rules.addtext_locale
if "AUX" in ktodata['KTOFILE']:
ktodata['ADDTEXT'] = addtext
return()
for addfile in addfiles:
if not os.path.isfile(addfile):
continue
if re.search(r"\.(kto[\.\d]*|kto|py|pyc|db|db-journal|pdf.*|aux|dvi|gif|jpg|zip|xls|xlsx|doc|docx|\.\d+)$",
addfile) or "EXCLUDE" in addfile or "NOTVALID" in addfile or "~" in addfile:
if not "AUX" in addfile:
continue
if re.search(r"(__pycache__)$",addfile):
continue
m = re.search(r"^(.*)[\\\/](.*)$",addfile)
if not "." in m.group(2):
continue
#print ("ADD1",addfile,m.group(2))
if os.path.isfile(addfile):
try:
addtext = addtext + str( base64.urlsafe_b64encode(
hashlib.md5(open(addfile,'r').read().encode("utf8")).digest()),"ascii" )
except:
print (addfile," is not utf8")
exit()
if m:
addtext = addtext + m.group(2)
else:
addtext = addtext + addfile
ktodata['ADDTEXT'] = addtext
#*************************************************************************************
def ktopath (self,dir):
newktopath = os.path.relpath(dir,self.home)
if newktopath == ".":
newktopath = ""
newktopath = re.sub(r"\_\_(.*?)(\\|\/|$)","-",newktopath,9999)
newktopath = re.sub(r"[\\\/]","-",newktopath,9999)
newktopath = newktopath.strip("-")
newktopath = re.sub(r"^\-+","",newktopath,9999) + "-"
return(newktopath)
#*************************************************************************************
def dbsync (self,ktodata,rounds):
dbhash = self.compute_dbhash(ktodata)
# print (ktodata['NEWHASH'])
if ktodata['NEWHASH'] == "xxxxxx":
ktodata['DBHASH'] = "."
if dbhash == "xxxxxx" and ktodata['NEWHASH'] == "xxxxxx":
ktodata['NEWHASH'] = "."
if 'AUX' in ktodata['KTOFILE']:
ktodata['RULES_APPLY'] = 99999999
if ktodata['DBHASH'] == "." and ktodata['NEWHASH'] == ".":
if rounds > 1 or ktodata['ADDTEXT'] == "":
self.mark("H. Konto ist aktuell. Steps: " + str(ktodata["STEPS"]) +".")
return("Kto is up-to-date") # Dann nichts machen
self.mark(" --> DBHASH: " + ktodata['DBHASH'] + ", DB_NEW: " + dbhash +
", KTOHASH: " + ktodata['KTOHASH'] + ", NEW_HASH: " + ktodata['NEWHASH'] +
", IMPORT0: " + ktodata['IMPORT0'] + ", IMPORT1: " + ktodata['IMPORT1'])
# Kontofile - oder die zugehoerigen Dateien, oder Readonly-File - haben sich nicht geaendert:
if ktodata['KTOHASH'] == ktodata['NEWHASH'] or ktodata['NEWHASH'] == 'xxxxxx':
if dbhash == ktodata['DBHASH'] and ( not dbhash == "xxxxxx" or ktodata['KTOHASH'] == "xxxxxx" ):
# Kontoeintraege in der Datenbank haben sich auch nicht geaendert.
self.mark("H. Konto ist aktuell. Steps: " + str(ktodata["STEPS"]) +".")
return("Kto is up-to-date") # Dann nichts machen
else:
ktodata['DBHASH'] = dbhash
self.get_from_db(ktodata) # Kontotext updaten aus der Datenbnk
self.mark("G1. Kontotext neu schreiben.")
else: # Kontofile - oder die zugehoerigen Dateien - haben sich geaendert
if dbhash == ktodata['DBHASH'] or dbhash == "xxxxxx": # Datenbankdaten haben sich nicht geaendert
merge_result = ""
else:
cursor = self.db.cursor()
qstr = " select DATUM,BETRAG,KTOA,KTOB,REMARK from buchungen "
qstr = qstr + " where (KTOA like '" + ktodata['UKTO1'] + "%' or KTOB like '" + ktodata['UKTO1'] + "%')"
qstr = qstr + " and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' "
qstr = qstr + " order by DATUM,KTOA,KTOB"
cursor.execute(qstr)
merge_result = self.rules.merge(ktodata,cursor)
self.mark("E. Mergen. " + merge_result)
if os.path.isfile(ktodata['KTOFILE']+".001"):
os.unlink(ktodata['KTOFILE']+".001")
merge_result = ""
if merge_result == "": # aus den kontodaten in die DB importieren
if not ktodata['IMPORT1'] == ktodata['IMPORT0']:
if not 'AUX' in ktodata['KTOFILE']:
self.db.cursor().execute("delete from buchungen where (KTOA like '" +
ktodata["UKTO1"] + "%' OR " + " KTOB like '" + ktodata["UKTO1"] + "%') " +
" and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' ")
unique_strings = {}
ul = len(ktodata['UKTO1'])
for zeile in ktodata['BUCHUNGEN'].split("\n"):
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\S+) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if m:
datum = m.group(1)
betrag = "%3.2f" % eval(m.group(2))
remark = m.group(6)
uniqu = []
ktoa = "-" + m.group(3)
if ktoa == "--":
ktoa = ktodata['UKTO1']
elif ktoa[0:2] == "--":
ktoa = ktodata['UKTO1'] + ktoa[1:]
elif not ktoa[0:ul] == ktodata['UKTO1']:
uniqu.append(ktoa)
ktob = "-" + m.group(4)
if ktob == "--":
ktob = ktodata['UKTO1']
elif ktob[0:2] == "--":
ktob = ktodata['UKTO1'] + ktob[1:]
elif not ktob[0:ul] == ktodata['UKTO1']:
uniqu.append(ktob)
if "Saldovortrag" in remark or ktob == "--11-1805":
continue
if ktoa > ktob: # um Eindeutigkeit zu schaffen. Sonst kann es durch
o = ktoa # Hin- und Herschwingen zu Endlos-Loops kommen
ktoa = ktob
ktob = o
betrag = re.sub(r"^--","","-"+betrag)
if uniqu == []:
uniqu = [ktoa,ktob]
uniqu1 = []
for k in uniqu:
uniqu1.append(re.sub(r"\-\d\d\d\d\d$","-BETRAG",k))
betrag1 = re.sub("\-","",betrag) + ","
remark1 = "," + re.sub(r"[\+\- ]","",remark,9999)
uniqu = betrag1 + ",".join(uniqu1) + remark1
if datum in unique_strings: # to avoid double entries
if uniqu in unique_strings[datum]:
continue
else:
unique_strings[datum].append(uniqu)
else:
unique_strings[datum] = [uniqu] # ,betrag1+"-13-9999"+remark1]
# print ("<<<----")
# if ktoa < ktob:
# id = datum + "," + betrag1 + "," + ktoa + "," + ktob + "," + remark1
# else:
# id = datum + "," + betrag1 + "," + ktob + "," + ktoa + "," + remark1
# id = str( base64.urlsafe_b64encode(hashlib.md5(id.encode("utf8")).digest())[0:9], "ascii" )
qstr = ("insert into buchungen (DATUM,BETRAG,KTOA,KTOB,REMARK,ID) values ('" + datum +
"'," + betrag + ",'" + ktoa + "','" + ktob + "','" +
re.sub(r"'","",remark,9999) + "','" + 'a' + "')")
# print(qstr)
self.db.cursor().execute(qstr)
ktodata['DBCHANGED'] = True # not ( ( ktodata['DBHASH'] == o ) and ( ktodata['IMPORT0'] == ktodata['IMPORT1'] ) )
self.mark("F. Importieren in die Datenbank.")
o = self.compute_dbhash(ktodata)
ktodata['DBHASH'] = o
else:
ktodata['DBCHANGED'] = False
# self.mark("F. Kein Datenbank-Update noetig.")
self.get_from_db(ktodata) # Kontotext updaten aus der Datenbnk
# print(ktodata['CONTENT'])
self.mark("G2. Kontotext neu schreiben.")
else:
ktodata['MERGE'] = merge_result
return("PROCEED.")
#********************************************************************************
def dbhash (self,ukto):
ktodata = { 'UKTO1' : "-"+ukto, 'START': '00000000', 'ENDE' : '99999999' }
print ( self.compute_dbhash(ktodata) )
#********************************************************************************
def compute_dbhash (self,ktodata):
qu_string = (" select DATUM,BETRAG,KTOB,REMARK " +
" from buchungen " +
" where (KTOA like '" + ktodata['UKTO1'] + "%' or KTOB like '" + ktodata['UKTO1'] + "%') " +
" and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' " +
" order by DATUM,KTOA,KTOB,BETRAG,REMARK")
# print (qu_string)
cursor = self.db.cursor()
cursor.execute(qu_string)
dbhash_new = [""]
while (0 == 0):
entry = cursor.fetchone()
if entry == None:
break
entry = list(entry)
entry[1] = "%3.2f" % entry[1]
dbhash_new.append(re.sub(r" +"," "," ".join(list(entry)),99999999))
if dbhash_new == [""]:
dbhash_new = "xxxxxx" # wenn es gar keine Buchungen im Unterkonto gibt, dann dbhash auf "xxxxxx" setzen
else:
dbhash_new = base64.urlsafe_b64encode(hashlib.md5("".join(dbhash_new).encode("utf8")).digest())[0:6]
dbhash_new = str(dbhash_new,"ascii")
return(dbhash_new)
#********************************************************************************
def compute_ktohash (self,ktodata,text):
if not "___CONTAINS___BUCHUNGEN___" in text[0:36]: # wenn es gar keine Buchungen im Kontoauszug gibt
erg = "xxxxxx"
elif "<<<< HEAD" in text:
erg = "xxxxxx"
else:
erg = str(base64.urlsafe_b64encode(hashlib.md5(text.encode("utf8")).digest()),"ascii" )[0:6]
return(erg)
#*******************************************************************************
def get_from_db (self,ktodata):
saldovortrag = []
salden = {}
if ktodata["INT"] == "":
saldovortrag = [0.0]
for kto in ("KTOA","KTOB"):
cursor = self.db.cursor()
qstr = " select sum(BETRAG) from buchungen "
qstr = qstr + " where (" + kto + " like '" + ktodata['UKTO1'] + "%')"
qstr = qstr + " and DATUM < '" + ktodata['START'] + "' "
cursor.execute(qstr)
o = cursor.fetchone()[0]
if o:
saldovortrag[0] = saldovortrag[0] + float(o)
saldovortrag[0] = -saldovortrag[0]
salden[""] = saldovortrag[0]
cursor = self.db.cursor()
qstr = " select DATUM,BETRAG,KTOA,KTOB,REMARK from buchungen "
qstr = qstr + " where (KTOA like '" + ktodata['UKTO1'] + "%' or KTOB like '" + ktodata['UKTO1'] + "%')"
qstr = qstr + " and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' "
qstr = qstr + " order by DATUM,BETRAG,KTOA,KTOB"
cursor.execute(qstr)
ukto1 = ktodata['UKTO1']
ul = len(ukto1)
gesamt = 0.00
maxa = 9
maxb = 9
maxa0 = "%-" + str(ktodata['MAXA']) + "s"
maxb0 = "%-" + str(ktodata['MAXB']) + "s"
text_intern = []
text_extern = []
t = ""
datum0 = ""
betrag0 = ""
while (0 == 0): # Zeilen des Kontos schreiben
if len(saldovortrag) > 0:
entry = [ ktodata['START'], saldovortrag[0], ktodata['UKTO1'], "-11-1805", "Saldovortrag"]
saldovortrag = []
else:
entry = cursor.fetchone()
if not entry:
break
if t == "":
if not "Saldovortrag" in entry[4] :
t = "___CONTAINS___BUCHUNGEN___"
betrag = float(entry[1])
ktoa = entry[2]
ktob = entry[3]
anz = 0
if ktoa[0:ul] == ukto1:
ktoa = ktoa[ul:]
# self.compute_salden(ktoa,betrag)
if ktoa == "":
ktoa = "-"
anz = anz + 1
else:
ktoa = ktoa[1:]
if ktob[0:ul] == ukto1:
ktob = ktob[ul:]
# self.compute_salden(ktob,-betrag)
if ktob == "":
ktob = "-"
if anz == 0:
o = ktoa
ktoa = ktob
ktob = o
betrag = -betrag
anz = anz + 1
else:
ktob = ktob[1:]
datum = entry[0]
# if datum == datum0 and betrag == betrag0 and abs(betrag) > 0.001:
# print ("WARNING:",datum,("%13.2f"%betrag))
datum0 = datum
betrag0 = betrag
remark = entry[4]
sortidx = datum
m = re.search(r"^(.*)? *\{\{SORTIDX\: +(.*?) *\}\} *(.*)$",remark) # proprietaeren Sort-Index herauslesen
if m:
remark = (m.group(1) + " " + m.group(3)).strip()
sortidx = sortidx + (m.group(2) + " "*40)[0:40]
sortidx = sortidx + self.rules.sortidx(ktoa)
m = re.search(r"^(\d\d? v\.?H\.? +.*\()(.*)\)",remark)
if m:
sortidx = sortidx + (m.group(2)+" "*40)[0:40] + "-Z"
else:
sortidx = sortidx + (re.sub(r"^(\+\-|\+\+)","",remark) + " "*40)[0:40] + "-A"
sortidx = sortidx + ktob
ktoa = re.sub("^"+ukto1,"",ktoa)
if ktoa == "":
ktoa = "-"
maxa = max(maxa,len(ktoa))
maxb = max(maxb,len(ktob))
buchung = datum + " " + ("%13.2f" % betrag) + " " + (maxa0 % ktoa) + " " + (maxb0 % ktob) + " "
sp = ""
if re.search(r"^\d\d? +v\.?H\.? ",entry[4]): # USt-Einrueckung
sp = " "
if anz == 1:
text_extern.append([buchung," " + sp + remark,betrag,sortidx])
else:
text_intern.append([buchung + " 0.00 " + sp + remark,"","",sortidx])
text_intern.sort(key=lambda x: x[3])
text_extern.sort(key=lambda x: x[3])
# self.mark("Start Salden")
fac = 1
for kto in ("KTOA","KTOB"):
qstr = " select " + kto + ",sum(BETRAG) from buchungen "
qstr = qstr + " where " + kto + " like '" + ktodata['UKTO1'] + "%'"
qstr = qstr + " and DATUM >= '" + ktodata['START'] + "' and DATUM <= '" + ktodata['ENDE'] + "' "
qstr = qstr + " group by (" + kto + ")"
cursor.execute(qstr)
while (0 == 0):
entry = cursor.fetchone()
if not entry:
break
ukto = entry[0][ul:]
betrag = float(entry[1])
while (0 == 0):
if not ukto in salden:
salden[ukto] = 0.00000001
salden[ukto] = salden[ukto] + fac * betrag
m = re.search(r"^(.*)\-(.*)$",ukto)
if m:
ukto = m.group(1)
else:
break
fac = -1
# self.mark("Ende Salden")
# print (salden)
ktoliste = [] # Kontenliste sortieren
for kto in salden.keys():
ktoliste.append([kto,self.rules.sortidx(re.sub(r"^-","",kto))])
ktoliste.sort(key=lambda x: x[1])
konten = []
text = []
gesamt = 0.00
for o in text_extern:
gesamt = gesamt + float(o[2])
text.append(o[0]+("%13.2f" % gesamt)+o[1])
text.append("")
for kto0 in ktoliste:
kto = kto0[0]
kto2 = re.sub(r"^\-","",kto)
sp = re.sub(r"[^\-]","",kto)
name = self.get_ktoname(ktodata['UKTO1']+kto,ktodata['START'],ktodata['ENDE'])
if self.rules.empty_line_in_ktolist(kto2):
text.append("")
text.append( ("%-56s" % (("%-20s" % kto2) + name ) ) +
re.sub(r"\-"," ",sp,9999) + ("%13.2f" % salden[kto]) )
if not "-" in kto2:
if not name == "":
name = "__" + name
if not 'UKTODIRS' in ktodata:
ktodata['UKTODIRS'] = {}
ktodata['UKTODIRS'][kto2+name] =1
text.append("")
for o in text_intern:
text.append(o[0])
text.append("")
if not ktodata['INT'] == "":
o = "-" + ktodata['INT']
else:
o = ""
text1 = ktodata['HEADER']
text1 = text1 + ("%-30s" % (ktodata['UKTO'] + o)) + " "
text2 = " " + ktodata['INTERVAL'] + " " + ("%13.2f" % float(gesamt) ) + "\n\n"
text2 = text2 + "\n".join(text) + "\n"
ktodata['NEWHASH'] = self.compute_ktohash(ktodata,t+text1+text2+ktodata['ADDTEXT'])
# if ktodata['NEWHASH'] == "xxxxxx":
# ktodata['NEWHASH'] = ktodata['KTOHASH']
# print ("----->",123)
ktodata['CONTENT'] = text1 + "(" + ktodata['DBHASH'] + ktodata['NEWHASH'] + ")" + text2
if not ktodata['MAXA'] == maxa or not ktodata['MAXB'] == maxb:
ktodata['MAXA'] = maxa
ktodata['MAXB'] = maxb
ktodata['CONTENT'] = ktodata['CONTENT'] + " " # damit der KTOHASH nicht mehr stimmt und neu berechnet wird
#********************************************************************************
def get_ktoname (self,ukto,startdatum="00000000",enddatum="99999999"):
ukto = re.sub(r"\-[123456789ABCIJKLMNPS]$","",ukto)
if 'ktoname' in vars(self):
if ukto[1:] in self.ktoname:
return( self.ktoname[ukto[1:]] )
return("")
cursor = self.db.cursor()
cursor.execute("select KTO,NAME,DATUMA,DATUMB from ktoname where KTO = '" + ukto + "'")
intervals = []
while (0 == 0):
entry = cursor.fetchone()
if not entry:
break
intervals.append([entry[1],entry[2],entry[3]])
if len(intervals) > 0:
interval = intervals[0]
name = interval[0]
else:
name = ""
return(name)
#********************************************************************************
def assign_ausgaben (self,ktodata,tmpkto,idbuch0): # Ordnet Ausgabenkonten automatisch zu
buchgrp = {} # Hier werden die Buchhaltungsgruppen gehalten
zeilen = []
idbuch = []
for o in re.sub(r"\n",",",idbuch0,9999,re.DOTALL).split(","):
if not o.strip() == "":
idbuch.append(o)
zeilennr = 0
for zeile in ktodata['CONTENT'].split("\n"):
zeilen.append(zeile)
m = re.search(r"^(\d\d\d\d\d\d\d\d) +(\-?\d+\.\d\d) +(\S*) +(\S+) +(\-?\d+\.\d\d) +(.*)$",zeile)
if m:
id1 = None
parts = None
for id in idbuch:
m1 = re.search(id,zeile,re.IGNORECASE)
if m1:
id1 = id
parts = []
zaehler = 0
while (0 == 0):
zaehler = zaehler + 1
try:
parts.append(m1.group(zaehler))
except:
break
break
if id1 == None:
parts = []
id1 = re.sub(r"[\+\-\. ]","",m.group(1)+m.group(2)+m.group(6),9999)
if not id1 in buchgrp:
buchgrp[id1] = []
ktob = m.group(4)
if not ktob in self.ktoname: # Konto rueckwaerts ueber den Namen finden
m2 = re.search("^"+tmpkto+"\-(.*)$",ktob)
if m2:
pattern = m2.group(1)
if pattern in self.ktoname_reverse:
ktob = self.ktoname_reverse[pattern]
else:
for name in self.ktoname_reverse:
if pattern in name:
ktob = self.ktoname_reverse[name]
zeilen[-1] = ( m.group(1) + " " + m.group(2) + " " + m.group(3) + " " +
ktob + " " + m.group(5) + " " + m.group(6))
break
buchgrp[id1].append(
{ 'DATUM': m.group(1), 'BETRAG': m.group(2), 'KTOA': m.group(3), 'KTOB': ktob,
'REMARK': m.group(6), 'ZEILENNR': zeilennr, 'CHANGED': 0, 'PARTS': parts } )
zeilennr = zeilennr + 1
ust = {}
for id in buchgrp:
ust[id] = {}
for entry in buchgrp[id]:
m = re.search(r"^(\+\+|\+\-)",entry['REMARK'])
if m:
ust[id][m.group(1)] = 1
o = list(ust[id].keys())
if len(o) == 1:
ust[id] = o[0]
else:
ust[id] = ""
zweiter_durchgang_erforderlich = False
for id in buchgrp:
alle_gegenkonten = {} # erstmal ueberhaupt alle gegenkonten zusammensammeln
for entry in buchgrp[id]:
o = re.sub(r"\-\d\d\d\d\d$","-BETRAG",entry['KTOB'])
alle_gegenkonten[o] = 1
alle_gegenkonten = list( alle_gegenkonten.keys() )
alle_gegenkonten.sort()
if len(alle_gegenkonten) > 2:
print ("ALLE",alle_gegenkonten,id)
if not idbuch0 == "":
zweiter_durchgang_erforderlich = True
if len(alle_gegenkonten) > 1 and tmpkto in alle_gegenkonten: # wenn es mehrere gegenkonto gibt
alle_gegenkonten.remove(tmpkto) # neben dem tmpkto, dann den gemeinsamen Start-String berechnen
common_start = alle_gegenkonten[0]
for o in alle_gegenkonten:
# print ("COMMON",common_start,o)
ul = min(len(common_start),len(o))
common_start = common_start[0:ul]
o = o[0:ul]
while (0 == 0):
if common_start == o:
break
common_start = common_start[:-1]
o = o[:-1]
# print ("COMMON",common_start)
if not len(alle_gegenkonten) == 1:
for entry in buchgrp[id]: # ueberpruefen, ob die Theorie stimmt, nach der die Gegenkonten gemacht sind
if not entry['KTOB'] == tmpkto: # bei allen schon zugeordneteten Konten
o1 = ""
if not len(alle_gegenkonten) == 1:
o1 = "".join( entry['PARTS'] )
if not entry['KTOB'] == common_start + o1:
common_start = None
break
if common_start == None:
continue
for entry in buchgrp[id]: # wenn die Theorie stimmt, dann mit den unbestimmenten Gegenkonten
if entry['KTOB'] == tmpkto: # genauso verfahren und zuordnen
o = ""
if not re.search(r"^(\,+\+|\+\-)",entry['REMARK']):
o = ust[id]
ktob = common_start
if not len(alle_gegenkonten) == 1:
ktob = ktob + "".join( entry['PARTS'] )
m = re.search(r"^(.*)(\-BETRAG$)",ktob)
if m:
betrag = ("%8.7f" % float(entry['BETRAG'])).strip()
betrag = re.sub(r"[\-\.]","",betrag)[0:5]
ktob = m.group(1) + "-" + betrag
zeilen[ entry['ZEILENNR'] ] = (
entry['DATUM'] + " " + entry['BETRAG'] + " " +
entry['KTOA'] + " " + ktob + " 0.00 " + o + entry['REMARK'] )
ktodata['CONTENT'] = "\n".join(zeilen)
if zweiter_durchgang_erforderlich:
self.assign_ausgaben(ktodata,tmpkto,"")
#********************************************************************************
def normalize_text (self,text):
text = re.sub(r"ä", "ae",text,99999999)
text = re.sub(r"ö", "oe",text,99999999)
text = re.sub(r"ü", "ue",text,99999999)
text = re.sub(r"Ä", "Ae",text,99999999)
text = re.sub(r"Ö", "Oe",text,99999999)
text = re.sub(r"Ü", "Ue",text,99999999)
text = re.sub(r"ß", "ss",text,99999999)
text = re.sub(r"a\"", "ae",text,99999999)
text = re.sub(r"o\"", "oe",text,99999999)
text = re.sub(r"u\"", "ue",text,99999999)
text = re.sub(r"A\"", "Ae",text,99999999)
text = re.sub(r"O\"", "Oe",text,99999999)
text = re.sub(r"U\"", "Ue",text,99999999)
text = re.sub(r"s\"", "ss",text,99999999)
text = re.sub(r"&", "u", text,99999999)
text = re.sub(chr(13),"", text,99999999)
return(text)
#******************************************************************************
def ukto_from_betrag (self,betrag):
id = re.sub(r"^\-","",betrag)
id = re.sub("\.","",id)
id = re.sub(r"^(.*?0)0*$","\\1",id)
id = id + "00000" # damit immer 5 Zeichen lang
id = id[0:min(5,len(id))]
return(id)
#******************************************************************************
def compute_teilmengen (self,elems,laenge,teilmengen=[set()]):
'''
Rechnet alle Teilmengen der Laenge laenge aus der Menge (0,1,...,elems) aus
'''
if type(elems) == type(0):
anzahl = elems
elems = []
while (0 == 0):
anzahl = anzahl - 1
elems.append(anzahl)
if anzahl == 0:
break
newteilmengen = []
for teilmenge in teilmengen:
for elem in elems:
if len(teilmenge) == 0 or elem > max(teilmenge):
o = teilmenge.copy()
o.add(elem)
newteilmengen.append(o)
if laenge == 1:
return(newteilmengen)
else:
return( self.compute_teilmengen (elems,laenge-1,newteilmengen) )
#******************************************************************************
def identify_betrkto (self,idem,betrktos,grenze,laenge=1):
# print ("-->",idem,grenze,laenge)
'''
Diese Funktion bringt, wenn moeglich, Betragskonten zusammen, so dass sie
auf Null aufgehen
'''
matchval = list(betrktos.keys())
# print (laenge,betrktos)
if len(matchval) > { 1:99999999, 2:1000, 3:120, 4:50, 5:30, 6:24, 7:20, 8:18, 9:17, 10:16,
11:15, 12:16, 13:15, 14:15, 15:15 } [laenge] or len(matchval) < laenge:
return()
if len(matchval) > { 1:99999999, 2:500, 3:80, 4:60, 5:25, 6:20, 7:15, 8:10, 9:9} [laenge]:
return()
# if len(matchval) > { 1:99999999, 2:300, 3:50, 4:30, 5:20, 6:15, 7:10, 8:8} [laenge]:
# return()
matchsets = self.compute_teilmengen(len(matchval),laenge) # die moeglichen Index-sets
while (0 == 0):
if matchsets == []:
break
matchset = matchsets.pop(0)
summe = 0.00
for i in matchset:
summe = summe + betrktos[ matchval[i] ]
if abs(summe) < grenze:
refkto = []
for i in matchset:
refkto.append( matchval[i] )
del betrktos[ matchval[i] ]
refkto.sort()
refkto = refkto[-1]
# print ("----")
for i in matchset:
# print (matchval[i] )
idem[ matchval[i] ] = refkto
# print ("----")
matchsets1 = matchsets[:] # alle Indexe entfernen, die schon gematcht sind
matchsets = []
for matchset1 in matchsets1:
matchset_weiter_untersuchen = True
for i in matchset:
if i in matchset1:
matchset_weiter_untersuchen = False
break
if matchset_weiter_untersuchen:
matchsets.append(matchset1)
self.identify_betrkto (idem,betrktos,grenze,laenge+1)
#********************************************************************************
def idem_kto (self,ktodata,grenze=0.99):
text = []
buchungen = []
betrktos = {}
for zeile in ktodata['CONTENT'].split("\n"):
m = re.search("^(\d\d\d\d\d) +(\-?\d+\.\d\d) *$",zeile)
if m:
betrkto = "-" + self.ukto_from_betrag(m.group(1))
if betrkto in betrktos:
betrktos[betrkto] = betrktos[betrkto] + float(m.group(2))
else:
betrktos[betrkto] = float(m.group(2))
text.append(zeile)
continue
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)
else:
datum = m.group(1)
betrag = m.group(2)
ktoa = m.group(3)
ktob = m.group(4)
remark = m.group(6)
# betrkto = "-" + self.ukto_from_betrag(betrag)
# if betrkto in betrktos:
# betrktos[betrkto] = betrktos[betrkto] + float(m.group(2))
# else:
# betrktos[betrkto] = float(m.group(2))
buchungen.append([datum,betrag,ktoa,ktob,"0.00",remark])
# print (betrktos)
# exit()
idem = {}
self.identify_betrkto(idem,betrktos,grenze)
# for o in idem:
# if not o == idem[o]:
# print (o,idem[o])
for buchung in buchungen:
if buchung[2] in idem and ("-" + self.ukto_from_betrag(buchung[1])) == buchung[2]:
buchung[2] = idem[ buchung[2] ]
text.append(" ".join(buchung))
# print (ktodata['CONTENT'])
ktodata['CONTENT'] = "\n".join(text) + "\n"
#********************************************************************************
if __name__ == "__main__":
if sys.argv[2] in Account3.__dict__:
Account3.__dict__[sys.argv[2]](Account3(sys.argv[1]),*sys.argv[3:])
else:
Account3.__dict__["cx"](Account3(sys.argv[1]),*sys.argv[2:])