← Back to team overview

savoirfairelinux-openerp team mailing list archive

[Merge] lp:~extra-addons-commiter/e-commerce-addons/7.0-sale-workflow into lp:e-commerce-addons

 

You have been requested to review the proposed merge of lp:~extra-addons-commiter/e-commerce-addons/7.0-sale-workflow into lp:e-commerce-addons.

For more details, see:
https://code.launchpad.net/~extra-addons-commiter/e-commerce-addons/7.0-sale-workflow/+merge/155920

This is part of the migration of the connectors (especially magentoerpconnect for my part) to version 7.0 of OpenERP.

This merge proposal follows the one on sale_payment_method / sale_quick_payment [0].

This merge proposal aims to improve / adapt the module sale_automatic_workflow for this new release of the Magentoerpconnect.
A part of the changes is the consequence of the changes in the prerequisite branch. Another part is the intention to keep the responsibilities of the automatic workflow in this module. Previously, half of the options in the workflow (default values, confirmation of sale order) where just fields in the workflow setup, letting the responsibilities to the connectors to implement the logic around them. I think that the automatic workflow should work out of the box, and the connectors should just have to choose the workflow to use for a sale order.

Most of the changes were discussed with Sébastien Beau.

List of changes:

* The module does no longer depends on sale_quick_payment but sale_payment_method (see the prerequisite branch).

* Adapt the reconcile method to use the move lines instead of the voucher (consequence of the prerequisite branch).

* Review of the automatic cron job
  - opening a new cr is no longer necessary since 7.0 as the cron does not share its own one anymore
  - removed the dependency on the module 'framework_helpers' and replace 'commit_now' by a local context manager
  - reorganize the 'run' method in smaller methods doing their own part

* Comment the field 'validate_manufacturing_order' until a reimplementation

* In version 6.1, the connectors were responsible to set the default values of the sale orders according to the workflow. Now, this is done by an onchange when the workflow is changed on the sale order. The connectors have to call the onchange though.

* When the payment method is changed on the sale order, the onchange set the right workflow (instead of a related), this allows to use an onchange on the workflow, but also to use a workflow even if the sale order has no payment method.

* Remove 'postpaid' from the order policy as this choice does no longer exist in OpenERP... (and use the same wording for the other choices)

* Removed the field 'days_before_order_cancel', I moved this field in connector_ecommerce, it has no sense otherwise.

* The field 'validate_order' is now a boolean instead of a selection 'never', 'always', 'if paid', because the behavior changes in the new connectors: per payment method, we can choose if a sale order is imported or not according to conditions (basically the same, always, never  or if paid, at the moment). But if we choose to import an order only if it is paid, it means that it will be created only if it is paid. We validate it or not.

* Fix: the workflow_process_id was not transfered to the stock picking (big mess in OpenERP with stock.picking and stock.picking.out)

* Add the automatic validation of sales orders (it was done in the connectors previously)


[0] https://code.launchpad.net/~extra-addons-commiter/e-commerce-addons/7.0-sale-method/+merge/155916

-- 
https://code.launchpad.net/~extra-addons-commiter/e-commerce-addons/7.0-sale-workflow/+merge/155920
Your team E-Commerce Addons Core Editors is requested to review the proposed merge of lp:~extra-addons-commiter/e-commerce-addons/7.0-sale-workflow into lp:e-commerce-addons.
=== modified file 'sale_automatic_workflow/__openerp__.py'
--- sale_automatic_workflow/__openerp__.py	2012-12-26 13:22:11 +0000
+++ sale_automatic_workflow/__openerp__.py	2013-05-02 07:30:40 +0000
@@ -21,31 +21,45 @@
 
 
 {
-    'name': 'sale_automatic_workflow',
-    'version': '0.1',
+    'name': 'Sale Automatic Workflow',
+    'version': '0.2',
     'category': 'Generic Modules/Others',
     'license': 'AGPL-3',
-    'description': """empty""",
+    'description': """
+Sale Automatic Workflow
+=======================
+
+Create workflows with more or less automatization and apply it on sales
+orders.
+
+A workflow can:
+
+- Apply default values:
+  * Packing Policy (partial, complete)
+  * Shipping Policy (prepaid, manual, postpaid, picking)
+  * Invoice On (ordered quantities, shipped quantities)
+  * Set the invoice's date to the sale order's date
+
+- Apply automatic actions:
+  * Validate the order (only if paid, always, never)
+  * Create an invoice
+  * Validate the invoice
+  * Confirm the picking
+
+This module is used by Magentoerpconnect and Prestashoperpconnect.
+It is well suited for other E-Commerce connectors as well.
+""",
     'author': 'Akretion',
     'website': 'http://www.akretion.com/',
-    'depends': [
-        'sale_quick_payment',
-        'framework_helpers',
-        'stock',
-    ], 
-    'init_xml': [],
-    'update_xml': [ 
-            'sale_view.xml',
-            'sale_workflow.xml',
-#            'invoice_workflow.xml',
-#            'stock_workflow.xml',
-            'sale_workflow_process_view.xml',
-            'payment_method_view.xml',
-            'automatic_workflow_data.xml',
-            'security/ir.model.access.csv',
-    ],
-    'demo_xml': [],
+    'depends': ['sale_payment_method',
+                'stock',
+                ],
+    'data': ['sale_view.xml',
+             'sale_workflow.xml',
+             'sale_workflow_process_view.xml',
+             'payment_method_view.xml',
+             'automatic_workflow_data.xml',
+             'security/ir.model.access.csv',
+             ],
     'installable': True,
-    'active': False,
 }
-

