Commit 4cf0d77a authored by Romain Courteaud's avatar Romain Courteaud

slapos_accounting: XXX break instance tree periodicity. Must move to hosting subscription

slapos_accounting: rename script for hosting subscription

slapos_accounting: revert failure error

slapos_accounting: force open order line to have an Instance tree and a hosting subscription

slapos_accounting: hosting subscript will host the date info

slapos_accounting: set open order periodicity on the hosting subscription

slapos_accounting: typo

slapos_accounting: hosting subscription will contain the periodicity

slapos_accounting: create hosting subscription

slapos_accounting: fixup start/stop date confusion

slapos_accounting: fixup

slapos_cloud: add hosting subscription workflow

slapos_cloud: stop using Instance Tree as Subscription Item

slapos_accounting: move periodicity view on hosting subscription

slapos_erp5: open order line have 2 items now

slapos_cloud: open order line has 2 items now

slapos_accounting: simulation is expanded from Hosting Subscription

slapos_accounting: validate hosting subscription

slapos_accounting: check all aggregate value

slapos_accounting: revert aggregate tester

slapos_accounting: simulate from hosting subscription

slapos_accounting: constraint is on hosting subscription

slapos_accounting: interaction are on hosting subscription

slapos_subscription_request: periodicity is on hosting subscription

slapos_accounting: open order line has 2 aggregate

slapos_cloud: hosting subscription have a workflow again

slapos_cloud: add hosting subscription template

slapos_accounting: do not create open order if it was not allocated

slapos_accounting: script renamed

