Commit d05c9406 authored by Jérome Perrin's avatar Jérome Perrin

Inventory API now supports a precision= keyword argument to round values to a...

Inventory API now supports a precision= keyword argument to round values to a given precision. In that case, it will return the sum of rounded values; sum(round(stock.quantity, precision))



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@11764 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent da2cb872
...@@ -451,7 +451,8 @@ class SimulationTool (BaseTool): ...@@ -451,7 +451,8 @@ class SimulationTool (BaseTool):
if kw.get('group_by_mirror_node',0): if kw.get('group_by_mirror_node',0):
group_by_expression_list.append('%s.mirror_node_uid' % table) group_by_expression_list.append('%s.mirror_node_uid' % table)
if len(group_by_expression_list): if len(group_by_expression_list):
group_by_expression_list.append('%s.resource_uid' % table) # Always group by resource # Always group by resource
group_by_expression_list.append('%s.resource_uid' % table)
sql_kw['group_by_expression'] = ', '.join(group_by_expression_list) sql_kw['group_by_expression'] = ', '.join(group_by_expression_list)
sql_kw.update(self.portal_catalog.buildSQLQuery(**new_kw)) sql_kw.update(self.portal_catalog.buildSQLQuery(**new_kw))
...@@ -463,7 +464,8 @@ class SimulationTool (BaseTool): ...@@ -463,7 +464,8 @@ class SimulationTool (BaseTool):
'getInventory') 'getInventory')
def getInventory(self, src__=0, ignore_variation=0, standardise=0, def getInventory(self, src__=0, ignore_variation=0, standardise=0,
omit_simulation=0, omit_input=0, omit_output=0, omit_simulation=0, omit_input=0, omit_output=0,
selection_domain=None, selection_report=None, **kw): selection_domain=None, selection_report=None,
precision=None, **kw):
""" """
Returns an inventory of a single or multiple resources on a single or Returns an inventory of a single or multiple resources on a single or
multiple nodes as a single float value multiple nodes as a single float value
...@@ -513,8 +515,8 @@ class SimulationTool (BaseTool): ...@@ -513,8 +515,8 @@ class SimulationTool (BaseTool):
section_filter - only take rows in stock table which section_uid section_filter - only take rows in stock table which section_uid
matches section_filter matches section_filter
mirror_section_filter - only take rows in stock table which mirror_section_uid mirror_section_filter - only take rows in stock table which
matches mirror_section_filter mirror_section_uid matches mirror_section_filter
variation_text - only take rows in stock table with specified variation_text - only take rows in stock table with specified
variation_text. variation_text.
...@@ -568,6 +570,8 @@ class SimulationTool (BaseTool): ...@@ -568,6 +570,8 @@ class SimulationTool (BaseTool):
group_by_sub_variation - (useless on getInventory, but useful on group_by_sub_variation - (useless on getInventory, but useful on
getInventoryList) getInventoryList)
precision - the precision used to round quantities and prices.
**kw - if we want extended selection with more keywords (but **kw - if we want extended selection with more keywords (but
bad performance) check what we can do with bad performance) check what we can do with
buildSqlQuery buildSqlQuery
...@@ -591,7 +595,7 @@ class SimulationTool (BaseTool): ...@@ -591,7 +595,7 @@ class SimulationTool (BaseTool):
standardise=standardise, omit_simulation=omit_simulation, standardise=standardise, omit_simulation=omit_simulation,
omit_input=omit_input, omit_output=omit_output, omit_input=omit_input, omit_output=omit_output,
selection_domain=selection_domain, selection_report=selection_report, selection_domain=selection_domain, selection_report=selection_report,
**sql_kw) precision=precision, **sql_kw)
if src__: if src__:
return result return result
...@@ -640,7 +644,8 @@ class SimulationTool (BaseTool): ...@@ -640,7 +644,8 @@ class SimulationTool (BaseTool):
'getInventoryList') 'getInventoryList')
def getInventoryList(self, src__=0, ignore_variation=0, standardise=0, def getInventoryList(self, src__=0, ignore_variation=0, standardise=0,
omit_simulation=0, omit_input=0, omit_output=0, omit_simulation=0, omit_input=0, omit_output=0,
selection_domain=None, selection_report=None, **kw): selection_domain=None, selection_report=None,
precision=None, **kw):
""" """
Returns a list of inventories for a single or multiple Returns a list of inventories for a single or multiple
resources on a single or multiple nodes, grouped by resource, resources on a single or multiple nodes, grouped by resource,
...@@ -656,7 +661,8 @@ class SimulationTool (BaseTool): ...@@ -656,7 +661,8 @@ class SimulationTool (BaseTool):
standardise=standardise, omit_simulation=omit_simulation, standardise=standardise, omit_simulation=omit_simulation,
omit_input=omit_input, omit_output=omit_output, omit_input=omit_input, omit_output=omit_output,
selection_domain=selection_domain, selection_domain=selection_domain,
selection_report=selection_report, **sql_kw) selection_report=selection_report, precision=precision,
**sql_kw)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getCurrentInventoryList') 'getCurrentInventoryList')
...@@ -694,7 +700,8 @@ class SimulationTool (BaseTool): ...@@ -694,7 +700,8 @@ class SimulationTool (BaseTool):
'getInventoryStat') 'getInventoryStat')
def getInventoryStat(self, src__=0, ignore_variation=0, standardise=0, def getInventoryStat(self, src__=0, ignore_variation=0, standardise=0,
omit_simulation=0, omit_input=0, omit_output=0, omit_simulation=0, omit_input=0, omit_output=0,
selection_domain=None, selection_report=None, **kw): selection_domain=None, selection_report=None,
precision=None, **kw):
""" """
getInventoryStat is the pending to getInventoryList in order to getInventoryStat is the pending to getInventoryList in order to
provide statistics on getInventoryList lines in ListBox such as: provide statistics on getInventoryList lines in ListBox such as:
...@@ -708,7 +715,8 @@ class SimulationTool (BaseTool): ...@@ -708,7 +715,8 @@ class SimulationTool (BaseTool):
standardise=standardise, omit_simulation=omit_simulation, standardise=standardise, omit_simulation=omit_simulation,
omit_input=omit_input, omit_output=omit_output, omit_input=omit_input, omit_output=omit_output,
selection_domain=selection_domain, selection_domain=selection_domain,
selection_report=selection_report, **sql_kw) selection_report=selection_report,
precision=precision, **sql_kw)
return result return result
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
...@@ -786,16 +794,10 @@ class SimulationTool (BaseTool): ...@@ -786,16 +794,10 @@ class SimulationTool (BaseTool):
def getInventoryAssetPrice(self, src__=0, ignore_variation=0, def getInventoryAssetPrice(self, src__=0, ignore_variation=0,
standardise=0, omit_simulation=0, omit_input=0, standardise=0, omit_simulation=0, omit_input=0,
omit_output=0, selection_domain=None, omit_output=0, selection_domain=None,
selection_report=None, **kw): selection_report=None, precision=None, **kw):
""" """
Same thing as getInventory but returns an asset Same thing as getInventory but returns an asset
price rather than an inventory. price rather than an inventory.
TODO:
- Make sure getInventoryAssetPrice API can
support precision defition (ie. calculate the
sum of rounded values)
""" """
sql_kw = self._generateSQLKeywordDict(**kw) sql_kw = self._generateSQLKeywordDict(**kw)
result = self.Resource_zGetInventory( result = self.Resource_zGetInventory(
...@@ -803,7 +805,7 @@ class SimulationTool (BaseTool): ...@@ -803,7 +805,7 @@ class SimulationTool (BaseTool):
standardise=standardise, omit_simulation=omit_simulation, standardise=standardise, omit_simulation=omit_simulation,
omit_input=omit_input, omit_output=omit_output, omit_input=omit_input, omit_output=omit_output,
selection_domain=selection_domain, selection_report=selection_report, selection_domain=selection_domain, selection_report=selection_report,
**sql_kw) precision=precision, **sql_kw)
if src__ : if src__ :
return result return result
...@@ -853,7 +855,7 @@ class SimulationTool (BaseTool): ...@@ -853,7 +855,7 @@ class SimulationTool (BaseTool):
def getInventoryHistoryList(self, src__=0, ignore_variation=0, def getInventoryHistoryList(self, src__=0, ignore_variation=0,
standardise=0, omit_simulation=0, omit_input=0, standardise=0, omit_simulation=0, omit_input=0,
omit_output=0, selection_domain=None, omit_output=0, selection_domain=None,
selection_report=None, **kw): selection_report=None, precision=None, **kw):
""" """
Returns a time based serie of inventory values Returns a time based serie of inventory values
for a single or a group of resource, node, section, etc. This is useful for a single or a group of resource, node, section, etc. This is useful
...@@ -869,7 +871,8 @@ class SimulationTool (BaseTool): ...@@ -869,7 +871,8 @@ class SimulationTool (BaseTool):
standardise=standardise, omit_simulation=omit_simulation, standardise=standardise, omit_simulation=omit_simulation,
omit_input=omit_input, omit_output=omit_output, omit_input=omit_input, omit_output=omit_output,
selection_domain=selection_domain, selection_domain=selection_domain,
selection_report=selection_report, **sql_kw) selection_report=selection_report, precision=precision,
**sql_kw)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getInventoryHistoryChart') 'getInventoryHistoryChart')
...@@ -877,7 +880,7 @@ class SimulationTool (BaseTool): ...@@ -877,7 +880,7 @@ class SimulationTool (BaseTool):
standardise=0, omit_simulation=0, standardise=0, omit_simulation=0,
omit_input=0, omit_output=0, omit_input=0, omit_output=0,
selection_domain=None, selection_domain=None,
selection_report=None, **kw): selection_report=None, precision=None, **kw):
""" """
getInventoryHistoryChart is the pensing to getInventoryHistoryList getInventoryHistoryChart is the pensing to getInventoryHistoryList
to ease the rendering of time based graphs which show the evolution to ease the rendering of time based graphs which show the evolution
...@@ -892,7 +895,8 @@ class SimulationTool (BaseTool): ...@@ -892,7 +895,8 @@ class SimulationTool (BaseTool):
standardise=standardise, omit_simulation=omit_simulation, standardise=standardise, omit_simulation=omit_simulation,
omit_input=omit_input, omit_output=omit_output, omit_input=omit_input, omit_output=omit_output,
selection_domain=selection_domain, selection_domain=selection_domain,
selection_report=selection_report, **sql_kw) selection_report=selection_report, precision=precision,
**sql_kw)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getMovementHistoryList') 'getMovementHistoryList')
...@@ -901,7 +905,7 @@ class SimulationTool (BaseTool): ...@@ -901,7 +905,7 @@ class SimulationTool (BaseTool):
omit_input=0, omit_output=0, omit_input=0, omit_output=0,
selection_domain=None, selection_report=None, selection_domain=None, selection_report=None,
initial_running_total_quantity=0, initial_running_total_quantity=0,
initial_running_total_price=0, initial_running_total_price=0, precision=None,
**kw): **kw):
"""Returns a list of movements which modify the inventory """Returns a list of movements which modify the inventory
for a single or a group of resource, node, section, etc. for a single or a group of resource, node, section, etc.
...@@ -921,14 +925,14 @@ class SimulationTool (BaseTool): ...@@ -921,14 +925,14 @@ class SimulationTool (BaseTool):
initial_running_total_quantity, initial_running_total_quantity,
initial_running_total_price= initial_running_total_price=
initial_running_total_price, initial_running_total_price,
**sql_kw) precision=precision, **sql_kw)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getMovementHistoryStat') 'getMovementHistoryStat')
def getMovementHistoryStat(self, src__=0, ignore_variation=0, def getMovementHistoryStat(self, src__=0, ignore_variation=0,
standardise=0, omit_simulation=0, omit_input=0, standardise=0, omit_simulation=0, omit_input=0,
omit_output=0, selection_domain=None, omit_output=0, selection_domain=None,
selection_report=None, **kw): selection_report=None, precision=None, **kw):
""" """
getMovementHistoryStat is the pending to getMovementHistoryList getMovementHistoryStat is the pending to getMovementHistoryList
for ListBox stat for ListBox stat
...@@ -938,7 +942,7 @@ class SimulationTool (BaseTool): ...@@ -938,7 +942,7 @@ class SimulationTool (BaseTool):
ignore_variation=ignore_variation, standardise=standardise, ignore_variation=ignore_variation, standardise=standardise,
omit_simulation=omit_simulation, omit_input=omit_input, omit_simulation=omit_simulation, omit_input=omit_input,
omit_output=omit_output, selection_domain=selection_domain, omit_output=omit_output, selection_domain=selection_domain,
selection_report=selection_report, **sql_kw) selection_report=selection_report, precision=precision, **sql_kw)
security.declareProtected(Permissions.AccessContentsInformation, 'getNextNegativeInventoryDate') security.declareProtected(Permissions.AccessContentsInformation, 'getNextNegativeInventoryDate')
def getNextNegativeInventoryDate(self, src__=0, def getNextNegativeInventoryDate(self, src__=0,
......
...@@ -101,6 +101,12 @@ ...@@ -101,6 +101,12 @@
</dictionary> </dictionary>
</value> </value>
</item> </item>
<item>
<key> <string>precision</string> </key>
<value>
<dictionary/>
</value>
</item>
<item> <item>
<key> <string>section_filtered</string> </key> <key> <string>section_filtered</string> </key>
<value> <value>
...@@ -138,20 +144,21 @@ ...@@ -138,20 +144,21 @@
<key> <string>_keys</string> </key> <key> <string>_keys</string> </key>
<value> <value>
<list> <list>
<string>from_table_list</string> <string>from_table_list</string>
<string>where_expression</string> <string>where_expression</string>
<string>order_by_expression</string> <string>order_by_expression</string>
<string>selection_domain</string> <string>selection_domain</string>
<string>selection_report</string> <string>selection_report</string>
<string>ignore_variation</string> <string>ignore_variation</string>
<string>standardize</string> <string>standardize</string>
<string>omit_simulation</string> <string>omit_simulation</string>
<string>omit_input</string> <string>omit_input</string>
<string>omit_output</string> <string>omit_output</string>
<string>section_filtered</string> <string>section_filtered</string>
<string>input_simulation_state</string> <string>input_simulation_state</string>
<string>output_simulation_state</string> <string>output_simulation_state</string>
<string>group_by_expression</string> <string>group_by_expression</string>
<string>precision</string>
</list> </list>
</value> </value>
</item> </item>
...@@ -181,7 +188,8 @@ omit_output\r\n ...@@ -181,7 +188,8 @@ omit_output\r\n
section_filtered\r\n section_filtered\r\n
input_simulation_state:list\r\n input_simulation_state:list\r\n
output_simulation_state:list\r\n output_simulation_state:list\r\n
group_by_expression</string> </value> group_by_expression\r\n
precision</string> </value>
</item> </item>
<item> <item>
<key> <string>cache_time_</string> </key> <key> <string>cache_time_</string> </key>
...@@ -222,9 +230,15 @@ group_by_expression</string> </value> ...@@ -222,9 +230,15 @@ group_by_expression</string> </value>
<value> <string encoding="cdata"><![CDATA[ <value> <string encoding="cdata"><![CDATA[
SELECT\n SELECT\n
SUM(ROUND(stock.quantity,2)) AS inventory,\n <dtml-if expr="precision is not None">\n
SUM(ROUND(stock.quantity,2)) AS total_quantity,\n SUM(ROUND(stock.quantity, <dtml-var precision>)) AS inventory,\n
SUM(ROUND(stock.total_price,2)) AS total_price,\n SUM(ROUND(stock.quantity, <dtml-var precision>)) AS total_quantity,\n
SUM(ROUND(stock.total_price, <dtml-var precision>)) AS total_price,\n
<dtml-else>\n
SUM(stock.quantity) AS inventory,\n
SUM(stock.quantity) AS total_quantity,\n
SUM(stock.total_price) AS total_price,\n
</dtml-if>\n
COUNT(DISTINCT node.title) AS node_title,\n COUNT(DISTINCT node.title) AS node_title,\n
COUNT(DISTINCT node.relative_url) AS node_relative_url,\n COUNT(DISTINCT node.relative_url) AS node_relative_url,\n
COUNT(DISTINCT section.title) AS section_title,\n COUNT(DISTINCT section.title) AS section_title,\n
...@@ -353,9 +367,15 @@ ORDER BY\n ...@@ -353,9 +367,15 @@ ORDER BY\n
<value> <string encoding="cdata"><![CDATA[ <value> <string encoding="cdata"><![CDATA[
SELECT\n SELECT\n
SUM(ROUND(stock.quantity,2)) AS inventory,\n <dtml-if expr="precision is not None">\n
SUM(ROUND(stock.quantity,2)) AS total_quantity,\n SUM(ROUND(stock.quantity, <dtml-var precision>)) AS inventory,\n
SUM(ROUND(stock.total_price,2)) AS total_price,\n SUM(ROUND(stock.quantity, <dtml-var precision>)) AS total_quantity,\n
SUM(ROUND(stock.total_price, <dtml-var precision>)) AS total_price,\n
<dtml-else>\n
SUM(stock.quantity) AS inventory,\n
SUM(stock.quantity) AS total_quantity,\n
SUM(stock.total_price) AS total_price,\n
</dtml-if>\n
COUNT(DISTINCT node.title) AS node_title,\n COUNT(DISTINCT node.title) AS node_title,\n
COUNT(DISTINCT node.relative_url) AS node_relative_url,\n COUNT(DISTINCT node.relative_url) AS node_relative_url,\n
COUNT(DISTINCT section.title) AS section_title,\n COUNT(DISTINCT section.title) AS section_title,\n
......
...@@ -113,6 +113,12 @@ ...@@ -113,6 +113,12 @@
</dictionary> </dictionary>
</value> </value>
</item> </item>
<item>
<key> <string>precision</string> </key>
<value>
<dictionary/>
</value>
</item>
<item> <item>
<key> <string>section_filtered</string> </key> <key> <string>section_filtered</string> </key>
<value> <value>
...@@ -150,22 +156,23 @@ ...@@ -150,22 +156,23 @@
<key> <string>_keys</string> </key> <key> <string>_keys</string> </key>
<value> <value>
<list> <list>
<string>from_table_list</string> <string>from_table_list</string>
<string>where_expression</string> <string>where_expression</string>
<string>order_by_expression</string> <string>order_by_expression</string>
<string>group_by_expression</string> <string>group_by_expression</string>
<string>selection_domain</string> <string>selection_domain</string>
<string>selection_report</string> <string>selection_report</string>
<string>ignore_variation</string> <string>ignore_variation</string>
<string>standardize</string> <string>standardize</string>
<string>omit_simulation</string> <string>omit_simulation</string>
<string>omit_input</string> <string>omit_input</string>
<string>omit_output</string> <string>omit_output</string>
<string>section_filtered</string> <string>section_filtered</string>
<string>initial_running_total_quantity</string> <string>initial_running_total_quantity</string>
<string>initial_running_total_price</string> <string>initial_running_total_price</string>
<string>input_simulation_state</string> <string>input_simulation_state</string>
<string>output_simulation_state</string> <string>output_simulation_state</string>
<string>precision</string>
</list> </list>
</value> </value>
</item> </item>
...@@ -606,7 +613,8 @@ section_filtered\r\n ...@@ -606,7 +613,8 @@ section_filtered\r\n
initial_running_total_quantity\r\n initial_running_total_quantity\r\n
initial_running_total_price\r\n initial_running_total_price\r\n
input_simulation_state:list\r\n input_simulation_state:list\r\n
output_simulation_state:list</string> </value> output_simulation_state:list\r\n
precision</string> </value>
</item> </item>
<item> <item>
<key> <string>cache_time_</string> </key> <key> <string>cache_time_</string> </key>
...@@ -662,8 +670,13 @@ SELECT\n ...@@ -662,8 +670,13 @@ SELECT\n
catalog.uid as uid,\n catalog.uid as uid,\n
catalog.relative_url as relative_url,\n catalog.relative_url as relative_url,\n
stock.date AS date,\n stock.date AS date,\n
<dtml-if expr="precision is not None">\n
ROUND(stock.quantity, <dtml-var precision>) AS total_quantity,\n
ROUND(stock.total_price, <dtml-var precision>) AS total_price,\n
<dtml-else>\n
stock.quantity AS total_quantity,\n stock.quantity AS total_quantity,\n
stock.total_price AS total_price,\n stock.total_price AS total_price,\n
</dtml-if>\n
stock.variation_text AS variation_text,\n stock.variation_text AS variation_text,\n
stock.simulation_state AS simulation_state,\n stock.simulation_state AS simulation_state,\n
stock.mirror_section_uid AS mirror_section_uid,\n stock.mirror_section_uid AS mirror_section_uid,\n
...@@ -814,8 +827,13 @@ SELECT\n ...@@ -814,8 +827,13 @@ SELECT\n
catalog.uid as uid,\n catalog.uid as uid,\n
catalog.relative_url as relative_url,\n catalog.relative_url as relative_url,\n
stock.date AS date,\n stock.date AS date,\n
<dtml-if expr="precision is not None">\n
ROUND(stock.quantity, <dtml-var precision>) AS total_quantity,\n
ROUND(stock.total_price, <dtml-var precision>) AS total_price,\n
<dtml-else>\n
stock.quantity AS total_quantity,\n stock.quantity AS total_quantity,\n
stock.total_price AS total_price,\n stock.total_price AS total_price,\n
</dtml-if>\n
stock.variation_text AS variation_text,\n stock.variation_text AS variation_text,\n
stock.simulation_state AS simulation_state,\n stock.simulation_state AS simulation_state,\n
stock.mirror_section_uid AS mirror_section_uid,\n stock.mirror_section_uid AS mirror_section_uid,\n
......
220 221
\ No newline at end of file \ No newline at end of file
...@@ -73,7 +73,7 @@ class InventoryAPITestCase(ERP5TypeTestCase): ...@@ -73,7 +73,7 @@ class InventoryAPITestCase(ERP5TypeTestCase):
self.portal = self.getPortal() self.portal = self.getPortal()
if not hasattr(self.portal, 'testing_folder'): if not hasattr(self.portal, 'testing_folder'):
self.portal.newContent(portal_type='Folder', self.portal.newContent(portal_type='Folder',
id='testing_folder') id='testing_folder')
self.folder = self.portal.testing_folder self.folder = self.portal.testing_folder
self.section = self._makeOrganisation(title='Section') self.section = self._makeOrganisation(title='Section')
...@@ -472,6 +472,31 @@ class TestInventory(InventoryAPITestCase): ...@@ -472,6 +472,31 @@ class TestInventory(InventoryAPITestCase):
self.assertEquals(getInventory( self.assertEquals(getInventory(
section_uid=self.section.getUid()), 100) section_uid=self.section.getUid()), 100)
def testPrecision(self):
# getInventory supports a precision= argument to specify the precision to
# round
getInventory = self.getSimulationTool().getInventory
getInventoryAssetPrice = self.getSimulationTool().getInventoryAssetPrice
self._makeMovement( quantity=0.1234, price=1 )
self.assertAlmostEquals(0.123,
getInventory(precision=3, node_uid=self.node.getUid()),
places=3)
self.assertAlmostEquals(0.123,
getInventoryAssetPrice(precision=3, node_uid=self.node.getUid()),
places=3)
def testPrecisionAndFloatRoundingIssues(self):
# sum([0.1] * 10) != 1.0 but this is not a problem here
getInventory = self.getSimulationTool().getInventory
getInventoryAssetPrice = self.getSimulationTool().getInventoryAssetPrice
self._makeMovement( quantity=1, price=1 )
for i in range(10):
self._makeMovement( quantity=-0.1, price=1 )
self.assertEquals(0, getInventory(precision=2, node_uid=self.node.getUid()))
self.assertEquals(0, getInventoryAssetPrice(precision=2,
node_uid=self.node.getUid()))
class TestInventoryList(InventoryAPITestCase): class TestInventoryList(InventoryAPITestCase):
"""Tests getInventoryList methods. """Tests getInventoryList methods.
""" """
...@@ -927,6 +952,44 @@ class TestMovementHistoryList(InventoryAPITestCase): ...@@ -927,6 +952,44 @@ class TestMovementHistoryList(InventoryAPITestCase):
node_uid=self.node.getUid(),) node_uid=self.node.getUid(),)
self.assertEquals(2, len(mvt_history_list)) self.assertEquals(2, len(mvt_history_list))
self.assertEquals(0, sum([r.total_quantity for r in mvt_history_list])) self.assertEquals(0, sum([r.total_quantity for r in mvt_history_list]))
def testPrecision(self):
# getMovementHistoryList supports a precision= argument to specify the
# precision to round
getMovementHistoryList = self.getSimulationTool().getMovementHistoryList
self._makeMovement( quantity=0.1234, price=1 )
mvt_history_list = getMovementHistoryList(
precision=2,
node_uid=self.node.getUid())
self.assertEquals(1, len(mvt_history_list))
self.assertEquals(0.12, mvt_history_list[0].running_total_quantity)
self.assertEquals(0.12, mvt_history_list[0].running_total_price)
self.assertEquals(0.12, mvt_history_list[0].total_quantity)
self.assertEquals(0.12, mvt_history_list[0].total_price)
mvt_history_list = getMovementHistoryList(
precision=3,
node_uid=self.node.getUid())
self.assertEquals(1, len(mvt_history_list))
self.assertEquals(0.123, mvt_history_list[0].running_total_quantity)
self.assertEquals(0.123, mvt_history_list[0].running_total_price)
self.assertEquals(0.123, mvt_history_list[0].total_quantity)
self.assertEquals(0.123, mvt_history_list[0].total_price)
def testPrecisionAndFloatRoundingIssues(self):
# sum([0.1] * 10) != 1.0 but this is not a problem here
getMovementHistoryList = self.getSimulationTool().getMovementHistoryList
date = DateTime()
self._makeMovement( quantity=1, price=1, start_date=date )
for i in range(10):
self._makeMovement( quantity=-0.1, price=1, start_date=date+i )
mvt_history_list = getMovementHistoryList(
precision=2,
node_uid=self.node.getUid(),
sort_on=[['stock.date', 'ASC']])
self.assertEquals(11, len(mvt_history_list))
self.assertEquals(0, mvt_history_list[-1].running_total_quantity)
self.assertEquals(0, mvt_history_list[-1].running_total_price)
class TestInventoryStat(InventoryAPITestCase): class TestInventoryStat(InventoryAPITestCase):
"""Tests Inventory Stat methods. """Tests Inventory Stat methods.
......
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