=== modified file 'sale_automatic_workflow/automatic_workflow_data.xml'
--- sale_automatic_workflow/automatic_workflow_data.xml	2012-05-06 17:55:14 +0000
+++ sale_automatic_workflow/automatic_workflow_data.xml	2013-05-02 07:30:40 +0000
@@ -1,27 +1,38 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  sale_quick_payment for OpenERP
+  sale_automatic_workflow for OpenERP
   Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
   The licence is in the file __openerp__.py
 -->
 
 <openerp>
-    <data>
+    <data noupdate="1">
 
         <!-- VIEW FOR THE OBJECT : payment_method -->
         <record id="automatic_validation" model="sale.workflow.process">
             <field name="name">Automatic Validation</field>
             <field name="picking_policy">one</field>
-            <field name="order_policy">postpaid</field>
+            <field name="order_policy">picking</field>
             <field name="invoice_quantity">order</field>
-            <field name="validate_order">if_paid</field>
+            <field name="validate_order" eval="0"/>
             <field name="create_invoice" eval="1" />
             <field name="validate_invoice" eval="1" />
             <field name="invoice_date_is_order_date" eval="0" />
             <field name="validate_picking" eval="0" />
             <field name="validate_manufactoring_order" eval="0" />
-            <field name="days_before_order_cancel">5</field>
         </record>
 
+        <record forcecreate="True" id="ir_cron_automatic_workflow_job" model="ir.cron">
+            <field name="name">Automatic Workflow Job</field>
+            <field eval="True" name="active"/>
+            <field name="user_id" ref="base.user_root"/>
+            <field name="interval_number">1</field>
+            <field name="interval_type">minutes</field>
+            <field name="numbercall">-1</field>
+            <field eval="False" name="doall"/>
+            <field eval="'automatic.workflow.job'" name="model"/>
+            <field eval="'run'" name="function"/>
+            <field eval="'()'" name="args"/>
+        </record>
     </data>
 </openerp>

=== modified file 'sale_automatic_workflow/automatic_workflow_job.py'
--- sale_automatic_workflow/automatic_workflow_job.py	2012-12-26 13:22:11 +0000
+++ sale_automatic_workflow/automatic_workflow_job.py	2013-05-02 07:30:40 +0000
@@ -1,4 +1,4 @@
-# -*- encoding: utf-8 -*-
+# -*- coding: utf-8 -*-
 #################################################################################
 #                                                                               #
 #    sale_automatic_workflow for OpenERP                                        #
@@ -20,62 +20,128 @@
 #################################################################################
 
 
-from openerp.osv.orm import Model
-import netsvc
 import logging
-from tools.translate import _
-from framework_helpers.context_managers import new_cursor, commit_now
-
-#Some comment about the implementation
-#In order to validate the invoice the picking we have to use schedule action
-#Indeed, if we directly jump the various step in the workflow of the invoice and the picking
-#the sale order workflow will be broken
-#The explication is "simple"
-#Example with the invoice workflow
-#When we are in the sale order at the step router
-#a transiotion like a signal or condition will change the step of the workflow to the step 'invoice'
-#the fact to enter in this step will launch the creation of the invoice
-#if the invoice in directly validated and reconcilled with the payment
-#the subworkflow will end and send a signal to the sale order workflow
-#the problem is that the sale order workflow have not finish to apply the step invoice
-#and so the signal of the subworkflow will be lost
-#because the step invoice is still not finish
-#The step invoice should be finish before receiving the signal
-#this is meant that we can not directly validated every step of the workflow invoice_amount
-#it the same with the picking workflow_method
-
-#If my explication is not clear contact me by email and I will imporve it: sebastien.beau@xxxxxxxxxxxx
-
-class automatic_workflow_job(Model):
-    """
-    Scheduler that will play automatically the validation on invoice, picking...
-    """
+from contextlib import contextmanager
+from openerp.osv import orm
+from openerp import pooler
+from openerp import netsvc
+
+"""
+Some comments about the implementation
+
+In order to validate the invoice and the picking, we have to use
+scheduled actions, because if we directly jump the various steps in the
+workflow of the invoice and the picking, the sale order workflow will be
+broken.
+
+The explanation is 'simple'. Example with the invoice workflow: When we
+are in the sale order at the workflow router, a transition like a signal
+or condition will change the step of the workflow to the step 'invoice';
+this step will launch the creation of the invoice.  If the invoice is
+directly validated and reconciled with the payment, the subworkflow will
+end and send a signal to the sale order workflow.  The problem is that
+the sale order workflow has not yet finished to apply the step 'invoice',
+so the signal of the subworkflow will be lost because the step 'invoice'
+is still not finished. The step invoice should be finished before
+receiving the signal. This means that we can not directly validate every
+steps of the workflow in the same transaction.
+
+If my explanation is not clear, contact me by email and I will improve
+it: sebastien.beau@xxxxxxxxxxxx
+"""
+
+_logger = logging.getLogger(__name__)
+
+
+@contextmanager
+def commit(cr):
+    """
+    Commit the cursor after the ``yield``, or rollback it if an
+    exception occurs.
+
+    Warning: using this method, the exceptions are logged then discarded.
+    """
+    try:
+        yield
+    except Exception, e:
+        cr.rollback()
+        _logger.exception('Error during an automatic workflow action.')
+    else:
+        cr.commit()
+
+
+class automatic_workflow_job(orm.Model):
+    """ Scheduler that will play automatically the validation of
+    invoices, pickings...  """
     _name = 'automatic.workflow.job'
 
