diff --git a/product/ERP5/Tool/SimulationTool.py b/product/ERP5/Tool/SimulationTool.py index bad810270ce45023528e1adc0b571e906c0c9c7e..7a0ae614487a9d02b27769a7a2b660e5bc77c6c7 100644 --- a/product/ERP5/Tool/SimulationTool.py +++ b/product/ERP5/Tool/SimulationTool.py @@ -865,10 +865,14 @@ class SimulationTool (BaseTool): standardise=0, omit_simulation=0, omit_input=0, omit_output=0, selection_domain=None, selection_report=None, + initial_running_total_quantity=0, + initial_running_total_price=0, **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. + A running total quantity and a running total price are available on + brains. The initial values can be passed, in case you want to have an + "initial summary line". """ sql_kw = self._generateSQLKeywordDict(**kw) return self.Resource_zGetMovementHistoryList( @@ -877,7 +881,12 @@ class SimulationTool (BaseTool): omit_simulation=omit_simulation, omit_input=omit_input, omit_output=omit_output, selection_domain=selection_domain, - selection_report=selection_report, **sql_kw) + selection_report=selection_report, + initial_running_total_quantity= + initial_running_total_quantity, + initial_running_total_price= + initial_running_total_price, + **sql_kw) security.declareProtected(Permissions.AccessContentsInformation, 'getMovementHistoryStat') diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml index 7f71ef061939b39dfb4f34cc686277270cbf27c1..55951cb501193b95f90b97f31f2f85c6c64b8a10 100644 --- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml +++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Resource_zGetMovementHistoryList.xml @@ -55,6 +55,18 @@ <dictionary/> </value> </item> + <item> + <key> <string>initial_running_total_price</string> </key> + <value> + <dictionary/> + </value> + </item> + <item> + <key> <string>initial_running_total_quantity</string> </key> + <value> + <dictionary/> + </value> + </item> <item> <key> <string>input_simulation_state</string> </key> <value> @@ -143,6 +155,8 @@ <string>omit_simulation</string> <string>omit_input</string> <string>omit_output</string> +<string>initial_running_total_quantity</string> +<string>initial_running_total_price</string> <string>input_simulation_state</string> <string>output_simulation_state</string> </list> @@ -587,6 +601,8 @@ standardize\r\n omit_simulation\r\n omit_input\r\n omit_output\r\n +initial_running_total_quantity\r\n +initial_running_total_price\r\n input_simulation_state:list\r\n output_simulation_state:list</string> </value> </item> @@ -628,14 +644,29 @@ output_simulation_state:list</string> </value> <key> <string>src</string> </key> <value> <string encoding="cdata"><![CDATA[ +SET @running_total_quantity := <dtml-var initial_running_total_quantity>,\n + @running_total_price := <dtml-var initial_running_total_price>;\n +\n +<dtml-var sql_delimiter>\n +\n +SELECT \n + q1.*,\n + @running_total_quantity := q1.total_quantity + \n + @running_total_quantity AS running_total_quantity,\n + @running_total_price := q1.total_price + \n + @running_total_price AS running_total_price\n +FROM (\n SELECT\n catalog.path as path,\n catalog.uid as uid,\n catalog.relative_url as relative_url,\n stock.date AS date,\n stock.quantity AS total_quantity,\n + stock.total_price AS total_price,\n stock.variation_text AS variation_text,\n stock.simulation_state AS simulation_state,\n + stock.mirror_section_uid AS mirror_section_uid,\n + stock.mirror_node_uid AS mirror_node_uid,\n node.uid AS node_uid,\n node.title AS node_title,\n node.relative_url AS node_relative_url,\n @@ -714,16 +745,19 @@ WHERE\n <dtml-if selection_report>\n AND <dtml-var "selection_report.asSqlExpression(strict_membership=1)">\n </dtml-if>\n +\n GROUP BY\n <dtml-if group_by_expression>\n <dtml-var group_by_expression>\n <dtml-else>\n stock.uid, stock.node_uid, stock.resource_uid\n </dtml-if>\n +\n <dtml-if order_by_expression>\n ORDER BY\n <dtml-var order_by_expression>\n </dtml-if>\n +) AS q1\n ]]></string> </value> @@ -762,14 +796,29 @@ ORDER BY\n <key> <string>raw</string> </key> <value> <string encoding="cdata"><![CDATA[ +SET @running_total_quantity := <dtml-var initial_running_total_quantity>,\n + @running_total_price := <dtml-var initial_running_total_price>;\n +\n +<dtml-var sql_delimiter>\n +\n +SELECT \n + q1.*,\n + @running_total_quantity := q1.total_quantity + \n + @running_total_quantity AS running_total_quantity,\n + @running_total_price := q1.total_price + \n + @running_total_price AS running_total_price\n +FROM (\n SELECT\n catalog.path as path,\n catalog.uid as uid,\n catalog.relative_url as relative_url,\n stock.date AS date,\n stock.quantity AS total_quantity,\n + stock.total_price AS total_price,\n stock.variation_text AS variation_text,\n stock.simulation_state AS simulation_state,\n + stock.mirror_section_uid AS mirror_section_uid,\n + stock.mirror_node_uid AS mirror_node_uid,\n node.uid AS node_uid,\n node.title AS node_title,\n node.relative_url AS node_relative_url,\n @@ -848,16 +897,19 @@ WHERE\n <dtml-if selection_report>\n AND <dtml-var "selection_report.asSqlExpression(strict_membership=1)">\n </dtml-if>\n +\n GROUP BY\n <dtml-if group_by_expression>\n <dtml-var group_by_expression>\n <dtml-else>\n stock.uid, stock.node_uid, stock.resource_uid\n </dtml-if>\n +\n <dtml-if order_by_expression>\n ORDER BY\n <dtml-var order_by_expression>\n </dtml-if>\n +) AS q1\n ]]></string> </value> diff --git a/product/ERP5/bootstrap/erp5_core/bt/revision b/product/ERP5/bootstrap/erp5_core/bt/revision index 2ebc6516c7df177c819b752dfac7b5ce5064189f..eebd1d10b6ec9917baf4df7f2e3de79e031a9af7 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/revision +++ b/product/ERP5/bootstrap/erp5_core/bt/revision @@ -1 +1 @@ -56 \ No newline at end of file +61 \ No newline at end of file diff --git a/product/ERP5/tests/testInventoryAPI.py b/product/ERP5/tests/testInventoryAPI.py index 45e325ad10026ee7388d505a61ff1023938eb452..54b6438e4c1595379c069adaac77aa4e510c953a 100644 --- a/product/ERP5/tests/testInventoryAPI.py +++ b/product/ERP5/tests/testInventoryAPI.py @@ -849,7 +849,73 @@ class TestMovementHistoryList(InventoryAPITestCase): omit_simulation=1) self.assertEquals(1, len(movement_history_list)) self.assertEquals(100, movement_history_list[0].quantity) - + + def test_RunningTotalQuantity(self): + """Test that a running_total_quantity attribute is set on brains + """ + getMovementHistoryList = self.getSimulationTool().getMovementHistoryList + date_and_qty_list = [(DateTime(2006, 01, day), day) for day in range(1, 10)] + for date, quantity in date_and_qty_list: + self._makeMovement(stop_date=date, quantity=quantity) + movement_history_list = getMovementHistoryList( + section_uid=self.section.getUid(), + sort_on=[('stock.date', 'asc'), + ('stock.uid', 'asc')]) + running_total_quantity=0 + for idx, (date, quantity) in enumerate(date_and_qty_list): + brain = movement_history_list[idx] + running_total_quantity += quantity + self.assertEquals(running_total_quantity, brain.running_total_quantity) + self.assertEquals(date, brain.date) + self.assertEquals(quantity, brain.quantity) + + def test_RunningTotalPrice(self): + """Test that a running_total_price attribute is set on brains + """ + getMovementHistoryList = self.getSimulationTool().getMovementHistoryList + date_and_price_list = [(DateTime(2006, 01, day), day) for day in range(1, 10)] + for date, price in date_and_price_list: + self._makeMovement(stop_date=date, quantity=1, price=price) + movement_history_list = getMovementHistoryList( + section_uid=self.section.getUid(), + sort_on=[('stock.date', 'asc'), + ('stock.uid', 'asc')]) + running_total_price=0 + for idx, (date, price) in enumerate(date_and_price_list): + brain = movement_history_list[idx] + running_total_price += price + self.assertEquals(running_total_price, brain.running_total_price) + self.assertEquals(date, brain.date) + self.assertEquals(price, brain.total_price) + + def test_RunningTotalWithInitialValue(self): + """Test running_total_price and running_total_quantity with an initial + value. + """ + getMovementHistoryList = self.getSimulationTool().getMovementHistoryList + date_and_qty_list = [(DateTime(2006, 01, day), day) for day in range(1, 10)] + for date, quantity in date_and_qty_list: + self._makeMovement(stop_date=date, price=quantity, quantity=quantity) + initial_running_total_price=100 + initial_running_total_quantity=-10 + movement_history_list = getMovementHistoryList( + initial_running_total_quantity= + initial_running_total_quantity, + initial_running_total_price= + initial_running_total_price, + section_uid=self.section.getUid(), + sort_on=[('stock.date', 'asc'), + ('stock.uid', 'asc')]) + running_total_price=initial_running_total_price + running_total_quantity=initial_running_total_quantity + for idx, (date, quantity) in enumerate(date_and_qty_list): + brain = movement_history_list[idx] + self.assertEquals(date, brain.date) + running_total_quantity += quantity + self.assertEquals(running_total_quantity, brain.running_total_quantity) + running_total_price += quantity * quantity # we've set price=quantity + self.assertEquals(running_total_price, brain.running_total_price) + class TestInventoryStat(InventoryAPITestCase): """Tests Inventory Stat methods. """