
| Current Path : /home/ift/ |
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/kto11.py |
# coding: utf
import os,sys,re,glob,time,base64,hashlib,random
#******************************************************************************
class Kto9 ():
def mark (self,remark=""):
t = time.perf_counter()
if 't0' in vars(self):
print ( ("%9.2f" % ((t-self.t0)*1000)) + " ms for: " + remark )
self.t0 = t
#******************************************************************************
def parse_pattern (self,pattern=""): # parse the pattern
self.interval = None
self.pattern = pattern
m = re.search(r"^(.*)([\.\:])(.*)$",pattern)
if m:
self.pattern = m.group(1)
mode = m.group(2)
interval = "20" + m.group(3)[0:2]
months = m.group(3)[2:]
if months == "A":
months = "10"
elif months == "B":
months = "11"
elif months == "C":
months = "12"
elif months == "I":
months = "0[123]"
elif months == "J":
months = "0[456]"
elif months == "K":
months = "0[789]"
elif months == "L":
months = "1[012]"
elif months == "M":
months = "0[123456]"
elif months == "N":
months = "[01][789012]"
elif months == "P":
months = ""
elif not months == "":
months = "0" + months
if mode == ":":
intervals = []
jahr = "2000"
while (0 == 0):
intervals.append(jahr)
jahr = str(int(jahr)+1)
if jahr == interval:
break
month = "01"
while (0 == 0):
intervals.append(jahr+month)
if month in (months,"12"):
break
month = "%02u" % (int(month) + 1)
self.interval = "\\(" + "\\|".join(intervals) + "\\)"
# print(self.interval)
self.egrep = "e"
else:
self.interval = interval + months
self.egrep = ""
#******************************************************************************
def kto_match (self,file): # deliver the matching part of database
pattern1 = re.sub(r"\^"," ",self.pattern,9999)
# print(pattern1,file)
if self.interval:
if self.pattern == "":
self.text_match = os.popen(self.egrep+"grep -i ^"+self.interval + " " + file).read()
else:
self.text_match = os.popen(self.egrep+"grep -i ^"+self.interval + " " + file + " | grep -i '" + pattern1 + "'").read()
else:
if self.pattern == "":
self.text_match = open(file).read()
else:
self.text_match = os.popen("grep -i '" + pattern1 + "' " + file).read()
#******************************************************************************
def kto_rest (self,file): # deliver the rest of the database, not matched by the pattern
pattern1 = re.sub(r"\^"," ",self.pattern,9999)
if self.interval:
if self.pattern == "":
self.text_rest = os.popen(self.egrep+"grep -i -v ^"+self.interval + " " + file).read()
else:
self.text_rest = ( os.popen(self.egrep+"grep -i -v ^"+self.interval + " " + file).read() +
os.popen(self.egrep+"grep -i ^" +self.interval + " " + file +
" | grep -i -v '" + pattern1 + "'").read() )
else:
if self.pattern == "":
self.text_rest = ""
else:
self.text_rest = os.popen("grep -i -v '" + pattern1 + "' " + file).read()
#******************************************************************************
def sync (self,file="",file0="",pattern_new="",add_string=""):
if file == "m":
paths = ['*/*/*/*/*/*/*/*/*/*/',
'*/*/*/*/*/*/*/*/*/',
'*/*/*/*/*/*/*/*/',
'*/*/*/*/*/*/*/',
'*/*/*/*/*/*/',
'*/*/*/*/*/',
'*/*/*/*/',
'*/*/*/',
'*/*/',
'*/'
# ,'.'
]
ktodir = []
for path in paths:
for dir in glob.glob(path):
if not os.path.isdir(dir):
continue
if len(glob.glob(dir+"/*.kto")) == 0:
continue
ktodir.append(dir)
# print(dir)
self.multisync(ktodir)
return()
self.mark("O. Start sync")
self.ukto = None
id = None
zaehler = 0
file1 = file0
while (0 == 0):
db_ktobase = glob.glob(file0+"/*.db.kto")
if len(db_ktobase) == 1:
file0 = db_ktobase[0]
if os.path.isfile(file0):
break
file0 = file0 + "/.."
zaehler = zaehler + 1
if zaehler == 20:
file0 = file
if zaehler > 40:
if pattern_new == "":
id = self.sync(file,".",file1)
else:
print("no parent file found: " + file0)
return(id)
if os.path.isdir(file):
file1 = glob.glob(file+"/*.kto")
if len(file1) > 1:
print("More than one ktofile.")
return()
if len(file1) == 0:
file = file + "/kto.kto"
else:
file = file1[0]
if not re.search(r"\.kto$",file):
id = self.sync(".",file0,file)
return(id)
if not os.path.isfile(file):
self.parse_pattern(pattern_new)
self.kto_match(file0)
open(file,"w").write(" " + pattern_new + "\n" + self.text_match)
return(None)
text = open(file)
keyline = text.readline()
text = text.read()
text2 = keyline + text
pattern = ""
m = re.search(r"\((\S\S\S\S\S\S)\) +(\S+)",keyline)
if not m:
m = re.search(r"\((\S\S\S\S\S\S)\)",keyline)
elif pattern == "":
pattern = m.group(2)
if not m:
if re.search(r"^ +(\S+) *$",keyline):
pattern = keyline.strip()
else:
text = keyline + text
if pattern_new == "":
pattern_new = pattern
if pattern_new == "":
print("No pattern in file: "+file)
os.system("mv "+file+" "+file+".DELETE")
return()
self.parse_pattern(pattern_new)
self.mark("A. Parse pattern")
self.kto_match(file0)
if not pattern_new == pattern: # neues Pattern, daher Datei neu anlegen
# self.kto_match(file0)
open(file,"w").write(" " + pattern_new + "\n" + self.text_match)
return()
if not m:
# self.kto_match(file0)
if not text == self.text_match:
self.kto_rest(file0)
open(file0,"w").write(self.text_rest + text)
open(file,"w").write(" (xxxxxx)\n\n"+text)
return()
key = "xxxxxx"
id = "yyyyyy"
else:
key = m.group(1)
id = self.make_id(0,text.strip()+add_string)
# print("KKK",key,id)
rule_file_exists = False
abs_file = os.path.abspath(file)
m = re.search(r"^(.*)[\\\/](.*)$",abs_file)
if m:
rule_dir = m.group(1)
file1 = m.group(2)
try:
self.rules_done
except:
self.rules_done = []
rule_file_exists = os.path.isfile(rule_dir+"/rule.xxxx") and not rule_dir in (self.rules_done)
self.rule_executed = 0
if not id == key:
if not key == "_rule_" and m:
if rule_file_exists:
orig_dir = os.path.relpath(".",rule_dir)
os.chdir(rule_dir)
print( os.popen("python3 rule.py " + file1).read() )
self.mark(" ... apply rule.")
os.chdir(orig_dir)
text = open(file)
text.readline()
text = text.read()
if len(text) == 0:
text = " "
self.rule_executed = 1
self.rules_done.append(rule_dir)
if self.rule_executed == 0:
os.unlink(file)
text = self.format_kto(text)
else:
self.kto_match(file0)
os.unlink(file)
text = self.format_kto(self.text_match,text.split("\n"))
if not text == None: # and len(text) > 0:
self.kto_rest(file0)
if self.rule_executed == 0:
text0 = self.text_rest + text
open(file0,"w").write(text0)
id0 = id
if self.rule_executed == 1:
id = "_rule_"
else:
id = self.make_id(0,text.strip()+add_string)
# print("XXX",key,id0,id)
if not id0 == id and not key == "_rule_" and not id == key and rule_file_exists:
id = "_chng_"
self.mark(" ... prepare for rule.")
if self.ukto:
open(file,"w").write(("%-25s" % self.ukto) + " " + "(" + id + ") " +
pattern + " " + self.last_sum + "\n\n"+text)
else:
open(file,"w").write(" (" + id + ") " + pattern + "\n\n"+text)
return(id)
else:
open(file,"w").write(text2)
if self.ukto:
return(id)
else:
return(None)
#****************************************************************************************
def make_id (self,mode,text):
profile = False
if profile:
self.mark("--1")
if mode == 9:
text = text.replace(" ","") # for performance reasons, this line doubles the speed!
text = text.replace(" ","").split("\n")
if profile:
self.mark("--2")
text.sort()
text1 = []
for line in text:
line1 = list(line)
line1.sort()
text1.append("".join(line))
if profile:
self.mark("--3")
text = "\n".join(text1)
if profile:
self.mark("--4")
if mode == 1:
# text = text.replace(" ","") # for performance reasons, this line doubles the speed!
# text = text.replace(" ","").split("\n")
text1 = []
for line in text.split("\n"):
m = re.search("^(\d\d\d\d\d\d\d\d) +\-?(\d+\.\d\d) +(\S+) +(\S+) +\S+ +(.*?) *$",line)
if m:
line1 = [m.group(3),m.group(4)]
line1.sort()
line1 = [m.group(1) + m.group(2)] + line1 + [m.group(5)]
# line1.sort()
text1.append("".join(line1))
text1.sort()
text = "\n".join(text1)
if mode == 2:
text1 = []
elements = []
for line in text.split("\n")+["99999999"]:
if len(line) == 8:
if re.search(r"^\d\d\d\d\d\d\d\d$",line):
if len(elements) > 0:
elements_a = elements[1:2]
elements_a.sort()
elements = [ elements[0] ] + elements_a + elements[3:]
text1.append("".join(line))
elements = [line]
else:
elements.append(line)
text1.sort()
text = "\n".join(text1)
text = text.replace(" ","") # for performance reasons, this line doubles the speed!
text = text.replace(" ","")
text = text.replace("\n","XX\n")
id = str( base64.urlsafe_b64encode(hashlib.md5( text.encode("utf-8")).digest()),"ascii" )[0:6]
if profile:
self.mark("--5")
return(id)
#****************************************************************************************
def make_db (self,text):
self.mark("--1")
text = re.sub(r"(\d\d\d\d\d\d\d\d) +(\d+\.\d\d) +(\S+?) +(\S+?) +(\-?\d+\.\d\d) +(.*?) *","---\\1.\\2.\\3.\\4.\\6",text,99999999)
text = re.sub(r"(\d\d\d\d\d\d\d\d) +-(\d+\.\d\d) +(\S+?) +(\S+?) +(\-?\d+\.\d\d) +(.*?) *","---\\1.\\3.\\2.\\4.\\6",text,99999999)
self.mark("--2")
print(text)
self.mark("--3")
#****************************************************************************************
def format_kto (self,text,ktotext_old=[]):
result = self.parse_ktotext(text.split("\n"),self.pattern,ktotext_old)
self.mark("B. parse ktotext.")
if not result:
return(None)
(ktotext,format_maxa,format_maxb,maxsaldo,ukto) = result
print("UKTO: " + ukto)
if ukto == "":
ktotext.sort(key=lambda x:x[0]+str(x[1])+x[3]+x[4])
else:
# if ukto.startswith("10-B12-3695-qu"):
# ktotext.sort(key=lambda x:str(abs(float(x[1])))+str(x[5]+1)+x[0])
# else:
ktotext.sort(key=lambda x:str(x[5]+1)+x[0])
text_match = []
gesamt = 0.00
datum0 = "00000000"
self.ukto0 = ukto
salden = {}
for zeile in ktotext:
if zeile[5] == -1:
text_match.append(zeile[1])
else:
betrag = float(zeile[1])
if ukto == "" or zeile[5] == 0:
saldo = " ...."
elif maxsaldo == 0 or zeile[5] == 1:
gesamt = gesamt + betrag
saldo = "%13.2f" % gesamt
elif zeile[5] == 2:
saldo = " 0.00"
ust = ""
if "v.H." in zeile[4]:
ust = " "
ktoa = zeile[2]
if ktoa[0] == "-":
self.rule_executed = 1
if ktoa == "-":
ktoa = ukto
else:
ktoa = ukto + ktoa
self.compute_salden(salden,ktoa,betrag,zeile[0])
ktob = zeile[3]
if ktob[0] == "-":
self.rule_executed = 1
if ktob == "-":
ktob = ukto
else:
ktob = ukto + ktob
self.compute_salden(salden,ktob,-betrag,zeile[0])
zeile1 = ( zeile[0] + " " + ("%13.2f" % betrag) + " " + (format_maxa % ktoa) + " " +
(format_maxb % ktob) + " " + saldo + " " + ust + re.sub(r" +"," ",zeile[4],9999) )
text_match.append(zeile1)
self.ukto = ukto
if ukto == "":
self.last_sum = ""
else:
self.last_sum = "%20.2f" % gesamt
ktoliste = list(salden.keys())
ktoliste.sort()
text_match.append("")
ktotyp = ["^[^-]+","xxB12-3695","C13-3751","C13-3759","C13-3740","B12-1361",
"C11-3170","C12-3310","B12-1435","B12-1340","B12-3695","Do.-4600","Do.-4610",
"Do.-6011","Do.-6111","Do.-6816","Do.-6817","Do.-6818",
"Bo.-ver","Bo.-kto","Bo.-umlagen","Bo.-1700",
"D..-4100","D..-4105","D..-4106","D..-4400"]
text_match.append(" " + ("%13.2f" % gesamt))
for kto in ktoliste:
bed = 0
if not "-" in kto:
bed = 1
else:
for ktyp in ktotyp:
if re.search("^"+ktyp+r"-[^\-]+$",kto):
bed = 1
break
if bed == 0:
continue
kto_ordnung = max(0,len(re.sub("[^\-]","",kto)))
if kto_ordnung > 3:
continue
kto_ordnung = "%-" + ("%2u"%(20+kto_ordnung*4)) + "s"
text_match.append( (kto_ordnung % kto) + " " + ("%13.2f" % salden[kto]["XX"]) )
self.mark("C. format kto")
return("\n".join(text_match) + "\n")
#******************************************************************************
def compute_salden (self,salden,ukto,betrag,datum):
monat = datum[4:6]
monat = "XX"
ukto = re.sub(r"-qu-","-",ukto)
if ukto.startswith(self.ukto0+"-"):
ukto = re.sub("^"+self.ukto0+"-","",ukto)
else:
return()
# ukto = re.sub(r"^(.*?)\-(.*)$","\\1",ukto)
while (0 == 0):
if not ukto in salden:
salden[ukto] = {}
if not monat in salden[ukto]:
salden[ukto][monat] = 0.00
salden[ukto][monat] = salden[ukto][monat] + betrag
m = re.search(r"^(.*)\-(.+)$",ukto)
# if not m:
# m = re.search(r"^(.*?)(.+)$",ukto)
if m:
ukto = m.group(1)
else:
return()
# return()
#******************************************************************************
def parse_ktotext (self,ktotext,pattern,ktotext_old=[]):
buchungen = []
unique_strings = {}
pattern = pattern.strip().upper()
if len(pattern) > 0 and pattern[-1] == "-":
pattern = pattern[:-1]
maxa = 10
maxb = 10
maxc = 0
maxd = 0
maxsaldo = 0
ukto = ""
if pattern == "":
ukto = None
# ktotext_old.sort()
self.kto_is_up_to_date_until_now = int(not ktotext_old == [])
zaehler = -1
vvv = re.compile(r"^(\d\d\d\d)(..)(\d\d) +(\S+) +(\S+) +(\S+) +(\-?\d+\.\d\d|\-+|\.+) +(.*?) *$")
# ktotext.sort()
for zeile in ktotext:
mm = vvv.search(zeile)
if not mm: # Einlesen der Kontobezeichnungen
# buchungen.append(["00000000",zeile,"","","",-1])
continue
if mm.group(2) == "MM":
monate = ["01","02","03","04","05","06","07","08","09","10","11","12"]
else:
monate = [mm.group(2)]
for monat in monate:
datum = mm.group(1) + monat + mm.group(3)
try:
betrag = "%3.2f" % eval(mm.group(4))
except:
print(mm.group(4))
exit()
remark = mm.group(8)
uniqu = []
ktoa = "^" + mm.group(5)
ktob = "^" + mm.group(6)
# ktoa = self.parse_ktotext_compute_kto(m.group(5),self.ukto,uniqu)
# ktob = self.parse_ktotext_compute_kto(m.group(6),self.ukto,uniqu)
if ktoa > ktob:
o = ktoa # um Eindeutigkeit zu schaffen. Sonst kann es durch
ktoa = ktob # Hin- und Herschwingen zu Endlos-Loops kommen
ktob = o
betrag = re.sub(r"^--","","-"+betrag)
if not ktoa[1] == "-" and not pattern in ktoa.upper() and pattern in ktob.upper():
o = ktoa # um das gefundene Konto an den Anfang zu stellen
ktoa = ktob
ktob = o
betrag = re.sub(r"^--","","-"+betrag)
saldo = 0
# print(zeile)
if not ukto == None:
if ukto == "":
if pattern in ktoa.upper() and not ktoa[1] == "-":
ukto = ktoa
for kto in (ktoa,ktob):
if pattern in kto.upper() and not kto[1] == "-":
while (0 == 0):
if kto.startswith(ukto):
break
m = re.search(r"^(.*)\-(.*)$",ukto)
if m:
ukto = m.group(1)
else:
ukto = ""
print(" fit ukto: " + ukto.replace("^",""))
if not pattern in ukto.upper():
ukto = None
print("No ukto found.")
break
# print(123)
if ukto:
while (0 == 0):
# print(pattern,ukto)
m = re.search(r"^(.*)\-(.*)$",ukto)
if not m or not pattern in m.group(1).upper():
break
ukto = m.group(1)
if ukto or ktoa[1] == "-":
saldo = ( int( ukto and ktoa.startswith(ukto) or ktoa[1] == "-") +
int( ukto and ktob.startswith(ukto) or ktob[1] == "-") )
# print(ktoa,ktob,ukto,saldo,betrag)
if uniqu == []:
uniqu = [ktoa,ktob]
maxsaldo = max(maxsaldo,saldo)
uniqu1 = []
for k in uniqu:
uniqu1.append(re.sub(r"\-\d\d\d\d\d$","-BETRAG",k))
uniqu = uniqu1
betrag1 = re.sub("\-","",betrag) + ","
remark1 = "," + re.sub(r"[\+\- ]","",remark,9999)
uniqu = betrag1 + ",".join(uniqu) + remark1
if datum in unique_strings: # to avoid double entries
if uniqu in unique_strings[datum]:
continue # der Eintrag mit diesem unique-String existiert schon, daher nicht nochmal nehmen
else:
unique_strings[datum].append(uniqu)
else:
unique_strings[datum] = [uniqu]
ktoa = ktoa.replace("^","")
ktob = ktob.replace("^","")
if ktoa[0] == "-":
maxc = max(maxc,len(ktoa))
else:
maxa = max(maxa,len(ktoa))
if ktob[0] == "-":
maxd = max(maxd,len(ktob))
else:
maxb = max(maxb,len(ktob))
buchungen.append([datum,betrag,ktoa,ktob,remark,saldo])
# print(buchungen[-1])
# ---- additional check
if self.kto_is_up_to_date_until_now:
while (0 == 0):
zaehler = zaehler + 1
if zaehler < len(ktotext_old):
line = ktotext_old[zaehler]
else:
m1 = None
break
m1 = re.search("^(\d\d\d\d\d\d\d\d) +(\-?\d+\.\d\d) +(\S+) +(\S+) +(\S+) +(.*?) *$",line)
if m1:
break
if m1:
datum1 = m1.group(1)
betrag1 = m1.group(2)
ktoa1 = m1.group(3)
ktob1 = m1.group(4)
remark1 = m1.group(6)
# print(line)
# print(zeile)
# print(datum,datum1)
# print(betrag,betrag1)
# print(ktoa,ktoa1)
# print(ktob,ktob1)
# print(remark,remark1)
if ( not datum1 == datum or not betrag1 == betrag or not remark1 == remark or
not ktoa in (ktoa1,ktob1) or not ktob in (ktoa1,ktob1) ):
self.kto_is_up_to_date_until_now = False
# print(line)
# print(zeile)
else:
self.kto_is_up_to_date_until_now = False
# print(self.kto_is_up_to_date_until_now)
if self.kto_is_up_to_date_until_now:
return(None)
if ukto == None:
ukto = ""
ukto = ukto.replace("^","")
if maxc > 0:
maxa = max(maxa,len(ukto)+maxc)
if maxd > 0:
maxb = max(maxb,len(ukto)+maxd)
format_maxa = "%-" + str(maxa) + "s"
format_maxb = "%-" + str(maxb) + "s"
return(buchungen,format_maxa,format_maxb,str(maxsaldo),ukto)
#******************************************************************************
def xxyy (self,file=".",pattern=None): # file: Ziel
self.mark("")
if os.path.isdir(file): # file is a dir
dir = file
file = dir + "/standard.kto"
else: # file is a file
if pattern:
dir = file
try:
os.mkdir(file)
except:
pass
file = dir + "/standard.kto"
else:
m = re.search(r"^(.*)[\\\/](.*)$",file)
if m:
dir = m.group(1)
else:
dir = "."
files = glob.glob(dir+"/*.kto")
if len(files) == 0:
if pattern:
try:
os.mkdir(dir)
except:
pass
try:
open(file,"w").write("")
except:
print("File " + file + " not able to create.")
return()
else:
print("No ktofile found.")
return()
elif len(files) > 1:
print("More than one ktofile found: " + " ".join(files))
return()
else:
file = files[0]
header = open(file).readline()
header = re.sub(r"\-?\d+\.\d\d *$","",header)
m = re.search(r"^(\S*) *(\(.*?\)) +(.*?) *$",header)
if m:
if pattern:
if not m.group(3) == pattern:
if os.path.isfile(file):
os.unlink(file)
else:
pattern = m.group(3)
self.mark("Kto " + m.group(1) + " found.")
m = re.search(r"^(.*[\\\/])(.*?)[\\\/](|pattern_)([^\\\/]+)\.kto$",os.path.abspath(file))
if m:
os.system("touch " + m.group(1) + m.group(2) + "/" + "rule.py")
if not pattern:
pattern = re.sub(r"\.\.",":",m.group(4),99)
pattern = re.sub(r"^\_","\^",pattern,99)
dir0 = dir # find the source kto
ruledir = None
if os.path.isfile(dir+"/rule.py") or dir[0:4] == "rule":
ruledir = dir
absdir0 = ""
while (0 == 0): # try to find a parent file, starting with the parent directory of dir
dir0 = dir0 + "/.."
absdir = os.path.abspath(dir0)
print(" ... searching parent directory in " + absdir + " ...") # + re.sub(r"^(.*)([\\\/].*)$","\\2",file0) )
if absdir == absdir0:
print("No parent ktofile found.")
return()
absdir0 = absdir
if not os.path.isdir(dir0):
break
files = glob.glob(dir0+"/*.kto")
for file0 in files:
if re.search(r"[\\\/]no\.kto$",file0):
print("No ktofile directories region from here.\n ... give it up in " + absdir + ".")
return()
if not pattern:
pattern0 = self.find_pattern_from_udir( os.path.relpath(dir0,dir)) # not yet implemented
else:
pattern0 = pattern
erg = self.sync(pattern0,file0,file,"",ruledir)
if not erg == 4:
return(erg)
# print("Failing to find parent kto in " + absdir + ".\n ... now try next uppermost parent ktofile directory.")
#******************************************************************************
def multisync (self,ktolist):
ktoids = {}
kto_in_work = []
for kto in ktolist:
if re.search(r"(^|[\\\/])_[^\\\/]+_([\\\/]|$)",kto):
continue
kto_in_work.append(re.sub(r"^(.*)[\\\/](.*.kto)$","\\1",kto))
print(kto_in_work[-1])
zaehler = 0
while (0 == 0):
if len(kto_in_work) == 0:
break
zaehler = (zaehler + 1) % len(ktolist)
# round = int((zaehler + 1) / len(kto_in_work)) + 1
kto = ktolist[zaehler]
if not kto in kto_in_work:
continue
if len(glob.glob(kto+"/*.kto")) == 0:
continue
# bed = False
while (0 == 0):
id = self.sync(kto)
if not id: # if not id in ["_rule_","_chng_"]: # technische id
break
# if not id in ["_rule_","_chng_"]:
if kto in kto_in_work:
kto_in_work.remove(kto)
# if not id:
# continue
kto_in_work.append(kto)
if not kto in ktoids:
ktoids[kto] = []
ktoids[kto].append(id)
print(len(ktoids[kto]),"----",id,kto)
if len(ktoids[kto]) > 1 and ktoids[kto][-2] == ktoids[kto][-1]:
kto_in_work.remove(kto)
# print(ktoids[kto])
# if len(ktoids[kto]) == 0:
# ktoids[kto].append(id)
# else:
# ktoids[kto] = [ ktoids[kto][-1],id ]
# if not ktoids[kto][0] == ktoids[kto][1]:
# kto_in_work.append(kto)
#******************************************************************************
def xxy (self,pattern=None,par=None):
if par:
dir = pattern
pattern = par
try:
os.system("mkdir "+dir)
except:
pass
files = glob.glob(dir+"/*.kto")
if len(files) > 1:
print("More than one file in " + dir)
return()
if len(files) == 1:
file = files[0]
os.unlink(file)
else:
file = dir + "/" + pattern + ".kto"
open(file,"w").write(" ")
pattern = dir
if pattern and (os.path.isdir(pattern) or os.path.isdir(pattern)):
self.yy(pattern) # pattern is a file or a directory
return()
if not pattern:
self.yy()
return()
# if not os.path.isdir("99_tmp"):
# os.mkdir("99_tmp")
tmp_dir = re.sub(r"\:","__",pattern)
tmp_dir = "99_tmp/" + re.sub(r"[^0-9a-zA-Z\\\/]","_",tmp_dir)
# last_dir = ""
# for file in glob.glob("tmp_*/rule.py"):
# last_dir = re.sub(r"[\\\/]rule.py","",file)
# os.unlink(file)
self.yy(tmp_dir,pattern)
os.system("joe " + tmp_dir + "/standard.kto")
for file in glob.glob("99_tmp/*/rule.py"):
os.unlink(file)
os.system("touch " + tmp_dir + "/rule.py")
self.yy(tmp_dir,pattern)
#******************************************************************************
def xxread_file (self,file=None):
if not file:
files = glob.glob("*.kto")
if len(files) == 1:
file = files[0]
text = open(file).read()
try:
pos = text.index("====")
text0 = text[0:pos]
text = text[pos:]
except:
text0 = ""
text1 = []
for zeile in text.split("\n"):
if zeile.startswith("====") or zeile.strip() == "":
continue
m = re.search(r"^(\d\d\d\d\d\d\d\d)( +\S+)( +)(\S+ +)(\S+ +)(\-?\d+\.\d\d| +\-+| +\.+)( +)(.*)$",zeile)
if not m:
text1.append(zeile)
continue
datum = m.group(1)
betrag = m.group(2)
zwa = m.group(3)
ktoa = m.group(4)
ktob = m.group(5)
saldo = m.group(6)
zwb = m.group(7)
remark = m.group(8)
text1.append([datum,betrag,zwa,ktoa,ktob,saldo,zwb,remark])
return(file,text0,text1)
#******************************************************************************
def xxusteuer (self,einnahmenkto,ausgabenkto,gegenkto,file=None):
(file,text0,text1) = self.read_file(file)
einnahmen = {}
ausgaben = {}
text2 = []
for zeile in text1:
if type(zeile) == type(""):
text2.append(zeile)
remark = zeile[7]
if "v.H." in remark:
continue
text2.append("".join(zeile))
if remark[0:2] == '++':
steuersatz = 19
steuerart = "6"
elif remark[0:2] == '+-':
steuersatz = 7
steuerart = "7"
else:
steuersatz = 0
steuerart = ""
datum = zeile[0]
betrag = zeile[1]
zwa = zeile[2]
ktoa = zeile[3]
ktob = zeile[4]
saldo = zeile[5]
zwb = zeile[6]
remark = remark[2:]
jahr = datum[0:4]
format_ktoa = "%-" + str(len(ktoa)) + "s"
format_ktob = "%-" + str(len(ktob)) + "s"
format_betrag = "%" + str(len(betrag)) + ".2f"
betrag = float(betrag)
# ktoa = ktoa.strip()
# ktob = ktob.strip()
if not datum[0:4] in einnahmen:
einnahmen[jahr] = 0.00
if not datum[0:4] in ausgaben:
ausgaben[jahr] = 0.00
netto = betrag - betrag * steuersatz * 0.01 / (1.0 + steuersatz * 0.01)
if ktoa.strip().startswith(einnahmenkto):
einnahmen[jahr] = einnahmen[jahr] + netto
if betrag > 0.0:
ktob = format_ktob % (gegenkto + "-I" + steuerart)
add = "Vorst."
else:
ktob = format_ktob % (gegenkto + "-U" + steuerart)
add = "USt."
elif ktoa.strip().startswith(ausgabenkto):
ausgaben[jahr] = ausgaben[jahr] + netto
if betrag < 0.0:
ktob = format_ktob % (gegenkto + "-U" + steuerart)
add = "USt."
else:
ktob = format_ktob % (gegenkto + "-I" + steuerart)
add = "Vorst."
elif ktob.strip().startswith(einnahmenkto):
einnahmen[jahr] = einnahmen[jahr] - netto
if betrag < 0.0:
ktoa = format_ktoa % (gegenkto + "-U" + steuerart)
add = "USt."
else:
ktoa = format_ktoa % (gegenkto + "-I" + steuerart)
add = "Vorst."
elif ktob.strip().startswith(ausgabenkto):
ausgaben[jahr] = ausgaben[jahr] - netto
if betrag > 0.0:
ktoa = format_ktoa % (gegenkto + "-I" + steuerart)
add = "Vorst."
else:
ktoa = format_ktoa % (gegenkto + "-U" + steuerart)
add = "USt."
else:
continue
if steuersatz == 0:
continue
ubetrag = format_betrag % (-betrag * steuersatz * 0.01 / (1.0 + steuersatz * 0.01) )
zeile1 = datum + ubetrag + zwa + ktoa + ktob + (" "*(len(saldo)-4)) + "0.00" + zwb + " "
zeile1 = zeile1 + str(steuersatz) + " v.H. " + add + " von " + '%3.2f' % abs(float(betrag))
zeile1 = zeile1 + ' (' + remark + ')'
text2.append(zeile1)
brutto = ""
jahre = list( einnahmen.keys() )
jahre.sort()
for jahr in jahre:
brutto = brutto + jahr + " " + ("%20.2f" % einnahmen[jahr] ) + "\n"
open("einnahmen.txt","w").write(brutto)
brutto = ""
jahre = list( ausgaben.keys() )
jahre.sort()
for jahr in jahre:
brutto = brutto + jahr + " " + ("%20.2f" % ausgaben[jahr] ) + "\n"
open("ausgaben.txt","w").write(brutto)
text2 = "\n".join(text2)
if not text0.strip() == "":
text2 = text0 + '====\n' + text2 + '\n'
open(file,"w").write(text2)
#**************************************************************************************
def xxsync (self,file,file1,pattern):
text = open(file).read()
try:
text1 = open(file1)
except:
text1 = None
if text1:
keyline = text1.readline()
text1 = text1.read()
m = re.search(r"\((\S\S\S\S\S\S)(\S\S\S\S\S\S)\)",keyline)
if m:
key0 = m.group(1)
key1 = m.group(2)
else:
key0 = ""
key1 = ""
text1 = keyline + text1
id0 = str( base64.urlsafe_b64encode(hashlib.md5( text1.encode("utf-8")).digest()),"ascii" )[0:6]
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_match.sort(key=lambda x: x[0:8])
id1 = str( base64.urlsafe_b64encode(hashlib.md5( (pattern+"\n".join(text_match)).encode("utf-8")).digest()),"ascii" )[0:6]
# print(id1,key1,id0,key0)
if text1:
if id1 == key1 or key1 == "":
if id0 == key0:
return(0)
else:
open(file,"w").write("\n".join(text_rest) + "\n" + text1)
print("update parent")
text1 = re.sub(r"^.*?\n(.*)$","\\1",text1)
elif id0 == key0:
text1 = None
else:
print("CONFLICT")
return(1)
if not text1:
text1 = "\n".join(text_match) + "\n"
id0 = str( base64.urlsafe_b64encode(hashlib.md5( text1.encode("utf-8")).digest()),"ascii" )[0:6]
text1 = " ("+id0+id1+")\n" + text1
open(file1,"w").write(text1)
print("update ukto")
return(0)
#******************************************************************************
def xxsort (self,part,pattern="",file=None):
if not file:
files = glob.glob("*.kto")
if len(files) == 1:
file = files[0]
interval = None
insertline = "==== " + pattern + "\n"
m = re.search(r"^(.*)([\.\:])(.*)$",pattern)
if m:
pattern = m.group(1)
mode = m.group(2)
interval = "20" + m.group(3)[0:2]
months = m.group(3)[2:]
if months == "A":
months = "10"
elif months == "B":
months = "11"
elif months == "C":
months = "12"
elif months == "I":
months = "0[123]"
elif months == "J":
months = "0[456]"
elif months == "K":
months = "0[789]"
elif months == "L":
months = "1[012]"
elif months == "M":
months = "0[123456]"
elif months == "N":
months = "[01][789012]"
elif months == "P":
months = ""
elif not months == "":
months = "0" + months
if mode == ":":
intervals = []
jahr = "2000"
while (0 == 0):
if jahr > interval:
break
intervals.append(jahr)
jahr = str(int(jahr)+1)
interval = "\\(" + "\\|".join(intervals) + months + "\\)"
e = "e"
else:
interval = interval + months
e = ""
pattern1 = re.sub(r"\^"," ",pattern,9999)
if part in (1,2):
if interval:
if pattern == "":
text_match = os.popen(e+"grep ^"+interval + " " + file).read()
else:
text_match = os.popen(e+"grep ^"+interval + " " + file + " | grep '" + pattern1 + "'").read()
else:
if pattern == "":
text_match = open(file).read()
else:
text_match = os.popen("grep '" + pattern1 + "' " + file).read()
if part in (1,2):
if interval:
if pattern == "":
if part in (1,2):
text_match = os.popen(e+"grep ^"+interval + " " + file).read()
if part in (0,2):
text_rest = os.popen(e+"grep -v ^"+interval + " " + file).read()
else:
if part in (1,2):
text_match = os.popen(e+"grep ^"+interval + " " + file + " | grep '" + pattern1 + "'").read()
if part in (0,2):
text_rest = ( os.popen(e+"grep -v ^"+interval + " " + file).read() +
os.popen(e+"grep ^"+interval + " " + file + " | grep -v '" + pattern1 + "'").read() )
else:
if pattern == "":
text_match = open(file).read()
text_rest = ""
else:
text_match = os.popen("grep '" + pattern1 + "' " + file).read()
text_rest = os.popen("grep -v '" + pattern1 + "' " + file).read()
self.mark("B1. grep")
self.text_rest = re.sub(r"\n====.*","",text_rest,9999)
if not self.text_rest == "":
self.text_rest = self.text_rest + insertline
# self.text_match = re.sub(r"====.*\n","",text_match[0:100],9999) + text_match[100:]
self.text_match = re.sub(r"====.*\n","",text_match,9999)
self.mark("B2. Combine")
self.pattern = pattern
self.mark("B1. grep")
self.text_rest = re.sub(r"\n====.*","",text_rest,9999)
if not self.text_rest == "":
self.text_rest = self.text_rest + insertline
# self.text_match = re.sub(r"====.*\n","",text_match[0:100],9999) + text_match[100:]
self.text_match = re.sub(r"====.*\n","",text_match,9999)
self.mark("B2. Combine")
self.pattern = pattern
if part in (1,2):
if interval:
if pattern == "":
if part in (1,2):
text_match = os.popen(e+"grep ^"+interval + " " + file).read()
if part in (0,2):
text_rest = os.popen(e+"grep -v ^"+interval + " " + file).read()
else:
if part in (1,2):
text_match = os.popen(e+"grep ^"+interval + " " + file + " | grep '" + pattern1 + "'").read()
if part in (0,2):
text_rest = ( os.popen(e+"grep -v ^"+interval + " " + file).read() +
os.popen(e+"grep ^"+interval + " " + file + " | grep -v '" + pattern1 + "'").read() )
else:
if pattern == "":
text_match = open(file).read()
text_rest = ""
else:
text_match = os.popen("grep '" + pattern1 + "' " + file).read()
text_rest = os.popen("grep -v '" + pattern1 + "' " + file).read()
self.mark("B1. grep")
self.text_rest = re.sub(r"\n====.*","",text_rest,9999)
if not self.text_rest == "":
self.text_rest = self.text_rest + insertline
# self.text_match = re.sub(r"====.*\n","",text_match[0:100],9999) + text_match[100:]
self.text_match = re.sub(r"====.*\n","",text_match,9999)
self.mark("B2. Combine")
self.pattern = pattern
#******************************************************************************
def xxsync (self,pattern,file0,file,add_string="",ruledir=None):
self.mark("A. Sync Start")
self.sort(pattern,file0)
self.mark("B. Sorting")
id0 = self.make_id(self.text_match)
self.text_match.replace(" ","")
id0 = str( base64.urlsafe_b64encode(hashlib.md5( id0.encode("utf-8")).digest()),"ascii" )[0:6]
self.mark("D. Compute db id")
# expr = '"^20[0123456789][0123456789][0123456789][0123456789][0123456789][0123456789] " '
if os.path.isfile(file):
text = open(file)
keyline = text.readline()
text = text.read()
if not re.search(r"\S",text):
key0 = ""
key = ""
id = ""
else:
m = re.search(r"\((\S\S\S\S\S\S)(\S\S\S\S\S\S)\)",keyline)
if m:
key0 = m.group(1)
key = m.group(2)
else:
key0 = id0
key = ""
text = keyline + "\n" + text
id = text + add_string
id = str( base64.urlsafe_b64encode(hashlib.md5( id.encode("utf-8")).digest()),"ascii" )[0:6]
else:
key0 = ""
key = ""
id = ""
self.mark("E. " + " ".join([id0,key0,id,key]))
self.ukto = ""
self.last_sum = ""
if id0 == key0:
if id == key:
open(file0,"w").write(self.text_rest + self.text_match)
erg = 1
else:
self.mark("F. Update database")
if ruledir and os.path.isdir(ruledir):
dir9 = os.path.relpath(".",ruledir)
file1 = re.sub(r"^(.*)[\\\/](.*)$","\\2",file)
os.chdir(ruledir)
os.popen("python3 rule.py " + file1).read()
os.chdir(dir9)
self.mark("F1. ... apply rule.py")
text = open(file).read()
text = "\n" + self.format_kto(text.split("\n")[1:]).strip() + "\n"
# open(file,"w").write(text)
self.mark("F2. ... format kto")
id = text + add_string
id = str( base64.urlsafe_b64encode(hashlib.md5( id.encode("utf-8")).digest()),"ascii" )[0:6]
self.mark("G. Compute kto id")
text0 = os.popen("grep ^20 " + file).read()
# id = text + add_string
# id = str( base64.urlsafe_b64encode(hashlib.md5( id.encode("utf-8")).digest()),"ascii" )[0:6]
id0 = text0.replace(" ","")
id0 = str( base64.urlsafe_b64encode(hashlib.md5( id0.encode("utf-8")).digest()),"ascii" )[0:6]
self.mark("H. Compute db id")
open(file,"w").write(("%-25s" % self.ukto) + " " + "(" + id0 + id + ") " +
pattern + " " + self.last_sum + "\n" + text)
open(file0,"w").write(self.text_rest + text0)
erg = 2
else:
if id == key:
self.mark("E. Update ktofile")
if ruledir and os.path.isdir(ruledir):
self.text_match = self.format_kto(self.text_match.split("\n")[:]).strip() + "\n"
self.mark("F. Format kto")
id0 = self.text_match.replace(" ","")
id0 = str( base64.urlsafe_b64encode(hashlib.md5( id0.encode("utf-8")).digest()),"ascii" )[0:6]
id = "\n" + self.text_match + add_string
id = str( base64.urlsafe_b64encode(hashlib.md5( id.encode("utf-8")).digest()),"ascii" )[0:6]
self.mark("G. Compute kto id")
open(file,"w").write(("%-25s" % self.ukto) + " " + "(" + id0 + id + ") " +
pattern + " " + self.last_sum + "\n\n"+self.text_match)
open(file0,"w").write(self.text_rest + self.text_match)
erg = 3
else:
open(file0,"w").write(self.text_rest + self.text_match)
print("CONFLICT")
erg = 4
return(erg)
#******************************************************************************
def xxsync (self,pattern,file0,file,add_string="",ruledir=None):
self.parse_pattern(pattern)
self.mark("A. Sync Start")
self.kto_match(file0)
self.mark("B. Find matching lines")
id0 = self.make_id(1,self.text_match)
self.mark("C. Compute db id")
if os.path.isfile(file):
text = open(file)
keyline = text.readline()
text = text.read()
if not re.search(r"\S",text):
key0 = ""
key = ""
id = ""
else:
m = re.search(r"\((\S\S\S\S\S\S)(\S\S\S\S\S\S)\)",keyline)
if m:
key0 = m.group(1)
key = m.group(2)
else:
key0 = id0
key = ""
text = keyline + "\n" + text
id = self.make_id(0,text+add_string)
else:
key0 = ""
key = ""
id = ""
self.mark("D. " + " ".join([id0,key0,id,key]))
self.ukto = ""
self.last_sum = ""
if id0 == key0:
if id == key:
# open(file0,"w").write(self.text_rest + self.text_match)
erg = 1
else:
self.mark("E. Update database")
if ruledir and os.path.isdir(ruledir):
dir9 = os.path.relpath(".",ruledir)
file1 = re.sub(r"^(.*)[\\\/](.*)$","\\2",file)
os.chdir(ruledir)
os.popen("python3 rule.py " + file1).read()
os.chdir(dir9)
self.mark("F. ... apply rule.py")
text = open(file).read()
text = "\n" + self.format_kto(text.split("\n")[1:]).strip() + "\n"
# open(file,"w").write(text)
self.mark("G. ... format kto")
id = self.make_id(0,text+add_string)
self.mark("H. Compute kto id")
# text0 = os.popen("grep ^20 " + file + " | grep -o -P '\S+'").read()
text0 = os.popen("grep -P '^\d\d\d\d\d\d\d\d ' " + file).read()
id0 = self.make_id(1,text0)
self.mark("I. Compute db id")
open(file,"w").write(("%-25s" % self.ukto) + " " + "(" + id0 + id + ") " +
pattern + " " + self.last_sum + "\n" + text)
self.kto_rest(file0)
open(file0,"w").write(self.text_rest + text0)
erg = 2
else:
if id == key:
self.mark("E. Update ktofile")
if ruledir and os.path.isdir(ruledir):
self.text_match = self.format_kto(self.text_match.split("\n")[:]).strip() + "\n"
self.mark("F. Format kto")
id0 = self.make_id(1,self.text_match)
id = self.make_id(0,"\n"+self.text_match+add_string)
self.mark("G. Compute kto id")
open(file,"w").write(("%-25s" % self.ukto) + " " + "(" + id0 + id + ") " +
pattern + " " + self.last_sum + "\n\n"+self.text_match)
# open(file0,"w").write(self.text_rest + self.text_match)
erg = 3
else:
# open(file0,"w").write(self.text_rest + self.text_match)
print("CONFLICT")
erg = 4
return(erg)
#******************************************************************************
if __name__ == "__main__":
vars()[sys.argv[1]](*sys.argv[2:])