source: treasury/finance_core/models.py @ 31bd056

client
Last change on this file since 31bd056 was 52c3467, checked in by Alex Dehnert <adehnert@…>, 16 years ago

Add transaction support (WIP)

  • Property mode set to 100644
File size: 5.0 KB
Line 
1from django.db import models
2import settings
3import treebeard.mp_tree
4
5
6class BudgetArea(treebeard.mp_tree.MP_Node):
7    indent_str = u"\u00A0\u00A0"
8
9    name = models.CharField(max_length=50)
10    comment = models.TextField(blank=True)
11    always = models.BooleanField(blank=True, default=False)
12
13    # Contact / ACL information
14    # If not specified, inherit from parent
15    owner = models.EmailField(help_text = 'Email address of the officer responsible for the area', blank=True) # owner of the budget area
16    interested = models.EmailField(help_text='Email address of parties interested in the area', blank=True) # interested parties (ie, whole committee)
17    use_owner = models.BooleanField(default=False, blank=True)
18
19    def contact_address(self,):
20        address = ''
21        if self.use_owner:
22            address = self.owner or self.interested
23        else:
24            address = self.interested or self.owner
25        return address or self.get_parent().contact_address()
26
27    def mark_used(self, term, comment=""):
28        BudgetAreaTerm.objects.get_or_create(
29            budget_area=self,
30            budget_term=term,
31            defaults={'comment':comment}
32        )
33
34    @classmethod
35    def get_by_path(cls, path):
36        root = BudgetArea.objects.get(name=path[0], depth=1)
37        node = root
38        for name in path[1:]:
39            node = node.get_children().filter(name=name)[0]
40        return node
41
42    def dump_to_html(self):
43        struct = self.dump_bulk()
44        return self.struct_to_html(struct, depth=0)
45
46    def struct_to_html(self, struct, depth=0):
47        def format_data(data):
48            return "<em>"+data['name']+"</em> "+unicode(data)
49        prefix = "\t"*depth
50        html = prefix+"<ul>\n"
51        html = html + "\n".join(
52            [("%(prefix)s\t<li>%(data)s\n%(children)s\t%(prefix)s</li>\n" % {
53                'prefix':prefix,
54                'data':format_data(elem['data']),
55                'children':('children' in elem and self.struct_to_html(elem['children'], depth+1) or '')
56            }) for elem in struct])
57        html = html + prefix + "</ul>\n"
58        return html
59
60    def indented_name(self, strip_levels=0):
61        return self.indent_str*(self.depth-strip_levels) + unicode(self)
62
63    def __unicode__(self,):
64        return u"%s [%s] (%s)" % (self.name, self.contact_address(), self.always, )
65
66
67class BudgetTerm(models.Model):
68    name = models.CharField(max_length=20)
69    slug = models.SlugField(max_length=20)
70    start_date = models.DateField()
71    end_date = models.DateField()
72    submit_deadline = models.DateField()
73
74    def __unicode__(self,):
75        return "%s (%s to %s [due %s])" % (self.name, self.start_date, self.end_date, self.submit_deadline, )
76
77
78class BudgetAreaTerm(models.Model):
79    budget_area = models.ForeignKey(BudgetArea)
80    budget_term = models.ForeignKey(BudgetTerm)
81    comment = models.TextField(blank=True, )
82
83    def __unicode__(self,):
84        return "%s during %s" % (self.budget_area, self.budget_term, )
85
86
87class Transaction(models.Model):
88    name = models.CharField(max_length=40)
89    desc = models.TextField(blank=True)
90
91    def __unicode__(self,):
92        return self.name
93
94def make_transfer(name, amount,
95    layer, budget_term, from_area, to_area, desc, ):
96    tx = Transaction(
97        name=name,
98        desc=desc,
99    )
100    tx.save()
101
102    from_li = LineItem(
103        label='Send: %s' % (name, ),
104        amount=-amount,
105        budget_area=from_area,
106        budget_term=budget_term,
107        layer=layer,
108        tx=tx,
109    )
110    from_li.save()
111
112    to_li = LineItem(
113        label='Receive: %s' % (name, ),
114        amount=amount,
115        budget_area=to_area,
116        budget_term=budget_term,
117        layer=layer,
118        tx=tx,
119    )
120    to_li.save()
121
122    return tx
123
124
125class LineItem(models.Model):
126    tx = models.ForeignKey(Transaction)
127    amount = models.DecimalField(max_digits=7, decimal_places=2, help_text='Do not include "$"')
128    label = models.CharField(max_length=40)
129    budget_area = models.ForeignKey(BudgetArea)
130    budget_term = models.ForeignKey(BudgetTerm)
131    layer = models.IntegerField() # this might actually be a Transaction property...
132
133    def layer_string(self,):
134        layer = self.layer
135        return layer_name(get_layer_by_num(layer))
136
137    def __unicode__(self, ):
138        return "%s: %s: $%s (%s) in %s during %s" % (
139            self.tx, self.label, self.amount, self.layer,
140            self.budget_area, self.budget_term, )
141
142
143layers=(
144    (10, 'budget'),
145    (20, 'allocation'),
146    (30, 'expenditure'),
147    (40, 'closeout'),
148)
149def get_layer_by_name(name):
150    for layer in layers:
151        if name == layer[1]:
152            return layer
153    raise KeyError, "layer %s not found" % (name, )
154def get_layer_by_num(num):
155    for layer in layers:
156        if num == layer[0]:
157            return layer
158    raise KeyError, "layer %d not found" % (num, )
159def layer_name(layer): return layer[1]
160def layer_num(layer):  return layer[0]
161
162
163def coerce_full_email(email):
164    if '@' in email: return email
165    else: return email + '@' + settings.DEFAULT_DOMAIN
Note: See TracBrowser for help on using the repository browser.