+    def _validate_sale_orders(self, cr, uid, context=None):
+        wf_service = netsvc.LocalService("workflow")
+        sale_obj = self.pool.get('sale.order')
+        sale_ids = sale_obj.search(
+            cr, uid,
+            [('state', '=', 'draft'),
+             ('workflow_process_id.validate_order', '=', True)],
+            context=context)
+        _logger.debug('Sale Orders to validate: %s', sale_ids)
+        for sale_id in sale_ids:
+            with commit(cr):
+                wf_service.trg_validate(uid, 'sale.order',
+                                        sale_id, 'order_confirm', cr)
+
+    def _reconcile_invoices(self, cr, uid, ids=None, context=None):
+        invoice_obj = self.pool.get('account.invoice')
+        if ids is None:
+            ids = invoice_obj.search(cr, uid,
+                                     [('state', 'in', ['open'])],
+                                     context=context)
+        for invoice_id in ids:
+            with commit(cr):
+                invoice_obj.reconcile_invoice(cr, uid,
+                                              [invoice_id],
+                                              context=context)
+
+    def _validate_invoices(self, cr, uid, context=None):
+        wf_service = netsvc.LocalService("workflow")
+        invoice_obj = self.pool.get('account.invoice')
+        invoice_ids = invoice_obj.search(
+            cr, uid,
+            [('state', 'in', ['draft']),
+             ('workflow_process_id.validate_invoice', '=', True)],
+            context=context)
+        _logger.debug('Invoices to validate: %s', invoice_ids)
+        for invoice_id in invoice_ids:
+            with commit(cr):
+                wf_service.trg_validate(uid, 'account.invoice',
+                                        invoice_id, 'invoice_open', cr)
+
+    def _validate_pickings(self, cr, uid, context=None):
+        picking_obj = self.pool.get('stock.picking')
+        picking_out_obj = self.pool.get('stock.picking.out')
+        # We search on stock.picking (using the type) rather than
+        # stock.picking.out because the ORM seems bugged and can't
+        # search on stock_picking_out.workflow_process_id.
+        # Later, we'll call `validate_picking` on stock.picking.out
+        # because anyway they have the same ID and the call will be at
+        # the correct object level.
+        picking_ids = picking_obj.search(
+            cr, uid,
+            [('state', 'in', ['draft', 'confirmed', 'assigned']),
+             ('workflow_process_id.validate_picking', '=', True),
+             ('type', '=', 'out')],
+            context=context)
+        _logger.debug('Pickings to validate: %s', picking_ids)
+        if picking_ids:
+            with commit(cr):
+                picking_out_obj.validate_picking(cr, uid,
+                                                 picking_ids,
+                                                 context=context)
+
     def run(self, cr, uid, ids=None, context=None):
-        logger = logging.getLogger(__name__)
-        wf_service = netsvc.LocalService("workflow")
-        invoice_obj = self.pool.get('account.invoice')
-
-        with new_cursor(cr, logger) as cr:
-            open_invoice_ids = invoice_obj.search(cr, uid, [('state', 'in', ['open'])], context=context)
-            for open_invoice_id in open_invoice_ids:
-                with commit_now(cr, logger) as cr:
-                    invoice_obj.reconcile_invoice(cr, uid, [open_invoice_id], context=context)
-
-            invoice_ids = invoice_obj.search(cr, uid, [('state', 'in', ['draft']), ('workflow_process_id.validate_invoice', '=',True)], context=context)
-            if invoice_ids:
-                logger.debug(_('start to validate invoice : %s') %invoice_ids)
-            for invoice_id in invoice_ids:
-                with commit_now(cr, logger) as cr:
-                    wf_service.trg_validate(uid, 'account.invoice', invoice_id, 'invoice_open', cr)
-                with commit_now(cr, logger) as cr:
-                    invoice_obj.reconcile_invoice(cr, uid, [invoice_id], context=context)
-
-            picking_obj = self.pool.get('stock.picking.out')
-            picking_ids = picking_obj.search(cr, uid, [('state', 'in', ['draft', 'confirmed', 'assigned']), ('workflow_process_id.validate_picking', '=',True)], context=context)
-            if picking_ids:
-                logger.debug(_('start to validate pickings : %s') %picking_ids)
-                with commit_now(cr, logger) as cr:
-                    picking_obj.validate_picking(cr, uid, picking_ids, context=context)
+        """ Must be called from ir.cron """
+
+        self._validate_sale_orders(cr, uid, context=context)
+        self._validate_invoices(cr, uid, context=context)
+        self._reconcile_invoices(cr, uid, context=context)
+        self._validate_pickings(cr, uid, context=context)
         return True

