Commit 0434841f authored by Julien Muchembled's avatar Julien Muchembled

amount_generator: make GeneratedAmountList really reusable

parent 7317246e
......@@ -27,6 +27,7 @@
#
##############################################################################
from collections import defaultdict
import zope.interface
from AccessControl import allow_class
from Products.ERP5Type import interfaces
......@@ -35,6 +36,13 @@ class GeneratedAmountList(list):
"""
Temporary object needed to aggregate Amount value
And to calculate some report or total value
For example, delivery.getGeneratedAmountList() returns an object of this
type, with amounts for each movement and/or for the delivery. This result
can be used to get:
1. totals for the delivery, by first using aggregate()
2. detailed information on each movement with split(), which would be
equivalent to call getGeneratedAmountList() on each movement
"""
zope.interface.implements(interfaces.IAmountList)
......@@ -61,6 +69,12 @@ class GeneratedAmountList(list):
return result
def aggregate(self):
"""Return a list of aggregated amounts
Groups amounts with same price, efficiency, reference and categories, merge
them by summing their quantities, and return the new amounts in a new list.
"""
from Products.ERP5Type.Document import newTempAmount
# XXX: Do we handle rounding correctly ?
# What to do if only total price is rounded ??
aggregate_dict = {}
......@@ -71,14 +85,33 @@ class GeneratedAmountList(list):
aggregate = aggregate_dict.get(key)
if aggregate is None:
aggregate_dict[key] = [amount, amount.getQuantity()]
result_list.append(amount)
else:
aggregate[1] += amount.getQuantity()
for amount, quantity in aggregate_dict.itervalues():
# Before we ignore 'quantity==0' amount here for better performance,
# but it is not a good idea, especially when the first expand causes
# non-zero quantity and then quantity becomes zero.
amount._setQuantity(quantity)
aggregate = newTempAmount(amount.aq_parent, '', notify_workflow=False)
result_list.append(aggregate)
aggregate.__dict__.update(amount.__dict__)
aggregate._setQuantity(quantity)
del aggregate._base
return result_list
def split(self):
"""Return a dictionary with all amounts grouped by base amount
Return {amount: amount_list} where
- amount is the Amount instance (e.g. movement, delivery)
that generated amounts
- amount_list is an instance of this class
This is the opposite of aggregate(), which merges amounts that only differ
by their base amounts.
"""
result = defaultdict(self.__class__)
for amount in self:
result[amount._base].append(amount)
return result
allow_class(GeneratedAmountList)
......@@ -474,6 +474,7 @@ class AmountGeneratorMixin:
property_dict['causality_value_list'][-1]
.getRelativeUrl().replace('/', '_'),
notify_workflow=False)
amount._base = delivery_amount
amount._setCategoryList(property_dict.pop('category_list', ()))
if amount.getQuantityUnit():
del property_dict['quantity_unit']
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment