Commit 9b035535 authored by Romain Courteaud's avatar Romain Courteaud

Create API consumption packing list with a global alarm.

Workflow history is analyzed to decide the kind of packing list to create.
Remove hardcoded values and use template documents instead.
parent 88b3b0ef
......@@ -2,98 +2,104 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_searchDivergedInstanceList</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
<key> <string>id</string> </key>
<value> <string>slapos_instance_invoicing</string> </value>
</item>
<item>
<key> <string>periodicity_day_frequency</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<key> <string>periodicity_hour</string> </key>
<value>
<list>
<string>Instance_changePromiseParameter</string>
</list>
<tuple>
<int>2</int>
</tuple>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<key> <string>periodicity_hour_frequency</string> </key>
<value>
<tuple/>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>guard</string> </key>
<key> <string>periodicity_minute_frequency</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>change_instance_parameter</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<key> <string>periodicity_month</string> </key>
<value>
<list>
<string>_setUrlString</string>
<string>_setTextContent</string>
<string>_setSourceReference</string>
<string>_setSlaXml</string>
<string>bang</string>
</list>
<tuple/>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>1</int> </value>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<key> <string>periodicity_start_date</string> </key>
<value>
<list>
<string>Slave Instance</string>
<string>Software Instance</string>
</list>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>0.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</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>
<value> <string>Instance Invoicing</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Packing List" 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>
<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>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>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>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>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>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_destination_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SPL-34</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_accounting_instance_delivery_line_template</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Packing List</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Slapos Accounting Instance Delivery Line Template</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="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Packing List Line" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>resource/service_module/slapos_instance_cleanup</string>
<string>quantity_unit/unit/piece</string>
<string>base_contribution/base_amount/invoicing/discounted</string>
<string>base_contribution/base_amount/invoicing/taxable</string>
<string>use/trade/sale</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>1</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>destroy</string> </value>
</item>
<item>
<key> <string>index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Packing List Line</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Destroy Line</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>movement</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Packing List Line" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>resource/service_module/slapos_instance_setup</string>
<string>quantity_unit/unit/piece</string>
<string>base_contribution/base_amount/invoicing/discounted</string>
<string>base_contribution/base_amount/invoicing/taxable</string>
<string>use/trade/sale</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>1</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>setup</string> </value>
</item>
<item>
<key> <string>index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Packing List Line</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Setup Line</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>movement</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Packing List Line" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>resource/service_module/slapos_instance_update</string>
<string>quantity_unit/unit/piece</string>
<string>base_contribution/base_amount/invoicing/discounted</string>
<string>base_contribution/base_amount/invoicing/taxable</string>
<string>use/trade/sale</string>
</tuple>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>1</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>update</string> </value>
</item>
<item>
<key> <string>index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Packing List Line</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Update Line</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>movement</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Packing List" 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>
<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>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>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>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>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SPL-33</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_accounting_instance_delivery_template</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Packing List</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Slapos Accounting Instance Delivery Template</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Service" 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>
<persistent> <string encoding="base64">AAAAAAAAAAI=</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>
</tuple>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>aggregated_portal_type</string> </key>
<value>
<tuple>
<string>Computer Partition</string>
<string>Slave Instance</string>
<string>Software Instance</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>quantity_unit/unit/piece</string>
<string>product_line/cloud/configuration</string>
<string>use/trade/sale</string>
<string>base_contribution/base_amount/invoicing/discounted</string>
<string>base_contribution/base_amount/invoicing/taxable</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</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>1277942400.0</float>
<string>Universal</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>instance_cleanup</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_instance_cleanup</string> </value>
</item>
<item>
<key> <string>modification_date</string> </key>
<value>
<object>
<klass> <reference id="1.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1278374400.0</float>
<string>Universal</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Service</string> </value>
</item>
<item>
<key> <string>required_aggregated_portal_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Instance Cleanup</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="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Service" 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>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>aggregated_portal_type</string> </key>
<value>
<tuple>
<string>Computer Partition</string>
<string>Slave Instance</string>
<string>Software Instance</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>quantity_unit/unit/piece</string>
<string>product_line/cloud/configuration</string>
<string>use/trade/sale</string>
<string>base_contribution/base_amount/invoicing/discounted</string>
<string>base_contribution/base_amount/invoicing/taxable</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>instance_setup</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_instance_setup</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Service</string> </value>
</item>
<item>
<key> <string>required_aggregated_portal_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Instance Setup</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="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Service" 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>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>aggregated_portal_type</string> </key>
<value>
<tuple>
<string>Hosting Subscription</string>
<string>Slave Instance</string>
<string>Software Instance</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>quantity_unit/unit/piece</string>
<string>product_line/cloud/configuration</string>
<string>use/trade/sale</string>
<string>base_contribution/base_amount/invoicing/discounted</string>
<string>base_contribution/base_amount/invoicing/taxable</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>instance_update</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_instance_update</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Service</string> </value>
</item>
<item>
<key> <string>required_aggregated_portal_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Instance Update</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="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<base_category_list>
<portal_type id="Slave Instance">
<item>causality</item>
</portal_type>
<portal_type id="Software Instance">
<item>causality</item>
</portal_type>
</base_category_list>
\ No newline at end of file
......@@ -2,4 +2,10 @@
<portal_type id="Hosting Subscription">
<item>SlapOSAccountingHostingSubscriptionConstraint</item>
</portal_type>
<portal_type id="Slave Instance">
<item>InstanceAccountingSynchronisation</item>
</portal_type>
<portal_type id="Software Instance">
<item>InstanceAccountingSynchronisation</item>
</portal_type>
</property_sheet_list>
\ No newline at end of file
......@@ -7,6 +7,14 @@
<type>Sale Packing List</type>
<workflow>slapos_accounting_interaction_workflow</workflow>
</chain>
<chain>
<type>Slave Instance</type>
<workflow>slapos_accounting_interaction_workflow, slapos_api_invoicing_workflow</workflow>
</chain>
<chain>
<type>Software Instance</type>
<workflow>slapos_accounting_interaction_workflow, slapos_api_invoicing_workflow</workflow>
</chain>
<chain>
<type>Subscription Item Root Simulation Rule</type>
<workflow>edit_workflow, rule_validation_workflow</workflow>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Property Sheet" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InstanceAccountingSynchronisation</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Property Sheet</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="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
......@@ -2,43 +2,37 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionWorkflowDefinition" module="Products.ERP5.InteractionWorkflow"/>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<key> <string>categories</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>creation_guard</string> </key>
<value>
<none/>
<tuple>
<string>elementary_type/int</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
<value> <string>Used by the invoicing alarm to now the invoicing generation status.</string> </value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<tuple/>
</value>
<key> <string>id</string> </key>
<value> <string>invoicing_synchronization_pointer_property</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>instance_accounting_slap_interaction_workflow</string> </value>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
<key> <string>read_permission</string> </key>
<value> <string>Manage portal</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Init script Interaction Workflow</string> </value>
<key> <string>write_permission</string> </key>
<value> <string>Manage portal</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>_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/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_instance_delivery_template_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: \'\'</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/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_instance_destroy_movement_template_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: \'\'</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/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_instance_setup_movement_template_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: \'\'</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/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_instance_update_movement_template_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: \'\'</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value> <string>Manage properties</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -50,49 +50,25 @@
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>instance = state_change[\'object\']\n
portal = instance.getPortalObject()\n
<value> <string>portal = context.getPortalObject()\n
\n
# Get current sale order\n
delivery = instance.getCausalityValue(portal_type=["Sale Order"])\n
\n
sale_order_line = delivery.contentValues(portal_type="Sale Order Line")[0]\n
\n
packing_list_module = portal.getDefaultModule(portal_type=\'Sale Packing List\')\n
packing_list = packing_list_module.newContent(\n
portal_type=\'Sale Packing List\',\n
specialise=delivery.getSpecialise() or delivery.getCausalityValue().getSpecialise(),\n
destination=delivery.getDestination(),\n
destination_section=delivery.getDestinationSection(),\n
destination_decision=delivery.getDestinationDecision(),\n
source=delivery.getSource(),\n
source_section=delivery.getSourceSection(),\n
price_currency=delivery.getPriceCurrency(),\n
start_date=DateTime())\n
\n
aggregate_list = sale_order_line.getAggregateList(portal_type=[\'Slave Instance\', \'Software Instance\', \'Hosting Subscription\', \'Computer Partition\'])\n
aggregate_list.append(software_release_document.getRelativeUrl())\n
packing_list_line = packing_list.newContent(\n
portal_type=\'Sale Packing List Line\',\n
resource=service.getRelativeUrl(),\n
quantity_unit="unit/piece",\n
quantity=1,\n
aggregate_list=aggregate_list,\n
# XXX Hardcode price on service\n
price=service.getSaleSupplyLineBasePrice(),\n
portal.portal_catalog.searchAndActivate(\n
portal_type=["Slave Instance", "Software Instance"],\n
causality_state="diverged",\n
method_id=\'Instance_solveInvoicingGeneration\',\n
activate_kw={\'tag\': tag}\n
)\n
\n
\n
return packing_list\n
context.activate(after_tag=tag).getId()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, service, software_release_document</string> </value>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Instance_createSalePackingList</string> </value>
<value> <string>Alarm_searchDivergedInstanceList</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -50,46 +50,138 @@
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>return\n
instance = state_change[\'object\']\n
# Get latest workflow transition\n
state = instance.getSlapState()\n
started = "start_requested"\n
stopped = "stop_requested"\n
\n
if (state in (started, stopped)):\n
partition = instance.getAggregate(portal_type="Computer Partition")\n
if (partition is not None):\n
portal = instance.getPortalObject()\n
delivery = instance.getCausalityValue(portal_type=["Sale Packing List"])\n
update_service_relative_url = portal.portal_preferences.getPreferredInstanceUpdateResource()\n
\n
software_release_document = instance.Base_getSoftwareReleaseDocument(instance.getUrlString())\n
if software_release_document is None:\n
raise NotImplemnetedError(\'Software Release %r not ready yet\' % instance.getUrlString())\n
if delivery is None:\n
new_delivery = context.Instance_createSalePackingList(state_change, portal.restrictedTraverse(update_service_relative_url), software_release_document)\n
<value> <string encoding="cdata"><![CDATA[
instance = context\n
portal = instance.getPortalObject()\n
portal_workflow = portal.portal_workflow\n
\n
if portal_workflow.isTransitionPossible(instance, \'converge\'):\n
instance.converge()\n
\n
slap_state = instance.getSlapState()\n
\n
if slap_state == \'draft\':\n
# Nothing to do except converging\n
pass\n
else:\n
new_delivery = delivery.Base_createCloneDocument(batch_mode=1)\n
new_delivery.edit(start_date=DateTime(), stop_date=DateTime(), causality_value=None)\n
delivery_line = new_delivery.contentValues(portal_type="Sale Packing List Line")[0]\n
aggregate_list = delivery_line.getAggregateList(portal_type=[\'Slave Instance\', \'Software Instance\', \'Hosting Subscription\', \'Computer Partition\'])\n
aggregate_list.append(software_release_document.getRelativeUrl())\n
delivery_line.edit(resource=update_service_relative_url, aggregate_list=aggregate_list)\n
new_delivery.confirm()\n
new_delivery.start()\n
new_delivery.stop()\n
new_delivery.deliver()\n
new_delivery.startBuilding()\n
</string> </value>
started = "start_requested"\n
stopped = "stop_requested"\n
destroyed = "destroy_requested"\n
assert slap_state in [started, stopped, destroyed]\n
\n
previous_length = instance.getInvoicingSynchronizationPointer(1)\n
history_list = portal_workflow.getInfoFor(ob=instance, name=\'history\', wf_id=\'instance_slap_interface_workflow\')\n
history_length = len(history_list)\n
history_entry = history_list[previous_length-1]\n
\n
# no divergence if no new history entry\n
assert previous_length != history_length\n
\n
setup_quantity = 0\n
update_quantity = 0\n
destroy_quantity = 0\n
\n
current_delivery = instance.getCausalityValue()\n
if current_delivery is None:\n
# No previous packing list, so, one setup should be created\n
# Drop all useless draft line\n
i_in_draft_state = True\n
i = 0\n
while i_in_draft_state:\n
checking_history_entry = history_list[i]\n
previous_state = checking_history_entry[\'slap_state\']\n
if previous_state != \'draft\':\n
i_in_draft_state = False\n
previous_length = i\n
else:\n
setup_quantity += 1\n
i += 1\n
\n
if slap_state == destroyed:\n
# Check if previous pointer was already in destroyed state\n
previous_state = history_entry[\'slap_state\']\n
if previous_state != destroyed:\n
# Let\'s create destroyed packing list\n
destroy_quantity = 1\n
\n
# 1 = entry to set document in draft state\n
update_quantity = history_length - previous_length - setup_quantity - destroy_quantity\n
\n
# Time to create the PL\n
delivery_template = portal.restrictedTraverse(\n
portal.portal_preferences.getPreferredInstanceDeliveryTemplate())\n
delivery = delivery_template.Base_createCloneDocument(batch_mode=1)\n
\n
hosting_subscription = instance.getSpecialiseValue(portal_type="Hosting Subscription")\n
person = hosting_subscription.getDestinationSectionValue(portal_type="Person")\n
\n
delivery.edit(\n
title="%s API usage" % instance.getReference(),\n
destination_section=person.getRelativeUrl(),\n
destination_decision=person.getRelativeUrl(),\n
destination=person.getRelativeUrl(),\n
start_date=history_entry[\'time\'],\n
stop_date=portal_workflow.getInfoFor(ob=instance, name=\'time\', wf_id=\'instance_slap_interface_workflow\'),\n
)\n
line_edit_kw = {\n
\'aggregate_value_list\': [instance, hosting_subscription],\n
}\n
\n
if setup_quantity:\n
delivery_line_template = portal.restrictedTraverse(\n
portal.portal_preferences.getPreferredInstanceSetupMovementTemplate())\n
line = delivery_line_template.Base_createCloneDocument(batch_mode=1,\n
destination=delivery)\n
line.edit(\n
quantity=1,\n
title="%s setup %s" % (instance.getReference(), setup_quantity),\n
**line_edit_kw\n
)\n
\n
if update_quantity > 0:\n
delivery_line_template = portal.restrictedTraverse(\n
portal.portal_preferences.getPreferredInstanceUpdateMovementTemplate())\n
line = delivery_line_template.Base_createCloneDocument(batch_mode=1,\n
destination=delivery)\n
line.edit(\n
quantity=update_quantity,\n
title="%s updated %i times" % (instance.getReference(), update_quantity),\n
**line_edit_kw\n
)\n
\n
if destroy_quantity:\n
delivery_line_template = portal.restrictedTraverse(\n
portal.portal_preferences.getPreferredInstanceDestroyMovementTemplate())\n
line = delivery_line_template.Base_createCloneDocument(batch_mode=1,\n
destination=delivery)\n
line.edit(\n
quantity=destroy_quantity,\n
title="%s destroyed" % instance.getReference(),\n
**line_edit_kw\n
)\n
\n
delivery.confirm()\n
delivery.start()\n
delivery.stop()\n
delivery.deliver()\n
delivery.startBuilding()\n
\n
instance.edit(\n
invoicing_synchronization_pointer=history_length,\n
causality_value=delivery,\n
)\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Instance_changePromiseParameter</string> </value>
<value> <string>Instance_solveInvoicingGeneration</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -95,6 +95,10 @@
<list>
<string>my_preferred_open_sale_order_line_template</string>
<string>my_preferred_open_sale_order_template</string>
<string>my_preferred_instance_update_movement_template</string>
<string>my_preferred_instance_destroy_movement_template</string>
<string>my_preferred_instance_setup_movement_template</string>
<string>my_preferred_instance_delivery_template</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_instance_delivery_template</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_string_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 Instance Delivery Template</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_instance_destroy_movement_template</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_string_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 Instance Update Movement Template</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_instance_setup_movement_template</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_string_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 Instance Setup Movement Template</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_instance_update_movement_template</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_string_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 Instance Update Movement Template</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2012 Nexedi SA and Contributors. All Rights Reserved.
#
##############################################################################
import transaction
import functools
from Products.ERP5Type.tests.utils import createZODBPythonScript
from Products.SlapOS.tests.testSlapOSMixin import \
testSlapOSMixin
from DateTime import DateTime
def simulateInstance_solveInvoicingGeneration(func):
@functools.wraps(func)
def wrapped(self, *args, **kwargs):
script_name = 'Instance_solveInvoicingGeneration'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""portal_workflow = context.portal_workflow
portal_workflow.doActionFor(context, action='edit_action', comment='Visited by Instance_solveInvoicingGeneration') """ )
transaction.commit()
try:
func(self, *args, **kwargs)
finally:
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
transaction.commit()
return wrapped
class TestInstanceInvoicingAlarm(testSlapOSMixin):
def afterSetUp(self):
super(TestInstanceInvoicingAlarm, self).afterSetUp()
self.software_instance_request_kw = dict(
software_release=self.generateNewSoftwareReleaseUrl(),
software_type=self.generateNewSoftwareType(),
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
)
self.slave_instance_request_kw = dict(
software_release=self.generateNewSoftwareReleaseUrl(),
software_type=self.generateNewSoftwareType(),
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=True,
)
def beforeTearDown(self):
transaction.abort()
def test_noSaleOrderPackingList_newSoftwareInstance(self):
"""
Be sure no delivery is created synchronously (break old code behaviour)
"""
instance = self.portal.software_instance_module.template_software_instance\
.Base_createCloneDocument(batch_mode=1)
instance.edit(title="TESTSI-%s" % self.generateNewId())
instance.requestStart(**self.software_instance_request_kw)
self.assertEqual(None, instance.getCausalityValue())
def test_noSaleOrderPackingList_newSlaveInstance(self):
"""
Be sure no delivery is created synchronously (break old code behaviour)
"""
instance = self.portal.software_instance_module.template_slave_instance\
.Base_createCloneDocument(batch_mode=1)
instance.edit(title="TESTSI-%s" % self.generateNewId())
instance.requestStart(**self.slave_instance_request_kw)
self.tic()
self.assertEqual(None, instance.getCausalityValue())
@simulateInstance_solveInvoicingGeneration
def test_alarm_findSoftwareInstance(self):
new_id = self.generateNewId()
instance = self.portal.software_instance_module.newContent(
portal_type='Software Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
ssl_certificate="foo",
ssl_key="bar",
)
self.tic()
self.portal.portal_alarms\
.slapos_instance_invoicing\
.activeSense()
self.tic()
self.assertEqual(
'Visited by Instance_solveInvoicingGeneration',
instance.workflow_history['edit_workflow'][-1]['comment'])
@simulateInstance_solveInvoicingGeneration
def test_alarm_findSlaveInstance(self):
new_id = self.generateNewId()
instance = self.portal.software_instance_module.newContent(
portal_type='Slave Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
)
self.tic()
self.portal.portal_alarms\
.slapos_instance_invoicing\
.activeSense()
self.tic()
self.assertEqual(
'Visited by Instance_solveInvoicingGeneration',
instance.workflow_history['edit_workflow'][-1]['comment'])
def test_solved_instance(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
)
request_time = DateTime('2012/01/01')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Simulated request instance',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroyed',
'time': request_time,
'action': 'request_instance'
})
self.portal.portal_workflow._jumpToStateFor(instance, 'solved')
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertEqual(None, instance.getCausalityValue())
def test_instance_in_draft_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Stay in draft',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'draft',
'time': DateTime(),
'action': 'foo_transition'
})
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertEqual(None, instance.getCausalityValue())
def test_instance_in_unknown_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Stay in unknown state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'unknown_state',
'time': DateTime(),
'action': 'foo_transition'
})
self.assertRaises(AssertionError, instance.Instance_solveInvoicingGeneration)
def test_instance_in_early_destroyed_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
start_date = instance.workflow_history\
['instance_slap_interface_workflow'][0]['time']
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in destroyed state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': stop_date,
'action': 'foo_transition'
})
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(2, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 2)
self.check_instance_movement(setup_line, instance, subscription, 1)
self.check_instance_movement(destroy_line, instance, subscription, 1)
def check_instance_delivery(self, delivery, start_date, stop_date,
person, line_count):
packing_list_line = delivery.contentValues(
portal_type='Sale Packing List Line')
self.assertEqual(len(packing_list_line), line_count)
self.assertEqual(delivery.getDestinationValue(), person)
self.assertEqual(delivery.getDestinationSectionValue(), person)
self.assertEqual(delivery.getDestinationDecisionValue(), person)
self.assertEqual(delivery.getStopDate(), stop_date)
self.assertEqual(delivery.getStartDate(), start_date)
self.assertEqual(delivery.getSimulationState(), 'delivered')
self.assertEqual(delivery.getCausalityState(), 'building')
# Hardcoded, but, no idea how to not make it...
setup_line = ([None]+[x for x in packing_list_line \
if x.getResource() == 'service_module/slapos_instance_setup'])[-1]
destroy_line = ([None]+[x for x in packing_list_line \
if x.getResource() == 'service_module/slapos_instance_cleanup'])[-1]
update_line = ([None]+[x for x in packing_list_line \
if x.getResource() == 'service_module/slapos_instance_update'])[-1]
return setup_line, update_line, destroy_line
def check_instance_movement(self, movement, instance,
subscription, quantity):
self.assertEqual(movement.getQuantity(), quantity)
self.assertSameSet(movement.getAggregateValueList(),
[instance, subscription])
self.assertEqual(len(movement.contentValues()), 0)
def test_instance_create_non_destroyed_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
start_date = instance.workflow_history\
['instance_slap_interface_workflow'][0]['time']
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in start state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'start_requested',
'time': stop_date,
'action': 'foo_transition'
})
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(2, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 1)
self.check_instance_movement(setup_line, instance, subscription, 1)
def test_instance_create_non_destroyed_with_update_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
start_date = instance.workflow_history\
['instance_slap_interface_workflow'][0]['time']
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-1,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-2,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in start state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'start_requested',
'time': stop_date,
'action': 'foo_transition'
})
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(4, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 2)
self.check_instance_movement(setup_line, instance, subscription, 1)
self.check_instance_movement(update_line, instance, subscription, 2)
def test_instance_create_destroyed_with_update_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
start_date = instance.workflow_history\
['instance_slap_interface_workflow'][0]['time']
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-1,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-2,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in destroy state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': stop_date,
'action': 'foo_transition'
})
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(4, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 3)
self.check_instance_movement(setup_line, instance, subscription, 1)
self.check_instance_movement(update_line, instance, subscription, 1)
self.check_instance_movement(destroy_line, instance, subscription, 1)
def test_instance_update_non_destroyed_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
previous_delivery = self.portal.sale_packing_list_module.newContent(
portal_type='Sale Packing List')
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
invoicing_synchronization_pointer=2,
causality_value=previous_delivery,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-1,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-2,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in start state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'start_requested',
'time': stop_date,
'action': 'foo_transition'
})
start_date = stop_date-1
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(4, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 1)
self.check_instance_movement(update_line, instance, subscription, 2)
def test_instance_update_destroyed_state(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
previous_delivery = self.portal.sale_packing_list_module.newContent(
portal_type='Sale Packing List')
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
invoicing_synchronization_pointer=2,
causality_value=previous_delivery,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-1,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'foo_state',
'time': stop_date-2,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in start state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': stop_date,
'action': 'foo_transition'
})
start_date = stop_date-1
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(4, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 2)
self.check_instance_movement(update_line, instance, subscription, 1)
self.check_instance_movement(destroy_line, instance, subscription, 1)
def test_instance_update_already_destroyed(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
subscription = self.portal.hosting_subscription_module\
.template_hosting_subscription.Base_createCloneDocument(batch_mode=1)
subscription.edit(
reference='TESTHS-%s' % self.generateNewId(),
destination_section_value=person)
instance = self.portal.software_instance_module\
.template_slave_instance.Base_createCloneDocument(batch_mode=1)
previous_delivery = self.portal.sale_packing_list_module.newContent(
portal_type='Sale Packing List')
new_id = self.generateNewId()
instance.edit(
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
specialise_value=subscription,
invoicing_synchronization_pointer=2,
causality_value=previous_delivery,
)
self.portal.portal_workflow._jumpToStateFor(instance, 'diverged')
stop_date = DateTime('2222/11/15')
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': stop_date-1,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Update',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': stop_date-2,
'action': 'foo_transition'
})
instance.workflow_history['instance_slap_interface_workflow'].append({
'comment':'Directly in start state',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'slap_state': 'destroy_requested',
'time': stop_date,
'action': 'foo_transition'
})
start_date = stop_date-1
instance.Instance_solveInvoicingGeneration()
self.assertEqual(instance.getCausalityState(), 'solved')
self.assertNotEqual(None, instance.getCausalityValue())
self.assertEqual(4, instance.getInvoicingSynchronizationPointer())
delivery = instance.getCausalityValue()
setup_line, update_line, destroy_line =\
self.check_instance_delivery(delivery, start_date, stop_date, person, 1)
self.check_instance_movement(update_line, instance, subscription, 2)
# Copyright (c) 2012 Nexedi SA and Contributors. All Rights Reserved.
from Products.SlapOS.tests.testSlapOSMixin import \
testSlapOSMixin
import transaction
class TestSlapOSAccountingInteractionWorkflow(testSlapOSMixin):
def beforeTearDown(self):
transaction.abort()
def test_SlaveInstance_changePromise(self):
new_id = self.generateNewId()
instance = self.portal.software_instance_module.newContent(
portal_type='Slave Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
)
instance.validate()
self.assertEqual(instance.getCausalityState(), 'diverged')
request_kw = dict(
software_release='http://example.org',
software_type='http://example.org',
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=True,
)
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.requestStop(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.requestStart(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.bang(comment='Test bang interaction', bang_tree=False)
self.assertEqual(instance.getCausalityState(), 'diverged')
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.requestDestroy(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
def test_SlaveInstance_changePromiseInDivergeState(self):
new_id = self.generateNewId()
instance = self.portal.software_instance_module.newContent(
portal_type='Slave Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
)
instance.validate()
self.assertEqual(instance.getCausalityState(), 'diverged')
request_kw = dict(
software_release='http://example.org',
software_type='http://example.org',
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=True,
)
instance.requestStop(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
def test_SoftwareInstance_changePromise(self):
new_id = self.generateNewId()
instance = self.portal.software_instance_module.newContent(
portal_type='Software Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
ssl_certificate="foo",
ssl_key="bar",
)
instance.validate()
self.assertEqual(instance.getCausalityState(), 'diverged')
request_kw = dict(
software_release='http://example.org',
software_type='http://example.org',
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
)
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.requestStop(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.requestStart(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.bang(comment='Test bang interaction', bang_tree=False)
self.assertEqual(instance.getCausalityState(), 'diverged')
instance.converge()
self.assertEqual(instance.getCausalityState(), 'solved')
instance.requestDestroy(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
def test_SoftwareInstance_changePromiseInDivergedState(self):
new_id = self.generateNewId()
instance = self.portal.software_instance_module.newContent(
portal_type='Software Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
destination_reference="TESTINST-%s" % new_id,
ssl_certificate="foo",
ssl_key="bar",
)
instance.validate()
self.assertEqual(instance.getCausalityState(), 'diverged')
request_kw = dict(
software_release='http://example.org',
software_type='http://example.org',
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
)
instance.requestStop(**request_kw)
self.assertEqual(instance.getCausalityState(), 'diverged')
......@@ -28,7 +28,7 @@
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>Instance_changePromiseState</string>
<string>Base_diverge</string>
</list>
</value>
</item>
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>change_instance_promise_state</string> </value>
<value> <string>Instance_changePromiseState</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
......@@ -59,7 +59,7 @@
<string>requestStart</string>
<string>requestStop</string>
<string>requestDestroy</string>
<string>allocatePartition</string>
<string>bang</string>
</list>
</value>
</item>
......
......@@ -51,7 +51,8 @@
<item>
<key> <string>_body</string> </key>
<value> <string>document = state_change["object"]\n
document.diverge()\n
if document.getPortalObject().portal_workflow.isTransitionPossible(document, \'diverge\'):\n
document.diverge()\n
</string> </value>
</item>
<item>
......
......@@ -33,7 +33,7 @@
<item>
<key> <string>guard</string> </key>
<value>
<none/>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
......@@ -59,4 +59,21 @@
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Guard" module="Products.DCWorkflow.Guard"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
46
\ No newline at end of file
47
\ No newline at end of file
organisation_module/slapos
sale_packing_list_module/slapos_accounting_instance_delivery_template
sale_packing_list_module/slapos_accounting_instance_delivery_line_template
sale_packing_list_module/slapos_accounting_instance_delivery_line_template/**
service_module/slapos_instance_cleanup
service_module/slapos_instance_setup
service_module/slapos_instance_update
\ No newline at end of file
......@@ -18,6 +18,7 @@ open_sale_order_module/slapos_accounting_open_sale_order_template
open_sale_order_module/template_open_sale_order
organisation_module/slapos
organisation_module/slapos/bank_account
portal_alarms/slapos_instance_invoicing
portal_alarms/slapos_manage_building_calculating_delivery
portal_alarms/slapos_request_update_hosting_subscription_open_sale_order
portal_alarms/slapos_trigger_build
......@@ -29,9 +30,15 @@ portal_rules/slapos_invoice_simulation_rule
portal_rules/slapos_invoice_simulation_rule/**
portal_rules/slapos_subscription_item_rule
portal_rules/slapos_subscription_item_rule/**
sale_packing_list_module/slapos_accounting_instance_delivery_line_template
sale_packing_list_module/slapos_accounting_instance_delivery_line_template/**
sale_packing_list_module/slapos_accounting_instance_delivery_template
sale_trade_condition_module/slapos_trade_condition
sale_trade_condition_module/slapos_trade_condition/1
service_module/slapos_discount
service_module/slapos_instance_cleanup
service_module/slapos_instance_setup
service_module/slapos_instance_subscription
service_module/slapos_instance_subscription/default_ssl
service_module/slapos_instance_update
service_module/slapos_tax
\ No newline at end of file
Slave Instance | causality
Software Instance | causality
\ No newline at end of file
Hosting Subscription | SlapOSAccountingHostingSubscriptionConstraint
Slave Instance | InstanceAccountingSynchronisation
Software Instance | InstanceAccountingSynchronisation
\ No newline at end of file
Hosting Subscription | slapos_accounting_interaction_workflow
Sale Packing List | slapos_accounting_interaction_workflow
Slave Instance | slapos_accounting_interaction_workflow
Slave Instance | slapos_api_invoicing_workflow
Software Instance | slapos_accounting_interaction_workflow
Software Instance | slapos_api_invoicing_workflow
Subscription Item Root Simulation Rule | edit_workflow
Subscription Item Root Simulation Rule | rule_validation_workflow
\ No newline at end of file
SlapOSAccountingSystemPreference
SlapOSAccountingHostingSubscriptionConstraint
InstanceAccountingSynchronisation
\ No newline at end of file
testSlapOSAccountingConstraint
testSlapOSAccountingDefaultSubscriptionItemRule
testSlapOSAccountingSlapOSManageBuildingCalculatingDelivery
testSlapOSAccountingInteractionWorkflow
testSlapOSAccountingSlapOSRequestUpdateHostingSubscriptionOpenSaleOrderAlarm
testSlapOSAccountingSlapOSTriggerBuildAlarm
testSlapOSAccountingInstanceInvoicingAlarm
\ No newline at end of file
......@@ -97,14 +97,30 @@
<key> <string>preferred_instance_cleanup_resource</string> </key>
<value> <string>service_module/vifib_instance_cleanup</string> </value>
</item>
<item>
<key> <string>preferred_instance_delivery_template</string> </key>
<value> <string>sale_packing_list_module/slapos_accounting_instance_delivery_template</string> </value>
</item>
<item>
<key> <string>preferred_instance_destroy_movement_template</string> </key>
<value> <string>sale_packing_list_module/slapos_accounting_instance_delivery_line_template/destroy</string> </value>
</item>
<item>
<key> <string>preferred_instance_hosting_resource</string> </key>
<value> <string>service_module/vifib_instance_hosting</string> </value>
</item>
<item>
<key> <string>preferred_instance_setup_movement_template</string> </key>
<value> <string>sale_packing_list_module/slapos_accounting_instance_delivery_line_template/setup</string> </value>
</item>
<item>
<key> <string>preferred_instance_setup_resource</string> </key>
<value> <string>service_module/vifib_instance_setup</string> </value>
</item>
<item>
<key> <string>preferred_instance_update_movement_template</string> </key>
<value> <string>sale_packing_list_module/slapos_accounting_instance_delivery_line_template/update</string> </value>
</item>
<item>
<key> <string>preferred_instance_update_resource</string> </key>
<value> <string>service_module/vifib_instance_update</string> </value>
......
242
\ No newline at end of file
243
\ No newline at end of file
94
\ No newline at end of file
95
\ No newline at end of file
<base_category_list>
<portal_type id="Slave Instance">
<item>causality</item>
</portal_type>
<portal_type id="Software Installation">
<item>causality</item>
</portal_type>
<portal_type id="Software Instance">
<item>causality</item>
</portal_type>
</base_category_list>
\ No newline at end of file
......@@ -3,16 +3,8 @@
<type>Purchase Packing List</type>
<workflow>slapos_open_order_interaction_workflow</workflow>
</chain>
<chain>
<type>Slave Instance</type>
<workflow>instance_accounting_slap_interaction_workflow</workflow>
</chain>
<chain>
<type>Software Installation</type>
<workflow>installation_accounting_slap_interaction_workflow</workflow>
</chain>
<chain>
<type>Software Instance</type>
<workflow>instance_accounting_slap_interaction_workflow</workflow>
</chain>
</workflow_chain>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interaction" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interactions</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Scripts" module="Products.DCWorkflow.Scripts"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>scripts</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>return\n
instance = state_change[\'object\']\n
hosting_subscription = instance.getSpecialiseValue(portal_type="Hosting Subscription")\n
person_relative_url = hosting_subscription.getDestinationSection()\n
portal = instance.getPortalObject()\n
isTransitionPossible = portal.portal_workflow.isTransitionPossible\n
\n
# Check if instance is allocated\n
partition = instance.getAggregate(portal_type="Computer Partition")\n
# Get current delivery\n
delivery = instance.getCausalityValue(portal_type=["Sale Order", "Sale Packing List"])\n
# Get latest workflow transition\n
state = instance.getSlapState()\n
started = "start_requested"\n
stopped = "stop_requested"\n
destroyed = "destroy_requested"\n
assert state in [started, stopped, destroyed]\n
# Get all needed services\n
setup_service_relative_url = portal.portal_preferences.getPreferredInstanceSetupResource()\n
setup_service = portal.restrictedTraverse(setup_service_relative_url)\n
hosting_service_relative_url = portal.portal_preferences.getPreferredInstanceHostingResource()\n
hosting_service = portal.restrictedTraverse(hosting_service_relative_url)\n
cleanup_service_relative_url = portal.portal_preferences.getPreferredInstanceCleanupResource()\n
cleanup_service = portal.restrictedTraverse(cleanup_service_relative_url)\n
\n
sale_order_portal_type = "Sale Order"\n
sale_order_line_portal_type = "Sale Order Line"\n
\n
if (partition is None):\n
# If partition is not allocated yet, only a sale order can be instanciated\n
if (delivery is None):\n
assert state != destroyed\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
specialise=\'sale_trade_condition_module/vifib_trade_condition\',\n
source="organisation_module/vifib_internet",\n
source_section="organisation_module/vifib_internet",\n
price_currency="currency_module/EUR",\n
)\n
sale_order_line = sale_order.newContent(\n
portal_type=sale_order_line_portal_type,\n
resource=setup_service_relative_url,\n
quantity_unit="unit/piece",\n
quantity=1,\n
price=setup_service.getSaleSupplyLineBasePrice(),\n
aggregate_value_list=[instance, hosting_subscription],\n
)\n
sale_order.plan()\n
instance.edit(causality_value=sale_order)\n
\n
else:\n
assert delivery.getPortalType() == sale_order_portal_type\n
if state == destroyed:\n
# Can destroy the instance before allocation\n
delivery.cancel()\n
else:\n
assert delivery is not None\n
\n
if (delivery.getPortalType() == "Sale Order" and delivery.getSimulationState() == "confirmed"):\n
if (state == stopped):\n
# Try to find the setup packing list created from the open order to\n
# associate it instead of the sale order\n
packing_list = delivery.getCausalityRelatedValue(portal_type="Sale Packing List")\n
if (packing_list is not None):\n
instance.edit(causality_value=packing_list)\n
else:\n
software_release_document = instance.Base_getSoftwareReleaseDocument(instance.getUrlString())\n
if software_release_document is None:\n
raise NotImplemnetedError(\'Software Release %r not ready yet\' % instance.getUrlString())\n
# Create a new packing list from scratch\n
if (state == started):\n
service_relative_url = hosting_service_relative_url\n
service = hosting_service\n
elif (state == destroyed):\n
service_relative_url = cleanup_service_relative_url\n
service = cleanup_service\n
\n
packing_list = context.Instance_createSalePackingList(state_change, service, software_release_document)\n
instance.edit(causality_value=packing_list)\n
\n
if (state == started):\n
packing_list.confirm()\n
elif (state == destroyed):\n
packing_list.confirm()\n
packing_list.startBuilding()\n
\n
elif delivery.getPortalType() == "Sale Packing List":\n
line_list = delivery.contentValues(portal_type="Sale Packing List Line")\n
assert len(line_list) == 1\n
line = line_list[0]\n
service_relative_url = line.getResource()\n
\n
def letsclone(service_relative_url):\n
software_release_document = instance.Base_getSoftwareReleaseDocument(instance.getUrlString())\n
if software_release_document is None:\n
raise NotImplementedError(\'Software Release %r not ready yet\' % instance.getUrlString())\n
new_delivery = delivery.Base_createCloneDocument(batch_mode=1)\n
new_delivery.edit(start_date=DateTime(), stop_date=DateTime(), causality_value=None)\n
delivery_line = new_delivery.contentValues(portal_type="Sale Packing List Line")[0]\n
aggregate_list = delivery_line.getAggregateList(portal_type=[\'Slave Instance\', \'Software Instance\', \'Hosting Subscription\', \'Computer Partition\'])\n
aggregate_list.append(software_release_document.getRelativeUrl())\n
delivery_line.edit(resource=service_relative_url, aggregate_list=aggregate_list)\n
return new_delivery\n
\n
new_delivery = None\n
if (service_relative_url == setup_service_relative_url):\n
if (state == started):\n
new_delivery = letsclone(hosting_service_relative_url)\n
new_delivery.confirm()\n
instance.edit(causality_value=new_delivery)\n
elif (state == stopped):\n
pass\n
elif (state == destroyed):\n
new_delivery = letsclone(cleanup_service_relative_url)\n
new_delivery.confirm()\n
instance.edit(causality_value=new_delivery)\n
else:\n
raise NotImplementedError\n
\n
elif (service_relative_url == hosting_service_relative_url):\n
if (state == started):\n
if (delivery.getSimulationState() == \'stopped\'):\n
delivery.deliver()\n
new_delivery = letsclone(hosting_service_relative_url)\n
new_delivery.confirm()\n
instance.edit(causality_value=new_delivery)\n
elif (state == stopped):\n
if isTransitionPossible(delivery, "stop"):\n
delivery.stop()\n
elif (state == destroyed):\n
if isTransitionPossible(delivery, "stop"):\n
delivery.stop()\n
if isTransitionPossible(delivery, "deliver"):\n
delivery.deliver()\n
new_delivery = letsclone(cleanup_service_relative_url)\n
new_delivery.confirm()\n
instance.edit(causality_value=new_delivery)\n
else:\n
raise NotImplementedError\n
elif (service_relative_url == cleanup_service_relative_url):\n
raise NotImplementedError, "Not update should be allowed"\n
else:\n
raise NotImplementedError\n
\n
if new_delivery is not None:\n
new_delivery.startBuilding()\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>Instance_changePromiseState</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Variables" module="Products.DCWorkflow.Variables"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variables</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Worklists" module="Products.DCWorkflow.Worklists"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_mapping</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>worklists</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
38
\ No newline at end of file
39
\ No newline at end of file
Slave Instance | causality
Software Installation | causality
\ No newline at end of file
Software Instance | causality
\ No newline at end of file
Purchase Packing List | slapos_open_order_interaction_workflow
Slave Instance | instance_accounting_slap_interaction_workflow
Software Installation | installation_accounting_slap_interaction_workflow
\ No newline at end of file
Software Instance | instance_accounting_slap_interaction_workflow
\ No newline at end of file
installation_accounting_slap_interaction_workflow
instance_accounting_slap_interaction_workflow
slapos_open_order_interaction_workflow
\ No newline at end of file
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