diff --git a/product/ERP5/mixin/amount_generator.py b/product/ERP5/mixin/amount_generator.py index d9518ce1ecc145a8f8de9b7dd8d299ba97964a80..abd3f85850c3057bb5671c8d201a2f0efd5ecc90 100644 --- a/product/ERP5/mixin/amount_generator.py +++ b/product/ERP5/mixin/amount_generator.py @@ -57,17 +57,8 @@ class BaseAmount(dict): def getContext(self): return self._context - def updateCache(self, base_amount_set, amount_generator_line): - cache = self._cache - base_amount_set = base_amount_set.difference(cache) - if base_amount_set: - method = amount_generator_line._getTypeBasedMethod( - 'getBaseAmountQuantityMethod') - for base_amount in base_amount_set: - if method is None: - cache[base_amount] = amount_generator_line.getBaseAmountQuantity - else: - cache[base_amount] = method(base_amount) + def setAmountGeneratorLine(self, amount_generator_line): + self._amount_generator_line = amount_generator_line def recurse(self, portal_type=None): for amount in self._context.objectValues(portal_type=portal_type): @@ -92,7 +83,9 @@ class BaseAmount(dict): return dict.__getitem__(self, key) except KeyError: value = 0 + amount_generator_line = self._amount_generator_line for lazy in self._lazy: + lazy._amount_generator_line = amount_generator_line value += lazy.getQuantity(key) self[key] = value return value @@ -109,7 +102,17 @@ class BaseAmount(dict): return dict.__getitem__(self, key) self[key] # initialize entry before we freeze it self._frozen.add(key) - self[key] = value = self._cache[key](self._context, key, **self._method_kw) + try: + method = self._cache[key] + except KeyError: + method = self._amount_generator_line._getTypeBasedMethod( + 'getBaseAmountQuantityMethod') + if method is not None: + method = method(key) + if method is None: + method = self._amount_generator_line.getBaseAmountQuantity + self._cache[key] = method + self[key] = value = method(self._context, key, **self._method_kw) return value @@ -241,11 +244,9 @@ class AmountGeneratorMixin: cell.getBaseContributionList()) property_dict['causality_value_list'].append(cell) + base_amount.setAmountGeneratorLine(self) for property_dict in cell_aggregate.itervalues(): base_application_set = property_dict['base_application_set'] - # Cache must be prepared with the right context in case that we iterate - # through different kinds of amount generator lines. - base_amount.updateCache(base_application_set, self) # property_dict may include # resource - VAT service or a Component in MRP # (if unset, the amount will only be used for reporting) @@ -293,13 +294,10 @@ class AmountGeneratorMixin: amount = getRoundingProxy(amount, context=self) result.append(amount) # Contribute - base_contribution_set = property_dict['base_contribution_set'] - if base_contribution_set: - quantity *= (property_dict.get('price') or 1) / \ - (property_dict.get('efficiency') or 1) - base_amount.updateCache(base_contribution_set, self) - for base_contribution in base_contribution_set: - base_amount[base_contribution] += quantity + quantity *= (property_dict.get('price') or 1) / \ + (property_dict.get('efficiency') or 1) + for base_contribution in property_dict['base_contribution_set']: + base_amount[base_contribution] += quantity is_mapped_value = isinstance(self, MappedValue) diff --git a/product/ERP5/tests/testBPMCore.py b/product/ERP5/tests/testBPMCore.py index 79abd94e08e40b6ed780ad4392ef2fb026ebf662..30f8c5a66991575258ff5a3e65c481fcc9fa74b5 100644 --- a/product/ERP5/tests/testBPMCore.py +++ b/product/ERP5/tests/testBPMCore.py @@ -60,7 +60,7 @@ class TestBPMMixin(ERP5TypeTestCase): def createCategories(self): category_tool = self.portal.portal_categories self.createCategoriesInCategory(category_tool.base_amount, ['discount', - 'tax', 'total_tax', 'total_discount', 'total', 'fixed_quantity']) + 'tax', 'total_tax', 'total_discount', 'total']) self.createCategoriesInCategory(category_tool.use, self.normal_resource_use_category_list + \ self.invoicing_resource_use_category_list) diff --git a/product/ERP5/tests/testComplexTradeModelLineUseCase.py b/product/ERP5/tests/testComplexTradeModelLineUseCase.py index 4230f8fd3e7bea4a456d4d6f14974a0612c60380..c63257c881901fb802f96d59ba738140e7094032 100644 --- a/product/ERP5/tests/testComplexTradeModelLineUseCase.py +++ b/product/ERP5/tests/testComplexTradeModelLineUseCase.py @@ -29,8 +29,6 @@ import unittest import transaction - -from Products.ERP5Type.tests.utils import createZODBPythonScript from Products.ERP5.tests.testTradeModelLine import TestTradeModelLineMixin @@ -39,140 +37,114 @@ class TestComplexTradeModelLineUseCase(TestTradeModelLineMixin): 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): - amount_list = [] - for amount in order.getAggregatedAmountList(): - if amount.getProperty('reference') == reference: - amount_list.append(amount) - if return_object: - return amount_list - if amount_list: - return sum(amount.getTotalPrice() for amount in amount_list) - - 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 appendBaseContributionCategory(self, document, *new_category): + document.setBaseContributionList( + document.getBaseContributionList() + list(new_category)) + + def createCategories(self): + super(TestComplexTradeModelLineUseCase, self).createCategories() + category_tool = self.portal.portal_categories + self.createCategoriesInCategory(category_tool.base_amount, ( + 'additional_charge', + 'discount_amount', + 'discount_amount_of_non_vat_taxable', + 'discount_amount_of_vat_taxable', + 'total_price_of_ordered_items', + 'total_price_of_vat_taxable', + 'total_price_without_vat', + 'total_price_with_vat', + 'vat_amount', + 'vat_taxable', + )) + self.createCategoriesInCategory(category_tool.product_line, ( + 'audio', 'video', 'other')) + self.createCategoriesInCategory(category_tool.product_line.audio, ('cd',)) + self.createCategoriesInCategory(category_tool.product_line.video, ('dvd',)) + self.createCategoriesInCategory(category_tool.quantity_unit, ('unit',)) def afterSetUp(self): + super(TestComplexTradeModelLineUseCase, self).afterSetUp() 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() - + jpy = portal.currency_module.newContent(title='Yen', reference='JPY', + base_unit_quantity='1') # 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.additional_charge = base_amount.newContent('additional_charge') - 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='DISCOUNT') self.service_shipping_fee = portal.service_module.newContent(title='SHIPPING FEE') - self.stepTic() - # create products - def addProductDocument(title, product_line_value): + def addProductDocument(title, product_line): 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( + product_line=product_line, + quantity_unit='unit', + base_contribution_list=('base_amount/vat_taxable', + 'base_amount/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') + self.poster = addProductDocument('Poster', 'other') + 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') + + # create a trade condition with several common trade model lines + self.trade_condition = self.createTradeCondition( + self.createBusinessProcess(), ( + dict(title='Total Price Without VAT', + reference='TOTAL_PRICE_WITHOUT_VAT', + price=1, + int_index=10, + target_delivery=True, + base_application_list=('base_amount/discount_amount_of_non_vat_taxable', + 'base_amount/discount_amount_of_vat_taxable', + 'base_amount/total_price_of_ordered_items', + 'base_amount/additional_charge'), + base_contribution='base_amount/total_price_without_vat'), + dict(title='Total Price Of VAT Taxable', + reference='TOTAL_PRICE_OF_VAT_TAXABLE', + price=1, + int_index=10, + target_delivery=True, + base_application_list=('base_amount/discount_amount_of_vat_taxable', + 'base_amount/vat_taxable'), + base_contribution='base_amount/total_price_of_vat_taxable'), + dict(title='Discount Amount', + reference='DISCOUNT_AMOUNT', + resource_value=self.service_discount, + price=1, + trade_phase='default/invoicing', + int_index=10, + target_delivery=True, + base_application_list=('base_amount/discount_amount_of_vat_taxable', + 'base_amount/discount_amount_of_non_vat_taxable'), + base_contribution='base_amount/discount_amount'), + dict(title='VAT Amount', + reference='VAT_AMOUNT', + resource_value=self.service_vat, + price=0.05, + trade_phase='default/invoicing', + int_index=10, + target_delivery=True, + base_application_list=('base_amount/discount_amount_of_vat_taxable', + 'base_amount/vat_taxable'), + base_contribution='base_amount/vat_amount'), + dict(title='Total Price With VAT', + reference='TOTAL_PRICE_WITH_VAT', + price=1, + int_index=20, + target_delivery=True, + base_application_list=('base_amount/vat_amount', + 'base_amount/total_price_without_vat'), + base_contribution='base_amount/total_price_with_vat') + ), source_section_value=my_company, source_value=my_company, source_decision_value=my_company, @@ -180,60 +152,6 @@ class TestComplexTradeModelLineUseCase(TestTradeModelLineMixin): 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, - trade_phase=None, - int_index=10, - base_application_value_list=[self.discount_amount_of_non_vat_taxable, - self.discount_amount_of_vat_taxable, - self.total_price_of_ordered_items, - self.additional_charge], - 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, - trade_phase=None, - int_index=10, - 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, - trade_phase_value=portal.portal_categories.trade_phase.default.invoicing, - int_index=10, - 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, - trade_phase_value=portal.portal_categories.trade_phase.default.invoicing, - int_index=10, - 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, - trade_phase=None, - int_index=20, - base_application_value_list=[self.vat_amount, - self.total_price_without_vat], - base_contribution_value_list=[self.total_price_with_vat]) self.stepTic() @@ -247,65 +165,56 @@ class TestComplexTradeModelLineUseCase(TestTradeModelLineMixin): 1 CD 2400 yen discount (5000+3000+2400) * 0.1 = 1040 yen """ - createZODBPythonScript( - self.portal.portal_skins.custom, - 'TradeModelLine_getAmountProperty', - 'amount, base_application, amount_list, *args, **kw', - """\ -if base_application == 'base_amount/special_discount_3cd': - total_quantity = sum([x.getQuantity() for x in amount_list - if x.isMovement() and base_application in x.getBaseContributionList()]) - if total_quantity < 3: - return 0 -""") - 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, - trade_phase=None, - int_index=0, - 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() + special_discount = self.setBaseAmountQuantityMethod( + 'special_discount', """\ +def getBaseAmountQuantity(delivery_amount, base_application, **kw): + if delivery_amount.isDelivery(): + total_quantity = sum([movement.getQuantity() + for movement in delivery_amount.getMovementList() + if base_application in movement.getBaseContributionList()]) + if total_quantity < 3: + return 0 + return context.getBaseAmountQuantity( + delivery_amount, base_application, **kw) +return getBaseAmountQuantity""") + + trade_condition = self.createTradeCondition( + self.trade_condition, ( + dict(reference='SPECIAL_DISCOUNT_3CD_LINEAR', + resource_value=self.service_discount, + price=-0.1, + int_index=0, + target_delivery=True, + base_application=special_discount, + base_contribution='base_amount/discount_amount_of_vat_taxable'), + )) + + order = self.createOrder(trade_condition, ( + dict(id='1', price=5000, quantity=1, resource_value=self.music_album_1), + dict(id='2', price=3000, quantity=1, resource_value=self.music_album_2), + dict(id='3', price=100, quantity=1, resource_value=self.candy), + )) + self.appendBaseContributionCategory(order['1'], special_discount) + self.appendBaseContributionCategory(order['2'], special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_LINEAR=None, + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=8100), + TOTAL_PRICE_WITH_VAT=dict(total_price=8505), + VAT_AMOUNT=dict(total_price=405)) - # 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) + line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(line, special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_LINEAR=dict(total_price=-1040), + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=9460), + TOTAL_PRICE_WITH_VAT=dict(total_price=9933), + VAT_AMOUNT=dict(total_price=473)) def test_usecase2(self): """ @@ -317,64 +226,51 @@ if base_application == 'base_amount/special_discount_3cd': 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, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD500YenDiscount', - trade_phase=None, - int_index=0, - 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() + special_discount = self.setBaseAmountQuantityMethod( + 'special_discount', """\ +return lambda delivery_amount, base_application, **kw: \\ + 3 <= sum([movement.getQuantity() + for movement in delivery_amount.getMovementList() + if base_application in movement.getBaseContributionList()])""") + + trade_condition = self.createTradeCondition( + self.trade_condition, ( + dict(reference='SPECIAL_DISCOUNT_3CD_FIXED', + resource_value=self.service_discount, + price=-1, + quantity=500, + int_index=0, + target_delivery=True, + base_application=special_discount, + base_contribution='base_amount/discount_amount_of_vat_taxable'), + )) + + order = self.createOrder(trade_condition, ( + dict(id='1', price=5000, quantity=1, resource_value=self.music_album_1), + dict(id='2', price=3000, quantity=1, resource_value=self.music_album_2), + dict(id='3', price=3000, quantity=1, resource_value=self.movie_dvd_1), + )) + self.appendBaseContributionCategory(order['1'], special_discount) + self.appendBaseContributionCategory(order['2'], special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_FIXED=None, + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=11000), + TOTAL_PRICE_WITH_VAT=dict(total_price=11550), + VAT_AMOUNT=dict(total_price=550)) - # 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) + line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(line, special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_FIXED=dict(total_price=-500), + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=12900), + TOTAL_PRICE_WITH_VAT=dict(total_price=13545), + VAT_AMOUNT=dict(total_price=645)) def test_usecase3(self): """ @@ -386,66 +282,55 @@ else: 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, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD10PercentDiscountFromTotal', - trade_phase=None, - int_index=0, - 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() + special_discount = self.setBaseAmountQuantityMethod( + 'special_discount', """\ +def getBaseAmountQuantity(delivery_amount, base_application, **kw): + total_quantity = sum([movement.getQuantity() + for movement in delivery_amount.getMovementList() + if base_application in movement.getBaseContributionList()]) + if total_quantity < 3: + return 0 + return delivery_amount.getGeneratedAmountQuantity( + 'base_amount/total_price_of_ordered_items') +return getBaseAmountQuantity""") + + trade_condition = self.createTradeCondition( + self.trade_condition, ( + dict(reference='SPECIAL_DISCOUNT_3CD_LINEAR', + resource_value=self.service_discount, + price=-0.1, + int_index=0, + target_delivery=True, + base_application=special_discount, + base_contribution='base_amount/discount_amount_of_vat_taxable'), + )) + + order = self.createOrder(trade_condition, ( + dict(id='1', price=5000, quantity=1, resource_value=self.music_album_1), + dict(id='2', price=3000, quantity=1, resource_value=self.movie_dvd_1), + dict(id='3', price=3000, quantity=1, resource_value=self.music_album_2), + )) + self.appendBaseContributionCategory(order['1'], special_discount) + self.appendBaseContributionCategory(order['3'], special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_LINEAR=None, + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=11000), + TOTAL_PRICE_WITH_VAT=dict(total_price=11550), + VAT_AMOUNT=dict(total_price=550)) - # 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) + line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(line, special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_LINEAR=dict(total_price=-1340), + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=12060), + TOTAL_PRICE_WITH_VAT=dict(total_price=12663), + VAT_AMOUNT=dict(total_price=603)) def test_usecase4(self): """ @@ -455,97 +340,72 @@ else: 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, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CDOr1DVDForPoster', - 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) + total_quantity = """\ +def getBaseAmountQuantity(delivery_amount, base_application, **kw): + value = delivery_amount.getGeneratedAmountQuantity(base_application) + if base_application in delivery_amount.getBaseContributionList(): + value += delivery_amount.getQuantity() + return value +return getBaseAmountQuantity""" + poster_present_1dvd = self.setBaseAmountQuantityMethod( + 'poster_present_1dvd', total_quantity) + poster_present_3cd = self.setBaseAmountQuantityMethod( + 'poster_present_3cd', total_quantity) + special_discount = self.setBaseAmountQuantityMethod( + 'special_discount', """\ +return lambda delivery_amount, base_application, **kw: \\ + 3 <= delivery_amount.getGeneratedAmountQuantity(%r) or \\ + 1 <= delivery_amount.getGeneratedAmountQuantity(%r)""" + % (poster_present_3cd, poster_present_1dvd)) + + trade_condition = self.createTradeCondition( + self.trade_condition, ( + dict(reference='SPECIAL_DISCOUNT_3CD_OR_1DVD_FIXED', + resource_value=self.poster, + price=0, + int_index=0, + target_delivery=True, + base_application=special_discount), + )) + + order = self.createOrder(trade_condition, ( + dict(id='1', price=3000, quantity=2, resource_value=self.music_album_4), + )) + self.appendBaseContributionCategory(order['1'], poster_present_3cd) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_OR_1DVD_FIXED=None, + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=6000), + TOTAL_PRICE_WITH_VAT=dict(total_price=6300), + VAT_AMOUNT=dict(total_price=300)) - 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_list = self.getAmount( - order, - '3CD_OR_1DVD_GET_1_POSTER_FREE', - return_object=True) - self.assertEqual(len(one_free_poster_amount_list), 1) - one_free_poster_amount = one_free_poster_amount_list[0] - 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) + line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.movie_dvd_1, + quantity=1, + price=3000) + self.appendBaseContributionCategory(line, poster_present_1dvd) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_OR_1DVD_FIXED=dict(total_price=None, quantity=1, + resource_value=self.poster), + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=9000), + TOTAL_PRICE_WITH_VAT=dict(total_price=9450), + VAT_AMOUNT=dict(total_price=450)) # 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_list = self.getAmount(order, - '3CD_OR_1DVD_GET_1_POSTER_FREE', - return_object=True) - self.assertEqual(len(one_free_poster_amount_list), 1) - one_free_poster_amount = one_free_poster_amount_list[0] - 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) + line = order.newContent(portal_type=self.order_line_portal_type, + resource_value=self.music_album_3, + quantity=1, + price=2400) + self.appendBaseContributionCategory(line, poster_present_3cd) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD_OR_1DVD_FIXED=dict(total_price=None, quantity=1, + resource_value=self.poster), + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=11400), + TOTAL_PRICE_WITH_VAT=dict(total_price=11970), + VAT_AMOUNT=dict(total_price=570)) def test_usecase5(self): """ @@ -557,156 +417,82 @@ else: 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, - target_level=TARGET_LEVEL_DELIVERY, - calculation_script_id='TradeModelLine_calculate3CD15PercentDiscountOf1HighestPricedDVD', - trade_phase=None, - int_index=0, - 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() + special_discount = self.setBaseAmountQuantityMethod( + 'special_discount', """\ +def getBaseAmountQuantity(delivery_amount, base_application, **kw): + highest_price = quantity = 0 + for movement in delivery_amount.getMovementList(): + if base_application in movement.getBaseContributionList(): + quantity += movement.getQuantity() + if movement.getResourceValue().getProductLine() == 'video/dvd': + highest_price = max(highest_price, movement.getPrice()) + return quantity >= 3 and highest_price +return getBaseAmountQuantity""") + + trade_condition = self.createTradeCondition( + self.trade_condition, ( + dict(reference='SPECIAL_DISCOUNT_3CD', + resource_value=self.service_discount, + price=-0.15, + int_index=0, + target_delivery=True, + base_application=special_discount, + base_contribution='base_amount/discount_amount_of_vat_taxable'), + )) + + order = self.createOrder(trade_condition, ( + dict(id='1', price=3000, quantity=1, resource_value=self.movie_dvd_1), + dict(id='2', price=1000, quantity=1, resource_value=self.movie_dvd_2), + dict(id='3', price=5000, quantity=1, resource_value=self.music_album_1), + dict(id='4', price=3000, quantity=1, resource_value=self.music_album_2), + )) + self.appendBaseContributionCategory(order['3'], special_discount) + self.appendBaseContributionCategory(order['4'], special_discount) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD=None, + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=12000), + TOTAL_PRICE_WITH_VAT=dict(total_price=12600), + VAT_AMOUNT=dict(total_price=600)) - # 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) + order['3'].setQuantity(2) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + SPECIAL_DISCOUNT_3CD=dict(total_price=-450), + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=16550), + TOTAL_PRICE_WITH_VAT=dict(total_price=17377.5), + VAT_AMOUNT=dict(total_price=827.5)) def test_usecase6(self): """ Use case 6 : Add a shipping fee by TradeModelLine and VAT is charged to this fee. """ - order = self.createOrder() - order.edit(specialise_value=self.trade_condition) - order.Order_applyTradeCondition(order.getSpecialiseValue()) - order.newContent(portal_type='Trade Model Line', - reference='SHIPPING_FEE', - resource_value=self.service_shipping_fee, - price=1, - quantity=500, - target_level=TARGET_LEVEL_DELIVERY, - trade_phase=None, - int_index=0, - base_application_value_list=[], - base_contribution_value_list=[self.additional_charge, - self.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) - - self.stepTic() - - # check amounts - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 4500) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 225) - self.assertEqual( - len(self.getAmount(order, 'VAT_AMOUNT', return_object=True)), - 1) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 4725) - - # change trade model line and calculate vat price per movement - order.newContent(portal_type='Trade Model Line', - title='VAT Amount', - reference='VAT_AMOUNT', - resource_value=self.service_vat, - price=0.05, - target_level=TARGET_LEVEL_MOVEMENT, - trade_phase_value=self.portal.portal_categories.trade_phase.default.invoicing, - int_index=10, - base_application_value_list=[self.discount_amount_of_vat_taxable, - self.vat_taxable], - base_contribution_value_list=[self.vat_amount]) - - self.stepTic() - - # check amounts again - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITHOUT_VAT'), 4500) - self.assertEqual(self.getAmount(order, 'VAT_AMOUNT'), 225) - self.assertEqual( - len(self.getAmount(order, 'VAT_AMOUNT', return_object=True)), - 3) - self.assertEqual(self.getAmount(order, 'TOTAL_PRICE_WITH_VAT'), 4725) + fixed_quantity = self.setBaseAmountQuantityMethod('fixed_quantity', """\ +return lambda *args, **kw: 1""") + + trade_condition = self.createTradeCondition( + self.trade_condition, ( + dict(reference='SHIPPING_FEE', + resource_value=self.service_discount, + quantity=500, + int_index=0, + target_delivery=True, + base_application=fixed_quantity, + base_contribution_list=('base_amount/additional_charge', + 'base_amount/vat_taxable')), + )) + + order = self.createOrder(trade_condition, ( + dict(id='1', price=3000, quantity=1, resource_value=self.movie_dvd_1), + dict(id='2', price=1000, quantity=1, resource_value=self.movie_dvd_2), + )) + transaction.commit() + self.getAggregatedAmountDict(order, partial_check=True, + TOTAL_PRICE_WITHOUT_VAT=dict(total_price=4500), + TOTAL_PRICE_WITH_VAT=dict(total_price=4725), + VAT_AMOUNT=dict(total_price=225)) class TestComplexTradeModelLineUseCaseSale(TestComplexTradeModelLineUseCase): diff --git a/product/ERP5/tests/testTradeModelLine.py b/product/ERP5/tests/testTradeModelLine.py index 2d6e6bd4290fed8c80eb1aa6ef14c0fc128131da..fcf4b6b58cd467f749d5725d28f1fe38286447eb 100644 --- a/product/ERP5/tests/testTradeModelLine.py +++ b/product/ERP5/tests/testTradeModelLine.py @@ -56,6 +56,8 @@ class TestTradeModelLineMixin(TestBPMMixin, UserDict): """Provides methods to implementations sharing similar logic to Trade Model Lines""" # Constants and variables shared by tests base_unit_quantity = 0.01 + node_portal_type = 'Organisation' + order_date = DateTime() def setBaseAmountQuantityMethod(self, base_amount_id, text): """Populate TradeModelLine_getBaseAmountQuantityMethod shared script @@ -65,10 +67,11 @@ class TestTradeModelLineMixin(TestBPMMixin, UserDict): - data produced by previous still behaves as expected """ base_amount = self.portal.portal_categories.base_amount - try: - base_amount = base_amount[self._testMethodName] - except KeyError: - base_amount = base_amount.newContent(self._testMethodName) + for name in self.__class__.__name__, self._testMethodName: + try: + base_amount = base_amount[name] + except KeyError: + base_amount = base_amount.newContent(name) try: return base_amount[base_amount_id].getRelativeUrl() except KeyError: @@ -79,7 +82,7 @@ class TestTradeModelLineMixin(TestBPMMixin, UserDict): try: old_text = '\n' + skin[script_id].body() except KeyError: - old_text = "\nreturn context.getBaseAmountQuantity" + old_text = '' else: skin._delObject(script_id) text = test + '\n '.join(text.splitlines()) + old_text @@ -176,19 +179,29 @@ class TestTradeModelLineMixin(TestBPMMixin, UserDict): order.newContent(portal_type=self.order_line_portal_type, **line_kw) return order - def getAggregatedAmountDict(self, amount_generator, **expected_amount_dict): + def getAggregatedAmountDict(self, amount_generator, partial_check=False, + **expected_amount_dict): amount_list = amount_generator.getAggregatedAmountList() amount_dict = {} for amount in amount_list: reference = amount.getReference() - expected_amount = expected_amount_dict.pop(reference) - for k, v in expected_amount.iteritems(): - if k == 'causality_value_list': - self.assertEqual(v, amount.getValueList('causality')) - else: - self.assertEqual(v, amount.getProperty(k)) - amount_dict[reference] = amount - self.assertEqual({}, expected_amount_dict) + try: + expected_amount = expected_amount_dict.pop(reference) + except KeyError: + if not partial_check: + raise + else: + for k, v in expected_amount.iteritems(): + if k == 'causality_value_list': + self.assertEqual(v, amount.getValueList('causality')) + else: + self.assertEqual(v, amount.getProperty(k)) + amount_dict[reference] = amount + if partial_check: + for value in expected_amount_dict.itervalues(): + self.assertEqual(None, value) + else: + self.assertEqual({}, expected_amount_dict) return amount_dict def getTradeModelSimulationMovementList(self, delivery_line): @@ -220,9 +233,6 @@ class TestTradeModelLine(TestTradeModelLineMixin): new_discount_ratio = -0.04 # -4% new_tax_ratio = 0.22 # 22% - node_portal_type = 'Organisation' - order_date = DateTime() - modified_order_line_price_ratio = 2.0 modified_packing_list_line_quantity_ratio = 0.4 modified_invoice_line_quantity_ratio = modified_order_line_quantity_ratio \