Schema Description
A project could have multiple project items, and a project item could have multiple acquisition costs. For example, capital project #1 contains two project items:
- Qty. 1 production equipment purchased
- One acquisition cost of $5,000 for the purchasing the equipment from a supplier
- Qty. 1 test fixture constructed by staff
- Twelve $1,000 purchases each for total acquisition costs of $12,000.
The production equipment might have only one cost associated with purchasing it. However, the test fixture could have multiple costs associated with constructing it.
Desire
I want to be able to determine the total acquisition costs for each item, and I want to be able to determine the total acquisition costs for each project. Based on the above example:
- Item 1 total acquisition costs = $5,000
- Item 2 total acquisition costs = $12,000
- Capital project total acquisition costs = $17,000
Questions
Should the
total_acquisition_costs
be calculated using Django's aggregates or saved as aDecimalField
on theProject
andProjectItem
models?Should I create a
total_acquisition_costs
property for theProjectItem
andProject
models? My gut feel is yes to create a property.My gut feel is to calculate the values using aggregates, so as to avoid database denormalization. Specifically, I'm leaning toward using Django's aggregate
Sum
function to create atotal_acquisition_costs
property. However, I'm not grokking how to put an aggregate on a model as a property so that it just returns a value instead of a dictionary.
Current Code
Note: My current code does not use Django's aggregate capabilities, but it works.
class ProjectItem(models.Model):
project = models.ForeignKey(CapExProject)
name = models.CharField(max_length=128)
@property
def total_acquisition_costs(self):
acquisition_costs = self.acquisitioncost_set.only(
'amount')
total_acquisition_costs = 0
for acquisition_cost in acquisition_costs:
total_acquisition_costs += acquisition_cost.amount
return total_acquisition_costs
I like your idea of using Sum but making it a property. Something like this should work: