From 73908cbac70c2db3f909673bc15472730094aae5 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 25 Mar 2026 03:24:16 +0100 Subject: [PATCH] first version, for a small tool, creating files for accounting familyrooms --- main.py | 218 ++++++++++++++++++++++++++++ resources/debitoren.csv | 38 +++++ resources/preise_familienzimmer.csv | 8 + 3 files changed, 264 insertions(+) create mode 100644 main.py create mode 100644 resources/debitoren.csv create mode 100644 resources/preise_familienzimmer.csv diff --git a/main.py b/main.py new file mode 100644 index 0000000..5381887 --- /dev/null +++ b/main.py @@ -0,0 +1,218 @@ +import argparse +import csv + +class Forderung: + def __init__(self )->None: + self.name:list[str] = [] + self.buchungsdatum:str = "" + self.belegdatum:str = "" + #Buchungstext, Buchungsbetrag, Sollkonto, Habenkonto, Steuerschl�ssel, + # Kostenstelle,Kostentr�ger, Zusatzangaben + self.amount:int = 0 + self.text:str = "" + self.soll:int = 0 + self.haben:int = 0 + self.steuerschluessel:int = 0 + self.amount:int = 0 + self.kostenstelle:int = 0 + self.kostentraeger:int = 0 + self.zusatzangaben:int = 0 + + def __str__(self): + return f"Haben {self.haben}, Soll {self.soll}, Amount {self.amount}, Verwendung {self.text}" + + +def print_to_file_lexware(forderungen:dict): + """ + print Forderungen to a file, that can be read by lexware according the following format: + "Belegdatum";"Buchungsdatum";"Buchungstext"; "Buchungsbetrag"; "Sollkonto";"Habenkonto";"Kostenstelle" + 01.03.2025; 19.02.2026;2; "Miete Familienzimmer"; 357,08; 12161; 4107; 200 + """ + names = read_account_names("resources/debitoren.csv",";") + for period, forderung in forderungen.items(): + if forderung !={}: + filename = f"output/{period[0]}-{period[1]:02d}_Forderungen_Familienzimmer.csv" + with open(filename, "w") as file: + file.write("\"Belegdatum\";\"Buchungsdatum\";\"Buchungstext\";\"Buchungsbetrag\";\"Sollkonto\";\"Habenkonto\";\"Kostenstelle\"\n") + for key in forderung: + f= forderung[key] + name = names[key] + file.write(f"01.{period[1]:02d}.{period[0]};01.{period[1]:02d}.{period[0]};\"{name} {f.text}\";{f.amount};{key};{f.haben};{f.kostenstelle}\n") + +def create_forderungen_familienzimmer(filename:str, seperator:str, accounts:dict)->list: + forderungen = {} + priceFamilyRooms = readPriceFamilyRooms("resources/preise_familienzimmer.csv", ",") + with open(filename, "r") as file: + reader = csv.DictReader(file) + for row in reader: + name = row["Created by"] + name = name.replace("(", "").replace(")","").replace("ß", "ss").split(" ") + id = getID(accounts, name[1:]) + + month = getMonth(row["End time"].split(" ")[2]) + year = row["End time"].split(" ")[3] + period = (year,month) + if id > 0: + room = row["Room"].replace("\"","") + duration = getDuration(row["Duration"]) + number_person = getNumberPerson(row["Number of guests"]) + price = getPrice(room, priceFamilyRooms, duration, number_person) + print(f"{name[1]} {id} {room} dauer {duration} Tage, personen {number_person} preis {price}") + if period not in forderungen.keys(): + forderungen[period] = {} + if id not in forderungen[period]: + forderungen[period][id]= Forderung() + forderungen[period][id].amount = price + forderungen[period][id].text = f"Miete Familienzimmer {period[0]}-{period[1]:02d}" + forderungen[period][id].kostenstelle = "200" + forderungen[period][id].haben = "4107" + forderungen[period][id].soll = id + else: + forderungen[period][id].amount += price + return forderungen + +def getPrice(room:str, prices:dict, duration:int, numberPerson:int)->int: + """ + calculate the price for one booking, 15 Euro per night, 5 Euro extra per extra person, + if there is no specific number take the max of person + """ + if numberPerson > 0: + return min(prices["proPerson"]*numberPerson+prices["Basis"],prices[room])*duration + else: + return prices[room]*duration + +def readPriceFamilyRooms(filename:str, seperator:str)->dict: + prices = {} + with open(filename, "r") as file: + for line in file: + line = line.strip().replace("\"","").split(seperator) + if len(line) == 2: + prices[line[0]] = int(line[1]) + return prices + +def getNumberPerson(field:str)->int: + if len(field) >0: + return int(field) + else: + return 0 + +def getID(accounts:dict, name:list)->int: + if name[0] in accounts: + return accounts[name[0]] + elif name[1] in accounts: + return accounts[name[1]] + return 0 + +def getMonth(month:str)->int: + month = month.lower() + if month == "january" or month =="januar": + return 1 + elif month == "february" or month =="febuar": + return 2 + elif month == "march" or month =="märz": + return 3 + elif month == "april": + return 4 + elif month == "may" or month =="mai": + return 5 + elif month == "june" or month =="juni": + return 6 + elif month == "july" or month =="juli": + return 7 + elif month == "august": + return 8 + elif month == "september": + return 9 + elif month == "october" or month =="oktober": + return 10 + elif month == "november": + return 11 + elif month == "december" or month =="dezember": + return 12 + else: + return 0 + +def getDuration(duration:str)->int: + duration = duration.split(" ") + if duration[1] == "weeks" or duration[1] == "Woche": + return int(duration[0]) * 7 + elif duration[1] == "days" or duration[1] == "Tage": + return int(duration[0]) + +def read_account_ids(file_name:str, seperator:str)->dict: + """ + Create a dictionary from name to account id for first and last name couples included, + names that are not uniquw will be removed + """ + accounts = {} + doubles = [] + with open(file_name, "r",encoding="ISO-8859-1") as file: + for line in file: + line = line.strip().replace("\"", "").split(seperator) + if len(line) >=2: + id = line[1] + name = line[0].strip() + names = name.replace("-","").replace(";","").replace(",","").split(" ") + for name in names: + if name in accounts: + doubles.append(name) + elif name[0].isupper(): + accounts[name] = int(id) + for twin in doubles: + if twin in accounts: + del accounts[twin] + return accounts + +def read_account_names(file_name:str, seperator:str)->dict: + """ + Create a dictionary from account id to name + """ + names = {} + with open(file_name, "r",encoding="ISO-8859-1") as file: + for line in file: + line = line.strip().replace("\"", "").split(seperator) + if len(line) >=2: + id = int(line[1]) + name = line[0].strip() + names[id] = name + return names + +def list_to_line(data:list)->str: + line = "" + for element in data: + line +=element+"," + return line[:-1] + +def parse_args() -> argparse.Namespace: + """ + Defines and parses command line arguments for this script. + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "bookings", + type=str, + help="the file from which the bookings come", + ) + parser.add_argument( + "accounts", + type=str, + help="the file from which the account id are read", + ) + return parser.parse_args() + +def main(args: argparse.Namespace) -> None: + accounts = read_account_ids(args.accounts, ";") + forderungen = create_forderungen_familienzimmer(args.bookings, ",", accounts) + for f in forderungen.values(): + for i in f.keys(): + print(f"{i} {f[i]}") + print_to_file_lexware(forderungen) + + + # seperator = ';' + #bookings = Booking() + #bookings.read_from_file(args.bookings, seperator) + #bookings.print_to_file(f"2025-{args.month}_Forderungen_Familienzimmer.csv", bookings[1],bookings[1:]) + +if __name__ == "__main__": + main(parse_args()) diff --git a/resources/debitoren.csv b/resources/debitoren.csv new file mode 100644 index 0000000..2128795 --- /dev/null +++ b/resources/debitoren.csv @@ -0,0 +1,38 @@ +"Brühl, Clara";"12020" +"Braungardt Simon, Färber Verena";"12021" +"Classen, Jona";"12030" +"Eilers Maria und Karl-Heinz";"12050" +"Fokuhl, Esther";"12060" +"Fröschen- Ludwig, Brigitte";"12061" +"Hababi Hashim und Mayyadah";"12080" +"Hellgardt Maria";"12081" +"Cuervo Hellgardt, Frida ";"12082" +"Jahnel Svende, Lohmar Martin";"12100" +"Janetzky, Birgit";"12101" +"Kniep Martin und Jana";"12110" +"Khoroshenko Olena, Fomin Andrii";"12111" +"Kottmeier, Anna Paula";"12112" +"Kiser, Gabriele";"12113" +"Lüth, Kyra";"12120" +"Laurenz Eric, Wolf Jennyfer";"12121" +"Mohamed, Youssef";"12130" +"Meinzer Niklas, Deye Christin";"12131" +"Markus, Felix";"12132" +"Niemann Christa, Heitbrink Rolf";"12140" +"Orth Astrid und Stefan";"12150" +"Oelschlaegel Hauke, Nesswetter Hannah";"12151" +"Oberhoffner, Nicolai";"12152" +"Ponomarenko Ivan und Anna";"12160" +"Röder, Brigitte";"12180" +"Reiners Nils, Peter Nina";"12181" +"Schindler Jens, Weiss Rebecca";"12190" +"Scholz, Rotraut";"12191" +"Schultheiss Achim und Brigitte";"12192" +"Taxis, Susanne";"12200" +"Von Keutz, Pia";"12220" +"Vereskun Elena und Valerii";"12221" +"Vogelsang, Leona";"12222" +"Wulff, Svenja";"12230" +"Forderungen Bauleistungsversicherung BHV";"13000" +"Forderungen an Hausverein allmende e.V";"13100" +"Prymak, Valentyna";"10001" diff --git a/resources/preise_familienzimmer.csv b/resources/preise_familienzimmer.csv new file mode 100644 index 0000000..ac507bc --- /dev/null +++ b/resources/preise_familienzimmer.csv @@ -0,0 +1,8 @@ +Basis, 10 +proPerson, 5 +Familienzimmer 1.OG, 25 +1. OG, 20 +2. OG, 20 +3. OG, 20 + +