Commit 5c09e2e2 authored by Julien Muchembled's avatar Julien Muchembled

Simulation: splitted expand, performance improvements and bugfixes

All interactions and activity tags are reviewed to fix bugs like duplicated
root applied rules, and also reduces the amount of duplicated/useless work, e.g:
- Simulation trees are not expanded anymore when simulated objects are modified.
- 'expand' activities are merged (i.e. dropped) with any other 'expand' activity
  for an ancestor.
New implementation exposes new API that hides much complexity to the developper
about activity dependencies.

By default, expand() now automatically defers any work if the current
transaction takes too long time. This method also gains a parameter to
explicitely choose when to expand, which is often important in unit tests or
solvers. In particular, when postponing work, it takes care of setting proper
activity dependencies.
- If you have any code requiring to expand everything immediately, you'll have
  to replace 'expand()' by 'expand(expand_policy="immediate")'.
- On the contrary, you should replace any 'activate().expand()' by
  'expand(expand_policy="deferred")'.
expand() still accepts activity parameters for any extra needs.

In causality workflow, 'building' state is clarified and now means
« delivery may diverge but we can't know now ». A delivery remains in draft
as long as it does not contain any movement built from simulation.
After init/clone/builder/etc. scripts used to call 'startBuilding' &
'updateCausalityState': this calls must be removed since only
SimulatedDeliveryBuilder should take care of move to 'building' state and
workflows now triggers 'updateCausalityState'.

Disguised interactions have been unhardcoded and either deleted, or moved to
appropriate interaction workflows, which have been reorganized. Those
that triggers update of portal_workflow can be easily customized or disabled.

New API:
- updateSimulation() on deliveries and subscription items. It takes care of
  creating root applied rule, expanding and reindexing parts of simulation
  trees. It somehow replaces:
  - Delivery_updateSimulation
  - Delivery_updateAppliedRule
  - Delivery.applyToDeliveryRelatedMovement
  - Delivery.updateAppliedRule
  - Delivery.expand
  - Delivery.expandRuleRelatedToMovement
  - SubscriptionItem.expand
  - SubscriptionItem.updateAppliedRule
- Delivery.localBuild() is the new way to do local building and replaces
  Delivery_expandAndBuild. Private method Delivery._localBuild replaces
  Delivery_buildOnComposedDocument.
- Simulation Movements that are being built by a builder are reindexed with
  the following tag: 'built:<delivery_path>'. Any after_path_and_method_id
  dependency against 'related_simulation_movement_path_list' and reindexing
  methods should be replaced by this after_tag.

