# -*- 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