From baff46c1a2f134abb26e82c588f333ea416ab685 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 27 Apr 2021 15:54:05 +0100 Subject: [PATCH] even quicker badder hack to create something vaguely resembling CSV --- src/budget_sync/budget_graph.py | 58 +++++++++++++++++++++++++++++++++ src/budget_sync/main.py | 38 +++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/budget_sync/budget_graph.py b/src/budget_sync/budget_graph.py index 5a9542b..164bd0a 100644 --- a/src/budget_sync/budget_graph.py +++ b/src/budget_sync/budget_graph.py @@ -11,6 +11,52 @@ from collections import deque from datetime import date, time, datetime from collections import OrderedDict +# Originally from http://code.activestate.com/recipes/576694/ +# cut down to minimum + +import collections + +class OrderedSet(collections.MutableSet): + + def __init__(self, iterable=None): + self.end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.map = {} # key --> [key, prev, next] + if iterable is not None: + self |= iterable + + def __len__(self): + return len(self.map) + + def __contains__(self, key): + return key in self.map + + def add(self, key): + if key in self.map: + return + end = self.end + curr = end[1] + curr[2] = end[1] = self.map[key] = [key, curr, end] + + def discard(self, key): + if key in self.map: + key, prev, next = self.map.pop(key) + prev[2] = next + next[1] = prev + + def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + class BudgetGraphBaseError(Exception): pass @@ -753,6 +799,18 @@ class BudgetGraph: self.milestone_payments[node.milestone].append(payment) return retval + def get_milestone_people(self): + """get a list of people associated with each milestone + """ + payments = list(self.payments) # just activate the payments + retval = OrderedDict() + for milestone in self.milestone_payments.keys(): + retval[milestone] = OrderedSet() + for milestone, payments in self.milestone_payments.items(): + for payment in payments: + retval[milestone].add(str(payment.payee.identifier)) + return retval + def __repr__(self): nodes = [*self.nodes.values()] try: diff --git a/src/budget_sync/main.py b/src/budget_sync/main.py index ca9ce51..7c3a36a 100644 --- a/src/budget_sync/main.py +++ b/src/budget_sync/main.py @@ -60,5 +60,43 @@ def main(): "submitted or paid %-9s" % total_req_or_paid) print () + # and one to display peole + milestones_people = budget_graph.get_milestone_people() + for milestone, people in milestones_people.items(): + print (milestone) + for person in people: + print("\t", person) + + # even quicker hack to create something vaguely resembling a CSV file + milestone_csvs = {} + for milestone, payments in budget_graph.milestone_payments.items(): + # first get the list of people, then create some columns + people = milestones_people[milestone] + headings = [] + for person in people: + name = str(person.identifier).replace(" ", "_") + # name, amount, requested (submitted), paid + headings.append(name+"_amount") + headings.append(name+"_req") + headings.append(name+"_paid") + # now we go through the whole "payments" thing again... + milestone_csvs[milestone] = [] # rows in the CSV file + row = {} + for payment in payments: + name = str(payment.payee.identifier).replace(" ", "_") + row[name+"_amount"] = str(payment.amount) + if payment.submitted is not None: + requested = str(payment.submitted) + else: + requested = "" + if payment.paid is not None: + paid = str(payment.paid) + else: + paid = "" + row[name+"_req"] = requested + row[name+"_paid"] = paid + print (row) + milestone_csvs[milestone].append(row) + if __name__ == "__main__": main() -- 2.30.2