=== added directory 'sale_automatic_workflow/i18n'
=== added file 'sale_automatic_workflow/i18n/fr_FR.po'
--- sale_automatic_workflow/i18n/fr_FR.po	1970-01-01 00:00:00 +0000
+++ sale_automatic_workflow/i18n/fr_FR.po	2013-05-02 07:30:40 +0000
@@ -0,0 +1,187 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* sale_automatic_workflow
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-05-02 07:15+0000\n"
+"PO-Revision-Date: 2013-05-02 07:15+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,validate_order:0
+msgid "Validate Order"
+msgstr "Confirmer les commandes"
+
+#. module: sale_automatic_workflow
+#: view:sale.workflow.process:0
+msgid "Workflow Options"
+msgstr "Options du flux automatique"
+
+#. module: sale_automatic_workflow
+#: field:payment.method,workflow_process_id:0
+#: field:sale.order,workflow_process_id:0
+msgid "Workflow Process"
+msgstr "Flux automatique"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,invoice_quantity:0
+msgid "Shipped Quantities"
+msgstr "Quantités livrées"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,create_invoice_on:0
+msgid "Create Invoice"
+msgstr "Créer les factures"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_stock_picking
+msgid "Picking List"
+msgstr "Liste de colisage"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,validate_invoice:0
+msgid "Validate Invoice"
+msgstr "Valider les factures"
+
+#. module: sale_automatic_workflow
+#: view:sale.workflow.process:0
+msgid "Order Configuration"
+msgstr "Configuration des bons de commande"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,order_policy:0
+msgid "On Demand"
+msgstr "À la demande"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_payment_method
+msgid "Payment Method"
+msgstr "Méthode de paiement"
+
+#. module: sale_automatic_workflow
+#: help:sale.workflow.process,invoice_date_is_order_date:0
+msgid "When checked, the invoice date will be the same than the order's date"
+msgstr "Si activé, la date de facturation sera identique à la date de la commande."
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,invoice_quantity:0
+msgid "Ordered Quantities"
+msgstr "Quantités commandées"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,invoice_date_is_order_date:0
+msgid "Force Invoice Date"
+msgstr "Forcer la date de facturation"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,picking_policy:0
+msgid "Deliver all products at once"
+msgstr "Livrer tous les articles en une fois"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,create_invoice_on:0
+msgid "No automatic invoice"
+msgstr "Pas de facture automatique"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,name:0
+msgid "Name"
+msgstr "Nom"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,invoice_quantity:0
+msgid "Invoice on"
+msgstr "Facturer sur"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,create_invoice_on:0
+msgid "On confirmation of Sale Order"
+msgstr "À la confirmation de la commande"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,order_policy:0
+msgid "On Delivery Order"
+msgstr "Sur le bon de livraison"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,order_policy:0
+msgid "Before Delivery"
+msgstr "Avant livraison"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_automatic_workflow_job
+msgid "automatic.workflow.job"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,create_invoice_on:0
+msgid "After Delivery"
+msgstr "Après livraison"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,picking_policy:0
+msgid "Shipping Policy"
+msgstr "Politique d'expédition"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_sale_workflow_process
+msgid "sale workflow process"
+msgstr "Flux automatique de vente"
+
+#. module: sale_automatic_workflow
+#: model:ir.actions.act_window,name:sale_automatic_workflow.act_sale_workflow_process_form
+#: model:ir.ui.menu,name:sale_automatic_workflow.menu_act_sale_workflow_process_form
+#: view:sale.order:0
+#: view:sale.workflow.process:0
+msgid "Automatic Workflow"
+msgstr "Flux automatique"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_sale_order
+msgid "Sales Order"
+msgstr "Bon de commande"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,validate_picking:0
+msgid "Confirm and Close Picking"
+msgstr "Confirmer et terminer les bons de livraison"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,order_policy:0
+msgid "Invoice Policy"
+msgstr "Politique de facturation"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_account_invoice
+msgid "Invoice"
+msgstr "Facture"
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,picking_policy:0
+msgid "Deliver each product when available"
+msgstr "Livrer chaque article dès disponibilité"
+
+#. module: sale_automatic_workflow
+#: field:account.invoice,sale_ids:0
+msgid "Sale Orders"
+msgstr "Bons de commande"
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_stock_picking_out
+msgid "Delivery Orders"
+msgstr "Bons de livraison"
+
+#. module: sale_automatic_workflow
+#: field:account.invoice,workflow_process_id:0
+#: field:stock.picking,workflow_process_id:0
+msgid "Sale Workflow Process"
+msgstr "Flux automatique de vente"
+

=== added file 'sale_automatic_workflow/i18n/sale_automatic_workflow.pot'
--- sale_automatic_workflow/i18n/sale_automatic_workflow.pot	1970-01-01 00:00:00 +0000
+++ sale_automatic_workflow/i18n/sale_automatic_workflow.pot	2013-05-02 07:30:40 +0000
@@ -0,0 +1,187 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* sale_automatic_workflow
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-05-02 07:15+0000\n"
+"PO-Revision-Date: 2013-05-02 07:15+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,validate_order:0
+msgid "Validate Order"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: view:sale.workflow.process:0
+msgid "Workflow Options"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:payment.method,workflow_process_id:0
+#: field:sale.order,workflow_process_id:0
+msgid "Workflow Process"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,invoice_quantity:0
+msgid "Shipped Quantities"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,create_invoice_on:0
+msgid "Create Invoice"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_stock_picking
+msgid "Picking List"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,validate_invoice:0
+msgid "Validate Invoice"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: view:sale.workflow.process:0
+msgid "Order Configuration"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,order_policy:0
+msgid "On Demand"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_payment_method
+msgid "Payment Method"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: help:sale.workflow.process,invoice_date_is_order_date:0
+msgid "When checked, the invoice date will be the same than the order's date"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,invoice_quantity:0
+msgid "Ordered Quantities"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,invoice_date_is_order_date:0
+msgid "Force Invoice Date"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,picking_policy:0
+msgid "Deliver all products at once"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,create_invoice_on:0
+msgid "No automatic invoice"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,name:0
+msgid "Name"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,invoice_quantity:0
+msgid "Invoice on"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,create_invoice_on:0
+msgid "On confirmation of Sale Order"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,order_policy:0
+msgid "On Delivery Order"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,order_policy:0
+msgid "Before Delivery"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_automatic_workflow_job
+msgid "automatic.workflow.job"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,create_invoice_on:0
+msgid "After Delivery"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,picking_policy:0
+msgid "Shipping Policy"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_sale_workflow_process
+msgid "sale workflow process"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.actions.act_window,name:sale_automatic_workflow.act_sale_workflow_process_form
+#: model:ir.ui.menu,name:sale_automatic_workflow.menu_act_sale_workflow_process_form
+#: view:sale.order:0
+#: view:sale.workflow.process:0
+msgid "Automatic Workflow"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,validate_picking:0
+msgid "Confirm and Close Picking"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:sale.workflow.process,order_policy:0
+msgid "Invoice Policy"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_account_invoice
+msgid "Invoice"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: selection:sale.workflow.process,picking_policy:0
+msgid "Deliver each product when available"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:account.invoice,sale_ids:0
+msgid "Sale Orders"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: model:ir.model,name:sale_automatic_workflow.model_stock_picking_out
+msgid "Delivery Orders"
+msgstr ""
+
+#. module: sale_automatic_workflow
+#: field:account.invoice,workflow_process_id:0
+#: field:stock.picking,workflow_process_id:0
+msgid "Sale Workflow Process"
+msgstr ""
+