After builder scripts used to confirm the delivery in a separate activity,
which was useless.
parent fb246bec
...@@ -56,11 +56,6 @@ context.setSourceReference(None)\n ...@@ -56,11 +56,6 @@ context.setSourceReference(None)\n
context.setReference(None)\n context.setReference(None)\n
context.setDestinationReference(None)\n context.setDestinationReference(None)\n
context.setSolver(None)\n context.setSolver(None)\n
\n
# Initialize Causality Workflow\n
if hasattr(context, \'startBuilding\'):\n
context.startBuilding()\n
context.updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>AccountingRuleCell_getRuleReference</string> </value> <value> <string>AccountingTransaction_getRuleReference</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -50,23 +50,15 @@ ...@@ -50,23 +50,15 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>from Products.CMFCore.utils import getToolByName\n <value> <string>preference_tool = context.getPortalObject().portal_preferences\n
\n context.edit(\n
transaction = context\n
preference_tool = getToolByName(context, \'portal_preferences\')\n
\n
transaction.edit (\n
source_section = preference_tool.getPreferredAccountingTransactionSourceSection(),\n source_section = preference_tool.getPreferredAccountingTransactionSourceSection(),\n
resource = preference_tool.getPreferredAccountingTransactionCurrency())\n resource = preference_tool.getPreferredAccountingTransactionCurrency())\n
\n
if hasattr(transaction, \'startBuilding\') :\n
transaction.startBuilding()\n
transaction.updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>*args, **kw</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>SaleInvoiceTransaction_getRuleReference</string> </value> <value> <string>Invoice_getRuleReference</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -57,13 +57,6 @@ payment_transaction = context\n ...@@ -57,13 +57,6 @@ payment_transaction = context\n
# initialize accounting_workflow to planned state\n # initialize accounting_workflow to planned state\n
if payment_transaction.getSimulationState() == "draft":\n if payment_transaction.getSimulationState() == "draft":\n
payment_transaction.plan(comment=translateString("Initialised by Delivery Builder."))\n payment_transaction.plan(comment=translateString("Initialised by Delivery Builder."))\n
\n
# First set the payment transaction in the building state on the causality workflow\n
payment_transaction.startBuilding()\n
\n
# Then an activity should put the causality state in diverged or solved\n
payment_transaction.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\'))).updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?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 \'default_invoice_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PurchaseInvoiceTransaction_getRuleReference</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>delivery = state_change[\'object\']\n
delivery.Delivery_expandAndBuild()\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>Delivery_Build</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>state_change[\'object\'].Delivery_updateSimulation()\n <value> <string>state_change[\'object\'].localBuild()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Delivery_createRule</string> </value> <value> <string>Delivery_localBuild</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Delivery_Build</string> </value> <value> <string>Delivery_localBuild</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Delivery_updateSimulation</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Delivery_Build</string> </value> <value> <string>Delivery_localBuild</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
<key> <string>tested_property</string> </key> <key> <string>tested_property</string> </key>
<value> <value>
<tuple> <tuple>
<string>specialise</string>
<string>source_section</string> <string>source_section</string>
<string>destination_section</string> <string>destination_section</string>
<string>source_payment</string> <string>source_payment</string>
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
<key> <string>tested_property</string> </key> <key> <string>tested_property</string> </key>
<value> <value>
<tuple> <tuple>
<string>specialise</string>
<string>source_section</string> <string>source_section</string>
<string>destination_section</string> <string>destination_section</string>
<string>source_payment</string> <string>source_payment</string>
......
...@@ -71,9 +71,11 @@ for builder_id in builder_id_list:\n ...@@ -71,9 +71,11 @@ for builder_id in builder_id_list:\n
serialization_tag = \'build:%s\' % delivery_portal_type\n serialization_tag = \'build:%s\' % delivery_portal_type\n
index_tag = \'index:%s\' % delivery_portal_type\n index_tag = \'index:%s\' % delivery_portal_type\n
after_tag = index_tag\n after_tag = index_tag\n
# depend on reindexing so that select methods\n
# do not return movements that are already built\n
after_method_id = (\'recursiveImmediateReindexObject\',\n after_method_id = (\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\',\n \'immediateReindexObject\',\n
\'Delivery_updateAppliedRule\')\n \'_updateSimulation\')\n
activate_kw = dict(tag=index_tag)\n activate_kw = dict(tag=index_tag)\n
builder.activate(\n builder.activate(\n
serialization_tag=serialization_tag,\n serialization_tag=serialization_tag,\n
......
...@@ -54,14 +54,6 @@ ...@@ -54,14 +54,6 @@
the new Invoice.\n the new Invoice.\n
"""\n """\n
from Products.ERP5Type.Message import translateString\n from Products.ERP5Type.Message import translateString\n
try:\n
from Products.CMFCore.WorkflowCore import WorkflowException\n
except ImportError:\n
# WorkflowException has not always been allowed in restricted\n
# environment, in this case, make sure WorkflowException is \n
# defined \n
class WorkflowException(Exception):\n
pass\n
\n \n
if related_simulation_movement_path_list is None:\n if related_simulation_movement_path_list is None:\n
raise RuntimeError, \'related_simulation_movement_path_list is missing. Update ERP5 Product.\'\n raise RuntimeError, \'related_simulation_movement_path_list is missing. Update ERP5 Product.\'\n
...@@ -80,26 +72,10 @@ if not invoice.hasTitle() and related_packing_list.hasTitle():\n ...@@ -80,26 +72,10 @@ if not invoice.hasTitle() and related_packing_list.hasTitle():\n
\n \n
# initialize accounting_workflow to confirmed state\n # initialize accounting_workflow to confirmed state\n
if invoice.getSimulationState() == \'draft\':\n if invoice.getSimulationState() == \'draft\':\n
try :\n invoice.Delivery_confirm()\n
context.getPortalObject().portal_workflow.doActionFor(\n else:\n
invoice, \'confirm_action\',\n # call builder just same as after script of \'confirm\' transition\n
comment=translateString(\'Initialised by Delivery Builder.\'),\n invoice.localBuild()\n
skip_period_validation=1)\n
except WorkflowException, e:\n
# The user cannot pass the transition, it\'s OK\n
pass\n
\n
if invoice.getSimulationState() == \'draft\':\n
# call the workflow method, if the user cannot perform this operation.\n
invoice.confirm(comment=translateString(\'Initialised by Delivery Builder.\'),)\n
\n
\n
# First set the invoice in the building state on the causality workflow\n
invoice.startBuilding()\n
\n
# Then an activity should put the causality state in diverged or solved\n
invoice.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\'))).updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -50,64 +50,12 @@ ...@@ -50,64 +50,12 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>"""\n <value> <string>state_change[\'object\'].localBuild()\n
Builds the delivery.\n
"""\n
from Products.ERP5Type.Log import log\n
delivery = sci[\'object\']\n
delivery_portal_type = delivery.getPortalType()\n
portal_deliveries = sci.getPortal().portal_deliveries\n
\n
builder_by_ptype = {\n
\'Sale Invoice\' : \'advanced_sale_invoice_transaction_builder\',\n
\'Purchase Invoice\' : \'advanced_purchase_invoice_transaction_builder\',\n
}\n
\n
if builder_by_ptype.has_key(delivery_portal_type) :\n
builder = getattr(portal_deliveries, builder_by_ptype[delivery_portal_type], None)\n
if builder is None :\n
log(\'erp5_advanced_invoicing\',\n
\'unable to build : no builder in %s\' % builder_by_ptype[delivery_portal_type])\n
return\n
\n
# build accounting lines\n
method_id_list = (\'expand\', \'edit\', \'updateAppliedRule\', \'Delivery_updateAppliedRule\',\n
\'immediateReindexObject\', \'recursiveImmediateReindexObject\')\n
\n
explanation_uid_list = [delivery.getUid(), ]\n
packing_list = delivery.getCausalityValue(\n
portal_type=(\'Sale Packing List\',\n
\'Purchase Packing List\'))\n
if packing_list is not None:\n
explanation_uid_list.append(packing_list.getUid())\n
order = packing_list.getCausalityValue(\n
portal_type=(\'Sale Order\',\n
\'Purchase Order\'))\n
if order is not None:\n
explanation_uid_list.append(order.getUid())\n
\n
\n
tag = \'invoice_transaction_build_%s\' % delivery.getRelativeUrl()\n
builder.activate(\n
activity=\'SQLQueue\',\n
after_method_id=method_id_list,\n
tag=tag,\n
activate_kw=dict(tag=tag)).build(activate_kw=dict(tag=tag),\n
explanation_uid=explanation_uid_list)\n
\n
# build related payment transactions\n
portal_deliveries.payment_transaction_builder.activate(\n
activity=\'SQLQueue\',\n
after_method_id=method_id_list).build(explanation_uid=explanation_uid_list)\n
\n
# set the object in building state.\n
delivery.startBuilding()\n
delivery.activate(after_tag=tag).updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>sci</string> </value> <value> <string>state_change</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Delivery_createRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -56,7 +56,7 @@ if portal.portal_workflow.isTransitionPossible(context, \'calculate\'):\n ...@@ -56,7 +56,7 @@ if portal.portal_workflow.isTransitionPossible(context, \'calculate\'):\n
else:\n else:\n
# Make sure no other node is moving the delivery\n # Make sure no other node is moving the delivery\n
# to \'diverged\' or \'solved\' state.\n # to \'diverged\' or \'solved\' state.\n
context.serialize()\n context.serializeCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?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>from Products.ERP5Type.Errors import SimulationError\n
\n
delivery = context\n
delivery_type = context.getPortalType()\n
\n
# XXX The following dict is only for backward compatibility.\n
applied_rule_dict = {\n
\'Pay Sheet Transaction\': \'default_invoice_rule\',\n
\'Payment Transaction\': \'default_invoice_rule\',\n
\n
\'Purchase Packing List\': \'default_delivery_rule\',\n
\'Purchase Invoice Transaction\': \'default_invoice_rule\',\n
\n
\'Sale Order\': \'default_order_rule\',\n
\'Sale Packing List\': \'default_delivery_rule\',\n
\'Sale Invoice Transaction\': \'default_invoice_rule\',\n
\n
\'Internal Packing List\': None,\n
\'Returned Sale Packing List\': None,\n
\n
\'Accounting Rule Cell\': None,\n
\'Accounting Transaction\': None,\n
\'Production Packing List\': None,\n
\'Production Report\': None,\n
\'Pay Sheet Model\': None,\n
\n
\'Amortisation Transaction\' : None,\n
\'Task Report\': \'default_delivery_rule\',\n
}\n
\n
try:\n
applied_rule = delivery.getRuleReference()\n
except SimulationError:\n
marker = []\n
applied_rule = applied_rule_dict.get(delivery_type, marker)\n
if applied_rule is marker:\n
raise\n
\n
if applied_rule is None:\n
# No need to add a rule, but still we need to expand the delivery\n
# if at least one of its movements is simulated.\n
for m in delivery.getMovementList():\n
if m.isSimulated():\n
delivery.activate(activate_kw=activate_kw).expand(**kw)\n
return\n
elif applied_rule:\n
delivery.updateAppliedRule(rule_reference=applied_rule, activate_kw=activate_kw, **kw)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>activate_kw=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Delivery_updateAppliedRule</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>delivery = context\n
delivery_path = delivery.getPath()\n
expand_tag = delivery_path + \'_expand\'\n
tag = delivery_path + \'_updateAppliedRule\'\n
\n
priority = 3\n
\n
# These parameters are passed to activate for expand and reindexObject,\n
# so Delivery_updateAppliedRule will wait for the creation and indexing of\n
# Applied Rules and Simulation Movements by another Delivery_updateAppliedRule.\n
# This is required for finding an existing Applied Rule by the catalog, and\n
# avoiding needless conflicts.\n
activate_kw = { \n
\'tag\': expand_tag,\n
\'priority\': priority,\n
}\n
\n
# Serialization is required for avoiding parallel executions of updateAppliedRule\n
# which may generate multiple Root Applied Rules.\n
delivery.activate(\n
after_tag=expand_tag,\n
tag=tag,\n
priority=priority,\n
serialization_tag=tag,\n
).Delivery_updateAppliedRule(activate_kw=activate_kw)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Delivery_updateSimulation</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <value>
<list> <list>
<string>Delivery_calculateCausalityState</string> <string>Delivery_calculate</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Delivery_calculateCausalityState</string> </value> <value> <string>Delivery_calculate</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>delivery = state_change[\'object\']\n
activate_kw = state_change[\'kwargs\'].get(\'activate_kw\') or {}\n
tag = delivery.getPath() + \'_calculate\'\n
delivery.activate(after_tag=tag, **activate_kw).updateCausalityState()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Delivery_afterEdit</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -60,8 +60,6 @@ split_and_defer = 0\n ...@@ -60,8 +60,6 @@ split_and_defer = 0\n
listbox = state_change[\'kwargs\'].get(\'listbox\')\n listbox = state_change[\'kwargs\'].get(\'listbox\')\n
split_movement_list = []\n split_movement_list = []\n
if listbox is not None:\n if listbox is not None:\n
# Create Delivery Applied Rule (if required)\n
delivery.Delivery_updateAppliedRule()\n
for line in listbox:\n for line in listbox:\n
url = line[\'listbox_key\']\n url = line[\'listbox_key\']\n
choice = line[\'choice\']\n choice = line[\'choice\']\n
......
...@@ -57,7 +57,6 @@ divergence_to_adopt_list = state_change[\'kwargs\'].get(\'divergence_to_adopt_li ...@@ -57,7 +57,6 @@ divergence_to_adopt_list = state_change[\'kwargs\'].get(\'divergence_to_adopt_li
\n \n
if len(delivery_solve_property_dict) or len(divergence_to_accept_list) \\\n if len(delivery_solve_property_dict) or len(divergence_to_accept_list) \\\n
or len(divergence_to_adopt_list):\n or len(divergence_to_adopt_list):\n
delivery.Delivery_updateAppliedRule()\n
delivery_relative_url = delivery.getRelativeUrl()\n delivery_relative_url = delivery.getRelativeUrl()\n
delivery_builder_list = delivery.getBuilderList()\n delivery_builder_list = delivery.getBuilderList()\n
if len(delivery_solve_property_dict):\n if len(delivery_solve_property_dict):\n
...@@ -68,9 +67,6 @@ if len(delivery_solve_property_dict) or len(divergence_to_accept_list) \\\n ...@@ -68,9 +67,6 @@ if len(delivery_solve_property_dict) or len(divergence_to_accept_list) \\\n
delivery_builder.solveDivergence(delivery_relative_url,\n delivery_builder.solveDivergence(delivery_relative_url,\n
divergence_to_accept_list=divergence_to_accept_list,\n divergence_to_accept_list=divergence_to_accept_list,\n
divergence_to_adopt_list=divergence_to_adopt_list)\n divergence_to_adopt_list=divergence_to_adopt_list)\n
# There could be a pending \'Delivery_calculate\' activity if we solved from\n
# \'calculating\' state, so wait that it is gone before updating causality state.\n
delivery.activate(after_tag=delivery.getPath() + \'_calculate\').updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -62,9 +62,6 @@ if not len(split_movement_list):\n ...@@ -62,9 +62,6 @@ if not len(split_movement_list):\n
\n \n
tag = delivery.getPath() + \'_split\'\n tag = delivery.getPath() + \'_split\'\n
\n \n
# Create Delivery Applied Rule (if required)\n
delivery.Delivery_updateAppliedRule()\n
\n
for movement in split_movement_list:\n for movement in split_movement_list:\n
delivery.getPortalObject().portal_simulation.solveMovement(\n delivery.getPortalObject().portal_simulation.solveMovement(\n
movement, None, \'SplitAndDefer\', start_date=start_date,\n movement, None, \'SplitAndDefer\', start_date=start_date,\n
......
...@@ -53,12 +53,11 @@ ...@@ -53,12 +53,11 @@
<value> <string>delivery = state_change[\'object\']\n <value> <string>delivery = state_change[\'object\']\n
\n \n
portal = delivery.getPortalObject()\n portal = delivery.getPortalObject()\n
solver_tool = getattr(portal, \'portal_solvers\', None)\n try:\n
solver_process_tool = getattr(portal, \'portal_solver_processes\', None)\n portal.portal_solvers\n
\n portal.portal_solver_processes\n
if solver_tool is None or solver_process_tool is None:\n except AttributeError:\n
delivery.diverge()\n delivery.diverge()\n
return\n
else:\n else:\n
solver_tag = \'%s_solve\' % delivery.getPath()\n solver_tag = \'%s_solve\' % delivery.getPath()\n
delivery.activate(tag=solver_tag).Delivery_solveDivergenceAutomatically()\n delivery.activate(tag=solver_tag).Delivery_solveDivergenceAutomatically()\n
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Delivery_afterEdit</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <value>
<list> <list>
<string>DeliveryMovement_calculateCausalityState</string> <string>DeliveryMovement_calculate</string>
</list> </list>
</value> </value>
</item> </item>
...@@ -56,7 +56,8 @@ ...@@ -56,7 +56,8 @@
<key> <string>method_id</string> </key> <key> <string>method_id</string> </key>
<value> <value>
<list> <list>
<string>_set.*</string> <string>_set(?!LastId$|Ob$|Object$)</string>
<string>manage_afterAdd</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>DeliveryMovement_calculateCausalityState</string> </value> <value> <string>DeliveryMovement_calculate</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string>call updateAppliedRule after a modification</string> </value> <value> <string>Reexpand root applied rule if the setter involves a movement that should be linked to a root simulation movement.</string> </value>
</item> </item>
<item> <item>
<key> <string>guard</string> </key> <key> <string>guard</string> </key>
......
...@@ -69,6 +69,8 @@ for simulation_movement in simulation_movement_list:\n ...@@ -69,6 +69,8 @@ for simulation_movement in simulation_movement_list:\n
# \'order\' category is deprecated. it is kept for compatibility.\n # \'order\' category is deprecated. it is kept for compatibility.\n
if simulation_movement.getOrder() == delivery_movement.getRelativeUrl():\n if simulation_movement.getOrder() == delivery_movement.getRelativeUrl():\n
simulation_movement.setOrder(None)\n simulation_movement.setOrder(None)\n
\n
context.DeliveryMovement_updateSimulation(state_change)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -50,7 +50,15 @@ ...@@ -50,7 +50,15 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>state_change[\'object\'].getRootDeliveryValue().Delivery_updateSimulation()\n <value> <string>movement = state_change[\'object\']\n
if not movement.isGeneratedBySimulation():\n
# A setter was called on a movement that should be linked to\n
# a root simulation movement, which usually copies the movement.\n
# If there\'s a new movement in the delivery (e.g. _setObject),\n
# the root applied rule must be reexpanded in order to generate\n
# the missing simulation movement.\n
# XXX: Otherwise, it should be enough to reexpand the related SM.\n
movement.getRootDeliveryValue().updateSimulation(expand_root=1)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <value>
<list> <list>
<string>Order_expandAppliedRule</string> <string>Delivery_updateSimulation</string>
</list> </list>
</value> </value>
</item> </item>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>expand_simulation</string> </value> <value> <string>expand_root</string> </value>
</item> </item>
<item> <item>
<key> <string>method_id</string> </key> <key> <string>method_id</string> </key>
......
...@@ -40,7 +40,9 @@ ...@@ -40,7 +40,9 @@
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string>reindex simulation after workflow state change, to keep consistency</string> </value> <value> <string>reindex simulation after workflow state change, to keep consistency\r\n
\r\n
XXX: Something more reliable than a hardcoded list of methods from simulation workflows should be implemented.</string> </value>
</item> </item>
<item> <item>
<key> <string>guard</string> </key> <key> <string>guard</string> </key>
...@@ -50,7 +52,7 @@ ...@@ -50,7 +52,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>reindex_simulation</string> </value> <value> <string>reindex_related</string> </value>
</item> </item>
<item> <item>
<key> <string>method_id</string> </key> <key> <string>method_id</string> </key>
...@@ -60,7 +62,6 @@ ...@@ -60,7 +62,6 @@
<string>close</string> <string>close</string>
<string>confirm</string> <string>confirm</string>
<string>deliver</string> <string>deliver</string>
<string>open</string>
<string>order</string> <string>order</string>
<string>plan</string> <string>plan</string>
<string>setReady</string> <string>setReady</string>
...@@ -72,7 +73,7 @@ ...@@ -72,7 +73,7 @@
</item> </item>
<item> <item>
<key> <string>once_per_transaction</string> </key> <key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value> <value> <int>1</int> </value>
</item> </item>
<item> <item>
<key> <string>portal_type_filter</string> </key> <key> <string>portal_type_filter</string> </key>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <value>
<list> <list>
<string>OrderMovement_expandAppliedRule</string> <string>Delivery_updateCausalityState</string>
</list> </list>
</value> </value>
</item> </item>
...@@ -50,13 +50,14 @@ ...@@ -50,13 +50,14 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>expand_simulation</string> </value> <value> <string>update_causality</string> </value>
</item> </item>
<item> <item>
<key> <string>method_id</string> </key> <key> <string>method_id</string> </key>
<value> <value>
<list> <list>
<string>_set.*</string> <string>calculate</string>
<string>startBuilding</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>Delivery_updateSimulation</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>call updateAppliedRule after a modification</string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>update_simulation</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>_set(?!LastId$|Ob$|Object$)</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,28 +50,7 @@ ...@@ -50,28 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>"""\n <value> <string>state_change[\'object\'].updateSimulation(create_root=1, index_related=1)\n
+-----+ +--------+\n
|Order| |Delivery| \n
+-----+ +--------+\n
| /\n
[AR] / \n
`--[SM] (1) \n
| \n
[AR] \n
`--[SM] (2)\n
| \n
...\n
\n
This script reindex simulation movements in (1), so that delivery builder select movement in (2)\n
with an up to date simulation state. We reindex simulation movements with the tag _updateAppliedRule,\n
because that delivery builder builds after that tag.\n
"""\n
\n
delivery = state_change[\'object\']\n
tag = \'%s_expand\' % delivery.getPath()\n
delivery.applyToDeliveryRelatedMovement(method_id=\'recursiveReindexObject\',\n
activate_kw=dict(tag=tag))\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>state_change[\'object\'].Delivery_updateSimulation()\n <value> <string>state_change[\'object\'].updateSimulation(calculate=1)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Delivery_updateSimulation</string> </value> <value> <string>Delivery_updateCausalityState</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>state_change[\'object\'].Delivery_updateSimulation()\n <value> <string>state_change[\'object\'].updateSimulation(expand_root=1)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionWorkflowDefinition" module="Products.ERP5.InteractionWorkflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>creation_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>This workflow manage the expand of the simulation related to an order movement</string> </value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>order_movement_simulation_interaction_workflow</string> </value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Order Movement Interaction Workflow</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>OrderMovement_expandAppliedRule</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>unlink_simulation</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>manage_beforeDelete</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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>order_movement = state_change[\'object\']\n
\n
order_movement.getExplanationValue().expandAppliedRuleRelatedToOrder()\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>OrderMovement_expandAppliedRule</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>order_movement = state_change[\'object\']\n
\n
# Clean simulation\n
simulation_movement_list = order_movement.getOrderRelatedValueList(\n
portal_type="Simulation Movement")\n
for simulation_movement in simulation_movement_list:\n
if simulation_movement.getDelivery() == order_movement.getRelativeUrl():\n
simulation_movement.setDelivery(None)\n
# \'order\' category is deprecated. it is kept for compatibility.\n
if simulation_movement.getOrder() == order_movement.getRelativeUrl():\n
simulation_movement.setOrder(None)\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>OrderMovement_unlinkSimulation</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>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionWorkflowDefinition" module="Products.ERP5.InteractionWorkflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>creation_guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>This workflow manage the expand of the simulation related to an order</string> </value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>order_simulation_interaction_workflow</string> </value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Order Interaction Workflow</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>Order_reindexAppliedRule</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>XXX \r\n
The purpose of this interaction is to reindex the simulation movement related to an order when the simulation state is changed.\r\n
Currently, method ids are hardcoded, and it could be better to use a generic trigger method if possible.</string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>reindex_simulation</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>cancel</string>
<string>close</string>
<string>confirm</string>
<string>deliver</string>
<string>open</string>
<string>order</string>
<string>plan</string>
<string>start</string>
<string>submit</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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>order = state_change[\'object\']\n
\n
order.expandAppliedRuleRelatedToOrder()\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>Order_expandAppliedRule</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>order = state_change[\'object\']\n
\n
applied_rule = order.getCausalityRelatedValue(portal_type=\'Applied Rule\')\n
if applied_rule is not None:\n
applied_rule.recursiveReindexObject()\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>Order_reindexAppliedRule</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>
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<key> <string>method_id</string> </key> <key> <string>method_id</string> </key>
<value> <value>
<list> <list>
<string>_set.*</string> <string>_set(?!LastId$|Ob$|Object$|Delivery$|DeliveryValue$)</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -50,31 +50,18 @@ ...@@ -50,31 +50,18 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>state_change[\'object\'].calculate()\n <value> <string>delivery = state_change[\'object\'].getExplanationValue()\n
try:\n
delivery.aq_explicit.getCausalityState\n
except AttributeError:\n
return\n
delivery.activate(tag=\'expand:\'+delivery.getPath()).Delivery_calculate()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>state_change</string> </value> <value> <string>state_change</string> </value>
</item> </item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Authenticated</string>
<string>Author</string>
<string>Manager</string>
<string>Member</string>
<string>Owner</string>
<string>Reviewer</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>SimulationMovement_calculateCausalityState</string> </value> <value> <string>SimulationMovement_calculateCausalityState</string> </value>
......
...@@ -12,8 +12,6 @@ embedded_workflow ...@@ -12,8 +12,6 @@ embedded_workflow
local_permission_interaction_workflow local_permission_interaction_workflow
movement_resource_interaction_workflow movement_resource_interaction_workflow
notification_message_workflow notification_message_workflow
order_movement_simulation_interaction_workflow
order_simulation_interaction_workflow
person_interaction_workflow person_interaction_workflow
processing_status_workflow processing_status_workflow
query_workflow query_workflow
......
...@@ -78,9 +78,11 @@ for builder_id in builder_id_list:\n ...@@ -78,9 +78,11 @@ for builder_id in builder_id_list:\n
serialization_tag = \'build:%s\' % delivery_portal_type\n serialization_tag = \'build:%s\' % delivery_portal_type\n
index_tag = \'index:%s\' % delivery_portal_type\n index_tag = \'index:%s\' % delivery_portal_type\n
after_tag = index_tag\n after_tag = index_tag\n
# depend on reindexing so that select methods\n
# do not return movements that are already built\n
after_method_id = (\'recursiveImmediateReindexObject\',\n after_method_id = (\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\',\n \'immediateReindexObject\',\n
\'Delivery_updateAppliedRule\')\n \'_updateSimulation\')\n
activate_kw = dict(tag=index_tag)\n activate_kw = dict(tag=index_tag)\n
builder.activate(\n builder.activate(\n
serialization_tag=serialization_tag,\n serialization_tag=serialization_tag,\n
......
...@@ -75,9 +75,11 @@ for builder_id in builder_id_list:\n ...@@ -75,9 +75,11 @@ for builder_id in builder_id_list:\n
serialization_tag = \'build:%s\' % delivery_portal_type\n serialization_tag = \'build:%s\' % delivery_portal_type\n
index_tag = \'index:%s\' % delivery_portal_type\n index_tag = \'index:%s\' % delivery_portal_type\n
after_tag = index_tag\n after_tag = index_tag\n
# depend on reindexing so that select methods\n
# do not return movements that are already built\n
after_method_id = (\'recursiveImmediateReindexObject\',\n after_method_id = (\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\',\n \'immediateReindexObject\',\n
\'Delivery_updateAppliedRule\')\n \'_updateSimulation\')\n
activate_kw = dict(tag=index_tag)\n activate_kw = dict(tag=index_tag)\n
builder.activate(\n builder.activate(\n
serialization_tag=serialization_tag,\n serialization_tag=serialization_tag,\n
......
...@@ -57,16 +57,6 @@ ...@@ -57,16 +57,6 @@
<none/> <none/>
</value> </value>
</item> </item>
<item>
<key> <string>delivery_after_generation_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>delivery_after_generation_script_id</string> </key>
<value> <string>Invoice_reindexRelatedSimulation</string> </value>
</item>
<item> <item>
<key> <string>delivery_cell_collect_order</string> </key> <key> <string>delivery_cell_collect_order</string> </key>
<value> <value>
......
...@@ -57,16 +57,6 @@ ...@@ -57,16 +57,6 @@
<none/> <none/>
</value> </value>
</item> </item>
<item>
<key> <string>delivery_after_generation_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>delivery_after_generation_script_id</string> </key>
<value> <string>Invoice_reindexRelatedSimulation</string> </value>
</item>
<item> <item>
<key> <string>delivery_cell_collect_order</string> </key> <key> <string>delivery_cell_collect_order</string> </key>
<value> <value>
......
...@@ -69,3 +69,6 @@ class DummyDelivery(Delivery): ...@@ -69,3 +69,6 @@ class DummyDelivery(Delivery):
def setCausalityState(self, state): def setCausalityState(self, state):
"""Directly sets a causality state.""" """Directly sets a causality state."""
self.causality_state = state self.causality_state = state
def serializeCausalityState(self):
pass
<?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>request = context.REQUEST\n
Base_translateString = context.Base_translateString\n
\n
listbox = request.get(\'listbox\')\n
start_date = context.getStartDate()\n
stop_date = context.getStopDate()\n
tag = context.getPath() + \'_split\'\n
\n
split_and_defer = 0\n
\n
if listbox is not None:\n
context.updateAppliedRule("default_delivery_rule")\n
for line in listbox.values():\n
url = line[\'listbox_key\']\n
quantity = line[\'quantity\']\n
movement = context.restrictedTraverse(url)\n
movement.edit(quantity=str(quantity))\n
choice = line[\'choice\']\n
if choice == \'SplitAndDefer\':\n
split_and_defer = 1\n
context.portal_simulation.solveMovement(movement, None, "SplitAndDefer", \n
start_date=start_date, stop_date=stop_date, \n
activate_kw={\'tag\':tag})\n
elif choice == \'CopyToTarget\':\n
context.portal_simulation.solveMovement(movement, None,"CopyToTarget", activate_kw={\'tag\':tag})\n
\n
context.activate(after_tag=tag).updateCausalityState()\n
\n
if split_and_defer:\n
context_portal_type = context.getPortalType()\n
explanation_uid_list = [context.getUid()]\n
# Create delivery\n
if context_portal_type == \'Internal Packing List\':\n
delivery_builder = context.portal_deliveries.serp_internal_packing_list_builder\n
elif context_portal_type == \'Purchase Packing List\':\n
order = context.getCausalityValue()\n
explanation_uid_list.append(order.getUid())\n
delivery_builder = context.portal_deliveries.purchase_packing_list_builder\n
\n
delivery_builder.activate(activity=\'SQLQueue\', after_tag=tag).build(explanation_uid=explanation_uid_list)\n
\n
message = Base_translateString("${obj_portal_type} updated.", mapping={\'obj_portal_type\':context.getTranslatedPortalType()})\n
message = message.replace(\' \', \'+\')\n
\n
redirect_url = \'%s/%s?%s\' % (context.absolute_url(), form_id, \n
\'portal_status_message=%s\' % message)\n
context.REQUEST[ \'RESPONSE\' ].redirect( redirect_url )\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>form_id, dialog_id=\'\', **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>AmortisationTransaction_doSolveActions</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -56,14 +56,6 @@ ...@@ -56,14 +56,6 @@
the new Invoice.\n the new Invoice.\n
"""\n """\n
from Products.ERP5Type.Message import translateString\n from Products.ERP5Type.Message import translateString\n
try:\n
from Products.CMFCore.WorkflowCore import WorkflowException\n
except ImportError:\n
# WorkflowException has not always been allowed in restricted\n
# environment, in this case, make sure WorkflowException is \n
# defined \n
class WorkflowException(Exception):\n
pass\n
\n \n
if related_simulation_movement_path_list is None:\n if related_simulation_movement_path_list is None:\n
raise RuntimeError, \'related_simulation_movement_path_list is missing. Update ERP5 Product.\'\n raise RuntimeError, \'related_simulation_movement_path_list is missing. Update ERP5 Product.\'\n
...@@ -101,24 +93,11 @@ if not invoice.hasTitle() and related_packing_list is not None and \\\n ...@@ -101,24 +93,11 @@ if not invoice.hasTitle() and related_packing_list is not None and \\\n
invoice.setTitle(related_packing_list.getTitle())\n invoice.setTitle(related_packing_list.getTitle())\n
\n \n
# initialize accounting_workflow to confirmed state\n # initialize accounting_workflow to confirmed state\n
confirm_tag = \'%s_confirm\' % invoice.getPath()\n
if invoice.getSimulationState() == \'draft\':\n if invoice.getSimulationState() == \'draft\':\n
invoice.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n invoice.Delivery_confirm()\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
tag=confirm_tag).Delivery_confirm()\n
else:\n else:\n
# call builder just same as after script of \'confirm\' transition\n # call builder just same as after script of \'confirm\' transition\n
invoice.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n invoice.localBuild()\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
tag=confirm_tag).Delivery_expandAndBuild()\n
\n
# First set the invoice in the building state on the causality workflow\n
invoice.startBuilding()\n
\n
# Then an activity should put the causality state in diverged or solved\n
invoice.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
after_tag=confirm_tag).updateCausalityState()\n
]]></string> </value> ]]></string> </value>
......
...@@ -61,23 +61,22 @@ ...@@ -61,23 +61,22 @@
# on the Transaction and delete resource on the lines.\n # on the Transaction and delete resource on the lines.\n
# TODO: this is a Property Assignment Movement Group\n # TODO: this is a Property Assignment Movement Group\n
\n \n
accounting_line_portal_type = context.getPortalAccountingMovementTypeList()\n line_list = context.objectValues(\n
resources_keys = {}\n portal_type=context.getPortalAccountingMovementTypeList())\n
for line in context.contentValues(portal_type=accounting_line_portal_type):\n resource_set = set(line.getResource() for line in line_list)\n
resources_keys[line.getResource()] = 1\n try:\n
\n resource, = resource_set\n
if len(resources_keys.keys()) == 1 :\n except ValueError:\n
raise ValueError("%s doesn\'t have only one resource %s" % (\n
context.getPath(), list(resource_set)))\n
if context.getResource() != resource:\n
# set the resource on the transaction\n # set the resource on the transaction\n
context.setResource(resources_keys.keys()[0])\n context.setResource(resource)\n
# and delete on the invoice lines, so that if the user\n # and delete on the invoice lines, so that if the user changes\n
# changes the ressource on the transaction, it also change on \n # the ressource on the transaction, it also change on the lines.\n
# the lines. \n for line in line_list:\n
for line in context.contentValues(portal_type=accounting_line_portal_type):\n
line.setResource(None)\n line.setResource(None)\n
assert(line.getResource() == context.getResource())\n assert line.getResource() == resource\n
else :\n
raise ValueError, "%s doesn\'t have only one resource %s" % (\n
context.getPath(), resources_keys.keys())\n
\n \n
# round debit / credit on created transaction.\n # round debit / credit on created transaction.\n
context.AccountingTransaction_roundDebitCredit()\n context.AccountingTransaction_roundDebitCredit()\n
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>return context.applyToDeliveryRelatedMovement(\n
method_id=\'recursiveReindexObject\')\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Invoice_reindexRelatedSimulation</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>order = state_change[\'object\']\n
\n
order.applyToOrderRelatedMovement(method_id=\'expand\')\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>Order_appliedToRelatedMovement</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,46 +50,8 @@ ...@@ -50,46 +50,8 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[ <value> <string>state_change[\'object\'].localBuild()\n
</string> </value>
order = state_change[\'object\']\n
business_process = order.getSpecialiseValue()\n
\n
# When a business process is selected as specialise, ProductionOrderModelRule can be used.\n
# But another one is selected, ProductionOrderRule is still used.\n
if (business_process is not None and\n
business_process.getPortalType() in context.getPortalBusinessProcessTypeList()):\n
rule_reference=\'default_production_order_model_rule\'\n
builder_list = []\n
for path in business_process.getBuildablePathValueList(order):\n
builder_list.extend(path.getDeliveryBuilderValueList())\n
else:\n
rule_reference=\'default_production_order_rule\'\n
builder_list = [\n
order.portal_deliveries.production_report_builder,\n
order.portal_deliveries.production_packing_list_builder\n
]\n
\n
order_path = order.getPath()\n
tag = order_path + \'_updateAppliedRule\'\n
expand_tag = order_path + \'_expand\'\n
activate_kw = {\'tag\':expand_tag, \'priority\':3}\n
order.activate(tag=tag, after_tag=expand_tag).updateAppliedRule(rule_reference=rule_reference, activate_kw=activate_kw)\n
\n
for i in xrange(len(builder_list)):\n
if i > 0:\n
after_tag = (tag, expand_tag, \'%s_builder_%s\' % (order_path, i-1))\n
else:\n
after_tag = (tag, expand_tag)\n
builder_list[i].activate(\n
activity=\'SQLQueue\',\n
after_tag=after_tag,\n
tag=\'%s_builder_%s\' % (order_path, i),\n
priority=3).build(explanation_uid=order.getUid(),\n
activate_kw=activate_kw)\n
]]></string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
......
<?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>order = state_change[\'object\']\n
business_process = order.getSpecialiseValue()\n
\n
# When a business process is selected as specialise, ProductionOrderModelRule can be used.\n
# But another one is selected, ProductionOrderRule is still used.\n
if (business_process is not None and\n
business_process.getPortalType() in context.getPortalBusinessProcessTypeList()):\n
rule_reference=\'default_production_order_model_rule\'\n
else:\n
rule_reference=\'default_production_order_rule\'\n
\n
path = order.getPath()\n
tag = \'%s_updateAppliedRule\' % path\n
expand_tag = \'%s_expand\' % path\n
activate_kw = {\'tag\':expand_tag, \'priority\':3}\n
order.activate(tag=tag, after_tag=expand_tag).updateAppliedRule(rule_reference=rule_reference, activate_kw=activate_kw)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Order_createOrderRule</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StateDefinition" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>closed</string> </value>
</item>
<item>
<key> <string>permission_roles</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Closed</string> </value>
</item>
<item>
<key> <string>transitions</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>type_list</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="PersistentMapping" module="Persistence.mapping"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>Access contents information</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Add portal content</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>Delete objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>Modify portal content</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>View</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StateDefinition" module="Products.DCWorkflow.States"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>open</string> </value>
</item>
<item>
<key> <string>permission_roles</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Open</string> </value>
</item>
<item>
<key> <string>transitions</string> </key>
<value>
<tuple>
<string>close</string>
<string>close_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>type_list</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="PersistentMapping" module="Persistence.mapping"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>Access contents information</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>Add portal content</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>Delete objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>Modify portal content</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>View</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_appliedToRelatedMovement</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>close</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>closed</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string>close</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>close_action</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>informDeliveryList</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>open</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string>open</string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string>open</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>open_action</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
<?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>packing_list = state_change[\'object\']\n
\n
activate_kw = {}\n
related_order = packing_list.getCausalityValue()\n
path = packing_list.getPath()\n
tag = \'%s_updateAppliedRule\' % path\n
expand_tag = \'%s_expand\' % path\n
activate_kw = {\'tag\':expand_tag,\'priority\':3}\n
after_tag_list = [expand_tag]\n
if related_order is not None:\n
# XXX is it really required?\n
after_tag_list.append(\'%s_expand\' % related_order.getPath())\n
\n
packing_list.activate(after_tag=after_tag_list,\n
tag=tag,\n
priority=3).Delivery_updateAppliedRule(activate_kw=activate_kw)\n
\n
\n
# Make sure to reindex related simulation movement if we are already\n
# simulated, call reindexObject, not immediateReindexObject so that\n
# catalogObjectList will be called with many objects\n
# XXX is it really required?\n
packing_list.activate(after_tag=after_tag_list,\n
tag=tag,\n
priority=3).applyToDeliveryRelatedMovement(method_id=\'reindexObject\')\n
\n
if packing_list.getCausalityState() == \'draft\':\n
packing_list.startBuilding()\n
# XXX is it really required?\n
packing_list.activate(\n
after_tag = tag,\n
).updateCausalityState()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>SaleOrder_getRuleReference</string> </value> <value> <string>OpenOrder_getRuleReference</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -50,22 +50,15 @@ ...@@ -50,22 +50,15 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>subscription_item_dict = dict()\n <value> <string>subscription_item_set = set()\n
\n \n
for open_order_line in context.contentValues():\n for open_order_line in context.objectValues():\n
for path in [open_order_line] + open_order_line.getCellValueList():\n for ob in [open_order_line] + open_order_line.getCellValueList():\n
for item in path.getAggregateValueList():\n for item in ob.getAggregateValueList():\n
if item.providesIExpandableItem(): # XXX hack to make it fails\n if getattr(item.aq_explicit, \'updateSimulation\', None) is not None and \\\n
subscription_item_dict[item] = 1\n item not in subscription_item_set:\n
\n subscription_item_set.add(item)\n
# XXX tag / after tag !\n item.updateSimulation(expand_root=1)\n
for item in subscription_item_dict:\n
activate_kw = dict(tag=\'%s_expand\' % item.getPath())\n
applied_rule = item.getCausalityRelatedValue(portal_type=\'Applied Rule\')\n
if applied_rule is not None:\n
applied_rule.activate(activate_kw=activate_kw).expand(activate_kw=activate_kw)\n
else:\n
item.activate(activate_kw=activate_kw).expand(activate_kw=activate_kw)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?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 \'default_order_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>OpenPurchaseOrder_getRuleReference</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 \'default_order_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>OpenSaleOrder_getRuleReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,15 +50,10 @@ ...@@ -50,15 +50,10 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>path = state_change[\'object\']\n <value> <string>ob = state_change[\'object\']\n
open_order_type_list = state_change.getPortal().getPortalOpenOrderTypeList()\n while not ob.isOpenOrderType():\n
\n ob = ob.getParentValue()\n
def getOpenOrder(path):\n ob.OpenOrder_updateSimulation()\n
if path.getPortalType() in open_order_type_list:\n
return path\n
return getOpenOrder(path.getParentValue())\n
\n
getOpenOrder(path).OpenOrder_updateSimulation()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?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 None\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PaySheetModel_getRuleReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -117,18 +117,7 @@ Please visit ERP5: %(url)s\n ...@@ -117,18 +117,7 @@ Please visit ERP5: %(url)s\n
subject="[ERP5 Task] %s" % task_report.getTitle(), \n subject="[ERP5 Task] %s" % task_report.getTitle(), \n
message=message)\n message=message)\n
\n \n
# Then, modify state\n task_report.Delivery_confirm()\n
confirm_tag = \'%s_confirm\' % task_report.getPath()\n
task_report.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
tag=confirm_tag).Delivery_confirm()\n
\n
# First set the task_report in the building state\n
task_report.startBuilding()\n
# Then an activity should put the causality state in diverged or solved\n
task_report.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
after_tag=confirm_tag).updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>portal = sci.getPortal()\n
if portal.hasObject(\'accounting_module\'):\n
portal.portal_deliveries.task_invoice_builder.activate(\n
after_method_id = [ \'expand\', \n
\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\' ],\n
).build()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>sci</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PackingList_buildInvoice</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>packing_list = state_change[\'object\']\n
\n
activate_kw = {}\n
related_order = packing_list.getCausalityValue()\n
path = packing_list.getPath()\n
tag = \'%s_updateAppliedRule\' % path\n
expand_tag = \'%s_expand\' % path\n
activate_kw = {\'tag\':expand_tag,\'priority\':3}\n
after_tag_list = [expand_tag]\n
if related_order is not None:\n
# XXX is it really required?\n
after_tag_list.append(\'%s_expand\' % related_order.getPath())\n
\n
packing_list.activate(after_tag=after_tag_list,\n
tag=tag,\n
priority=3).Delivery_updateAppliedRule(activate_kw=activate_kw)\n
\n
\n
# Make sure to reindex related simulation movement if we are already\n
# simulated, call reindexObject, not immediateReindexObject so that\n
# catalogObjectList will be called with many objects\n
# XXX is it really required?\n
packing_list.activate(after_tag=after_tag_list,\n
tag=tag,\n
priority=3).applyToDeliveryRelatedMovement(method_id=\'reindexObject\')\n
\n
if packing_list.getCausalityState() == \'draft\':\n
packing_list.startBuilding()\n
# XXX is it really required?\n
packing_list.activate(\n
after_tag = tag,\n
).updateCausalityState()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -74,8 +74,6 @@ Please look at this URL:\n ...@@ -74,8 +74,6 @@ Please look at this URL:\n
task_report.ERP5Site_getAbsoluteUrl(), task_report.getRelativeUrl())\n task_report.ERP5Site_getAbsoluteUrl(), task_report.getRelativeUrl())\n
portal.portal_notifications.sendMessage(sender=source_person, recipient=destination_decision_person,\n portal.portal_notifications.sendMessage(sender=source_person, recipient=destination_decision_person,\n
subject="Task Report Finished", message=message)\n subject="Task Report Finished", message=message)\n
\n
container.PackingList_updateAppliedRule(state_change)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string>Confirm Task</string> </value> <value> <string>Confirm Task</string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string>Start Task</string> </value> <value> <string>Start Task</string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
<?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>task = state_change[\'object\']\n
\n
task.applyToOrderRelatedMovement(method_id=\'expand\')\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>Task_appliedToRelatedMovement</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,17 +50,7 @@ ...@@ -50,17 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>task = state_change[\'object\']\n <value> <string>state_change[\'object\'].localBuild()\n
\n
path = task.getPath()\n
tag = \'%s_updateAppliedRule\' % path\n
expand_tag = \'%s_expand\' % path\n
activate_kw = {\'tag\':expand_tag, \'priority\':3}\n
\n
task.activate(tag=tag, after_tag=expand_tag).Delivery_updateAppliedRule(activate_kw=activate_kw)\n
\n
delivery_builder = task.portal_deliveries.task_report_builder\n
delivery_builder.activate(activity=\'SQLQueue\',after_tag=(tag, expand_tag)).build(explanation_uid=task.getUid())\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?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>task = state_change[\'object\']\n
\n
path = task.getPath()\n
tag = \'%s_updateAppliedRule\' % path\n
expand_tag = \'%s_expand\' % path\n
activate_kw = {\'tag\':expand_tag, \'priority\':3}\n
\n
task.activate(tag=tag, after_tag=expand_tag).Delivery_updateAppliedRule(activate_kw=activate_kw)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Task_createOrderRule</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string>Cancel Task</string> </value> <value> <string>Cancel Task</string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Task_appliedToRelatedMovement</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string>Order Task</string> </value> <value> <string>Order Task</string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Task_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string>Plan Task</string> </value> <value> <string>Plan Task</string> </value>
...@@ -42,7 +46,7 @@ ...@@ -42,7 +46,7 @@
</item> </item>
<item> <item>
<key> <string>script_name</string> </key> <key> <string>script_name</string> </key>
<value> <string>Task_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
......
<?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 context.asComposedDocument().build(explanation=context)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Delivery_buildOnComposedDocument</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>delivery = context\n
delivery_path = delivery.getPath()\n
path_and_method_id = (delivery_path, (\'immediateReindexObject\', \'recursiveImmediateReindexObject\'))\n
expand_tag = delivery_path + \'_expand\'\n
tag = delivery_path + \'_updateAppliedRule\'\n
after_tag = [expand_tag]\n
\n
# wait for expand activities of related documents.\n
# XXX ideally, it should be calculated by explanation tree, instead of causalities.\n
for causality in delivery.getCausalityValueList():\n
causality_path = causality.getPath()\n
after_tag.append(\'%s_expand\' % causality_path)\n
after_tag.append(\'%s_updateAppliedRule\' % causality_path)\n
\n
priority = 3\n
activate_kw = { \n
\'tag\': expand_tag,\n
\'priority\':priority,\n
}\n
delivery.activate(\n
activity=\'SQLQueue\',\n
after_path_and_method_id=path_and_method_id,\n
after_tag=after_tag,\n
tag=tag,\n
priority=priority,\n
serialization_tag=tag,\n
).Delivery_updateAppliedRule(activate_kw=activate_kw)\n
delivery.activate(activity=\'SQLQueue\', after_tag=(tag, expand_tag)).Delivery_buildOnComposedDocument()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Delivery_expandAndBuild</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,7 +50,9 @@ ...@@ -50,7 +50,9 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>return False\n <value> <string># XXX: Using reference to select a rule (for a root applied rule) is wrong\n
# and should be replaced by predicate and workflow state.\n
return False\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -45,10 +45,6 @@ ...@@ -45,10 +45,6 @@
</list> </list>
</value> </value>
</item> </item>
<item>
<key> <string>delivery_after_generation_script_id</string> </key>
<value> <string>Invoice_reindexRelatedSimulation</string> </value>
</item>
<item> <item>
<key> <string>delivery_cell_collect_order</string> </key> <key> <string>delivery_cell_collect_order</string> </key>
<value> <value>
......
...@@ -65,7 +65,7 @@ index_tag = \'index:\' + delivery_portal_type\n ...@@ -65,7 +65,7 @@ index_tag = \'index:\' + delivery_portal_type\n
after_method_id = (\'recursiveImmediateReindexObject\',\n after_method_id = (\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\',\n \'immediateReindexObject\',\n
\'expand\',\n \'expand\',\n
\'Delivery_updateAppliedRule\')\n \'_updateSimulation\')\n
activate_kw = dict(tag=index_tag)\n activate_kw = dict(tag=index_tag)\n
builder.activate(\n builder.activate(\n
serialization_tag=serialization_tag,\n serialization_tag=serialization_tag,\n
......
...@@ -71,9 +71,11 @@ for builder_id in builder_id_list:\n ...@@ -71,9 +71,11 @@ for builder_id in builder_id_list:\n
serialization_tag = \'build:%s\' % delivery_portal_type\n serialization_tag = \'build:%s\' % delivery_portal_type\n
index_tag = \'index:%s\' % delivery_portal_type\n index_tag = \'index:%s\' % delivery_portal_type\n
after_tag = index_tag\n after_tag = index_tag\n
# depend on reindexing so that select methods\n
# do not return movements that are already built\n
after_method_id = (\'recursiveImmediateReindexObject\',\n after_method_id = (\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\',\n \'immediateReindexObject\',\n
\'Delivery_updateAppliedRule\')\n \'_updateSimulation\')\n
activate_kw = dict(tag=index_tag)\n activate_kw = dict(tag=index_tag)\n
builder.activate(\n builder.activate(\n
serialization_tag=serialization_tag,\n serialization_tag=serialization_tag,\n
......
...@@ -70,9 +70,11 @@ for builder_id in builder_id_list:\n ...@@ -70,9 +70,11 @@ for builder_id in builder_id_list:\n
serialization_tag = \'build:%s\' % delivery_portal_type\n serialization_tag = \'build:%s\' % delivery_portal_type\n
index_tag = \'index:%s\' % delivery_portal_type\n index_tag = \'index:%s\' % delivery_portal_type\n
after_tag = index_tag\n after_tag = index_tag\n
# depend on reindexing so that select methods\n
# do not return movements that are already built\n
after_method_id = (\'recursiveImmediateReindexObject\',\n after_method_id = (\'recursiveImmediateReindexObject\',\n
\'immediateReindexObject\',\n \'immediateReindexObject\',\n
\'Delivery_updateAppliedRule\')\n \'_updateSimulation\')\n
activate_kw = dict(tag=index_tag)\n activate_kw = dict(tag=index_tag)\n
builder.activate(\n builder.activate(\n
serialization_tag=serialization_tag,\n serialization_tag=serialization_tag,\n
......
...@@ -50,23 +50,18 @@ ...@@ -50,23 +50,18 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>from Products.ERP5Type.Message import translateString\n <value> <string>if REQUEST is not None:\n
\n
if REQUEST is not None:\n
from zExceptions import Unauthorized\n from zExceptions import Unauthorized\n
raise Unauthorized(script.id)\n raise Unauthorized(script.id)\n
\n \n
packing_list = context\n if context.getSimulationState() == "draft":\n
\n from Products.ERP5Type.Message import translateString\n
# Modify state\n context.confirm(comment=translateString(\'Initialised by Delivery Builder.\'))\n
packing_list_state = packing_list.getSimulationState()\n
if packing_list_state == "draft":\n
packing_list.confirm(comment=translateString(\'Initialised by Delivery Builder.\'))\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>REQUEST=None, **kw</string> </value> <value> <string>REQUEST=None</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
<?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 \'default_order_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InternalOrder_getRuleReference</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 None\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InternalPackingList_getRuleReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Task_getRuleReference</string> </value> <value> <string>Order_getRuleReference</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>request = context.REQUEST\n
\n
listbox = request.get(\'listbox\')\n
start_date = context.getStartDate()\n
stop_date = context.getStopDate()\n
tag = context.getPath() + \'_split\'\n
\n
split_and_defer = 0\n
\n
if listbox is not None:\n
context.updateAppliedRule("default_delivery_rule")\n
for line_key in listbox:\n
line = listbox[line_key]\n
url = line[\'listbox_key\']\n
quantity = line[\'quantity\']\n
movement = context.restrictedTraverse(url)\n
movement.setProperty(\'quantity\', quantity, type=\'float\')\n
choice = line[\'choice\']\n
if choice == \'SplitAndDefer\':\n
split_and_defer = 1\n
context.portal_simulation.solveMovement(movement, None, "SplitAndDefer", start_date=start_date, stop_date=stop_date, activate_kw={\'tag\':tag})\n
elif choice == \'CopyToTarget\':\n
context.portal_simulation.solveMovement(movement, None,"CopyToTarget")\n
\n
context.updateCausalityState()\n
\n
if split_and_defer:\n
# Create delivery\n
order = context.getCausalityValue()\n
applied_rule = order.getCausalityRelatedValue(portal_type="Applied Rule")\n
\n
order_portal_type = order.getPortalType()\n
if order_portal_type == \'Sale Order\':\n
delivery_builder = order.portal_deliveries.sale_packing_list_builder\n
elif order_portal_type == \'Purchase Order\':\n
delivery_builder = order.portal_deliveries.purchase_packing_list_builder\n
\n
explanation_uid_list = [order.getUid(),context.getUid()]\n
delivery_builder.activate(activity=\'SQLQueue\',after_tag=tag).build(explanation_uid=explanation_uid_list)\n
\n
\n
_ = context.Base_translateString\n
return context.Base_redirect(form_id, keep_items=\n
dict(portal_status_message=_(\'Packing List updated.\')))\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>form_id, dialog_id=\'\', **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PackingList_doSolveActions</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>TaskReport_getRuleReference</string> </value> <value> <string>PackingList_getRuleReference</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>return \'default_order_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PurchaseOrder_getRuleReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,31 +50,13 @@ ...@@ -50,31 +50,13 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>if related_simulation_movement_path_list is None:\n <value> <string>context.PackingList_copyOrderProperties()\n
raise RuntimeError, \'related_simulation_movement_path_list is missing. Update ERP5 Product.\'\n context.Delivery_confirm()\n
\n
packing_list = context\n
\n
# First, copy Order properties\n
packing_list.PackingList_copyOrderProperties()\n
\n
# Then, modify state\n
confirm_tag = \'%s_confirm\' % packing_list.getPath()\n
packing_list.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
tag=confirm_tag).Delivery_confirm()\n
\n
# First set the packing_list in the building state\n
packing_list.startBuilding()\n
# Then an activity should put the causality state in diverged or solved\n
packing_list.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
after_tag=confirm_tag).updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>related_simulation_movement_path_list=None</string> </value> <value> <string>related_simulation_movement_path_list</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
<?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 \'default_delivery_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PurchasePackingList_getRuleReference</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 \'default_delivery_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ReturnedPurchasePackingList_getRuleReference</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 \'default_delivery_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ReturnedSalePackingList_getRuleReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,33 +50,13 @@ ...@@ -50,33 +50,13 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>if related_simulation_movement_path_list is None:\n <value> <string>context.PackingList_copyOrderProperties()\n
raise RuntimeError, \'related_simulation_movement_path_list is missing. Update ERP5 Product.\'\n context.Delivery_confirm()\n
\n
from Products.ERP5Type.Message import translateString\n
\n
packing_list = context\n
\n
# First, copy Order properties\n
packing_list.PackingList_copyOrderProperties()\n
\n
# Then, modify state\n
confirm_tag = \'%s_confirm\' % packing_list.getPath()\n
packing_list.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
tag=confirm_tag).Delivery_confirm()\n
\n
# First set the packing_list in the building state\n
packing_list.startBuilding()\n
# Then an activity should put the causality state in diverged or solved\n
packing_list.activate(after_path_and_method_id=(related_simulation_movement_path_list,\n
(\'immediateReindexObject\',\'recursiveImmediateReindexObject\')),\n
after_tag=confirm_tag).updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>related_simulation_movement_path_list=None</string> </value> <value> <string>related_simulation_movement_path_list</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
<?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 \'default_delivery_rule\'\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SalePackingList_getRuleReference</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>order = state_change[\'object\']\n
\n
order.applyToOrderRelatedMovement(method_id=\'expand\')\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>Order_appliedToRelatedMovement</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>order = state_change[\'object\']\n
order.Delivery_updateSimulation()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Order_createOrderRule</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_appliedToRelatedMovement</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TransitionDefinition" module="Products.DCWorkflow.Transitions"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>informDeliveryList</string> </value>
</item>
<item>
<key> <string>new_state_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>script_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>Order_createOrderRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
<?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>delivery = state_change[\'object\']\n
delivery.Delivery_updateSimulation()\n
\n
if delivery.getCausalityState() == \'draft\':\n
delivery.startBuilding()\n
path = delivery.getPath()\n
delivery.activate(\n
after_tag = (path + \'_calculate\', path + \'_updateAppliedRule\'),\n
).updateCausalityState()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
<key> <string>actbox_category</string> </key> <key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value> <value> <string>workflow</string> </value>
</item> </item>
<item>
<key> <string>actbox_icon</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>actbox_name</string> </key> <key> <string>actbox_name</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -20,7 +24,7 @@ ...@@ -20,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</item> </item>
<item> <item>
<key> <string>after_script_name</string> </key> <key> <string>after_script_name</string> </key>
<value> <string>PackingList_updateAppliedRule</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>delivery = state_change[\'object\'].getParentValue()\n <value> <string>delivery = state_change[\'object\'].getParentValue()\n
if delivery.isDelivery:\n if delivery.isDelivery:\n
delivery.Delivery_updateSimulation()\n delivery.updateSimulation(expand_related=1)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -73,7 +73,7 @@ class AmortisationRule(RuleMixin): ...@@ -73,7 +73,7 @@ class AmortisationRule(RuleMixin):
# Simulation workflow # Simulation workflow
security.declareProtected(Permissions.ModifyPortalContent, 'expand') security.declareProtected(Permissions.ModifyPortalContent, 'expand')
def expand(self, applied_rule, force=0, **kw): def expand(self, applied_rule, expand_policy=None, activate_kw={}):
""" """
Expands the current movement downward. Expands the current movement downward.
...@@ -82,6 +82,8 @@ class AmortisationRule(RuleMixin): ...@@ -82,6 +82,8 @@ class AmortisationRule(RuleMixin):
An applied rule can be expanded only if its parent movement An applied rule can be expanded only if its parent movement
is expanded. is expanded.
""" """
assert expand_policy == "immediate" and not activate_kw
invalid_state_list = self.getPortalUpdatableAmortisationTransactionStateList() invalid_state_list = self.getPortalUpdatableAmortisationTransactionStateList()
to_aggregate_movement_list = [] to_aggregate_movement_list = []
......
...@@ -40,13 +40,10 @@ from Products.ERP5Type.Base import WorkflowMethod ...@@ -40,13 +40,10 @@ from Products.ERP5Type.Base import WorkflowMethod
from Products.ERP5Type.Globals import PersistentMapping from Products.ERP5Type.Globals import PersistentMapping
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5.ExpandPolicy import TREE_DELIVERED_CACHE_KEY
from Products.ERP5.mixin.explainable import ExplainableMixin from Products.ERP5.mixin.explainable import ExplainableMixin
from Products.ERP5.mixin.rule import RuleMixin from Products.ERP5.mixin.rule import RuleMixin
TREE_DELIVERED_CACHE_KEY = 'AppliedRule._isTreeDelivered_cache'
TREE_DELIVERED_CACHE_ENABLED = 'TREE_DELIVERED_CACHE_ENABLED'
class AppliedRule(XMLObject, ExplainableMixin): class AppliedRule(XMLObject, ExplainableMixin):
""" """
An applied rule holds a list of simulation movements. An applied rule holds a list of simulation movements.
...@@ -83,7 +80,8 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -83,7 +80,8 @@ class AppliedRule(XMLObject, ExplainableMixin):
) )
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.IMovementCollection,) zope.interface.implements(interfaces.IExpandable,
interfaces.IMovementCollection)
def tpValues(self) : def tpValues(self) :
""" show the content in the left pane of the ZMI """ """ show the content in the left pane of the ZMI """
...@@ -95,74 +93,17 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -95,74 +93,17 @@ class AppliedRule(XMLObject, ExplainableMixin):
"""Tells whether generated movement needs to be accounted or not.""" """Tells whether generated movement needs to be accounted or not."""
return self.getSpecialiseValue().isAccountable(movement) return self.getSpecialiseValue().isAccountable(movement)
security.declareProtected(Permissions.ModifyPortalContent, 'expand') security.declarePrivate("getSimulationState")
@UnrestrictedMethod def getSimulationState(self):
def expand(self, **kw): return
"""
Expands the current movement downward.
-> new status -> expanded
An applied rule can be expanded only if its parent movement
is expanded.
"""
tv = getTransactionalVariable()
cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {})
cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
# enable cache security.declareProtected(Permissions.ModifyPortalContent, 'expand')
if not cache_enabled: def expand(self, *args, **kw):
cache[TREE_DELIVERED_CACHE_ENABLED] = 1 """Expand this applied rule to create new documents inside the applied rule
rule = self.getSpecialiseValue()
if rule is not None:
rule.expand(self,**kw)
# disable and clear cache
if not cache_enabled:
try:
del tv[TREE_DELIVERED_CACHE_KEY]
except KeyError:
pass
security.declareProtected(Permissions.ModifyPortalContent, 'solve')
def solve(self, solution_list):
"""
Solve inconsistency according to a certain number of solutions
templates. This updates the
-> new status -> solved
This applies a solution to an applied rule. Once
the solution is applied, the parent movement is checked.
If it does not diverge, the rule is reexpanded. If not,
diverge is called on the parent movement.
"""
rule = self.getSpecialiseValue()
if rule is not None:
rule.solve(self)
security.declareProtected(Permissions.ModifyPortalContent, 'diverge')
def diverge(self):
"""
-> new status -> diverged
This basically sets the rule to "diverged"
and blocks expansion process
""" """
rule = self.getSpecialiseValue() self.getSpecialiseValue().expand(self, *args, **kw)
if rule is not None:
rule.diverge(self)
# Solvers # Solvers
security.declareProtected(Permissions.AccessContentsInformation,
'isStable')
def isStable(self):
"""
Tells whether the rule is stable or not.
"""
return self.getSpecialiseValue().isStable(self)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'isDivergent') 'isDivergent')
def isDivergent(self, sim_mvt): def isDivergent(self, sim_mvt):
...@@ -205,26 +146,21 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -205,26 +146,21 @@ class AppliedRule(XMLObject, ExplainableMixin):
see SimulationMovement._isTreeDelivered see SimulationMovement._isTreeDelivered
""" """
tv = getTransactionalVariable() def getTreeDelivered():
cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {}) for movement in self.objectValues():
cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
def getTreeDelivered(applied_rule):
for movement in applied_rule.objectValues():
if movement._isTreeDelivered(): if movement._isTreeDelivered():
return True return True
return False return False
try:
cache = getTransactionalVariable()[TREE_DELIVERED_CACHE_KEY]
except KeyError:
return getTreeDelivered()
rule_key = self.getRelativeUrl() rule_key = self.getRelativeUrl()
if cache_enabled:
try: try:
return cache[rule_key] return cache[rule_key]
except: except KeyError:
result = getTreeDelivered(self) cache[rule_key] = result = getTreeDelivered()
cache[rule_key] = result
return result return result
else:
return getTreeDelivered(self)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getMovementList') 'getMovementList')
...@@ -234,59 +170,6 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -234,59 +170,6 @@ class AppliedRule(XMLObject, ExplainableMixin):
""" """
return self.objectValues(portal_type=RuleMixin.movement_type) return self.objectValues(portal_type=RuleMixin.movement_type)
security.declareProtected(Permissions.AccessContentsInformation,
'getIndexableChildSimulationMovementValueList')
def getIndexableChildSimulationMovementValueList(self):
return [x for x in self.getIndexableChildValueList()
if x.getPortalType() == 'Simulation Movement']
security.declarePublic('recursiveImmediateReindexSimulationMovement')
def recursiveImmediateReindexSimulationMovement(self, **kw):
"""
Applies immediateReindexObject recursively to Simulation Movements
"""
# Reindex direct children
root_indexable = int(getattr(self.getPortalObject(), 'isIndexable', 1))
for movement in self.objectValues():
if movement.isIndexable and root_indexable:
movement.immediateReindexObject(**kw)
# Go recursively
for movement in self.objectValues():
for applied_rule in movement.objectValues():
applied_rule.recursiveImmediateReindexSimulationMovement(**kw)
security.declarePublic('recursiveReindexSimulationMovement')
def recursiveReindexSimulationMovement(self, activate_kw=None, **kw):
if self.isIndexable:
if activate_kw is None:
activate_kw = {}
reindex_kw = self.getDefaultReindexParameterDict()
if reindex_kw is not None:
reindex_activate_kw = reindex_kw.pop('activate_kw', None)
if reindex_activate_kw is not None:
reindex_activate_kw = reindex_activate_kw.copy()
if activate_kw is not None:
# activate_kw parameter takes precedence
reindex_activate_kw.update(activate_kw)
activate_kw = reindex_activate_kw
kw.update(reindex_kw)
group_id_list = []
if kw.get("group_id", "") not in ('', None):
group_id_list.append(kw.get("group_id", ""))
if kw.get("sql_catalog_id", "") not in ('', None):
group_id_list.append(kw.get("sql_catalog_id", ""))
group_id = ' '.join(group_id_list)
self.activate(
group_method_id='portal_catalog/catalogObjectList',
expand_method_id='getIndexableChildSimulationMovementValueList',
alternate_method_id='alternateReindexObject',
group_id=group_id,
serialization_tag=self.getRootDocumentPath(),
**activate_kw).recursiveImmediateReindexSimulationMovement(**kw)
def _migrateSimulationTree(self, get_matching_key, def _migrateSimulationTree(self, get_matching_key,
get_original_property_dict, root_rule=None): get_original_property_dict, root_rule=None):
"""Migrate an entire simulation tree in order to use new rules """Migrate an entire simulation tree in order to use new rules
...@@ -480,7 +363,7 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -480,7 +363,7 @@ class AppliedRule(XMLObject, ExplainableMixin):
AppliedRule.isIndexable = SimulationMovement.isIndexable = \ AppliedRule.isIndexable = SimulationMovement.isIndexable = \
ConstantGetter('isIndexable', value=False) ConstantGetter('isIndexable', value=False)
mixin.updateMovementCollection = updateMovementCollection mixin.updateMovementCollection = updateMovementCollection
self.expand() self.expand("immediate")
finally: finally:
mixin.updateMovementCollection = orig_updateMovementCollection mixin.updateMovementCollection = orig_updateMovementCollection
del AppliedRule.isIndexable, SimulationMovement.isIndexable del AppliedRule.isIndexable, SimulationMovement.isIndexable
...@@ -512,7 +395,7 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -512,7 +395,7 @@ class AppliedRule(XMLObject, ExplainableMixin):
return rule_dict return rule_dict
initial_rule_dict = fillRuleDict() initial_rule_dict = fillRuleDict()
try: try:
self.expand() self.expand("immediate")
except ConflictError: except ConflictError:
raise raise
except Exception: except Exception:
......
...@@ -30,20 +30,18 @@ ...@@ -30,20 +30,18 @@
import zope.interface import zope.interface
from Products.CMFCore.utils import getToolByName
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from Products.ERP5Type.Errors import SimulationError
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5.Document.ImmobilisationDelivery import ImmobilisationDelivery from Products.ERP5.Document.ImmobilisationDelivery import ImmobilisationDelivery
from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin
from Products.ERP5.mixin.composition import CompositionMixin from Products.ERP5.mixin.composition import CompositionMixin
from Products.ERP5.mixin.rule import SimulableMixin
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from zLOG import LOG, PROBLEM from zLOG import LOG, PROBLEM
class Delivery(XMLObject, ImmobilisationDelivery, class Delivery(XMLObject, ImmobilisationDelivery, SimulableMixin,
CompositionMixin, AmountGeneratorMixin): CompositionMixin, AmountGeneratorMixin):
""" """
Each time delivery is modified, it MUST launch a reindexing of Each time delivery is modified, it MUST launch a reindexing of
...@@ -321,12 +319,6 @@ class Delivery(XMLObject, ImmobilisationDelivery, ...@@ -321,12 +319,6 @@ class Delivery(XMLObject, ImmobilisationDelivery,
container_list.append(m) container_list.append(m)
return container_list return container_list
def applyToDeliveryRelatedMovement(self, portal_type='Simulation Movement',
method_id='expand', **kw):
for simulation_movement in self._getAllRelatedSimulationMovementList():
# And apply
getattr(simulation_movement.getObject(), method_id)(**kw)
####################################################### #######################################################
# Causality computation # Causality computation
security.declareProtected(Permissions.AccessContentsInformation, 'isConvergent') security.declareProtected(Permissions.AccessContentsInformation, 'isConvergent')
...@@ -394,6 +386,16 @@ class Delivery(XMLObject, ImmobilisationDelivery, ...@@ -394,6 +386,16 @@ class Delivery(XMLObject, ImmobilisationDelivery,
else: else:
self.converge() self.converge()
def updateSimulation(self, calculate=False, **kw):
if calculate:
path = self.getPath()
self.activate(
after_tag=('built:'+path, 'expand:'+path),
after_path_and_method_id=(path, '_localBuild'),
).updateCausalityState()
if kw:
super(Delivery, self).updateSimulation(**kw)
def splitAndDeferMovementList(self, start_date=None, stop_date=None, def splitAndDeferMovementList(self, start_date=None, stop_date=None,
movement_uid_list=[], delivery_solver=None, movement_uid_list=[], delivery_solver=None,
target_solver='CopyToTarget', delivery_builder=None): target_solver='CopyToTarget', delivery_builder=None):
...@@ -434,8 +436,9 @@ class Delivery(XMLObject, ImmobilisationDelivery, ...@@ -434,8 +436,9 @@ class Delivery(XMLObject, ImmobilisationDelivery,
movement.activate(tag=solver_tag).Movement_solveMovement( movement.activate(tag=solver_tag).Movement_solveMovement(
delivery_solver, target_solver) delivery_solver, target_solver)
tag_list.append(solver_tag) tag_list.append(solver_tag)
kw = {'after_tag': tag_list[:], 'tag': expand_tag}
for s_m in deferred_simulation_movement_list: for s_m in deferred_simulation_movement_list:
s_m.activate(after_tag=tag_list[:], tag=expand_tag).expand() s_m.expand('deferred', activate_kw=kw)
tag_list.append(expand_tag) tag_list.append(expand_tag)
detached_movement_url_list = [] detached_movement_url_list = []
...@@ -476,9 +479,7 @@ class Delivery(XMLObject, ImmobilisationDelivery, ...@@ -476,9 +479,7 @@ class Delivery(XMLObject, ImmobilisationDelivery,
Reindex children and simulation Reindex children and simulation
""" """
self.recursiveReindexObject(*k, **kw) self.recursiveReindexObject(*k, **kw)
# NEW: we never rexpand simulation - This is a task for DSolver / TSolver # do not reexpand simulation: this is a task for DSolver / TSolver
# Make sure expanded simulation is still OK (expand and reindex)
# self.activate().applyToDeliveryRelatedMovement(method_id = 'expand')
####################################################### #######################################################
# Stock Management # Stock Management
...@@ -685,150 +686,50 @@ class Delivery(XMLObject, ImmobilisationDelivery, ...@@ -685,150 +686,50 @@ class Delivery(XMLObject, ImmobilisationDelivery,
########################################################################## ##########################################################################
# Applied Rule stuff # Applied Rule stuff
@UnrestrictedMethod # XXX-JPS What is this ?
def updateAppliedRule(self, rule_reference=None, rule_id=None, **kw):
"""
Create a new Applied Rule if none is related, or call expand
on the existing one.
The chosen applied rule will be the validated rule with reference ==
rule_reference, and the higher version number.
"""
if rule_id is not None:
from warnings import warn
warn('rule_id to updateAppliedRule is deprecated; use rule_reference instead',
DeprecationWarning)
rule_reference = rule_id
if rule_reference is None:
return
# only expand if we are not in a "too early" or "too late" state
if (self.getSimulationState() in
self.getPortalDraftOrderStateList()):
return
portal_rules = getToolByName(self, 'portal_rules')
res = portal_rules.searchFolder(reference=rule_reference,
validation_state="validated", sort_on='version',
sort_order='descending') # XXX validated is Hardcoded !
if len(res) > 0: security.declareProtected(Permissions.AccessContentsInformation,
rule_id = res[0].getId() 'localBuild')
def localBuild(self, activity_kw=()):
"""Activate builders for this delivery
The generated activity will find all buildable business links for this
delivery, and call related builders, which will select all simulation
movements part of the same explanation(s) as the delivery.
XXX: Consider moving it to SimulableMixin if it's useful for
Subscription Items.
"""
# XXX: Previous implementation waited for expand activities of related
# documents and even suggested to look at explanation tree,
# instead of causalities. Is it required ?
kw = {'priority': 3}
kw.update(activity_kw)
after_tag = kw.pop('after_tag', None)
if isinstance(after_tag, basestring):
after_tag = [after_tag]
else: else:
raise ValueError, 'No such rule as %r is found' % rule_reference after_tag = list(after_tag) if after_tag else []
after_tag.append('expand:' + self.getPath())
self.activate(after_tag=after_tag, **kw)._localBuild()
self._createAppliedRule(rule_id, **kw) def _localBuild(self):
"""Do an immediate local build for this delivery"""
return self.asComposedDocument().build(explanation=self)
def _createAppliedRule(self, rule_id, activate_kw=None, **kw): # deprecated - see ExpandableMixin
"""
Create a new Applied Rule is none is related, or call expand
on the existing one.
"""
# Look up if existing applied rule
my_applied_rule_list = self.getCausalityRelatedValueList(
portal_type='Applied Rule')
my_applied_rule = None
if len(my_applied_rule_list) == 0:
if self.isSimulated():
# No need to create a DeliveryRule
# if we are already in the simulation process
pass
else:
# Create a new applied order rule (portal_rules.order_rule)
portal_rules = getToolByName(self, 'portal_rules')
portal_simulation = getToolByName(self, 'portal_simulation')
my_applied_rule = portal_rules[rule_id].\
constructNewAppliedRule(portal_simulation,
activate_kw=activate_kw)
# Set causality
my_applied_rule.setCausalityValue(self)
# We must make sure this rule is indexed
# now in order not to create another one later
my_applied_rule.reindexObject(activate_kw=activate_kw, **kw)
elif len(my_applied_rule_list) == 1:
# Re expand the rule if possible
my_applied_rule = my_applied_rule_list[0]
else:
raise SimulationError('Delivery %s has more than one applied'
' rule.' % self.getRelativeUrl())
my_applied_rule_id = None
expand_activate_kw = {}
if my_applied_rule is not None:
my_applied_rule_id = my_applied_rule.getId()
expand_activate_kw['after_path_and_method_id'] = (
my_applied_rule.getPath(),
['immediateReindexObject', 'recursiveImmediateReindexObject'])
# We are now certain we have a single applied rule
# It is time to expand it
self.activate(activate_kw=activate_kw, **expand_activate_kw).expand(
applied_rule_id=my_applied_rule_id,
activate_kw=activate_kw, **kw)
security.declareProtected(Permissions.ModifyPortalContent, 'expand')
@UnrestrictedMethod @UnrestrictedMethod
def expand(self, applied_rule_id=None, activate_kw=None,**kw): def updateAppliedRule(self, rule_reference=None, rule_id=None, **kw):
""" reference = self.getRuleReference()
Reexpand applied rule if (rule_id or rule_reference) != reference:
raise RuntimeError("expected %r as rule reference, got %r"
Also reexpand all rules related to movements % (reference, rule_reference))
self._updateSimulation(create_root=1) # should it be always reexpanded ?
NOTE: seems to be deprecated ?
""" def _createRootAppliedRule(self):
excluded_rule_path_list = [] portal = self.getPortalObject()
if applied_rule_id is not None: # Only create RAR if we are not in a "too early" or "too late" state.
my_applied_rule = self.portal_simulation.get(applied_rule_id, None) if self.getSimulationState() not in portal.getPortalDraftOrderStateList():
if my_applied_rule is not None: return super(Delivery, self)._createRootAppliedRule()
excluded_rule_path_list.append(my_applied_rule.getPath())
my_applied_rule.expand(activate_kw=activate_kw,**kw)
# once expanded, the applied_rule must be reindexed
# because some simulation_movement may change even
# if there are not edited (acquisition)
#
# XXX yo thinks that this is excessive. First of all, we may
# need to reindex simulation movements but not applied rules
# here. So we should skip reindexing applied rules.
# In addition, the policy is "copy everything required to
# simulation movements", so acquisitions should not matter to
# indexing. The only exception is the simulation state.
# I think, if each simulation movement remembers the previous
# state, we can avoid unnecessary reindexing.
my_applied_rule.recursiveReindexSimulationMovement(activate_kw=activate_kw)
else:
LOG("ERP5", PROBLEM,
"Could not expand applied rule %s for delivery %s" %\
(applied_rule_id, self.getId()))
self.expandRuleRelatedToMovement(
excluded_rule_path_list=excluded_rule_path_list,
activate_kw=activate_kw,
**kw)
security.declareProtected(Permissions.ModifyPortalContent,
'expandRuleRelatedToMovement')
def expandRuleRelatedToMovement(self,excluded_rule_path_list=None,
activate_kw=None,**kw):
"""
Some delivery movement may be related to another applied rule than
the one related to the delivery. Delivery movements may be related
to many simulation movements from many different root applied rules,
so it is required to expand the applied rule parent to related
simulation movements.
exclude_rule_path : do not expand this applied rule (or children
applied rule)
"""
excluded_rule_path_list = set(excluded_rule_path_list or ())
to_expand = sorted(set(sm.getParentValue()
for sm in self._getAllRelatedSimulationMovementList()
if sm.getRootAppliedRule().getPath() not in excluded_rule_path_list),
key=lambda x: x.getRelativeUrl())
prev_ar = None
for ar in to_expand:
if not ar.aq_inContextOf(prev_ar):
ar.expand(activate_kw=activate_kw, **kw)
ar.recursiveReindexSimulationMovement(activate_kw=activate_kw)
prev_ar = ar
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getRootCausalityValueList') 'getRootCausalityValueList')
...@@ -894,15 +795,6 @@ class Delivery(XMLObject, ImmobilisationDelivery, ...@@ -894,15 +795,6 @@ class Delivery(XMLObject, ImmobilisationDelivery,
# since the main purpose of this method is superceded # since the main purpose of this method is superceded
# by IDivergenceController # by IDivergenceController
def getRuleReference(self):
"""Returns an appropriate rule reference."""
method = self._getTypeBasedMethod('getRuleReference')
if method is not None:
return method()
else:
raise SimulationError('%s_getRuleReference script is missing.'
% self.getPortalType().replace(' ', ''))
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getRootSpecialiseValue') 'getRootSpecialiseValue')
def getRootSpecialiseValue(self, portal_type_list): def getRootSpecialiseValue(self, portal_type_list):
......
...@@ -78,12 +78,7 @@ class ImmobilisableItem(Item, Amount): ...@@ -78,12 +78,7 @@ class ImmobilisableItem(Item, Amount):
, PropertySheet.Amortisation , PropertySheet.Amortisation
) )
# FIXME: ImmobilisableItem have to implement IExpandableItem, but they do zope.interface.implements(interfaces.IImmobilisationItem)
# not have 'expand' method at the time beeing, simulation methods used here
# have different names.
zope.interface.implements(interfaces.IExpandableItem,
interfaces.IImmobilisationItem)
# IExpandableItem interface implementation # IExpandableItem interface implementation
def getSimulationMovementSimulationState(self, simulation_movement): def getSimulationMovementSimulationState(self, simulation_movement):
...@@ -101,12 +96,6 @@ class ImmobilisableItem(Item, Amount): ...@@ -101,12 +96,6 @@ class ImmobilisableItem(Item, Amount):
return 'planned' return 'planned'
return 'draft' return 'draft'
def expand(self, applied_rule_id=None, activate_kw=None, **kw):
"""Expand is not implemented that way for now...
"""
pass
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getImmobilisationRelatedMovementList') 'getImmobilisationRelatedMovementList')
def getImmobilisationRelatedMovementList(self, def getImmobilisationRelatedMovementList(self,
...@@ -1076,7 +1065,7 @@ class ImmobilisableItem(Item, Amount): ...@@ -1076,7 +1065,7 @@ class ImmobilisableItem(Item, Amount):
my_applied_rule = my_applied_rule_list[-1] my_applied_rule = my_applied_rule_list[-1]
# We are now certain we have a single applied rule # We are now certain we have a single applied rule
# It is time to expand it # It is time to expand it
my_applied_rule.expand() my_applied_rule.expand('immediate') # XXX: can it be done by activity ?
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'expandAmortisation') 'expandAmortisation')
......
...@@ -37,9 +37,11 @@ from Products.ERP5Type.Base import Base ...@@ -37,9 +37,11 @@ from Products.ERP5Type.Base import Base
#from Products.ERP5.Core import MetaNode, MetaResource #from Products.ERP5.Core import MetaNode, MetaResource
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin
from Products.ERP5.mixin.composition import CompositionMixin from Products.ERP5.mixin.composition import CompositionMixin
from Products.ERP5.Document.Amount import Amount from Products.ERP5.Document.Amount import Amount
from Products.ERP5.Document.SimulatedDeliveryBuilder import BUILDING_KEY
from zLOG import LOG, WARNING from zLOG import LOG, WARNING
...@@ -582,6 +584,23 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin): ...@@ -582,6 +584,23 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin):
return (len(self.getDeliveryRelatedValueList()) > 0) or\ return (len(self.getDeliveryRelatedValueList()) > 0) or\
(len(self.getOrderRelatedValueList()) > 0) (len(self.getOrderRelatedValueList()) > 0)
security.declareProtected(Permissions.AccessContentsInformation,
'isGeneratedBySimulation')
def isGeneratedBySimulation(self):
"""
Returns true if the movement is linked to a simulation movement whose
parent is not a root applied rule, even if the movement is being built.
Otherwise, this means the movement is or should be linked to a root
simulation movement.
"""
simulation_movement = self.getDeliveryRelatedValue()
if simulation_movement is not None and \
not simulation_movement.getParentValue().isRootAppliedRule():
return True
building = getTransactionalVariable().get(BUILDING_KEY, ())
return self in building or self.getRootDeliveryValue() in building
# New Causality API # New Causality API
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getOrderQuantity') 'getOrderQuantity')
......
...@@ -27,10 +27,8 @@ ...@@ -27,10 +27,8 @@
# #
############################################################################## ##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Supply import Supply from Products.ERP5.Document.Supply import Supply
class OpenOrder(Supply): class OpenOrder(Supply):
...@@ -45,9 +43,6 @@ class OpenOrder(Supply): ...@@ -45,9 +43,6 @@ class OpenOrder(Supply):
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IExpandable)
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject , PropertySheet.XMLObject
...@@ -59,23 +54,3 @@ class OpenOrder(Supply): ...@@ -59,23 +54,3 @@ class OpenOrder(Supply):
, PropertySheet.Order , PropertySheet.Order
, PropertySheet.Version , PropertySheet.Version
) )
# Expandable Interface Implementation
def expand(self, *args, **kw):
"""
Any Open Order Line / Open Order Cell which does not relate
(aggregate) to a Subscription Item must be expanded
through the default rule.
What would be nice is to use the SubscriptionItemRule to expand
lines one by one so that an Item can be used at any time.
expansion logic is provided by the OpenOrder or by the
SubscriptionItem
Others are expanded by their Item
NOTE-JPS: not sure if it is really necessary to keep this
since only used by one client and tiolive. For tiolive
it will be dropped out
"""
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Utils import deprecated
from Products.ERP5.Document.Delivery import Delivery from Products.ERP5.Document.Delivery import Delivery
from warnings import warn from warnings import warn
...@@ -116,73 +116,13 @@ class Order(Delivery): ...@@ -116,73 +116,13 @@ class Order(Delivery):
kw.setdefault('portal_type', self.getPortalOrderMovementTypeList()) kw.setdefault('portal_type', self.getPortalOrderMovementTypeList())
return Delivery.getTotalQuantity(self, **kw) return Delivery.getTotalQuantity(self, **kw)
def applyToDeliveryRelatedMovement(self, portal_type='Simulation Movement', @deprecated
method_id='expand',**kw): def applyToOrderRelatedMovement(self, method_id='expand', **kw):
""" # WARNING: does not work if it was not catalogued immediately
Warning: does not work if it was not catalogued immediately
"""
# 'order' category is deprecated. it is kept for compatibility. # 'order' category is deprecated. it is kept for compatibility.
for my_simulation_movement in self.getDeliveryRelatedValueList( for m in self.getMovementList():
portal_type='Simulation Movement') or \
self.getOrderRelatedValueList(
portal_type='Simulation Movement'):
# And apply
getattr(my_simulation_movement, method_id)(**kw)
for m in self.contentValues(filter={'portal_type': \
self.getPortalMovementTypeList()}):
# Find related in simulation
for my_simulation_movement in m.getDeliveryRelatedValueList( for my_simulation_movement in m.getDeliveryRelatedValueList(
portal_type='Simulation Movement') or \ portal_type='Simulation Movement') or \
m.getOrderRelatedValueList( m.getOrderRelatedValueList(
portal_type='Simulation Movement'): portal_type='Simulation Movement'):
# And apply
getattr(my_simulation_movement, method_id)(**kw) getattr(my_simulation_movement, method_id)(**kw)
for c in m.contentValues(filter={'portal_type':
self.getPortalMovementTypeList()}):
for my_simulation_movement in c.getDeliveryRelatedValueList(
portal_type='Simulation Movement') or \
c.getOrderRelatedValueList(
portal_type='Simulation Movement'):
# And apply
getattr(my_simulation_movement, method_id)(**kw)
# 'order' category is deprecated. it is kept for compatibility.
applyToOrderRelatedMovement = applyToDeliveryRelatedMovement
def applyToOrderRelatedAppliedRule(self, method_id='expand',**kw):
my_applied_rule = self.getCausalityRelatedValue( \
portal_type='Applied Rule')
getattr(my_applied_rule.getObject(), method_id)(**kw)
def manage_beforeDelete(self, item, container):
"""
Delete related Applied Rule
"""
for o in self.getCausalityRelatedValueList(portal_type='Applied Rule'):
o.getParentValue().deleteContent(o.getId())
Delivery.manage_beforeDelete(self, item, container)
##########################################################################
# Applied Rule stuff
def updateAppliedRule(self, rule_id=None, rule_reference=None, **kw):
"""XXX FIXME: Kept for compatibility.
updateAppliedRule must be called with a rule_reference in a workflow
script.
"""
if rule_id is None and rule_reference is None:
warn('Relying on a default order rule is deprecated; ' \
'rule_reference must be specified explicitly.',
DeprecationWarning)
rule_reference = 'default_order_rule'
Delivery.updateAppliedRule(self, rule_id=rule_id,
rule_reference=rule_reference, **kw)
def expandAppliedRuleRelatedToOrder(self, activate_kw=None,**kw):
"""
Expand the applied rule related
"""
applied_rule_list = self.getCausalityRelatedValueList(
portal_type='Applied Rule')
for applied_rule in applied_rule_list:
# XXX Missing activate keys
applied_rule.activate(activate_kw=activate_kw).expand(**kw)
...@@ -108,18 +108,3 @@ class PackingList(Delivery): ...@@ -108,18 +108,3 @@ class PackingList(Delivery):
return 0 return 0
return 1 return 1
##########################################################################
# Applied Rule stuff
def updateAppliedRule(self, rule_id=None, rule_reference=None, **kw):
"""XXX FIXME: Kept for compatibility.
updateAppliedRule must be called with a rule_reference in a workflow
script.
"""
if rule_id is None and rule_reference is None:
warn('Relying on a default delivery rule is deprecated; ' \
'rule_reference must be specified explicitly.',
DeprecationWarning)
rule_reference = 'default_delivery_rule'
Delivery.updateAppliedRule(self, rule_id=rule_id,
rule_reference=rule_reference, **kw)
...@@ -122,9 +122,8 @@ class QuantitySplitSolver(SolverMixin, ConfigurableMixin, XMLObject): ...@@ -122,9 +122,8 @@ class QuantitySplitSolver(SolverMixin, ConfigurableMixin, XMLObject):
new_movement.setStopDate(stop_date) new_movement.setStopDate(stop_date)
if activate_kw: if activate_kw:
new_movement.setDefaultActivateParameterDict({}) new_movement.setDefaultActivateParameterDict({})
# XXX we need to call expand on both simulation_movement and new_movement here? simulation_movement.expand(activate_kw=activate_kw)
# simulation_movement.expand(activate_kw=activate_kw) new_movement.expand(activate_kw=activate_kw)
# new_movement.expand(activate_kw=activate_kw)
# Finish solving # Finish solving
if self.getPortalObject().portal_workflow.isTransitionPossible( if self.getPortalObject().portal_workflow.isTransitionPossible(
self, 'succeed'): self, 'succeed'):
......
...@@ -31,9 +31,16 @@ from zLOG import LOG, BLATHER ...@@ -31,9 +31,16 @@ from zLOG import LOG, BLATHER
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.mixin.builder import BuilderMixin, SelectMethodError from Products.ERP5.mixin.builder import BuilderMixin, SelectMethodError
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Type.CopySupport import CopyError, tryMethodCallWithTemporaryPermission from Products.ERP5Type.CopySupport import CopyError, tryMethodCallWithTemporaryPermission
# Quite ugly way to avoid useless expand when building lines
# in a delivery that already have lines and a root applied rule.
# For example, it's normally useless to expand after building
# accounting lines in an invoice with manually created invoice lines.
BUILDING_KEY = 'building_from_portal_simulation'
class SimulatedDeliveryBuilder(BuilderMixin): class SimulatedDeliveryBuilder(BuilderMixin):
""" """
Delivery Builder objects allow to gather multiple Simulation Movements Delivery Builder objects allow to gather multiple Simulation Movements
...@@ -137,6 +144,12 @@ class SimulatedDeliveryBuilder(BuilderMixin): ...@@ -137,6 +144,12 @@ class SimulatedDeliveryBuilder(BuilderMixin):
Create the relation between simulation movement Create the relation between simulation movement
and delivery movement. and delivery movement.
""" """
delivery = delivery_movement.getExplanationValue()
building = getTransactionalVariable()[BUILDING_KEY]
if delivery in building:
building.add(delivery_movement)
simulation_movement.recursiveReindexObject(activate_kw=dict(
activate_kw or (), tag='built:'+delivery.getPath()))
BuilderMixin._setDeliveryMovementProperties( BuilderMixin._setDeliveryMovementProperties(
self, delivery_movement, self, delivery_movement,
simulation_movement, property_dict, simulation_movement, property_dict,
...@@ -151,12 +164,22 @@ class SimulatedDeliveryBuilder(BuilderMixin): ...@@ -151,12 +164,22 @@ class SimulatedDeliveryBuilder(BuilderMixin):
# Delivery will probably diverge now, but this is not the job of # Delivery will probably diverge now, but this is not the job of
# Delivery Builder to resolve such problem. # Delivery Builder to resolve such problem.
# Use Solver instead. # Use Solver instead.
simulation_movement.edit(delivery_ratio=0) simulation_movement._setDeliveryRatio(0)
else: else:
simulation_movement.edit(delivery_ratio=1) simulation_movement._setDeliveryRatio(1)
delivery_movement = delivery_movement.getRelativeUrl()
simulation_movement.edit(delivery_value=delivery_movement, if simulation_movement.getDeliveryList() != [delivery_movement]:
activate_kw=activate_kw) simulation_movement._setDelivery(delivery_movement)
if not simulation_movement.isTempDocument():
try:
getCausalityState = delivery.aq_explicit.getCausalityState
except AttributeError:
return
if getCausalityState() == 'building':
# Make sure no other node is changing state of the delivery
delivery.serializeCausalityState()
else:
delivery.startBuilding()
# Simulation consistency propagation # Simulation consistency propagation
security.declareProtected(Permissions.ModifyPortalContent, security.declareProtected(Permissions.ModifyPortalContent,
...@@ -337,6 +360,10 @@ class SimulatedDeliveryBuilder(BuilderMixin): ...@@ -337,6 +360,10 @@ class SimulatedDeliveryBuilder(BuilderMixin):
new_delivery_id = str(delivery_module.generateNewId()) new_delivery_id = str(delivery_module.generateNewId())
delivery = super(SimulatedDeliveryBuilder, self)._createDelivery( delivery = super(SimulatedDeliveryBuilder, self)._createDelivery(
delivery_module, movement_list, activate_kw) delivery_module, movement_list, activate_kw)
# Interactions will usually trigger reindexing of related SM when
# simulation state changes. Disable them for this transaction
# because we already do this in _setDeliveryMovementProperties
delivery.updateSimulation(index_related=0)
else: else:
# from duplicated original delivery # from duplicated original delivery
cp = tryMethodCallWithTemporaryPermission( cp = tryMethodCallWithTemporaryPermission(
...@@ -353,6 +380,25 @@ class SimulatedDeliveryBuilder(BuilderMixin): ...@@ -353,6 +380,25 @@ class SimulatedDeliveryBuilder(BuilderMixin):
return delivery return delivery
def _processDeliveryLineGroup(self, delivery, movement_group_node,
*args, **kw):
building = getTransactionalVariable().setdefault(BUILDING_KEY, set())
if None in building:
super(SimulatedDeliveryBuilder, self)._processDeliveryLineGroup(
delivery, movement_group_node, *args, **kw)
return
building.add(None)
try:
for movement in movement_group_node.getMovementList():
if not movement.isTempDocument():
building.add(delivery)
break
super(SimulatedDeliveryBuilder, self)._processDeliveryLineGroup(
delivery, movement_group_node, *args, **kw)
finally:
building.remove(None)
building.discard(delivery)
def _createDeliveryLine(self, delivery, movement_list, activate_kw): def _createDeliveryLine(self, delivery, movement_list, activate_kw):
""" """
Refer to the docstring in GeneratedDeliveryBuilder. Refer to the docstring in GeneratedDeliveryBuilder.
......
...@@ -27,21 +27,16 @@ ...@@ -27,21 +27,16 @@
# #
############################################################################## ##############################################################################
import transaction
import zope.interface import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5.Document.Movement import Movement from Products.ERP5.Document.Movement import Movement
from Products.ERP5.ExpandPolicy import policy_dict, TREE_DELIVERED_CACHE_KEY
from zLOG import LOG, WARNING from zLOG import LOG, WARNING
from Acquisition import aq_base
from Products.ERP5.Document.AppliedRule import TREE_DELIVERED_CACHE_KEY, TREE_DELIVERED_CACHE_ENABLED
from Products.ERP5.mixin.property_recordable import PropertyRecordableMixin from Products.ERP5.mixin.property_recordable import PropertyRecordableMixin
from Products.ERP5.mixin.explainable import ExplainableMixin from Products.ERP5.mixin.explainable import ExplainableMixin
...@@ -120,7 +115,8 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -120,7 +115,8 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
) )
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.IPropertyRecordable, ) zope.interface.implements(interfaces.IExpandable,
interfaces.IPropertyRecordable)
def tpValues(self) : def tpValues(self) :
""" show the content in the left pane of the ZMI """ """ show the content in the left pane of the ZMI """
...@@ -134,22 +130,6 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -134,22 +130,6 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
""" """
return self._baseGetPrice(default) # Call the price method return self._baseGetPrice(default) # Call the price method
security.declareProtected( Permissions.AccessContentsInformation,
'getCausalityState')
def getCausalityState(self):
"""
Returns the current state in causality
"""
return getattr(aq_base(self), 'causality_state', 'solved')
security.declareProtected( Permissions.ModifyPortalContent,
'setCausalityState')
def setCausalityState(self, value):
"""
Change causality state
"""
self.causality_state = value
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getSimulationState') 'getSimulationState')
def getSimulationState(self, id_only=1): def getSimulationState(self, id_only=1):
...@@ -171,22 +151,19 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -171,22 +151,19 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
if order is not None: if order is not None:
return order.getSimulationState() return order.getSimulationState()
parent = self.getParentValue() applied_rule = self.getParentValue()
try: parent = applied_rule.getParentValue()
try: try:
parent_state = parent.getSimulationState() if isinstance(parent, SimulationMovement):
except AttributeError: return parent_to_movement_simulation_state[parent.getSimulationState()]
item = parent.getCausalityValue( getState = applied_rule.getCausalityValue() \
portal_type=self.getPortalItemTypeList()) .aq_explicit.getSimulationMovementSimulationState
if interfaces.IExpandableItem.providedBy(item): except (AttributeError, KeyError):
return item.getSimulationMovementSimulationState(self)
raise
return parent_to_movement_simulation_state[parent_state]
except (KeyError, AttributeError):
LOG('SimulationMovement.getSimulationState', WARNING, LOG('SimulationMovement.getSimulationState', WARNING,
'Could not acquire simulation state from %s' 'Could not acquire simulation state from %s'
% self.getRelativeUrl(), error=True) % self.getRelativeUrl(), error=True)
return None else:
return getState(self)
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getTranslatedSimulationStateTitle') 'getTranslatedSimulationStateTitle')
...@@ -255,35 +232,6 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -255,35 +232,6 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
####################################################### #######################################################
# Causality Workflow Methods # Causality Workflow Methods
security.declareProtected(Permissions.ModifyPortalContent, 'calculate')
def calculate(self):
"""Move related delivery in 'calculating' state by activity
Activity to update causality state is delayed until all related simulation
movement are reindexed.
This method should be only called by
simulation_movement_causality_interaction_workflow.
"""
delivery = self.getDeliveryValue()
if delivery is not None:
delivery = delivery.getRootDeliveryValue()
tv = getTransactionalVariable()
path = self.getPath()
delivery_path = delivery.getPath()
key = 'SimulationMovement.calculate', delivery_path
try:
tv[key].append(path)
except KeyError:
tv[key] = [path]
def before_commit():
method_id_list = ('immediateReindexObject',
'recursiveImmediateReindexObject')
tag = delivery_path + '_calculate'
delivery.activate(tag=tag).Delivery_calculate(activate_kw=
{'after_path_and_method_id': (tv[key], method_id_list)})
tv[key] = None # disallow further calls to 'calculate'
transaction.get().addBeforeCommitHook(before_commit)
security.declarePrivate('_getApplicableRuleList') security.declarePrivate('_getApplicableRuleList')
def _getApplicableRuleList(self): def _getApplicableRuleList(self):
""" Search rules that match this movement """ Search rules that match this movement
...@@ -297,25 +245,32 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -297,25 +245,32 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
sort_order='descending') sort_order='descending')
security.declareProtected(Permissions.ModifyPortalContent, 'expand') security.declareProtected(Permissions.ModifyPortalContent, 'expand')
def expand(self, **kw): def expand(self, expand_policy=None, **kw):
""" """Update applied rules inside this simulation movement and expand them
Checks all existing applied rules and make sure they still apply. Checks all existing applied rules and make sure they still apply.
Checks for other possible rules and starts expansion process (instanciates Checks for other possible rules and starts expansion process (instanciates
applied rules and calls expand on them). applied rules and calls expand on them).
"""
policy_dict[expand_policy](**kw).expand(self)
def _expandNow(self, maybe_expand):
"""
First get all applicable rules, First get all applicable rules,
then, delete all applied rules that no longer match and are not linked to then, delete all applied rules that no longer match and are not linked to
a delivery, a delivery, or expand those that still apply,
finally, apply new rules if no rule with the same type is already applied. finally, apply new rules if no rule with the same type is already applied.
""" """
tv = getTransactionalVariable() # XXX: Although policy is "copy everything required to simulation
cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {}) # movements", we must reindex in case that simulation state has
cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0) # changed.
# Also, if this movement is edited (by 'expand' call on the parent),
# enable cache # there's already a reindexing activity so this does nothing; but if
if not cache_enabled: # 'expand' was deferred for this movement, this will generate a
cache[TREE_DELIVERED_CACHE_ENABLED] = 1 # second & useless reindexing activity.
# All this could be avoided if each simulation movement remembered
# the previous state.
self.reindexObject()
applicable_rule_dict = {} applicable_rule_dict = {}
for rule in self._getApplicableRuleList(): for rule in self._getApplicableRuleList():
reference = rule.getReference() reference = rule.getReference()
...@@ -339,28 +294,10 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -339,28 +294,10 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
else: else:
self._delObject(applied_rule.getId()) self._delObject(applied_rule.getId())
else: else:
applied_rule.expand(**kw) maybe_expand(rule, applied_rule)
for rule in applicable_rule_list: for rule in applicable_rule_list:
rule.constructNewAppliedRule(self, **kw).expand(**kw) maybe_expand(rule, rule.constructNewAppliedRule(self))
self.setCausalityState('expanded')
# disable and clear cache
if not cache_enabled:
try:
del tv[TREE_DELIVERED_CACHE_KEY]
except KeyError:
pass
security.declareProtected(Permissions.ModifyPortalContent, 'diverge')
def diverge(self):
"""
-> new status -> diverged
Movements which diverge can not be expanded
"""
self.setCausalityState('diverged')
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getExplanationValue') 'getExplanationValue')
...@@ -580,7 +517,7 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -580,7 +517,7 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
# 'recursiveImmediateReindexObject'])) # 'recursiveImmediateReindexObject']))
# activity.edit() # activity.edit()
def _isTreeDelivered(self, ignore_first=0): def _isTreeDelivered(self):
""" """
checks if subapplied rules of this movement (going down the complete checks if subapplied rules of this movement (going down the complete
simulation tree) have a child with a delivery relation. simulation tree) have a child with a delivery relation.
...@@ -588,32 +525,23 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -588,32 +525,23 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
see AppliedRule._isTreeDelivered see AppliedRule._isTreeDelivered
""" """
tv = getTransactionalVariable() def getTreeDelivered():
cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {}) if self.getDeliveryList():
cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
def getTreeDelivered(movement, ignore_first=0):
if not ignore_first:
if len(movement.getDeliveryList()) > 0:
return True return True
for applied_rule in movement.objectValues(): for applied_rule in self.objectValues():
if applied_rule._isTreeDelivered(): if applied_rule._isTreeDelivered():
return True return True
return False return False
try:
if ignore_first: cache = getTransactionalVariable()[TREE_DELIVERED_CACHE_KEY]
rule_key = (self.getRelativeUrl(), 1) except KeyError:
else: return getTreeDelivered()
rule_key = self.getRelativeUrl() rule_key = self.getRelativeUrl()
if cache_enabled:
try: try:
return cache[rule_key] return cache[rule_key]
except KeyError: except KeyError:
result = getTreeDelivered(self, ignore_first=ignore_first) cache[rule_key] = result = getTreeDelivered()
cache[rule_key] = result
return result return result
else:
return getTreeDelivered(self, ignore_first=ignore_first)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'isBuildable') 'isBuildable')
......
...@@ -180,8 +180,9 @@ class SolverProcess(XMLObject, ActiveProcess): ...@@ -180,8 +180,9 @@ class SolverProcess(XMLObject, ActiveProcess):
""" """
Start solving Start solving
""" """
isTransitionPossible = self.getPortalObject().portal_workflow.isTransitionPossible portal = self.getPortalObject()
for solver in self.contentValues(portal_type=self.getPortalObject().getPortalTargetSolverTypeList()): isTransitionPossible = portal.portal_workflow.isTransitionPossible
for solver in self.objectValues(portal_type=portal.getPortalTargetSolverTypeList()):
if solver.isTempObject(): if solver.isTempObject():
solver_type = solver.getPortalTypeValue() solver_type = solver.getPortalTypeValue()
# Since multiple documents may need the same solver, activity must be # Since multiple documents may need the same solver, activity must be
......
...@@ -30,19 +30,18 @@ ...@@ -30,19 +30,18 @@
import zope.interface import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.Errors import SimulationError
from Products.ERP5.Document.Item import Item from Products.ERP5.Document.Item import Item
from Products.ERP5.mixin.composition import CompositionMixin from Products.ERP5.mixin.composition import CompositionMixin
from Products.ERP5.mixin.rule import MovementGeneratorMixin from Products.ERP5.mixin.rule import MovementGeneratorMixin, SimulableMixin
from Products.ERP5.mixin.periodicity import PeriodicityMixin from Products.ERP5.mixin.periodicity import PeriodicityMixin
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Type.Base import Base from Products.ERP5Type.Base import Base
from zLOG import LOG from zLOG import LOG
class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, PeriodicityMixin): class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin,
SimulableMixin, PeriodicityMixin):
""" """
A SubscriptionItem is an Item which expands itself A SubscriptionItem is an Item which expands itself
into simulation movements which represent the item future. into simulation movements which represent the item future.
...@@ -70,37 +69,15 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici ...@@ -70,37 +69,15 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici
) )
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.IExpandableItem, zope.interface.implements(interfaces.IMovementGenerator,
interfaces.IMovementGenerator,
) )
# IExpandable interface implementation def _createRootAppliedRule(self):
@UnrestrictedMethod # YXU - Is it a good permission setting?
def expand(self, applied_rule_id=None, activate_kw=None, **kw):
"""
Lookup start / stop properties in related Open Order
or Path and expand.
"""
# only try to expand if we are not in draft state # only try to expand if we are not in draft state
if self.getValidationState() in ('draft', ): # XXX-JPS harcoded if self.getValidationState() in ('draft', ): # XXX-JPS harcoded
return return
return super(SubscriptionItem, self)._createRootAppliedRule()
# do not expand if no bp/stc is applied
if self.getSpecialiseValue() is None:
return
# use hint if provided (but what for ?) XXX-JPS
if applied_rule_id is not None:
portal_simulation = getToolByName(self, 'portal_simulation')
my_applied_rule = portal_simulation[applied_rule_id]
else:
my_applied_rule = self._getRootAppliedRule(activate_kw=activate_kw)
# Pass expand
if my_applied_rule is not None:
my_applied_rule.expand(activate_kw=activate_kw, **kw) # XXX-JPS why **kw ?
# IExpandableItem interface implementation
def getSimulationMovementSimulationState(self, simulation_movement): def getSimulationMovementSimulationState(self, simulation_movement):
"""Returns the simulation state for this simulation movement. """Returns the simulation state for this simulation movement.
...@@ -120,139 +97,6 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici ...@@ -120,139 +97,6 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici
""" """
return False return False
def getRuleReference(self):
"""Returns an appropriate rule reference.
XXX Copy/Paste from delivery
"""
method = self._getTypeBasedMethod('getRuleReference')
if method is not None:
return method()
else:
raise SimulationError('%s_getRuleReference script is missing.'
% self.getPortalType().replace(' ', ''))
@UnrestrictedMethod # XXX-JPS What is this ?
def updateAppliedRule(self, rule_reference=None, rule_id=None, **kw):
"""
Create a new Applied Rule if none is related, or call expand
on the existing one.
The chosen applied rule will be the validated rule with reference ==
rule_reference, and the higher version number.
"""
if rule_id is not None:
from warnings import warn
warn('rule_id to updateAppliedRule is deprecated; use rule_reference instead',
DeprecationWarning)
rule_reference = rule_id
if rule_reference is None:
return
portal_rules = getToolByName(self, 'portal_rules')
res = portal_rules.searchFolder(reference=rule_reference,
validation_state="validated", sort_on='version',
sort_order='descending') # XXX validated is Hardcoded !
if len(res) > 0:
rule_id = res[0].getId()
else:
raise ValueError, 'No such rule as %r is found' % rule_reference
self._createAppliedRule(rule_id, **kw)
def _createAppliedRule(self, rule_id, activate_kw=None, **kw):
"""
Create a new Applied Rule is none is related, or call expand
on the existing one.
"""
# Look up if existing applied rule
my_applied_rule_list = self.getCausalityRelatedValueList(
portal_type='Applied Rule')
my_applied_rule = None
if len(my_applied_rule_list) == 0:
if self.isSimulated():
# No need to create a DeliveryRule
# if we are already in the simulation process
pass
else:
# Create a new applied order rule (portal_rules.order_rule)
portal_rules = getToolByName(self, 'portal_rules')
portal_simulation = getToolByName(self, 'portal_simulation')
my_applied_rule = portal_rules[rule_id].\
constructNewAppliedRule(portal_simulation,
activate_kw=activate_kw)
# Set causality
my_applied_rule.setCausalityValue(self)
# We must make sure this rule is indexed
# now in order not to create another one later
my_applied_rule.reindexObject(activate_kw=activate_kw, **kw)
elif len(my_applied_rule_list) == 1:
# Re expand the rule if possible
my_applied_rule = my_applied_rule_list[0]
else:
raise SimulationError('Delivery %s has more than one applied'
' rule.' % self.getRelativeUrl())
my_applied_rule_id = None
expand_activate_kw = {}
if my_applied_rule is not None:
my_applied_rule_id = my_applied_rule.getId()
expand_activate_kw['after_path_and_method_id'] = (
my_applied_rule.getPath(),
['immediateReindexObject', 'recursiveImmediateReindexObject'])
# We are now certain we have a single applied rule
# It is time to expand it
self.activate(activate_kw=activate_kw, **expand_activate_kw).expand(
applied_rule_id=my_applied_rule_id,
activate_kw=activate_kw, **kw)
def _getRootAppliedRule(self, tested_base_category_list=None,
activate_kw=None):
"""
Returns existing root applied rule or, if none,
create a new one a return it
"""
# Look up if existing applied rule
my_applied_rule_list = self.getCausalityRelatedValueList(
portal_type='Applied Rule')
my_applied_rule = None
if len(my_applied_rule_list) == 0:
if self.isSimulated():
# No need to create a DeliveryRule
# if we are already in the simulation process
pass
else:
# Create a new applied order rule (portal_rules.order_rule)
portal_rules = getToolByName(self, 'portal_rules')
portal_simulation = getToolByName(self, 'portal_simulation')
search_rule_kw = { 'sort_on': 'version', 'sort_order': 'descending' }
if self.getRuleReference() is None:
rule_value_list = portal_rules.searchRuleList(self, **search_rule_kw)
if len(rule_value_list) > 1:
raise SimulationError('Expandable Document %s has more than one'
' matching rule.' % self.getRelativeUrl())
else:
rule_value_list = portal_rules.searchRuleList(self,
reference=self.getRuleReference(), **search_rule_kw)
if len(rule_value_list):
rule_value = rule_value_list[0]
my_applied_rule = rule_value.constructNewAppliedRule(portal_simulation,
activate_kw=activate_kw)
# Set causality
my_applied_rule.setCausalityValue(self)
# We must make sure this rule is indexed
# now in order not to create another one later
my_applied_rule.reindexObject(activate_kw=activate_kw) # XXX-JPS removed **kw
elif len(my_applied_rule_list) == 1:
# Re expand the rule if possible
my_applied_rule = my_applied_rule_list[0]
else:
raise SimulationError('Expandable Document %s has more than one root'
' applied rule.' % self.getRelativeUrl())
return my_applied_rule
# IMovementGenerator interface implementation # IMovementGenerator interface implementation
def _getUpdatePropertyDict(self, input_movement): def _getUpdatePropertyDict(self, input_movement):
# Default implementation bellow can be overriden by subclasses # Default implementation bellow can be overriden by subclasses
...@@ -268,7 +112,6 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici ...@@ -268,7 +112,6 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici
""" """
from Products.ERP5Type.Document import newTempMovement from Products.ERP5Type.Document import newTempMovement
result = [] result = []
catalog_tool = getToolByName(self, 'portal_catalog')
# Try to find the source open order # Try to find the source open order
open_order_movement_list = self.getAggregateRelatedValueList( open_order_movement_list = self.getAggregateRelatedValueList(
...@@ -293,7 +136,7 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici ...@@ -293,7 +136,7 @@ class SubscriptionItem(Item, CompositionMixin, MovementGeneratorMixin, Periodici
price = movement.getPrice() price = movement.getPrice()
price_currency = movement.getPriceCurrency() price_currency = movement.getPriceCurrency()
base_application_list = movement.getBaseApplicationList() base_application_list = movement.getBaseApplicationList()
base_contribution_list = movement.getBaseContributionList() base_contribution_list = movhement.getBaseContributionList()
use_list = movement.getUseList() use_list = movement.getUseList()
specialise = movement.getSpecialise() specialise = movement.getSpecialise()
......
...@@ -112,7 +112,7 @@ class TradeModelSolver(AcceptSolver): ...@@ -112,7 +112,7 @@ class TradeModelSolver(AcceptSolver):
if not simulation_movement.isPropertyRecorded(property_id): if not simulation_movement.isPropertyRecorded(property_id):
simulation_movement.recordProperty(property_id) simulation_movement.recordProperty(property_id)
simulation_movement.setMappedProperty(property_id, value) simulation_movement.setMappedProperty(property_id, value)
simulation_movement.expand(activate_kw=activate_kw) simulation_movement.expand('immediate')
# Third, adopt changes on trade model related lines. # Third, adopt changes on trade model related lines.
# XXX non-linear case is not yet supported. # XXX non-linear case is not yet supported.
......
...@@ -125,7 +125,8 @@ class UnifySolver(AcceptSolver): ...@@ -125,7 +125,8 @@ class UnifySolver(AcceptSolver):
if not simulation_movement.isPropertyRecorded(solved_property): if not simulation_movement.isPropertyRecorded(solved_property):
simulation_movement.recordProperty(solved_property) simulation_movement.recordProperty(solved_property)
simulation_movement.setMappedProperty(solved_property, value) simulation_movement.setMappedProperty(solved_property, value)
simulation_movement.expand(activate_kw=activate_kw) # XXX: would it be safe to expand by activity ?
simulation_movement.expand('immediate')
# Finish solving # Finish solving
if portal.portal_workflow.isTransitionPossible(self, 'succeed'): if portal.portal_workflow.isTransitionPossible(self, 'succeed'):
self.succeed() self.succeed()
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2012 Nexedi SARL and Contributors. All Rights Reserved.
# Julien Muchembled <jm@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
##############################################################################
from time import time
import transaction
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Type.Utils import convertToLowerCase
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
# XXX: Consider moving it to ERP5Type if it implements recursion policies
# for anything other than expand.
# XXX: Policy of deferred expands currently is currently hardcoded to the
# preferred one, which is itself hardcoded to "vertical_time_bound".
# If any parameter is added to policies in order to make them customizable,
# Base class should probably handle this automatically by:
# - keeping all parameters in a 'kw' attribute and;
# - activating with something like 'expand(policy, **self.kw)'
# It may also be better if that 'kw' does not mix up several kinds of
# parameters, for example those that are specific to the policy
# (e.g. policy_kw), and other for expand() itself (e.g. expand_kw).
# Any extension to the API must be reviewed first.
# Put there to avoid circular import loop.
TREE_DELIVERED_CACHE_KEY = 'AppliedRule._isTreeDelivered'
policy_dict = {} # {None: preferred, 'foo_bar': FooBar}
VERTICAL_EXPAND_TIMEOUT = 5 # XXX: hardcoded for the moment
class _Policy(object):
"""Base class of policies for RuleMixin.expand and SimulationMovement.expand
"""
class __metaclass__(type):
"""Automatically register policies in policy_dict"""
def __init__(cls, name, bases, d):
type.__init__(cls, name, bases, d)
if name[0] != '_':
policy_dict[convertToLowerCase(name)[1:]] = cls
def __init__(self, activate_kw=None):
self.activate_kw = activate_kw
@UnrestrictedMethod
def expand(self, *args):
"""Initialize context, and really start to expand"""
tv = getTransactionalVariable()
assert TREE_DELIVERED_CACHE_KEY not in tv, "already expanding"
self.context = args[-1]
with self.context.defaultActivateParameterDict(self.activate_kw, True):
tv[TREE_DELIVERED_CACHE_KEY] = {}
try:
self(*args)
finally:
del tv[TREE_DELIVERED_CACHE_KEY]
# lazy computation of root applied rule path
def __getattr__(self, attr):
if attr == 'merge_parent':
self.merge_parent = value = self.context.getRootAppliedRule().getPath()
else:
object.__getattribute__(self, attr)
return value
def deferAll(self):
self.test = self.activate
def activate(self, context):
context.activate(merge_parent=self.merge_parent) \
.expand(activate_kw=self.activate_kw)
def __call__(self, *args):
context = args[-1]
if self.test(context):
args[0]._expandNow(self, *args[1:])
class Deferred(_Policy):
"""Do not expand anything in the current transaction, but do it by activity"""
# We won't expand at all so we override expand() to avoid wasting time on
# initializing anything.
def expand(self, *args):
context = args[-1]
kw = self.activate_kw
context.activate(merge_parent=context.getRootAppliedRule().getPath(),
**(kw or {})).expand(activate_kw=kw)
class Immediate(_Policy):
"""Expand everything immediately"""
# Optimize by overriding '__call__' instead of 'test'
#test = lambda *args: True
def __call__(self, *args):
args[0]._expandNow(self, *args[1:])
class VerticalTimeBound(_Policy):
"""Vertical recursion, limited by duration
Expand immediately only if the current transaction is young enough.
Defer by activity otherwise.
"""
def __init__(self, **kw):
super(VerticalTimeBound, self).__init__(**kw)
self.stop = transaction.get().start_time + VERTICAL_EXPAND_TIMEOUT
def test(self, context):
if time() < self.stop:
return True
self.deferAll()
self.test(context)
# XXX: Should be a function reading system preferences
preferred = VerticalTimeBound
policy_dict[None] = preferred
...@@ -322,12 +322,26 @@ class FakeMovement: ...@@ -322,12 +322,26 @@ class FakeMovement:
""" """
return self.__movement_list return self.__movement_list
def setDeliveryValue(self, object): def isTempDocument(self):
for movement in self.__movement_list:
if movement.isTempDocument():
return True
return False
def _setDelivery(self, object):
""" """
Set Delivery value for each movement Set Delivery value for each movement
""" """
for movement in self.__movement_list: for movement in self.__movement_list:
movement.edit(delivery_value=object) movement._setDelivery(object)
def getDeliveryList(self):
"""
Only used to know if _setDeliveryValue needs to be called.
Be careful: behaviour differs from CMFCategory in that returned
list may include None, when there is at least 1 unlinked SM.
"""
return list(set(x.getDelivery() for x in self.__movement_list))
def getDeliveryValue(self): def getDeliveryValue(self):
""" """
...@@ -335,13 +349,10 @@ class FakeMovement: ...@@ -335,13 +349,10 @@ class FakeMovement:
configure DeliveryBuilder well...). configure DeliveryBuilder well...).
Be careful. Be careful.
""" """
result = None
for movement in self.__movement_list: for movement in self.__movement_list:
mvt_delivery = movement.getDeliveryValue() mvt_delivery = movement.getDeliveryValue()
if mvt_delivery is not None: if mvt_delivery is not None:
result = mvt_delivery return mvt_delivery
break
return result
def getRelativeUrl(self): def getRelativeUrl(self):
""" """
...@@ -351,7 +362,7 @@ class FakeMovement: ...@@ -351,7 +362,7 @@ class FakeMovement:
""" """
return self.__movement_list[0].getRelativeUrl() return self.__movement_list[0].getRelativeUrl()
def setDeliveryRatio(self, delivery_ratio): def _setDeliveryRatio(self, delivery_ratio):
""" """
Calculate delivery_ratio Calculate delivery_ratio
""" """
...@@ -359,15 +370,15 @@ class FakeMovement: ...@@ -359,15 +370,15 @@ class FakeMovement:
for movement in self.__movement_list: for movement in self.__movement_list:
total_quantity += movement.getMappedProperty('quantity') total_quantity += movement.getMappedProperty('quantity')
if total_quantity != 0: if total_quantity:
for movement in self.__movement_list: for movement in self.__movement_list:
quantity = movement.getMappedProperty('quantity') quantity = movement.getMappedProperty('quantity')
movement.edit(delivery_ratio=quantity*float(delivery_ratio)/total_quantity) movement._setDeliveryRatio(quantity*float(delivery_ratio)/total_quantity)
else: else:
# Distribute equally ratio to all movement # Distribute equally ratio to all movements
mvt_ratio = float(delivery_ratio) / len(self.__movement_list) mvt_ratio = float(delivery_ratio) / len(self.__movement_list)
for movement in self.__movement_list: for movement in self.__movement_list:
movement.edit(delivery_ratio=mvt_ratio) movement._setDeliveryRatio(mvt_ratio)
def getPrice(self): def getPrice(self):
""" """
...@@ -450,19 +461,12 @@ class FakeMovement: ...@@ -450,19 +461,12 @@ class FakeMovement:
price_dict = self._getPriceDict() price_dict = self._getPriceDict()
return sum(price * quantity for price, quantity in price_dict.items()) return sum(price * quantity for price, quantity in price_dict.items())
def recursiveReindexObject(self): def recursiveReindexObject(self, *args, **kw):
""" """
Reindex all movements Reindex all movements
""" """
for movement in self.getMovementList(): for movement in self.getMovementList():
movement.recursiveReindexObject() movement.recursiveReindexObject(*args, **kw)
def immediateReindexObject(self):
"""
Reindex immediately all movements
"""
for movement in self.getMovementList():
movement.immediateReindexObject()
def getPath(self): def getPath(self):
""" """
...@@ -509,23 +513,6 @@ class FakeMovement: ...@@ -509,23 +513,6 @@ class FakeMovement:
else: else:
raise NotImplementedError raise NotImplementedError
def edit(self, activate_kw=None, **kw):
"""
Written in order to call edit in delivery builder,
as it is the generic way to modify object.
activate_kw is here for compatibility reason with Base.edit,
it will not be used here.
"""
for key in kw.keys():
if key == 'delivery_ratio':
self.setDeliveryRatio(kw[key])
elif key == 'delivery_value':
self.setDeliveryValue(kw[key])
else:
raise FakeMovementError,\
"Could not call edit on Fakemovement with parameters: %r" % key
def __repr__(self): def __repr__(self):
repr_str = '<%s object at 0x%x for %r' % (self.__class__.__name__, repr_str = '<%s object at 0x%x for %r' % (self.__class__.__name__,
id(self), id(self),
......
...@@ -79,5 +79,5 @@ class Copy(TargetSolver): ...@@ -79,5 +79,5 @@ class Copy(TargetSolver):
simulation_movement.recordProperty(property_id) simulation_movement.recordProperty(property_id)
simulation_movement.edit(**value_dict) simulation_movement.edit(**value_dict)
# XXX can we use activity for further expand? # XXX: would it be safe to expand by activity ?
simulation_movement.expand() simulation_movement.expand('immediate')
...@@ -73,8 +73,8 @@ class CopyAndPropagate(TargetSolver): ...@@ -73,8 +73,8 @@ class CopyAndPropagate(TargetSolver):
quantity_ratio=quantity_ratio, quantity_ratio=quantity_ratio,
value_dict=value_dict, value_dict=value_dict,
property_id=property_id) property_id=property_id)
# XXX can we use activity for further expand? # XXX: would it be safe to expand by activity ?
simulation_movement.expand() simulation_movement.expand('immediate')
def _solveRecursively(self, simulation_movement, is_last_movement=1, def _solveRecursively(self, simulation_movement, is_last_movement=1,
quantity_ratio=None, value_dict=None, quantity_ratio=None, value_dict=None,
......
...@@ -98,11 +98,11 @@ class SplitAndDefer(CopyToTarget): ...@@ -98,11 +98,11 @@ class SplitAndDefer(CopyToTarget):
if stop_date is not None: if stop_date is not None:
new_movement.recordProperty('stop_date') new_movement.recordProperty('stop_date')
new_movement.edit(stop_date=stop_date) new_movement.edit(stop_date=stop_date)
new_movement.activate(**self.additional_parameters).expand() new_movement.expand(activate_kw=self.additional_parameters)
# adopt new quantity on original simulation movement # adopt new quantity on original simulation movement
simulation_movement.edit(quantity=new_movement_quantity) simulation_movement.edit(quantity=new_movement_quantity)
simulation_movement.setDefaultActivateParameterDict(self.activate_kw) simulation_movement.setDefaultActivateParameterDict(self.activate_kw)
simulation_movement.activate(**self.additional_parameters).expand() simulation_movement.expand(activate_kw=self.additional_parameters)
# SplitAndDefer solves the divergence at the current level, no need to # SplitAndDefer solves the divergence at the current level, no need to
# backtrack. # backtrack.
...@@ -26,11 +26,13 @@ ...@@ -26,11 +26,13 @@
# #
############################################################################## ##############################################################################
from zLOG import LOG, INFO
from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type.Tool.BaseTool import BaseTool
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Globals import InitializeClass, DTMLFile from Products.ERP5Type.Globals import InitializeClass, DTMLFile
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5 import _dtmldir from Products.ERP5 import _dtmldir
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
class RuleTool(BaseTool): class RuleTool(BaseTool):
""" """
...@@ -135,5 +137,15 @@ class RuleTool(BaseTool): ...@@ -135,5 +137,15 @@ class RuleTool(BaseTool):
return rule_list return rule_list
security.declarePrivate('updateSimulation')
@UnrestrictedMethod
def updateSimulation(self, message_list):
expandable_dict = {}
for m in message_list:
expandable_dict.setdefault(m[0], {}).update(m[2])
for expandable, kw in expandable_dict.iteritems():
LOG("RuleTool", INFO, "Updating simulation for %s: %r"
% (expandable.getPath(), kw))
expandable._updateSimulation(**kw)
InitializeClass(RuleTool) InitializeClass(RuleTool)
...@@ -54,11 +54,6 @@ ...@@ -54,11 +54,6 @@
context.setSourceReference(None)\n context.setSourceReference(None)\n
context.setDestinationReference(None)\n context.setDestinationReference(None)\n
context.setSolver(None)\n context.setSolver(None)\n
\n
# Initialize Causality Workflow\n
if hasattr(context, \'startBuilding\'):\n
context.startBuilding()\n
context.updateCausalityState()\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
<?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>error_list = []\n
return_list = []\n
\n
for object in context.portal_simulation.objectValues():\n
# Reexpand to propagate new rules\n
object.expand()\n
\n
for object in context.portal_simulation.objectValues():\n
#print "#### Indexing inside the folder %s ####" % \'portal_simulation\'\n
# Reindex\n
error_list += context.reindexAll(object=object,request=context)\n
\n
nb_types = {}\n
\n
for error in error_list:\n
# We count the number of each portal type\n
if error[1]==\'portal_type\':\n
type = error[3]\n
if nb_types.has_key(type):\n
nb_types[type] = nb_types[type] + 1\n
else:\n
nb_types[type] = 1\n
else:\n
#print error\n
return_list.append(error)\n
\n
for type in nb_types.keys():\n
# Find the number of each portal type in the catalog\n
count_result = context.portal_catalog.countResults(portal_type=type)\n
nb_catalog = count_result[0][0]\n
if nb_types[type] != nb_catalog:\n
message = "XXX Warning for %s: there is %i lines in the catalog instead of %i" % \\\n
(type,nb_catalog,nb_types[type])\n
return_list.append((\'Count Error\', \'PortalRoot_reindexAll\',1,message))\n
#else: print "%s: %i" % (type,nb_types[type])\n
\n
return return_list\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>request=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_reindexSimulation</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1052.3622"
height="744.09448"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="simulation.svg">
<title
id="title3064">Interactions and activity dependencies in simulation</title>
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path4232"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="DotM"
orient="auto"
refY="0.0"
refX="0.0"
id="DotM"
style="overflow:visible">
<path
id="path4824"
d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4) translate(7.4, 1)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;">
<path
id="path5518"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-6"
style="overflow:visible">
<path
inkscape:connector-curvature="0"
id="path5518-6"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.74318519"
inkscape:cx="387.99291"
inkscape:cy="372.04724"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:showpageshadow="true"
units="mm"
fit-margin-top="1"
fit-margin-bottom="1"
fit-margin-left="1"
fit-margin-right="1"
inkscape:snap-object-midpoints="false"
inkscape:snap-bbox="false"
inkscape:connector-spacing="10"
inkscape:window-width="1280"
inkscape:window-height="756"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid3022"
units="mm"
empspacing="10"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="5mm"
spacingy="5mm"
dotted="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Interactions and activity dependencies in simulation</dc:title>
<dc:date>2012-05-29</dc:date>
<dc:description />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-308.26449)">
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="70.866142"
y="396.84717"
id="text3024"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3026"
x="70.866142"
y="396.84717">build</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230"
width="106.29922"
height="53.149612"
x="53.149601"
y="361.41409"
ry="26.574806" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="425.1969"
y="379.13065"
id="text3024-0"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3026-8"
x="425.1969"
y="379.13065">SM.recursiveImmediateReindexObject</tspan><tspan
sodipodi:role="line"
x="425.1969"
y="401.63065"
id="tspan5261"> tag = built:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5"
width="407.48029"
height="70.866119"
x="407.48035"
y="343.69757" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="478.3465"
y="503.14636"
id="text3024-0-0"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3026-8-6"
x="478.3465"
y="503.14636">D._updateSimulation(create_root, index_related,</tspan><tspan
sodipodi:role="line"
x="478.3465"
y="525.64636"
id="tspan5292"> expand_root, expand_related)</tspan><tspan
sodipodi:role="line"
x="478.3465"
y="548.14636"
id="tspan5261-4"> tag = expand:&lt;delivery_path&gt;</tspan><tspan
sodipodi:role="line"
x="478.3465"
y="570.64636"
id="tspan5290"> after_tag = build:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5-6"
width="549.21259"
height="124.01569"
x="460.62994"
y="467.71338"
inkscape:connector-avoid="true" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="70.866165"
y="591.72913"
id="text3024-0-3"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="70.866165"
y="591.72913"
id="tspan5261-0">D.Delivery_calculate</tspan><tspan
sodipodi:role="line"
x="70.866165"
y="614.22913"
id="tspan5323"> tag = expand:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5-5"
width="354.33069"
height="70.866112"
x="53.149612"
y="556.29602"
inkscape:connector-avoid="true" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:7.99999998, 7.99999998;stroke-dashoffset:0;marker-end:url(#Arrow1Lend)"
d="m 159.44881,380.35897 248.0315,0"
id="path5327"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:7.99999992, 7.99999992;stroke-dashoffset:0;marker-end:url(#Arrow1Lend)"
d="m 159.44883,396.84715 301.1811,70.86613"
id="path5329"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:7.99999988, 7.99999988;stroke-dashoffset:0;marker-end:url(#Arrow1Lend)"
d="m 106.29921,414.5637 0,141.73228"
id="path5329-4"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="53.149605"
y="733.46136"
id="text6720"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="53.149605"
y="733.46136"
id="tspan6724">startBuilding / calculate</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165341;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-4"
width="301.18112"
height="53.149609"
x="35.433048"
y="698.02826"
ry="26.574804" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8.0000002, 8.0000002;stroke-dashoffset:0;marker-mid:none;marker-end:url(#Arrow1Lend-6)"
d="m 177.16535,627.16208 0,70.86618"
id="path7170"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="53.14959"
y="892.91022"
id="text3024-0-3-2"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="53.14959"
y="892.91022"
id="tspan5261-0-9">D.updateCausalityState</tspan><tspan
sodipodi:role="line"
x="53.14959"
y="915.41022"
id="tspan5323-4"> after_tag = expand:&lt;delivey_path&gt;</tspan><tspan
sodipodi:role="line"
x="53.14959"
y="937.91022"
id="tspan7567"> built:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5-5-3"
width="407.48035"
height="106.29918"
x="35.433037"
y="857.47711"
inkscape:connector-avoid="true" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8.00000011, 8.00000011;stroke-dashoffset:0;marker-mid:none;marker-end:url(#Arrow1Lend-6);display:inline"
d="m 177.16535,751.17786 0,106.29922"
id="path7569"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6)"
d="m 354.33071,857.47707 0,-230.31495"
id="path7939"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Lend-6);display:inline"
d="m 425.19685,538.57944 35.43307,0"
id="path8125"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6)"
d="m 637.79528,467.7133 0,-53.1496"
id="path8127"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
inkscape:transform-center-x="17.716536"
inkscape:transform-center-y="-246.25662" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6)"
d="m 425.19685,857.47707 0,-442.91338"
id="path4597"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="566.92914"
y="804.32758"
id="text3024-0-3-3"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="566.92914"
y="804.32758"
id="tspan5323-7">D._localBuild</tspan><tspan
sodipodi:role="line"
x="566.92914"
y="826.82758"
id="tspan3839"> after_tag = expand:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5-5-5"
width="425.19684"
height="70.866112"
x="549.21259"
y="768.89447"
inkscape:connector-avoid="true" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="513.77954"
y="680.31171"
id="text3024-0-3-3-3"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="513.77954"
y="680.31171"
id="tspan5323-7-5">reindexing</tspan><tspan
sodipodi:role="line"
x="513.77954"
y="702.81171"
id="tspan3839-6"> tag = expand:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5-5-5-2"
width="354.33075"
height="70.866112"
x="496.06299"
y="644.8786"
inkscape:connector-avoid="true" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace"
x="513.77942"
y="928.34332"
id="text3024-0-3-3-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="513.77942"
y="928.34332"
id="tspan5323-7-1">expand</tspan><tspan
sodipodi:role="line"
x="513.77942"
y="950.84332"
id="tspan3839-2"> tag = expand:&lt;delivery_path&gt;</tspan></text>
<rect
style="fill:none;stroke:#000000;stroke-width:1.77165353;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect5230-5-5-5-7"
width="354.33075"
height="70.866112"
x="496.06296"
y="892.91022"
inkscape:connector-avoid="true" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6);display:inline"
d="m 921.25984,768.89441 0,-177.16536"
id="path4453"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM);marker-end:url(#Arrow1Lend-6)"
d="m 425.19685,680.31173 70.86614,-2e-5"
id="path4639"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8, 8;stroke-dashoffset:0;marker-end:url(#Arrow1Lend-6)"
d="m 513.77953,892.91015 0,-177.16535"
id="path4825"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:7.99370116, 7.99370116;stroke-dashoffset:0;marker-end:url(#Arrow1Lend-6)"
d="M 496.06299,892.91016 372.04724,627.16215"
id="path3049"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend-6)"
d="m 442.91338,875.19362 262.74802,0 c 1.5,0 3,-1.5 3,-3 l 0,-32.43307"
id="path3048"
inkscape:connector-type="orthogonal"
inkscape:connector-curvature="3"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6)"
d="m 442.91339,928.34322 53.14961,0"
id="path4198"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6)"
d="m 744.09449,839.76055 0,53.1496"
id="path4384"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8, 8;stroke-dashoffset:0;marker-end:url(#Arrow1Lend-6)"
d="m 708.66142,591.72905 0,53.14961"
id="path4570"
inkscape:connector-type="polyline"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:7.99370079, 7.99370079;stroke-dashoffset:0;marker-end:url(#Arrow1Lend-6)"
d="M 70.866142,414.5637 C 35.433071,556.29598 35.433071,627.16212 53.149606,698.02826"
id="path3053"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="3" />
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8, 8;stroke-dashoffset:0;marker-end:url(#Arrow1Lend-6)"
d="m 992.12598,591.72905 0,336.61417 -141.73228,0"
id="path4214"
inkscape:connector-type="orthogonal"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#DotM)"
d="m 549.2126,804.32748 -194.88189,0"
id="path4402"
inkscape:connector-type="polyline"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-6);display:inline"
d="m 708.66142,768.89441 0,-53.14961"
id="path4590"
inkscape:connector-type="polyline"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="519.49603"
y="871.1936"
id="text4778"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4780"
x="519.49603"
y="871.1936">after_path_and_method_id</tspan></text>
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="-499.53085"
y="149.93913"
id="text4790"
sodipodi:linespacing="125%"
transform="matrix(0.20867807,-0.97798439,0.97798439,0.20867807,0,0)"
inkscape:transform-center-x="-21.15626"
inkscape:transform-center-y="15.10145"><tspan
sodipodi:role="line"
id="tspan4792"
x="-499.53085"
y="149.93913">_setObject</tspan></text>
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="875.2049"
y="-69.862999"
id="text4786-7"
sodipodi:linespacing="125%"
transform="matrix(0.43080996,0.90244267,-0.90244267,0.43080996,0,0)"><tspan
sodipodi:role="line"
id="tspan4788-5"
x="875.2049"
y="-69.862999">_set*</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:7.99370079, 7.99370079;stroke-dashoffset:0;marker-end:url(#Arrow1Lend-6)"
d="m 779.52756,892.91015 0,-35.43307 53.14961,0 0,35.43307"
id="path3068"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="35.433071"
y="999.20935"
id="text3066"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3068"
x="35.433071"
y="999.20935">This describes activity messages related to Simulation Tool when a Delivery Builder is invoked.</tspan><tspan
sodipodi:role="line"
x="35.433071"
y="1021.7094"
id="tspan3070">Continuous lines represent dependencies. Dashed lines show calls: if target is squared, then it's by activity.</tspan><tspan
sodipodi:role="line"
x="35.433071"
y="1044.2094"
id="tspan3072" /></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.99921260000000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:7.99370079000000011, 7.99370079000000011;marker-end:url(#Arrow1Lend-6);stroke-dashoffset:0;marker-start:url(#Arrow1Lstart)"
d="m 885.82677,768.89441 c 0,-159.44883 0,-159.44883 -354.33071,-159.44883 -194.88189,0 17.71654,-88.58268 -389.76378,-194.88188"
id="path3074"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csc" />
</g>
</svg>
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
############################################################################## ##############################################################################
# #
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved. # Copyright (c) 2012 Nexedi SA and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# #
# WARNING: This program as such is intended to be used by professional # WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential # programmers who take the whole responsability of assessing all potential
...@@ -29,29 +28,21 @@ ...@@ -29,29 +28,21 @@
""" """
Products.ERP5.interfaces.expandable Products.ERP5.interfaces.expandable
""" """
from zope.interface import Interface from zope.interface import Interface
class IExpandable(Interface): class IExpandable(Interface):
"""Common Interface for Applied Rules and Simulation Movements
""" """
An Expandable class provides methods which trigger def expand(expand_policy=None, activate_kw=None):
the generation of the root applied rule of a simulation tree
and its expansion. Classes which implement IExpandable include
Deliveries (whenever can be the cause of an Applied Rule),
Items (whenever they are the cause of a movement sequence)
such as Subscription Items or Immobilisation Items, Movements
(which have been previously built).
""" """
Update subobjects of this document and expand them
def expand(applied_rule_id=None, activate_kw=None, **kw): expand_policy -- string defining whether a node in the simulation tree
""" should be expand immediately or in a separate activity,
Expand the current Expandable class into the simulation. or None to use the preferred policy
If no applied_rule_id is provided, try first to find
appropriate applied rule if any to start expansion process.
applied_rule_id -- a hint parameter (optional), which can activate_kw -- activity parameters, required to control
be provided to reindex the whole activity constraints
simulation tree from the root applied rule
activate_kw -- (TO BE EXPLAINED BY KAZ) Available policies: immediate, deferred, vertical_time_bound
""" """
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved.
#
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""
Products.ERP5.interfaces.expandable_item
"""
from Products.ERP5.interfaces.expandable import IExpandable
class IExpandableItem(IExpandable):
""" An expandable item is an item that generate simulation, such as a
Subscription Item or an Immobilisation Item.
Such items are also responsible for returning the simulation state of the
movements they build.
"""
def getSimulationMovementSimulationState(simulation_movement):
"""Returns the simulation state of this simulation movement, unless it is
built and related to a delivery.
"""
...@@ -37,8 +37,7 @@ class IRule(IMovementCollectionUpdater): ...@@ -37,8 +37,7 @@ class IRule(IMovementCollectionUpdater):
Documents which implement IRule can be used to Documents which implement IRule can be used to
expand applied rules in ERP5 simulation. expand applied rules in ERP5 simulation.
""" """
def constructNewAppliedRule(context, id=None, def constructNewAppliedRule(context, **kw):
activate_kw=None, **kw):
""" """
Create a new applied rule in the context. Create a new applied rule in the context.
...@@ -48,13 +47,10 @@ class IRule(IMovementCollectionUpdater): ...@@ -48,13 +47,10 @@ class IRule(IMovementCollectionUpdater):
context -- usually, a parent simulation movement of the context -- usually, a parent simulation movement of the
newly created applied rule newly created applied rule
activate_kw -- activity parameters, required to control kw -- optional parameters which can be passed to Folder API
activity constraints
kw -- XXX-JPS probably wrong interface specification
""" """
def expand(applied_rule, **kw): def expand(applied_rule, expand_policy=None, activate_kw=None):
""" """
Expand this applied rule to create new documents inside the Expand this applied rule to create new documents inside the
applied rule. applied rule.
...@@ -66,6 +62,14 @@ class IRule(IMovementCollectionUpdater): ...@@ -66,6 +62,14 @@ class IRule(IMovementCollectionUpdater):
of compensation are implemented through of compensation are implemented through
IMovementCollectionUpdater API IMovementCollectionUpdater API
kw -- XXX-JPS probably wrong interface specification applied_rule -- applied rule to expand
activate_kw should probably be defined explicitely here
expand_policy -- string defining whether a node in the simulation tree
should be expand immediately or in a separate activity,
or None to use the preferred policy
activate_kw -- activity parameters, required to control
activity constraints
Available policies: immediate, deferred, vertical_time_bound
""" """
...@@ -26,12 +26,16 @@ ...@@ -26,12 +26,16 @@
# #
############################################################################## ##############################################################################
import transaction
import zope.interface import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Acquisition import aq_base from Acquisition import aq_base
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type import Permissions, interfaces from Products.ERP5Type import Permissions, interfaces
from Products.ERP5Type.Base import Base
from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5Type.Errors import SimulationError
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5.ExpandPolicy import policy_dict
from Products.ERP5.MovementCollectionDiff import _getPropertyAndCategoryList from Products.ERP5.MovementCollectionDiff import _getPropertyAndCategoryList
from zLOG import LOG from zLOG import LOG
...@@ -153,8 +157,7 @@ class RuleMixin(Predicate): ...@@ -153,8 +157,7 @@ class RuleMixin(Predicate):
movement_type = 'Simulation Movement' movement_type = 'Simulation Movement'
# Implementation of IRule # Implementation of IRule
def constructNewAppliedRule(self, context, id=None, def constructNewAppliedRule(self, context, **kw):
activate_kw=None, **kw):
""" """
Create a new applied rule in the context. Create a new applied rule in the context.
...@@ -170,14 +173,8 @@ class RuleMixin(Predicate): ...@@ -170,14 +173,8 @@ class RuleMixin(Predicate):
kw -- XXX-JPS probably wrong interface specification kw -- XXX-JPS probably wrong interface specification
""" """
if id is None: return context.newContent(portal_type='Applied Rule',
id = context.generateNewId() specialise_value=self, **kw)
if getattr(aq_base(context), id, None) is None:
context.newContent(id=id,
portal_type='Applied Rule',
specialise_value=self,
activate_kw=activate_kw)
return context.get(id)
if 0: # XXX-JPS - if people are stupid enough not to configfure predicates, if 0: # XXX-JPS - if people are stupid enough not to configfure predicates,
# it is not our role to be clever for them # it is not our role to be clever for them
...@@ -192,7 +189,7 @@ class RuleMixin(Predicate): ...@@ -192,7 +189,7 @@ class RuleMixin(Predicate):
return False return False
return super(RuleMixin, self).test(*args, **kw) return super(RuleMixin, self).test(*args, **kw)
def expand(self, applied_rule, **kw): def expand(self, applied_rule, expand_policy=None, **kw):
""" """
Expand this applied rule to create new documents inside the Expand this applied rule to create new documents inside the
applied rule. applied rule.
...@@ -202,13 +199,17 @@ class RuleMixin(Predicate): ...@@ -202,13 +199,17 @@ class RuleMixin(Predicate):
by a decision (ie. a resource is changed), then we by a decision (ie. a resource is changed), then we
should not try to compensate such a decision. should not try to compensate such a decision.
""" """
# Update movements policy_dict[expand_policy](**kw).expand(self, applied_rule)
def _expandNow(self, maybe_expand, applied_rule):
# Update moveme-nts
# NOTE-JPS: it is OK to make rounding a standard parameter of rules # NOTE-JPS: it is OK to make rounding a standard parameter of rules
# although rounding in simulation is not recommended at all # although rounding in simulation is not recommended at all
self.updateMovementCollection(applied_rule, movement_generator=self._getMovementGenerator(applied_rule)) self.updateMovementCollection(applied_rule,
movement_generator=self._getMovementGenerator(applied_rule))
# And forward expand # And forward expand
for movement in applied_rule.getMovementList(): for movement in applied_rule.getMovementList():
movement.expand(**kw) maybe_expand(movement)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable') 'isAccountable')
...@@ -474,3 +475,130 @@ class RuleMixin(Predicate): ...@@ -474,3 +475,130 @@ class RuleMixin(Predicate):
new_movement = self._newProfitAndLossMovement(prevision_movement) new_movement = self._newProfitAndLossMovement(prevision_movement)
movement_collection_diff.addNewMovement(new_movement) movement_collection_diff.addNewMovement(new_movement)
class SimulableMixin(Base):
def updateSimulation(self, **kw):
"""Create/update related simulation trees by activity
This method is used to maintain related objects in simulation trees:
- hiding complexity of activity dependencies
- avoiding duplicate work
Repeated calls of this method for the same delivery will result in a single
call to _updateSimulation. Grouping may happen at the end of the transaction
or by the grouping method.
See _updateSimulation for accepted parameters.
"""
tv = getTransactionalVariable()
key = 'SimulableMixin.updateSimulation', self.getUid()
item_list = kw.items()
try:
kw, ignore = tv[key]
kw.update(item_list)
except KeyError:
ignore = set()
tv[key] = kw, ignore
def before_commit():
if kw:
path = self.getPath()
if aq_base(self.unrestrictedTraverse(path, None)) is aq_base(self):
self.activate(
activity='SQLQueue',
group_method_id='portal_rules/updateSimulation',
tag='expand:' + path,
after_tag='built:'+ path, # see SimulatedDeliveryBuilder
priority=3,
)._updateSimulation(**kw)
tv[key] = None # disallow further calls to 'updateSimulation' for self
transaction.get().addBeforeCommitHook(before_commit)
for k, v in item_list:
if not v:
ignore.add(k)
elif k not in ignore:
continue
del kw[k]
def _updateSimulation(self, create_root=0, expand_root=0,
expand_related=0, index_related=0):
"""
Depending on set parameters, this method will:
create_root -- if a root applied rule is missing, create and expand it
expand_root -- expand related root applied rule,
create it before if missing
expand_related -- reindex related simulation movements (recursively)
index_related -- expand related simulation movements
"""
if create_root or expand_root:
applied_rule = self._getRootAppliedRule()
if applied_rule is None:
applied_rule = self._createRootAppliedRule()
expand_root = applied_rule is not None
activate_kw = {'tag': 'expand:'+self.getPath()}
if expand_root:
applied_rule.expand(activate_kw=activate_kw)
else:
applied_rule = None
if expand_related:
for movement in self._getAllRelatedSimulationMovementList():
movement = movement.getObject()
if not movement.aq_inContextOf(applied_rule):
# XXX: make sure this will also reindex of all sub-objects recursively
movement.expand(activate_kw=activate_kw)
elif index_related:
for movement in self._getAllRelatedSimulationMovementList():
movement = movement.getObject()
if not movement.aq_inContextOf(applied_rule):
movement.recursiveReindexObject(activate_kw=activate_kw)
def getRuleReference(self):
"""Returns an appropriate rule reference
XXX: Using reference to select a rule (for a root applied rule) is wrong
and should be replaced by predicate and workflow state.
"""
method = self._getTypeBasedMethod('getRuleReference')
if method is None:
raise SimulationError("Missing type-based 'getRuleReference' script for "
+ repr(self))
return method()
def _getRootAppliedRule(self):
"""Get related root applied rule if it exists"""
applied_rule_list = self.getCausalityRelatedValueList(
portal_type='Applied Rule')
if len(applied_rule_list) == 1:
return applied_rule_list[0]
elif applied_rule_list:
raise SimulationError('%r has more than one applied rule.' % self)
def _createRootAppliedRule(self):
"""Create a root applied rule"""
# XXX: Consider moving this first test to Delivery
if self.isSimulated():
# No need to have a root applied rule
# if we are already in the simulation process
return
rule_reference = self.getRuleReference()
if rule_reference:
portal = self.getPortalObject()
rule_list = portal.portal_catalog.unrestrictedSearchResults(
portal_type=portal.getPortalRuleTypeList(),
validation_state="validated", reference=rule_reference,
sort_on='version', sort_order='descending')
if rule_list:
applied_rule = rule_list[0].constructNewAppliedRule(
portal.portal_simulation, is_indexable=False)
applied_rule._setCausalityValue(self)
del applied_rule.isIndexable
applied_rule.immediateReindexObject()
self.serialize() # prevent duplicate root Applied Rule
return applied_rule
raise SimulationError("No such rule as %r is found" % rule_reference)
def manage_beforeDelete(self, item, container):
"""Delete related Applied Rule"""
for o in self.getCausalityRelatedValueList(portal_type='Applied Rule'):
o.getParentValue().deleteContent(o.getId())
super(SimulableMixin, self).manage_beforeDelete(item, container)
...@@ -677,15 +677,6 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase): ...@@ -677,15 +677,6 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase):
invoice._delObject(invoice_line.getId()) invoice._delObject(invoice_line.getId())
invoice.recursiveReindexObject() invoice.recursiveReindexObject()
def stepUpdateAppliedRule(self, sequence, **kw) :
""" update the applied rule for the invoice. In the UI, the call to
updateAppliedRule is made in an interraction workflow when you edit
an invoice or its content."""
# edit is done through interaction workflow, so we just call 'edit'
# on the invoice (but this is not necessary)
invoice=sequence.get('invoice')
invoice.edit()
def stepCreateSimpleInvoiceTwoLines(self, sequence, **kw) : def stepCreateSimpleInvoiceTwoLines(self, sequence, **kw) :
""" """
similar to stepCreateSimpleInvoice, but replace similar to stepCreateSimpleInvoice, but replace
...@@ -1784,7 +1775,7 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase): ...@@ -1784,7 +1775,7 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase):
@newSimulationExpectedFailure @newSimulationExpectedFailure
def test_05a_SimpleInvoiceReExpandAddLine(self, quiet=QUIET, def test_05a_SimpleInvoiceReExpandAddLine(self, quiet=QUIET,
run=RUN_ALL_TESTS): run=RUN_ALL_TESTS):
""" Add a new line then updateAppliedRule. """ Add a new line then updateSimulation.
Create an empty invoice, plan, add a line so that this Create an empty invoice, plan, add a line so that this
invoice is the same as `SimpleInvoice`, confirm it then check invoice is the same as `SimpleInvoice`, confirm it then check
accounting lines accounting lines
...@@ -1951,7 +1942,7 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase): ...@@ -1951,7 +1942,7 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase):
if not run: if not run:
return return
if not quiet: if not quiet:
message = 'Test Simple Invoice Rule (many updateAppliedRule)' message = 'Test Simple Invoice Rule (many updateSimulation)'
ZopeTestCase._print('\n%s ' % message) ZopeTestCase._print('\n%s ' % message)
LOG('Testing... ', INFO, message) LOG('Testing... ', INFO, message)
...@@ -1974,7 +1965,6 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase): ...@@ -1974,7 +1965,6 @@ class TestAccountingRules(TestAccountingRulesMixin, ERP5TypeTestCase):
stepTic """ + stepTic """ +
(""" ("""
stepEditInvoiceLine stepEditInvoiceLine
stepUpdateAppliedRule
stepTic""" * 4) + stepTic""" * 4) +
""" """
stepConfirmInvoice stepConfirmInvoice
......
...@@ -280,7 +280,7 @@ class TestAdvancedInvoice(TestSaleInvoiceMixin, ERP5TypeTestCase): ...@@ -280,7 +280,7 @@ class TestAdvancedInvoice(TestSaleInvoiceMixin, ERP5TypeTestCase):
invoice_transaction = invoice.getCausalityRelatedValue() invoice_transaction = invoice.getCausalityRelatedValue()
self.assertNotEquals(invoice_transaction, None) self.assertNotEquals(invoice_transaction, None)
self.assertEquals('draft', invoice_transaction.getCausalityState()) self.assertEquals('solved', invoice_transaction.getCausalityState())
def test_AcceptQuantityDivergenceOnInvoiceWithStoppedPackingList(self, quiet=quiet, run=RUN_ALL_TESTS): def test_AcceptQuantityDivergenceOnInvoiceWithStoppedPackingList(self, quiet=quiet, run=RUN_ALL_TESTS):
"""Accept divergence with stopped packing list""" """Accept divergence with stopped packing list"""
......
...@@ -31,7 +31,6 @@ import unittest ...@@ -31,7 +31,6 @@ import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from Products.ERP5Form.Form import ERP5Form from Products.ERP5Form.Form import ERP5Form
from Products.ERP5.tests.utils import newSimulationExpectedFailure
class TestICal(ERP5TypeTestCase): class TestICal(ERP5TypeTestCase):
...@@ -165,7 +164,6 @@ class TestICal(ERP5TypeTestCase): ...@@ -165,7 +164,6 @@ class TestICal(ERP5TypeTestCase):
feed_dict = self.getICalFeed(module) feed_dict = self.getICalFeed(module)
self.assertEquals(feed_dict['STATUS'], 'CANCELLED') self.assertEquals(feed_dict['STATUS'], 'CANCELLED')
@newSimulationExpectedFailure
def test_02_renderTask(self, quiet=0, run=run_all_test): def test_02_renderTask(self, quiet=0, run=run_all_test):
""" """
Task - is rendered as "todo". Task - is rendered as "todo".
......
...@@ -669,20 +669,12 @@ class TestInvoiceMixin(TestPackingListMixin): ...@@ -669,20 +669,12 @@ class TestInvoiceMixin(TestPackingListMixin):
def stepCheckTwoInvoices(self,sequence=None, sequence_list=None, **kw): def stepCheckTwoInvoices(self,sequence=None, sequence_list=None, **kw):
""" checks invoice properties are well set. """ """ checks invoice properties are well set. """
# Now we will check that we have two invoices created # Now we will check that we have two invoices created
packing_list = sequence.get('packing_list') for x in '', 'new_':
invoice_list = packing_list.getCausalityRelatedValueList( packing_list = sequence.get(x + 'packing_list')
invoice, = packing_list.getCausalityRelatedValueList(
portal_type=self.invoice_portal_type) portal_type=self.invoice_portal_type)
self.assertEquals(len(invoice_list),1) self.assertEqual(invoice.getSimulationState(), 'confirmed')
invoice = invoice_list[0] sequence.set(x + 'invoice', invoice)
self.assertEquals(invoice.getSimulationState(), 'confirmed')
sequence.edit(invoice=invoice)
new_packing_list = sequence.get('new_packing_list')
new_invoice_list = new_packing_list.getCausalityRelatedValueList(
portal_type=self.invoice_portal_type)
self.assertEquals(len(new_invoice_list),1)
new_invoice = new_invoice_list[0]
self.assertEquals(new_invoice.getSimulationState(), 'confirmed')
sequence.edit(new_invoice=new_invoice)
def stepStartTwoInvoices(self,sequence=None, sequence_list=None, **kw): def stepStartTwoInvoices(self,sequence=None, sequence_list=None, **kw):
""" start both invoices. """ """ start both invoices. """
...@@ -781,50 +773,28 @@ class TestInvoiceMixin(TestPackingListMixin): ...@@ -781,50 +773,28 @@ class TestInvoiceMixin(TestPackingListMixin):
newSecurityManager(None, user) newSecurityManager(None, user)
def stepEditInvoice(self, sequence=None, sequence_list=None, **kw): def stepEditInvoice(self, sequence=None, sequence_list=None, **kw):
"""Edit the current invoice, to trigger updateAppliedRule.""" """Edit the current invoice, to trigger updateSimulation."""
invoice = sequence.get('invoice') invoice = sequence.get('invoice')
invoice.edit() invoice.edit(description='This invoice was edited!')
# call updateAppliedRule directly, don't rely on edit interactions
rule_reference = 'default_invoice_rule'
self.assertNotEquals(0,
len(self.portal.portal_rules.searchFolder(reference=rule_reference)))
invoice.updateAppliedRule(rule_reference=rule_reference)
def stepCheckInvoiceRuleNotAppliedOnInvoiceEdit(self, def stepCheckInvoiceRuleNotAppliedOnInvoiceEdit(self,
sequence=None, sequence_list=None, **kw): sequence=None, sequence_list=None, **kw):
"""If we call edit on the invoice, invoice rule should not be """If we call edit on the invoice, invoice rule should not be
applied on lines created by delivery builder.""" applied on lines created by delivery builder."""
invoice = sequence.get('invoice') invoice = sequence.get('invoice')
# FIXME: empty applied rule should not be created self.assertEqual([], invoice.getCausalityRelatedValueList())
#self.assertEquals(len(invoice.getCausalityRelatedValueList(
# portal_type=self.applied_rule_portal_type)), 0)
for invoice_mvt in invoice.getMovementList():
self.assertEquals(len(invoice_mvt.getOrderRelatedValueList(
portal_type=self.simulation_movement_portal_type)), 0)
def stepEditPackingList(self, sequence=None, sequence_list=None, **kw): def stepEditPackingList(self, sequence=None, sequence_list=None, **kw):
"""Edit the current packing list, to trigger updateAppliedRule.""" """Edit the current packing list, to trigger updateSimulation."""
packing_list = sequence.get('packing_list') packing_list = sequence.get('packing_list')
packing_list.edit() packing_list.edit(description='This packing list was edited!')
# call updateAppliedRule directly, don't rely on edit interactions
rule_reference = 'default_delivery_rule'
self.assertNotEquals(0,
len(self.portal.portal_rules.searchFolder(reference=rule_reference)))
packing_list.updateAppliedRule(rule_reference=rule_reference)
def stepCheckDeliveryRuleNotAppliedOnPackingListEdit(self, def stepCheckDeliveryRuleNotAppliedOnPackingListEdit(self,
sequence=None, sequence_list=None, **kw): sequence=None, sequence_list=None, **kw):
"""If we call edit on the packing list, delivery rule should not be """If we call edit on the packing list, delivery rule should not be
applied on lines created by delivery builder.""" applied on lines created by delivery builder."""
packing_list = sequence.get('packing_list') packing_list = sequence.get('packing_list')
# FIXME: empty applied rule should not be created self.assertEqual([], packing_list.getCausalityRelatedValueList())
#self.assertEquals(len(packing_list.getCausalityRelatedValueList(
# portal_type=self.applied_rule_portal_type)), 0)
for delivery_mvt in packing_list.getMovementList():
self.assertEquals(len(delivery_mvt.getOrderRelatedValueList(
portal_type=self.simulation_movement_portal_type)), 0)
def stepDecreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None, def stepDecreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None,
**kw): **kw):
...@@ -1037,14 +1007,9 @@ class TestInvoiceMixin(TestPackingListMixin): ...@@ -1037,14 +1007,9 @@ class TestInvoiceMixin(TestPackingListMixin):
# check which activities are failing # check which activities are failing
self.assertTrue(str(exc).startswith('tic is looping forever.'), self.assertTrue(str(exc).startswith('tic is looping forever.'),
'%s does not start with "tic is looping forever."' % str(exc)) '%s does not start with "tic is looping forever."' % str(exc))
msg_list = ['/'.join(x.object_path) for x in msg_list = [('/'.join(x.object_path), x.method_id)
self.getActivityTool().getMessageList()] for x in self.getActivityTool().getMessageList()]
self.assertTrue(invoice.getPath() in msg_list, '%s in %s' % self.assertTrue((invoice.getPath(), '_localBuild') in msg_list, msg_list)
(invoice.getPath(), msg_list))
method_id_list = [x.method_id for x in
self.getActivityTool().getMessageList()]
self.assertTrue('Delivery_buildOnComposedDocument' in method_id_list, '%s in %s' %
('Delivery_buildOnComposedDocument', method_id_list))
# flush failing activities # flush failing activities
activity_tool = self.getActivityTool() activity_tool = self.getActivityTool()
activity_tool.manageClearActivities(keep=0) activity_tool.manageClearActivities(keep=0)
...@@ -2613,7 +2578,7 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase): ...@@ -2613,7 +2578,7 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
We want to prevent this from happening: We want to prevent this from happening:
- Create a packing list - Create a packing list
- An invoice is created from packing list - An invoice is created from packing list
- Invoice is edited, updateAppliedRule is called - Invoice is edited, updateSimulation is called
- A new Invoice Rule is created for this invoice, and accounting - A new Invoice Rule is created for this invoice, and accounting
movements for this invoice are present twice in the simulation. movements for this invoice are present twice in the simulation.
""" """
...@@ -2633,9 +2598,9 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase): ...@@ -2633,9 +2598,9 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
stepTic stepTic
stepCheckInvoiceBuilding stepCheckInvoiceBuilding
stepEditInvoice stepEditInvoice
stepTic
stepCheckInvoiceRuleNotAppliedOnInvoiceEdit stepCheckInvoiceRuleNotAppliedOnInvoiceEdit
stepCheckInvoicesConsistency stepCheckInvoicesConsistency
stepTic
""") """)
sequence_list.play(self, quiet=quiet) sequence_list.play(self, quiet=quiet)
...@@ -2652,9 +2617,8 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase): ...@@ -2652,9 +2617,8 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
base_sequence + base_sequence +
""" """
stepEditPackingList stepEditPackingList
stepCheckDeliveryRuleNotAppliedOnPackingListEdit
stepCheckInvoicesConsistency
stepTic stepTic
stepCheckDeliveryRuleNotAppliedOnPackingListEdit
""") """)
sequence_list.play(self, quiet=quiet) sequence_list.play(self, quiet=quiet)
...@@ -2725,6 +2689,7 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase): ...@@ -2725,6 +2689,7 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
base_sequence + base_sequence +
""" """
stepAddPackingListLine stepAddPackingListLine
stepTic
stepSetContainerFullQuantity stepSetContainerFullQuantity
stepTic stepTic
stepSetReadyPackingList stepSetReadyPackingList
......
...@@ -1134,23 +1134,13 @@ class TestOrderMixin(SubcontentReindexingWrapper): ...@@ -1134,23 +1134,13 @@ class TestOrderMixin(SubcontentReindexingWrapper):
order_line = sequence.get('order_line') order_line = sequence.get('order_line')
order_line.getParentValue().manage_delObjects([order_line.getId()]) order_line.getParentValue().manage_delObjects([order_line.getId()])
def stepCheckOrderSimulationStable(self, sequence=None, \ def stepCheckOrderConvergent(self, sequence=None, sequence_list=None, **kw):
sequence_list=None, **kw):
""" """
Tests that the simulation related to the order is stable and not Tests that the simulation related to the order is stable and not
divergent divergent
""" """
order = sequence.get('order') order = sequence.get('order')
order_movement_list = order.getMovementList() self.assertTrue(order.isConvergent())
related_simulation_list = []
for order_movement in order_movement_list:
related_simulation_list.extend(order_movement.getOrderRelatedValueList())
related_applied_rule_list = {}
for simulation_mvt in related_simulation_list:
self.assertFalse(simulation_mvt.isDivergent())
related_applied_rule_list[simulation_mvt.getParentValue()]=1
for applied_rule in related_applied_rule_list.keys():
self.assertTrue(applied_rule.isStable())
def stepPackingListAdoptPrevision(self,sequence=None, sequence_list=None, def stepPackingListAdoptPrevision(self,sequence=None, sequence_list=None,
**kw): **kw):
...@@ -2078,7 +2068,7 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase): ...@@ -2078,7 +2068,7 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase):
stepConfirmOrder \ stepConfirmOrder \
stepTic \ stepTic \
stepCheckOrderSimulation \ stepCheckOrderSimulation \
stepCheckOrderSimulationStable \ stepCheckOrderConvergent \
' '
sequence_list.addSequenceString(sequence_string) sequence_list.addSequenceString(sequence_string)
# XXX XXX FIXME # XXX XXX FIXME
...@@ -2109,7 +2099,7 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase): ...@@ -2109,7 +2099,7 @@ class TestOrder(TestOrderMixin, ERP5TypeTestCase):
stepTic \ stepTic \
stepCheckOrderSimulation \ stepCheckOrderSimulation \
stepCheckDeliveryBuilding \ stepCheckDeliveryBuilding \
stepCheckOrderSimulationStable \ stepCheckOrderConvergent \
' '
# sequence_list.addSequenceString(sequence_string) # sequence_list.addSequenceString(sequence_string)
......
...@@ -31,7 +31,6 @@ import unittest ...@@ -31,7 +31,6 @@ import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from DateTime import DateTime from DateTime import DateTime
from Products.ERP5.tests.utils import newSimulationExpectedFailure
class TestProject(ERP5TypeTestCase): class TestProject(ERP5TypeTestCase):
""" Test for Project API and scripts and forms """ Test for Project API and scripts and forms
...@@ -110,7 +109,6 @@ class TestProject(ERP5TypeTestCase): ...@@ -110,7 +109,6 @@ class TestProject(ERP5TypeTestCase):
self.tic() self.tic()
@newSimulationExpectedFailure
def testProject_getSourceProjectRelatedTaskReportList(self): def testProject_getSourceProjectRelatedTaskReportList(self):
""" """
Basic Test if the script behaviour as expected. Basic Test if the script behaviour as expected.
......
...@@ -368,9 +368,9 @@ return context.generatePredicate( ...@@ -368,9 +368,9 @@ return context.generatePredicate(
kw['trade_phase_relative_url'] = [] kw['trade_phase_relative_url'] = []
self.assertEqual(len(rule_tool.searchRuleList(self.sm, **kw)), 1) self.assertEqual(len(rule_tool.searchRuleList(self.sm, **kw)), 1)
def test_08_updateAppliedRule(self, quiet=quiet, run=run_all_test): def test_08_createRootAppliedRule(self, quiet=quiet, run=run_all_test):
""" """
test that when updateAppliedRule is called, the rule with the correct test that when updateSimulation is called, the rule with the correct
reference and higher version is used reference and higher version is used
XXX as expand is triggered here, make sure rules won't be created forever XXX as expand is triggered here, make sure rules won't be created forever
...@@ -396,24 +396,28 @@ return context.generatePredicate( ...@@ -396,24 +396,28 @@ return context.generatePredicate(
self.tic() self.tic()
# delivery_rule_2 should be applied # delivery_rule_2 should be applied
self.pl.updateAppliedRule('default_delivery_rule') self.pl.updateSimulation(create_root=1)
self.tic() self.tic()
self.assertEquals(self.pl.getCausalityRelatedValue().getSpecialise(), root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule_2.getRelativeUrl()) delivery_rule_2.getRelativeUrl())
self.getSimulationTool().manage_delObjects( self.getSimulationTool()._delObject(root_applied_rule.getId())
ids=[self.pl.getCausalityRelatedId()])
# increase version of delivery_rule_1 # increase version of delivery_rule_1
delivery_rule_1.setVersion("testRule.3") delivery_rule_1.setVersion("testRule.3")
self.tic() self.tic()
# delivery_rule_1 should be applied # delivery_rule_1 should be applied
self.pl.updateAppliedRule('default_delivery_rule') self.pl.updateSimulation(create_root=1)
self.tic() self.tic()
self.assertEquals(self.pl.getCausalityRelatedValue().getSpecialise(), root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule_1.getRelativeUrl()) delivery_rule_1.getRelativeUrl())
self.getSimulationTool()._delObject(root_applied_rule.getId())
self.tic()
def test_09_expandTwoRules(self, quiet=quiet, run=run_all_test): def test_09_expandTwoRules(self, quiet=quiet, run=run_all_test):
""" """
test that when expand is called on a simulation movement, if two rules test that when expand is called on a simulation movement, if two rules
...@@ -443,47 +447,40 @@ return context.generatePredicate( ...@@ -443,47 +447,40 @@ return context.generatePredicate(
test_method_id='invoice_rule_script') test_method_id='invoice_rule_script')
invoicing_rule_2.validate() invoicing_rule_2.validate()
# clear simulation self.pl.updateSimulation(create_root=1)
self.getSimulationTool().manage_delObjects(
ids=list(self.getSimulationTool().objectIds()))
self.tic()
self.pl.updateAppliedRule('default_delivery_rule')
self.tic() self.tic()
# check that only one invoicing rule (higher version) was applied # check that only one invoicing rule (higher version) was applied
root_applied_rule = self.pl.getCausalityRelatedValue() root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.assertEquals(root_applied_rule.getSpecialise(), self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl()) delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1) movement, = root_applied_rule.objectValues()
movement = root_applied_rule.objectValues()[0] applied_rule, = movement.objectValues()
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_2.getRelativeUrl()) invoicing_rule_2.getRelativeUrl())
# increase version of other rule, clean simulation and check again # increase version of other rule, clean simulation and check again
self.getSimulationTool().manage_delObjects( self.getSimulationTool()._delObject(root_applied_rule.getId())
ids=[self.pl.getCausalityRelatedId()])
invoicing_rule_1.setVersion('testRule.3') invoicing_rule_1.setVersion('testRule.3')
self.tic() self.tic()
self.pl.updateAppliedRule('default_delivery_rule') self.pl.updateSimulation(create_root=1)
self.tic() self.tic()
# check that only one invoicing rule (higher version) was applied # check that only one invoicing rule (higher version) was applied
root_applied_rule = self.pl.getCausalityRelatedValue() root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.assertEquals(root_applied_rule.getSpecialise(), self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl()) delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1) movement, = root_applied_rule.objectValues()
movement = root_applied_rule.objectValues()[0] applied_rule, = movement.objectValues()
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
self.getSimulationTool()._delObject(root_applied_rule.getId())
self.tic()
def test_10_expandAddsRule(self, quiet=quiet, run=run_all_test): def test_10_expandAddsRule(self, quiet=quiet, run=run_all_test):
""" """
test that if a rule didn't match previously, and does now, it should apply test that if a rule didn't match previously, and does now, it should apply
...@@ -508,20 +505,14 @@ return context.generatePredicate( ...@@ -508,20 +505,14 @@ return context.generatePredicate(
test_method_id='delivery_rule_script') test_method_id='delivery_rule_script')
invoicing_rule_1.validate() invoicing_rule_1.validate()
# clear simulation self.pl.updateSimulation(create_root=1)
self.getSimulationTool().manage_delObjects(
ids=list(self.getSimulationTool().objectIds()))
self.tic() self.tic()
root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.pl.updateAppliedRule('default_delivery_rule')
self.tic()
root_applied_rule = self.pl.getCausalityRelatedValue()
# check that no invoicing rule was applied # check that no invoicing rule was applied
self.assertEquals(root_applied_rule.getSpecialise(), self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl()) delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1) movement, = root_applied_rule.objectValues()
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 0) self.assertEquals(movement.objectCount(), 0)
# change rule script so that it matches and test again # change rule script so that it matches and test again
...@@ -529,17 +520,8 @@ return context.generatePredicate( ...@@ -529,17 +520,8 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated()) invoicing_rule_1_applied_rule, = movement.objectValues()
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 1)
invoicing_rule_1_applied_rule = movement.objectValues()[0]
self.assertEquals(invoicing_rule_1_applied_rule.getSpecialise(), self.assertEquals(invoicing_rule_1_applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
...@@ -557,24 +539,17 @@ return context.generatePredicate( ...@@ -557,24 +539,17 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated()) applied_rule_1, applied_rule_2 = sorted(movement.objectValues(),
self.assertEquals(root_applied_rule.getSpecialise(), key=lambda x: x.getSpecialiseReference())
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 2)
applied_rule_list = sorted(movement.objectValues(),
key=lambda x: x.getSpecialiseValue().getReference())
# check the 1st applied rule is an application of invoicing_rule_1 # check the 1st applied rule is an application of invoicing_rule_1
self.assertEquals(applied_rule_list[0].getSpecialise(), self.assertEquals(applied_rule_1.getSpecialise(),
invoicing_rule_n.getRelativeUrl()) invoicing_rule_n.getRelativeUrl())
self.assertEquals(applied_rule_list[1].getSpecialise(), self.assertEquals(applied_rule_2.getSpecialise(),
invoicing_rule_2.getRelativeUrl()) invoicing_rule_2.getRelativeUrl())
self.getSimulationTool()._delObject(root_applied_rule.getId())
self.tic()
def test_11_expandRemovesRule(self, quiet=quiet, run=run_all_test): def test_11_expandRemovesRule(self, quiet=quiet, run=run_all_test):
""" """
...@@ -600,23 +575,15 @@ return context.generatePredicate( ...@@ -600,23 +575,15 @@ return context.generatePredicate(
test_method_id='invoice_rule_script') test_method_id='invoice_rule_script')
invoicing_rule_1.validate() invoicing_rule_1.validate()
# clear simulation self.pl.updateSimulation(create_root=1)
self.getSimulationTool().manage_delObjects(
ids=list(self.getSimulationTool().objectIds()))
self.tic() self.tic()
root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.pl.updateAppliedRule('default_delivery_rule')
self.tic()
root_applied_rule = self.pl.getCausalityRelatedValue()
# check that the invoicing rule was applied # check that the invoicing rule was applied
self.assertEquals(root_applied_rule.getSpecialise(), self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl()) delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1) movement, = root_applied_rule.objectValues()
movement = root_applied_rule.objectValues()[0] applied_rule, = movement.objectValues()
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
...@@ -627,12 +594,7 @@ return context.generatePredicate( ...@@ -627,12 +594,7 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated())
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 0) self.assertEquals(movement.objectCount(), 0)
# change the test method to one that fails, and test that the rule is # change the test method to one that fails, and test that the rule is
...@@ -641,12 +603,7 @@ return context.generatePredicate( ...@@ -641,12 +603,7 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated())
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 0) self.assertEquals(movement.objectCount(), 0)
# change the test to one that succeeds, revalidate, expand, add a delivery # change the test to one that succeeds, revalidate, expand, add a delivery
...@@ -659,18 +616,11 @@ return context.generatePredicate( ...@@ -659,18 +616,11 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated()) applied_rule, = movement.objectValues()
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
self.assertEquals(applied_rule.objectCount(), 1) sub_movement, = applied_rule.objectValues()
sub_movement = applied_rule.objectValues()[0]
sub_movement.setDeliveryValue(self.pl.line) sub_movement.setDeliveryValue(self.pl.line)
...@@ -678,20 +628,16 @@ return context.generatePredicate( ...@@ -678,20 +628,16 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated()) self.assertEquals(list(movement.objectValues()), [applied_rule])
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
self.assertEquals(applied_rule.objectCount(), 1) self.assertEquals(list(applied_rule.objectValues()), [sub_movement])
sub_movement = applied_rule.objectValues()[0]
self.assertEquals(sub_movement.getDelivery(), self.pl.line.getRelativeUrl()) self.assertEquals(sub_movement.getDelivery(), self.pl.line.getRelativeUrl())
self.getSimulationTool()._delObject(root_applied_rule.getId())
self.tic()
def test_12_expandReplacesRule(self, quiet=quiet, run=run_all_test): def test_12_expandReplacesRule(self, quiet=quiet, run=run_all_test):
""" """
test that if a rule matched previously and does not anymore, and another test that if a rule matched previously and does not anymore, and another
...@@ -721,23 +667,15 @@ return context.generatePredicate( ...@@ -721,23 +667,15 @@ return context.generatePredicate(
test_method_id='invoice_rule_script') test_method_id='invoice_rule_script')
invoicing_rule_2.validate() invoicing_rule_2.validate()
# clear simulation self.pl.updateSimulation(create_root=1)
self.getSimulationTool().manage_delObjects(
ids=list(self.getSimulationTool().objectIds()))
self.tic() self.tic()
root_applied_rule, = self.pl.getCausalityRelatedValueList()
self.pl.updateAppliedRule('default_delivery_rule')
self.tic()
root_applied_rule = self.pl.getCausalityRelatedValue()
# check that the invoicing rule 2 was applied # check that the invoicing rule 2 was applied
self.assertEquals(root_applied_rule.getSpecialise(), self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl()) delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1) movement, = root_applied_rule.objectValues()
movement = root_applied_rule.objectValues()[0] applied_rule, = movement.objectValues()
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_2.getRelativeUrl()) invoicing_rule_2.getRelativeUrl())
...@@ -747,39 +685,29 @@ return context.generatePredicate( ...@@ -747,39 +685,29 @@ return context.generatePredicate(
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated()) applied_rule, = movement.objectValues()
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
# change the test of invoicing rule 2 to one that succeeds, add a delivery # change the test of invoicing rule 2 to one that succeeds, add a delivery
# relation, expand, and test that the invoicing rule 1 is still there # relation, expand, and test that the invoicing rule 1 is still there
invoicing_rule_2.setTestMethodId('invoice_rule_script') invoicing_rule_2.setTestMethodId('invoice_rule_script')
sub_movement = applied_rule.objectValues()[0] sub_movement, = applied_rule.objectValues()
sub_movement.setDeliveryValue(self.pl.line) sub_movement.setDeliveryValue(self.pl.line)
root_applied_rule.expand() root_applied_rule.expand()
self.tic() self.tic()
self.assertEquals(root_applied_rule.getRelativeUrl(), self.assertEquals(list(root_applied_rule.objectValues()), [movement])
self.pl.getCausalityRelated()) self.assertEquals(list(movement.objectValues()), [applied_rule])
self.assertEquals(root_applied_rule.getSpecialise(),
delivery_rule.getRelativeUrl())
self.assertEquals(root_applied_rule.objectCount(), 1)
movement = root_applied_rule.objectValues()[0]
self.assertEquals(movement.objectCount(), 1)
applied_rule = movement.objectValues()[0]
self.assertEquals(applied_rule.getSpecialise(), self.assertEquals(applied_rule.getSpecialise(),
invoicing_rule_1.getRelativeUrl()) invoicing_rule_1.getRelativeUrl())
self.assertEquals(applied_rule.objectCount(), 1) self.assertEquals(list(applied_rule.objectValues()), [sub_movement])
sub_movement = applied_rule.objectValues()[0]
self.assertEquals(sub_movement.getDelivery(), self.pl.line.getRelativeUrl()) self.assertEquals(sub_movement.getDelivery(), self.pl.line.getRelativeUrl())
self.getSimulationTool()._delObject(root_applied_rule.getId())
self.tic()
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
...@@ -458,13 +458,13 @@ class TestTaskMixin: ...@@ -458,13 +458,13 @@ class TestTaskMixin:
self.assertEqual(task_line.getDescription(), self.assertEqual(task_line.getDescription(),
task_report_line.getDescription()) task_report_line.getDescription())
def stepVerifyTaskReportCausalityState(self, sequence=None, def stepAssertDraftCausalityState(self, sequence=None,
sequence_list=None, **kw): sequence_list=None, **kw):
""" """
Verify that confirmed task report starts building and gets solved. Verify that confirmed task report starts building and gets solved.
""" """
task_report = sequence.get('task_report') task_report = sequence.get('task_report')
self.assertEqual(task_report.getCausalityState(), 'solved') self.assertEqual(task_report.getCausalityState(), 'draft')
def stepVerifyTaskReportNoPrice(self, sequence=None, def stepVerifyTaskReportNoPrice(self, sequence=None,
sequence_list=None, **kw): sequence_list=None, **kw):
...@@ -625,7 +625,7 @@ class TestTask(TestTaskMixin, ERP5TypeTestCase): ...@@ -625,7 +625,7 @@ class TestTask(TestTaskMixin, ERP5TypeTestCase):
sequence_string = self.default_task_report_sequence + '\ sequence_string = self.default_task_report_sequence + '\
stepConfirmTaskReport \ stepConfirmTaskReport \
stepTic \ stepTic \
stepVerifyTaskReportCausalityState \ stepAssertDraftCausalityState \
stepStartTaskReport \ stepStartTaskReport \
stepFinishTaskReport \ stepFinishTaskReport \
stepCloseTaskReport \ stepCloseTaskReport \
......
...@@ -370,8 +370,8 @@ class TestTradeModelLine(TestTradeModelLineMixin): ...@@ -370,8 +370,8 @@ class TestTradeModelLine(TestTradeModelLineMixin):
def checkWithoutBPM(self, order): def checkWithoutBPM(self, order):
self.commit()# clear transactional cache self.commit()# clear transactional cache
order.getSpecialiseValue()._setSpecialise(None) order.getSpecialiseValue()._setSpecialise(None)
self.assertRaises(ValueError, order.expand, self.assertRaises(ValueError, order.getCausalityRelatedValue(
applied_rule_id=order.getCausalityRelatedId(portal_type='Applied Rule')) portal_type='Applied Rule').expand, 'immediate')
self.abort() self.abort()
def checkModelLineOnDelivery(self, delivery): def checkModelLineOnDelivery(self, delivery):
......
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