| 1 | import sys |
|---|
| 2 | import os |
|---|
| 3 | import csv |
|---|
| 4 | import subprocess |
|---|
| 5 | import vouchers.models |
|---|
| 6 | import finance_core.models |
|---|
| 7 | from django.db import connection |
|---|
| 8 | from finance_core.models import BudgetArea |
|---|
| 9 | from finance_core.models import coerce_full_email |
|---|
| 10 | from finance_core.models import Transaction |
|---|
| 11 | from finance_core.models import get_layer_by_name, layer_num |
|---|
| 12 | from decimal import * |
|---|
| 13 | |
|---|
| 14 | columns = ['comm_name','priority','expense_type','start_date','end_date','project','item_name','desc','people','count','costitem','subtotal','per_person','email_list'] |
|---|
| 15 | line_format = "%(priority)-4.4s %(expense_type)-10.10s %(subtotal)10.10s %(project)-16.16s %(item_name)-20.20s %(desc)-20.20s %(people)6.6s %(count)5.5s %(costitem)10.10s" |
|---|
| 16 | |
|---|
| 17 | def build_committees(infile=sys.stdin): |
|---|
| 18 | committees = {} |
|---|
| 19 | reader = csv.reader(infile) |
|---|
| 20 | for comm in reader: |
|---|
| 21 | email_list,chair_list,name,prefer_chair,area,account = comm |
|---|
| 22 | if prefer_chair=='yes': prefer_chair = True |
|---|
| 23 | else: prefer_chair = False |
|---|
| 24 | committees[email_list] = { 'email_list': email_list, 'chair_list': chair_list, 'name': name, 'prefer_chair':prefer_chair, 'area':area, 'account':account} |
|---|
| 25 | return committees |
|---|
| 26 | |
|---|
| 27 | def do_populate_area_structure(): |
|---|
| 28 | nodes = [ |
|---|
| 29 | [ ('Accounts', 'Root',) ], |
|---|
| 30 | [ ('Assets', 'Assets', ) ], |
|---|
| 31 | [ ('Budget', "This period's intended operating budget", ) ], |
|---|
| 32 | [ |
|---|
| 33 | ('Holding', "Holding account for the budgets between income and transferring to committee / line item accounts", ), |
|---|
| 34 | ('Core', "Core budget areas", ), |
|---|
| 35 | ('Committees', "Committees and auxiliary budget areas", ), |
|---|
| 36 | ], |
|---|
| 37 | ] |
|---|
| 38 | parent = None |
|---|
| 39 | for zdepth, accounts in enumerate(nodes): |
|---|
| 40 | depth=zdepth+1 |
|---|
| 41 | for name, comment in accounts: |
|---|
| 42 | if(len(BudgetArea.objects.filter(name=name, depth=depth)) == 0): |
|---|
| 43 | # Create the new node |
|---|
| 44 | if parent: |
|---|
| 45 | parent.add_child(name=name, comment=comment, |
|---|
| 46 | always=True, use_owner=True,) |
|---|
| 47 | else: |
|---|
| 48 | BudgetArea.add_root(name=name, comment=comment, |
|---|
| 49 | always=True, use_owner=True, |
|---|
| 50 | owner='ua-treasurer@mit.edu', |
|---|
| 51 | interested='ua-treasurer@mit.edu', |
|---|
| 52 | account_number=0, |
|---|
| 53 | ) |
|---|
| 54 | # This is sorta evil, in that it abuses the fact that Python |
|---|
| 55 | # won't put name out of scope |
|---|
| 56 | parent = BudgetArea.objects.get(name=name, depth=depth) |
|---|
| 57 | return (depth, ) |
|---|
| 58 | |
|---|
| 59 | def do_populate_committees(committees): |
|---|
| 60 | (depth,) = do_populate_area_structure() |
|---|
| 61 | core = BudgetArea.objects.get(name='Core', depth=depth) |
|---|
| 62 | comms = BudgetArea.objects.get(name='Committees', depth=depth) |
|---|
| 63 | parents = { |
|---|
| 64 | 'Core':core, |
|---|
| 65 | 'Committees':comms, |
|---|
| 66 | } |
|---|
| 67 | for comm in committees.values(): |
|---|
| 68 | parent = parents[comm['area']] |
|---|
| 69 | if len(parent.get_children().filter(name=comm['name'])) > 0: |
|---|
| 70 | pass |
|---|
| 71 | else: |
|---|
| 72 | parent.add_child( |
|---|
| 73 | name=comm['name'], |
|---|
| 74 | owner=coerce_full_email(comm['chair_list']), |
|---|
| 75 | interested=coerce_full_email(comm['email_list']), |
|---|
| 76 | use_owner=comm['prefer_chair'], |
|---|
| 77 | account_number=(comm['account'] or 0), |
|---|
| 78 | always=True, |
|---|
| 79 | ) |
|---|
| 80 | return (depth+1, ) |
|---|
| 81 | |
|---|
| 82 | budget_layer = layer_num(get_layer_by_name('budget')) |
|---|
| 83 | def do_process_rows(committees, budget, term, depth): |
|---|
| 84 | reader = csv.reader(budget) |
|---|
| 85 | |
|---|
| 86 | header = reader.next() |
|---|
| 87 | line_dict = {} |
|---|
| 88 | for key, elem in zip(columns, header,): |
|---|
| 89 | line_dict[key]=elem |
|---|
| 90 | |
|---|
| 91 | budget_source = BudgetArea.get_by_path( |
|---|
| 92 | ['Accounts','Assets','Budget','Holding'] |
|---|
| 93 | ) |
|---|
| 94 | |
|---|
| 95 | for line in reader: |
|---|
| 96 | comm_name,priority,expense_type,start_date,end_date,project,item_name,desc,people,count,costitem,subtotal,perperson,email_list=line |
|---|
| 97 | line_dict = {} |
|---|
| 98 | for key, elem in zip(columns, line,): |
|---|
| 99 | line_dict[key]=elem |
|---|
| 100 | if(email_list != "" and comm_name[-4:] != " Sum"): |
|---|
| 101 | email_list = coerce_full_email(email_list.lower()) |
|---|
| 102 | comm = BudgetArea.objects.get(depth=depth, interested=email_list,) |
|---|
| 103 | projects = comm.get_children().filter(name=project) |
|---|
| 104 | if(len(projects)==0): |
|---|
| 105 | parent_project = comm.add_child( |
|---|
| 106 | name=project, |
|---|
| 107 | always=False, |
|---|
| 108 | ) |
|---|
| 109 | else: parent_project = projects[0] |
|---|
| 110 | parent_project.mark_used(term) |
|---|
| 111 | line_items = parent_project.get_children().filter(name=item_name) |
|---|
| 112 | if(len(line_items)==0): |
|---|
| 113 | line_item_obj = parent_project.add_child( |
|---|
| 114 | name=item_name, |
|---|
| 115 | always=False, |
|---|
| 116 | ) |
|---|
| 117 | else: line_item_obj = line_items[0] |
|---|
| 118 | line_item_obj.mark_used(term) |
|---|
| 119 | amount = Decimal(subtotal.replace('$', '').replace(',', '')) |
|---|
| 120 | finance_core.models.make_transfer( |
|---|
| 121 | item_name, amount, budget_layer, |
|---|
| 122 | term, budget_source, line_item_obj, desc=desc) |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | def main(committees_file, budget_file, term_name, ): |
|---|
| 126 | term = vouchers.models.BudgetTerm.objects.get(name=term_name) |
|---|
| 127 | committees = build_committees(committees_file,) |
|---|
| 128 | (depth, ) = do_populate_committees(committees) |
|---|
| 129 | do_process_rows(committees, budget_file, term, depth) |
|---|
| 130 | |
|---|
| 131 | |
|---|
| 132 | def spring_2010(): |
|---|
| 133 | committee_file = open('/mit/ua/officers/treasurer/resources/software/committees.csv') |
|---|
| 134 | budget_file = open('/mit/ua/officers/treasurer/budgeting/FY10/private/spring-working.csv') |
|---|
| 135 | term_name = 'Spring 2010' |
|---|
| 136 | main(committee_file, budget_file, term_name, ) |
|---|
| 137 | print connection.queries |
|---|
| 138 | |
|---|
| 139 | |
|---|
| 140 | if __name__== '__main__': |
|---|
| 141 | #print "Syntax: %s committee_file format_file budget_file budget_term [override_address]" % (sys.argv[0], ) |
|---|
| 142 | spring_2010() |
|---|