=== modified file 'sale_automatic_workflow/invoice.py'
--- sale_automatic_workflow/invoice.py	2012-12-26 13:22:11 +0000
+++ sale_automatic_workflow/invoice.py	2013-05-02 07:30:40 +0000
@@ -5,6 +5,8 @@
 #   Copyright (C) 2011-TODAY Akretion <http://www.akretion.com>.
 #     All Rights Reserved
 #     @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+#   Copyright Camptocamp SA 2013 (Guewen Baconnier)
+#
 #   This program is free software: you can redistribute it and/or modify
 #   it under the terms of the GNU Affero General Public License as
 #   published by the Free Software Foundation, either version 3 of the
@@ -19,24 +21,31 @@
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ###############################################################################
-from openerp.osv.orm import Model
-from openerp.osv import fields
-
-class account_invoice(Model):
+from openerp.osv import fields, orm
+
+
+class account_invoice(orm.Model):
     _inherit = "account.invoice"
+
     _columns = {
-        'workflow_process_id':fields.many2one('sale.workflow.process', 'Sale Workflow Process'),
+        'workflow_process_id': fields.many2one('sale.workflow.process',
+                                               string='Sale Workflow Process'),
         #TODO propose a merge to add this field by default in acount module
-        'sale_ids': fields.many2many('sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale Orders')
+        'sale_ids': fields.many2many('sale.order', 'sale_order_invoice_rel',
+                                     'invoice_id', 'order_id',
+                                     string='Sale Orders')
     }
 
     def _can_be_reconciled(self, cr, uid, invoice, context=None):
-        if not (invoice.sale_ids and invoice.sale_ids[0].payment_ids and invoice.move_id):
+        if not (invoice.sale_ids and
+                invoice.sale_ids[0].payment_ids and invoice.move_id):
             return False
-        #Check currency
+        # Check currency
+        company_currency_id = invoice.company_id.currency_id.id
         for payment in invoice.sale_ids[0].payment_ids:
-            for move in payment.move_ids:
-                if (move.currency_id.id or invoice.company_id.currency_id.id) != invoice.currency_id.id:
+            for move in payment.line_id:
+                currency_id = move.currency_id.id or company_currency_id
+                if currency_id != invoice.currency_id.id:
                     return False
         return True
 
@@ -63,7 +72,7 @@
         return res
 
     def _prepare_write_off(self, cr, uid, invoice, res_invoice, res_payment, context=None):
-        if not context:
+        if context is None:
             context = {}
         ctx = context.copy()
         if res_invoice['total_amount'] - res_payment['total_amount'] > 0:
@@ -74,7 +83,8 @@
             get_write_off_information('exchange', writeoff_type, context=context)
         max_date = max(res_invoice['max_date'], res_payment['max_date'])
         ctx['p_date'] = max_date
-        period_id = self.pool.get('account.period').find(cr, uid, max_date, context=context)[0]
+        period_obj = self.pool.get('account.period')
+        period_id = period_obj.find(cr, uid, max_date, context=context)[0]
         return {
             'type': 'auto',
             'writeoff_acc_id': account_id,
@@ -83,30 +93,43 @@
             'context': ctx,
         }
 
+    def _reconcile_invoice(self, cr, uid, invoice, context=None):
+        move_line_obj = self.pool.get('account.move.line')
+        currency_obj = self.pool.get('res.currency')
+        is_zero = currency_obj.is_zero
+        company_currency_id = invoice.company_id.currency_id.id
+        currency = invoice.currency_id
+        use_currency = currency.id != company_currency_id
+        if self._can_be_reconciled(cr, uid, invoice, context=context):
+            payment_move_lines = []
+            for payment in invoice.sale_ids[0].payment_ids:
+                payment_move_lines += payment.line_id
+            res_payment = self._get_sum_payment_move_line(
+                cr, uid, payment_move_lines, context=context)
+            res_invoice = self._get_sum_invoice_move_line(
+                cr, uid, invoice.move_id.line_id, context=context)
+            line_ids = res_invoice['line_ids'] + res_payment['line_ids']
+            if not use_currency:
+                balance = abs(res_invoice['total_amount'] -
+                              res_payment['total_amount'])
+                if line_ids and is_zero(cr, uid, currency, balance):
+                    move_line_obj.reconcile(cr, uid, line_ids, context=context)
+            else:
+                balance = abs(res_invoice['total_amount_currency'] -
+                              res_payment['total_amount_currency'])
+                if line_ids and is_zero(cr, uid, currency, balance):
+                    kwargs = self._prepare_write_off(cr, uid,
+                                                     invoice,
+                                                     res_invoice,
+                                                     res_payment,
+                                                     context=context)
+                    move_line_obj.reconcile(cr, uid, line_ids, **kwargs)
+
     def reconcile_invoice(self, cr, uid, ids, context=None):
-        """
-        Simple method to reconcile the invoice with the payment generated on the sale order
-        """
-        if not context:
-            context={}
-        precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
-        obj_move_line = self.pool.get('account.move.line')
+        """ Simple method to reconcile the invoice with the payment
+        generated on the sale order """
+        if not hasattr(ids, '__iter__'):
+            ids = [ids]
         for invoice in self.browse(cr, uid, ids, context=context):
