Commit 1c1f266e authored by Cédric de Saint Martin's avatar Cédric de Saint Martin

Merge branch 'master' into no_bridge

parents 3f49f908 986dd36f
......@@ -60,7 +60,7 @@
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Software Instance</string> </value>
<value> <string>Requester</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
......@@ -79,7 +79,7 @@
<key> <string>text</string> </key>
<value> <string encoding="cdata"><![CDATA[
string:${object_url}/Base_jumpToRelatedObject?base_category=predecessor&portal_type=Software+Instance
string:${object_url}/Base_jumpToRelatedObject?base_category=predecessor&portal_type:list=Software+Instance&portal_type:list=Hosting+Subscription
]]></string> </value>
</item>
......
......@@ -36,3 +36,7 @@ class Person(ERP5Person):
"""Revokes existing certificate"""
self._checkCertificateRequest()
self._revokeCertificate()
def getPaymentState(self):
"""Allows to catalog slap_date in payment_state column"""
return self.getSlapState()
......@@ -108,3 +108,7 @@ class SoftwareInstance(Item):
if size != len(visited) + 1:
raise DisconnectedSoftwareTree
return True
def getPaymentState(self):
"""Allows to catalog slap_date in payment_state column"""
return self.getSlapState()
......@@ -7,6 +7,7 @@
<item>SlaveInstanceContraint</item>
<item>SoftwareInstance</item>
<item>TextDocument</item>
<item>VariationRange</item>
</portal_type>
<portal_type id="Software Instance">
<item>Reference</item>
......
......@@ -6,6 +6,18 @@
</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_property</string> </key>
<value>
......@@ -22,6 +34,18 @@
<key> <string>id</string> </key>
<value> <string>ssl_certificate_constraint</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>SSL Certificate must be set</string> </value>
......@@ -30,6 +54,52 @@
<key> <string>portal_type</string> </key>
<value> <string>Property Existence Constraint</string> </value>
</item>
<item>
<key> <string>string_index</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>test_tales_expression</string> </key>
<value> <string>python: context.SoftwareInstance_getStatus() != \'Destroyed\'</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/>
</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>
......
......@@ -6,6 +6,18 @@
</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_property</string> </key>
<value>
......@@ -22,6 +34,18 @@
<key> <string>id</string> </key>
<value> <string>ssl_key_constraint</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>SSL Key must be set</string> </value>
......@@ -30,6 +54,52 @@
<key> <string>portal_type</string> </key>
<value> <string>Property Existence Constraint</string> </value>
</item>
<item>
<key> <string>string_index</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>test_tales_expression</string> </key>
<value> <string>python: context.SoftwareInstance_getStatus() != \'Destroyed\'</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/>
</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>
......
......@@ -6,6 +6,18 @@
</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>
......@@ -16,7 +28,7 @@
</item>
<item>
<key> <string>constraint_portal_type</string> </key>
<value> <string>python: \'Software Instance\'</string> </value>
<value> <string>python: (\'Slave Instance\', \'Software Instance\')</string> </value>
</item>
<item>
<key> <string>description</string> </key>
......@@ -59,4 +71,34 @@
</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>
......@@ -286,9 +286,7 @@
</item>
<item>
<key> <string>lines</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
<value> <string></string> </value>
</item>
<item>
<key> <string>list_action</string> </key>
......@@ -416,7 +414,7 @@
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string>hidden_label gadget</string> </value>
<value> <string></string> </value>
</item>
<item>
<key> <string>default_display_style</string> </key>
......@@ -500,7 +498,7 @@
<item>
<key> <string>list_method</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
......@@ -615,19 +613,6 @@
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: int(context.restrictedTraverse(context.REQUEST.get(\'box_relative_url\', \'\')).KnowledgeBox_getDefaultPreferencesDict().get(\'listbox_selection_list_lines\', None) or 10)</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string># Did not import Products.ERP5Security.ERP5GroupManager\n
# because of semantic matter.\n
class ConsistencyError(Exception):\n
pass\n
\n
predecessor_software_instance = context\n
while (predecessor_software_instance is not None):\n
root_software_instance = predecessor_software_instance\n
predecessor_software_instance = predecessor_software_instance.getPredecessorRelatedValue(\n
portal_type=["Software Instance", "Slave Instance"])\n
\n
root_hosting_subscription = root_software_instance.getPredecessorRelatedValue(\n
portal_type="Hosting Subscription")\n
\n
# XXX-Antoine: As Romain wanted it, we raise an error if it\'s not attached to a\n
# root Hosting Subscription.\n
if root_hosting_subscription is None:\n
raise ConsistencyError(("Software instance %s has no hosting "\n
"subscription as root.") % context.getReference())\n
\n
return root_hosting_subscription.getUid()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_getRootHostingSubscriptionUid</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -50,21 +50,21 @@
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>predecessor_software_instance = context\n
while (predecessor_software_instance is not None):\n
root_software_instance = predecessor_software_instance\n
predecessor_software_instance = predecessor_software_instance.getPredecessorRelatedValue(\n
portal_type=["Software Instance", "Slave Instance"])\n
return root_software_instance.getUid()\n
<value> <string>movement = context\n
\n
if movement.getSimulationState() in movement.getCausalityValue(portal_type=\'Business Link\').getCompletedStateList():\n
return True\n
\n
return False\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<value> <string>rule</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_getRootSoftwareInstanceUid</string> </value>
<value> <string>SimulationMovement_testDeliverySimulationRule</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -65,7 +65,10 @@ if source_section == destination_section or source_section is None \\\n
or destination_section is None:\n
return False\n
\n
return True\n
if movement.getSimulationState() in movement.getCausalityValue(portal_type=\'Business Link\').getCompletedStateList():\n
return True\n
\n
return False\n
</string> </value>
</item>
<item>
......
......@@ -58,7 +58,10 @@ if delivery_movement is not None and (\n
and delivery_movement.getPortalType() not in movement.getPortalTaxMovementTypeList()):\n
return False\n
\n
return True\n
if movement.getSimulationState() in movement.getCausalityValue(portal_type=\'Business Link\').getCompletedStateList():\n
return True\n
\n
return False\n
</string> </value>
</item>
<item>
......
......@@ -56,6 +56,13 @@
receivable_account_type_list = (\'asset/receivable\',)\n
payable_account_type_list = (\'liability/payable\',)\n
\n
if movement.getQuantity() == 0:\n
# do not create empty payment movements\n
return False\n
\n
if movement.getSimulationState() not in movement.getCausalityValue(portal_type=\'Business Link\').getCompletedStateList():\n
return False\n
\n
for account in (movement.getSourceValue(portal_type=\'Account\'),\n
movement.getDestinationValue(portal_type=\'Account\')):\n
if account is not None:\n
......
......@@ -51,17 +51,18 @@
<item>
<key> <string>_body</string> </key>
<value> <string>software_instance = state_change[\'object\']\n
portal = context.getPortalObject()\n
portal = software_instance.getPortalObject()\n
\n
root_software_instance = software_instance\n
while (software_instance is not None):\n
root_software_instance = software_instance\n
software_instance = software_instance.getPredecessorRelatedValue()\n
root_hosting_subscription = portal.portal_catalog.getResultValue(uid=software_instance.SoftwareInstance_getRootHostingSubscriptionUid())\n
tag = \'%s_%s_inProgress\' % (software_instance.getUid(), root_hosting_subscription.getTitle())\n
root_software_instance = root_hosting_subscription.HostingSubscription_requestRootSoftwareInstance(tag)\n
\n
for software_instance in context.portal_catalog(\n
portal_type=\'Software Instance\',\n
root_uid=root_software_instance.getUid()):\n
software_instance = software_instance.getObject()\n
# Use iterative algorithm instead of recursive approach in order to avoid\n
# complexity as much as possible.\n
flat_tree = [root_software_instance]\n
while flat_tree:\n
software_instance = flat_tree.pop(0)\n
flat_tree.extend(software_instance.getPredecessorValueList())\n
try:\n
software_instance.Item_getInstancePackingListLine(service_relative_url=portal.portal_preferences.getPreferredInstanceCleanupResource())\n
except ValueError:\n
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string># Get the software_instance\n
software_instance = state_change[\'object\']\n
\n
# Change the title\n
software_instance.edit(title=state_change.kwargs[\'new_name\'])\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_rename</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Rename software instance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -64,6 +64,8 @@ is_slave = kwargs.get("shared", False)\n
sla_xml = kwargs["sla_xml"]\n
state = kwargs["state"]\n
\n
from DateTime import DateTime\n
\n
if is_slave == True:\n
software_instance_portal_type = "Slave Instance"\n
else:\n
......@@ -72,20 +74,23 @@ else:\n
# graph allows to "simulate" tree change after requested operation\n
graph = {}\n
# Get root software instance and create initial graph\n
predecessor_software_instance = software_instance\n
while (predecessor_software_instance is not None):\n
predecessor_software_instance_pred_uid_list = predecessor_software_instance.getPredecessorUidList()\n
graph[predecessor_software_instance.getUid()] = predecessor_software_instance_pred_uid_list\n
# as this walking is not fetching all instances fill predecessors into graph, in order to have\n
# "nearly" complete representation\n
for uid in predecessor_software_instance_pred_uid_list:\n
if uid not in graph:\n
graph[uid] = []\n
root_software_instance = predecessor_software_instance\n
predecessor_software_instance = predecessor_software_instance.getPredecessorRelatedValue(\n
portal_type="Software Instance")\n
root_hosting_subscription = software_instance.portal_catalog.getResultValue(\n
uid=software_instance.SoftwareInstance_getRootHostingSubscriptionUid(),\n
)\n
\n
tag = "%s_%s_inProgress" % (root_software_instance.getUid(),\n
predecessor_list = root_hosting_subscription.getPredecessorValueList()\n
graph[root_hosting_subscription.getUid()] = [predecessor.getUid() for predecessor in predecessor_list]\n
while True:\n
try:\n
current_software_instance = predecessor_list.pop(0)\n
except IndexError:\n
break\n
current_software_instance_predecessor_list = current_software_instance.getPredecessorValueList() or []\n
graph[current_software_instance.getUid()] = [predecessor.getUid()\n
for predecessor in current_software_instance_predecessor_list]\n
predecessor_list.extend(current_software_instance_predecessor_list)\n
\n
tag = "%s_%s_inProgress" % (root_hosting_subscription.getUid(),\n
requested_partition_reference)\n
\n
# Check if it already exists\n
......@@ -94,20 +99,22 @@ request_software_instance = software_instance.portal_catalog.getResultValue(\n
# XXX: User based property is used in non manual operation\n
# XXX-2: Do we really need to use root_uid?\n
title=requested_partition_reference,\n
root_uid=root_software_instance.getUid(),\n
root_uid=root_hosting_subscription.getUid(),\n
)\n
\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
# The software instance is already under creation but can not be fetched from catalog\n
# As it is not possible to fetch informations, it is better to raise an error\n
raise NotImplementedError(tag)\n
\n
root_software_instance = root_hosting_subscription.HostingSubscription_requestRootSoftwareInstance(tag)\n
\n
# above query does not find root software instance, but as this case is easy\n
# to find, just check if such request does not come and raise\n
if root_software_instance.getTitle() == requested_partition_reference:\n
raise ValueError(\'It is disallowed to request root software instance\')\n
\n
if (request_software_instance is None):\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
# The software instance is already under creation but can not be fetched from catalog\n
# As it is not possible to fetch informations, it is better to raise an error\n
raise NotImplementedError(tag)\n
else:\n
# First time that the software instance is requested\n
# Create a new one\n
module = software_instance.getDefaultModule(portal_type="Software Instance")\n
......@@ -121,11 +128,6 @@ if (request_software_instance is None):\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n
request_software_instance.portal_workflow.doActionFor(request_software_instance, \'validate_action\')\n
if state == "started":\n
request_software_instance.startRequested()\n
if state == "stopped":\n
request_software_instance.stopRequested()\n
setup_service_relative_url = portal.portal_preferences.getPreferredInstanceSetupResource()\n
packing_list_line = software_instance.getAggregateRelatedValue(portal_type="Sale Packing List Line")\n
subscription = packing_list_line.getAggregateValue(portal_type="Hosting Subscription")\n
software_release_document = context.portal_catalog.getResultValue(\n
......@@ -147,6 +149,7 @@ if (request_software_instance is None):\n
activate_kw={\'tag\': tag},\n
)\n
\n
setup_service_relative_url = portal.portal_preferences.getPreferredInstanceSetupResource()\n
sale_order.setSpecialise(trade_condition, portal_type="Sale Trade Condition")\n
sale_order_line = sale_order.newContent(\n
portal_type="Sale Order Line",\n
......@@ -168,21 +171,30 @@ else:\n
# Update the predecessor category of the original caller\n
predecessor_software_instance = request_software_instance.getPredecessorRelatedValue(\n
portal_type="Software Instance")\n
\n
predecessor = None\n
if predecessor_software_instance is None:\n
raise ValueError(\'Requested Software Instance %s should have a predecessor\' % request_software_instance.getRelativeUrl())\n
sale_packing_list_line = context.SoftwareInstance_getInstanceSetupPackingListLine(state_change)\n
hosting_subscription = sale_packing_list_line.getAggregateValue(portal_type=\'Hosting Subscription\')\n
if request_software_instance.getPredecessorRelatedValue(portal_type="Hosting Subscription") != hosting_subscription:\n
raise ValueError(\'Requested Software Instance %s should have a predecessor from same tree\' % request_software_instance.getRelativeUrl())\n
else:\n
predecessor = hosting_subscription\n
else:\n
predecessor_uid_list = predecessor_software_instance.getPredecessorUidList()\n
predecessor = predecessor_software_instance\n
\n
predecessor_uid_list = predecessor.getPredecessorUidList()\n
predecessor_uid_list.remove(request_software_instance.getUid())\n
predecessor_software_instance.edit(\n
predecessor.edit(\n
predecessor_uid_list=predecessor_uid_list,\n
activate_kw={\'tag\': tag},)\n
graph[predecessor_software_instance.getUid()] = predecessor_uid_list\n
graph[predecessor.getUid()] = predecessor_uid_list\n
\n
if state == \'started\':\n
request_software_instance.startRequested()\n
request_software_instance.activate(after_tag=tag).requestStartComputerPartition()\n
elif state == \'stopped\':\n
request_software_instance.stopRequested() \n
request_software_instance.stopRequested()\n
request_software_instance.activate(after_tag=tag).requestStopComputerPartition()\n
else:\n
raise ValueError(\'State %r is not supported\' % state)\n
......@@ -195,7 +207,7 @@ if not request_software_instance.getUid() in graph:\n
graph[software_instance.getUid()] = software_instance.getPredecessorUidList() + [request_software_instance.getUid()]\n
\n
# check if all elements are still connected and if there is no cycle\n
software_instance.checkConnected(graph, root_software_instance.getUid())\n
software_instance.checkConnected(graph, root_hosting_subscription.getUid())\n
software_instance.checkNotCyclic(graph)\n
\n
software_instance.edit(\n
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>try:\n
packing_list_line = context.SoftwareInstance_getInstanceHostingPackingListLine(state_change)\n
except ValueError:\n
pass\n
else:\n
packing_list = packing_list_line.getParentValue()\n
if packing_list.getPortalObject().portal_workflow.isTransitionPossible(packing_list, \'stop\'):\n
packing_list.stop()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_requestStopIfNeeded</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -52,11 +52,15 @@
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
from Products.DCWorkflow.DCWorkflow import ValidationFailed\n
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery\n
\n
software_instance = state_change[\'object\']\n
portal = software_instance.getPortalObject()\n
\n
if software_instance.SoftwareInstance_getStatus() == \'Destroyed\':\n
raise ValidationFailed\n
\n
# avoid conflicting with "in progress" update tasks\n
tag_list = ["%s_destroyInProgress" % software_instance.getUid(), "%s_startInProgress" % software_instance.getUid()]\n
for tag in tag_list:\n
......@@ -73,7 +77,11 @@ service_uid_state_mapping = {\n
setup_resource_uid: [\'stopped\'],\n
hosting_resource_uid: [\'started\', \'delivered\']\n
}\n
previous_packing_list_line = context.SoftwareInstance_getInstancePackingListLine(state_change)\n
try:\n
previous_packing_list_line = context.SoftwareInstance_getInstancePackingListLine(state_change)\n
except ValueError:\n
# no packing list yet, no need to update\n
return\n
\n
if previous_packing_list_line.getResourceUid() == hosting_resource_uid:\n
if previous_packing_list_line.getSimulationState() not in service_uid_state_mapping[hosting_resource_uid]:\n
......
......@@ -24,9 +24,10 @@
<tuple>
<string>destroy_computer_partition</string>
<string>destroy_requested</string>
<string>lock</string>
<string>rename</string>
<string>report_computer_partition_bang</string>
<string>report_computer_partition_error</string>
<string>request_computer_partition</string>
<string>request_destroy_computer_partition</string>
<string>request_destroy_computer_partition_action</string>
<string>request_software_instance</string>
......
......@@ -24,9 +24,9 @@
<tuple>
<string>destroy_computer_partition</string>
<string>destroy_requested</string>
<string>lock</string>
<string>report_computer_partition_bang</string>
<string>report_computer_partition_error</string>
<string>request_computer_partition</string>
<string>request_destroy_computer_partition</string>
<string>request_destroy_computer_partition_action</string>
<string>request_software_instance</string>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StateDefinition" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>locked</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>transitions</string> </key>
<value>
<tuple>
<string>destroy_computer_partition</string>
<string>destroy_requested</string>
<string>request_destroy_computer_partition</string>
<string>request_destroy_computer_partition_action</string>
<string>stop_computer_partition</string>
<string>unlock</string>
</tuple>
</value>
</item>
<item>
<key> <string>type_list</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -24,9 +24,10 @@
<tuple>
<string>destroy_computer_partition</string>
<string>destroy_requested</string>
<string>lock</string>
<string>rename</string>
<string>report_computer_partition_bang</string>
<string>report_computer_partition_error</string>
<string>request_computer_partition</string>
<string>request_destroy_computer_partition</string>
<string>request_destroy_computer_partition_action</string>
<string>request_software_instance</string>
......
......@@ -24,9 +24,10 @@
<tuple>
<string>destroy_computer_partition</string>
<string>destroy_requested</string>
<string>lock</string>
<string>rename</string>
<string>report_computer_partition_bang</string>
<string>report_computer_partition_error</string>
<string>request_computer_partition</string>
<string>request_destroy_computer_partition</string>
<string>request_destroy_computer_partition_action</string>
<string>request_software_instance</string>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>lock</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>locked</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string>SoftwareInstance_requestStopIfNeeded</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></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="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string>SoftwareInstance_rename</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rename</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Rename Software Instance</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="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>unlock</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>draft</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
352
\ No newline at end of file
370
\ No newline at end of file
......@@ -3,6 +3,7 @@ Slave Instance | Reference
Slave Instance | SlaveInstanceContraint
Slave Instance | SoftwareInstance
Slave Instance | TextDocument
Slave Instance | VariationRange
Software Instance | Reference
Software Instance | SoftwareInstance
Software Instance | SoftwareInstanceConstraint
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/asset/cash/bank</string>
<string>financial_section/asset/current_assets/cash</string>
<string>gap/fr/pcg/5/51/512</string>
</tuple>
</value>
</item>
......@@ -310,6 +311,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072164.63</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/equity</string>
<string>financial_section/equity/share_capital</string>
<string>gap/fr/pcg/1/10/101</string>
</tuple>
</value>
</item>
......@@ -310,6 +311,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072157.04</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/liability/payable/collected_vat</string>
<string>financial_section/liability/current/other</string>
<string>gap/fr/pcg/4/44/445/4457/44571</string>
</tuple>
</value>
</item>
......@@ -310,6 +311,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072148.22</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/asset</string>
<string>financial_section/asset/non_current/fixed_assets</string>
<string>gap/fr/pcg/2/21</string>
</tuple>
</value>
</item>
......@@ -310,6 +311,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072132.24</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/asset</string>
<string>financial_section/asset/current_assets/stock</string>
<string>gap/fr/pcg/3</string>
</tuple>
</value>
</item>
......@@ -355,6 +356,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072119.36</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/liability/payable</string>
<string>financial_section/liability/current/payable</string>
<string>gap/fr/pcg/4/40/401</string>
</tuple>
</value>
</item>
......@@ -355,6 +356,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072105.29</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/equity</string>
<string>financial_section/equity/net_profit</string>
<string>gap/fr/pcg/1/12</string>
</tuple>
</value>
</item>
......@@ -400,6 +401,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072093.86</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/expense</string>
<string>financial_section/expense/op_expense/cogs</string>
<string>gap/fr/pcg/6</string>
</tuple>
</value>
</item>
......@@ -355,6 +356,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072085.3</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/asset/receivable</string>
<string>financial_section/asset/current_assets/receivables</string>
<string>gap/fr/pcg/4/41/411</string>
</tuple>
</value>
</item>
......@@ -400,6 +401,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072074.09</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/asset/receivable/refundable_vat</string>
<string>financial_section/asset/current_assets/receivables</string>
<string>gap/fr/pcg/4/44/445/4456/44566</string>
</tuple>
</value>
</item>
......@@ -490,6 +491,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072058.6</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -60,6 +60,7 @@
<tuple>
<string>account_type/income</string>
<string>financial_section/income/revenue</string>
<string>gap/fr/pcg/7</string>
</tuple>
</value>
</item>
......@@ -355,6 +356,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.52330.26845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="4.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327072021.77</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
......@@ -194,7 +194,9 @@
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
<tuple>
<string>SimulationMovement_testDeliverySimulationRule</string>
</tuple>
</value>
</item>
<item>
......@@ -583,6 +585,51 @@
</value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58652.61044.15803</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="8.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1327588714.75</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
......
82
\ No newline at end of file
84
\ No newline at end of file
......@@ -630,20 +630,16 @@ Vifib Cloud is a distributed cloud around the world.<br />Just fill the email fi
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>hosting</string> </value>
<key> <string>format</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>last_id</string> </key>
<value> <string>5</string> </value>
<key> <string>id</string> </key>
<value> <string>hosting</string> </value>
</item>
<item>
<key> <string>layout_additional_css</string> </key>
<value>
<tuple>
<string>/vifib_hosting_style/hosting-design.css</string>
</tuple>
</value>
<value> <string>/vifib_hosting_style/hosting-design.css</string> </value>
</item>
<item>
<key> <string>layout_additional_js</string> </key>
......@@ -781,6 +777,12 @@ Vifib Cloud is a distributed cloud around the world.<br />Just fill the email fi
<key> <string>visible</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAk=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
......@@ -852,4 +854,85 @@ Vifib Cloud is a distributed cloud around the world.<br />Just fill the email fi
<none/>
</pickle>
</record>
<record id="9" aka="AAAAAAAAAAk=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAo=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="10" aka="AAAAAAAAAAo=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>superluke</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>915.58653.2524.62566</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</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>1327055846.43</float>
<string>GMT+1</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
81
\ No newline at end of file
82
\ No newline at end of file
<local_roles_item>
<local_roles>
<role id='ERP5TypeTestCase'>
<item>Owner</item>
</role>
<role id='test_computer'>
<item>Assignor</item>
</role>
</local_roles>
</local_roles_item>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Email" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>coordinate_text</string> </key>
<value> <string>test_hr_admin@example.org</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>default_email</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Email</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>url_string</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Trade Condition" module="erp5.portal_type"/>
<global name="Career" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -12,22 +12,7 @@
<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>
......@@ -39,8 +24,6 @@
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -52,9 +35,7 @@
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -64,22 +45,17 @@
<key> <string>categories</string> </key>
<value>
<tuple>
<string>specialise/sale_trade_condition_module/vifib_trade_condition</string>
<string>destination_section/organisation_module/vifib_client_A</string>
<string>role/client</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>10</string> </value>
<value> <string>default_career</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Trade Condition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ViFiB Custom Conditions</string> </value>
<value> <string>Career</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Email" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>coordinate_text</string> </key>
<value> <string>test_updated_vifib_user@example.org</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>default_email</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Email</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>url_string</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Email" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>coordinate_text</string> </key>
<value> <string>test_vifib_member@example.org</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>default_email</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Email</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>url_string</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -23,6 +23,9 @@
<portal_type id="Purchase Packing List Line">
<item>VifibPurchasePackingListLineConstraint</item>
</portal_type>
<portal_type id="Sale Order">
<item>VifibSaleOrderCosntraint</item>
</portal_type>
<portal_type id="Software Product">
<item>VifibSoftwareProductConstraint</item>
</portal_type>
......
......@@ -9,7 +9,7 @@
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromAggregateMovementItemByPerson</property>
<multi_property id='base_category'>destination_section</multi_property>
</role>
<role id='Auditor'>
<role id='Assignor'>
<property id='title'>Related Software Instance Group</property>
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromSelf</property>
<multi_property id='base_category'>aggregate</multi_property>
......
......@@ -6,7 +6,7 @@
</role>
<role id='Assignee'>
<property id='title'>Customer of the Instance</property>
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromAggregateMovementItemByPerson</property>
<property id='base_category_script'>SoftwareType_getSecurityCategoryFromAggregateMovementItemByPerson</property>
<multi_property id='base_category'>destination_section</multi_property>
</role>
<role id='Assignee'>
......@@ -17,7 +17,7 @@
</role>
<role id='Assignor'>
<property id='title'>Slave Instance related by Hosting Subscription</property>
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromAggregateMovementItemByHostingSubscription</property>
<property id='base_category_script'>SoftwareType_getSecurityCategoryFromAggregateMovementItemByHostingSubscription</property>
<multi_property id='base_category'>aggregate</multi_property>
</role>
<role id='Assignor'>
......
......@@ -6,7 +6,7 @@
</role>
<role id='Assignee'>
<property id='title'>Customer of the Instance</property>
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromAggregateMovementItemByPerson</property>
<property id='base_category_script'>SoftwareType_getSecurityCategoryFromAggregateMovementItemByPerson</property>
<multi_property id='base_category'>destination_section</multi_property>
</role>
<role id='Assignee'>
......@@ -17,7 +17,7 @@
</role>
<role id='Assignor'>
<property id='title'>Software Instance related by Hosting Subscription</property>
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromAggregateMovementItemByHostingSubscription</property>
<property id='base_category_script'>SoftwareType_getSecurityCategoryFromAggregateMovementItemByHostingSubscription</property>
<multi_property id='base_category'>aggregate</multi_property>
</role>
</type_roles>
\ No newline at end of file
......@@ -70,7 +70,7 @@
</item>
<item>
<key> <string>test_tales_expression</string> </key>
<value> <string>python: object.getAggregateValue(portal_type=\'Software Release\') is not None</string> </value>
<value> <string>python: object.getAggregateValue(portal_type=\'Software Release\') is not None and object.getSimulationState() not in (\'stopped\', \'delivered\')</string> </value>
</item>
<item>
<key> <string>workflow_state_list</string> </key>
......
......@@ -2,56 +2,10 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Computer" module="erp5.portal_type"/>
<global name="Property Sheet" 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>Manager</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>Manager</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>Manager</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>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_count</string> </key>
<value>
......@@ -70,10 +24,6 @@
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>test_computer</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
......@@ -82,15 +32,11 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test_computer</string> </value>
</item>
<item>
<key> <string>last_id</string> </key>
<value> <string>1</string> </value>
<value> <string>VifibSaleOrderCosntraint</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Computer</string> </value>
<value> <string>Property Sheet</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Content Existence 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_portal_type</string> </key>
<value> <string>python: (\'Sale Order Line\',)</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>lines_constraint</string> </value>
</item>
<item>
<key> <string>message_no_subobject</string> </key>
<value> <string>Purchase Packing List Line is not defined</string> </value>
</item>
<item>
<key> <string>message_no_subobject_portal_type</string> </key>
<value> <string>Purchase Packing List Line is not defined</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Content Existence Constraint</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/>
</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>
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Open Sale Order Line" module="erp5.portal_type"/>
<global name="String Attribute Match Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -13,104 +13,61 @@
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<key> <string>_local_properties</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<tuple>
<dictionary>
<item>
<key> <string>base_price</string> </key>
<value> <float>40.0</float> </value>
<key> <string>id</string> </key>
<value> <string>message_property_not_set</string> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>resource/service_module/vm_monthly_hosting</string>
<string>aggregate/subscription_item_module/2</string>
<string>aggregate/subscription_item_module/3</string>
<string>aggregate/subscription_item_module/4</string>
<string>aggregate/subscription_item_module/5</string>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<key> <string>_range_criterion</string> </key>
<value>
<none/>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>1</string> </value>
</item>
<item>
<key> <string>mapped_value_property_list</string> </key>
<key> <string>constraint_property</string> </key>
<value>
<tuple>
<string>base_price</string>
<string>additional_price</string>
<string>discount_ratio</string>
<string>exclusive_discount_ratio</string>
<string>surcharge_ratio</string>
<string>variable_additional_price</string>
<string>non_discountable_additional_price</string>
<string>priced_quantity</string>
<string>base_unit_price</string>
<string>reference</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Open Sale Order Line</string> </value>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>price</string> </key>
<value> <float>0.0</float> </value>
<key> <string>id</string> </key>
<value> <string>reference_not_empty_constraint</string> </value>
</item>
<item>
<key> <string>priced_quantity</string> </key>
<value> <float>20.0</float> </value>
<key> <string>message_attribute_match</string> </key>
<value> <string>Reference must be defined</string> </value>
</item>
<item>
<key> <string>quantity</string> </key>
<value> <float>50.0</float> </value>
<key> <string>message_no_such_property</string> </key>
<value> <string>Reference must be defined</string> </value>
</item>
<item>
<key> <string>start_date_range_max</string> </key>
<value>
<object>
<klass>
<global id="1.1" name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1277935200.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
<key> <string>message_property_not_set</string> </key>
<value> <string>Reference must be defined</string> </value>
</item>
<item>
<key> <string>start_date_range_min</string> </key>
<value>
<object>
<klass> <reference id="1.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1272664800.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
<key> <string>portal_type</string> </key>
<value> <string>String Attribute Match Constraint</string> </value>
</item>
</dictionary>
</pickle>
......@@ -139,41 +96,7 @@
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>start_date</string> </key>
<value>
<tuple>
<object>
<klass>
<global id="3.1" name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1272664800.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
<object>
<klass> <reference id="3.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1277935200.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</tuple>
</value>
</item>
</dictionary>
<dictionary/>
</value>
</item>
</dictionary>
......
......@@ -2,24 +2,33 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Purchase Packing List Line" module="erp5.portal_type"/>
<global name="Category Membership Arity Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<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>resource/service_module/vifib_software_setup</string>
<string>quantity_unit/unit/piece</string>
<string>aggregate/software_release_module/test_software_release</string>
<string>aggregate/computer_module/test_computer</string>
<string>specialise</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>1</string> </value>
<key> <string>constraint_portal_type</string> </key>
<value> <string>python: (\'Sale Trade Condition\',)</string> </value>
</item>
<item>
<key> <string>description</string> </key>
......@@ -29,21 +38,23 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>1</string> </value>
<value> <string>sale_order_specialise_sale_trade_condition_constraint_constraint</string> </value>
</item>
<item>
<key> <string>index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
<key> <string>max_arity</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<key> <string>min_arity</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Purchase Packing List Line</string> </value>
<value> <string>Category Membership Arity Constraint</string> </value>
</item>
<item>
<key> <string>use_acquisition</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
......@@ -57,14 +68,7 @@
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>movement</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
<dictionary/>
</value>
</item>
</dictionary>
......
......@@ -2,68 +2,47 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Computer Partition" module="erp5.portal_type"/>
<global name="Property Existence Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<key> <string>_identity_criterion</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>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>message_property_not_set</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<key> <string>_range_criterion</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<key> <string>constraint_property</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>
<string>start_date</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>test_computer_partition</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
......@@ -72,21 +51,49 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test_computer_partition</string> </value>
<value> <string>start_date_existence_constraint</string> </value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>Property start_date must be defined</string> </value>
</item>
<item>
<key> <string>message_property_not_set</string> </key>
<value> <string>Property start_date must be defined</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Computer Partition</string> </value>
<value> <string>Property Existence Constraint</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>quantity</string> </key>
<key> <string>data</string> </key>
<value>
<none/>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>title</string> </key>
<value> <string>1</string> </value>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string># XXX For now, this script requires proxy manager\n
\n
# base_category_list : list of category values we need to retrieve\n
# user_name : string obtained from getSecurityManager().getUser().getUserName() [NuxUserGroup]\n
# or from getSecurityManager().getUser().getId() [PluggableAuthService with ERP5GroupManager]\n
# object : object which we want to assign roles to.\n
# portal_type : portal type of object\n
\n
# must always return a list of dicts\n
\n
category_list = []\n
\n
if obj is None:\n
return []\n
\n
item_portal_type = "Hosting Subscription"\n
movement_portal_type = "Sale Order Line"\n
\n
portal = obj.getPortalObject()\n
\n
movement = portal.portal_catalog.getResultValue(\n
portal_type=movement_portal_type,\n
strict_aggregate_uid=obj.getUid(),\n
simulation_state=(\'confirmed\', \'ordered\'),\n
)\n
\n
if movement is not None:\n
item = movement.getAggregateValue(portal_type=item_portal_type)\n
if item is not None:\n
category_list.append({"aggregate": [item.getRelativeUrl()]})\n
\n
return category_list\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>base_category_list, user_name, obj, portal_type</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareType_getSecurityCategoryFromAggregateMovementItemByHostingSubscription</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
# XXX For now, this script requires proxy manager\n
\n
# base_category_list : list of category values we need to retrieve\n
# user_name : string obtained from getSecurityManager().getUser().getUserName() [NuxUserGroup]\n
# or from getSecurityManager().getUser().getId() [PluggableAuthService with ERP5GroupManager]\n
# object : object which we want to assign roles to.\n
# portal_type : portal type of object\n
\n
# must always return a list of dicts\n
\n
category_list = []\n
\n
if obj is None:\n
return []\n
\n
movement_portal_type = "Sale Order Line"\n
\n
portal = obj.getPortalObject()\n
\n
security_dict = {}\n
\n
parent_url_list = []\n
for movement in portal.portal_catalog(\n
portal_type=movement_portal_type,\n
strict_aggregate_uid=obj.getUid(),\n
simulation_state=(\'ordered\', \'confirmed\'),\n
):\n
item = movement.getDestinationSectionValue(portal_type="Person")\n
if item is not None:\n
parent_url_list.append(item.getRelativeUrl())\n
\n
if len(parent_url_list) > 0:\n
parent_url_list.sort()\n
category_list.append({"destination_section": parent_url_list})\n
return category_list\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>base_category_list, user_name, obj, portal_type</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareType_getSecurityCategoryFromAggregateMovementItemByPerson</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -79,14 +79,16 @@ class TestVifibModuleSecurity(testVifibMixin):
portal = self.getPortal()
self.login(user_name='test_vifib_member')
error_list = []
for module_id in portal.objectIds(spec=('ERP5 Folder',)):
if module_id in self.used_module_id_list:
try:
portal.restrictedTraverse(module_id)
except Unauthorized:
raise AssertionError, "User can not access '%s'" % module_id
error_list.append("User can not access '%s'" % module_id)
else:
try:
self.assertRaises(Unauthorized, portal.restrictedTraverse, module_id)
except AssertionError:
raise AssertionError, "User can access '%s'" % module_id
error_list.append("User can access '%s'" % module_id)
self.assertEqual([], error_list, '\n'.join(error_list))
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>SaleOrder_updateAggregateLocalRoles</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SaleOrder_order</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>order</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<list>
<string>Sale Order</string>
</list>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -54,7 +54,7 @@
This script updates all local roles on the object. It requires Assignor\n
proxy role since it may be called by owner in draft state.\n
"""\n
portal_type_list = ["Software Instance", "Slave Instance", "Hosting Subscription", "Computer Partition"]\n
portal_type_list = ["Hosting Subscription", "Computer Partition", "Software Instance", "Slave Instance"]\n
for movement in state_change[\'object\'].getMovementList():\n
tag = "softinssec_%s" % movement.getUid()\n
movement.activate(activity=\'SQLQueue\', tag=tag, after_path_and_method_id=(movement.getPath(),\n
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>"""\n
This script updates all local roles on the object. It requires Assignor\n
proxy role since it may be called by owner in draft state.\n
"""\n
portal_type_list = ["Slave Instance", "Software Instance", "Hosting Subscription"]\n
for movement in state_change[\'object\'].getMovementList():\n
tag = "softinssec_%s" % movement.getUid()\n
movement.activate(activity=\'SQLQueue\', tag=tag, after_path_and_method_id=(movement.getPath(),\n
(\'immediateReindexObject\', \'recursiveImmediateReindexObject\'))).serialize()\n
movement.activate(activity=\'SQLQueue\', tag=tag, after_path_and_method_id=(movement.getParentValue().getPath(),\n
(\'immediateReindexObject\', \'recursiveImmediateReindexObject\'))).serialize()\n
for software_instance in movement.getAggregateValueList(portal_type=portal_type_list):\n
software_instance.activate(after_tag=tag).updateLocalRolesOnSecurityGroups()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SaleOrder_updateAggregateLocalRoles</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
327
\ No newline at end of file
335
\ No newline at end of file
......@@ -17,7 +17,6 @@ business_process_module/vifib_sale_business_process
campaign_module
component_module
computer_module
computer_module/test_computer
credential_update_module
currency_module
currency_module/EUR
......
......@@ -17,7 +17,6 @@ business_process_module/vifib_sale_business_process
campaign_module
component_module
computer_module
computer_module/test_computer
credential_update_module
currency_module
currency_module/EUR
......
......@@ -3,6 +3,7 @@ person_module/test_hr_admin/**
person_module/test_sale_agent
person_module/test_sale_agent/**
person_module/test_updated_vifib_user
person_module/test_updated_vifib_user/**
person_module/test_vifib_admin
person_module/test_vifib_admin/**
person_module/test_vifib_customer
......
......@@ -6,5 +6,6 @@ Internal Packing List | VifibInternalPackingListConstraint
Person | VifibPersonConstraint
Purchase Packing List Line | VifibPurchasePackingListLineConstraint
Purchase Packing List | VifibPurchasePackingListConstraint
Sale Order | VifibSaleOrderCosntraint
Software Product | VifibSoftwareProductConstraint
Software Release | VifibSoftwareReleaseConstraint
\ No newline at end of file
......@@ -8,3 +8,4 @@ VifibInternalPackingListLineConstraint
VifibPurchasePackingListLineConstraint
VifibPurchasePackingListConstraint
VifibSoftwareReleaseConstraint
VifibSaleOrderCosntraint
\ No newline at end of file
......@@ -15,7 +15,7 @@
<item>
<key> <string>arguments_src</string> </key>
<value> <string>uid\r\n
SoftwareInstance_getRootSoftwareInstanceUid</string> </value>
SoftwareInstance_getRootHostingSubscriptionUid</string> </value>
</item>
<item>
<key> <string>cache_time_</string> </key>
......@@ -69,7 +69,7 @@ WHERE\n
<dtml-in prefix="loop" expr="_.range(_.len(uid))">\n
<dtml-call expr="row_list.append([\n
uid[loop_item],\n
SoftwareInstance_getRootSoftwareInstanceUid[loop_item]])">\n
SoftwareInstance_getRootHostingSubscriptionUid[loop_item]])">\n
</dtml-in>\n
\n
<dtml-if "row_list">\n
......
32
\ No newline at end of file
33
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Open Sale Order" 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>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>modification_date</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>date</string> </value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>creation_date</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>date</string> </value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>price_currency</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>source_section/organisation_module/vifib_internet</string>
<string>source/organisation_module/2</string>
<string>destination_section/organisation_module/vifib_client_A</string>
<string>destination/organisation_module/4</string>
<string>specialise/sale_trade_condition_module/vifib_trade_condition</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string>TioLive rents VMS for its clients</string> </value>
</item>
<item>
<key> <string>creation_date</string> </key>
<value>
<object>
<klass>
<global id="1.1" name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1272146400.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>1</string> </value>
</item>
<item>
<key> <string>last_id</string> </key>
<value> <string>1</string> </value>
</item>
<item>
<key> <string>modification_date</string> </key>
<value>
<object>
<klass> <reference id="1.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1273096800.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Open Sale Order</string> </value>
</item>
<item>
<key> <string>price_currency</string> </key>
<value> <string>currency_module/1</string> </value>
</item>
<item>
<key> <string>start_date_range_max</string> </key>
<value>
<object>
<klass> <reference id="1.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1304200800.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>start_date_range_min</string> </key>
<value>
<object>
<klass> <reference id="1.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1272664800.0</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>TioLive VM Order</string> </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="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<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="6" aka="AAAAAAAAAAY=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<base_category_list>
<portal_type id="Hosting Subscription">
<item>predecessor</item>
</portal_type>
<portal_type id="Hosting Subscription Module">
<item>business_application</item>
</portal_type>
......
<property_sheet_list>
<portal_type id="Hosting Subscription">
<item>HostingSubscription</item>
<item>SoftwareInstance</item>
<item>TextDocument</item>
<item>VariationRange</item>
</portal_type>
</property_sheet_list>
\ No newline at end of file
......@@ -2,61 +2,10 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Purchase Packing List" module="erp5.portal_type"/>
<global name="Property Sheet" 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>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</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>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_count</string> </key>
<value>
......@@ -75,16 +24,6 @@
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>PPL-793</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
......@@ -93,19 +32,11 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test_purchase_packing_list</string> </value>
</item>
<item>
<key> <string>last_id</string> </key>
<value> <string>1</string> </value>
<value> <string>HostingSubscription</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Purchase Packing List</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>test_purchase_packing_list</string> </value>
<value> <string>Property Sheet</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/boolean</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>root_slave_property</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>root_software_release_url_property</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>root_state_property</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -95,6 +95,10 @@
<list>
<string>my_title</string>
<string>my_reference</string>
<string>my_predecessor_title_list</string>
<string>my_source_reference</string>
<string>my_text_content</string>
<string>my_sla_xml</string>
</list>
</value>
</item>
......
<?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>editable</string>
<string>portal_type</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_predecessor_title_list</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>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_multi_relation_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value>
<list>
<tuple>
<string>Software Instance</string>
<string>Slave Instance</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Predecessors</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>
<string>editable</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_sla_xml</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>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_text_area_field</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>
<item>
<key> <string>title</string> </key>
<value> <string>Root SLA XML</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>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_source_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>
<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_read_only_reference</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>
<item>
<key> <string>title</string> </key>
<value> <string>Root Software Type</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>
<string>editable</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_text_content</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>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_text_area_field</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>
<item>
<key> <string>title</string> </key>
<value> <string>Root XML</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -21,15 +21,15 @@
<item>
<key> <string>activate_script_name</string> </key>
<value>
<list>
<string>Delivery_assertCustomTradeConditionAndOpenOrder</string>
</list>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<tuple/>
<list>
<string>Delivery_assertCustomTradeConditionAndOpenOrder</string>
</list>
</value>
</item>
<item>
......@@ -80,6 +80,10 @@
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
......
......@@ -54,6 +54,7 @@
order = state_change[\'object\']\n
portal = order.getPortalObject()\n
\n
vifib_trade_condition = \'sale_trade_condition_module/vifib_trade_condition\'\n
### STEP 1: does this order have a client-specific Trade Condition\n
trade_condition = order.getSpecialiseValue(portal_type="Sale Trade Condition")\n
custom_trade_condition = None\n
......@@ -65,21 +66,25 @@ if trade_condition is not None:\n
if custom_trade_condition is None:\n
# If no trade condition or generic trade condition\n
# try to find existing trade condition\n
trade_condition_list = portal.sale_trade_condition_module.searchFolder(destination_section_uid=order.getDestinationSectionUid(),\n
validation_state="validated")\n
trade_condition_list = portal.portal_catalog(\n
destination_section_relative_url=order.getDestinationSection(),\n
validation_state="validated",\n
specialise_relative_url=vifib_trade_condition,\n
portal_type=\'Sale Trade Condition\')\n
if len(trade_condition_list):\n
custom_trade_condition = trade_condition_list[0].getObject()\n
\n
if custom_trade_condition is None:\n
# nothing found then create a new custom trade condition\n
if trade_condition is None:\n
trade_condition = \'sale_trade_condition_module/vifib_trade_condition\'\n
custom_trade_condition = portal.sale_trade_condition_module.newContent(specialise_value=trade_condition,\n
destination_section_uid=order.getDestinationSectionUid(),\n
title="ViFiB Custom Conditions")\n
custom_trade_condition = portal.sale_trade_condition_module.newContent(specialise=vifib_trade_condition,\n
destination_section=order.getDestinationSection(),\n
title="ViFiB Custom Conditions",\n
portal_type=\'Sale Trade Condition\')\n
\n
if order.getSpecialise() != custom_trade_condition.getRelativeUrl():\n
order.setSpecialiseValue(custom_trade_condition, portal_type="Sale Trade Condition")\n
if custom_trade_condition is None:\n
raise ValueError(\'It was impossible to generate custom trade condition.\')\n
if order.getSpecialise(portal_type="Sale Trade Condition") != custom_trade_condition.getRelativeUrl():\n
order.setSpecialiseValue(custom_trade_condition)\n
\n
if portal.portal_workflow.isTransitionPossible(custom_trade_condition, \'validate\'):\n
custom_trade_condition.validate()\n
......
141
\ No newline at end of file
149
\ No newline at end of file
computer_module/test_computer
computer_module/test_computer/**
open_sale_order_module/1
open_sale_order_module/1/**
organisation_module/vifib_client_A
organisation_module/vifib_client_A/**
organisation_module/vifib_internet
organisation_module/vifib_internet/1
organisation_module/vifib_internet/bank_account
purchase_packing_list_module/test_purchase_packing_list
purchase_packing_list_module/test_purchase_packing_list/**
purchase_trade_condition_module/vifib_purchase_trade_condition
purchase_trade_condition_module/vifib_purchase_trade_condition/**
sale_trade_condition_module/10
sale_trade_condition_module/10/**
sale_trade_condition_module/vifib_trade_condition
sale_trade_condition_module/vifib_trade_condition/**
software_product_module/test_software_product
......
Hosting Subscription Module | business_application
Hosting Subscription | predecessor
\ No newline at end of file
Hosting Subscription | HostingSubscription
Hosting Subscription | SoftwareInstance
Hosting Subscription | TextDocument
Hosting Subscription | VariationRange
\ No newline at end of file
HostingSubscription
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_lockSoftwareInstance</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>vifib_lock_software_instance</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>946684800.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Locks unlocked Software/Slave instances owned by locked person</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_managePersonLock</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>vifib_manage_person_lock</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>946684800.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Manages person locks</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_unlockSoftwareInstance</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>vifib_unlock_software_instance</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>946684800.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Unlocks locked Software/Slave instances owned by unlocked person</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_updateOpenSaleOrderLine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>vifib_update_open_sale_order_line</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>946684800.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Open Sale Order Line update</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/float</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Maximum accepted balance.</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_maximum_balance_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>preference</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: 0.0</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value> <string>Manage properties</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/int</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Maximum accepted days of having any balance.</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_maximum_due_day_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>preference</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: 0</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value> <string>Manage properties</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>portal_catalog = context.getPortalObject().portal_catalog\n
\n
portal_catalog.searchAndActivate(\n
method_id=\'SoftwareInstance_lockForLockedPerson\',\n
portal_type=(\'Software Instance\', \'Slave Instance\'),\n
payment_state=\'!= locked\',\n
activate_kw={\'tag\': tag}\n
)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_lockSoftwareInstance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>portal_catalog = context.getPortalObject().portal_catalog\n
from DateTime import DateTime\n
method_kw = {}\n
method_kw.update(\n
maximum_balance=context.portal_preferences.getPreferredMaximumBalance(),\n
maximum_due_date=(DateTime() - context.portal_preferences.getPreferredMaximumDueDay()).Date(),\n
simulation_state=context.getPortalCurrentInventoryStateList() + context.getPortalTransitInventoryStateList(),\n
ongoing_simulation_state=context.getPortalFutureInventoryStateList() + context.getPortalReservedInventoryStateList(),\n
section_uid=context.restrictedTraverse(\'organisation_module/vifib_internet\').getUid(), \n
)\n
portal_catalog.searchAndActivate(\n
method_id=\'Person_manageLockByBalance\',\n
portal_type=\'Person\',\n
activate_kw={\'tag\': tag},\n
method_kw=method_kw\n
)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_managePersonLock</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>portal_catalog = context.getPortalObject().portal_catalog\n
\n
portal_catalog.searchAndActivate(\n
method_id=\'SoftwareInstance_unlockForUnlockedPerson\',\n
portal_type=(\'Software Instance\', \'Slave Instance\'),\n
payment_state=\'locked\',\n
activate_kw={\'tag\': tag}\n
)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_unlockSoftwareInstance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>stop_date = None\n
if params is not None:\n
stop_date = params.get(\'stop_date\')\n
from DateTime import DateTime\n
from Products.ERP5Type.DateUtils import getClosestDate, addToDate\n
\n
if stop_date is None:\n
# generate expected next month\n
stop_date = addToDate(getClosestDate(target_date=DateTime(), precision=\'month\', before=1), month=2)\n
\n
context.portal_catalog.searchAndActivate(\n
method_id=\'OpenSaleOrderLine_updateStopDate\',\n
activate_kw={\'tag\':tag},\n
method_kw={\'stop_date\': stop_date},\n
portal_type=\'Open Sale Order Line\')\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_updateOpenSaleOrderLine</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
from DateTime import DateTime\n
from Products.ERP5Type.DateUtils import getClosestDate, addToDate\n
\n
portal = context.getPortalObject()\n
cleanup_resource = portal.portal_preferences.getPreferredInstanceCleanupResource()\n
\n
# copy and paste from\n
# portal_workflow/person_slap_interface_workflow/scripts/Person_requestSoftwareInstance\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
# The software instance is already under creation but can not be fetched from catalog\n
# As it is not possible to fetch informations, it is better to raise an error\n
raise NotImplementedError(tag)\n
hosting_subscription = context\n
\n
sale_order_portal_type = "Sale Order"\n
sale_order_line_portal_type = "Sale Order Line"\n
hosting_subscription_portal_type = "Hosting Subscription"\n
if hosting_subscription.isRootSlave():\n
software_instance_portal_type = "Slave Instance"\n
else:\n
software_instance_portal_type = "Software Instance"\n
\n
# Mostly copy and paste from\n
# portal_workflow/person_slap_interface_workflow/scripts/Person_requestSoftwareInstance\n
request_software_instance = hosting_subscription.portal_catalog.getResultValue(\n
portal_type=software_instance_portal_type,\n
title=hosting_subscription.getTitle(),\n
root_uid=hosting_subscription.getUid(),\n
)\n
\n
if person is None:\n
open_sale_order_line = hosting_subscription.portal_catalog.getResultValue(\n
portal_type=\'Open Sale Order Line\', strict_aggregate_uid=hosting_subscription.getUid())\n
open_sale_order = open_sale_order_line.getParentValue()\n
person_relative_url = open_sale_order.getDestinationSection()\n
else:\n
person_relative_url = person.getRelativeUrl()\n
\n
new_one = False\n
if (request_software_instance is None):\n
new_one = True\n
setup_service_relative_url = portal.portal_preferences.getPreferredInstanceSetupResource()\n
request_software_instance = portal.getDefaultModule(portal_type=software_instance_portal_type).newContent(\n
portal_type=software_instance_portal_type,\n
source_reference=hosting_subscription.getSourceReference(),\n
title=hosting_subscription.getTitle(),\n
text_content=hosting_subscription.getTextContent(),\n
sla_xml=hosting_subscription.getSlaXml(),\n
activate_kw={\'tag\': tag},\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n
request_software_instance.portal_workflow.doActionFor(request_software_instance,\n
\'validate_action\')\n
\n
software_release_document = context.portal_catalog.getResultValue(\n
portal_type=\'Software Release\',\n
url_string=hosting_subscription.getRootSoftwareReleaseUrl())\n
\n
sale_order = portal.getDefaultModule(portal_type=sale_order_portal_type).newContent(\n
portal_type=sale_order_portal_type,\n
destination=person_relative_url,\n
destination_section=person_relative_url,\n
destination_decision=person_relative_url,\n
start_date=DateTime(),\n
received_date=DateTime(),\n
# XXX Hardcoded values\n
source="organisation_module/vifib_internet",\n
source_section="organisation_module/vifib_internet",\n
quantity_unit="unit/piece",\n
price_currency="currency_module/EUR",\n
activate_kw={\'tag\': tag},\n
)\n
sale_order_line = sale_order.newContent(\n
portal_type=sale_order_line_portal_type,\n
resource=setup_service_relative_url,\n
quantity=1,\n
price=0,\n
aggregate_value_list=[request_software_instance,\n
hosting_subscription,\n
software_release_document\n
],\n
activate_kw={\'tag\': tag},\n
)\n
#portal.portal_workflow.doActionFor(sale_order, "order_action")\n
# XXX: Do not verify security\n
sale_order.order()\n
\n
if person is not None:\n
# Update Open Order\n
# does this order have a client-specific Open Order\n
open_order = portal.portal_catalog.getResultValue(\n
default_destination_section_uid=person.getUid(),\n
portal_type="Open Sale Order",\n
validation_state="validated")\n
if open_order is None:\n
person_slap_interface_state = person.getSlapState()\n
if person_slap_interface_state == \'open_order_created\':\n
open_order_url = context.portal_workflow.getInfoFor(\n
ob=person, name=\'open_order_url\',\n
wf_id=\'person_slap_interface_workflow\')\n
open_order = portal.restrictedTraverse(open_order_url)\n
else:\n
raise ValueError(\'Person has no open order created\')\n
\n
now = DateTime()\n
start_date = getClosestDate(target_date=now, precision=\'day\', before=1)\n
# 12 months of subscription by default\n
stop_date = addToDate(getClosestDate(target_date=now, precision=\'month\', before=1), month=2)\n
\n
subscription_service_relative_url = portal.portal_preferences.getPreferredInstanceSubscriptionResource()\n
open_order.newContent(\n
portal_type="Open Sale Order Line",\n
title=hosting_subscription.getTitle(),\n
aggregate_value=hosting_subscription,\n
start_date=start_date,\n
stop_date=stop_date,\n
quantity=1,\n
quantity_unit="unit/piece",\n
price=1,\n
price_currency="currency_module/EUR",\n
specialise=sale_order.getSpecialise(portal_type="Sale Trade Condition"),\n
# XXX Hardcoded values\\n\n
resource=subscription_service_relative_url,\n
destination=person_relative_url,\n
destination_section=person_relative_url,\n
source="organisation_module/vifib_internet",\n
source_section="organisation_module/vifib_internet",\n
activate_kw={\'tag\': tag},\n
)\n
\n
hosting_subscription_predecessor_list = hosting_subscription.getPredecessorList()\n
hosting_subscription_predecessor_list.append(request_software_instance.getRelativeUrl())\n
hosting_subscription.edit(predecessor_list=hosting_subscription_predecessor_list)\n
\n
# Find Computer partition\n
# XXX Link subscript to open order\n
else:\n
# Update existing software instance\n
request_software_instance.edit(\n
text_content=hosting_subscription.getTextContent(),\n
source_reference=hosting_subscription.getSourceReference(),\n
sla_xml=hosting_subscription.getSlaXml(),\n
activate_kw={\'tag\': tag},\n
)\n
for predecessor_related in request_software_instance.getPredecessorRelatedValueList():\n
predecessor_list = predecessor_related.getPredecessorList()\n
predecessor_list.remove(request_software_instance.getRelativeUrl())\n
predecessor_related.setPredecessorList(predecessor_list)\n
\n
hosting_subscription_predecessor_list = hosting_subscription.getPredecessorList()\n
hosting_subscription_predecessor_list.append(request_software_instance.getRelativeUrl())\n
hosting_subscription.setPredecessorList(hosting_subscription_predecessor_list)\n
\n
if hosting_subscription.getRootState() == \'started\':\n
request_software_instance.startRequested()\n
if not new_one:\n
request_software_instance.activate(after_tag=tag).requestStartComputerPartition()\n
elif hosting_subscription.getRootState() == \'stopped\':\n
request_software_instance.stopRequested()\n
if not new_one:\n
request_software_instance.activate(after_tag=tag).requestStopComputerPartition()\n
\n
return request_software_instance\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, person=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>HostingSubscription_requestRootSoftwareInstance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
if context.getStopDate() < stop_date:\n
context.setStopDate(stop_date)\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>stop_date</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>OpenSaleOrderLine_updateStopDate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
locked = context.getSlapState() == \'locked\'\n
customer_uid = context.getUid()\n
balance = context.portal_simulation.getInventoryAssetPrice(\n
node_category=\'account_type/asset/receivable\',\n
simulation_state=simulation_state,\n
section_uid=section_uid,\n
mirror_section_uid=customer_uid)\n
\n
if maximum_balance > balance:\n
# customer reached his balance, shall be locked\n
if not locked:\n
context.lock()\n
return\n
\n
# check ongoing payments and check that date if is acceptable, if not lock\n
if context.portal_catalog.countResults(\n
portal_type=\'Payment Transaction\',\n
simulation_state=ongoing_simulation_state,\n
**{\n
\'delivery.destination_section_uid\': customer_uid,\n
\'delivery.start_date\': \'<= %s\' % maximum_due_date\n
})[0][0] > 0:\n
# there are ongoing old payments, shall be locked\n
if not locked:\n
context.lock()\n
else:\n
# there are no ongoing payments and balance is acceptable\n
if locked:\n
context.unlock()\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>maximum_balance, maximum_due_date, simulation_state, section_uid, ongoing_simulation_state</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_manageLockByBalance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>software_instance = context\n
if software_instance.getSlapState() == \'locked\':\n
return\n
if software_instance.SoftwareInstance_getStatus() == \'destroyed\':\n
return\n
\n
try:\n
packing_list_line = software_instance.Item_getInstancePackingListLine()\n
except ValueError:\n
return\n
person = packing_list_line.getDestinationValue()\n
\n
if person.getSlapState() == \'locked\':\n
software_instance.lock()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_lockForLockedPerson</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>software_instance = context\n
if software_instance.getSlapState() != \'locked\':\n
return\n
if software_instance.SoftwareInstance_getStatus() == \'destroyed\':\n
return\n
\n
try:\n
packing_list_line = software_instance.Item_getInstancePackingListLine()\n
except ValueError:\n
return\n
person = packing_list_line.getDestinationValue()\n
\n
if person.getSlapState() != \'locked\':\n
software_instance.unlock()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_unlockForUnlockedPerson</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -100,6 +100,8 @@
<string>my_preferred_instance_update_resource</string>
<string>my_preferred_instance_subscription_resource</string>
<string>my_preferred_payzen_integration_site</string>
<string>my_preferred_maximum_balance</string>
<string>my_preferred_maximum_due_day</string>
</list>
</value>
</item>
......
<?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>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_preferred_maximum_balance</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_float_field</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>
<item>
<key> <string>title</string> </key>
<value> <string>Preferred Maximum Balance</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>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_preferred_maximum_due_day</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_integer_field</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>
<item>
<key> <string>title</string> </key>
<value> <string>Preferred Maximum Due Day</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -34,7 +34,7 @@
</item>
<item>
<key> <string>initial_state</string> </key>
<value> <string>draft</string> </value>
<value> <string>locked</string> </value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
......
......@@ -52,8 +52,6 @@
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
from DateTime import DateTime\n
from Products.ERP5Type.DateUtils import getClosestDate, addToDate\n
person = state_change[\'object\']\n
portal = person.getPortalObject()\n
# Get required arguments\n
......@@ -66,8 +64,6 @@ sla_xml = kwargs.get("sla_xml") or ""\n
is_slave = kwargs.get("shared", False)\n
state = kwargs.get(\'state\') or \'started\'\n
\n
sale_order_portal_type = "Sale Order"\n
sale_order_line_portal_type = "Sale Order Line"\n
hosting_subscription_portal_type = "Hosting Subscription"\n
\n
if is_slave == True:\n
......@@ -80,142 +76,60 @@ tag = "%s_%s_inProgress" % (person.getUid(), \n
\n
# Check if it already exists\n
cleanup_resource = portal.portal_preferences.getPreferredInstanceCleanupResource()\n
request_software_instance = None\n
for si in portal.portal_catalog(\n
portal_type=software_instance_portal_type,\n
request_hosting_subscription = None\n
for hs in portal.portal_catalog(\n
portal_type=hosting_subscription_portal_type,\n
title=software_title,\n
):\n
si = hs.portal_catalog.getResultValue(title=software_title,\n
root_uid=hs.getUid())\n
try:\n
cleanup_delivery_line = si.Item_getInstancePackingListLine(cleanup_resource)\n
except ValueError:\n
request_software_instance = si\n
request_hosting_subscription = hs\n
break\n
else:\n
if cleanup_delivery_line.getSimulationState() != \'delivered\':\n
request_software_instance = si\n
request_hosting_subscription = hs\n
break\n
\n
if (request_software_instance is None):\n
hosting_subscription_reference = "HOSTSUBS-%s" % context.getPortalObject().portal_ids\\\n
.generateNewId(id_group=\'slap_hosting_subscription_reference\', id_generator=\'uid\')\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
# The software instance is already under creation but can not be fetched from catalog\n
# As it is not possible to fetch informations, it is better to raise an error\n
raise NotImplementedError(tag)\n
else:\n
\n
setup_service_relative_url = portal.portal_preferences.getPreferredInstanceSetupResource()\n
software_instance = portal.getDefaultModule(portal_type=software_instance_portal_type).newContent(\n
portal_type=software_instance_portal_type,\n
source_reference=software_type,\n
title=software_title,\n
text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n
software_instance.portal_workflow.doActionFor(software_instance, \'validate_action\')\n
subscription = portal.getDefaultModule(portal_type=hosting_subscription_portal_type).newContent(\n
if (request_hosting_subscription is None):\n
hosting_subscription_reference = "HOSTSUBS-%s" % context.getPortalObject().portal_ids\\\n
.generateNewId(id_group=\'slap_hosting_subscription_reference\', id_generator=\'uid\')\n
request_hosting_subscription = portal.getDefaultModule(portal_type=hosting_subscription_portal_type).newContent(\n
portal_type=hosting_subscription_portal_type,\n
reference=hosting_subscription_reference,\n
title=software_title,\n
source_reference=software_type,\n
text_content=instance_xml,\n
sla_xml=sla_xml,\n
root_software_release_url=software_release_url_string,\n
root_slave=is_slave,\n
root_state=state,\n
periodicity_hour_list=[0],\n
periodicity_minute_list=[0],\n
periodicity_month_day=[1],\n
activate_kw={\'tag\': tag},\n
)\n
subscription.portal_workflow.doActionFor(subscription, \'validate_action\')\n
if state == \'started\':\n
software_instance.startRequested()\n
elif state == \'stopped\':\n
software_instance.stopRequested()\n
\n
software_release_document = context.portal_catalog.getResultValue(\n
portal_type=\'Software Release\',\n
url_string=software_release_url_string)\n
\n
sale_order = portal.getDefaultModule(portal_type=sale_order_portal_type).newContent(\n
portal_type=sale_order_portal_type,\n
destination_value=person,\n
destination_section_value=person,\n
destination_decision_value=person,\n
start_date=DateTime(),\n
received_date=DateTime(),\n
# XXX Hardcoded values\n
source="organisation_module/vifib_internet",\n
source_section="organisation_module/vifib_internet",\n
quantity_unit="unit/piece",\n
price_currency="currency_module/EUR",\n
activate_kw={\'tag\': tag},\n
)\n
sale_order_line = sale_order.newContent(\n
portal_type=sale_order_line_portal_type,\n
resource=setup_service_relative_url,\n
quantity=1,\n
price=0,\n
aggregate_value_list=[software_instance, subscription, software_release_document],\n
activate_kw={\'tag\': tag},\n
)\n
portal.portal_workflow.doActionFor(sale_order, "order_action")\n
\n
# Update Open Order\n
# does this order have a client-specific Open Order\n
open_order = portal.portal_catalog.getResultValue(\n
default_destination_section_uid=person.getUid(),\n
portal_type="Open Sale Order",\n
validation_state="validated")\n
if open_order is None:\n
person_slap_interface_state = person.getSlapState()\n
if person_slap_interface_state == \'open_order_created\':\n
open_order_url = context.portal_workflow.getInfoFor(\n
ob=person, name=\'open_order_url\',\n
wf_id=\'person_slap_interface_workflow\')\n
open_order = portal.restrictedTraverse(open_order_url)\n
else:\n
raise ValueError(\'Person has no open order created\')\n
\n
now = DateTime()\n
start_date = getClosestDate(target_date=now, precision=\'day\', before=1)\n
# 12 months of subscription by default\n
stop_date = addToDate(getClosestDate(target_date=now, precision=\'month\', before=1), year=1)\n
\n
subscription_service_relative_url = portal.portal_preferences.getPreferredInstanceSubscriptionResource()\n
open_order.newContent(\n
portal_type="Open Sale Order Line",\n
title=software_title,\n
aggregate_value=subscription,\n
start_date=start_date,\n
stop_date=stop_date,\n
quantity=1,\n
quantity_unit="unit/piece",\n
price=1,\n
price_currency="currency_module/EUR",\n
specialise=sale_order.getSpecialise(portal_type="Sale Trade Condition"),\n
# XXX Hardcoded values\\n\n
resource=subscription_service_relative_url,\n
destination_value=person,\n
destination_section_value=person,\n
source="organisation_module/vifib_internet",\n
source_section="organisation_module/vifib_internet",\n
activate_kw={\'tag\': tag},\n
)\n
\n
# Find Computer partition\n
# XXX Link subscript to open order\n
request_hosting_subscription.portal_workflow.doActionFor(request_hosting_subscription,\n
\'validate_action\')\n
else:\n
# Update existing software instance\n
request_software_instance.edit(\n
request_hosting_subscription.edit(\n
text_content=instance_xml,\n
source_reference=software_type,\n
sla_xml=sla_xml,\n
root_software_release_url=software_release_url_string,\n
root_slave=is_slave,\n
root_state=state,\n
activate_kw={\'tag\': tag},\n
)\n
if state == \'started\':\n
request_software_instance.startRequested()\n
request_software_instance.activate(after_tag=tag).requestStartComputerPartition()\n
elif state == \'stopped\':\n
request_software_instance.stopRequested()\n
request_software_instance.activate(after_tag=tag).requestStopComputerPartition()\n
\n
request_hosting_subscription.HostingSubscription_requestRootSoftwareInstance(tag, person=person)\n
]]></string> </value>
......
......@@ -29,6 +29,7 @@
<value>
<tuple>
<string>create_open_order</string>
<string>lock</string>
<string>request_software_instance</string>
</tuple>
</value>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StateDefinition" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>locked</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>transitions</string> </key>
<value>
<tuple>
<string>unlock</string>
</tuple>
</value>
</item>
<item>
<key> <string>type_list</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -28,6 +28,7 @@
<key> <string>transitions</string> </key>
<value>
<tuple>
<string>lock</string>
<string>request_software_instance</string>
</tuple>
</value>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>lock</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>locked</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></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="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>unlock</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>draft</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
506
\ No newline at end of file
524
\ No newline at end of file
portal_alarms/confirm_ordered_sale_order
portal_alarms/stop_planned_sale_invoice_transaction
portal_alarms/vifib_check_consistency
portal_alarms/vifib_lock_software_instance
portal_alarms/vifib_manage_person_lock
portal_alarms/vifib_trigger_build
portal_alarms/vifib_unlock_software_instance
portal_alarms/vifib_update_open_sale_order_line
\ No newline at end of file
......@@ -245,6 +245,17 @@ class SlapTool(BaseTool):
return self._softwareInstanceError(computer_id, computer_partition_id,
error_log)
security.declareProtected(Permissions.AccessContentsInformation,
'softwareInstanceRename')
def softwareInstanceRename(self, new_name, computer_id,
computer_partition_id, slave_reference=None):
"""
Change the title of a Software Instance using Workflow.
"""
return self._softwareInstanceRename(new_name, computer_id,
computer_partition_id,
slave_reference)
security.declareProtected(Permissions.AccessContentsInformation,
'softwareInstanceBang')
def softwareInstanceBang(self, computer_id,
......@@ -632,6 +643,15 @@ class SlapTool(BaseTool):
computer_partition_id).reportComputerPartitionError(
comment=error_log)
@convertToREST
def _softwareInstanceRename(self, new_name, computer_id,
computer_partition_id, slave_reference):
software_instance = self._getSoftwareInstanceForComputerPartition(
computer_id, computer_partition_id,
slave_reference)
return software_instance.rename(new_name=new_name,
comment="Rename %s into %s" % (software_instance.title, new_name))
@convertToREST
def _softwareInstanceBang(self, computer_id,
computer_partition_id, message):
......
......@@ -91,6 +91,8 @@ class testVifibMixin(ERP5TypeTestCase):
'erp5_system_event',
'erp5_secure_payment',
'erp5_payzen_secure_payment',
'erp5_ui_test_core',
'erp5_ui_test',
'vifib_mysql_innodb_catalog',
'vifib_core',
'vifib_base',
......@@ -159,6 +161,14 @@ class testVifibMixin(ERP5TypeTestCase):
Create ERP5 user.
This has to be called only once.
"""
# setup new active process for this test, in order have
# consistency report local for one test
sm = getSecurityManager()
self.login()
try:
self.portal.portal_alarms.vifib_check_consistency.newActiveProcess()
finally:
setSecurityManager(sm)
self.setupPortalCertificateAuthority()
import random
self.portal.portal_caches.erp5_site_global_id = '%s' % random.random()
......@@ -201,6 +211,8 @@ class testVifibMixin(ERP5TypeTestCase):
person = person.getObject()
if isTransitionPossible(person, 'validate'):
person.validate()
if isTransitionPossible(person, 'unlock'):
person.unlock()
for assignment in person.contentValues(portal_type='Assignment'):
if isTransitionPossible(assignment, 'open'):
assignment.open()
......@@ -340,6 +352,18 @@ class testVifibMixin(ERP5TypeTestCase):
finally:
setSecurityManager(sm)
def checkDivergency(self):
# there shall be no divergency
current_skin = self.app.REQUEST.get('portal_skin', 'View')
try:
# Note: Worklists are cached, so in order to have next correct result
# clear cache
self.clearCache()
self.changeSkin('RSS')
self.assertFalse('to Solve' in self.portal.ERP5Site_viewWorklist())
finally:
self.changeSkin(current_skin)
def stepCheckSiteConsistency(self, **kw):
self.portal.portal_alarms.vifib_check_consistency.activeSense()
transaction.commit()
......@@ -347,6 +371,7 @@ class testVifibMixin(ERP5TypeTestCase):
self.assertEqual([], self.portal.portal_alarms.vifib_check_consistency\
.Alarm_getConsistencyCheckReportLineList())
self.assertFalse(self.portal.portal_alarms.vifib_check_consistency.sense())
self.checkDivergency()
def stepTic(self, **kw):
def build():
......@@ -374,13 +399,4 @@ class testVifibMixin(ERP5TypeTestCase):
# tic after build
super(testVifibMixin, self).stepTic(**kw)
# there shall be no divergency
current_skin = self.app.REQUEST.get('portal_skin', 'View')
try:
# Note: Worklists are cached, so in order to have next correct result
# clear cache
self.clearCache()
self.changeSkin('RSS')
self.assertFalse('to Solve' in self.portal.ERP5Site_viewWorklist())
finally:
self.changeSkin(current_skin)
self.checkDivergency()
......@@ -48,7 +48,6 @@ class testVifibSecurityMixin(SecurityTestCase, testVifibMixin):
Mixin class for security unit test of Vifib.
"""
run_all_test = 1
login = PortalTestCase.login
def createManagerAndLogin(self):
"""
......
......@@ -17,8 +17,8 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
causality_relative_url=hosting_subscription.getRelativeUrl(),
sort_on=(('delivery.start_date', 'desc'),)
)
# is whole year covered?
self.assertEqual(12, len(delivery_list))
# are next two months covered?
self.assertEqual(2, len(delivery_list))
# generate the expected time frames
now = DateTime()
......@@ -123,7 +123,7 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
self.assertEqual('planned', setup_invoice_line_list[0]\
.getSimulationState())
# there are 12 confirmed subscription, so no invoice
# there are 2 confirmed subscription, so no invoice
subscription_delivery_line_list = catalog(
portal_type='Sale Packing List Line',
aggregate_relative_url=hosting_subscription_url,
......@@ -131,8 +131,8 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
sort_on=(('movement.start_date', 'desc'),)
)
self.assertEqual(12, len(subscription_delivery_line_list))
self.assertEqual(['confirmed'] * 12, [q.getSimulationState() for \
self.assertEqual(2, len(subscription_delivery_line_list))
self.assertEqual(['confirmed'] * 2, [q.getSimulationState() for \
q in subscription_delivery_line_list])
subscription_invoice_line_list = catalog(portal_type='Invoice Line',
......@@ -212,14 +212,14 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
self.assertEqual('planned', setup_invoice_line_list[0]\
.getSimulationState())
# there are 11 confirmed and 1 stopped subscription, so 1 invoice line
# there are 1 confirmed and 1 stopped subscription, so 1 invoice line
subscription_delivery_line_list = catalog(
portal_type='Sale Packing List Line',
aggregate_relative_url=hosting_subscription_url,
resource_relative_url=sequence['subscription_resource'])
self.assertEqual(12, len(subscription_delivery_line_list))
self.assertEqual((['confirmed'] * 11) + ['stopped'],
self.assertEqual(2, len(subscription_delivery_line_list))
self.assertEqual(['confirmed'] + ['stopped'],
sorted([q.getSimulationState() for \
q in subscription_delivery_line_list]))
......@@ -308,8 +308,8 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
aggregate_relative_url=hosting_subscription_url,
resource_relative_url=sequence['subscription_resource'])
self.assertEqual(12, len(subscription_delivery_line_list))
self.assertEqual((['confirmed'] * 10) + (['stopped'] * 2),
self.assertEqual(2, len(subscription_delivery_line_list))
self.assertEqual(['stopped'] * 2,
sorted([q.getSimulationState() for \
q in subscription_delivery_line_list]))
......@@ -416,8 +416,8 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
aggregate_relative_url=hosting_subscription_url,
resource_relative_url=sequence['subscription_resource'])
self.assertEqual(12, len(subscription_delivery_line_list))
self.assertEqual((['confirmed'] * 10) + (['stopped'] * 2),
self.assertEqual(2, len(subscription_delivery_line_list))
self.assertEqual(['stopped'] * 2,
sorted([q.getSimulationState() for \
q in subscription_delivery_line_list]))
......@@ -532,8 +532,8 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
aggregate_relative_url=hosting_subscription_url,
resource_relative_url=sequence['subscription_resource'])
self.assertEqual(12, len(subscription_delivery_line_list))
self.assertEqual((['confirmed'] * 10) + (['stopped'] * 2),
self.assertEqual(2, len(subscription_delivery_line_list))
self.assertEqual(['stopped'] * 2,
sorted([q.getSimulationState() for \
q in subscription_delivery_line_list]))
......@@ -590,7 +590,12 @@ class TestVifibInstanceHostingRelatedDocument(TestVifibSlapWebServiceMixin):
invoice.setStartDate(getClosestDate(target_date=DateTime())-1)
def stepTriggerStopInvoiceAlarm(self, sequence, **kw):
sm = getSecurityManager()
self.login()
try:
self.portal.portal_alarms.stop_planned_sale_invoice_transaction.activeSense()
finally:
setSecurityManager(sm)
def test_OpenOrder_sale_packing_list(self):
"""
......
......@@ -52,7 +52,7 @@ class TestVifibOpenOrderSimulation(TestVifibSlapWebServiceMixin):
None, hosting_subscription.getPeriodicityWeekFrequency())
# check start date and stop date of the subscription item,
# currently there are 12 months
# currently there are 2 months
now = DateTime()
start_date = \
getClosestDate(target_date=now, precision='day', before=1)
......@@ -69,7 +69,7 @@ class TestVifibOpenOrderSimulation(TestVifibSlapWebServiceMixin):
self.assertEquals(
0.0, open_order_line.getStartDate().second())
stop_date = addToDate(
getClosestDate(target_date=now, precision='month', before=1), year=1)
getClosestDate(target_date=now, precision='month', before=1), month=2)
self.assertEquals(
stop_date.year(), open_order_line.getStopDate().year())
self.assertEquals(
......@@ -94,8 +94,8 @@ class TestVifibOpenOrderSimulation(TestVifibSlapWebServiceMixin):
parent_uid=applied_rule.getUid(),
sort_on=(('movement.start_date', 'desc'),)
)
# Check that simulation is created by the periodicity for one year
self.assertEquals(12,
# Check that simulation is created by the periodicity for two months
self.assertEquals(2,
len(simulation_movement_list))
# Check the list of expected simulation
......@@ -143,261 +143,55 @@ class TestVifibOpenOrderSimulation(TestVifibSlapWebServiceMixin):
self.assertEqual(expected_start_date, simulation_movement.getStartDate())
self.assertEqual(expected_stop_date, simulation_movement.getStopDate())
# not delivered yet
self.assertEqual(None, simulation_movement.getDelivery())
# delivered already
self.assertNotEqual(None, simulation_movement.getDelivery())
self.assertEqual('Sale Packing List Line',
simulation_movement.getDeliveryValue().getPortalType())
# packing list shall be buildable
self.assertTrue(simulation_movement.isBuildable())
self.assertFalse(simulation_movement.isBuildable())
# fetch invoice level simulation
# no invoice movements on this level
applied_rule_invoice_list = \
simulation_movement.contentValues(portal_type="Applied Rule")
self.assertEquals(1, len(applied_rule_invoice_list))
applied_rule_invoice = \
applied_rule_invoice_list[0].getObject()
self.assertNotEquals(None, applied_rule_invoice)
simulation_movement_invoice_list = \
applied_rule_invoice.contentValues(portal_type="Simulation Movement")
self.assertEquals(1, len(simulation_movement_invoice_list))
simulation_movement_invoice = \
simulation_movement_invoice_list[0].getObject()
self.assertNotEquals(None, simulation_movement_invoice)
# not delivered yet
self.assertEqual(None, simulation_movement_invoice.getDelivery())
# invoice shall be not yet buildable
self.assertFalse(False, simulation_movement_invoice.isBuildable())
# check property of invoice simulation
self.assertEquals(1.0,
simulation_movement_invoice.getQuantity())
self.assertEquals("unit/piece",
simulation_movement_invoice.getQuantityUnit())
self.assertEquals(1.0,
simulation_movement_invoice.getPrice())
self.assertEquals("currency_module/EUR",
simulation_movement_invoice.getPriceCurrency())
self.assertEquals("organisation_module/vifib_internet",
simulation_movement_invoice.getSource())
self.assertEquals("organisation_module/vifib_internet",
simulation_movement_invoice.getSourceSection())
self.assertEquals("person_module/test_vifib_customer",
simulation_movement_invoice.getDestination())
self.assertEquals("person_module/test_vifib_customer",
simulation_movement_invoice.getDestinationSection())
self.assertEquals(open_order_line.getSpecialise(),
simulation_movement_invoice.getSpecialise())
self.assertEquals("service_module/vifib_instance_subscription",
simulation_movement_invoice.getResource())
self.assertEquals("vifib/invoicing",
simulation_movement_invoice.getTradePhase())
self.assertEquals(expected_start_date,
simulation_movement_invoice.getStartDate())
self.assertEquals(expected_stop_date,
simulation_movement_invoice.getStopDate())
self.assertEquals(None,
simulation_movement_invoice.getAggregate(
portal_type="Computer Partition"))
self.assertEquals(None,
simulation_movement_invoice.getAggregate(
portal_type="Software Instance"))
self.assertEquals(hosting_subscription.getRelativeUrl(),
simulation_movement_invoice.getAggregate(
portal_type="Hosting Subscription"))
self.assertEquals(None,
simulation_movement_invoice.getAggregate(
portal_type="Software Release"))
# fetch invoice transaction level simulation, there are 2:
# credit and debit, and resource should be currency
applied_rule_invoice_transaction_list = \
simulation_movement_invoice.contentValues(portal_type="Applied Rule")
self.assertEquals(1, len(applied_rule_invoice_transaction_list))
applied_rule_invoice_transaction = \
applied_rule_invoice_transaction_list[0].getObject()
self.assertNotEquals(None, applied_rule_invoice_transaction)
simulation_movement_invoice_transaction_list = \
applied_rule_invoice_transaction.contentValues(
portal_type="Simulation Movement")
self.assertEquals(2, len(simulation_movement_invoice_transaction_list))
simulation_movement_invoice_transaction_credit = None
simulation_movement_invoice_transaction_debit = None
for simulation_movement_invoice_transaction in \
simulation_movement_invoice_transaction_list:
# not delivered nor buildable
self.assertEqual(None, simulation_movement_invoice_transaction\
.getDelivery())
self.assertFalse(simulation_movement_invoice_transaction.isBuildable())
if "business_process_module/vifib_sale_business_process/account_credit_path" \
in simulation_movement_invoice_transaction.getCausalityList():
simulation_movement_invoice_transaction_credit = \
simulation_movement_invoice_transaction.getObject()
if "business_process_module/vifib_sale_business_process/account_debit_path" \
in simulation_movement_invoice_transaction.getCausalityList():
simulation_movement_invoice_transaction_debit = \
simulation_movement_invoice_transaction.getObject()
self.assertNotEquals(None, simulation_movement_invoice_transaction_credit)
# not delivered nor buildable
self.assertEqual(None, simulation_movement_invoice_transaction_credit\
.getDelivery())
self.assertFalse(simulation_movement_invoice_transaction_credit\
.isBuildable())
self.assertNotEquals(None, simulation_movement_invoice_transaction_debit)
# not delivered nor buildable
self.assertEqual(None, simulation_movement_invoice_transaction_debit\
.getDelivery())
self.assertFalse(simulation_movement_invoice_transaction_debit\
.isBuildable())
# check property of invoice transaction simulation
self.assertEquals(-1.0,
simulation_movement_invoice_transaction_credit.getQuantity())
self.assertEquals("unit/piece",
simulation_movement_invoice_transaction_credit.getQuantityUnit())
self.assertEquals(1.0,
simulation_movement_invoice_transaction_credit.getPrice())
self.assertEquals(None,
simulation_movement_invoice_transaction_credit.getPriceCurrency())
self.assertEquals("account_module/sales",
simulation_movement_invoice_transaction_credit.getSource())
self.assertEquals("organisation_module/vifib_internet",
simulation_movement_invoice_transaction_credit.getSourceSection())
self.assertEquals("account_module/purchase",
simulation_movement_invoice_transaction_credit.getDestination())
self.assertEquals("person_module/test_vifib_customer",
simulation_movement_invoice_transaction_credit.getDestinationSection())
self.assertEquals("currency_module/EUR",
simulation_movement_invoice_transaction_credit.getResource())
self.assertEquals(open_order_line.getSpecialise(),
simulation_movement_invoice_transaction_credit.getSpecialise())
self.assertEquals("vifib/accounting",
simulation_movement_invoice_transaction_credit.getTradePhase())
self.assertEquals(expected_start_date,
simulation_movement_invoice_transaction_credit.getStartDate())
self.assertEquals(expected_stop_date,
simulation_movement_invoice_transaction_credit.getStopDate())
self.assertEquals(1.0,
simulation_movement_invoice_transaction_debit.getQuantity())
self.assertEquals("unit/piece",
simulation_movement_invoice_transaction_debit.getQuantityUnit())
self.assertEquals(1.0,
simulation_movement_invoice_transaction_debit.getPrice())
self.assertEquals(None,
simulation_movement_invoice_transaction_debit.getPriceCurrency())
self.assertEquals("account_module/receivable",
simulation_movement_invoice_transaction_debit.getSource())
self.assertEquals("organisation_module/vifib_internet",
simulation_movement_invoice_transaction_debit.getSourceSection())
self.assertEquals("account_module/payable",
simulation_movement_invoice_transaction_debit.getDestination())
self.assertEquals("person_module/test_vifib_customer",
simulation_movement_invoice_transaction_debit.getDestinationSection())
self.assertEquals("currency_module/EUR",
simulation_movement_invoice_transaction_debit.getResource())
self.assertEquals(open_order_line.getSpecialise(),
simulation_movement_invoice_transaction_debit.getSpecialise())
self.assertEquals("vifib/accounting",
simulation_movement_invoice_transaction_debit.getTradePhase())
self.assertEquals(expected_start_date,
simulation_movement_invoice_transaction_debit.getStartDate())
self.assertEquals(expected_stop_date,
simulation_movement_invoice_transaction_debit.getStopDate())
# credit simulation movement has no content
self.assertEquals([],
simulation_movement_invoice_transaction_credit.contentValues(
portal_type="Applied Rule"))
# fetch payment level simulation
applied_rule_credit_payment_list = \
simulation_movement_invoice_transaction_debit.contentValues(
portal_type="Applied Rule")
self.assertEquals(1, len(applied_rule_credit_payment_list))
applied_rule_credit_payment = \
applied_rule_credit_payment_list[0].getObject()
self.assertNotEquals(None, applied_rule_credit_payment)
simulation_movement_credit_payment_list = \
applied_rule_credit_payment.contentValues(
portal_type="Simulation Movement")
self.assertEquals(2, len(simulation_movement_credit_payment_list))
simulation_movement_credit_payment_credit = None
simulation_movement_credit_payment_debit = None
for simulation_movement_credit_payment in \
simulation_movement_credit_payment_list:
if "business_process_module/vifib_sale_business_process/payment_credit_path" \
in simulation_movement_credit_payment.getCausalityList():
simulation_movement_credit_payment_credit = \
simulation_movement_credit_payment.getObject()
if "business_process_module/vifib_sale_business_process/payment_debit_path" \
in simulation_movement_credit_payment.getCausalityList():
simulation_movement_credit_payment_debit = \
simulation_movement_credit_payment.getObject()
self.assertNotEquals(None, simulation_movement_credit_payment_credit)
# not delivered nor buildable
self.assertEqual(None, simulation_movement_credit_payment_credit\
.getDelivery())
self.assertFalse(simulation_movement_credit_payment_credit\
.isBuildable())
self.assertNotEquals(None, simulation_movement_credit_payment_debit)
# not delivered nor buildable
self.assertEqual(None, simulation_movement_credit_payment_debit\
.getDelivery())
self.assertFalse(simulation_movement_credit_payment_debit\
.isBuildable())
# check next simulation movement
idx += 1
# check payment level of simulation
self.assertEquals(-1.0,
simulation_movement_credit_payment_credit.getQuantity())
self.assertEquals("unit/piece",
simulation_movement_credit_payment_credit.getQuantityUnit())
self.assertEquals(1.0,
simulation_movement_credit_payment_credit.getPrice())
self.assertEquals("currency_module/EUR",
simulation_movement_credit_payment_credit.getResource())
self.assertEquals("account_module/receivable",
simulation_movement_credit_payment_credit.getSource())
self.assertEquals("organisation_module/vifib_internet",
simulation_movement_credit_payment_credit.getSourceSection())
self.assertEquals("account_module/payable",
simulation_movement_credit_payment_credit.getDestination())
self.assertEquals("person_module/test_vifib_customer",
simulation_movement_credit_payment_credit.getDestinationSection())
self.assertEquals(open_order_line.getSpecialise(),
simulation_movement_credit_payment_credit.getSpecialise())
self.assertEquals("vifib/payment",
simulation_movement_credit_payment_credit.getTradePhase())
self.assertEquals(expected_start_date,
simulation_movement_credit_payment_credit.getStartDate())
self.assertEquals(expected_stop_date,
simulation_movement_credit_payment_credit.getStopDate())
def stepIncreaseOpenOrderCoverage(self, sequence, **kw):
person = self.portal.person_module['test_vifib_customer']
open_order = \
person.getDestinationDecisionRelatedValue(portal_type="Open Sale Order")
open_order_line_list = \
open_order.contentValues(portal_type="Open Sale Order Line")
self.assertEquals(1, len(open_order_line_list))
open_order_line = open_order_line_list[0]
self.portal.portal_alarms.vifib_update_open_sale_order_line.activeSense(
params={'stop_date': addToDate(getClosestDate(target_date=DateTime(),
precision='month', before=1), month=3)})
self.assertEquals(1.0,
simulation_movement_credit_payment_debit.getQuantity())
self.assertEquals("unit/piece",
simulation_movement_credit_payment_debit.getQuantityUnit())
self.assertEquals(1.0,
simulation_movement_credit_payment_debit.getPrice())
self.assertEquals("currency_module/EUR",
simulation_movement_credit_payment_debit.getResource())
self.assertEquals("account_module/bank",
simulation_movement_credit_payment_debit.getSource())
self.assertEquals("organisation_module/vifib_internet",
simulation_movement_credit_payment_debit.getSourceSection())
self.assertEquals("account_module/bank",
simulation_movement_credit_payment_debit.getDestination())
self.assertEquals("person_module/test_vifib_customer",
simulation_movement_credit_payment_debit.getDestinationSection())
self.assertEquals(open_order_line.getSpecialise(),
simulation_movement_credit_payment_debit.getSpecialise())
self.assertEquals("vifib/payment",
simulation_movement_credit_payment_debit.getTradePhase())
self.assertEquals(expected_start_date,
simulation_movement_credit_payment_debit.getStartDate())
self.assertEquals(expected_stop_date,
simulation_movement_credit_payment_debit.getStopDate())
# check next simulation movement
idx += 1
def stepCheckThreeTopLevelSimulationMovement(self, sequence, **kw):
person = self.portal.person_module['test_vifib_customer']
open_order = \
person.getDestinationDecisionRelatedValue(portal_type="Open Sale Order")
open_order_line_list = \
open_order.contentValues(portal_type="Open Sale Order Line")
self.assertEquals(1, len(open_order_line_list))
open_order_line = open_order_line_list[0]
hosting_subscription = \
open_order_line.getAggregateValue(portal_type="Hosting Subscription")
applied_rule = \
hosting_subscription.getCausalityRelatedValue(portal_type="Applied Rule")
self.assertEquals(
"portal_rules/default_subscription_item_rule",
applied_rule.getSpecialise())
simulation_movement_list = self.portal.portal_catalog(
portal_type='Simulation Movement',
parent_uid=applied_rule.getUid(),
sort_on=(('movement.start_date', 'desc'),)
)
# Check that simulation is created by the periodicity for two months
self.assertEquals(3,
len(simulation_movement_list))
def test_OpenOrder_request_changeSoftwareType(self):
"""
......@@ -412,7 +206,13 @@ class TestVifibOpenOrderSimulation(TestVifibSlapWebServiceMixin):
CheckSimulationMovement
Tic
SlapLogout
""" + """
LoginERP5TypeTestCase
IncreaseOpenOrderCoverage
Tic
CheckThreeTopLevelSimulationMovement
Logout
LoginTestVifibCustomer
RequestSoftwareInstanceStart
Tic
......@@ -420,13 +220,13 @@ class TestVifibOpenOrderSimulation(TestVifibSlapWebServiceMixin):
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListConfirmed
Logout
SlapLoginCurrentComputer \
SoftwareInstanceStarted \
Tic \
SlapLogout \
\
LoginDefaultUser \
CheckComputerPartitionInstanceHostingSalePackingListStarted \
SlapLoginCurrentComputer
SoftwareInstanceStarted
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListStarted
Logout
LoginERP5TypeTestCase
......
......@@ -178,6 +178,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -273,6 +275,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -368,6 +372,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -405,6 +411,7 @@ vifib_simulation
vifib_slap
vifib_software_pdm
vifib_test
vifib_web_ui_test
erp5_knowledge_pad
erp5_simulation
erp5_dms_base
......@@ -456,6 +463,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -492,6 +501,7 @@ vifib_simulation
vifib_slap
vifib_software_pdm
vifib_test
vifib_web_ui_test
erp5_knowledge_pad
erp5_simulation
erp5_dms_base
......@@ -543,6 +553,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -634,6 +646,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -671,6 +685,7 @@ vifib_simulation
vifib_slap
vifib_software_pdm
vifib_test
vifib_web_ui_test
erp5_km
erp5_km_theme
erp5_knowledge_pad
......@@ -725,6 +740,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -762,6 +779,7 @@ vifib_simulation
vifib_slap
vifib_software_pdm
vifib_test
vifib_web_ui_test
erp5_commerce_multiflex_layout
erp5_knowledge_pad
erp5_simulation
......@@ -813,6 +831,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -849,6 +869,7 @@ vifib_simulation
vifib_slap
vifib_software_pdm
vifib_test
vifib_web_ui_test
erp5_web_download_theme
erp5_knowledge_pad
erp5_simulation
......@@ -900,6 +921,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......@@ -935,6 +958,7 @@ vifib_simulation
vifib_slap
vifib_software_pdm
vifib_test
vifib_web_ui_test
erp5_rss_style
erp5_knowledge_pad
erp5_simulation
......@@ -986,6 +1010,8 @@ erp5_system_event
erp5_tax_resource
erp5_toolbox
erp5_trade
erp5_ui_test
erp5_ui_test_core
erp5_vcs
erp5_web
erp5_web_crm
......
from Products.ERP5Type.tests.backportUnittest import skip
from Products.ERP5Type.tests.Sequence import SequenceList
import unittest
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from slapos import slap
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
from random import random
......@@ -299,8 +299,7 @@ class TestVifibSlapBang(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# Computer owner cannot do bang yet
@expectedFailure
@skip('Computer owner cannot do bang yet')
def test_admin_bang_computer_complex_tree(self):
"""Checks that bangs works on complex tree
......@@ -718,6 +717,346 @@ class TestVifibSlapBang(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def stepCheckTreeLooksLikeRenameComplexTree(self, sequence, **kw):
hosting_subscription_uid = sequence['hosting_subscription_uid']
hosting_subscription = self.portal.portal_catalog.getResultValue(
uid=hosting_subscription_uid
)
root_software_instance = hosting_subscription.portal_catalog.getResultValue(
title=hosting_subscription.getTitle(), portal_type="Software Instance",
root_uid=hosting_subscription_uid)
self.failIfEqual(root_software_instance, None)
children_titles = set([si.getTitle()
for si in root_software_instance.getPredecessorValueList()])
self.failUnless(set(['children_a', 'children_b']) <= children_titles)
children_b_child = hosting_subscription.portal_catalog.getResultValue(
title='children_b_child',
root_uid=hosting_subscription.getUid(),
)
self.failIfEqual(children_b_child, None)
@skip('Ignored for now')
def test_ComputerPartition_rename_root_and_bang(self):
r"""
Request Master: __________
/ \
| HS: Master |
\__________/
_____|____
/ \
| SI: Master |
\__________/
Rename Software Instance Master into MasterDead:
__________
/ \
| HS: Master |
\__________/
_______|______
/ \
| SI: MasterDead |
\______________/
Banging the tree should result:
_____________________________
/ \
| HS: Master |
\______________________________/
____/_____ _______\______
/ \ / \
| SI: Master | | SI: MasterDead |
\__________/ \______________/
"""
self.computer_partition_amount = 2
sequence_list = SequenceList()
sequence_string = self.prepare_install_requested_computer_partition_sequence_string + """
SetRootSoftwareInstanceCurrentInstance
Tic
LoginDefaultUser
RenameCurrentSoftwareInstanceDead
Tic
Logout
SlapLoginCurrentSoftwareInstance
Bang
ConfirmOrderedSaleOrderActiveSense
SlapLogout
Tic
LoginTestVifibCustomer
CheckTreeHasARootSoftwareInstance
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
@skip('Ignored for now')
def test_ComputerPartition_rename_root_complex_tree(self):
r"""
Request Master which is a software realease having a complex tree :
___________________________
/ \
| HS: Master |
\____________________________/
_____________|_____________
/ \
| SI: Master |
\____________________________/
_____/_____ _____\_____
/ \ / \
| SI: Child A | | SI: Child B |
\___________/ \___________/
______|______
/ \
| SI: GrandChild |
\______________/
Rename Software Instance Master :
___________________________
/ \
| SI: Master |
\____________________________/
_____________|_____________
/ \
| SI: MasterDead |
\____________________________/
_____/_____ _____\_____
/ \ / \
| SI: Child A | | SI: Child B |
\___________/ \___________/
______|______
/ \
| SI: GrandChild |
\______________/
Run bang() on the tree. We expect to have a new root as :
_______________________________________________
/ \
| HS: Master |
\_______________________________________________/
_____________|______________ _______|______
/ \ / \
| SI: Master | | SI: MasterDead |
\____________________________/ \______________/
_____/_____ _____\_____
/ \ / \
| SI: Child A | | SI: Child B |
\___________/ \___________/
______|______
/ \
| SI: GrandChild |
\______________/
"""
self.computer_partition_amount = 5
sequence_list = SequenceList()
sequence_string = self.prepare_children_a_children_b_sequence_string + """
LoginDefaultUser
SetSoftwareInstanceChildrenB
SelectRequestedReferenceChildrenBChild
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
CheckRaisesNotFoundComputerPartitionParameterDict
Tic
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
SlapLoginTestVifibCustomer
SetSoftwareInstanceRoot
RenameCurrentSoftwareInstanceDead
Tic
Bang
ConfirmOrderedSaleOrderActiveSense
Tic
Logout
SlapLogout
LoginDefaultUser
SetSoftwareInstanceGetRootOfTheTree
SetRootSoftwareInstanceCurrentInstance
SelectRequestedReferenceChildrenA
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
SelectRequestedReferenceChildrenB
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
ConfirmOrderedSaleOrderActiveSense
Tic
SlapLogout
LoginDefaultUser
SetSoftwareInstanceChildrenB
SelectRequestedReferenceChildrenBChild
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
ConfirmOrderedSaleOrderActiveSense
Tic
SlapLogout
LoginDefaultUser
SlapLoginCurrentComputer
CheckTreeHasARootSoftwareInstance
CheckTreeLooksLikeRenameComplexTree
SlapLogout
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_ComputerPartition_rename_child_complex_tree(self):
r"""
Request A which is a software realease having a complex tree :
___________________________
/ \
| HS: Master |
\____________________________/
_____________|_____________
/ \
| SI: Master |
\____________________________/
_____/_____ _____\_____
/ \ / \
| SI: Child A | | SI: Child B |
\___________/ \___________/
______|______
/ \
| SI: GrandChild |
\______________/
Rename child C into E :
(Rename reattach to root as Luke wanted it)
________________________________
/ \
| HS: Master |
\________________________________/
________________|_______________
/ \
| SI: Master |
\________________________________/
_____/_____ _________\______
/ \ / \
| SI: Child A | | SI: Child B Dead |
\___________/ \________________/
______|______
/ \
| SI: GrandChild |
\______________/
Bang the tree. We espect to have a new C replacing it,
as : _________________________________________________
/ \
| HS: Master |
\_________________________________________________/
_____________|___________________________________
/ \
| SI: Master |
\_________________________________________________/
_____/_____ _____\_____ _______|________
/ \ / \ / \
| SI: Child A | | SI: Child B | | SI: Child B Dead |
\___________/ \___________/ \________________/
______|______
/ \
| SI: GrandChild |
\______________/
"""
self.computer_partition_amount = 5
sequence_list = SequenceList()
sequence_string = self.prepare_children_a_children_b_sequence_string + """
LoginDefaultUser
SetSoftwareInstanceChildrenB
SelectRequestedReferenceChildrenBChild
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
CheckRaisesNotFoundComputerPartitionParameterDict
Tic
RequestComputerPartition
ConfirmOrderedSaleOrderActiveSense
Tic
SlapLogout
LoginDefaultUser
SlapLoginTestVifibCustomer
SetSoftwareInstanceChildrenB
RenameCurrentSoftwareInstanceDead
Tic
Bang
ConfirmOrderedSaleOrderActiveSense
Tic
Logout
SlapLogout
LoginDefaultUser
SetSoftwareInstanceGetRootOfTheTree
SetRootSoftwareInstanceCurrentInstance
SelectRequestedReferenceChildrenA
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
ConfirmOrderedSaleOrderActiveSense
Tic
SlapLogout
LoginDefaultUser
SelectRequestedReferenceChildrenB
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
ConfirmOrderedSaleOrderActiveSense
Tic
SlapLogout
LoginDefaultUser
SetSoftwareInstanceChildrenB
SelectRequestedReferenceChildrenBChild
SelectEmptyRequestedParameterDict
Logout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
ConfirmOrderedSaleOrderActiveSense
Tic
SlapLogout
LoginDefaultUser
SlapLoginCurrentComputer
CheckTreeHasARootSoftwareInstance
CheckTreeLooksLikeRenameComplexTree
SlapLogout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestVifibSlapBang))
......
......@@ -2,6 +2,7 @@ from Products.ERP5Type.tests.Sequence import SequenceList
import unittest
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
import random
import transaction
class TestVifibSlapBug(TestVifibSlapWebServiceMixin):
def test_bug_Person_request_more_then_one_instance(self):
......@@ -702,6 +703,7 @@ class TestVifibSlapBug(TestVifibSlapWebServiceMixin):
sla_xml=self.minimal_correct_xml,
state='started'
)
transaction.abort()
def test_bug_orhpaned_software_instance(self):
"""Check that no orphaned Software Instances would be created
......@@ -866,6 +868,7 @@ class TestVifibSlapBug(TestVifibSlapWebServiceMixin):
sla_xml=self.minimal_correct_xml,
state='started'
)
transaction.abort()
def test_bug_cyclic_software_instance(self):
"""Check that no cyclic Software Instance trees would be created
......@@ -1520,6 +1523,84 @@ class TestVifibSlapBug(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_bug_person_request_ComputerPartition_own_computer(self):
"""Checks that Person using Slap interface is able to request Computer
Partition"""
self.computer_partition_amount = 1
sequence_list = SequenceList()
sequence_string = self.prepare_published_software_release + \
"""
Logout
RequestCredentialFromWebSite
Tic
LoginDefaultUser
SubmitCredentialRequest
Tic
AcceptSubmittedCredentialsActiveSense
Tic
Logout
LoginWebUser
CustomerRegisterNewComputer
Tic
SetComputerCoordinatesFromComputerTitle
ComputerSetAllocationScopeOpenPersonal
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
LoginWebUser
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
SetRandomRequestedReference
SlapLoginWebUser
PersonRequestSlapSoftwareInstancePrepare
Tic
SlapLogout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
Logout
SlapLoginWebUser
PersonRequestSlapSoftwareInstance
Tic
SlapLogout
LoginDefaultUser
SetCurrentPersonSlapRequestedSoftwareInstance
CheckPersonRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
SlapLogout
LoginWebUser
CheckViewCurrentSoftwareInstance
CheckWriteCurrentSoftwareInstance
Tic
Logout
LoginERP5TypeTestCase
CheckSiteConsistency
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestVifibSlapBug))
......
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from Products.ERP5Type.tests.backportUnittest import skip
import transaction
import unittest
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
......@@ -50,9 +50,8 @@ class TestVifibSlapComputerGetComputerPartitionList(TestVifibSlapWebServiceMixin
self.computer_partition_amount = 2
self.test_Computer_getComputerPartitionList_emptyPartition()
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_Computer_getComputerPartitionList_unknowComputerUid(self):
sequence_list = SequenceList()
sequence_string = '\
......@@ -66,9 +65,8 @@ class TestVifibSlapComputerGetComputerPartitionList(TestVifibSlapWebServiceMixin
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_Computer_getComputerPartitionList_draftComputer(self):
sequence_list = SequenceList()
sequence_string = '\
......@@ -109,9 +107,8 @@ class TestVifibSlapComputerGetComputerPartitionList(TestVifibSlapWebServiceMixin
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_Computer_getComputerPartitionList_TwoValidatedComputer(self):
# XXX: It shall be part of VifibMachineAuthentication test suite
sequence_list = SequenceList()
......
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from Products.ERP5Type.tests.backportUnittest import skip
import transaction
import unittest
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
......@@ -9,9 +9,8 @@ class TestVifibSlapComputerGetSoftwareReleaseList(TestVifibSlapWebServiceMixin):
# Computer.getSoftwareReleaseList
########################################
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_Computer_getSoftwareReleaseList_unknowComputerUid(self):
sequence_list = SequenceList()
sequence_string = '\
......@@ -27,9 +26,8 @@ class TestVifibSlapComputerGetSoftwareReleaseList(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_Computer_getSoftwareReleaseList_draftComputer(self):
sequence_list = SequenceList()
sequence_string = '\
......@@ -88,9 +86,8 @@ class TestVifibSlapComputerGetSoftwareReleaseList(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_Computer_getSoftwareReleaseList_TwoValidatedComputer(self):
# XXX: It shall be part of VifibMachineAuthentication test suite
sequence_list = SequenceList()
......
from Products.ERP5Type.tests.Sequence import SequenceList
import unittest
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
from Products.DCWorkflow.DCWorkflow import ValidationFailed
from random import random
from slapos import slap
class TestVifibSlapComputerPartitionLock(TestVifibSlapWebServiceMixin):
def test_lock_building(self):
"""Check locking building computer partition
It shall render it as stopped and disallow any operation.
Destruction shall be possible.
"""
raise NotImplementedError
def test_lock_stopping(self):
"""Check locking stopping computer partition
It shall render it as stopped and disallow any operation.
Stopping shall be possible.
Destruction shall be possible.
"""
raise NotImplementedError
def test_lock_stopped(self):
"""Check locking stopped computer partition
It shall render it as stopped and disallow any operation.
Destruction shall be possible.
"""
raise NotImplementedError
def test_lock_starting(self):
"""Check locking starting computer partition
It shall render it as stopped and disallow any operation.
Stopping shall be possible.
Destruction shall be possible.
"""
raise NotImplementedError
def test_lock_started(self):
"""Check locking started computer partition
It shall render it as stopped and disallow starting.
Stopping shall be possible.
Destruction shall be possible.
"""
raise NotImplementedError
def test_lock_destroying(self):
"""Check locking destroying computer partition
It shall render it as destroyed.
Destruction shall be possible.
"""
raise NotImplementedError
def test_lock_destroyed(self):
"""Check locking destroyed computer partition
It shall not render it at all.
"""
raise NotImplementedError
def test_lock_update(self):
"""Check locking update computer partition
It shall render as stopped.
Destruction shall be possible.
"""
raise NotImplementedError
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestVifibSlapComputerPartitionLock))
return suite
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from Products.ERP5Type.tests.backportUnittest import skip
import urllib
import urlparse
import httplib
......@@ -353,10 +353,9 @@ class TestVifibSlapComputerPartitionRequest(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# XXX: This test fails because test_vifib_customer security is cached
# and this user is not in SOFTINST-x group. We do not want to clear
# cache in tests.
@expectedFailure
@skip('This test fails because test_vifib_customer security is cached '
'and this user is not in SOFTINST-x group. We do not want to clear '
'cache in tests.')
def test_ComputerPartition_request_instantiateStop(self):
"""
Check that after computer partition is requested it is possible to
......@@ -715,8 +714,7 @@ class TestVifibSlapComputerPartitionRequest(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# Marked as expectedFailure as implementation is not ready yet
@expectedFailure
@skip('Implementation is not ready yet')
def test_ComputerPartition_request_twiceDifferentParentWithoutTic(self):
"""
Checks that requesting twice with same arguments from different Computer
......@@ -837,8 +835,7 @@ class TestVifibSlapComputerPartitionRequest(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# Marked as expectedFailure as implementation is not ready yet
@expectedFailure
@skip('Implementation is not ready yet.')
def test_ComputerPartition_request_differentSourceDifferentResultWithoutTic(
self):
"""
......
......@@ -571,9 +571,9 @@ class TestVifibSlapComputerPartitionUpdate(TestVifibSlapWebServiceMixin):
slap_computer_partition.request(**kw)
def stepCheckActivityRequestInProgress(self, sequence, **kw):
software_instance_uid = sequence['software_instance_uid']
hosting_subscription_uid = sequence['hosting_subscription_uid']
requested_partition_reference = sequence.get('software_type', 'requested_reference')
tag = "%s_%s_inProgress" % (software_instance_uid,
tag = "%s_%s_inProgress" % (hosting_subscription_uid,
requested_partition_reference)
self.assertNotEqual(0, self.portal.portal_activities.
......
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from Products.ERP5Type.tests.backportUnittest import skip
import unittest
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
......@@ -8,9 +8,8 @@ class TestVifibSlapRegisterComputerPartition(TestVifibSlapWebServiceMixin):
# slap.registerComputerPartition
########################################
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_slap_registerComputerPartition_unknowComputerUid(self):
"""
Check the slap.registerComputerPartition without any Computer document
......@@ -30,9 +29,8 @@ class TestVifibSlapRegisterComputerPartition(TestVifibSlapWebServiceMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# ERP5/Zope does not follow REST API beacuse it is not possible to configure
# Cookie Crumbler to ignore portal_slap
@expectedFailure
@skip('ERP5/Zope does not follow REST API beacuse it is not possible to '
'configure Cookie Crumbler to ignore portal_slap')
def test_slap_registerComputerPartition_draftComputer(self):
"""
Check the slap.registerComputerPartition fails
......
......@@ -873,6 +873,10 @@ class TestVifibSlapWebServiceMixin(testVifibMixin):
global REMOTE_USER
REMOTE_USER = 'test_vifib_customer'
def stepSlapLoginWebUser(self, sequence, **kw):
global REMOTE_USER
REMOTE_USER = sequence['web_user']
########################################
# Typical sequences for scenarios
########################################
......@@ -1798,18 +1802,15 @@ class TestVifibSlapWebServiceMixin(testVifibMixin):
second = slap_computer_partition.request(software_release,
software_type, software_type + str(2))
self.stepLoginDefaultUser()
transaction.commit()
self.tic()
self.stepTic()
self.stepConfirmOrderedSaleOrderActiveSense()
transaction.commit()
self.tic()
self.stepTic()
self.stepLogout()
first = slap_computer_partition.request(software_release,
software_type, software_type + str(1))
second = slap_computer_partition.request(software_release,
software_type, software_type + str(2))
transaction.commit()
self.tic()
self.stepTic()
self.assertNotEqual(first.getId(), second.getId())
def stepRequestComputerPartition(self, sequence, **kw):
......@@ -1837,12 +1838,13 @@ class TestVifibSlapWebServiceMixin(testVifibMixin):
def _stepSetSoftwareInstanceChildren(self, sequence, source_reference):
software_instance_uid = sequence['root_software_instance_uid']
hosting_subscription_uid = sequence['hosting_subscription_uid']
software_instance = self.portal.portal_catalog.getResultValue(
uid=software_instance_uid)
children_software_instance = \
software_instance.portal_catalog.getResultValue(
portal_type="Software Instance", source_reference=source_reference,
root_uid=software_instance_uid)
root_uid=hosting_subscription_uid)
self.assertNotEqual(None, children_software_instance)
self.assertNotEqual(software_instance.getRelativeUrl(),
children_software_instance.getRelativeUrl())
......@@ -1864,6 +1866,18 @@ class TestVifibSlapWebServiceMixin(testVifibMixin):
self.assertNotEqual(None, software_instance_uid)
sequence.edit(root_software_instance_uid=software_instance_uid)
def stepSetSoftwareInstanceRoot(self, sequence, **kw):
root_software_instance_uid = sequence['root_software_instance_uid']
self.failIfEqual(None, root_software_instance_uid)
root_software_instance = self.portal.portal_catalog.getResultValue(
uid=root_software_instance_uid,
)
self.failIfEqual(None, root_software_instance)
computer_partition_reference = self._softwareInstance_getComputerPartition(
root_software_instance).getReference()
sequence.edit(software_instance_uid=root_software_instance_uid,
computer_partition_reference=computer_partition_reference)
def stepRequestComputerPartitionDifferentReferenceSameTransaction(self,
sequence, **kw):
software_release_uri = sequence['software_release_uri']
......@@ -2017,6 +2031,8 @@ class TestVifibSlapWebServiceMixin(testVifibMixin):
finally:
Base.serialize = Base.serialize_call
transaction.abort()
def _getComputerPartitionByReference(self, sequence):
computer_partition_list = self.portal.portal_catalog(
portal_type=self.computer_partition_portal_type,
......@@ -3896,6 +3912,73 @@ class TestVifibSlapWebServiceMixin(testVifibMixin):
def stepSetRandomRequestedReference(self, sequence, **kw):
sequence['requested_reference'] = self.id() + str(random())
def stepRenameCurrentSoftwareInstanceDead(self, sequence, **kw):
hosting_subscription = self.portal.portal_catalog.getResultValue(
uid=sequence['hosting_subscription_uid'],
)
software_instance = self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']
)
software_instance.rename(new_name='%sDead' % software_instance.getTitle())
def stepCheckTreeHasARootSoftwareInstance(self, sequence, **kw):
hosting_subscription_uid = sequence['hosting_subscription_uid']
hosting_subscription = self.portal.portal_catalog.getResultValue(
uid=hosting_subscription_uid,
)
root_software_instance = self.portal.portal_catalog.getResultValue(
root_uid=hosting_subscription_uid,
title=hosting_subscription.getTitle(),
)
self.failIfEqual(root_software_instance, None,
"No root software instance")
def stepSetSoftwareInstanceGetRootOfTheTree(self, sequence, **kw):
hosting_subscription_uid = sequence['hosting_subscription_uid']
hosting_subscription = self.portal.portal_catalog.getResultValue(
uid=hosting_subscription_uid,
)
root_software_instance = self.portal.portal_catalog.getResultValue(
root_uid=hosting_subscription_uid,
title=hosting_subscription.getTitle(),
)
self.failIfEqual(root_software_instance, None,
"No root software instance")
computer_partition_reference = self._softwareInstance_getComputerPartition(
root_software_instance).getReference()
sequence.edit(software_instance_uid=root_software_instance.getUid(),
computer_partition_reference=computer_partition_reference)
def stepRequestCredentialFromWebSite(self, sequence, **kw):
sequence['web_user_email'] = '%s@example.com' % random()
sequence['web_user'] = '%s.%s' % (self.id(), random())
self.portal.ERP5Site_newCredentialRequest(\
first_name='Homer',
last_name='Simpson',
reference=sequence['web_user'],
password='secret',
default_email_text=sequence['web_user_email'],
)
def stepSubmitCredentialRequest(self, sequence, **kw):
"""Simulates click of user in email confirmation about account"""
credential_request = self.portal.portal_catalog.getResultValue(
portal_type='Credential Request',
reference=sequence['web_user']
)
credential_request.submit()
def stepAcceptSubmittedCredentialsActiveSense(self, **kw):
self.portal.portal_alarms.accept_submitted_credentials.activeSense()
def stepLoginWebUser(self, sequence, **kw):
self.login(sequence['web_user'])
class TestVifibSlapWebService(TestVifibSlapWebServiceMixin):
########################################
# slap.initializeConnection
......@@ -4138,31 +4221,6 @@ class TestVifibSlapWebService(TestVifibSlapWebServiceMixin):
# Other tests
########################################
def stepRequestCredentialFromWebSite(self, sequence, **kw):
sequence['web_user_email'] = '%s@example.com' % random()
sequence['web_user'] = '%s.%s' % (self.id(), random())
self.portal.ERP5Site_newCredentialRequest(\
first_name='Homer',
last_name='Simpson',
reference=sequence['web_user'],
password='secret',
default_email_text=sequence['web_user_email'],
)
def stepSubmitCredentialRequest(self, sequence, **kw):
"""Simulates click of user in email confirmation about account"""
credential_request = self.portal.portal_catalog.getResultValue(
portal_type='Credential Request',
reference=sequence['web_user']
)
credential_request.submit()
def stepAcceptSubmittedCredentialsActiveSense(self, **kw):
self.portal.portal_alarms.accept_submitted_credentials.activeSense()
def stepLoginWebUser(self, sequence, **kw):
self.login(sequence['web_user'])
def test_person_from_credential_request_software_instance(self):
"""Checks that person created from web can use the system"""
sequence_list = SequenceList()
......@@ -4258,6 +4316,7 @@ class TestVifibSlapWebService(TestVifibSlapWebServiceMixin):
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# class IComputerPartition
# def started():
# def stopped():
......
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from Products.ERP5Type.tests.backportUnittest import skip
import unittest
from VifibMixin import testVifibMixin
......@@ -65,8 +65,7 @@ class TestVifibSoftwareInstance(testVifibMixin):
self.assertRaises(DisconnectedSoftwareTree, self.checkConnected, graph,
root)
# For now limitation of implementation gives false positive
@expectedFailure
@skip('For now limitation of implementation gives false positive')
def test_si_tree_cyclic_connected(self):
"""Cyclic is connected
......
......@@ -32,6 +32,7 @@ from lxml import etree
from slapos import slap
from testVifibSlapWebService import TestVifibSlapWebServiceMixin
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.tests.backportUnittest import skip
def test_suite():
suite = unittest.TestSuite()
......@@ -312,6 +313,7 @@ class TestVifibUsageReport(TestVifibUsageReportMixin):
def getTitle(self):
return "testVifibUsageReport"
@skip('Ignored for now.')
def test_usageReportWithSinglePartition(self):
"""
Checks if useComputer method of SlapTool is properly called one time.
......@@ -343,6 +345,7 @@ class TestVifibUsageReport(TestVifibUsageReportMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
@skip('Ignored for now.')
def test_usageReportWithTwoPartitions(self):
"""
Checks if useComputer method of SlapTool is properly called two times.
......
......@@ -28,7 +28,7 @@
##############################################################################
import unittest
from VifibMixin import testVifibMixin
from Products.ERP5Type.tests.backportUnittest import expectedFailure
from Products.ERP5Type.tests.backportUnittest import skip
class TestVifibXHTML(testVifibMixin):
run_all_test = 1
......@@ -112,7 +112,7 @@ class TestVifibXHTML(testVifibMixin):
error_list.append(form_path)
self.assertEquals(error_list, [])
@expectedFailure
@skip('Skipped.')
def test_configurationOfFieldLibrary(self):
self.login()
error_list = []
......
......@@ -70,25 +70,43 @@ class OS(object):
def __getattr__(self, name):
return getattr(self._os, name)
class SlapError(Exception):
class UsageError(Exception):
pass
class NoAddressOnBridge(Exception):
"""
Slap error
Exception raised if there's not address on the bridge to construct IPv6
address with.
Attributes:
brige: String, the name of the bridge.
"""
def __init__(self, message):
self.msg = message
class UsageError(SlapError):
pass
def __init__(self, bridge):
super(NoAddressOnBridge, self).__init__(
'No IPv6 found on bridge %s to construct IPv6 with.' % (bridge, )
)
class ExecError(SlapError):
pass
class AddressGenerationError(Exception):
"""
Exception raised if the generation of an IPv6 based on the prefix obtained
from the bridge failed.
Attributes:
addr: String, the invalid address the exception is raised for.
"""
def __init__(self, addr):
super(AddressGenerationError, self).__init__(
'Generated IPv6 %s seems not to be a valid IP.' % addr
)
def callAndRead(argument_list, raise_on_error=True):
popen = subprocess.Popen(argument_list, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
result = popen.communicate()[0]
if raise_on_error and popen.returncode != 0:
raise ValueError('Issue during invoking %r, result was:\n%s' % (argument_list, result))
raise ValueError('Issue during invoking %r, result was:\n%s' % (
argument_list, result))
return popen.returncode, result
def isGlobalScopeAddress(a):
......@@ -124,54 +142,27 @@ def _getDict(instance):
elif isinstance(instance, dict):
result = {}
for key in instance.keys():
for key in instance:
result[key] = _getDict(instance[key])
return result
else:
try:
result = {}
for key in instance.__dict__.keys():
result[key] = _getDict(instance.__dict__[key])
return result
dikt = instance.__dict__
except AttributeError:
return instance
result = {}
for key, value in dikt.iteritems():
result[key] = _getDict(value)
return result
class Error(Exception):
"Base class for exceptions in this module."
def __str__(self):
return self.message
class NoAddressOnBridge(Error):
"""
Exception raised if there's not address on the bridge to construct IPv6
address with.
Attributes:
brige: String, the name of the bridge.
"""
def __init__(self, bridge):
self.message = 'No IPv6 found on bridge %s to construct IPv6 with.' % bridge
class AddressGenerationError(Error):
"""
Exception raised if the generation of an IPv6 based on the prefix obtained
from the bridge failed.
Attributes:
addr: String, the invalid address the exception is raised for.
"""
def __init__(self, addr):
self.message = 'Generated IPv6 %s seems not to be a valid IP.' % addr
class Computer:
class Computer(object):
"Object representing the computer"
instance_root = None
software_root = None
def __init__(self, reference, bridge=None, addr = None, netmask = None,
ipv6_interface=None):
def __init__(self, reference, bridge=None, addr=None, netmask=None,
ipv6_interface=None, software_user='slapsoft'):
"""
Attributes:
reference: String, the reference of the computer.
......@@ -183,6 +174,7 @@ class Computer:
self.address = addr
self.netmask = netmask
self.ipv6_interface = ipv6_interface
self.software_user = software_user
def __getinitargs__(self):
return (self.reference, self.bridge)
......@@ -259,8 +251,7 @@ class Computer:
a valid configuration.
Return:
A Computer object if the path where pointing on a valid
file, False otherwise.
A Computer object.
"""
dumped_dict = xml_marshaller.loads(open(path_to_xml).read())
......@@ -271,6 +262,7 @@ class Computer:
addr = dumped_dict['address'],
netmask = dumped_dict['netmask'],
ipv6_interface=ipv6_interface,
software_user=dumped_dict.get('software_user', 'slapsoft'),
)
for partition_dict in dumped_dict['partition_list']:
......@@ -312,8 +304,8 @@ class Computer:
else:
os.chmod(path, 0755)
# own self.software_root by slapsoft
slapsoft = User('slapsoft')
# own self.software_root by software user
slapsoft = User(self.software_user)
slapsoft.path = self.software_root
if alter_user:
slapsoft.create()
......@@ -363,16 +355,20 @@ class Computer:
partition.address_list = []
if len(old_partition_address_list) != 2:
raise ValueError('There should be exactly 2 stored addresses')
if not any([netaddr.valid_ipv6(q['addr']) for q in old_partition_address_list]):
if not any([netaddr.valid_ipv6(q['addr'])
for q in old_partition_address_list]):
raise ValueError('Not valid ipv6 addresses loaded')
if not any([netaddr.valid_ipv4(q['addr']) for q in old_partition_address_list]):
if not any([netaddr.valid_ipv4(q['addr'])
for q in old_partition_address_list]):
raise ValueError('Not valid ipv6 addresses loaded')
for address in old_partition_address_list:
if netaddr.valid_ipv6(address['addr']):
partition.address_list.append(self.bridge.addAddr(address['addr'],
partition.address_list.append(self.bridge.addAddr(
address['addr'],
address['netmask']))
elif netaddr.valid_ipv4(address['addr']):
partition.address_list.append(self.bridge.addIPv4LocalAddress(address['addr']))
partition.address_list.append(self.bridge.addIPv4LocalAddress(
address['addr']))
else:
raise ValueError('Address %r is incorrect' % address['addr'])
finally:
......@@ -382,7 +378,7 @@ class Computer:
except IndexError:
pass
class Partition:
class Partition(object):
"Represent a computer partition"
def __init__(self, reference, path, user, address_list, tap):
......@@ -406,8 +402,8 @@ class Partition:
def createPath(self, alter_user=True):
"""
Create the directory of the partition, assign to the partition user and give
it the 750 permission. In case if path exists just modifies it.
Create the directory of the partition, assign to the partition user and
give it the 750 permission. In case if path exists just modifies it.
"""
self.path = os.path.abspath(self.path)
......@@ -419,8 +415,9 @@ class Partition:
os.chown(self.path, owner_pw.pw_uid, owner_pw.pw_gid)
os.chmod(self.path, 0750)
class User:
class User(object):
"User: represent and manipulate a user on the system."
path = None
def __init__(self, user_name, additional_group_list=None):
"""
......@@ -452,7 +449,8 @@ class User:
except KeyError:
callAndRead(['groupadd', self.name])
user_parameter_list = ['-d', self.path, '-g', self.name, '-s', '/bin/false']
user_parameter_list = ['-d', self.path, '-g', self.name, '-s',
'/bin/false']
if self.additional_group_list is not None:
user_parameter_list.extend(['-G', ','.join(self.additional_group_list)])
user_parameter_list.append(self.name)
......@@ -486,7 +484,7 @@ import fcntl
import errno
import threading
class Tap:
class Tap(object):
"Tap represent a tap interface on the system"
IFF_TAP = 0x0002
TUNSETIFF = 0x400454ca
......@@ -496,7 +494,6 @@ class Tap:
"""
Attributes:
tap_name: String, the name of the tap interface.
user: User, the owner of the tap interface.
"""
self.name = str(tap_name)
......@@ -558,9 +555,6 @@ class Tap:
def createWithOwner(self, owner, attach_to_tap=False):
"""
Create a tap interface on the system.
Return:
True: Everything went right.
"""
# some systems does not have -p switch for tunctl
......@@ -568,20 +562,19 @@ class Tap:
check_file = '/sys/devices/virtual/net/%s/owner' % self.name
owner_id = None
if os.path.exists(check_file):
owner_id = open(check_file).read().strip()
try:
owner_id = int(open(check_file).read().strip())
except Exception:
owner_id = int(owner_id)
except ValueError:
pass
if (owner_id is None) or (owner_id != pwd.getpwnam(owner.name).pw_uid):
if owner_id != pwd.getpwnam(owner.name).pw_uid:
callAndRead(['tunctl', '-t', self.name, '-u', owner.name])
callAndRead(['ip', 'link', 'set', self.name, 'up'])
if attach_to_tap:
threading.Thread(target=self.attach).start()
return True
class Bridge:
class Bridge(object):
"Bridge represent a bridge on the system"
def __init__(self, name, ipv4_local_network, ipv6_interface=None):
......@@ -596,14 +589,17 @@ class Bridge:
# Attach to TAP network interface, only if the bridge interface does not
# report carrier
returncode, result = callAndRead(['ip', 'addr', 'list', self.name])
_, result = callAndRead(['ip', 'addr', 'list', self.name])
self.attach_to_tap = 'DOWN' in result.split('\n', 1)[0]
def __getinitargs__(self):
return (self.name,)
def getIPv4LocalAddressList(self):
"""Returns currently configured local IPv4 addresses which are in ipv4_local_network"""
"""
Returns currently configured local IPv4 addresses which are in
ipv4_local_network
"""
if not socket.AF_INET in netifaces.ifaddresses(self.name):
return []
return [dict(addr=q['addr'], netmask=q['netmask']) for q in
......@@ -618,7 +614,8 @@ class Bridge:
else:
interface_name = self.name
try:
address_list = [q for q in netifaces.ifaddresses(interface_name)[socket.AF_INET6]
address_list = [q
for q in netifaces.ifaddresses(interface_name)[socket.AF_INET6]
if isGlobalScopeAddress(q['addr'].split('%')[0])]
except KeyError:
raise ValueError("%s must have at least one IPv6 address assigned" % \
......@@ -635,7 +632,7 @@ class Bridge:
def getInterfaceList(self):
"""Returns list of interfaces already present on bridge"""
interface_list = []
returncode, result = callAndRead(['brctl', 'show'])
_, result = callAndRead(['brctl', 'show'])
in_bridge = False
for line in result.split('\n'):
if len(line.split()) > 1:
......@@ -688,13 +685,15 @@ class Bridge:
if address in [q['addr'].split('%')[0] for q in address_dict[af]]:
return False
if not af in netifaces.ifaddresses(interface_name) or not address in [q['addr'].split('%')[0] for q in netifaces.ifaddresses(interface_name)[af]]:
if not af in netifaces.ifaddresses(interface_name) \
or not address in [q['addr'].split('%')[0]
for q in netifaces.ifaddresses(interface_name)[af]]:
# add an address
callAndRead(['ip', 'addr', 'add', address_string, 'dev', interface_name])
# wait few moments
time.sleep(2)
# check existence on interface
returncode, result = callAndRead(['ip', 'addr', 'list', interface_name])
_, result = callAndRead(['ip', 'addr', 'list', interface_name])
for l in result.split('\n'):
if address in l:
if 'tentative' in l:
......@@ -714,7 +713,8 @@ class Bridge:
while try_num > 0:
addr = random.choice([q for q in netaddr.glob_to_iprange(
netaddr.cidr_to_glob(self.ipv4_local_network))]).format()
if dict(addr=addr, netmask=netmask) not in self.getIPv4LocalAddressList():
if dict(addr=addr, netmask=netmask) not in \
self.getIPv4LocalAddressList():
# Checking the validity of the IPv6 address
if self._addSystemAddress(addr, netmask, False):
return dict(addr=addr, netmask=netmask)
......@@ -743,8 +743,9 @@ class Bridge:
If addr is specified and exists already on bridge does nothing.
If addr is specified and does not exists on bridge, tries to add given address.
In case if it is not possible (ex. because network changed) calculates new address.
If addr is specified and does not exists on bridge, tries to add given
address. If it is not possible (ex. because network changed) calculates new
address.
Args:
addr: Wished address to be added to bridge.
......@@ -779,7 +780,8 @@ class Bridge:
# same netmask, so there is a chance to add good one
bridge_network = netaddr.ip.IPNetwork('%s/%s' % (address_dict['addr'],
netmaskToPrefixIPv6(address_dict['netmask'])))
requested_network = netaddr.ip.IPNetwork('%s/%s' % (addr, netmaskToPrefixIPv6(netmask)))
requested_network = netaddr.ip.IPNetwork('%s/%s' % (addr,
netmaskToPrefixIPv6(netmask)))
if bridge_network.network == requested_network.network:
# same network, try to add
if self._addSystemAddress(addr, netmask):
......@@ -790,9 +792,11 @@ class Bridge:
try_num = 10
netmask = address_dict['netmask']
while try_num > 0:
addr = ':'.join(address_dict['addr'].split(':')[:-1] + ['%x' % random.randint(1, 65000)])
addr = ':'.join(address_dict['addr'].split(':')[:-1] + ['%x' % (
random.randint(1, 65000), )])
socket.inet_pton(socket.AF_INET6, addr)
if dict(addr=addr, netmask=netmask) not in self.getGlobalScopeAddressList():
if dict(addr=addr, netmask=netmask) not in \
self.getGlobalScopeAddressList():
# Checking the validity of the IPv6 address
if self._addSystemAddress(addr, netmask):
return dict(addr=addr, netmask=netmask)
......@@ -859,18 +863,20 @@ class Parser(OptionParser):
return options, args[0]
def run(config):
try:
# Define the computer
if config.input_definition_file:
filepath = os.path.abspath(config.input_definition_file)
config.logger.info('Using definition file %r' % filepath)
computer_definition = ConfigParser.RawConfigParser()
computer_definition = ConfigParser.RawConfigParser({
'software_user': 'slapsoft',
})
computer_definition.read(filepath)
bridge = None
address = None
netmask = None
if computer_definition.has_option('computer', 'address'):
address, netmask = computer_definition.get('computer', 'address').split('/')
address, netmask = computer_definition.get('computer',
'address').split('/')
if config.alter_network and config.bridge_name is not None \
and config.ipv4_local_network is not None:
bridge = Bridge(config.bridge_name, config.ipv4_local_network,
......@@ -880,7 +886,8 @@ def run(config):
bridge=bridge,
addr=address,
netmask=netmask,
ipv6_interface=config.ipv6_interface
ipv6_interface=config.ipv6_interface,
software_user=computer_definition.get('computer', 'software_user'),
)
partition_list = []
for partition_number in range(int(config.partition_amount)):
......@@ -891,8 +898,10 @@ def run(config):
address, netmask = a.split('/')
address_list.append(dict(addr=address, netmask=netmask))
tap = Tap(computer_definition.get(section, 'network_interface'))
partition_list.append(Partition(reference=computer_definition.get(section, 'pathname'),
path=os.path.join(config.instance_root, computer_definition.get(section, 'pathname')),
partition_list.append(Partition(reference=computer_definition.get(
section, 'pathname'),
path=os.path.join(config.instance_root, computer_definition.get(
section, 'pathname')),
user=user,
address_list=address_list,
tap=tap,
......@@ -901,21 +910,25 @@ def run(config):
else:
# no definition file, figure out computer
if os.path.exists(config.computer_xml):
config.logger.info('Loading previous computer data from %r' % config.computer_xml)
computer = Computer.load(config.computer_xml, reference=config.computer_id, ipv6_interface=config.ipv6_interface)
config.logger.info('Loading previous computer data from %r' % (
config.computer_xml, ))
computer = Computer.load(config.computer_xml,
reference=config.computer_id, ipv6_interface=config.ipv6_interface)
# Connect to the bridge interface defined by the configuration
computer.bridge = Bridge(config.bridge_name, config.ipv4_local_network,
config.ipv6_interface)
else:
# If no pre-existent configuration found, creating a new computer object
config.logger.warning('Creating new data computer with id %r' % config.computer_id)
config.logger.warning('Creating new data computer with id %r' % (
config.computer_id, ))
computer = Computer(
reference=config.computer_id,
bridge=Bridge(config.bridge_name, config.ipv4_local_network,
config.ipv6_interface),
addr=None,
netmask=None,
ipv6_interface=config.ipv6_interface
ipv6_interface=config.ipv6_interface,
software_user=config.software_user,
)
partition_amount = int(config.partition_amount)
......@@ -955,7 +968,8 @@ def run(config):
computer_definition = ConfigParser.RawConfigParser()
computer_definition.add_section('computer')
if computer.address is not None and computer.netmask is not None:
computer_definition.set('computer', 'address', '/'.join([computer.address, computer.netmask]))
computer_definition.set('computer', 'address', '/'.join(
[computer.address, computer.netmask]))
partition_number = 0
for partition in computer.partition_list:
section = 'partition_%s' % partition_number
......@@ -980,12 +994,22 @@ def run(config):
computer.dump(config.computer_xml)
config.logger.info('Posting information to %r' % config.master_url)
computer.send(config)
except:
config.logger.exception('Uncaught exception:')
raise
class Config:
def checkRequiredBinary(self, binary_list):
class Config(object):
key_file = None
cert_file = None
alter_network = None
alter_user = None
computer_xml = None
logger = None
log_file = None
verbose = None
dry_run = None
console = None
software_user = None
@staticmethod
def checkRequiredBinary(binary_list):
missing_binary_list = []
for b in binary_list:
try:
......@@ -995,8 +1019,8 @@ class Config:
except OSError:
missing_binary_list.append(b)
if missing_binary_list:
raise UsageError('Some required binaries are missing or not functional: %s'%
','.join(missing_binary_list))
raise UsageError('Some required binaries are missing or not '
'functional: %s' % (','.join(missing_binary_list), ))
def setConfig(self, option_dict, configuration_file_path):
"""
......@@ -1029,6 +1053,8 @@ class Config:
self.alter_network = 'True'
if self.alter_user is None:
self.alter_user = 'True'
if self.software_user is None:
self.software_user = 'slapsoft'
# set up logging
self.logger = logging.getLogger("slapformat")
......@@ -1045,8 +1071,8 @@ class Config:
elif getattr(self, o).lower() == 'false':
setattr(self, o, False)
else:
message = 'Option %r needs to be "True" or "False", wrong value: %r' % (
o, getattr(self, o))
message = 'Option %r needs to be "True" or "False", wrong value: ' \
'%r' % (o, getattr(self, o))
self.logger.error(message)
raise UsageError(message)
......@@ -1076,7 +1102,8 @@ class Config:
os.path.dirname(self.log_file), self.log_file))
else:
file_handler = logging.FileHandler(self.log_file)
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
file_handler.setFormatter(logging.Formatter("%(asctime)s - "
"%(name)s - %(levelname)s - %(message)s"))
self.logger.addHandler(file_handler)
self.logger.info('Configured logging to file %r' % self.log_file)
# Check mandatory options
......@@ -1100,15 +1127,18 @@ def main(*args):
"Run default configuration."
global os
global callAndRead
global pwd
real_callAndRead = callAndRead
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
# Parse arguments
options, configuration_file_path = Parser(usage=usage).check_args(args)
config = Config()
try:
config.setConfig(options, configuration_file_path)
except UsageError, err:
print >>sys.stderr, err.message
print >>sys.stderr, "For help use --help"
sys.exit(1)
os = OS(config)
if config.dry_run:
def dry_callAndRead(argument_list, raise_on_error=True):
......@@ -1124,7 +1154,7 @@ def main(*args):
return True
Bridge._addSystemAddress = fake_addSystemAddress
def fake_getpwnam(user):
class result:
class result(object):
pw_uid = 12345
pw_gid = 54321
return result
......@@ -1136,7 +1166,8 @@ def main(*args):
config.logger.debug(' '.join(argument_list))
return dry_callAndRead(argument_list, raise_on_error)
callAndRead = logging_callAndRead
try:
run(config)
except UsageError, err:
print >>sys.stderr, err.msg
print >>sys.stderr, "For help use --help"
except:
config.logger.exception('Uncaught exception:')
raise
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