From 49a9b13ec2b7f27195fd87c69f1c4b96f2059d27 Mon Sep 17 00:00:00 2001 From: Yusei Tahara <yusei@nexedi.com> Date: Wed, 2 Dec 2009 07:39:41 +0000 Subject: [PATCH] Separate complex trade model line test to another test case class and add 4 more tests. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30971 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/tests/testTradeModelLine.py | 634 +++++++++++++++++++---- 1 file changed, 522 insertions(+), 112 deletions(-) diff --git a/product/ERP5/tests/testTradeModelLine.py b/product/ERP5/tests/testTradeModelLine.py index 3ad37d0a0c..b028f3616f 100644 --- a/product/ERP5/tests/testTradeModelLine.py +++ b/product/ERP5/tests/testTradeModelLine.py @@ -32,6 +32,7 @@ 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, @@ -2657,83 +2658,143 @@ class TestTradeModelLine(TestTradeModelLineMixin): self.assertEqual(2, len(amount_list)) self.assertEqual(508.51000000000005, getTotalAmount(amount_list)) - def test_complexTradeModel(self): - """Make sure that trade model line is capable of complex use cases in the - real world. - """ + +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') - transaction.commit() - self.tic() + self.stepTic() # add organisations my_company = portal.organisation_module.newContent(title='My Company') client_1 = portal.organisation_module.newContent(title='Client 1') - transaction.commit() - self.tic() + self.stepTic() # add base amount subcategories base_amount = portal.portal_categories.base_amount - total_price_of_ordered_items = base_amount.newContent(id='total_price_of_ordered_items') - discount_amount_of_non_vat_taxable = base_amount.newContent(id='discount_amount_of_non_vat_taxable') - discount_amount_of_vat_taxable = base_amount.newContent(id='discount_amount_of_vat_taxable') - vat_taxable = base_amount.newContent(id='vat_taxable') - total_price_without_vat = base_amount.newContent(id='total_price_without_vat') - total_price_of_vat_taxable = base_amount.newContent(id='total_price_of_vat_taxable') - discount_amount = base_amount.newContent(id='discount_amount') - vat_amount = base_amount.newContent(id='vat_amount') - total_price_with_vat = base_amount.newContent(id='total_price_with_vat') - poster_present_1dvd = base_amount.newContent(id='poster_present_1dvd') - poster_present_3cd = base_amount.newContent(id='poster_present_3cd') - special_discount_3cd = base_amount.newContent(id='special_discount_3cd') + 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='dvd') + video = product_line.newContent(id='video') video_dvd = video.newContent(id='dvd') other_product = product_line.newContent(id='other') # add a quantity unit subcategory - unit = portal.portal_categories.quantity_unit.newContent(id='unit') + self.unit = portal.portal_categories.quantity_unit.newContent(id='unit') - transaction.commit() - self.tic() + self.stepTic() # create services - service_vat = portal.service_module.newContent(title='VAT') - service_discount = portal.service_module.newContent(title='VAT') + self.service_vat = portal.service_module.newContent(title='VAT') + self.service_discount = portal.service_module.newContent(title='VAT') - transaction.commit() - self.tic() + 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=unit, - base_contribution_value_list=[vat_taxable, - total_price_of_ordered_items]) - - music_album_1 = addProductDocument('Music Album 1', audio_cd) - movie_dvd_1 = addProductDocument('Movie DVD 1', video_dvd) - music_album_2 = addProductDocument('Movie Album 2', audio_cd) - candy = addProductDocument('Candy', other_product) - poster = addProductDocument('Poster', other_product) - music_album_3 = addProductDocument('Movie Album 3', audio_cd) - movie_dvd_2 = addProductDocument('Movie DVD 2', video_dvd) - music_album_4 = addProductDocument('Movie Album 4', audio_cd) + quantity_unit_value=self.unit, + base_contribution_value_list=[self.vat_taxable, + self.total_price_of_ordered_items]) - transaction.commit() - self.tic() + 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. - trade_condition = self.createTradeCondition() - trade_condition.edit( + self.trade_condition = self.createTradeCondition() + self.trade_condition.edit( source_section_value=my_company, source_value=my_company, source_decision_value=my_company, @@ -2741,7 +2802,7 @@ class TestTradeModelLine(TestTradeModelLineMixin): destination_value=client_1, destination_decision_value=client_1, price_currency_value=jpy) - trade_condition.newContent( + self.trade_condition.newContent( portal_type='Trade Model Line', title='Total Price Without VAT', reference='TOTAL_PRICE_WITHOUT_VAT', @@ -2751,11 +2812,11 @@ class TestTradeModelLine(TestTradeModelLineMixin): target_level=TARGET_LEVEL_DELIVERY, create_line=True, trade_phase=None, - base_application_value_list=[discount_amount_of_non_vat_taxable, - discount_amount_of_vat_taxable, - total_price_of_ordered_items], - base_contribution_value_list=[total_price_without_vat]) - trade_condition.newContent( + 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', @@ -2765,38 +2826,38 @@ class TestTradeModelLine(TestTradeModelLineMixin): target_level=TARGET_LEVEL_DELIVERY, create_line=True, trade_phase=None, - base_application_value_list=[discount_amount_of_vat_taxable, - vat_taxable], - base_contribution_value_list=[total_price_of_vat_taxable]) - trade_condition.newContent( + 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=service_discount, + 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=[discount_amount_of_vat_taxable, - discount_amount_of_non_vat_taxable], - base_contribution_value_list=[discount_amount]) - trade_condition.newContent( + 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=service_vat, + 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=[discount_amount_of_vat_taxable, - vat_taxable], - base_contribution_value_list=[vat_amount]) - trade_condition.newContent( + 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', @@ -2806,34 +2867,40 @@ class TestTradeModelLine(TestTradeModelLineMixin): target_level=TARGET_LEVEL_DELIVERY, create_line=True, trade_phase=None, - base_application_value_list=[vat_amount, total_price_without_vat], - base_contribution_value_list=[total_price_with_vat]) + base_application_value_list=[self.vat_amount, + self.total_price_without_vat], + base_contribution_value_list=[self.total_price_with_vat]) - transaction.commit() - self.tic() + self.stepTic() + + def test_usecase1(self): + """ + Use case 1 : Buy 3 CDs or more, get 10% off them. - # - # Use case 1 : Buy 3 CDs or more, get 10 percent discount off them. - # - from Products.ERP5Type.tests.utils import createZODBPythonScript + 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( - portal.portal_skins.custom, + 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=trade_condition) - order.Order_applyTradeCondition(trade_condition) + 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=service_discount, + resource_value=self.service_discount, price=-0.1, quantity=None, efficiency=1, @@ -2841,59 +2908,388 @@ else: calculation_script_id='TradeModelLine_calculate3CD10PercentDiscount', create_line=True, trade_phase=None, - base_application_value_list=[special_discount_3cd], - base_contribution_value_list=[discount_amount_of_vat_taxable]) + base_application_value_list=[self.special_discount_3cd], + base_contribution_value_list=[self.discount_amount_of_vat_taxable]) - def appendBaseContributionCategory(document, new_category): - base_contribution_value_list = document.getBaseContributionValueList() - document.setBaseContributionValueList( - base_contribution_value_list+[new_category]) - order_line_1 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=music_album_1, + resource_value=self.music_album_1, quantity=1, price=5000) - appendBaseContributionCategory(order_line_1, special_discount_3cd) + self.appendBaseContributionCategory(order_line_1, self.special_discount_3cd) order_line_2 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=music_album_2, + resource_value=self.music_album_2, quantity=1, price=3000) - appendBaseContributionCategory(order_line_2, special_discount_3cd) + self.appendBaseContributionCategory(order_line_2, self.special_discount_3cd) order_line_3 = order.newContent(portal_type=self.order_line_portal_type, - resource_value=candy, + resource_value=self.candy, quantity=1, price=100) - transaction.commit() - self.tic() - - def getAggregatedAmountResult(order, reference): - trade_condition = order.getSpecialiseValue() - for movement in trade_condition.getAggregatedAmountList(order): - if movement.getReference()==reference: - return movement.getTotalPrice() + self.stepTic() # check the current amount - self.assertEqual(getAggregatedAmountResult(order, 'TOTAL_PRICE_WITHOUT_VAT'), - 8100) - self.assertEqual(getAggregatedAmountResult(order, 'VAT_AMOUNT'), 405) - self.assertEqual(getAggregatedAmountResult(order, 'TOTAL_PRICE_WITH_VAT'), - 8505) + 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=music_album_3, + resource_value=self.music_album_3, quantity=1, price=2400) - appendBaseContributionCategory(order_line_4, special_discount_3cd) + self.appendBaseContributionCategory(order_line_4, self.special_discount_3cd) + + self.stepTic() + # check again - self.assertEqual(getAggregatedAmountResult(order, '3CD_AND_10PERCENT_DISCOUNT_OFF_THEM'), + self.assertEqual(self.getAmount(order, '3CD_AND_10PERCENT_DISCOUNT_OFF_THEM'), -1040) - self.assertEqual(getAggregatedAmountResult(order, 'TOTAL_PRICE_WITHOUT_VAT'), - 9460) - self.assertEqual(getAggregatedAmountResult(order, 'VAT_AMOUNT'), 473) - self.assertEqual(getAggregatedAmountResult(order, 'TOTAL_PRICE_WITH_VAT'), - 9933) - ### TODO: More use cases are needed. + 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): @@ -2916,8 +3312,22 @@ 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