-            use_currency = invoice.currency_id.id != invoice.company_id.currency_id.id
-            if self._can_be_reconciled(cr, uid, invoice, context=context):
-                payment_move_line = []
-                for payment in invoice.sale_ids[0].payment_ids:
-                    payment_move_line += payment.move_ids
-                res_payment = self._get_sum_payment_move_line(cr, uid, payment_move_line, context=context)
-                res_invoice = self._get_sum_invoice_move_line(cr, uid, invoice.move_id.line_id, context=context)
-                line_ids = res_invoice['line_ids'] + res_payment['line_ids']
-                if not use_currency:
-                    balance = abs(res_invoice['total_amount']-res_payment['total_amount'])
-                    if line_ids and not round(balance, precision):
-                        obj_move_line.reconcile(cr, uid, line_ids, context=context)
-                else:
-                    balance = abs(res_invoice['total_amount_currency']-res_payment['total_amount_currency'])
-                    if line_ids and not round(balance, precision):
-                        kwargs = self._prepare_write_off(cr, uid, invoice, res_invoice, res_payment, context=context)
-                        obj_move_line.reconcile(cr, uid, line_ids, **kwargs)
+            self._reconcile_invoice(cr, uid, invoice, context=context)
         return True

=== modified file 'sale_automatic_workflow/payment_method.py'
--- sale_automatic_workflow/payment_method.py	2012-08-21 13:57:44 +0000
+++ sale_automatic_workflow/payment_method.py	2013-05-02 07:30:40 +0000
@@ -26,10 +26,9 @@
 
 class payment_method(Model):
     _inherit = "payment.method"
-    
 
     _columns = {
-        'workflow_process_id': fields.many2one('sale.workflow.process', 'Workflow Process'),
-
+        'workflow_process_id': fields.many2one('sale.workflow.process',
+                                               'Workflow Process'),
     }
 

=== modified file 'sale_automatic_workflow/payment_method_view.xml'
--- sale_automatic_workflow/payment_method_view.xml	2012-04-22 12:49:21 +0000
+++ sale_automatic_workflow/payment_method_view.xml	2013-05-02 07:30:40 +0000
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  sale_quick_payment for OpenERP
+  sale_automatic_workflow for OpenERP
   Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
   The licence is in the file __openerp__.py
 -->
@@ -12,11 +12,9 @@
         <record id="payment_method_view_form" model="ir.ui.view">
             <field name="name">sale_automatic_workflow.payment_method.view_form</field>
             <field name="model">payment.method</field>
-            <field name="inherit_id" ref="sale_quick_payment.payment_method_view_form" />
-            <field eval="16" name="priority"/>
-            <field name="type">form</field>
+            <field name="inherit_id" ref="sale_payment_method.payment_method_view_form" />
             <field name="arch" type="xml">
-                <field name="payment_term_id" position="after">
+                <field name="journal_id" position="after">
                     <field name="workflow_process_id" />
                 </field>
             </field>
@@ -25,9 +23,7 @@
         <record id="payment_method_view_tree" model="ir.ui.view">
             <field name="name">sale_automatic_workflow.payment_method.view_tree</field>
             <field name="model">payment.method</field>
-            <field name="inherit_id" ref="sale_quick_payment.payment_method_view_tree" />
-            <field eval="16" name="priority"/>
-            <field name="type">tree</field>
+            <field name="inherit_id" ref="sale_payment_method.payment_method_view_tree" />
             <field name="arch" type="xml">
                 <field name="payment_term_id" position="after">
                     <field name="workflow_process_id" />

=== modified file 'sale_automatic_workflow/sale.py'
--- sale_automatic_workflow/sale.py	2012-12-26 10:17:28 +0000
+++ sale_automatic_workflow/sale.py	2013-05-02 07:30:40 +0000
@@ -1,8 +1,9 @@
-# -*- encoding: utf-8 -*-
+# -*- coding: utf-8 -*-
 #################################################################################
 #                                                                               #
 #    sale_automatic_workflow for OpenERP                                        #
 #    Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>   #
+#    Copyright 2013 Camptocamp SA (Guewen Baconnier)
 #                                                                               #
 #    This program is free software: you can redistribute it and/or modify       #
 #    it under the terms of the GNU Affero General Public License as             #
@@ -18,24 +19,56 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.      #
 #                                                                               #
 #################################################################################
-from openerp.osv.orm import Model
-from openerp.osv import fields
-
-class sale_order(Model):
+from openerp.osv import orm, fields
+
+
+class sale_order(orm.Model):
     _inherit = "sale.order"
     _columns = {
-        'workflow_process_id':fields.related('payment_method_id', 'workflow_process_id', \
-            type='many2one',relation='sale.workflow.process', string='Workflow Process', readonly=True),
+        'workflow_process_id': fields.many2one('sale.workflow.process',
+                                               string='Workflow Process',
+                                               ondelete='restrict'),
     }
 
     def _prepare_invoice(self, cr, uid, order, lines, context=None):
         invoice_vals = super(sale_order, self)._prepare_invoice(cr, uid, order, lines, context=context)
-        invoice_vals['workflow_process_id'] = order.workflow_process_id.id
-        if order.workflow_process_id.invoice_date_is_order_date:
+        workflow = order.workflow_process_id
+        if not workflow:
+            return invoice_vals
+        invoice_vals['workflow_process_id'] = workflow.id
+        if workflow.invoice_date_is_order_date:
             invoice_vals['date_invoice'] = order.date_order
         return invoice_vals
 
     def _prepare_order_picking(self, cr, uid, order, context=None):
         picking_vals = super(sale_order, self)._prepare_order_picking(cr, uid, order, context=context)
-        picking_vals['workflow_process_id'] = order.workflow_process_id.id
+        if order.workflow_process_id:
+            picking_vals['workflow_process_id'] = order.workflow_process_id.id
         return picking_vals
