diff --git a/product/ERP5/Tool/SimulationTool.py b/product/ERP5/Tool/SimulationTool.py index b62ce24fa735d48ec8e738cc228af00793906036..c0d4188dcb817b72e336de6aa11039c44c153ce8 100644 --- a/product/ERP5/Tool/SimulationTool.py +++ b/product/ERP5/Tool/SimulationTool.py @@ -354,8 +354,12 @@ class SimulationTool(BaseTool): simulation_dict['simulation_state'] = output_simulation_state return simulation_dict - def _getOmitQuery(self, query_table=None, omit_input=0, omit_output=0, **kw): - omit_dict = self._getOmitDict(omit_input=omit_input, omit_output=omit_output) + def _getOmitQuery(self, query_table=None, omit_input=0, omit_output=0, + omit_asset_increase=0, omit_asset_decrease=0, **kw): + omit_dict = self._getOmitDict(omit_input=omit_input, + omit_output=omit_output, + omit_asset_increase=omit_asset_increase, + omit_asset_decrease=omit_asset_decrease) return self._buildOmitQuery(query_table=query_table, omit_dict=omit_dict) def _buildOmitQuery(self, query_table, omit_dict): @@ -363,11 +367,16 @@ class SimulationTool(BaseTool): Build a specific query in order to take: - negatives quantity values if omit_input - postives quantity values if omit_output + - negatives asset price values if omit_asset_increase + - positives asset price values if omit_asset_decrease """ omit_query = None omit_input = omit_dict.get('input', False) omit_output = omit_dict.get('output', False) - if omit_input or omit_output: + omit_asset_increase = omit_dict.get('asset_increase', False) + omit_asset_decrease = omit_dict.get('asset_decrease', False) + if omit_input or omit_output\ + or omit_asset_increase or omit_asset_decrease: # Make sure to check some conditions condition_expression = \ "%(query_table)s.node_uid <> %(query_table)s.mirror_node_uid \ @@ -400,18 +409,57 @@ class SimulationTool(BaseTool): Query(**{'%s.is_cancellation' % query_table: 1}), operator='AND'), operator='OR') - if omit_query is None: - omit_query = ComplexQuery(quantity_query, condition_expression, + output_query = ComplexQuery(quantity_query, condition_expression, operator='AND') - else: - output_query = ComplexQuery(quantity_query, condition_expression, - operator='AND') + if omit_query is not None: omit_query = ComplexQuery(omit_query, output_query, operator='AND') + else: + omit_query = output_query + + if omit_asset_increase: + asset_price_query = ComplexQuery( + ComplexQuery( + Query(**{'%s.total_price' % query_table: '<0'}), + Query(**{'%s.is_cancellation' % query_table: 0}), + operator='AND'), + ComplexQuery( + Query(**{'%s.total_price' % query_table: '>0'}), + Query(**{'%s.is_cancellation' % query_table: 1}), + operator='AND'), + operator='OR') + asset_increase_query = ComplexQuery(asset_price_query, condition_expression, + operator='AND') + if omit_query is not None: + omit_query = ComplexQuery(omit_query, asset_increase_query, operator='AND') + else: + omit_query = asset_increase_query + + if omit_asset_decrease: + asset_price_query = ComplexQuery( + ComplexQuery( + Query(**{'%s.total_price' % query_table: '>0'}), + Query(**{'%s.is_cancellation' % query_table: 0}), + operator='AND'), + ComplexQuery( + Query(**{'%s.total_price' % query_table: '<0'}), + Query(**{'%s.is_cancellation' % query_table: 1}), + operator='AND'), + operator='OR') + asset_decrease_query = ComplexQuery(asset_price_query, condition_expression, + operator='AND') + if omit_query is not None: + omit_query = ComplexQuery(omit_query, asset_decrease_query, operator='AND') + else: + omit_query = asset_decrease_query return omit_query - def _getOmitDict(self, omit_input=False, omit_output=False): - return {'input': omit_input, 'output': omit_output} + def _getOmitDict(self, omit_input=False, omit_output=False, + omit_asset_increase=False, omit_asset_decrease=False): + return { 'input': omit_input, + 'output': omit_output, + 'asset_increase': omit_asset_increase, + 'asset_decrease': omit_asset_decrease, } def _generateSQLKeywordDict(self, table='stock', **kw): sql_kw, new_kw = self._generateKeywordDict(**kw) @@ -558,6 +606,8 @@ class SimulationTool(BaseTool): # omit input and output omit_input=0, omit_output=0, + omit_asset_increase=0, + omit_asset_decrease=0, # group by group_by_node=0, group_by_node_category=0, @@ -714,7 +764,9 @@ class SimulationTool(BaseTool): strict_simulation_state=strict_simulation_state) new_kw['simulation_dict'] = simulation_dict omit_dict = self._getOmitDict(omit_input=omit_input, - omit_output=omit_output) + omit_output=omit_output, + omit_asset_increase=omit_asset_increase, + omit_asset_decrease=omit_asset_decrease) new_kw['omit_dict'] = omit_dict if reserved_kw is not None: if not isinstance(reserved_kw, dict): @@ -950,9 +1002,13 @@ class SimulationTool(BaseTool): omit_simulation - doesn't take into account simulation movements - omit_input - doesn't take into account movement with quantity < 0 + omit_input - doesn't take into account movement with quantity > 0 + + omit_output - doesn't take into account movement with quantity < 0 + + omit_asset_increase - doesn't take into account movement with asset_price > 0 - omit_output - doesn't take into account movement with quantity > 0 + omit_asset_decrease - doesn't take into account movement with asset_price < 0 selection_domain, selection_report - see ListBox @@ -1807,6 +1863,7 @@ class SimulationTool(BaseTool): def getMovementHistoryList(self, src__=0, ignore_variation=0, standardise=0, omit_simulation=0, omit_input=0, omit_output=0, + omit_asset_increase=0, omit_asset_decrease=0, selection_domain=None, selection_report=None, initial_running_total_quantity=0, initial_running_total_price=0, precision=None, @@ -1826,6 +1883,8 @@ class SimulationTool(BaseTool): standardise=standardise, omit_simulation=omit_simulation, omit_input=omit_input, omit_output=omit_output, + omit_asset_increase=omit_asset_increase, + omit_asset_decrease=omit_asset_decrease, selection_domain=selection_domain, selection_report=selection_report, initial_running_total_quantity= 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 6c26d605e4056c3d76b42905b78937a4887cd239..18a9fe3736f32cd0be5eecdae8ffa39de1532ff5 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 @@ -75,6 +75,18 @@ <dictionary/> </value> </item> + <item> + <key> <string>omit_asset_decrease</string> </key> + <value> + <dictionary/> + </value> + </item> + <item> + <key> <string>omit_asset_increase</string> </key> + <value> + <dictionary/> + </value> + </item> <item> <key> <string>omit_input</string> </key> <value> @@ -165,6 +177,8 @@ <string>omit_simulation</string> <string>omit_input</string> <string>omit_output</string> + <string>omit_asset_increase</string> + <string>omit_asset_decrease</string> <string>section_filtered</string> <string>initial_running_total_quantity</string> <string>initial_running_total_price</string> @@ -602,6 +616,8 @@ standardize\r\n omit_simulation\r\n omit_input\r\n omit_output\r\n +omit_asset_increase\r\n +omit_asset_decrease\r\n section_filtered\r\n initial_running_total_quantity\r\n initial_running_total_price\r\n @@ -726,6 +742,24 @@ WHERE\n OR stock.mirror_section_uid IS NULL\n OR stock.payment_uid IS NOT NULL )\n </dtml-if>\n +<dtml-if omit_asset_increase>\n + AND ( ( stock.is_cancellation AND stock.total_price > 0 )\n + OR ( not stock.is_cancellation AND stock.total_price < 0 ))\n + AND ( stock.node_uid <> stock.mirror_node_uid\n + OR stock.section_uid <> stock.mirror_section_uid\n + OR stock.mirror_node_uid IS NULL\n + OR stock.mirror_section_uid IS NULL\n + OR stock.payment_uid IS NOT NULL )\n +</dtml-if>\n +<dtml-if omit_asset_decrease>\n + AND ( ( stock.is_cancellation AND stock.total_price < 0 )\n + OR ( not stock.is_cancellation AND stock.total_price > 0 ))\n + AND ( stock.node_uid <> stock.mirror_node_uid\n + OR stock.section_uid <> stock.mirror_section_uid\n + OR stock.mirror_node_uid IS NULL\n + OR stock.mirror_section_uid IS NULL\n + OR stock.payment_uid IS NOT NULL )\n +</dtml-if>\n \n <dtml-if input_simulation_state>\n <dtml-if output_simulation_state>\n @@ -893,6 +927,24 @@ WHERE\n OR stock.mirror_section_uid IS NULL\n OR stock.payment_uid IS NOT NULL )\n </dtml-if>\n +<dtml-if omit_asset_increase>\n + AND ( ( stock.is_cancellation AND stock.total_price > 0 )\n + OR ( not stock.is_cancellation AND stock.total_price < 0 ))\n + AND ( stock.node_uid <> stock.mirror_node_uid\n + OR stock.section_uid <> stock.mirror_section_uid\n + OR stock.mirror_node_uid IS NULL\n + OR stock.mirror_section_uid IS NULL\n + OR stock.payment_uid IS NOT NULL )\n +</dtml-if>\n +<dtml-if omit_asset_decrease>\n + AND ( ( stock.is_cancellation AND stock.total_price < 0 )\n + OR ( not stock.is_cancellation AND stock.total_price > 0 ))\n + AND ( stock.node_uid <> stock.mirror_node_uid\n + OR stock.section_uid <> stock.mirror_section_uid\n + OR stock.mirror_node_uid IS NULL\n + OR stock.mirror_section_uid IS NULL\n + OR stock.payment_uid IS NOT NULL )\n +</dtml-if>\n \n <dtml-if input_simulation_state>\n <dtml-if output_simulation_state>\n diff --git a/product/ERP5/bootstrap/erp5_core/bt/revision b/product/ERP5/bootstrap/erp5_core/bt/revision index dfac53b0c4c76e690a689ad7a23fe770d6082340..7fc5e9be95527a0a5d013b2206208f5e6d854dc7 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/revision +++ b/product/ERP5/bootstrap/erp5_core/bt/revision @@ -1 +1 @@ -1641 \ No newline at end of file +1642 \ No newline at end of file diff --git a/product/ERP5/tests/testInventoryAPI.py b/product/ERP5/tests/testInventoryAPI.py index 12cdb0b5f6b3987495c5fb7659c0fe3562c58ecc..3fbc538b121a92688fa215766b77af422edad460 100644 --- a/product/ERP5/tests/testInventoryAPI.py +++ b/product/ERP5/tests/testInventoryAPI.py @@ -1008,6 +1008,54 @@ class TestInventoryList(InventoryAPITestCase): omit_input=1, omit_output=1))) + def test_OmitAssetIncreaseDecrease(self): + getInventoryList = self.getSimulationTool().getInventoryList + m1 = self._makeMovement(quantity=1, price=1) + m2 = self._makeMovement(quantity=-1, price=1) + # omit movements that increases the asset + inventory_list = getInventoryList(node_uid=self.node.getUid(), + omit_asset_increase=1) + self.assertEquals(1, len(inventory_list)) + self.assertEquals(-1, inventory_list[0].total_price) + self.assertEquals(-1, inventory_list[0].total_quantity) + + # omit movements that decrease the asset + inventory_list = getInventoryList(node_uid=self.node.getUid(), + omit_asset_decrease=1) + self.assertEquals(1, len(inventory_list)) + self.assertEquals(1, inventory_list[0].total_price) + self.assertEquals(1, inventory_list[0].total_quantity) + + # omit_asset_increase and omit_asset_decrease return nothing in that case + self.assertEquals(0, len(getInventoryList(node_uid=self.node.getUid(), + omit_asset_increase=1, + omit_asset_decrease=1))) + + # so far, it works the same as omit_input & omit_output, but if we have + # negative prices, we see the interest of such feature + m1.setPrice(-1) + self.assertEquals(-1, m1.getTotalPrice()) + m2.setPrice(-1) + self.assertEquals(1, m2.getTotalPrice()) + + transaction.commit() + self.tic() + + inventory_list = getInventoryList(node_uid=self.node.getUid(), + omit_asset_increase=1) + self.assertEquals(1, len(inventory_list)) + # this is m1 + self.assertEquals(-1, inventory_list[0].total_price) + self.assertEquals(1, inventory_list[0].total_quantity) + + inventory_list = getInventoryList(node_uid=self.node.getUid(), + omit_asset_decrease=1) + self.assertEquals(1, len(inventory_list)) + # this is m2 + self.assertEquals(1, inventory_list[0].total_price) + self.assertEquals(-1, inventory_list[0].total_quantity) + + def test_OmitInputOmitOutputWithDifferentPaymentSameNodeSameSection(self): getInventoryList = self.getSimulationTool().getInventoryList self._makeMovement(quantity=2, price=1, @@ -1812,6 +1860,22 @@ class TestMovementHistoryList(InventoryAPITestCase): omit_input=1, omit_output=1))) + def test_OmitAssetIncreaseDecrease(self): + getMovementHistoryList = self.getSimulationTool().getMovementHistoryList + m1 = self._makeMovement(quantity=1, price=-1) + m2 = self._makeMovement(quantity=-1, price=-1) + mvt_history_list = getMovementHistoryList(node_uid=self.node.getUid(), + omit_asset_increase=1) + self.assertEquals(1, len(mvt_history_list)) + self.assertEquals(-1, mvt_history_list[0].total_price) + self.assertEquals(1, mvt_history_list[0].total_quantity) + + mvt_history_list = getMovementHistoryList(node_uid=self.node.getUid(), + omit_asset_decrease=1) + self.assertEquals(1, len(mvt_history_list)) + self.assertEquals(1, mvt_history_list[0].total_price) + self.assertEquals(-1, mvt_history_list[0].total_quantity) + def test_OmitInputOmitOutputWithDifferentPaymentSameNodeSameSection(self): getMovementHistoryList = self.getSimulationTool().getMovementHistoryList self._makeMovement(quantity=2, price=1,