- def do_GET(self):
- from urllib.parse import urlparse
- self.send_response(200)
- self.send_header("Content-type", "text/html")
- self.end_headers()
- db = Database()
- page = self.header + ''
- parsed_url = urlparse(self.path)
- if parsed_url.path == '/balance':
- page += self.balance_as_html(db)
- elif parsed_url.path == '/add':
- params = parse_qs(parsed_url.query)
- start = int(params.get('start', ['0'])[0])
- end = int(params.get('end', ['0'])[0])
- page += self.add(db, start, end)
- else:
- page += self.ledger_as_html(db)
- page += self.footer
- self.wfile.write(bytes(page, "utf-8"))
-
- def balance_as_html(self, db):
- account_sums = {}
- for booking in db.bookings:
- for account, changes in booking.account_changes.items():
- for currency, amount in changes.items():
- apply_booking_to_account_balances(account_sums, account, currency, amount)
- account_tree = {}
- def collect_branches(account_name, path):
- node = account_tree
- path_copy = path[:]
- while len(path_copy) > 0:
- step = path_copy.pop(0)
- node = node[step]
- toks = account_name.split(":", maxsplit=1)
- parent = toks[0]
- if parent in node.keys():
- child = node[parent]
- else:
- child = {}
- node[parent] = child
- if len(toks) == 2:
- k, v = collect_branches(toks[1], path + [parent])
- if k not in child.keys():
- child[k] = v
- else:
- child[k].update(v)
- return parent, child
- for account_name in sorted(account_sums.keys()):
- k, v = collect_branches(account_name, [])
- if k not in account_tree.keys():
- account_tree[k] = v
+ def write_db(self, text, mode='w'):
+ self.write_text_to_db(text)
+
+ def insert_at_date(self, lines, date):
+ start_at = len(self.real_lines)
+ for b in self.bookings:
+ if b.date_string >= date:
+ start_at = b.start_line
+ break
+ elif b.date_string > date:
+ break
+ if start_at == len(self.real_lines):
+ lines = [''] + lines
+ return self.write_lines_in_total_lines_at(self.real_lines, start_at, lines)
+
+ def update(self, start, end, lines, date):
+ total_lines = self.real_lines[:start] + self.real_lines[end:]
+ n_original_lines = end - start
+ start_at = len(total_lines)
+ for b in self.bookings:
+ if b.date_string == date:
+ if start_at == len(total_lines) or b.start_line == start:
+ start_at = b.start_line
+ if b.start_line > start:
+ start_at -= n_original_lines
+ elif b.date_string > date:
+ break
+ if start_at == len(total_lines):
+ lines = [''] + lines
+ return self.write_lines_in_total_lines_at(total_lines, start_at, lines)
+
+ def write_lines_in_total_lines_at(self, total_lines, start_at, lines):
+ total_lines = total_lines[:start_at] + lines + [''] + total_lines[start_at:]
+ _, _ = parse_lines(lines)
+ text = '\n'.join(total_lines)
+ self.write_db(text)
+ return start_at
+
+ def get_nth_for_booking_of_start_line(self, start_line):
+ nth = 0
+ for b in self.bookings:
+ if b.start_line >= start_line:
+ break
+ nth += 1
+ return nth
+
+ def add_taxes(self, lines, finish=False):
+ ret = []
+ bookings, _ = parse_lines(lines)
+ date = bookings[0].date_string
+ acc_kk_add = 'Reserves:KrankenkassenBeitragsWachstum'
+ acc_kk_minimum = 'Reserves:Month:KrankenkassenDefaultBeitrag'
+ acc_kk = 'Expenses:KrankenKasse'
+ acc_est = 'Reserves:Einkommenssteuer'
+ acc_assets = 'Assets'
+ acc_buffer = 'Reserves:NeuAnfangsPuffer:Ausgaben'
+ last_monthbreak_assets = 0
+ last_monthbreak_est = 0
+ last_monthbreak_kk_minimum = 0
+ last_monthbreak_kk_add = 0
+ buffer_expenses = 0
+ kk_expenses = 0
+ est_expenses = 0
+ months_passed = -int(finish)
+ for b in self.bookings:
+ if date == b.date_string:
+ break
+ acc_keys = b.account_changes.keys()
+ if acc_buffer in acc_keys:
+ buffer_expenses -= b.account_changes[acc_buffer]['€']
+ if acc_kk_add in acc_keys:
+ kk_expenses += b.account_changes[acc_kk_add]['€']
+ if acc_kk in acc_keys:
+ kk_expenses += b.account_changes[acc_kk]['€']
+ if acc_est in acc_keys:
+ est_expenses += b.account_changes[acc_est]['€']
+ if acc_kk_add in acc_keys and acc_kk_minimum in acc_keys:
+ months_passed += 1
+ if finish:
+ last_monthbreak_kk_add = b.account_changes[acc_kk_add]['€']
+ last_monthbreak_est = b.account_changes[acc_est]['€']
+ last_monthbreak_kk_minimum = b.account_changes[acc_kk_minimum]['€']
+ last_monthbreak_assets = b.account_changes[acc_buffer]['€']
+ old_needed_income_before_anything = - last_monthbreak_assets - last_monthbreak_kk_add - last_monthbreak_kk_minimum - last_monthbreak_est
+ if finish:
+ ret += [f' {acc_est} {-last_monthbreak_est}€ ; for old assumption of needed income: {old_needed_income_before_anything}€']
+ _, account_sums = bookings_to_account_tree(bookings)
+ expenses_so_far = -1 * account_sums[acc_assets]['€'] + old_needed_income_before_anything
+ needed_income_before_kk = expenses_so_far
+ ESt_this_month = 0
+ left_over = needed_income_before_kk - ESt_this_month
+ too_low = 0
+ too_high = 2 * needed_income_before_kk
+ E0 = decimal.Decimal(10908)
+ E1 = decimal.Decimal(15999)
+ E2 = decimal.Decimal(62809)
+ E3 = decimal.Decimal(277825)
+ while True:
+ zvE = buffer_expenses - kk_expenses + (12 - months_passed) * needed_income_before_kk
+ if finish:
+ zvE += last_monthbreak_assets + last_monthbreak_kk_add + last_monthbreak_kk_minimum
+ if zvE < E0:
+ ESt = decimal.Decimal(0)
+ elif zvE < E1:
+ y = (zvE - E0)/10000
+ ESt = (decimal.Decimal(979.18) * y + 1400) * y
+ elif zvE < E2:
+ y = (zvE - E1)/10000
+ ESt = (decimal.Decimal(192.59) * y + 2397) * y + decimal.Decimal(966.53)
+ elif zvE < E3:
+ ESt = decimal.Decimal(0.42) * (zvE - decimal.Decimal(62809)) + decimal.Decimal(16405.54)