+
+    def onchange_payment_method_id(self, cr, uid, ids, payment_method_id, context=None):
+        values = super(sale_order, self).onchange_payment_method_id(
+            cr, uid, ids, payment_method_id, context=context)
+        if not payment_method_id:
+            return values
+        method_obj = self.pool.get('payment.method')
+        method = method_obj.browse(cr, uid, payment_method_id, context=context)
+        workflow = method.workflow_process_id
+        if workflow:
+            values.setdefault('value', {})
+            values['value']['workflow_process_id'] = workflow.id
+        return values
+
+    def onchange_workflow_process_id(self, cr, uid, ids, workflow_process_id, context=None):
+        if not workflow_process_id:
+            return {}
+        result = {}
+        workflow_obj = self.pool.get('sale.workflow.process')
+        workflow = workflow_obj.browse(cr, uid, workflow_process_id, context=context)
+        if workflow.picking_policy:
+            result['picking_policy'] = workflow.picking_policy
+        if workflow.order_policy:
+            result['order_policy'] = workflow.order_policy
+        if workflow.invoice_quantity:
+            result['invoice_quantity'] = workflow.invoice_quantity
+        return {'value': result}

=== modified file 'sale_automatic_workflow/sale_view.xml'
--- sale_automatic_workflow/sale_view.xml	2012-05-24 20:44:47 +0000
+++ sale_automatic_workflow/sale_view.xml	2013-05-02 07:30:40 +0000
@@ -1,28 +1,22 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  sale_automic_workflow for OpenERP
+  sale_automatic_workflow for OpenERP
   Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
   The licence is in the file __openerp__.py
 -->
 
 <openerp>
     <data>
-    
-        <!-- INHERITED VIEW FOR THE OBJECT : sale_order -->
 
         <record id="sale_order_view_form" model="ir.ui.view">
             <field name="name">sale_automatic_workflow.sale_order.view_form</field>
             <field name="model">sale.order</field>
-            <field name="inherit_id" ref="sale_quick_payment.sale_order_view_form" />
-            <field eval="16" name="priority"/>
-            <field name="type">form</field>
+            <field name="inherit_id" ref="sale_payment_method.sale_order_view_form" />
             <field name="arch" type="xml">
-                <group name="payment_information" position="after">
-                    <group name="automatic_workflow" colspan="4">
-                        <separator string="Automatic Workflow" colspan="4"/>
-                        <field name="workflow_process_id" />
-                    </group>
-                </group>
+                <field name="payment_method_id" position="after">
+                    <field name="workflow_process_id" string="Automatic Workflow"
+                        on_change="onchange_workflow_process_id(workflow_process_id)" />
+                </field>
             </field>
         </record>
 

=== modified file 'sale_automatic_workflow/sale_workflow_process.py'
--- sale_automatic_workflow/sale_workflow_process.py	2012-08-21 13:57:44 +0000
+++ sale_automatic_workflow/sale_workflow_process.py	2013-05-02 07:30:40 +0000
@@ -19,40 +19,43 @@
 #                                                                               #
 #################################################################################
 
-from openerp.osv.orm import Model
-from openerp.osv import fields
-import netsvc
-
-
-class sale_workflow_process(Model):
+from openerp.osv import orm, fields
+
+
+class sale_workflow_process(orm.Model):
     _name = "sale.workflow.process"
     _description = "sale workflow process"
 
     _columns = {
         'name': fields.char('Name', size=64),
-        'picking_policy': fields.selection([('direct', 'Partial Delivery'), ('one', 'Complete Delivery')], 'Packing Policy'),
+        'picking_policy': fields.selection([('direct', 'Deliver each product when available'),
+                                            ('one', 'Deliver all products at once')],
+                                           string='Shipping Policy'),
         'order_policy': fields.selection([
-            ('prepaid', 'Payment Before Delivery'),
-            ('manual', 'Shipping & Manual Invoice'),
-            ('postpaid', 'Invoice on Order After Delivery'),
-            ('picking', 'Invoice from the Packing'),
-        ], 'Shipping Policy'),
-        'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on'),
-        'validate_order': fields.selection([('always', 'Always'), ('if_paid', 'Only If Paid'), ('never', 'Never')], 'Validate Order'),
+            ('prepaid', 'Before Delivery'),
+            ('manual', 'On Demand'),
+            # https://bugs.launchpad.net/openobject-addons/+bug/1160835
+            # ('postpaid', 'Invoice on Order After Delivery'),
+            ('picking', 'On Delivery Order'),
+        ], 'Invoice Policy'),
+        'invoice_quantity': fields.selection([('order', 'Ordered Quantities'),
+                                              ('procurement', 'Shipped Quantities')],
+                                             string='Invoice on'),
+        'validate_order': fields.boolean('Validate Order'),
         'create_invoice': fields.boolean('Create Invoice'),
         'validate_invoice': fields.boolean('Validate Invoice'),
-        'validate_picking': fields.boolean('Validate Picking'),
-        'validate_manufactoring_order': fields.boolean('Validate Manufactoring Order'),
-        'days_before_order_cancel': fields.integer('Days Delay before Cancel', help='number of days before an unpaid order will be cancelled at next status update from Magento'),
-        'invoice_date_is_order_date' : fields.boolean('Force Invoice Date', help="If it's check the invoice date will be the same as the order date"),
+        'validate_picking': fields.boolean('Confirm and Close Picking'),
+        # TODO not implemented actually
+        # 'validate_manufactoring_order': fields.boolean('Validate Manufactoring Order'),
+        'invoice_date_is_order_date': fields.boolean(
+            'Force Invoice Date',
+            help="When checked, the invoice date will be "
+                 "the same than the order's date"),
     }
 
     _defaults = {
-        'picking_policy': lambda *a: 'direct',
-        'order_policy': lambda *a: 'manual',
-        'invoice_quantity': lambda *a: 'order',
-        'validate_invoice': lambda *a: False,
-        'days_before_order_cancel': lambda *a: 30,
+        'picking_policy': 'direct',
+        'order_policy': 'manual',
+        'invoice_quantity': 'order',
+        'validate_invoice': False,
     }
