From 768b20d8eb235fdb5d9d06d85502be74fde33d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nowak?= <luke@nexedi.com> Date: Tue, 22 Dec 2009 17:59:56 +0000 Subject: [PATCH] - move out complex test case to separate test file, testTradeModelLine was already big and long test git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@31422 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../tests/testComplexTradeModelLineUseCase.py | 684 ++++++++++++++++++ product/ERP5/tests/testTradeModelLine.py | 648 ----------------- 2 files changed, 684 insertions(+), 648 deletions(-) create mode 100644 product/ERP5/tests/testComplexTradeModelLineUseCase.py diff --git a/product/ERP5/tests/testComplexTradeModelLineUseCase.py b/product/ERP5/tests/testComplexTradeModelLineUseCase.py new file mode 100644 index 0000000000..d94a35610f --- /dev/null +++ b/product/ERP5/tests/testComplexTradeModelLineUseCase.py @@ -0,0 +1,684 @@ +# -*- coding: utf-8 -*- +############################################################################## +# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved. +# Åukasz Nowak <luke@nexedi.com> +# Fabien Morin <fabien@nexedi.com> +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import unittest +import transaction + +from Products.ERP5Type.tests.utils import createZODBPythonScript +from Products.ERP5.tests.testTradeModelLine import TestTradeModelLineMixin +from Products.ERP5.PropertySheet.TradeModelLine import TARGET_LEVEL_DELIVERY + +class TestComplexTradeModelLineUseCase(TestTradeModelLineMixin): + """This test provides several complex use cases which are seen in the normal + shop and make sure that trade model line is capable of real business scene. + """ + + def createOrder(self): + module = self.portal.getDefaultModule(portal_type=self.order_portal_type) + return module.newContent(portal_type=self.order_portal_type, + title=self.id()) + + def createTradeCondition(self): + module = self.portal.getDefaultModule( + portal_type=self.trade_condition_portal_type) + trade_condition = module.newContent( + portal_type=self.trade_condition_portal_type, + title=self.id()) + return trade_condition + + def getAmount(self, order, reference, return_object=False): + trade_condition = order.getSpecialiseValue() + for movement in trade_condition.getAggregatedAmountList(order): + if movement.getReference() == reference: + if return_object == True: + return movement + else: + return movement.getTotalPrice() + + def appendBaseContributionCategory(self, document, new_category): + base_contribution_value_list = document.getBaseContributionValueList() + document.setBaseContributionValueList( + base_contribution_value_list+[new_category]) + + def beforeTearDown(self): + # abort any transaction + transaction.abort() + # put non finished activities into ignored state + activity_connection = self.portal.cmf_activity_sql_connection + for table in 'message', 'message_queue': + activity_connection.manage_test( + 'delete from %s where processing_node=-2' % table) + + def removeAll(*args): + for container in args: + container.manage_delObjects(ids=list(container.objectIds())) + removeAll(self.portal.sale_order_module, + self.portal.purchase_order_module, + self.portal.sale_trade_condition_module, + self.portal.purchase_trade_condition_module, + self.portal.person_module, + self.portal.organisation_module, + self.portal.service_module, + self.portal.product_module, + self.portal.currency_module, + self.portal.portal_categories.product_line, + self.portal.portal_categories.base_amount, + self.portal.portal_categories.trade_phase, + self.portal.portal_categories.use, + self.portal.portal_categories.quantity_unit, + ) + + self.stepTic() + + def afterSetUp(self): + portal = self.portal + + # inherited method + self.createCategories() + + self.stepTic() + + # add currency + jpy = portal.currency_module.newContent(title='Yen', reference='JPY', base_unit_quantity='1') + + self.stepTic() + + # add organisations + my_company = portal.organisation_module.newContent(title='My Company') + client_1 = portal.organisation_module.newContent(title='Client 1') + + self.stepTic() + + # add base amount subcategories + base_amount = portal.portal_categories.base_amount + self.total_price_of_ordered_items = base_amount.newContent(id='total_price_of_ordered_items') + self.discount_amount_of_non_vat_taxable = base_amount.newContent(id='discount_amount_of_non_vat_taxable') + self.discount_amount_of_vat_taxable = base_amount.newContent(id='discount_amount_of_vat_taxable') + self.vat_taxable = base_amount.newContent(id='vat_taxable') + self.total_price_without_vat = base_amount.newContent(id='total_price_without_vat') + self.total_price_of_vat_taxable = base_amount.newContent(id='total_price_of_vat_taxable') + self.discount_amount = base_amount.newContent(id='discount_amount') + self.vat_amount = base_amount.newContent(id='vat_amount') + self.total_price_with_vat = base_amount.newContent(id='total_price_with_vat') + self.poster_present_1dvd = base_amount.newContent(id='poster_present_1dvd') + self.poster_present_3cd = base_amount.newContent(id='poster_present_3cd') + self.special_discount_3cd = base_amount.newContent(id='special_discount_3cd') + # add product line subcategories + product_line = portal.portal_categories.product_line + audio = product_line.newContent(id='audio') + audio_cd = audio.newContent(id='cd') + video = product_line.newContent(id='video') + video_dvd = video.newContent(id='dvd') + other_product = product_line.newContent(id='other') + # add a quantity unit subcategory + self.unit = portal.portal_categories.quantity_unit.newContent(id='unit') + + self.stepTic() + + # create services + self.service_vat = portal.service_module.newContent(title='VAT') + self.service_discount = portal.service_module.newContent(title='VAT') + + self.stepTic() + + # create products + def addProductDocument(title, product_line_value): + return portal.product_module.newContent( + title=title, + product_line_value=product_line_value, + quantity_unit_value=self.unit, + base_contribution_value_list=[self.vat_taxable, + self.total_price_of_ordered_items]) + + self.music_album_1 = addProductDocument('Music Album 1', audio_cd) + self.movie_dvd_1 = addProductDocument('Movie DVD 1', video_dvd) + self.music_album_2 = addProductDocument('Movie Album 2', audio_cd) + self.candy = addProductDocument('Candy', other_product) + self.poster = addProductDocument('Poster', other_product) + self.music_album_3 = addProductDocument('Movie Album 3', audio_cd) + self.movie_dvd_2 = addProductDocument('Movie DVD 2', video_dvd) + self.music_album_4 = addProductDocument('Movie Album 4', audio_cd) + + self.stepTic() + + # create a trade condition and add several common trade model lines in it. + self.trade_condition = self.createTradeCondition() + self.trade_condition.edit( + source_section_value=my_company, + source_value=my_company, + source_decision_value=my_company, + destination_section_value=client_1, + destination_value=client_1, + destination_decision_value=client_1, + price_currency_value=jpy) + self.trade_condition.newContent( + portal_type='Trade Model Line', + title='Total Price Without VAT', + reference='TOTAL_PRICE_WITHOUT_VAT', + price=1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + create_line=True, + trade_phase=None, + base_application_value_list=[self.discount_amount_of_non_vat_taxable, + self.discount_amount_of_vat_taxable, + self.total_price_of_ordered_items], + base_contribution_value_list=[self.total_price_without_vat]) + self.trade_condition.newContent( + portal_type='Trade Model Line', + title='Total Price Of VAT Taxable', + reference='TOTAL_PRICE_OF_VAT_TAXABLE', + price=1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + create_line=True, + trade_phase=None, + base_application_value_list=[self.discount_amount_of_vat_taxable, + self.vat_taxable], + base_contribution_value_list=[self.total_price_of_vat_taxable]) + self.trade_condition.newContent( + portal_type='Trade Model Line', + title='Discount Amount', + reference='DISCOUNT_AMOUNT', + resource_value=self.service_discount, + price=1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + create_line=True, + trade_phase_value=portal.portal_categories.trade_phase.default.invoicing, + base_application_value_list=[self.discount_amount_of_vat_taxable, + self.discount_amount_of_non_vat_taxable], + base_contribution_value_list=[self.discount_amount]) + self.trade_condition.newContent( + portal_type='Trade Model Line', + title='VAT Amount', + reference='VAT_AMOUNT', + resource_value=self.service_vat, + price=0.05, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + create_line=True, + trade_phase_value=portal.portal_categories.trade_phase.default.invoicing, + base_application_value_list=[self.discount_amount_of_vat_taxable, + self.vat_taxable], + base_contribution_value_list=[self.vat_amount]) + self.trade_condition.newContent( + portal_type='Trade Model Line', + title='Total Price With VAT', + reference='TOTAL_PRICE_WITH_VAT', + price=1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + create_line=True, + trade_phase=None, + base_application_value_list=[self.vat_amount, + self.total_price_without_vat], + base_contribution_value_list=[self.total_price_with_vat]) + + self.stepTic() + + def test_usecase1(self): + """ + Use case 1 : Buy 3 CDs or more, get 10% off them. + + 1 CD 5000 yen + 1 CD 3000 yen + 1 Candy 100 yen + 1 CD 2400 yen + discount (5000+3000+2400) * 0.1 = 1040 yen + """ + createZODBPythonScript( + self.portal.portal_skins.custom, + 'TradeModelLine_calculate3CD10PercentDiscount', + 'current_aggregated_amount_list, current_movement, aggregated_movement_list', + """\ +total_quantity = sum([movement.getQuantity() + for movement in aggregated_movement_list]) +if total_quantity >= 3: + return current_movement +else: + return None +""") + order = self.createOrder() + order.edit(specialise_value=self.trade_condition) + order.Order_applyTradeCondition(order.getSpecialiseValue()) + order.newContent(portal_type='Trade Model Line', + reference='3CD_AND_10PERCENT_DISCOUNT_OFF_THEM', + resource_value=self.service_discount, + price=-0.1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + calculation_script_id='TradeModelLine_calculate3CD10PercentDiscount', + create_line=True, + trade_phase=None, + base_application_value_list=[self.special_discount_3cd], + base_contribution_value_list=[self.discount_amount_of_vat_taxable]) + + order_line_1 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_1, + quantity=1, + price=5000) + self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) + order_line_2 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_2, + quantity=1, + price=3000) + self.appendBaseContributionCategory(order_line_2, self.special_discount_3cd) + order_line_3 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.candy, + quantity=1, + price=100) + + self.stepTic() + + # check the current amount + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 8100) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 405) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 8505) + # add one more cd, then total is 3. the special discount will be applied. + order_line_4 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) + + self.stepTic() + + # check again + self.assertEqual(self.getAmount(order, '3CD_AND_10PERCENT_DISCOUNT_OFF_THEM'), + -1040) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 9460) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 473) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 9933) + + def test_usecase2(self): + """ + Use case 2 : Buy 3 CDs or more, get 500 yen off. + + 1 CD 5000 yen + 1 CD 3000 yen + 1 DVD 3000 yen + 1 CD 2400 yen + discount 500 yen + """ + createZODBPythonScript( + self.portal.portal_skins.custom, + 'TradeModelLine_calculate3CD500YenDiscount', + 'current_aggregated_amount_list, current_movement, aggregated_movement_list', + """\ +total_quantity = sum([movement.getQuantity() for movement in aggregated_movement_list]) +if total_quantity >= 3: + current_movement.setQuantity(-500) + return current_movement +else: + return None +""") + order = self.createOrder() + order.edit(specialise_value=self.trade_condition) + order.Order_applyTradeCondition(order.getSpecialiseValue()) + order.newContent(portal_type='Trade Model Line', + reference='3CD_AND_500YEN_OFF', + resource_value=self.service_discount, + price=1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + calculation_script_id='TradeModelLine_calculate3CD500YenDiscount', + create_line=True, + trade_phase=None, + base_application_value_list=[self.special_discount_3cd], + base_contribution_value_list=[self.discount_amount_of_vat_taxable]) + + order_line_1 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_1, + quantity=1, + price=5000) + self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) + order_line_2 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_2, + quantity=1, + price=3000) + self.appendBaseContributionCategory(order_line_2, self.special_discount_3cd) + order_line_3 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.movie_dvd_1, + quantity=1, + price=3000) + + self.stepTic() + + # check the current amount + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 11000) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 550) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 11550) + # add one more cd, then total is 3. the special discount will be applied. + order_line_4 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) + # check again + self.assertEqual(self.getAmount(order, '3CD_AND_500YEN_OFF'), -500) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 12900) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 645) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 13545) + + def test_usecase3(self): + """ + Use case 3 : Buy 3 CDs or more, get 10% off total. + + 1 CD 5000 yen + 1 DVD 3000 yen + 1 CD 3000 yen + 1 CD 2400 yen + discount (5000+3000+3000+2400) * 0.1 = 1340 yen + """ + createZODBPythonScript( + self.portal.portal_skins.custom, + 'TradeModelLine_calculate3CD10PercentDiscountFromTotal', + 'current_aggregated_amount_list, current_movement, aggregated_movement_list', + '''\ +special_discount_3cd = context.portal_categories.base_amount.special_discount_3cd +total_quantity = sum([movement.getQuantity() for movement in current_aggregated_amount_list + if special_discount_3cd in movement.getBaseContributionValueList()]) +if total_quantity >= 3: + return current_movement +else: + return None +''') + order = self.createOrder() + order.edit(specialise_value=self.trade_condition) + order.Order_applyTradeCondition(order.getSpecialiseValue()) + order.newContent(portal_type='Trade Model Line', + reference='3CD_10PERCENT_OFF_FROM_TOTAL', + resource_value=self.service_discount, + price=-0.1, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + calculation_script_id='TradeModelLine_calculate3CD10PercentDiscountFromTotal', + create_line=True, + trade_phase=None, + base_application_value_list=[self.total_price_of_ordered_items], + base_contribution_value_list=[self.discount_amount_of_vat_taxable]) + + order_line_1 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_1, + quantity=1, + price=5000) + self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) + order_line_2 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.movie_dvd_1, + quantity=1, + price=3000) + order_line_3 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_2, + quantity=1, + price=3000) + self.appendBaseContributionCategory(order_line_3, self.special_discount_3cd) + + self.stepTic() + + # check the current amount + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 11000) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 550) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 11550) + # add one more cd, then total is 3. the special discount will be applied. + order_line_4 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) + # check again + self.assertEqual(self.getAmount(order, '3CD_10PERCENT_OFF_FROM_TOTAL'), + -1340) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 12060) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 603) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 12663) + + def test_usecase4(self): + """ + Use case 4 : Buy 3 CDs or 1 DVD, get 1 poster free. + + 2 CD 6000 yen + 1 DVD 3000 yen + 1 Poster 0 yen + """ + createZODBPythonScript( + self.portal.portal_skins.custom, + 'TradeModelLine_calculate3CDOr1DVDForPoster', + 'current_aggregated_amount_list, current_movement, aggregated_movement_list', + '''\ +poster_present_3cd = context.portal_categories.base_amount.poster_present_3cd +poster_present_1dvd = context.portal_categories.base_amount.poster_present_1dvd + +total_quantity_3cd = sum([movement.getQuantity() for movement in aggregated_movement_list + if poster_present_3cd in movement.getBaseContributionValueList()]) +total_quantity_1dvd = sum([movement.getQuantity() for movement in aggregated_movement_list + if poster_present_1dvd in movement.getBaseContributionValueList()]) +if (total_quantity_3cd >= 3 or total_quantity_1dvd >= 1): + current_movement.setQuantity(1) + return current_movement +else: + return None +''') + order = self.createOrder() + order.edit(specialise_value=self.trade_condition) + order.Order_applyTradeCondition(order.getSpecialiseValue()) + order.newContent(portal_type='Trade Model Line', + reference='3CD_OR_1DVD_GET_1_POSTER_FREE', + resource_value=self.poster, + price=0, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + calculation_script_id='TradeModelLine_calculate3CDOr1DVDForPoster', + create_line=True, + trade_phase=None, + base_application_value_list=[self.poster_present_1dvd, + self.poster_present_3cd]) + + order_line_1 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_4, + quantity=2, + price=3000) + self.appendBaseContributionCategory(order_line_1, self.poster_present_3cd) + + self.stepTic() + + # check the current amount + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 6000) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 300) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 6300) + self.assertEqual(self.getAmount(order, '3CD_OR_1DVD_GET_1_POSTER_FREE'), + None) + # add 1 dvd, then 1 poster will be given. + order_line_2 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.movie_dvd_1, + quantity=1, + price=3000) + self.appendBaseContributionCategory(order_line_2, self.poster_present_1dvd) + + self.stepTic() + + # check again + one_free_poster_amount = self.getAmount(order, + '3CD_OR_1DVD_GET_1_POSTER_FREE', + return_object=True) + self.assertEqual(one_free_poster_amount.getTotalPrice(), 0) + self.assertEqual(one_free_poster_amount.getQuantity(), 1) + self.assertEqual(one_free_poster_amount.getPrice(), 0) + self.assertEqual(one_free_poster_amount.getResourceValue(), self.poster) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 9000) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 450) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 9450) + + # even if we buy 3 CDs and 1 DVD, only one poster will be given. + order_line_3 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(order_line_3, self.poster_present_3cd) + + self.stepTic() + + # check again + one_free_poster_amount = self.getAmount(order, + '3CD_OR_1DVD_GET_1_POSTER_FREE', + return_object=True) + self.assertEqual(one_free_poster_amount.getTotalPrice(), 0) + self.assertEqual(one_free_poster_amount.getQuantity(), 1) + self.assertEqual(one_free_poster_amount.getPrice(), 0) + self.assertEqual(one_free_poster_amount.getResourceValue(), self.poster) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 11400) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 570) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 11970) + + def test_usecase5(self): + """ + Use case 5 : Buy 3 CDs or more, 1 highest priced DVD in ordered 15% off. + + 1 DVD 3000 yen + 1 DVD 1000 yen + 2 CD 10000 yen + 1 CD 3000 yen + discount 3000 * 0.15 = 450 yen + """ + createZODBPythonScript( + self.portal.portal_skins.custom, + 'TradeModelLine_calculate3CD15PercentDiscountOf1HighestPricedDVD', + 'current_aggregated_amount_list, current_movement, aggregated_movement_list', + '''\ +total_quantity = sum([movement.getQuantity() for movement in aggregated_movement_list]) +if total_quantity >= 3: + price_dvd_list = [] + product_line_dvd = context.portal_categories.product_line.video.dvd + for movement in current_aggregated_amount_list: + resource = movement.getResourceValue() + if resource.getProductLineValue() == product_line_dvd: + price_dvd_list.append((movement.getPrice(), movement)) + if price_dvd_list: + price_dvd_list.sort() + highest_priced_dvd_movement = price_dvd_list[-1][1] + total_price = highest_priced_dvd_movement.getTotalPrice() + + from Products.ERP5Type.Document import newTempSimulationMovement + causality_value_list = list(aggregated_movement_list) + [highest_priced_dvd_movement] + temporary_movement = newTempSimulationMovement(current_movement.getParentValue(), current_movement.getId()) + temporary_movement.edit(title=current_movement.getProperty('title'), + description=current_movement.getProperty('description'), + resource=current_movement.getProperty('resource'), + reference=current_movement.getProperty('reference'), + int_index=current_movement.getProperty('int_index'), + base_application_list=current_movement.getProperty('base_application_list'), + base_contribution_list=current_movement.getProperty('base_contribution_list'), + start_date=highest_priced_dvd_movement.getStartDate(), + stop_date=highest_priced_dvd_movement.getStopDate(), + create_line=current_movement.getProperty('is_create_line'), + trade_phase_list=current_movement.getTradePhaseList(), + causality_list=[movement.getRelativeUrl() for movement in causality_value_list]) + temporary_movement.setPrice(current_movement.getProperty('price')) + temporary_movement.setQuantity(highest_priced_dvd_movement.getPrice()) + return temporary_movement +''') + order = self.createOrder() + order.edit(specialise_value=self.trade_condition) + order.Order_applyTradeCondition(order.getSpecialiseValue()) + order.newContent(portal_type='Trade Model Line', + reference='3CD_AND_1HIGHEST_PRICED_DVD_15PERCENT_OFF', + resource_value=self.service_discount, + price=-0.15, + quantity=None, + efficiency=1, + target_level=TARGET_LEVEL_DELIVERY, + calculation_script_id='TradeModelLine_calculate3CD15PercentDiscountOf1HighestPricedDVD', + create_line=True, + trade_phase=None, + base_application_value_list=[self.special_discount_3cd], + base_contribution_value_list=[self.discount_amount_of_vat_taxable]) + + order_line_1 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.movie_dvd_1, + quantity=1, + price=3000) + order_line_2 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.movie_dvd_2, + quantity=1, + price=1000) + order_line_3 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_1, + quantity=1, + price=5000) + self.appendBaseContributionCategory(order_line_3, self.special_discount_3cd) + order_line_4 = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_2, + quantity=1, + price=3000) + self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) + + self.stepTic() + + # check the current amount + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 12000) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 600) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), + 12600) + # add one more cd, then total is 3. the special discount will be applied. + order_line_3.setQuantity(2) + + self.stepTic() + + # check again + self.assertEqual(self.getAmount(order, '3CD_AND_1HIGHEST_PRICED_DVD_15PERCENT_OFF'), + -450) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 16550) + self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 827.5) + self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 17377.5) +class TestComplexTradeModelLineUseCaseSale(TestComplexTradeModelLineUseCase): + order_portal_type = 'Sale Order' + order_line_portal_type = 'Sale Order Line' + trade_condition_portal_type = 'Sale Trade Condition' + + +class TestComplexTradeModelLineUseCasePurchase(TestComplexTradeModelLineUseCase): + order_portal_type = 'Purchase Order' + order_line_portal_type = 'Purchase Order Line' + trade_condition_portal_type = 'Purchase Trade Condition' + + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestComplexTradeModelLineUseCaseSale)) + suite.addTest(unittest.makeSuite(TestComplexTradeModelLineUseCasePurchase)) + return suite diff --git a/product/ERP5/tests/testTradeModelLine.py b/product/ERP5/tests/testTradeModelLine.py index 2ad1922af1..20819604fa 100644 --- a/product/ERP5/tests/testTradeModelLine.py +++ b/product/ERP5/tests/testTradeModelLine.py @@ -32,7 +32,6 @@ import transaction from Products.ERP5.tests.testBPMCore import TestBPMMixin from Products.ERP5Type.tests.Sequence import SequenceList -from Products.ERP5Type.tests.utils import createZODBPythonScript from DateTime import DateTime from Products.CMFCore.utils import getToolByName from Products.ERP5.PropertySheet.TradeModelLine import (TARGET_LEVEL_MOVEMENT, @@ -2722,639 +2721,6 @@ class TestTradeModelLine(TestTradeModelLineMixin): self.assertEqual(508.51000000000005, getTotalAmount(amount_list)) -class TestComplexTradeModelLineUseCase(TestTradeModelLineMixin): - """This test provides several complex use cases which are seen in the normal - shop and make sure that trade model line is capable of real business scene. - """ - - def createOrder(self): - module = self.portal.getDefaultModule(portal_type=self.order_portal_type) - return module.newContent(portal_type=self.order_portal_type, - title=self.id()) - - def createTradeCondition(self): - module = self.portal.getDefaultModule( - portal_type=self.trade_condition_portal_type) - trade_condition = module.newContent( - portal_type=self.trade_condition_portal_type, - title=self.id()) - return trade_condition - - def getAmount(self, order, reference, return_object=False): - trade_condition = order.getSpecialiseValue() - for movement in trade_condition.getAggregatedAmountList(order): - if movement.getReference() == reference: - if return_object == True: - return movement - else: - return movement.getTotalPrice() - - def appendBaseContributionCategory(self, document, new_category): - base_contribution_value_list = document.getBaseContributionValueList() - document.setBaseContributionValueList( - base_contribution_value_list+[new_category]) - - def beforeTearDown(self): - # abort any transaction - transaction.abort() - # put non finished activities into ignored state - activity_connection = self.portal.cmf_activity_sql_connection - for table in 'message', 'message_queue': - activity_connection.manage_test( - 'delete from %s where processing_node=-2' % table) - - def removeAll(*args): - for container in args: - container.manage_delObjects(ids=list(container.objectIds())) - removeAll(self.portal.sale_order_module, - self.portal.purchase_order_module, - self.portal.sale_trade_condition_module, - self.portal.purchase_trade_condition_module, - self.portal.person_module, - self.portal.organisation_module, - self.portal.service_module, - self.portal.product_module, - self.portal.currency_module, - self.portal.portal_categories.product_line, - self.portal.portal_categories.base_amount, - self.portal.portal_categories.trade_phase, - self.portal.portal_categories.use, - self.portal.portal_categories.quantity_unit, - ) - - self.stepTic() - - def afterSetUp(self): - portal = self.portal - - # inherited method - self.createCategories() - - self.stepTic() - - # add currency - jpy = portal.currency_module.newContent(title='Yen', reference='JPY', base_unit_quantity='1') - - self.stepTic() - - # add organisations - my_company = portal.organisation_module.newContent(title='My Company') - client_1 = portal.organisation_module.newContent(title='Client 1') - - self.stepTic() - - # add base amount subcategories - base_amount = portal.portal_categories.base_amount - self.total_price_of_ordered_items = base_amount.newContent(id='total_price_of_ordered_items') - self.discount_amount_of_non_vat_taxable = base_amount.newContent(id='discount_amount_of_non_vat_taxable') - self.discount_amount_of_vat_taxable = base_amount.newContent(id='discount_amount_of_vat_taxable') - self.vat_taxable = base_amount.newContent(id='vat_taxable') - self.total_price_without_vat = base_amount.newContent(id='total_price_without_vat') - self.total_price_of_vat_taxable = base_amount.newContent(id='total_price_of_vat_taxable') - self.discount_amount = base_amount.newContent(id='discount_amount') - self.vat_amount = base_amount.newContent(id='vat_amount') - self.total_price_with_vat = base_amount.newContent(id='total_price_with_vat') - self.poster_present_1dvd = base_amount.newContent(id='poster_present_1dvd') - self.poster_present_3cd = base_amount.newContent(id='poster_present_3cd') - self.special_discount_3cd = base_amount.newContent(id='special_discount_3cd') - # add product line subcategories - product_line = portal.portal_categories.product_line - audio = product_line.newContent(id='audio') - audio_cd = audio.newContent(id='cd') - video = product_line.newContent(id='video') - video_dvd = video.newContent(id='dvd') - other_product = product_line.newContent(id='other') - # add a quantity unit subcategory - self.unit = portal.portal_categories.quantity_unit.newContent(id='unit') - - self.stepTic() - - # create services - self.service_vat = portal.service_module.newContent(title='VAT') - self.service_discount = portal.service_module.newContent(title='VAT') - - self.stepTic() - - # create products - def addProductDocument(title, product_line_value): - return portal.product_module.newContent( - title=title, - product_line_value=product_line_value, - quantity_unit_value=self.unit, - base_contribution_value_list=[self.vat_taxable, - self.total_price_of_ordered_items]) - - self.music_album_1 = addProductDocument('Music Album 1', audio_cd) - self.movie_dvd_1 = addProductDocument('Movie DVD 1', video_dvd) - self.music_album_2 = addProductDocument('Movie Album 2', audio_cd) - self.candy = addProductDocument('Candy', other_product) - self.poster = addProductDocument('Poster', other_product) - self.music_album_3 = addProductDocument('Movie Album 3', audio_cd) - self.movie_dvd_2 = addProductDocument('Movie DVD 2', video_dvd) - self.music_album_4 = addProductDocument('Movie Album 4', audio_cd) - - self.stepTic() - - # create a trade condition and add several common trade model lines in it. - self.trade_condition = self.createTradeCondition() - self.trade_condition.edit( - source_section_value=my_company, - source_value=my_company, - source_decision_value=my_company, - destination_section_value=client_1, - destination_value=client_1, - destination_decision_value=client_1, - price_currency_value=jpy) - self.trade_condition.newContent( - portal_type='Trade Model Line', - title='Total Price Without VAT', - reference='TOTAL_PRICE_WITHOUT_VAT', - price=1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - create_line=True, - trade_phase=None, - base_application_value_list=[self.discount_amount_of_non_vat_taxable, - self.discount_amount_of_vat_taxable, - self.total_price_of_ordered_items], - base_contribution_value_list=[self.total_price_without_vat]) - self.trade_condition.newContent( - portal_type='Trade Model Line', - title='Total Price Of VAT Taxable', - reference='TOTAL_PRICE_OF_VAT_TAXABLE', - price=1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - create_line=True, - trade_phase=None, - base_application_value_list=[self.discount_amount_of_vat_taxable, - self.vat_taxable], - base_contribution_value_list=[self.total_price_of_vat_taxable]) - self.trade_condition.newContent( - portal_type='Trade Model Line', - title='Discount Amount', - reference='DISCOUNT_AMOUNT', - resource_value=self.service_discount, - price=1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - create_line=True, - trade_phase_value=portal.portal_categories.trade_phase.default.invoicing, - base_application_value_list=[self.discount_amount_of_vat_taxable, - self.discount_amount_of_non_vat_taxable], - base_contribution_value_list=[self.discount_amount]) - self.trade_condition.newContent( - portal_type='Trade Model Line', - title='VAT Amount', - reference='VAT_AMOUNT', - resource_value=self.service_vat, - price=0.05, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - create_line=True, - trade_phase_value=portal.portal_categories.trade_phase.default.invoicing, - base_application_value_list=[self.discount_amount_of_vat_taxable, - self.vat_taxable], - base_contribution_value_list=[self.vat_amount]) - self.trade_condition.newContent( - portal_type='Trade Model Line', - title='Total Price With VAT', - reference='TOTAL_PRICE_WITH_VAT', - price=1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - create_line=True, - trade_phase=None, - base_application_value_list=[self.vat_amount, - self.total_price_without_vat], - base_contribution_value_list=[self.total_price_with_vat]) - - self.stepTic() - - def test_usecase1(self): - """ - Use case 1 : Buy 3 CDs or more, get 10% off them. - - 1 CD 5000 yen - 1 CD 3000 yen - 1 Candy 100 yen - 1 CD 2400 yen - discount (5000+3000+2400) * 0.1 = 1040 yen - """ - createZODBPythonScript( - self.portal.portal_skins.custom, - 'TradeModelLine_calculate3CD10PercentDiscount', - 'current_aggregated_amount_list, current_movement, aggregated_movement_list', - """\ -total_quantity = sum([movement.getQuantity() - for movement in aggregated_movement_list]) -if total_quantity >= 3: - return current_movement -else: - return None -""") - order = self.createOrder() - order.edit(specialise_value=self.trade_condition) - order.Order_applyTradeCondition(order.getSpecialiseValue()) - order.newContent(portal_type='Trade Model Line', - reference='3CD_AND_10PERCENT_DISCOUNT_OFF_THEM', - resource_value=self.service_discount, - price=-0.1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD10PercentDiscount', - create_line=True, - trade_phase=None, - base_application_value_list=[self.special_discount_3cd], - base_contribution_value_list=[self.discount_amount_of_vat_taxable]) - - order_line_1 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_1, - quantity=1, - price=5000) - self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) - order_line_2 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_2, - quantity=1, - price=3000) - self.appendBaseContributionCategory(order_line_2, self.special_discount_3cd) - order_line_3 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.candy, - quantity=1, - price=100) - - self.stepTic() - - # check the current amount - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 8100) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 405) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 8505) - # add one more cd, then total is 3. the special discount will be applied. - order_line_4 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_3, - quantity=1, - price=2400) - self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) - - self.stepTic() - - # check again - self.assertEqual(self.getAmount(order, '3CD_AND_10PERCENT_DISCOUNT_OFF_THEM'), - -1040) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 9460) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 473) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 9933) - - def test_usecase2(self): - """ - Use case 2 : Buy 3 CDs or more, get 500 yen off. - - 1 CD 5000 yen - 1 CD 3000 yen - 1 DVD 3000 yen - 1 CD 2400 yen - discount 500 yen - """ - createZODBPythonScript( - self.portal.portal_skins.custom, - 'TradeModelLine_calculate3CD500YenDiscount', - 'current_aggregated_amount_list, current_movement, aggregated_movement_list', - """\ -total_quantity = sum([movement.getQuantity() for movement in aggregated_movement_list]) -if total_quantity >= 3: - current_movement.setQuantity(-500) - return current_movement -else: - return None -""") - order = self.createOrder() - order.edit(specialise_value=self.trade_condition) - order.Order_applyTradeCondition(order.getSpecialiseValue()) - order.newContent(portal_type='Trade Model Line', - reference='3CD_AND_500YEN_OFF', - resource_value=self.service_discount, - price=1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD500YenDiscount', - create_line=True, - trade_phase=None, - base_application_value_list=[self.special_discount_3cd], - base_contribution_value_list=[self.discount_amount_of_vat_taxable]) - - order_line_1 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_1, - quantity=1, - price=5000) - self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) - order_line_2 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_2, - quantity=1, - price=3000) - self.appendBaseContributionCategory(order_line_2, self.special_discount_3cd) - order_line_3 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.movie_dvd_1, - quantity=1, - price=3000) - - self.stepTic() - - # check the current amount - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 11000) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 550) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 11550) - # add one more cd, then total is 3. the special discount will be applied. - order_line_4 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_3, - quantity=1, - price=2400) - self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) - # check again - self.assertEqual(self.getAmount(order, '3CD_AND_500YEN_OFF'), -500) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 12900) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 645) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 13545) - - def test_usecase3(self): - """ - Use case 3 : Buy 3 CDs or more, get 10% off total. - - 1 CD 5000 yen - 1 DVD 3000 yen - 1 CD 3000 yen - 1 CD 2400 yen - discount (5000+3000+3000+2400) * 0.1 = 1340 yen - """ - createZODBPythonScript( - self.portal.portal_skins.custom, - 'TradeModelLine_calculate3CD10PercentDiscountFromTotal', - 'current_aggregated_amount_list, current_movement, aggregated_movement_list', - '''\ -special_discount_3cd = context.portal_categories.base_amount.special_discount_3cd -total_quantity = sum([movement.getQuantity() for movement in current_aggregated_amount_list - if special_discount_3cd in movement.getBaseContributionValueList()]) -if total_quantity >= 3: - return current_movement -else: - return None -''') - order = self.createOrder() - order.edit(specialise_value=self.trade_condition) - order.Order_applyTradeCondition(order.getSpecialiseValue()) - order.newContent(portal_type='Trade Model Line', - reference='3CD_10PERCENT_OFF_FROM_TOTAL', - resource_value=self.service_discount, - price=-0.1, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD10PercentDiscountFromTotal', - create_line=True, - trade_phase=None, - base_application_value_list=[self.total_price_of_ordered_items], - base_contribution_value_list=[self.discount_amount_of_vat_taxable]) - - order_line_1 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_1, - quantity=1, - price=5000) - self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) - order_line_2 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.movie_dvd_1, - quantity=1, - price=3000) - order_line_3 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_2, - quantity=1, - price=3000) - self.appendBaseContributionCategory(order_line_3, self.special_discount_3cd) - - self.stepTic() - - # check the current amount - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 11000) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 550) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 11550) - # add one more cd, then total is 3. the special discount will be applied. - order_line_4 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_3, - quantity=1, - price=2400) - self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) - # check again - self.assertEqual(self.getAmount(order, '3CD_10PERCENT_OFF_FROM_TOTAL'), - -1340) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 12060) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 603) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 12663) - - def test_usecase4(self): - """ - Use case 4 : Buy 3 CDs or 1 DVD, get 1 poster free. - - 2 CD 6000 yen - 1 DVD 3000 yen - 1 Poster 0 yen - """ - createZODBPythonScript( - self.portal.portal_skins.custom, - 'TradeModelLine_calculate3CDOr1DVDForPoster', - 'current_aggregated_amount_list, current_movement, aggregated_movement_list', - '''\ -poster_present_3cd = context.portal_categories.base_amount.poster_present_3cd -poster_present_1dvd = context.portal_categories.base_amount.poster_present_1dvd - -total_quantity_3cd = sum([movement.getQuantity() for movement in aggregated_movement_list - if poster_present_3cd in movement.getBaseContributionValueList()]) -total_quantity_1dvd = sum([movement.getQuantity() for movement in aggregated_movement_list - if poster_present_1dvd in movement.getBaseContributionValueList()]) -if (total_quantity_3cd >= 3 or total_quantity_1dvd >= 1): - current_movement.setQuantity(1) - return current_movement -else: - return None -''') - order = self.createOrder() - order.edit(specialise_value=self.trade_condition) - order.Order_applyTradeCondition(order.getSpecialiseValue()) - order.newContent(portal_type='Trade Model Line', - reference='3CD_OR_1DVD_GET_1_POSTER_FREE', - resource_value=self.poster, - price=0, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CDOr1DVDForPoster', - create_line=True, - trade_phase=None, - base_application_value_list=[self.poster_present_1dvd, - self.poster_present_3cd]) - - order_line_1 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_4, - quantity=2, - price=3000) - self.appendBaseContributionCategory(order_line_1, self.poster_present_3cd) - - self.stepTic() - - # check the current amount - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 6000) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 300) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 6300) - self.assertEqual(self.getAmount(order, '3CD_OR_1DVD_GET_1_POSTER_FREE'), - None) - # add 1 dvd, then 1 poster will be given. - order_line_2 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.movie_dvd_1, - quantity=1, - price=3000) - self.appendBaseContributionCategory(order_line_2, self.poster_present_1dvd) - - self.stepTic() - - # check again - one_free_poster_amount = self.getAmount(order, - '3CD_OR_1DVD_GET_1_POSTER_FREE', - return_object=True) - self.assertEqual(one_free_poster_amount.getTotalPrice(), 0) - self.assertEqual(one_free_poster_amount.getQuantity(), 1) - self.assertEqual(one_free_poster_amount.getPrice(), 0) - self.assertEqual(one_free_poster_amount.getResourceValue(), self.poster) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 9000) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 450) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 9450) - - # even if we buy 3 CDs and 1 DVD, only one poster will be given. - order_line_3 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_3, - quantity=1, - price=2400) - self.appendBaseContributionCategory(order_line_3, self.poster_present_3cd) - - self.stepTic() - - # check again - one_free_poster_amount = self.getAmount(order, - '3CD_OR_1DVD_GET_1_POSTER_FREE', - return_object=True) - self.assertEqual(one_free_poster_amount.getTotalPrice(), 0) - self.assertEqual(one_free_poster_amount.getQuantity(), 1) - self.assertEqual(one_free_poster_amount.getPrice(), 0) - self.assertEqual(one_free_poster_amount.getResourceValue(), self.poster) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 11400) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 570) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 11970) - - def test_usecase5(self): - """ - Use case 5 : Buy 3 CDs or more, 1 highest priced DVD in ordered 15% off. - - 1 DVD 3000 yen - 1 DVD 1000 yen - 2 CD 10000 yen - 1 CD 3000 yen - discount 3000 * 0.15 = 450 yen - """ - createZODBPythonScript( - self.portal.portal_skins.custom, - 'TradeModelLine_calculate3CD15PercentDiscountOf1HighestPricedDVD', - 'current_aggregated_amount_list, current_movement, aggregated_movement_list', - '''\ -total_quantity = sum([movement.getQuantity() for movement in aggregated_movement_list]) -if total_quantity >= 3: - price_dvd_list = [] - product_line_dvd = context.portal_categories.product_line.video.dvd - for movement in current_aggregated_amount_list: - resource = movement.getResourceValue() - if resource.getProductLineValue() == product_line_dvd: - price_dvd_list.append((movement.getPrice(), movement)) - if price_dvd_list: - price_dvd_list.sort() - highest_priced_dvd_movement = price_dvd_list[-1][1] - total_price = highest_priced_dvd_movement.getTotalPrice() - - from Products.ERP5Type.Document import newTempSimulationMovement - causality_value_list = list(aggregated_movement_list) + [highest_priced_dvd_movement] - temporary_movement = newTempSimulationMovement(current_movement.getParentValue(), current_movement.getId()) - temporary_movement.edit(title=current_movement.getProperty('title'), - description=current_movement.getProperty('description'), - resource=current_movement.getProperty('resource'), - reference=current_movement.getProperty('reference'), - int_index=current_movement.getProperty('int_index'), - base_application_list=current_movement.getProperty('base_application_list'), - base_contribution_list=current_movement.getProperty('base_contribution_list'), - start_date=highest_priced_dvd_movement.getStartDate(), - stop_date=highest_priced_dvd_movement.getStopDate(), - create_line=current_movement.getProperty('is_create_line'), - trade_phase_list=current_movement.getTradePhaseList(), - causality_list=[movement.getRelativeUrl() for movement in causality_value_list]) - temporary_movement.setPrice(current_movement.getProperty('price')) - temporary_movement.setQuantity(highest_priced_dvd_movement.getPrice()) - return temporary_movement -''') - order = self.createOrder() - order.edit(specialise_value=self.trade_condition) - order.Order_applyTradeCondition(order.getSpecialiseValue()) - order.newContent(portal_type='Trade Model Line', - reference='3CD_AND_1HIGHEST_PRICED_DVD_15PERCENT_OFF', - resource_value=self.service_discount, - price=-0.15, - quantity=None, - efficiency=1, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD15PercentDiscountOf1HighestPricedDVD', - create_line=True, - trade_phase=None, - base_application_value_list=[self.special_discount_3cd], - base_contribution_value_list=[self.discount_amount_of_vat_taxable]) - - order_line_1 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.movie_dvd_1, - quantity=1, - price=3000) - order_line_2 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.movie_dvd_2, - quantity=1, - price=1000) - order_line_3 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_1, - quantity=1, - price=5000) - self.appendBaseContributionCategory(order_line_3, self.special_discount_3cd) - order_line_4 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=self.music_album_2, - quantity=1, - price=3000) - self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) - - self.stepTic() - - # check the current amount - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 12000) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 600) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), - 12600) - # add one more cd, then total is 3. the special discount will be applied. - order_line_3.setQuantity(2) - - self.stepTic() - - # check again - self.assertEqual(self.getAmount(order, '3CD_AND_1HIGHEST_PRICED_DVD_15PERCENT_OFF'), - -450) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 16550) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 827.5) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 17377.5) - - class TestTradeModelLineSale(TestTradeModelLine): invoice_portal_type = 'Sale Invoice Transaction' invoice_line_portal_type = 'Invoice Line' @@ -3375,22 +2741,8 @@ class TestTradeModelLinePurchase(TestTradeModelLine): trade_condition_portal_type = 'Purchase Trade Condition' -class TestComplexTradeModelLineUseCaseSale(TestComplexTradeModelLineUseCase): - order_portal_type = 'Sale Order' - order_line_portal_type = 'Sale Order Line' - trade_condition_portal_type = 'Sale Trade Condition' - - -class TestComplexTradeModelLineUseCasePurchase(TestComplexTradeModelLineUseCase): - order_portal_type = 'Purchase Order' - order_line_portal_type = 'Purchase Order Line' - trade_condition_portal_type = 'Purchase Trade Condition' - - def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestTradeModelLineSale)) suite.addTest(unittest.makeSuite(TestTradeModelLinePurchase)) - suite.addTest(unittest.makeSuite(TestComplexTradeModelLineUseCaseSale)) - suite.addTest(unittest.makeSuite(TestComplexTradeModelLineUseCasePurchase)) return suite -- 2.30.9