source: remit/finance_core/reporting.py @ af48a00

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

Add row and column totals

  • Property mode set to 100644
File size: 3.6 KB
RevLine 
[13e7c01]1from decimal import Decimal
[162f527]2from django.db.models import Q, Sum
3import finance_core.models
[13e7c01]4
[d1692e8]5def build_table_annotate(line_items, primary_field, secondary_field, primary_axis, secondary_axis, ):
[18149fd]6    # Setup
7    arcprimary = {}
8    arcsecondary = {}
9    table = []
10    zero = Decimal('0.00')
[d1692e8]11    for num, (pk, label, qobj, ) in enumerate(primary_axis):
[18149fd]12        arcprimary[pk] = num
13        table.append([zero]*len(secondary_axis))
[d1692e8]14    for num, (pk, label, qobj, ) in enumerate(secondary_axis):
[18149fd]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:
[d1692e8]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)
[18149fd]28
29    return table
30
[d1692e8]31def build_table_aggregate(line_items, primary_field, secondary_field, primary_axis, secondary_axis):
[13e7c01]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
[162f527]40                total_amount(line_items.filter(primary[2], secondary[2]))
[13e7c01]41            for secondary in secondary_axis]
42        for primary in primary_axis]
43
44    return table
45
46build_table = build_table_annotate
[162f527]47
48
[dd2c3d9]49def get_primary_axis(slug, base_area, term, ):
[18149fd]50    if slug in axes and axes[slug][3]:
[d1692e8]51        return axes[slug][0:2] + (axes[slug][2](base_area, term, ), )
[162f527]52    else:
[3d00b0a]53        raise NotImplementedError
[162f527]54
[dd2c3d9]55def get_secondary_axis(slug, base_area, term, ):
[18149fd]56    if slug in axes and axes[slug][4]:
[d1692e8]57        return axes[slug][0:2] + (axes[slug][2](base_area, term, ), )
[162f527]58    else:
59        raise NotImplementedError
60
[dd2c3d9]61def get_budget_areas(base_area, term, ):
[162f527]62    base_area_depth = base_area.depth
[dd2c3d9]63    areas = base_area.get_descendants()
64    if term:
[ee37f93]65        areas = areas.filter(Q(always=True) | Q(budget_term=term))
[162f527]66    axis = [
67        (
68            area.pk,
69            area.indented_name(base_area_depth),
70            Q(budget_area=area),
71        )
[dd2c3d9]72        for area in areas
[162f527]73    ]
[d1692e8]74    return axis
[162f527]75
[dd2c3d9]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()
[ca03565]81    axis = [
82        (
83            term.pk,
84            term.name,
85            Q(budget_term=term),
86        )
87        for term in terms
88    ]
[d1692e8]89    return axis
[ca03565]90
[dd2c3d9]91def get_layers(base_area, term, ):
[162f527]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    ]
[d1692e8]100    return axis
[162f527]101
[3d00b0a]102axes = {
[18149fd]103    'budget-areas': ('Budget Areas', 'budget_area', get_budget_areas, True,  True,  ),
104    'budget-terms': ('Budget Terms', 'budget_term', get_budget_terms, True,  True,  ),
[d1692e8]105    'layers':       ('Layers',       'layer',       get_layers,       True,  True,  ),
[3d00b0a]106}
107
[a838ee3]108def append_totals(table):
109    # Row totals
110    for row in table:
111        row.append(sum(row))
112    # Column totals
113    if len(table) > 0:
114        totalrow = [None]*len(table[0])
115        for col in xrange(len(table[0])):
116            totalrow[col] = sum([row[col] for row in table])
117        table.append(totalrow)
Note: See TracBrowser for help on using the repository browser.