source: remit/finance_core/reporting.py @ d1692e8

client
Last change on this file since d1692e8 was d1692e8, checked in by Alex Dehnert <adehnert@…>, 14 years ago

Finally completely punt the old-style annotate

  • Property mode set to 100644
File size: 3.3 KB
Line 
1from decimal import Decimal
2from django.db.models import Q, Sum
3import finance_core.models
4
5def build_table_annotate(line_items, primary_field, secondary_field, primary_axis, secondary_axis, ):
6    # Setup
7    arcprimary = {}
8    arcsecondary = {}
9    table = []
10    zero = Decimal('0.00')
11    for num, (pk, label, qobj, ) in enumerate(primary_axis):
12        arcprimary[pk] = num
13        table.append([zero]*len(secondary_axis))
14    for num, (pk, label, qobj, ) in enumerate(secondary_axis):
15        arcsecondary[pk] = num
16
17    def lineitem_total(obj):
18        if obj['amount__sum'] is None: return zero
19        else: return obj['amount__sum']
20
21    # Do the real work
22    results = line_items.values(primary_field, secondary_field,).annotate(Sum('amount'))
23    for result in results:
24        pkey = arcprimary[result[primary_field]]
25        skey = arcsecondary[result[secondary_field]]
26        assert table[pkey][skey] == zero
27        table[pkey][skey] = lineitem_total(result)
28
29    return table
30
31def build_table_aggregate(line_items, primary_field, secondary_field, primary_axis, secondary_axis):
32    # This uses a simpler but probably slower method
33    zero = Decimal('0.00')
34    def total_amount(queryset):
35        amount = queryset.aggregate(Sum('amount'))['amount__sum']
36        if amount is None: return zero
37        else: return amount
38    table = [ # Primary axis
39            [ # Secondary axis
40                total_amount(line_items.filter(primary[2], secondary[2]))
41            for secondary in secondary_axis]
42        for primary in primary_axis]
43
44    return table
45
46build_table = build_table_annotate
47
48
49def get_primary_axis(slug, base_area, term, ):
50    if slug in axes and axes[slug][3]:
51        return axes[slug][0:2] + (axes[slug][2](base_area, term, ), )
52    else:
53        raise NotImplementedError
54
55def get_secondary_axis(slug, base_area, term, ):
56    if slug in axes and axes[slug][4]:
57        return axes[slug][0:2] + (axes[slug][2](base_area, term, ), )
58    else:
59        raise NotImplementedError
60
61def get_budget_areas(base_area, term, ):
62    base_area_depth = base_area.depth
63    areas = base_area.get_descendants()
64    if term:
65        areas = areas.filter(Q(always=True) | Q(budget_term=term))
66    axis = [
67        (
68            area.pk,
69            area.indented_name(base_area_depth),
70            Q(budget_area=area),
71        )
72        for area in areas
73    ]
74    return axis
75
76def get_budget_terms(base_area, term, ):
77    if term:
78        terms = finance_core.models.BudgetTerm.objects.filter(pk=term.pk)
79    else:
80        terms = finance_core.models.BudgetTerm.objects.all()
81    axis = [
82        (
83            term.pk,
84            term.name,
85            Q(budget_term=term),
86        )
87        for term in terms
88    ]
89    return axis
90
91def get_layers(base_area, term, ):
92    axis = [
93        (
94            finance_core.models.layer_num(layer),
95            finance_core.models.layer_name(layer),
96            Q(layer=finance_core.models.layer_num(layer)),
97        )
98        for layer in finance_core.models.layers
99    ]
100    return axis
101
102axes = {
103    'budget-areas': ('Budget Areas', 'budget_area', get_budget_areas, True,  True,  ),
104    'budget-terms': ('Budget Terms', 'budget_term', get_budget_terms, True,  True,  ),
105    'layers':       ('Layers',       'layer',       get_layers,       True,  True,  ),
106}
107
Note: See TracBrowser for help on using the repository browser.