slapos_cloud: update HS_view
parent 8b386f26
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
<portal_type id="Computer Consumption TioXML File"> <portal_type id="Computer Consumption TioXML File">
<item>SortIndex</item> <item>SortIndex</item>
</portal_type> </portal_type>
<portal_type id="Instance Tree"> <portal_type id="Hosting Subscription">
<item>SlapOSAccountingInstanceTreeConstraint</item> <item>SlapOSAccountingHostingSubscriptionConstraint</item>
</portal_type> </portal_type>
<portal_type id="Open Sale Order"> <portal_type id="Open Sale Order">
<item>SlapOSAccountingOpenSaleOrderConstraint</item> <item>SlapOSAccountingOpenSaleOrderConstraint</item>
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
<type>Computer Consumption TioXML File</type> <type>Computer Consumption TioXML File</type>
<workflow>document_conversion_interaction_workflow, document_publication_workflow, edit_workflow</workflow> <workflow>document_conversion_interaction_workflow, document_publication_workflow, edit_workflow</workflow>
</chain> </chain>
<chain>
<type>Hosting Subscription</type>
<workflow>slapos_accounting_interaction_workflow</workflow>
</chain>
<chain> <chain>
<type>Instance Tree</type> <type>Instance Tree</type>
<workflow>slapos_accounting_interaction_workflow, slapos_api_invoicing_workflow</workflow> <workflow>slapos_accounting_interaction_workflow, slapos_api_invoicing_workflow</workflow>
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>SlapOSAccountingInstanceTreeConstraint</string> </value> <value> <string>SlapOSAccountingHostingSubscriptionConstraint</string> </value>
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Membership Arity Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_base_category</string> </key>
<value>
<tuple>
<string>aggregate</string>
</tuple>
</value>
</item>
<item>
<key> <string>constraint_portal_type</string> </key>
<value> <string>python: (\'Hosting Subscription\',)</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>aggregate_hosting_subscription_existence_constraint</string> </value>
</item>
<item>
<key> <string>max_arity</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>min_arity</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Membership Arity Constraint</string> </value>
</item>
<item>
<key> <string>use_acquisition</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Membership Arity Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_base_category</string> </key>
<value>
<tuple>
<string>aggregate</string>
</tuple>
</value>
</item>
<item>
<key> <string>constraint_portal_type</string> </key>
<value> <string>python: (\'Instance Tree\',)</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>aggregate_instance_tree_existence_constraint</string> </value>
</item>
<item>
<key> <string>max_arity</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>min_arity</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Membership Arity Constraint</string> </value>
</item>
<item>
<key> <string>use_acquisition</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
from erp5.component.module.DateUtils import getClosestDate
hosting_subscription = context
assert hosting_subscription.getPortalType() == "Hosting Subscription"
return getClosestDate(target_date=hosting_subscription.getCreationDate(), precision='day')
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>InstanceTree_calculateSubscriptionStartDate</string> </value> <value> <string>HostingSubscription_calculateSubscriptionStartDate</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
from erp5.component.module.DateUtils import getClosestDate
instance_tree = context
portal = context.getPortalObject()
workflow_item_list = portal.portal_workflow.getInfoFor(
ob=instance_tree,
name='history',
wf_id='instance_slap_interface_workflow')
start_date = None
for item in workflow_item_list:
start_date = item.get('time')
if start_date:
break
if start_date is None:
# Compatibility with old Instance tree
start_date = instance_tree.getCreationDate()
start_date = getClosestDate(target_date=start_date, precision='day')
return start_date
...@@ -62,9 +62,11 @@ if instance_tree.getCausalityState() == 'diverged': ...@@ -62,9 +62,11 @@ if instance_tree.getCausalityState() == 'diverged':
if (open_order_line is not None) and (open_order_line.getValidationState() == "invalidated"): if (open_order_line is not None) and (open_order_line.getValidationState() == "invalidated"):
instance_tree.converge(comment="Last open order: %s" % open_order_line.getRelativeUrl()) instance_tree.converge(comment="Last open order: %s" % open_order_line.getRelativeUrl())
elif open_order_line is None: elif open_order_line is None:
# User has no Open Sale Order (likely), so we add the line to remove later. This allow us to charge # User has no Open Sale Order (likely).
# eventual usage between the runs of the alarm. # No need to charge, as it was never allocated
is_open_order_creation_needed = True is_open_order_creation_needed = False
instance_tree.converge(comment="No open order needed as it was never allocated")
elif open_order_line is None: elif open_order_line is None:
# Let's add # Let's add
is_open_order_creation_needed = True is_open_order_creation_needed = True
...@@ -77,9 +79,14 @@ if instance_tree.getCausalityState() == 'diverged': ...@@ -77,9 +79,14 @@ if instance_tree.getCausalityState() == 'diverged':
# Add lines # Add lines
open_sale_order_line_template = portal.restrictedTraverse( open_sale_order_line_template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredOpenSaleOrderLineTemplate()) portal.portal_preferences.getPreferredOpenSaleOrderLineTemplate())
open_sale_order_line = open_sale_order_line_template.Base_createCloneDocument(batch_mode=1, open_order_line = open_sale_order_line_template.Base_createCloneDocument(batch_mode=1,
destination=open_sale_order) destination=open_sale_order)
start_date = instance_tree.InstanceTree_calculateSubscriptionStartDate() hosting_subscription = portal.hosting_subscription_module.newContent(
portal_type="Hosting Subscription",
title=instance_tree.getTitle()
)
hosting_subscription.validate()
start_date = hosting_subscription.HostingSubscription_calculateSubscriptionStartDate()
edit_kw = {} edit_kw = {}
subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request") subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request")
...@@ -106,7 +113,7 @@ if instance_tree.getCausalityState() == 'diverged': ...@@ -106,7 +113,7 @@ if instance_tree.getCausalityState() == 'diverged':
# You can increase 0 days to keep generating one month only # You can increase 0 days to keep generating one month only
# start_date_delta = 0 # start_date_delta = 0
open_sale_order_line.edit( open_order_line.edit(
activate_kw=activate_kw, activate_kw=activate_kw,
title=instance_tree.getTitle(), title=instance_tree.getTitle(),
start_date=start_date, start_date=start_date,
...@@ -115,19 +122,17 @@ if instance_tree.getCausalityState() == 'diverged': ...@@ -115,19 +122,17 @@ if instance_tree.getCausalityState() == 'diverged':
stop_date=start_date + 1, stop_date=start_date + 1,
# stop_date=calculateOpenOrderLineStopDate(open_sale_order_line, # stop_date=calculateOpenOrderLineStopDate(open_sale_order_line,
# instance_tree, start_date_delta=start_date_delta), # instance_tree, start_date_delta=start_date_delta),
aggregate_value=instance_tree, aggregate_value_list=[hosting_subscription, instance_tree],
**edit_kw **edit_kw
) )
storeWorkflowComment(open_sale_order_line, "Created for %s" % instance_tree.getRelativeUrl()) storeWorkflowComment(open_order_line, "Created for %s" % instance_tree.getRelativeUrl())
# instance_tree.converge(comment="Last open order: %s" % open_sale_order_line.getRelativeUrl()) # instance_tree.converge(comment="Last open order: %s" % open_sale_order_line.getRelativeUrl())
open_order_explanation = "Added %s." % str(open_sale_order_line.getId()) open_order_explanation = "Added %s." % str(open_order_line.getId())
storeWorkflowComment(open_sale_order, open_order_explanation) storeWorkflowComment(open_sale_order, open_order_explanation)
else: if open_order_line is not None:
open_sale_order = open_order_line.getParentValue() open_order_line.getParentValue().OpenSaleOrder_updatePeriod()
open_sale_order.OpenSaleOrder_updatePeriod()
# Person_storeOpenSaleOrderJournal should fix all divergent Instance Tree in one run # Person_storeOpenSaleOrderJournal should fix all divergent Instance Tree in one run
assert instance_tree.getCausalityState() == 'solved' assert instance_tree.getCausalityState() == 'solved'
...@@ -20,14 +20,14 @@ def storeWorkflowComment(document, comment): ...@@ -20,14 +20,14 @@ def storeWorkflowComment(document, comment):
portal.portal_workflow.doActionFor(document, 'edit_action', comment=comment) portal.portal_workflow.doActionFor(document, 'edit_action', comment=comment)
def calculateOpenOrderLineStopDate(open_order_line, instance_tree, start_date_delta, next_stop_date_delta=0): def calculateOpenOrderLineStopDate(open_order_line, hosting_subscription, instance_tree, start_date_delta, next_stop_date_delta=0):
end_date = instance_tree.InstanceTree_calculateSubscriptionStopDate() end_date = instance_tree.InstanceTree_calculateSubscriptionStopDate()
if end_date is None: if end_date is None:
# Be sure that start date is different from stop date # Be sure that start date is different from stop date
# Consider the first period longer (delta), this allow us to change X days/months # Consider the first period longer (delta), this allow us to change X days/months
# On a first invoice. # On a first invoice.
next_stop_date = instance_tree.getNextPeriodicalDate( next_stop_date = hosting_subscription.getNextPeriodicalDate(
instance_tree.InstanceTree_calculateSubscriptionStartDate() + start_date_delta) hosting_subscription.HostingSubscription_calculateSubscriptionStartDate() + start_date_delta)
current_stop_date = next_stop_date current_stop_date = next_stop_date
# Ensure the invoice is generated 15 days in advance of the next period. # Ensure the invoice is generated 15 days in advance of the next period.
...@@ -35,7 +35,7 @@ def calculateOpenOrderLineStopDate(open_order_line, instance_tree, start_date_de ...@@ -35,7 +35,7 @@ def calculateOpenOrderLineStopDate(open_order_line, instance_tree, start_date_de
# Return result should be < now, it order to provide stability in simulation (destruction if it happen should be >= now) # Return result should be < now, it order to provide stability in simulation (destruction if it happen should be >= now)
current_stop_date = next_stop_date current_stop_date = next_stop_date
next_stop_date = \ next_stop_date = \
instance_tree.getNextPeriodicalDate(current_stop_date) hosting_subscription.getNextPeriodicalDate(current_stop_date)
return addToDate(current_stop_date, to_add={'second': -1}) return addToDate(current_stop_date, to_add={'second': -1})
else: else:
...@@ -56,8 +56,9 @@ if open_sale_order.getValidationState() == 'validated': ...@@ -56,8 +56,9 @@ if open_sale_order.getValidationState() == 'validated':
assert current_stop_date is not None assert current_stop_date is not None
assert current_start_date < current_stop_date assert current_start_date < current_stop_date
hosting_subscription = open_order_line.getAggregateValue(portal_type='Hosting Subscription')
instance_tree = open_order_line.getAggregateValue(portal_type='Instance Tree') instance_tree = open_order_line.getAggregateValue(portal_type='Instance Tree')
assert current_start_date == instance_tree.InstanceTree_calculateSubscriptionStartDate() assert current_start_date == hosting_subscription.HostingSubscription_calculateSubscriptionStartDate()
subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request") subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request")
# Define the start date of the period, this can variates with the time. # Define the start date of the period, this can variates with the time.
...@@ -66,7 +67,7 @@ if open_sale_order.getValidationState() == 'validated': ...@@ -66,7 +67,7 @@ if open_sale_order.getValidationState() == 'validated':
next_stop_date_delta = 46 next_stop_date_delta = 46
# First check if the instance tree has been correctly simulated (this script may run only once per year...) # First check if the instance tree has been correctly simulated (this script may run only once per year...)
stop_date = calculateOpenOrderLineStopDate(open_order_line, instance_tree, stop_date = calculateOpenOrderLineStopDate(open_order_line, hosting_subscription, instance_tree,
start_date_delta=0, next_stop_date_delta=next_stop_date_delta) start_date_delta=0, next_stop_date_delta=next_stop_date_delta)
if current_stop_date < stop_date: if current_stop_date < stop_date:
# Bingo, new subscription to generate # Bingo, new subscription to generate
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>InstanceTree_getRuleReference</string> </value> <value> <string>HostingSubscription_getRuleReference</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -11,13 +11,13 @@ from unittest import skip ...@@ -11,13 +11,13 @@ from unittest import skip
import transaction import transaction
class TestInstanceTree(TestSlapOSConstraintMixin): class TestHostingSubscription(TestSlapOSConstraintMixin):
# use decrator in order to avoid fixing consistency of new object # use decrator in order to avoid fixing consistency of new object
@WorkflowMethod.disable @WorkflowMethod.disable
def _createInstanceTree(self): def _createInstanceTree(self):
self.subscription = self.portal.instance_tree_module.newContent( self.subscription = self.portal.hosting_subscription_module.newContent(
portal_type='Instance Tree') portal_type='Hosting Subscription')
def afterSetUp(self): def afterSetUp(self):
TestSlapOSConstraintMixin.afterSetUp(self) TestSlapOSConstraintMixin.afterSetUp(self)
......
...@@ -9,8 +9,8 @@ class TestSlapOSAccountingInteractionWorkflow(SlapOSTestCaseMixin): ...@@ -9,8 +9,8 @@ class TestSlapOSAccountingInteractionWorkflow(SlapOSTestCaseMixin):
def beforeTearDown(self): def beforeTearDown(self):
transaction.abort() transaction.abort()
def _simulateInstanceTree_calculateSubscriptionStartDate(self, date): def _simulateHostingSubscription_calculateSubscriptionStartDate(self, date):
script_name = 'InstanceTree_calculateSubscriptionStartDate' script_name = 'HostingSubscription_calculateSubscriptionStartDate'
if script_name in self.portal.portal_skins.custom.objectIds(): if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name) raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom, createZODBPythonScript(self.portal.portal_skins.custom,
...@@ -21,17 +21,17 @@ class TestSlapOSAccountingInteractionWorkflow(SlapOSTestCaseMixin): ...@@ -21,17 +21,17 @@ class TestSlapOSAccountingInteractionWorkflow(SlapOSTestCaseMixin):
return DateTime('%s') """ % date.ISO()) return DateTime('%s') """ % date.ISO())
transaction.commit() transaction.commit()
def _dropInstanceTree_calculateSubscriptionStartDate(self): def _dropHostingSubscription_calculateSubscriptionStartDate(self):
script_name = 'InstanceTree_calculateSubscriptionStartDate' script_name = 'HostingSubscription_calculateSubscriptionStartDate'
if script_name in self.portal.portal_skins.custom.objectIds(): if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name) self.portal.portal_skins.custom.manage_delObjects(script_name)
transaction.commit() transaction.commit()
def test_InstanceTree_fixConsistency(self, def test_HostingSubscription_fixConsistency(self,
date=DateTime('2012/01/15'), day=15): date=DateTime('2012/01/15'), day=15):
new_id = self.generateNewId() new_id = self.generateNewId()
item = self.portal.instance_tree_module.newContent( item = self.portal.hosting_subscription_module.newContent(
portal_type='Instance Tree', portal_type='Hosting Subscription',
title="Subscription %s" % new_id, title="Subscription %s" % new_id,
reference="TESTSUB-%s" % new_id, reference="TESTSUB-%s" % new_id,
periodicity_hour_list=None, periodicity_hour_list=None,
...@@ -43,48 +43,48 @@ return DateTime('%s') """ % date.ISO()) ...@@ -43,48 +43,48 @@ return DateTime('%s') """ % date.ISO())
self.assertEqual(item.getPeriodicityMinute(), None) self.assertEqual(item.getPeriodicityMinute(), None)
self.assertEqual(item.getPeriodicityMonthDay(), None) self.assertEqual(item.getPeriodicityMonthDay(), None)
self._simulateInstanceTree_calculateSubscriptionStartDate(date) self._simulateHostingSubscription_calculateSubscriptionStartDate(date)
try: try:
item.fixConsistency() item.fixConsistency()
finally: finally:
self._dropInstanceTree_calculateSubscriptionStartDate() self._dropHostingSubscription_calculateSubscriptionStartDate()
self.assertEqual(item.getPeriodicityHourList(), [0]) self.assertEqual(item.getPeriodicityHourList(), [0])
self.assertEqual(item.getPeriodicityMinuteList(), [0]) self.assertEqual(item.getPeriodicityMinuteList(), [0])
self.assertEqual(item.getPeriodicityMonthDay(), day) self.assertEqual(item.getPeriodicityMonthDay(), day)
def test_InstanceTree_fixConsistency_today_after_28(self): def test_HostingSubscription_fixConsistency_today_after_28(self):
self.test_InstanceTree_fixConsistency(DateTime('2012/01/29'), 28) self.test_HostingSubscription_fixConsistency(DateTime('2012/01/29'), 28)
def test_InstanceTree_manageAfter(self): def test_HostingSubscription_manageAfter(self):
class DummyTestException(Exception): class DummyTestException(Exception):
pass pass
def verify_fixConsistency_call(self): def verify_fixConsistency_call(self):
# Check that fixConsistency is called on instance tree # Check that fixConsistency is called on instance tree
if self.getRelativeUrl().startswith('instance_tree_module/'): if self.getRelativeUrl().startswith('hosting_subscription_module/'):
raise DummyTestException raise DummyTestException
else: else:
return self.fixConsistency_call() return self.fixConsistency_call()
# Replace serialize by a dummy method # Replace serialize by a dummy method
InstanceTreeClass = self.portal.portal_types.getPortalTypeClass( HostingSubscriptionClass = self.portal.portal_types.getPortalTypeClass(
'Instance Tree') 'Hosting Subscription')
InstanceTreeClass.fixConsistency_call = InstanceTreeClass.\ HostingSubscriptionClass.fixConsistency_call = HostingSubscriptionClass.\
fixConsistency fixConsistency
InstanceTreeClass.fixConsistency = verify_fixConsistency_call HostingSubscriptionClass.fixConsistency = verify_fixConsistency_call
try: try:
# manage_afterAdd # manage_afterAdd
self.assertRaises( self.assertRaises(
DummyTestException, DummyTestException,
self.portal.instance_tree_module.newContent, self.portal.hosting_subscription_module.newContent,
portal_type='Instance Tree') portal_type='Hosting Subscription')
# manage_afterClone # manage_afterClone
self.assertRaises( self.assertRaises(
DummyTestException, DummyTestException,
self.portal.instance_tree_module.\ self.portal.hosting_subscription_module.\
template_instance_tree.Base_createCloneDocument, template_hosting_subscription.Base_createCloneDocument,
batch_mode=1) batch_mode=1)
finally: finally:
self.portal.portal_types.resetDynamicDocumentsOnceAtTransactionBoundary() self.portal.portal_types.resetDynamicDocumentsOnceAtTransactionBoundary()
......
...@@ -417,11 +417,12 @@ class TestDefaultPaymentRule(SlapOSTestCaseMixin): ...@@ -417,11 +417,12 @@ class TestDefaultPaymentRule(SlapOSTestCaseMixin):
SimulationMovement.getSimulationState = SimulationMovement\ SimulationMovement.getSimulationState = SimulationMovement\
.original_getSimulationState .original_getSimulationState
class TestInstanceTreeSimulation(SlapOSTestCaseMixin): class TestHostingSubscriptionSimulation(SlapOSTestCaseMixin):
def _prepare(self): def _prepare(self):
person = self.portal.person_module.template_member\ person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1) .Base_createCloneDocument(batch_mode=1)
self.subscription = self.portal.instance_tree_module\ self.subscription = self.portal.hosting_subscription_module.newContent()
self.instance_tree = self.portal.instance_tree_module\
.template_instance_tree.Base_createCloneDocument(batch_mode=1) .template_instance_tree.Base_createCloneDocument(batch_mode=1)
self.initial_date = DateTime('2011/02/16') self.initial_date = DateTime('2011/02/16')
stop_date = DateTime('2011/04/16') stop_date = DateTime('2011/04/16')
...@@ -432,6 +433,7 @@ class TestInstanceTreeSimulation(SlapOSTestCaseMixin): ...@@ -432,6 +433,7 @@ class TestInstanceTreeSimulation(SlapOSTestCaseMixin):
destination_section=person.getRelativeUrl() destination_section=person.getRelativeUrl()
) )
self.portal.portal_workflow._jumpToStateFor(self.subscription, 'validated') self.portal.portal_workflow._jumpToStateFor(self.subscription, 'validated')
self.portal.portal_workflow._jumpToStateFor(self.instance_tree, 'validated')
open_sale_order_template = self.portal.restrictedTraverse( open_sale_order_template = self.portal.restrictedTraverse(
self.portal.portal_preferences.getPreferredOpenSaleOrderTemplate()) self.portal.portal_preferences.getPreferredOpenSaleOrderTemplate())
......
...@@ -12,12 +12,20 @@ import time ...@@ -12,12 +12,20 @@ import time
class TestSlapOSAccounting(SlapOSTestCaseMixin): class TestSlapOSAccounting(SlapOSTestCaseMixin):
def createHostingSubscription(self):
new_id = self.generateNewId()
return self.portal.hosting_subscription_module.newContent(
portal_type='Hosting Subscription',
title="Subscription %s" % new_id,
reference="TESTHS-%s" % new_id,
)
def createInstanceTree(self): def createInstanceTree(self):
new_id = self.generateNewId() new_id = self.generateNewId()
return self.portal.instance_tree_module.newContent( return self.portal.instance_tree_module.newContent(
portal_type='Instance Tree', portal_type='Instance Tree',
title="Subscription %s" % new_id, title="Subscription %s" % new_id,
reference="TESTHS-%s" % new_id, reference="TESTIT-%s" % new_id,
) )
def createOpenSaleOrder(self): def createOpenSaleOrder(self):
...@@ -30,72 +38,45 @@ class TestSlapOSAccounting(SlapOSTestCaseMixin): ...@@ -30,72 +38,45 @@ class TestSlapOSAccounting(SlapOSTestCaseMixin):
@withAbort @withAbort
def test_HS_calculateSubscriptionStartDate_REQUEST_disallowed(self): def test_HS_calculateSubscriptionStartDate_REQUEST_disallowed(self):
item = self.createInstanceTree() item = self.createHostingSubscription()
self.assertRaises( self.assertRaises(
Unauthorized, Unauthorized,
item.InstanceTree_calculateSubscriptionStartDate, item.HostingSubscription_calculateSubscriptionStartDate,
REQUEST={}) REQUEST={})
@withAbort @withAbort
def test_HS_calculateSubscriptionStartDate_noWorkflow(self): def test_HS_calculateSubscriptionStartDate_noWorkflow(self):
item = self.createInstanceTree() item = self.createHostingSubscription()
item.workflow_history['instance_slap_interface_workflow'] = [] item.workflow_history['instance_slap_interface_workflow'] = []
date = item.InstanceTree_calculateSubscriptionStartDate() date = item.HostingSubscription_calculateSubscriptionStartDate()
self.assertEqual(date, item.getCreationDate().earliestTime()) self.assertEqual(date, item.getCreationDate().earliestTime())
@withAbort @withAbort
def test_HS_calculateSubscriptionStartDate_withRequest(self): def test_HS_calculateSubscriptionStartDate_withRequest(self):
item = self.createInstanceTree() item = self.createHostingSubscription()
item.workflow_history['instance_slap_interface_workflow'] = [{ item.workflow_history['edit_workflow'] = [{
'comment':'Directly request the instance', 'comment':'Directly request the instance',
'error_message': '', 'error_message': '',
'actor': 'ERP5TypeTestCase', 'actor': 'ERP5TypeTestCase',
'slap_state': 'draft',
'time': DateTime('2012/11/15 11:11'), 'time': DateTime('2012/11/15 11:11'),
'action': 'request_instance' 'action': 'edit'
}] }]
date = item.InstanceTree_calculateSubscriptionStartDate() date = item.HostingSubscription_calculateSubscriptionStartDate()
self.assertEqual(date, DateTime('2012/11/15')) self.assertEqual(date, DateTime('2012/11/15'))
@withAbort @withAbort
def test_HS_calculateSubscriptionStartDate_withRequestEndOfMonth(self): def test_HS_calculateSubscriptionStartDate_withRequestEndOfMonth(self):
item = self.createInstanceTree() item = self.createHostingSubscription()
item.workflow_history['instance_slap_interface_workflow'] = [{ item.workflow_history['edit_workflow'] = [{
'comment':'Directly request the instance', 'comment':'Directly request the instance',
'error_message': '', 'error_message': '',
'actor': 'ERP5TypeTestCase', 'actor': 'ERP5TypeTestCase',
'slap_state': 'draft',
'time': DateTime('2012/11/30 11:11'), 'time': DateTime('2012/11/30 11:11'),
'action': 'request_instance' 'action': 'edit'
}] }]
date = item.InstanceTree_calculateSubscriptionStartDate() date = item.HostingSubscription_calculateSubscriptionStartDate()
self.assertEqual(date, DateTime('2012/11/30')) self.assertEqual(date, DateTime('2012/11/30'))
@withAbort
def test_HS_calculateSubscriptionStartDate_withRequestAfterDestroy(self):
item = self.createInstanceTree()
destroy_date = DateTime('2012/10/30 11:11')
request_date = DateTime('2012/11/30 11:11')
item.workflow_history['instance_slap_interface_workflow'] = []
item.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly destroy',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': destroy_date,
'action': 'request_destroy'
})
item.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly request the instance',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'draft',
'time': request_date,
'action': 'request_instance'
})
date = item.InstanceTree_calculateSubscriptionStartDate()
self.assertEqual(date, DateTime('2012/10/30'))
@withAbort @withAbort
def test_HS_calculateSubscriptionStopDate_REQUEST_disallowed(self): def test_HS_calculateSubscriptionStopDate_REQUEST_disallowed(self):
item = self.createInstanceTree() item = self.createInstanceTree()
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>interaction_InstanceTree_afterAddClone</string> </value> <value> <string>interaction_HostingSubscription_afterAddClone</string> </value>
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
<key> <string>portal_type_filter</string> </key> <key> <string>portal_type_filter</string> </key>
<value> <value>
<tuple> <tuple>
<string>Instance Tree</string> <string>Hosting Subscription</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -46,6 +46,10 @@ ...@@ -46,6 +46,10 @@
<key> <string>temporary_document_disallowed</string> </key> <key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value> <value> <int>1</int> </value>
</item> </item>
<item>
<key> <string>title</string> </key>
<value> <string>HostingSubscription_afterAddClone</string> </value>
</item>
<item> <item>
<key> <string>trigger_method_id</string> </key> <key> <string>trigger_method_id</string> </key>
<value> <value>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<key> <string>categories</string> </key> <key> <string>categories</string> </key>
<value> <value>
<tuple> <tuple>
<string>before_script/portal_workflow/slapos_accounting_interaction_workflow/script_InstanceTree_fixPeriodicity</string> <string>before_script/portal_workflow/slapos_accounting_interaction_workflow/script_HostingSubscription_fixPeriodicity</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>interaction_InstanceTree_fixConsistency</string> </value> <value> <string>interaction_HostingSubscription_fixConsistency</string> </value>
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
<key> <string>portal_type_filter</string> </key> <key> <string>portal_type_filter</string> </key>
<value> <value>
<tuple> <tuple>
<string>Instance Tree</string> <string>Hosting Subscription</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -46,6 +46,10 @@ ...@@ -46,6 +46,10 @@
<key> <string>temporary_document_disallowed</string> </key> <key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value> <value> <int>1</int> </value>
</item> </item>
<item>
<key> <string>title</string> </key>
<value> <string>HostingSubscription_fixConsistency</string> </value>
</item>
<item> <item>
<key> <string>trigger_method_id</string> </key> <key> <string>trigger_method_id</string> </key>
<value> <value>
......
from erp5.component.module.DateUtils import addToDate, getClosestDate from erp5.component.module.DateUtils import addToDate, getClosestDate
instance_tree = state_change['object'] hosting_subscription = state_change['object']
edit_kw = {} edit_kw = {}
if instance_tree.getPeriodicityHour() is None: if hosting_subscription.getPeriodicityHour() is None:
edit_kw['periodicity_hour_list'] = [0] edit_kw['periodicity_hour_list'] = [0]
if instance_tree.getPeriodicityMinute() is None: if hosting_subscription.getPeriodicityMinute() is None:
edit_kw['periodicity_minute_list'] = [0] edit_kw['periodicity_minute_list'] = [0]
if instance_tree.getPeriodicityMonthDay() is None: if hosting_subscription.getPeriodicityMonthDay() is None:
start_date = instance_tree.InstanceTree_calculateSubscriptionStartDate() start_date = hosting_subscription.HostingSubscription_calculateSubscriptionStartDate()
start_date = getClosestDate(target_date=start_date, precision='day') start_date = getClosestDate(target_date=start_date, precision='day')
while start_date.day() >= 29: while start_date.day() >= 29:
start_date = addToDate(start_date, to_add={'day': -1}) start_date = addToDate(start_date, to_add={'day': -1})
edit_kw['periodicity_month_day_list'] = [start_date.day()] edit_kw['periodicity_month_day_list'] = [start_date.day()]
if edit_kw: if edit_kw:
instance_tree.edit(**edit_kw) hosting_subscription.edit(**edit_kw)
...@@ -60,9 +60,15 @@ ...@@ -60,9 +60,15 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>script_InstanceTree_fixPeriodicity</string> </value> <value> <string>script_HostingSubscription_fixPeriodicity</string> </value>
</item> </item>
<item> <item>
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
......
...@@ -5,8 +5,8 @@ Compute Node | jump_to_consumption_report_view ...@@ -5,8 +5,8 @@ Compute Node | jump_to_consumption_report_view
Computer Consumption TioXML File | download Computer Consumption TioXML File | download
Computer Consumption TioXML File | view Computer Consumption TioXML File | view
Consumption Document Module | view Consumption Document Module | view
Hosting Subscription | periodicity
Instance Tree | jump_to_related_open_order_line Instance Tree | jump_to_related_open_order_line
Instance Tree | periodicity
Payment Transaction | related_payzen_event Payment Transaction | related_payzen_event
Person | create_new_cloud_contract Person | create_new_cloud_contract
Person | jump_to_cloud_contract Person | jump_to_cloud_contract
......
Cloud Contract Line | SlapOSCloudContractLineAccounting Cloud Contract Line | SlapOSCloudContractLineAccounting
Cloud Contract | SlapOSCloudContractAccounting Cloud Contract | SlapOSCloudContractAccounting
Computer Consumption TioXML File | SortIndex Computer Consumption TioXML File | SortIndex
Instance Tree | SlapOSAccountingInstanceTreeConstraint Hosting Subscription | SlapOSAccountingHostingSubscriptionConstraint
Open Sale Order Line | SlapOSAccountingOpenSaleOrderLineConstraint Open Sale Order Line | SlapOSAccountingOpenSaleOrderLineConstraint
Open Sale Order | SlapOSAccountingOpenSaleOrderConstraint Open Sale Order | SlapOSAccountingOpenSaleOrderConstraint
Sale Invoice Transaction | SlapOSAccountingSaleInvoiceTransactionConstraint Sale Invoice Transaction | SlapOSAccountingSaleInvoiceTransactionConstraint
......
...@@ -4,6 +4,7 @@ Cloud Contract | item_workflow ...@@ -4,6 +4,7 @@ Cloud Contract | item_workflow
Computer Consumption TioXML File | document_conversion_interaction_workflow Computer Consumption TioXML File | document_conversion_interaction_workflow
Computer Consumption TioXML File | document_publication_workflow Computer Consumption TioXML File | document_publication_workflow
Computer Consumption TioXML File | edit_workflow Computer Consumption TioXML File | edit_workflow
Hosting Subscription | slapos_accounting_interaction_workflow
Instance Tree | slapos_accounting_interaction_workflow Instance Tree | slapos_accounting_interaction_workflow
Instance Tree | slapos_api_invoicing_workflow Instance Tree | slapos_api_invoicing_workflow
Sale Invoice Transaction | slapos_accounting_interaction_workflow Sale Invoice Transaction | slapos_accounting_interaction_workflow
......
InstanceAccountingSynchronisation InstanceAccountingSynchronisation
SlapOSAccountingOpenSaleOrderLineConstraint SlapOSAccountingOpenSaleOrderLineConstraint
SlapOSAccountingOpenSaleOrderConstraint SlapOSAccountingOpenSaleOrderConstraint
SlapOSAccountingInstanceTreeConstraint SlapOSAccountingHostingSubscriptionConstraint
SlapOSAccountingSaleInvoiceTransactionConstraint SlapOSAccountingSaleInvoiceTransactionConstraint
SlapOSAccountingSalePackingListConstraint SlapOSAccountingSalePackingListConstraint
SlapOSAccountingSalePackingListLineConstraint SlapOSAccountingSalePackingListLineConstraint
......
...@@ -174,9 +174,7 @@ def HostingSubscription_checkInstanceTreeMigrationConsistency(self, fixit=False) ...@@ -174,9 +174,7 @@ def HostingSubscription_checkInstanceTreeMigrationConsistency(self, fixit=False)
mod = __import__('erp5.portal_type', globals(), locals(), ['Instance Tree']) mod = __import__('erp5.portal_type', globals(), locals(), ['Instance Tree'])
klass = getattr(mod, 'Instance Tree') klass = getattr(mod, 'Instance Tree')
if ((getattr(self, 'workflow_history', None) is not None) and if (self.__class__ == klass) or \
('hosting_subscription_workflow' in self.workflow_history)) or \
(self.__class__ == klass) or \
(self.getProperty('sla_xml', None) is not None) or \ (self.getProperty('sla_xml', None) is not None) or \
([x for x in self.getCategoryList() if (x.startswith('predecessor/') or ([x for x in self.getCategoryList() if (x.startswith('predecessor/') or
x.startswith('successor/'))]): x.startswith('successor/'))]):
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Hosting Subscription" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>template_hosting_subscription</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple>
<int>17</int>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Hosting Subscription</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
</item> </item>
<item> <item>
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>SubscriptionItem</string> </value> <value> <string>Item</string> </value>
</item> </item>
<item> <item>
<key> <string>type_interface</string> </key> <key> <string>type_interface</string> </key>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
</chain> </chain>
<chain> <chain>
<type>Hosting Subscription</type> <type>Hosting Subscription</type>
<workflow>edit_workflow</workflow> <workflow>edit_workflow, hosting_subscription_workflow</workflow>
</chain> </chain>
<chain> <chain>
<type>Instance Tree</type> <type>Instance Tree</type>
......
...@@ -94,13 +94,16 @@ ...@@ -94,13 +94,16 @@
<value> <value>
<list> <list>
<string>my_title</string> <string>my_title</string>
<string>my_reference</string>
</list> </list>
</value> </value>
</item> </item>
<item> <item>
<key> <string>right</string> </key> <key> <string>right</string> </key>
<value> <value>
<list/> <list>
<string>my_translated_validation_state_title</string>
</list>
</value> </value>
</item> </item>
</dictionary> </dictionary>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>display_width</string>
<string>editable</string>
<string>enabled</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_reference</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_reference</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Reference</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_translated_validation_state_title</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_translated_workflow_state_title</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -633,9 +633,15 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin): ...@@ -633,9 +633,15 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
self.assertEqual(len(instance_tree_list), len(line_list)) self.assertEqual(len(instance_tree_list), len(line_list))
self.assertSameSet( self.assertSameSet(
[q.getRelativeUrl() for q in instance_tree_list], [q.getRelativeUrl() for q in instance_tree_list],
[q.getAggregate() for q in line_list] [q.getAggregate(portal_type="Instance Tree") for q in line_list]
) )
# Every line must have 2 aggregate categories:
# one Instance Tree and one Hosting Subscription
for line in line_list:
self.assertEqual(2, len(line.getAggregateList()))
self.assertEqual(1, len(line.getAggregateList(portal_type="Hosting Subscription")))
validated_open_sale_order_list = [q for q in open_sale_order_list validated_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'validated'] if q.getValidationState() == 'validated']
# if no line, all open orders are kept archived # if no line, all open orders are kept archived
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>source/portal_workflow/hosting_subscription_workflow/state_draft</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>instance_tree_workflow</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>hosting_subscription_workflow</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow</string> </value>
</item>
<item>
<key> <string>state_variable</string> </key>
<value> <string>validation_state</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Hosting Subscription Workflow</string> </value>
</item>
<item>
<key> <string>workflow_managed_permission</string> </key>
<value>
<tuple>
<string>Access contents information</string>
<string>View</string>
<string>Add portal content</string>
<string>Modify portal content</string>
<string>Delete objects</string>
</tuple>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow State" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>state_archived</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow State</string> </value>
</item>
<item>
<key> <string>state_permission_role_list_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>state_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Archived</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>Access contents information</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Add portal content</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Delete objects</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Modify portal content</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>View</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow State" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/portal_workflow/hosting_subscription_workflow/transition_validate</string>
<string>destination/portal_workflow/hosting_subscription_workflow/transition_validate_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>state_draft</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow State</string> </value>
</item>
<item>
<key> <string>state_permission_role_list_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>state_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Draft</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>Access contents information</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>Add portal content</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>Delete objects</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>Modify portal content</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>View</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow State" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/portal_workflow/hosting_subscription_workflow/transition_archive</string>
<string>destination/portal_workflow/hosting_subscription_workflow/transition_archive_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>state_validated</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow State</string> </value>
</item>
<item>
<key> <string>state_permission_role_list_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>state_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Validated</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>Access contents information</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Add portal content</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Delete objects</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Modify portal content</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>View</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
</tuple>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>destination/portal_workflow/hosting_subscription_workflow/state_archived</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_archive</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Archive</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string encoding="cdata"><![CDATA[
%(content_url)s/BaseWorkflow_viewWorkflowActionDialog?workflow_action=archive_action&cancel_url=%(content_url)s
]]></string> </value>
</item>
<item>
<key> <string>action_name</string> </key>
<value> <string>Archive</string> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>after_script/portal_workflow/hosting_subscription_workflow/transition_archive</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_group</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>guard_role</string> </key>
<value>
<tuple>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_archive_action</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ArchiveAction</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>destination/portal_workflow/hosting_subscription_workflow/state_validated</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_validate</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Validate</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string encoding="cdata"><![CDATA[
%(content_url)s/BaseWorkflow_viewWorkflowActionDialog?workflow_action=validate_action&cancel_url=%(content_url)s
]]></string> </value>
</item>
<item>
<key> <string>action_name</string> </key>
<value> <string>Validate</string> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>after_script/portal_workflow/hosting_subscription_workflow/transition_validate</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_group</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>guard_role</string> </key>
<value>
<tuple>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_validate_action</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ValidateAction</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_action</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>transition/getReference|nothing</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The name of the user who performed the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_actor</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>user/getUserName</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Comments about the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_comment</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>python:state_change.kwargs.get(\'comment\', \'\')</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Error message if validation failed</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_error_message</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Provides access to workflow history</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_history</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>state_change/getHistory</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>portal type (use as filter for worklists)</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_portal_type</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Time of the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_time</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>state_change/getDateTime</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -5,6 +5,7 @@ compute_node_module/template_compute_node ...@@ -5,6 +5,7 @@ compute_node_module/template_compute_node
compute_node_module/template_compute_node/** compute_node_module/template_compute_node/**
computer_model_module/template_computer_model computer_model_module/template_computer_model
computer_model_module/template_computer_model/** computer_model_module/template_computer_model/**
hosting_subscription_module/template_hosting_subscription
instance_tree_module/template_instance_tree instance_tree_module/template_instance_tree
person_module/template_member person_module/template_member
person_module/template_member/** person_module/template_member/**
...@@ -26,4 +27,4 @@ portal_caches/last_stored_data_cache_factory/volatile_cache_plugin ...@@ -26,4 +27,4 @@ portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
product_module/compute_node product_module/compute_node
software_installation_module/template_software_installation software_installation_module/template_software_installation
software_instance_module/template_slave_instance software_instance_module/template_slave_instance
software_instance_module/template_software_instance software_instance_module/template_software_instance
\ No newline at end of file
...@@ -3,6 +3,7 @@ Compute Node | slapos_cloud_interaction_workflow ...@@ -3,6 +3,7 @@ Compute Node | slapos_cloud_interaction_workflow
Compute Partition | compute_partition_slap_interface_workflow Compute Partition | compute_partition_slap_interface_workflow
Computer Network | network_slap_interface_workflow Computer Network | network_slap_interface_workflow
Hosting Subscription | edit_workflow Hosting Subscription | edit_workflow
Hosting Subscription | hosting_subscription_workflow
Instance Tree | edit_workflow Instance Tree | edit_workflow
Instance Tree | instance_slap_interface_workflow Instance Tree | instance_slap_interface_workflow
Instance Tree | instance_tree_workflow Instance Tree | instance_tree_workflow
......
audit_validation_workflow audit_validation_workflow
compute_node_slap_interface_workflow compute_node_slap_interface_workflow
compute_partition_slap_interface_workflow compute_partition_slap_interface_workflow
hosting_subscription_workflow
installation_slap_interface_workflow installation_slap_interface_workflow
instance_slap_interface_workflow instance_slap_interface_workflow
instance_tree_workflow instance_tree_workflow
......
...@@ -321,11 +321,18 @@ class TestSlapOSDefaultCRMEscalation(DefaultScenarioMixin): ...@@ -321,11 +321,18 @@ class TestSlapOSDefaultCRMEscalation(DefaultScenarioMixin):
line_list = open_sale_order.contentValues( line_list = open_sale_order.contentValues(
portal_type='Open Sale Order Line') portal_type='Open Sale Order Line')
self.assertEqual(len(instance_tree_list), len(line_list)) self.assertEqual(len(instance_tree_list), len(line_list))
self.assertSameSet( self.assertSameSet(
[q.getRelativeUrl() for q in instance_tree_list], [q.getRelativeUrl() for q in instance_tree_list],
[q.getAggregate() for q in line_list] [q.getAggregate(portal_type="Instance Tree") for q in line_list]
) )
# Every line must have 2 aggregate categories:
# one Instance Tree and one Hosting Subscription
for line in line_list:
self.assertEqual(2, len(line.getAggregateList()))
self.assertEqual(1, len(line.getAggregateList(portal_type="Hosting Subscription")))
def assertAggregatedSalePackingList(self, delivery): def assertAggregatedSalePackingList(self, delivery):
self.assertEqual('delivered', delivery.getSimulationState()) self.assertEqual('delivered', delivery.getSimulationState())
self.assertEqual('solved', delivery.getCausalityState()) self.assertEqual('solved', delivery.getCausalityState())
......
...@@ -1829,7 +1829,9 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans ...@@ -1829,7 +1829,9 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
# Ensure periodicity is correct # Ensure periodicity is correct
for subscription_request in subscription_request_list: for subscription_request in subscription_request_list:
instance_tree = subscription_request.getAggregateValue() instance_tree = subscription_request.getAggregateValue()
self.assertEqual(instance_tree.getPeriodicityMonthDay(), open_order_line = instance_tree.getAggregateRelatedValue(portal_type="Open Sale Order Line")
hosting_subscription = open_order_line.getAggregateValue(portal_type="Hosting Subscription")
self.assertEqual(hosting_subscription.getPeriodicityMonthDay(),
min(DateTime().day(), 28)) min(DateTime().day(), 28))
self.pinDateTime(DateTime(DateTime().asdatetime() + datetime.timedelta(days=17))) self.pinDateTime(DateTime(DateTime().asdatetime() + datetime.timedelta(days=17)))
......
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