even quicker badder hack to create something vaguely resembling CSV
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 27 Apr 2021 14:54:05 +0000 (15:54 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 27 Apr 2021 14:54:05 +0000 (15:54 +0100)
src/budget_sync/budget_graph.py
src/budget_sync/main.py

index 5a9542b3edeb1d3b7026fa40075643a7609d9040..164bd0a57791dceef340f612acc732af2a0a454c 100644 (file)
@@ -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:
index ca9ce5137af3ea27fef40e555d12cf55f2357fa9..7c3a36a7bb6436b749131112b5871543e4693f59 100644 (file)
@@ -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()