Commit 5d929056 authored by Jérome Perrin's avatar Jérome Perrin

composition: only consider validated when looking up effective models

composition API, which is used to select the "most applicable" model
(Trade Condition, Transformation, Pay Sheet Model, etc) with the same
reference was only discarding deleted and validated models, but it
was selecting draft models.

This leads to this kind of problem:
 - A validated model exist, with an effective date
 - A new model is made by cloning the validated one, edited to set
  effective date from now and validated
 - The first validated model is also cloned by mistake, but not
  validated
In such case, the model cloned by mistake might be used, which from
user point of view is wrong, because user validated a model, so if
the system use a draft instead, that's a very wrong behaviour.

This change require models to be validated for the composition API to
work, many tests were updated to validate the model (either in the test
or in the data business template used by the test).

This change might also produce different results in production, because
it was possible that some draft models were selected before, now they
will no longer be selected. To check for potential side effects, we
recommend looking for all draft models with a reference, examine them
one by one and validate the model if it's a case where user forgot to
validate.
parent 0e57df28
...@@ -225,6 +225,7 @@ class TestConversionInSimulation(AccountingTestCase): ...@@ -225,6 +225,7 @@ class TestConversionInSimulation(AccountingTestCase):
# The ones we are creating are for Invoice Transaction Simulation Rule. # The ones we are creating are for Invoice Transaction Simulation Rule.
trade_model_path._setCriterionPropertyList(('portal_type',)) trade_model_path._setCriterionPropertyList(('portal_type',))
trade_model_path.setCriterion('portal_type', 'Simulation Movement') trade_model_path.setCriterion('portal_type', 'Simulation Movement')
business_process.validate()
self.tic() self.tic()
def buildPackingLists(self): def buildPackingLists(self):
......
...@@ -318,6 +318,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -318,6 +318,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
version='001', version='001',
reference='basic_model', reference='basic_model',
) )
model.validate()
sequence.edit(model = model) sequence.edit(model = model)
def addSlice(self, model, paysheet_model_slice, min_value, max_value, base_id='cell'): def addSlice(self, model, paysheet_model_slice, min_value, max_value, base_id='cell'):
...@@ -1086,16 +1087,20 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1086,16 +1087,20 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
model_employee = self.createModel() model_employee = self.createModel()
model_employee.edit(title='Employee Model', reference='model_employee', model_employee.edit(title='Employee Model', reference='model_employee',
variation_settings_category_list='salary_range/france') variation_settings_category_list='salary_range/france')
model_employee.validate()
model_company = self.createModel() model_company = self.createModel()
model_company.edit(title='Company Model', reference='model_company', model_company.edit(title='Company Model', reference='model_company',
variation_settings_category_list='salary_range/france') variation_settings_category_list='salary_range/france')
model_company.validate()
model_company_alt = self.createModel() model_company_alt = self.createModel()
model_company_alt.edit(title='Second Company Model', model_company_alt.edit(title='Second Company Model',
reference='model_company_alt', reference='model_company_alt',
variation_settings_category_list='salary_range/france') variation_settings_category_list='salary_range/france')
model_company_alt.validate()
model_country = self.createModel() model_country = self.createModel()
model_country.edit(title='Country Model', reference='model_country', model_country.edit(title='Country Model', reference='model_country',
variation_settings_category_list='salary_range/france') variation_settings_category_list='salary_range/france')
model_country.validate()
# add some cells in the models # add some cells in the models
slice1 = model_employee.newCell('salary_range/france/slice_a', slice1 = model_employee.newCell('salary_range/france/slice_a',
portal_type='Pay Sheet Model Slice', portal_type='Pay Sheet Model Slice',
...@@ -1570,6 +1575,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1570,6 +1575,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
price=0.01, price=0.01,
quantity=10000.0) quantity=10000.0)
model_without_date.validate()
self.tic() self.tic()
# create a paysheet without date # create a paysheet without date
...@@ -1628,6 +1634,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1628,6 +1634,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
reference='fabien_model_2009', reference='fabien_model_2009',
effective_date=DateTime(2009, 1, 1), effective_date=DateTime(2009, 1, 1),
expiration_date=DateTime(2009, 06, 30)) expiration_date=DateTime(2009, 06, 30))
model_1.validate()
model_2 = self.getPortalObject().paysheet_model_module.newContent( \ model_2 = self.getPortalObject().paysheet_model_module.newContent( \
specialise_value=sequence.get('business_process'), specialise_value=sequence.get('business_process'),
...@@ -1636,6 +1643,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1636,6 +1643,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
reference='fabien_model_2009', reference='fabien_model_2009',
effective_date=DateTime(2009, 07, 1), effective_date=DateTime(2009, 07, 1),
expiration_date=DateTime(2009, 12, 31)) expiration_date=DateTime(2009, 12, 31))
model_2.validate()
model_line_3 = self.createModelLine(model_1) model_line_3 = self.createModelLine(model_1)
model_line_3.edit( model_line_3.edit(
...@@ -1675,12 +1683,11 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1675,12 +1683,11 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
# calculate the pay sheet # calculate the pay sheet
paysheet.applyTransformation() paysheet.applyTransformation()
self.tic() self.tic()
# XXX-Aurel Why it is one as the model should not apply since date are not in the range ??
self.assertEqual(len(paysheet.contentValues(\ self.assertEqual(len(paysheet.contentValues(\
portal_type='Pay Sheet Line')), 1) portal_type='Pay Sheet Line')), 1)
# check values on the paysheet, if it's model_2, the total_price # check values on the paysheet, if it's model_2, the total_price
# should be 30000. # should be 30000.
# self.assertEqual(paysheet.contentValues()[0].getTotalPrice(), 30000) self.assertEqual(paysheet.contentValues()[0].getTotalPrice(), 30000)
def stepCheckModelVersioning(self, sequence=None, **kw): def stepCheckModelVersioning(self, sequence=None, **kw):
''' '''
...@@ -1697,6 +1704,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1697,6 +1704,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
effective_date=DateTime(2009, 01, 1), effective_date=DateTime(2009, 01, 1),
expiration_date=DateTime(2009, 02, 28), expiration_date=DateTime(2009, 02, 28),
specialise_value=sequence.get('business_process')) specialise_value=sequence.get('business_process'))
model_1.validate()
# define two models with same references and same dates # define two models with same references and same dates
# but different version number # but different version number
...@@ -1708,8 +1716,9 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1708,8 +1716,9 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
expiration_date=DateTime(2009, 12, 31), expiration_date=DateTime(2009, 12, 31),
version='002', version='002',
specialise_value=sequence.get('business_process')) specialise_value=sequence.get('business_process'))
model_2.validate()
self.getPortalObject().paysheet_model_module.newContent( \ model_2b = self.getPortalObject().paysheet_model_module.newContent( \
portal_type='Pay Sheet Model', portal_type='Pay Sheet Model',
variation_settings_category_list=['salary_range/france',], variation_settings_category_list=['salary_range/france',],
reference='fabien_model_2009', reference='fabien_model_2009',
...@@ -1717,6 +1726,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1717,6 +1726,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
expiration_date=DateTime(2009, 12, 31), expiration_date=DateTime(2009, 12, 31),
version='001', version='001',
specialise_value=sequence.get('business_process')) specialise_value=sequence.get('business_process'))
model_2b.validate()
self.tic() self.tic()
# create the paysheet # create the paysheet
...@@ -1794,6 +1804,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1794,6 +1804,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=10000) quantity=10000)
model_1.validate()
# define two models with same references and same dates # define two models with same references and same dates
# but different version number # but different version number
...@@ -1810,6 +1821,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1810,6 +1821,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=20000) quantity=20000)
model_2.validate()
model_3 = paysheet_model_module.newContent( \ model_3 = paysheet_model_module.newContent( \
portal_type='Pay Sheet Model', portal_type='Pay Sheet Model',
...@@ -1824,6 +1836,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1824,6 +1836,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=30000) quantity=30000)
model_3.validate()
# define two models with same references and same dates # define two models with same references and same dates
# but different version number # but different version number
...@@ -1840,6 +1853,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1840,6 +1853,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=40000) quantity=40000)
model_4.validate()
model_5 = paysheet_model_module.newContent( \ model_5 = paysheet_model_module.newContent( \
portal_type='Pay Sheet Model', portal_type='Pay Sheet Model',
...@@ -1854,6 +1868,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1854,6 +1868,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=50000) quantity=50000)
model_5.validate()
# third level : define two models with same references and same dates # third level : define two models with same references and same dates
# but different version number # but different version number
...@@ -1870,6 +1885,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1870,6 +1885,7 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=60000) quantity=60000)
model_6.validate()
model_7 = paysheet_model_module.newContent( \ model_7 = paysheet_model_module.newContent( \
portal_type='Pay Sheet Model', portal_type='Pay Sheet Model',
...@@ -1884,6 +1900,16 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase): ...@@ -1884,6 +1900,16 @@ class TestPayrollMixin(TestTradeModelLineMixin, ERP5ReportTestCase):
base_contribution_list=['base_amount/payroll/base/contribution', base_contribution_list=['base_amount/payroll/base/contribution',
'base_amount/payroll/report/salary/gross'], 'base_amount/payroll/report/salary/gross'],
quantity=70000) quantity=70000)
model_7.validate()
# a draft model that should not be selected
paysheet_model_module.newContent(
portal_type='Pay Sheet Model',
specialise_value=sequence.get('business_process'),
reference='fabien_model_level_3_2009',
effective_date=DateTime(2009, 07, 1),
expiration_date=DateTime(2009, 12, 31),
version='001')
self.tic() self.tic()
......
...@@ -134,6 +134,12 @@ ...@@ -134,6 +134,12 @@
<key> <string>version</string> </key> <key> <string>version</string> </key>
<value> <string>005</string> </value> <value> <string>005</string> </value>
</item> </item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
...@@ -195,4 +201,83 @@ ...@@ -195,4 +201,83 @@
<none/> <none/>
</pickle> </pickle>
</record> </record>
<record id="7" aka="AAAAAAAAAAc=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAg=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="8" aka="AAAAAAAAAAg=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>ERP5TypeTestCase</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1654590223.05</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData> </ZopeData>
...@@ -14,9 +14,7 @@ ...@@ -14,9 +14,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -27,9 +25,7 @@ ...@@ -27,9 +25,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -40,9 +36,7 @@ ...@@ -40,9 +36,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -54,9 +48,7 @@ ...@@ -54,9 +48,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -140,6 +132,12 @@ ...@@ -140,6 +132,12 @@
<key> <string>version</string> </key> <key> <string>version</string> </key>
<value> <string>005</string> </value> <value> <string>005</string> </value>
</item> </item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
...@@ -201,4 +199,83 @@ ...@@ -201,4 +199,83 @@
<none/> <none/>
</pickle> </pickle>
</record> </record>
<record id="7" aka="AAAAAAAAAAc=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAg=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="8" aka="AAAAAAAAAAg=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>ERP5TypeTestCase</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1654590227.55</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData> </ZopeData>
...@@ -2,3 +2,5 @@ person_module/beginner/default_career ...@@ -2,3 +2,5 @@ person_module/beginner/default_career
person_module/slicea/default_career person_module/slicea/default_career
person_module/sliceb/default_career person_module/sliceb/default_career
person_module/test_pay_sheet_transaction_user/default_career person_module/test_pay_sheet_transaction_user/default_career
paysheet_model_module/paysheet_model
paysheet_model_module/test_trainee
\ No newline at end of file
...@@ -479,6 +479,37 @@ class TestTradeConditionSupplyLine(TradeConditionTestCase): ...@@ -479,6 +479,37 @@ class TestTradeConditionSupplyLine(TradeConditionTestCase):
# not using the supply line inside trade condition # not using the supply line inside trade condition
self.assertEqual(1, line.getPrice()) self.assertEqual(1, line.getPrice())
def test_supply_line_in_draft_trade_condition_with_reference_does_not_apply(self):
# Supply lines in draft trade condition should not apply. This is a
# non regression test for a bug happening when there's a validated trade condition
# with a reference containing supply lines, but also a draft trade condition with
# the same reference. This use to confuse the composition and prices from the
# validated trade condition did not apply.
self.trade_condition.setReference(self.id())
self.trade_condition.newContent(
portal_type=self.supply_line_type,
resource_value=self.resource,
base_price=2)
another_trade_condition = self.trade_condition_module.newContent(
portal_type=self.trade_condition_type,
reference=self.id(),
)
another_trade_condition.newContent(
portal_type=self.supply_line_type,
resource_value=self.resource,
base_price=3,
)
self.tic()
self.order.setSpecialiseValue(self.trade_condition)
# using price from the validated trade condiion
self.assertEqual(
self.order.newContent(
portal_type=self.order_line_type,
resource_value=self.resource,
quantity=1).getPrice(), 2)
def test_supply_line_in_other_trade_condition_does_not_apply(self): def test_supply_line_in_other_trade_condition_does_not_apply(self):
"""Supply lines from trade condition not related to an order does not apply. """Supply lines from trade condition not related to an order does not apply.
""" """
...@@ -498,6 +529,81 @@ class TestTradeConditionSupplyLine(TradeConditionTestCase): ...@@ -498,6 +529,81 @@ class TestTradeConditionSupplyLine(TradeConditionTestCase):
# not using the supply line inside trade condition # not using the supply line inside trade condition
self.assertEqual(None, line.getPrice()) self.assertEqual(None, line.getPrice())
def test_supply_line_from_effective_trade_condition_apply_based_on_order_date(self):
self.trade_condition.setReference(self.id())
self.trade_condition.setExpirationDate(DateTime(1999, 12, 31))
self.trade_condition.newContent(
portal_type=self.supply_line_type,
resource_value=self.resource,
base_price=2,
)
another_trade_condition = self.trade_condition_module.newContent(
portal_type=self.trade_condition_type,
effective_date=DateTime(2000, 1, 1),
reference=self.id(),
)
another_trade_condition.newContent(
portal_type=self.supply_line_type,
resource_value=self.resource,
base_price=3,
)
another_trade_condition.validate()
self.tic()
self.order.setSpecialiseValue(self.trade_condition)
self.order.setStartDate(DateTime(1999, 1, 1))
self.assertEqual(
self.order.newContent(
portal_type=self.order_line_type,
resource_value=self.resource,
quantity=1).getPrice(), 2)
self.order.setStartDate(DateTime(2001, 1, 1))
self.assertEqual(
self.order.newContent(
portal_type=self.order_line_type,
resource_value=self.resource,
quantity=1).getPrice(), 3)
def test_supply_line_from_effective_specialised_trade_condition_apply(self):
# order -> self.trade_condition -> ~~invalidated_trade_condition~~ <- invalidated, not used
# validated_trade_condition <- validated, used instead
invalidated_trade_condition = self.trade_condition_module.newContent(
portal_type=self.trade_condition_type,
reference=self.id(),
)
invalidated_trade_condition.newContent(
portal_type=self.supply_line_type,
resource_value=self.resource,
base_price=2,
)
invalidated_trade_condition.validate()
invalidated_trade_condition.invalidate()
validated_trade_condition = self.trade_condition_module.newContent(
portal_type=self.trade_condition_type,
effective_date=DateTime(2000, 1, 1),
reference=self.id(),
)
validated_trade_condition.newContent(
portal_type=self.supply_line_type,
resource_value=self.resource,
base_price=3,
)
validated_trade_condition.validate()
self.trade_condition.setSpecialiseValue(invalidated_trade_condition)
self.order.setSpecialiseValue(self.trade_condition)
self.tic()
self.assertEqual(
self.order.newContent(
portal_type=self.order_line_type,
resource_value=self.resource,
quantity=1).getPrice(), 3)
# TODO: move to testSupplyLine ! (which does not exist yet) # TODO: move to testSupplyLine ! (which does not exist yet)
def test_supply_line_section(self): def test_supply_line_section(self):
# if a supply lines defines a section, it has priority over supply lines # if a supply lines defines a section, it has priority over supply lines
...@@ -538,8 +644,6 @@ class TestEffectiveTradeCondition(TradeConditionTestCase): ...@@ -538,8 +644,6 @@ class TestEffectiveTradeCondition(TradeConditionTestCase):
"""Tests for getEffectiveModel """Tests for getEffectiveModel
XXX open questions: XXX open questions:
- should getEffectiveModel take validation state into account ? if yes, how
to do it in generic/customizable way ?
- would getEffectiveModel(at_date) be enough ? - would getEffectiveModel(at_date) be enough ?
""" """
def test_getEffectiveModel(self): def test_getEffectiveModel(self):
...@@ -558,6 +662,13 @@ class TestEffectiveTradeCondition(TradeConditionTestCase): ...@@ -558,6 +662,13 @@ class TestEffectiveTradeCondition(TradeConditionTestCase):
version='002') version='002')
self.tic() self.tic()
self.assertEqual(self.trade_condition,
self.trade_condition.getEffectiveModel(
start_date=DateTime('2009/06/01'),
stop_date=DateTime('2009/06/01')))
other_trade_condition.validate()
self.tic()
self.assertEqual(other_trade_condition, self.assertEqual(other_trade_condition,
self.trade_condition.getEffectiveModel( self.trade_condition.getEffectiveModel(
start_date=DateTime('2009/06/01'), start_date=DateTime('2009/06/01'),
...@@ -621,7 +732,6 @@ class TestEffectiveTradeCondition(TradeConditionTestCase): ...@@ -621,7 +732,6 @@ class TestEffectiveTradeCondition(TradeConditionTestCase):
stop_date=DateTime())) stop_date=DateTime()))
class TestWithSaleOrder: class TestWithSaleOrder:
order_type = 'Sale Order' order_type = 'Sale Order'
order_line_type = 'Sale Order Line' order_line_type = 'Sale Order Line'
......
...@@ -14,9 +14,7 @@ ...@@ -14,9 +14,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -27,9 +25,7 @@ ...@@ -27,9 +25,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -40,9 +36,7 @@ ...@@ -40,9 +36,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -54,9 +48,7 @@ ...@@ -54,9 +48,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -114,6 +106,12 @@ ...@@ -114,6 +106,12 @@
<key> <string>version</string> </key> <key> <string>version</string> </key>
<value> <string>1</string> </value> <value> <string>1</string> </value>
</item> </item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
...@@ -139,4 +137,83 @@ ...@@ -139,4 +137,83 @@
<none/> <none/>
</pickle> </pickle>
</record> </record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="6" aka="AAAAAAAAAAY=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>ERP5TypeTestCase</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1654400466.1</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData> </ZopeData>
...@@ -14,9 +14,7 @@ ...@@ -14,9 +14,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -27,9 +25,7 @@ ...@@ -27,9 +25,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -40,9 +36,7 @@ ...@@ -40,9 +36,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -54,9 +48,7 @@ ...@@ -54,9 +48,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -120,6 +112,12 @@ ...@@ -120,6 +112,12 @@
<key> <string>version</string> </key> <key> <string>version</string> </key>
<value> <string>1</string> </value> <value> <string>1</string> </value>
</item> </item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
...@@ -175,4 +173,83 @@ ...@@ -175,4 +173,83 @@
<none/> <none/>
</pickle> </pickle>
</record> </record>
<record id="7" aka="AAAAAAAAAAc=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAg=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="8" aka="AAAAAAAAAAg=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>ERP5TypeTestCase</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1654400466.1</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData> </ZopeData>
business_process_module/erp5_default_business_process
business_process_module/erp5_default_task_business_process
\ No newline at end of file
...@@ -14,9 +14,7 @@ ...@@ -14,9 +14,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -27,9 +25,7 @@ ...@@ -27,9 +25,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -40,9 +36,7 @@ ...@@ -40,9 +36,7 @@
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -54,9 +48,7 @@ ...@@ -54,9 +48,7 @@
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string> <string>Auditor</string>
<string>Author</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -253,13 +245,11 @@ ...@@ -253,13 +245,11 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>action</string> </key> <key> <string>action</string> </key>
<value> <value> <string>validate</string> </value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>zope</string> </value> <value> <string>ERP5TypeTestCase</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -281,8 +271,8 @@ ...@@ -281,8 +271,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1560521297.13</float> <float>1654591230.28</float>
<string>UTC</string> <string>GMT+2</string>
</tuple> </tuple>
</state> </state>
</object> </object>
...@@ -290,7 +280,7 @@ ...@@ -290,7 +280,7 @@
</item> </item>
<item> <item>
<key> <string>validation_state</string> </key> <key> <string>validation_state</string> </key>
<value> <string>draft</string> </value> <value> <string>validated</string> </value>
</item> </item>
</dictionary> </dictionary>
</list> </list>
......
...@@ -53,10 +53,15 @@ def _getEffectiveModel(self, start_date, stop_date): ...@@ -53,10 +53,15 @@ def _getEffectiveModel(self, start_date, stop_date):
if not reference: if not reference:
return self return self
query_list = [Query(reference=reference), query_list = [
Query(reference=reference),
Query(portal_type=self.getPortalType()), Query(portal_type=self.getPortalType()),
Query(validation_state=('deleted', 'invalidated'), Query(validation_state=(
operator='NOT')] 'validated',
# XXX published is used in erp5_advanced_commerce
'published',
)),
]
if start_date is not None: if start_date is not None:
query_list.append(ComplexQuery(Query(effective_date=None), query_list.append(ComplexQuery(Query(effective_date=None),
Query(effective_date=start_date, Query(effective_date=start_date,
...@@ -68,16 +73,12 @@ def _getEffectiveModel(self, start_date, stop_date): ...@@ -68,16 +73,12 @@ def _getEffectiveModel(self, start_date, stop_date):
range='>'), range='>'),
logical_operator='OR')) logical_operator='OR'))
# XXX What to do the catalog returns nothing (either because 'self' was just
# created and not yet indexed, or because it was invalidated) ?
# For the moment, we return self if self is invalidated and we raise otherwise.
# This way, if this happens in activity it may succeed when activity is retried.
model_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults( model_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
query=ComplexQuery(logical_operator='AND', *query_list), query=ComplexQuery(logical_operator='AND', *query_list),
sort_on=(('version', 'descending'),)) sort_on=(('version', 'descending'),))
if not model_list: if not model_list:
if self.getValidationState() == 'invalidated': # The raise below also make the activity retried for cases where the model would
return self # not be indexed yet.
raise KeyError('No %s found with the reference %s between %s and %s' % \ raise KeyError('No %s found with the reference %s between %s and %s' % \
(self.getPortalType(), reference, start_date, stop_date)) (self.getPortalType(), reference, start_date, stop_date))
return model_list[0].getObject() return model_list[0].getObject()
......
...@@ -102,7 +102,13 @@ if explanation is not None: ...@@ -102,7 +102,13 @@ if explanation is not None:
context.getPortalOrderTypeList() + context.getPortalDeliveryTypeList(): context.getPortalOrderTypeList() + context.getPortalDeliveryTypeList():
# if there are trade conditions containing supply lines related to that # if there are trade conditions containing supply lines related to that
# order/invoice, we give high priority to those supply lines # order/invoice, we give high priority to those supply lines
for supply_line in explanation.asComposedDocument().objectValues(portal_type=context.getPortalSupplyPathTypeList()): try:
composed_document = explanation.asComposedDocument()
except KeyError:
pass
else:
for supply_line in composed_document.objectValues(
portal_type=context.getPortalSupplyPathTypeList()):
supply_cell_list = supply_line.objectValues( supply_cell_list = supply_line.objectValues(
portal_type=context.getPortalSupplyPathTypeList()) portal_type=context.getPortalSupplyPathTypeList())
if supply_cell_list: if supply_cell_list:
......
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