-
-

=== modified file 'sale_automatic_workflow/sale_workflow_process_view.xml'
--- sale_automatic_workflow/sale_workflow_process_view.xml	2012-10-19 08:57:19 +0000
+++ sale_automatic_workflow/sale_workflow_process_view.xml	2013-05-02 07:30:40 +0000
@@ -12,23 +12,20 @@
         <record id="sale_workflow_process_view_form" model="ir.ui.view">
             <field name="name">sale_automic_workflow.sale_workflow_process.view_form</field>
             <field name="model">sale.workflow.process</field>
-            <field eval="16" name="priority"/>
-            <field name="type">form</field>
             <field name="arch" type="xml">
-                <form string="sale_workflow_process">
+                <form string="Automatic Workflow">
                     <field name="name"/>
                     <separator string="Order Configuration" colspan="4" />
                     <field name="picking_policy"/>
                     <field name="order_policy"/>
                     <field name="invoice_quantity"/>
-                    <separator string="Worflow Option" colspan="4" />
+                    <separator string="Workflow Options" colspan="4" />
                     <field name="validate_order"/>
                     <field name="validate_picking"/>
-                    <field name="validate_manufactoring_order"/>
+                    <!-- <field name="validate_manufactoring_order"/> -->
                     <field name="create_invoice" />
                     <field name="validate_invoice"/>
                     <field name="invoice_date_is_order_date"/>
-                    <field name="days_before_order_cancel"/>
 
                 </form>
             </field>
@@ -37,27 +34,24 @@
         <record id="sale_workflow_process_view_tree" model="ir.ui.view">
             <field name="name">sale_automic_workflow.sale_workflow_process.view_tree</field>
             <field name="model">sale.workflow.process</field>
-            <field eval="16" name="priority"/>
-            <field name="type">tree</field>
             <field name="arch" type="xml">
-                <tree string="sale_workflow_process">
+                <tree string="Automatic Workflow">
                     <field name="name"/>
                     <field name="picking_policy"/>
                     <field name="order_policy"/>
                     <field name="invoice_quantity"/>
                     <field name="validate_order"/>
                     <field name="validate_picking"/>
-                    <field name="validate_manufactoring_order"/>
+                    <!-- <field name="validate_manufactoring_order"/> -->
                     <field name="create_invoice" />
                     <field name="validate_invoice"/>
                     <field name="invoice_date_is_order_date"/>
-                    <field name="days_before_order_cancel"/>
                 </tree>
             </field>
         </record>
 
         <record id="act_sale_workflow_process_form" model="ir.actions.act_window">
-            <field name="name">Sale Workflow Method</field>
+            <field name="name">Automatic Workflow</field>
             <field name="res_model">sale.workflow.process</field>
             <field name="view_type">form</field>
             <field name="view_mode">tree,form</field>
@@ -66,19 +60,4 @@
         <menuitem action="act_sale_workflow_process_form" id="menu_act_sale_workflow_process_form" parent="base.menu_sale_config_sales" sequence="20"/>
 
     </data>
-    <data noupdate="1">
-
-        <record forcecreate="True" id="ir_cron_automatic_workflow_job" model="ir.cron">
-            <field name="name">Automatic Workflow Job</field>
-            <field eval="True" name="active"/>
-            <field name="user_id" ref="base.user_root"/>
-            <field name="interval_number">1</field>
-            <field name="interval_type">minutes</field>
-            <field name="numbercall">-1</field>
-            <field eval="False" name="doall"/>
-            <field eval="'automatic.workflow.job'" name="model"/>
-            <field eval="'run'" name="function"/>
-            <field eval="'()'" name="args"/>
-        </record>
-    </data>
 </openerp>

=== modified file 'sale_automatic_workflow/stock.py'
--- sale_automatic_workflow/stock.py	2012-12-26 13:22:11 +0000
+++ sale_automatic_workflow/stock.py	2013-05-02 07:30:40 +0000
@@ -19,23 +19,30 @@
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ###############################################################################
-from openerp.osv.orm import Model
-from openerp.osv import fields
-
-class stock_picking_out(Model):
-    _inherit = "stock.picking.out"
+from openerp.osv import orm, fields
+
+
+class stock_picking(orm.Model):
+    _inherit = "stock.picking"
+
     _columns = {
-        'workflow_process_id':fields.many2one('sale.workflow.process', 'Sale Workflow Process'),
+        # if we add the column in stock.picking.out, we can't write it
+        'workflow_process_id': fields.many2one('sale.workflow.process',
+                                               'Sale Workflow Process'),
     }
 
     def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
-        invoice_vals = super(stock_picking_out, self)._prepare_invoice(cr, uid, picking, partner, \
-                                                            inv_type, journal_id, context=context)
+        invoice_vals = super(stock_picking, self)._prepare_invoice(
+            cr, uid, picking, partner, inv_type, journal_id, context=context)
         invoice_vals['workflow_process_id'] = picking.workflow_process_id.id
         if picking.workflow_process_id.invoice_date_is_order_date:
             invoice_vals['date_invoice'] = picking.sale_id.date_order
         return invoice_vals
 
+
+class stock_picking_out(orm.Model):
+    _inherit = "stock.picking.out"
+
     def validate_picking(self, cr, uid, ids, context=None):
         for picking in self.browse(cr, uid, ids, context=context):
             self.force_assign(cr, uid, [picking.id])
@@ -62,4 +69,3 @@
 #            mrp_product_produce_obj.do_produce(cr, uid, [produce], context)
 #            self.validate_manufactoring_order(cr, uid, production.name, context)
 #        return True
-#        


References