Commit 20aad2ff authored by Jérome Perrin's avatar Jérome Perrin

Lots of fixes in Balance Transaction class:

 - InventoryKey class, was missing a __cmp__ operator.
 - take into account portal type in inventory queries
 - skip inventory list brain where quantity and total_price == 0
 - also copy ids to temp objects
 - add a missing payment_uid= parameter
 - only calculate section_uid once, as it will not change on lines



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@16539 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 9b2eaca1
...@@ -64,6 +64,17 @@ class InventoryKey(UserDict): ...@@ -64,6 +64,17 @@ class InventoryKey(UserDict):
def __hash__(self): def __hash__(self):
return hash(tuple(self.items())) return hash(tuple(self.items()))
def __cmp__(self, other):
# this is basically here so that we can see if two inventory keys are
# equals.
if tuple(self.keys()) != tuple(other.keys()):
return -1
for k, v in self.items():
if v != other[k]:
return -1
return 0
class BalanceTransaction(AccountingTransaction, Inventory): class BalanceTransaction(AccountingTransaction, Inventory):
"""Balance Transaction """Balance Transaction
...@@ -97,6 +108,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -97,6 +108,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
, PropertySheet.PaymentCondition , PropertySheet.PaymentCondition
) )
def _getGroupByNodeMovementList(self): def _getGroupByNodeMovementList(self):
"""Returns movements that implies only grouping by node.""" """Returns movements that implies only grouping by node."""
movement_list = [] movement_list = []
...@@ -136,15 +148,18 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -136,15 +148,18 @@ class BalanceTransaction(AccountingTransaction, Inventory):
current_stock = dict() current_stock = dict()
getInventoryList = self.getPortalObject()\ getInventoryList = self.getPortalObject()\
.portal_simulation.getInventoryList .portal_simulation.getInventoryList
section_uid = self.getDestinationSectionUid()
default_inventory_params = dict( default_inventory_params = dict(
to_date=self.getStartDate().earliestTime(), to_date=self.getStartDate().earliestTime(),
section_uid=self.getDestinationSectionUid(), section_uid=section_uid,
portal_type=self.getPortalAccountingMovementTypeList(),
simulation_state=('delivered', )) simulation_state=('delivered', ))
# node # node
for movement in self._getGroupByNodeMovementList(): for movement in self._getGroupByNodeMovementList():
node_uid = movement.getDestinationUid() node_uid = movement.getDestinationUid()
section_uid = movement.getDestinationSectionUid() if not node_uid:
raise ValueError, "No destination uid for %s" % movement
stock_list = current_stock.setdefault( stock_list = current_stock.setdefault(
InventoryKey(node_uid=node_uid, InventoryKey(node_uid=node_uid,
...@@ -154,6 +169,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -154,6 +169,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
group_by_node=1, group_by_node=1,
group_by_resource=1, group_by_resource=1,
**default_inventory_params): **default_inventory_params):
if inventory.total_price and inventory.total_quantity:
stock_list.append( stock_list.append(
dict(destination_uid=node_uid, dict(destination_uid=node_uid,
destination_section_uid=section_uid, destination_section_uid=section_uid,
...@@ -164,7 +180,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -164,7 +180,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
# mirror section # mirror section
for movement in self._getGroupByMirrorSectionMovementList(): for movement in self._getGroupByMirrorSectionMovementList():
node_uid = movement.getDestinationUid() node_uid = movement.getDestinationUid()
section_uid = movement.getDestinationSectionUid() if not node_uid:
raise ValueError, "No destination uid for %s" % movement
mirror_section_uid = movement.getSourceSectionUid() mirror_section_uid = movement.getSourceSectionUid()
stock_list = current_stock.setdefault( stock_list = current_stock.setdefault(
...@@ -178,6 +195,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -178,6 +195,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
group_by_mirror_section=1, group_by_mirror_section=1,
group_by_resource=1, group_by_resource=1,
**default_inventory_params): **default_inventory_params):
if inventory.total_price and inventory.total_quantity:
stock_list.append( stock_list.append(
dict(destination_uid=node_uid, dict(destination_uid=node_uid,
destination_section_uid=section_uid, destination_section_uid=section_uid,
...@@ -189,8 +207,9 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -189,8 +207,9 @@ class BalanceTransaction(AccountingTransaction, Inventory):
# payment # payment
for movement in self._getGroupByPaymentMovementList(): for movement in self._getGroupByPaymentMovementList():
node_uid = movement.getDestinationUid() node_uid = movement.getDestinationUid()
if not node_uid:
raise ValueError, "No destination uid for %s" % movement
payment_uid = movement.getDestinationPaymentUid() payment_uid = movement.getDestinationPaymentUid()
section_uid = movement.getDestinationSectionUid()
stock_list = current_stock.setdefault( stock_list = current_stock.setdefault(
InventoryKey(node_uid=node_uid, InventoryKey(node_uid=node_uid,
...@@ -198,10 +217,12 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -198,10 +217,12 @@ class BalanceTransaction(AccountingTransaction, Inventory):
payment_uid=payment_uid), []) payment_uid=payment_uid), [])
for inventory in getInventoryList( for inventory in getInventoryList(
node_uid=node_uid, node_uid=node_uid,
payment_uid=payment_uid,
group_by_node=1, group_by_node=1,
group_by_payment=1, group_by_payment=1,
group_by_resource=1, group_by_resource=1,
**default_inventory_params): **default_inventory_params):
if inventory.total_price and inventory.total_quantity:
stock_list.append( stock_list.append(
dict(destination_uid=node_uid, dict(destination_uid=node_uid,
destination_section_uid=section_uid, destination_section_uid=section_uid,
...@@ -221,6 +242,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -221,6 +242,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
# node # node
for movement in self._getGroupByNodeMovementList(): for movement in self._getGroupByNodeMovementList():
node_uid = movement.getDestinationUid() node_uid = movement.getDestinationUid()
if not node_uid:
raise ValueError, "No destination uid for %s" % movement
section_uid = movement.getDestinationSectionUid() section_uid = movement.getDestinationSectionUid()
stock_list = new_stock.setdefault( stock_list = new_stock.setdefault(
...@@ -230,6 +253,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -230,6 +253,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
dict(destination_uid=node_uid, dict(destination_uid=node_uid,
destination_section_uid=section_uid, destination_section_uid=section_uid,
resource_uid=movement.getResourceUid(), resource_uid=movement.getResourceUid(),
id=movement.getId(),
uid=movement.getUid(), uid=movement.getUid(),
relative_url=movement.getRelativeUrl(), relative_url=movement.getRelativeUrl(),
quantity=movement.getQuantity(), quantity=movement.getQuantity(),
...@@ -239,6 +263,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -239,6 +263,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
# mirror section # mirror section
for movement in self._getGroupByMirrorSectionMovementList(): for movement in self._getGroupByMirrorSectionMovementList():
node_uid = movement.getDestinationUid() node_uid = movement.getDestinationUid()
if not node_uid:
raise ValueError, "No destination uid for %s" % movement
section_uid = movement.getDestinationSectionUid() section_uid = movement.getDestinationSectionUid()
mirror_section_uid = movement.getSourceSectionUid() mirror_section_uid = movement.getSourceSectionUid()
...@@ -251,6 +277,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -251,6 +277,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
destination_section_uid=section_uid, destination_section_uid=section_uid,
source_section_uid=mirror_section_uid, source_section_uid=mirror_section_uid,
resource_uid=movement.getResourceUid(), resource_uid=movement.getResourceUid(),
id=movement.getId(),
uid=movement.getUid(), uid=movement.getUid(),
relative_url=movement.getRelativeUrl(), relative_url=movement.getRelativeUrl(),
quantity=movement.getQuantity(), quantity=movement.getQuantity(),
...@@ -260,6 +287,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -260,6 +287,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
# payment # payment
for movement in self._getGroupByPaymentMovementList(): for movement in self._getGroupByPaymentMovementList():
node_uid = movement.getDestinationUid() node_uid = movement.getDestinationUid()
if not node_uid:
raise ValueError, "No destination uid for %s" % movement
section_uid = movement.getDestinationSectionUid() section_uid = movement.getDestinationSectionUid()
payment_uid = movement.getDestinationPaymentUid() payment_uid = movement.getDestinationPaymentUid()
...@@ -272,6 +301,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -272,6 +301,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
destination_section_uid=section_uid, destination_section_uid=section_uid,
destination_payment_uid=payment_uid, destination_payment_uid=payment_uid,
resource_uid=movement.getResourceUid(), resource_uid=movement.getResourceUid(),
id=movement.getId(),
uid=movement.getUid(), uid=movement.getUid(),
relative_url=movement.getRelativeUrl(), relative_url=movement.getRelativeUrl(),
quantity=movement.getQuantity(), quantity=movement.getQuantity(),
...@@ -286,6 +316,8 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -286,6 +316,8 @@ class BalanceTransaction(AccountingTransaction, Inventory):
_getNewStockDict. Returns a list of dictionnaries with similar keys that _getNewStockDict. Returns a list of dictionnaries with similar keys that
the ones on inventory brains (node, section, mirror_section ...) the ones on inventory brains (node, section, mirror_section ...)
""" """
precision = self.getResourceValue().getQuantityPrecision()
def computeStockDifference(current_stock_list, new_stock_list): def computeStockDifference(current_stock_list, new_stock_list):
# helper function to compute difference between two stock lists. # helper function to compute difference between two stock lists.
if not current_stock_list: if not current_stock_list:
...@@ -297,7 +329,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -297,7 +329,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
matching_diff = None matching_diff = None
for diff in stock_diff_list: for diff in stock_diff_list:
for prop in [k for k in diff.keys() if k not in ('quantity', for prop in [k for k in diff.keys() if k not in ('quantity',
'total_price', 'uid', 'relative_url')]: 'total_price', 'id', 'uid', 'relative_url')]:
if diff[prop] != new_stock.get(prop): if diff[prop] != new_stock.get(prop):
break break
else: else:
...@@ -305,7 +337,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -305,7 +337,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
# matching_diff are negated later # matching_diff are negated later
if matching_diff: if matching_diff:
matching_diff['quantity'] -= new_stock['quantity'] matching_diff['quantity'] -= round(new_stock['quantity'], precision)
# Matching_diff and new_stock must be consistent. # Matching_diff and new_stock must be consistent.
# both with total price or none. # both with total price or none.
if matching_diff['total_price'] and new_stock['total_price']: if matching_diff['total_price'] and new_stock['total_price']:
...@@ -313,10 +345,12 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -313,10 +345,12 @@ class BalanceTransaction(AccountingTransaction, Inventory):
else: else:
stock_diff_list.append(new_stock) stock_diff_list.append(new_stock)
# we were doing with reversed calculation, so negate deltas again. # we were doing with reversed calculation, so negate deltas again.
# Also we remove stocks that have 0 quantity and price. # Also we remove stocks that have 0 quantity and price.
return [negateStock(s) for s in stock_diff_list return [negateStock(s) for s in stock_diff_list
if s['quantity'] and s['total_price']] if round(s['quantity'], precision) and
round(s['total_price'], precision)]
def negateStock(stock): def negateStock(stock):
negated_stock = stock.copy() negated_stock = stock.copy()
...@@ -354,7 +388,7 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -354,7 +388,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
from Products.ERP5Type.Document import newTempBalanceTransactionLine from Products.ERP5Type.Document import newTempBalanceTransactionLine
def factory(*args, **kw): def factory(*args, **kw):
doc = newTempBalanceTransactionLine(self, self.getId(), doc = newTempBalanceTransactionLine(self, kw.pop('id', self.getId()),
uid=self.getUid()) uid=self.getUid())
relative_url = kw.pop('relative_url', None) relative_url = kw.pop('relative_url', None)
destination_total_asset_price = kw.pop('total_price', None) destination_total_asset_price = kw.pop('total_price', None)
...@@ -409,7 +443,6 @@ class BalanceTransaction(AccountingTransaction, Inventory): ...@@ -409,7 +443,6 @@ class BalanceTransaction(AccountingTransaction, Inventory):
diff_list = self._computeStockDifferenceList( diff_list = self._computeStockDifferenceList(
current_stock_dict, current_stock_dict,
new_stock_dict) new_stock_dict)
temp_object_factory = self._getTempObjectFactory() temp_object_factory = self._getTempObjectFactory()
stock_object_list = [] stock_object_list = []
add_obj = stock_object_list.append add_obj = stock_object_list.append
......
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