Commit fec3c923 authored by Yusei Tahara's avatar Yusei Tahara

Add target level property which defines how trade model line is applied to...

Add target level property which defines how trade model line is applied to movements and this changes getAggregatedAmountList behavior.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30853 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 1da4a6dc
......@@ -35,6 +35,8 @@ from Products.ERP5.Document.Amount import Amount
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.AggregatedAmountList import AggregatedAmountList
from Products.ERP5.Document.TradeCondition import TradeCondition
from Products.ERP5.PropertySheet.TradeModelLine import (TARGET_LEVEL_MOVEMENT,
TARGET_LEVEL_DELIVERY)
import zope.interface
def isMovement(document):
......@@ -101,11 +103,24 @@ class TradeModelLine(Predicate, XMLMatrix, Amount):
script_name
return script
security.declareProtected(Permissions.AccessContentsInformation, 'test')
def test(self, context, tested_base_category_list=None, strict_membership=0,
**kw):
result = TradeModelLine.inheritedAttribute('test')(
self, context, tested_base_category_list, strict_membership, **kw)
if result and self.getTargetLevel():
# If Trade Model Line is set to delivery level, then do nothing
# at movement level.
if self.getTargetLevel()==TARGET_LEVEL_DELIVERY and not context.isDelivery():
return False
return result
security.declareProtected(Permissions.AccessContentsInformation,
'getAggregatedAmountList')
def getAggregatedAmountList(self, context, movement_list = None,
current_aggregated_amount_list = None, base_id='movement', **kw):
from Products.ERP5Type.Document import newTempSimulationMovement
def getAggregatedAmountList(self, context, movement_list=None,
current_aggregated_amount_list=None, base_id='movement',
rounding=False, **kw):
# test with predicate if this model line could be applied
if not self.test(context):
......@@ -134,13 +149,37 @@ class TradeModelLine(Predicate, XMLMatrix, Amount):
if not movement.getBaseApplication():
movement_list.append(movement)
if self.getTargetLevel()==TARGET_LEVEL_MOVEMENT:
# movement level trade model is applied to each movement and
# generate result par movement.
result = []
for movement in movement_list:
result.extend(self._getAggregatedAmountList(
context, [movement], current_aggregated_amount_list,
base_id, rounding, **kw))
return result
else:
return self._getAggregatedAmountList(
context, movement_list, current_aggregated_amount_list,
base_id, rounding, **kw)
def _getAggregatedAmountList(self, context, movement_list=None,
current_aggregated_amount_list=None,
base_id='movement', rounding=False, **kw):
from Products.ERP5Type.Document import newTempSimulationMovement
aggregated_amount_list = AggregatedAmountList()
base_application_list = self.getBaseApplicationList()
self_id = self.getParentValue().getId() + '_' + self.getId()
tmp_movement_list = [q for q in current_aggregated_amount_list \
if q.getReference() == self.getReference()]
# Make tmp movement list only when trade model line is not set to movement level.
tmp_movement_list = []
if self.getTargetLevel()!=TARGET_LEVEL_MOVEMENT:
tmp_movement_list = [processed_movement
for processed_movement in current_aggregated_amount_list
if processed_movement.getReference() == self.getReference()]
if len(tmp_movement_list) > 0:
update = 1
else:
......@@ -201,6 +240,8 @@ class TradeModelLine(Predicate, XMLMatrix, Amount):
'stop_date': context.getStopDate(),
'create_line': self.isCreateLine(),
'trade_phase_list': self.getTradePhaseList(),
'causality_list': [movement.getRelativeUrl()
for movement in movement_list],
}
common_params.update(property_dict)
......
......@@ -26,6 +26,14 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ModuleSecurityInfo
TARGET_LEVEL_DELIVERY = 'DELIVERY'
TARGET_LEVEL_MOVEMENT = 'MOVEMENT'
ModuleSecurityInfo('Products.ERP5.PropertySheet.TradeModelLine').declarePublic(
'TARGET_LEVEL_DELIVERY', 'TARGET_LEVEL_MOVEMENT')
class TradeModelLine:
"""
......@@ -45,6 +53,27 @@ class TradeModelLine:
'type' : 'string',
'mode' : 'w',
},
{ 'id' : 'target_level',
'description' : 'Target level defines how trade model line is applied to '
'what(a set of movement or a movement). If target level '
'is `delivery`, then this is applied only at delivery '
'level(for example, VAT to total price of order). And if '
'target level is `movement`, then this is applied to one '
'movement and result will not be summed up(for example, '
'VAT to each order line). If target level is neither '
'delivery nor movement, this is applied to anything '
'without restriction.',
'type' : 'selection',
'select_variable' : 'getTargetLevelSelectionList',
'mode' : 'w',
'default' : None,
},
{ 'id' : 'target_level_selection',
'description' : 'List of possible values for target_level property',
'type' : 'tokens',
'mode' : '',
'default' : [TARGET_LEVEL_DELIVERY, TARGET_LEVEL_MOVEMENT],
},
)
_categories = (
......
......@@ -2386,6 +2386,107 @@ class TestTradeModelLine(TestTradeModelLineMixin):
self.expense_account)
self.assertEquals(1000, income_movement.getSourceCredit())
def test_tradeModelLineWithTargetLevelSetting(self):
"""
Test that target level setting can specify a target of trade model line
and trade model line can works with appropriate context(delivery or
movement) only.
"""
from Products.ERP5.PropertySheet.TradeModelLine import (
TARGET_LEVEL_MOVEMENT,
TARGET_LEVEL_DELIVERY)
trade_condition = self.createTradeCondition()
# create a model line and set target level to `delivery`.
tax = self.createTradeModelLine(trade_condition,
reference='TAX',
base_application_list=['base_amount/taxable'],
base_contribution_list=['base_amount/total_tax'])
tax.edit(price=0.05, target_level=TARGET_LEVEL_DELIVERY)
# create an order.
resource_A = self.createResource('Product', title='A')
resource_B = self.createResource('Product', title='B')
order = self.createOrder()
order.setSpecialiseValue(trade_condition)
order_line_1 = order.newContent(portal_type=self.order_line_portal_type,
price=1000, quantity=1,
resource_value=resource_A,
base_contribution_list=['base_amount/taxable'])
order_line_2 = order.newContent(portal_type=self.order_line_portal_type,
price=500, quantity=1,
resource_value=resource_B,
base_contribution_list=['base_amount/taxable'])
amount_list = trade_condition.getAggregatedAmountList(order)
self.assertEqual(1, len(amount_list))
self.assertEqual(set([order_line_1, order_line_2]),
set(amount_list[0].getCausalityValueList()))
self.assertEqual(75.0, amount_list[0].getTotalPrice())
# change target level to `movement`.
tax.edit(target_level=TARGET_LEVEL_MOVEMENT)
amount_list = trade_condition.getAggregatedAmountList(order)
self.assertEqual(2, len(amount_list))
self.assertEqual(1,
len([1 for amount in amount_list
if amount.getCausalityValueList() == [order_line_1]]))
self.assertEqual(1,
len([1 for amount in amount_list
if amount.getCausalityValueList() == [order_line_2]]))
# check getAggregatedAmountList result of order line.
amount_list = trade_condition.getAggregatedAmountList(order_line_1)
self.assertEqual(1, len(amount_list))
self.assertEqual([order_line_1], amount_list[0].getCausalityValueList())
amount_list = trade_condition.getAggregatedAmountList(order_line_2)
self.assertEqual(1, len(amount_list))
self.assertEqual([order_line_2], amount_list[0].getCausalityValueList())
# create other trade model lines.
# for movement
extra_fee = self.createTradeModelLine(trade_condition,
reference='EXTRA_FEE_A',
base_contribution_list=['base_amount/total'])
extra_fee.edit(quantity=100, price=1, target_level=TARGET_LEVEL_MOVEMENT)
# for delivery level
discount = self.createTradeModelLine(trade_condition,
reference='DISCOUNT_B',
base_contribution_list=['base_amount/total'],)
discount.edit(quantity=10, price=-1, target_level=TARGET_LEVEL_DELIVERY)
def getTotalAmount(amount_list):
result = 0
for amount in amount_list:
if amount.getBaseContribution() in ('base_amount/total', 'base_amount/total_tax'):
result += amount.getTotalPrice()
return result
amount_list = trade_condition.getAggregatedAmountList(order)
self.assertEqual(5, len(amount_list))
self.assertEqual(100 + 100 - 10 + 1000*0.05 + 500*0.05,
getTotalAmount(amount_list))
# Make sure that getAggregatedAmountList of movement uses movement
# level trade model line only.
amount_list = trade_condition.getAggregatedAmountList(order_line_1)
self.assertEqual(2, len(amount_list))
self.assertEqual([order_line_1],
amount_list[0].getCausalityValueList())
self.assertEqual([order_line_1],
amount_list[1].getCausalityValueList())
amount_list = trade_condition.getAggregatedAmountList(order_line_2)
self.assertEqual(2, len(amount_list))
self.assertEqual([order_line_2],
amount_list[0].getCausalityValueList())
self.assertEqual([order_line_2],
amount_list[1].getCausalityValueList())
# Change target level
extra_fee.edit(target_level=TARGET_LEVEL_DELIVERY)
tax.edit(target_level=TARGET_LEVEL_DELIVERY)
amount_list = trade_condition.getAggregatedAmountList(order)
self.assertEqual(3, len(amount_list))
self.assertEqual(100 - 10 + 1500*0.05,
getTotalAmount(amount_list))
class TestTradeModelLineSale(TestTradeModelLine):
invoice_portal_type = 'Sale Invoice Transaction'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment