← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~camptocamp/openerp-humanitarian-ngo/ngo-addons-add_other_procurement_method-nbi into lp:openerp-humanitarian-ngo

 

Nicolas Bessi - Camptocamp has proposed merging lp:~camptocamp/openerp-humanitarian-ngo/ngo-addons-add_other_procurement_method-nbi into lp:openerp-humanitarian-ngo.

Commit message:
[ADD] support of "other" sourcing method.
Allows to create a call for bid or an agreement purchase order from many source lines including service source lines.

[Add] multi-currency:

Allows to have a currency (pricelist) defined in on logisitc request and have sourcing process (call for bid or agreement PO) in an other currency.

[IMP] separate budget in an external module

Requested reviews:
  OpenERP for Humanitarian Core Editors (humanitarian-core-editors)

For more details, see:
https://code.launchpad.net/~camptocamp/openerp-humanitarian-ngo/ngo-addons-add_other_procurement_method-nbi/+merge/205155

[ADD] support of "other" sourcing method.
Allows to create a call for bid or an agreement purchase order from many source lines including service source lines.

[Add] multi-currency:

Allows to have a currency (pricelist) defined in on logisitc request and have sourcing process (call for bid or agreement PO) in an other currency.

[IMP] separate budget in an external module

Depends on https://code.launchpad.net/~camptocamp/openerp-humanitarian-ngo/ngo-addons-add_agreement_sourcing-nbi/+merge/196676
-- 
https://code.launchpad.net/~camptocamp/openerp-humanitarian-ngo/ngo-addons-add_other_procurement_method-nbi/+merge/205155
Your team OpenERP for Humanitarian Core Editors is requested to review the proposed merge of lp:~camptocamp/openerp-humanitarian-ngo/ngo-addons-add_other_procurement_method-nbi into lp:openerp-humanitarian-ngo.
=== added directory 'framework_agreement_requisition'
=== added file 'framework_agreement_requisition/__init__.py'
--- framework_agreement_requisition/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import model

=== added file 'framework_agreement_requisition/__openerp__.py'
--- framework_agreement_requisition/__openerp__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/__openerp__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{'name': 'Framework Agreement Negociation',
+ 'version': '0.1',
+ 'author': 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'NGO',
+ 'complexity': 'normal',
+ 'depends': ['purchase_requisition',
+             'purchase_requisition_extended',
+             'framework_agreement'],
+ 'description': """
+Negociate framework agreement using tender process
+==================================================
+
+This will allows you to use "The calls for Bids" model
+ to negociate agreement.
+
+To to so you have too check the box "Negociate Agreement".
+
+The module add a state "Agreement selected" on tender and PO.
+
+
+These will be the final state once you have choosen
+the agreement that fit your needs the best.
+
+Once the selection is done juste use the button "Agreement selected" on tender
+That will close flow of tender and related PO accordingly.
+
+""",
+ 'website': 'http://www.camptocamp.com',
+ 'data': ['requisition_workflow.xml',
+          'purchase_workflow.xml',
+          'view/purchase_requisition_view.xml'],
+ 'demo': [],
+ 'test': ['test/agreement_requisition.yml'],
+ 'installable': True,
+ 'auto_install': False,
+ 'license': 'AGPL-3',
+ 'application': False,
+ }

=== added directory 'framework_agreement_requisition/model'
=== added file 'framework_agreement_requisition/model/__init__.py'
--- framework_agreement_requisition/model/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/model/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import purchase_requisition
+from . import purchase

=== added file 'framework_agreement_requisition/model/purchase.py'
--- framework_agreement_requisition/model/purchase.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/model/purchase.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp import netsvc
+from openerp.osv import orm
+
+SELECTED_STATE = ('agreement_selected', 'Agreement selected')
+AGR_SELECT = 'agreement_selected'
+
+
+class purchase_order(orm.Model):
+    """Add workflow behavior"""
+
+    _inherit = "purchase.order"
+
+    def __init__(self, pool, cr):
+        """Add a new state value using PO class property"""
+        if SELECTED_STATE not in super(purchase_order, self).STATE_SELECTION:
+            super(purchase_order, self).STATE_SELECTION.append(SELECTED_STATE)
+        return super(purchase_order, self).__init__(pool, cr)
+
+    def select_agreement(self, cr, uid, agr_id, context=None):
+        """Pass PO in state 'Agreement selected'"""
+        if isinstance(agr_id, (list, tuple)):
+            assert len(agr_id) == 1
+            agr_id = agr_id[0]
+            wf_service = netsvc.LocalService("workflow")
+        return wf_service.trg_validate(uid, 'purchase.order',
+                                       agr_id, 'select_agreement', cr)
+
+    def po_tender_agreement_selected(self, cr, uid, ids, context=None):
+        """Workflow function that write state 'Agreement selected'"""
+        return self.write(cr, uid, ids, {'state': AGR_SELECT},
+                          context=context)
+
+
+class purchase_order_line(orm.Model):
+    """Add make_agreement function"""
+
+    _inherit = "purchase.order.line"
+
+    # Did you know a good way to supress SQL constraint to add
+    # Python constraint...
+    _sql_constraints = [
+        ('quantity_bid', 'CHECK(true)',
+         'Selected quantity must be less or equal than the quantity in the bid'),
+    ]
+
+    def _check_quantity_bid(self, cr, uid, ids, context=None):
+        for line in self.browse(cr, uid, ids, context=context):
+            if line.order_id.framework_agreement_id:
+                continue
+            if line.product_id.type == 'product' and  not line.quantity_bid <= line.product_qty:
+                return False
+        return True
+
+    _constraints = [
+        (_check_quantity_bid,
+         'Selected quantity must be less or equal than the quantity in the bid',
+         [])
+    ]
+    def _agreement_data(self, cr, uid, po_line, origin, context=None):
+        """Get agreement values from PO line
+
+        :param po_line: Po line records
+
+        :returns: agreement dict to be used by orm.Model.create
+        """
+        vals = {}
+        vals['supplier_id'] = po_line.order_id.partner_id.id
+        vals['product_id'] = po_line.product_id.id
+        vals['quantity'] = po_line.product_qty
+        vals['delay'] = po_line.product_lead_time
+        vals['origin'] = origin if origin else False
+        return vals
+
+    def make_agreement(self, cr, uid, line_id, origin, context=None):
+        """ generate a draft framework agreement
+
+        :returns: a record of LTA
+
+        """
+        agr_model = self.pool['framework.agreement']
+        if isinstance(line_id, (list, tuple)):
+            assert len(line_id) == 1
+            line_id = line_id[0]
+        current = self.browse(cr, uid, line_id, context=context)
+        vals = self._agreement_data(cr, uid, current, origin, context=context)
+        agr_id = agr_model.create(cr, uid, vals, context=context)
+        return agr_model.browse(cr, uid, agr_id, context=context)

=== added file 'framework_agreement_requisition/model/purchase_requisition.py'
--- framework_agreement_requisition/model/purchase_requisition.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/model/purchase_requisition.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from itertools import chain
+from openerp import netsvc
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+from .purchase import AGR_SELECT as PO_AGR_SELECT
+
+SELECTED_STATE = ('agreement_selected', 'Agreement selected')
+AGR_SELECT = 'agreement_selected'
+
+
+class purchase_requisition(orm.Model):
+    """Add support to negociate LTA using tender process"""
+
+    def __init__(self, pool, cr):
+        """Nasty hack to add fields to select fields
+
+        We do this in order not to compromising other state added
+        by other addons that are not in inheritance chain...
+
+        """
+        sel = super(purchase_requisition, self)._columns['state']
+        if SELECTED_STATE not in sel.selection:
+            sel.selection.append(SELECTED_STATE)
+        return super(purchase_requisition, self).__init__(pool, cr)
+
+    _inherit = "purchase.requisition"
+    _columns = {
+        'framework_agreement_tender': fields.boolean('Negociate Agreement'),
+    }
+
+    def tender_agreement_selected(self, cr, uid, ids, context=None):
+        """Workflow function that write state 'Agreement selected'"""
+        return self.write(cr, uid, ids, {'state': AGR_SELECT},
+                          context=context)
+
+    def select_agreement(self, cr, uid, agr_id, context=None):
+        """Pass tender to state 'Agreement selected'"""
+        if isinstance(agr_id, (list, tuple)):
+            assert len(agr_id) == 1
+            agr_id = agr_id[0]
+        wf_service = netsvc.LocalService("workflow")
+        return wf_service.trg_validate(uid, 'purchase.requisition',
+                                       agr_id, 'select_agreement', cr)
+
+    def _agreement_selected(self, cr, uid, ids, context=None):
+        """Tells tender that an agreement has been selected"""
+        if isinstance(ids, (int, long)):
+            ids = [ids]
+        generated = []
+        for req in self.browse(cr, uid, ids, context=context):
+            if not req.framework_agreement_tender:
+                raise orm.except_orm(_('Invalid tender'),
+                                     _('Request is not of type agreement'))
+            self.select_agreement(cr, uid, req.id, context=context)
+            req.refresh()
+            if req.state != AGR_SELECT:
+                raise RuntimeError('requisiton %s does not pass to state'
+                                   ' agreement_selected' %
+                                   req.name)
+            rfqs = chain.from_iterable(req_line.purchase_line_ids
+                                       for req_line in req.line_ids)
+            po_to_select = []
+            po_to_cancel = []
+            for rfq in rfqs:
+                if rfq.state == 'confirmed':
+                    agr_record = rfq.make_agreement(req.name)
+                    generated.append(agr_record)
+                    po_to_select.append(rfq.order_id)
+                else:
+                    po_to_cancel.append(rfq.order_id)
+
+            if not po_to_select:
+                raise orm.except_orm(_('No confirmed RFQ related to tender'),
+                                     _('Please choose at least one'))
+
+            for p_order in set(po_to_select):
+                p_order.select_agreement()
+                p_order.refresh()
+                if p_order.state != PO_AGR_SELECT:
+                    raise RuntimeError('Purchase order %s does not pass to %s' %
+                                       (p_order.name, PO_AGR_SELECT))
+            wf_service = netsvc.LocalService("workflow")
+            for p_order in set(po_to_cancel):
+                wf_service.trg_validate(uid, 'purchase.order', p_order.id,
+                                        'purchase_cancel', cr)
+        return generated
+
+    def agreement_selected(self, cr, uid, ids, context=None):
+        agrements = self._agreement_selected(cr, uid, ids, context=context)
+        a_ids = [x.id for x in agrements]
+        return {
+            'name': _('Generated Agreements'),
+            'view_mode': 'tree,form',
+            'res_model': 'framework.agreement',
+            'domain': [('id', 'in', a_ids)],
+            'target': 'current',
+            'view_id': False,
+            'context': {},
+            'type': 'ir.actions.act_window',
+        }

=== added file 'framework_agreement_requisition/purchase_workflow.xml'
--- framework_agreement_requisition/purchase_workflow.xml	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/purchase_workflow.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data>
+    <record id="act_po_agreement_selected" model="workflow.activity">
+      <field name="wkf_id" ref="purchase.purchase_order"/>
+      <field name="name">Agreement selected</field>
+      <field name="kind">function</field>
+      <field name="action">po_tender_agreement_selected()</field>
+      <field name="flow_stop">True</field>
+    </record>
+    <record id="trans_po_agreement_selected" model="workflow.transition">
+      <field name="act_from" ref="purchase.act_bid"/>
+      <field name="act_to" ref="act_po_agreement_selected"/>
+      <field name="signal">select_agreement</field>
+    </record>
+  </data>
+</openerp>

=== added file 'framework_agreement_requisition/requisition_workflow.xml'
--- framework_agreement_requisition/requisition_workflow.xml	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/requisition_workflow.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data>
+    <record id="act_agreement_selected" model="workflow.activity">
+      <field name="wkf_id" ref="purchase_requisition.purchase_requisition_workflow"/>
+      <field name="name">Agreement selected</field>
+      <field name="kind">function</field>
+      <field name="action">tender_agreement_selected()</field>
+      <field name="flow_stop">True</field>
+    </record>
+
+    <record id="trans_agreement_selected" model="workflow.transition">
+      <field name="act_from" ref="purchase_requisition_extended.act_closed"/>
+      <field name="act_to" ref="act_agreement_selected"/>
+      <field name="signal">select_agreement</field>
+    </record>
+  </data>
+</openerp>

=== added directory 'framework_agreement_requisition/test'
=== added file 'framework_agreement_requisition/test/agreement_requisition.yml'
--- framework_agreement_requisition/test/agreement_requisition.yml	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/test/agreement_requisition.yml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,98 @@
+-
+  Standard flow of a Call for agreement Bids in mode open
+-
+  Create Call for Bids
+-
+  !record {model: purchase.requisition, id: purchase_requisition_agreement}:
+    date_start: '2013-08-02 00:00:00'
+    date_end: '2013-08-30 00:00:00'
+    bid_tendering_mode: 'open'
+    schedule_date: '2013-09-30'
+    req_validity: '2013-09-10'
+    framework_agreement_tender: True
+    line_ids:
+      - product_id: product.product_product_15
+        product_qty: 2500.0
+-
+  Confirm Call
+-
+  !python {model: purchase.requisition}: |
+    import netsvc
+    wf_service = netsvc.LocalService("workflow")
+    wf_service.trg_validate(uid, 'purchase.requisition', ref("purchase_requisition_agreement"), 'sent_suppliers', cr)
+-
+  Create RFQ1. I run the 'Request a quotation' wizard. I fill the supplier.
+-
+  !record {model: purchase.requisition.partner, id: purchase_requisition_agreement_partner1_create}:
+    partner_id: base.res_partner_2
+-
+  Create RFQ1. I confirm the wizard.
+-
+  !python {model: purchase.requisition.partner}: |
+    self.create_order(cr, uid, [ref("purchase_requisition_agreement_partner1_create")],{
+        'active_model': 'purchase.requisition',
+        'active_id': ref("purchase_requisition_agreement"),
+        'active_ids': [ref("purchase_requisition_agreement")],
+        })
+-
+  I encode the bid. I set a 300 price on the line.
+-
+  !python {model: purchase.requisition}: |
+    purchase_req = self.browse(cr, uid, ref("purchase_requisition_agreement"))
+    assert len(purchase_req.purchase_ids) == 1, "There must be 1 RFQs linked to this Call for bids"
+    price = 300
+    for rfq in purchase_req.purchase_ids:
+        for line in rfq.order_line:
+            self.pool.get('purchase.order.line').write(cr, uid, [line.id], {'price_unit': price})
+
+-
+  I send the RFQ. For this, I print the RFQ.
+-
+  !python {model: purchase.requisition}: |
+    purchase_req = self.browse(cr, uid, ref("purchase_requisition_agreement"))
+    for rfq in purchase_req.purchase_ids:
+        self.pool.get('purchase.order').print_quotation(cr, uid, [rfq.id])
+-
+  I run the 'Bid encoded' wizard of bid1. I fill the date.
+-
+  !record {model: purchase.action_modal_datetime, id: purchase_requisition_agreement_bid1_bidencoded}:
+    datetime: '2013-08-13 00:00:00'
+-
+ I launch wizard action.
+-
+  !python {model: purchase.action_modal_datetime}: |
+    purchase_req = self.pool['purchase.requisition'].browse(cr, uid, ref("purchase_requisition_agreement"))
+    po_id = purchase_req.purchase_ids[0].id
+    self.action(cr, uid, [ref('purchase_requisition_agreement_bid1_bidencoded')],
+                {'action': 'bid_received_ok',
+                'active_id': po_id,
+                'active_ids': [po_id],
+                'active_model': 'purchase.order',
+                'default_datetime': '2013-08-13 00:00:00',
+                'uid': 1})
+-
+  I close the Call for bids and move to bids selection
+-
+  !python {model: purchase.requisition}: |
+    import netsvc
+    wf_service = netsvc.LocalService("workflow")
+    wf_service.trg_validate(uid, 'purchase.requisition', ref("purchase_requisition_agreement"), 'open_bid', cr)
+
+-
+  In the bids selection, I confirm line 1 of bid 1
+-
+  !python {model: purchase.requisition}: |
+    purchase_req = self.browse(cr, uid, ref("purchase_requisition_agreement"))
+    self.pool.get('purchase.order.line').action_confirm(cr, uid, [purchase_req.purchase_ids[0].order_line[0].id])
+-
+  I close the call for bids
+-
+  !python {model: purchase.requisition}: |
+    self.close_callforbids(cr, uid, [ref("purchase_requisition_agreement")])
+-
+  I mark the tender as agreement selected
+-
+  !python {model: purchase.requisition}: |
+    self.agreement_selected(cr, uid, ref("purchase_requisition_agreement"))
+    purchase_req = self.browse(cr, uid, ref("purchase_requisition_agreement"))
+    assert purchase_req.state == 'agreement_selected'

=== added directory 'framework_agreement_requisition/view'
=== added file 'framework_agreement_requisition/view/purchase_requisition_view.xml'
--- framework_agreement_requisition/view/purchase_requisition_view.xml	1970-01-01 00:00:00 +0000
+++ framework_agreement_requisition/view/purchase_requisition_view.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data noupdate="0">
+    <record model="ir.ui.view" id="view_purchase_requisition_form_agreement">
+      <field name="name">purchase.requisition.form.inherit.aggrement.button</field>
+      <field name="model">purchase.requisition</field>
+      <field name="inherit_id" ref="purchase_requisition.view_purchase_requisition_form"/>
+      <field name="arch" type="xml">
+        <field name="multiple_rfq_per_supplier"
+               position="after">
+          <field name="framework_agreement_tender"/>
+        </field>
+        <button name="cancel_requisition" position="after">
+          <button name="agreement_selected"
+                  type="object"
+                  class="po_buttons oe_form_buttons"
+                  attrs="{'invisible': ['|', ('framework_agreement_tender', '=', False), ('state', '!=', 'closed')]}"
+                  string="Framework agreement selected"/>
+        </button>
+      </field>
+    </record>
+
+    <record model="ir.ui.view" id="view_purchase_requisition_filter">
+      <field name="name">purchase.requisition.form.inherit.agreement.filter</field>
+      <field name="model">purchase.requisition</field>
+      <field name="inherit_id" ref="purchase_requisition.view_purchase_requisition_filter"/>
+      <field name="arch" type="xml">
+        <filter name="draft"
+                position="after">
+                  <filter icon="terp-document-new"
+                          name="framework_agreement"
+                          string="Framework Agreement?"
+                          domain="[(framework_agreement_tender,'=',True)]"/>
+        </filter>
+      </field>
+    </record>
+
+  </data>
+</openerp>

=== added directory 'framework_agreement_sourcing'
=== added file 'framework_agreement_sourcing/__init__.py'
--- framework_agreement_sourcing/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import model
+from . import wizard

=== added file 'framework_agreement_sourcing/__openerp__.py'
--- framework_agreement_sourcing/__openerp__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/__openerp__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{'name': 'Framework agreement integration in sourcing',
+ 'version': '0.1',
+ 'author': 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'NGO',
+ 'complexity': 'normal',
+ 'depends': ['framework_agreement', 'logistic_requisition'],
+ 'description': """
+Automatically source logistic order from framework agreement
+============================================================
+
+If you have a framework agreement negociated for the current product in
+your logistic requisition. If the date and state of agreement are OK,
+agreement will be used as source for the concerned source lines
+of your request.
+
+In this case tender flow is byassed and confirmed PO will be generated
+when logistic requisition is confirmed.
+
+When confirming Logistic request sourcing lines are generating.
+Generation process will look up all agreements with remaining quantity
+and use them one after the other.
+
+We will first choose cheapest agreements with price in negociated currency even
+if they are cheaper in other currences.
+
+Then we will choose remaining agreements ordered
+by price converted in company currency.
+
+You can prevent this behavior by forcing only one agreement per product at
+the same time in company.
+
+""",
+ 'website': 'http://www.camptocamp.com',
+ 'data': [
+    'view/requisition_view.xml',
+    'wizard/logistic_requisition_source_create_po_view.xml',
+    'security/ir.model.access.csv'
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'auto_install': False,
+ 'license': 'AGPL-3',
+ 'application': False,
+ }

=== added directory 'framework_agreement_sourcing/i18n'
=== added file 'framework_agreement_sourcing/i18n/en_US.po'
--- framework_agreement_sourcing/i18n/en_US.po	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/i18n/en_US.po	2014-03-10 15:39:56 +0000
@@ -0,0 +1,220 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* framework_agreement_sourcing
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-02-04 10:39+0000\n"
+"PO-Revision-Date: 2014-02-04 10:39+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: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:72
+#, python-format
+msgid "Please cancel uneeded one"
+msgstr "Please cancel uneeded one"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py:64
+#, python-format
+msgid "Please add one"
+msgstr "Please add one"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:240
+#, python-format
+msgid "Source line must be of type other or agreement"
+msgstr "Source line must be of type other or agreement"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py:63
+#, python-format
+msgid "No stockable product in related PO"
+msgstr "No stockable product in related PO"
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_source_create_agr_po
+msgid "logistic.requisition.source.create.agr.po"
+msgstr "logistic.requisition.source.create.agr.po"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Which pricelist / currency you want ?"
+msgstr "Which pricelist / currency you want ?"
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_line
+msgid "Logistic Requisition Line"
+msgstr "Logistic Requisition Line"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "{'invisible': [('procurement_method', '=', 'fw_agreement')]}"
+msgstr "{'invisible': [('procurement_method', '=', 'fw_agreement')]}"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "onchange_sourcing_method(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)"
+msgstr "onchange_sourcing_method(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)"
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_cost_estimate
+msgid "Create cost estimate of logistic requisition lines"
+msgstr "Create cost estimate of logistic requisition lines"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:71
+#, python-format
+msgid "Many Purchase order lines found for %s"
+msgstr "Many Purchase order lines found for %s"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:241
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:246
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:249
+#, python-format
+msgid "Please correct selection"
+msgstr "Please correct selection"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:248
+#, python-format
+msgid "There should be at least one agreement line"
+msgstr "There should be at least one agreement line"
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source,framework_agreement_id:0
+msgid "Agreement"
+msgstr "Agreement"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:245
+#, python-format
+msgid "There should be only one agreement line"
+msgstr "There should be only one agreement line"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py:85
+#, python-format
+msgid "User Error"
+msgstr "User Error"
+
+#. module: framework_agreement_sourcing
+#: model:ir.actions.act_window,name:framework_agreement_sourcing.action_view_create_agr_po_from_source
+msgid "Create Agreement Purchase Order"
+msgstr "Create Agreement Purchase Order"
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source.create.agr.po,pricelist_id:0
+msgid "Pricelist / Currency"
+msgstr "Pricelist / Currency"
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source.create.agr.po,framework_currency_ids:0
+msgid "Available Currency"
+msgstr "Available Currency"
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source,supplier_id:0
+msgid "Agreement Supplier"
+msgstr "Agreement Supplier"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "                            Please note that: \n"
+" \n"
+"                            Requisition will only be created if: \n"
+"                            * Lines belong to the same company \n"
+"                            * There is only one agreement line in selection \n"
+"                            * Products are define on all selected lines \n"
+"                            * Non agreement line are of type other \n"
+"                            \n"
+" \n"
+"                            "
+msgstr "                            Please note that: \n"
+" \n"
+"                            Requisition will only be created if: \n"
+"                            * Lines belong to the same company \n"
+"                            * There is only one agreement line in selection \n"
+"                            * Products are define on all selected lines \n"
+"                            * Non agreement line are of type other \n"
+"                            \n"
+" \n"
+"                            "
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_purchase_order
+msgid "Purchase Order"
+msgstr "Purchase Order"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:327
+#, python-format
+msgid "You have ask for a quantity of %s \n"
+" but there is only %s available for current agreement"
+msgstr "You have ask for a quantity of %s \n"
+" but there is only %s available for current agreement"
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_source
+msgid "Logistic Requisition Source"
+msgstr "Logistic Requisition Source"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "You can only chose a pricelist with a currency that is included             in the framewrok agreement you have chosen."
+msgstr "You can only chose a pricelist with a currency that is included             in the framewrok agreement you have chosen."
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "onchange_quantity(procurement_method, requisition_line_id, proposed_qty, proposed_product_id)"
+msgstr "onchange_quantity(procurement_method, requisition_line_id, proposed_qty, proposed_product_id)"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Create Purchase Order"
+msgstr "Create Purchase Order"
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py:85
+#, python-format
+msgid "You must chose a pricelist that is in the same currency than one of the available in the framework agreement."
+msgstr "You must chose a pricelist that is in the same currency than one of the available in the framework agreement."
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source,framework_agreement_po_id:0
+msgid "Agreement Purchase"
+msgstr "Agreement Purchase"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Cancel"
+msgstr "Cancel"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "onchange_product_id(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)"
+msgstr "onchange_product_id(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Are you sure you want to create a Purchase Order from those lines ?"
+msgstr "Are you sure you want to create a Purchase Order from those lines ?"
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "or"
+msgstr "or"
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Sales Order Line"
+

=== added file 'framework_agreement_sourcing/i18n/framework_agreement_sourcing.pot'
--- framework_agreement_sourcing/i18n/framework_agreement_sourcing.pot	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/i18n/framework_agreement_sourcing.pot	2014-03-10 15:39:56 +0000
@@ -0,0 +1,209 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#       * framework_agreement_sourcing
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-02-04 10:37+0000\n"
+"PO-Revision-Date: 2014-02-04 10:37+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: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:72
+#, python-format
+msgid "Please cancel uneeded one"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py:64
+#, python-format
+msgid "Please add one"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:240
+#, python-format
+msgid "Source line must be of type other or agreement"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py:63
+#, python-format
+msgid "No stockable product in related PO"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_source_create_agr_po
+msgid "logistic.requisition.source.create.agr.po"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Which pricelist / currency you want ?"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_line
+msgid "Logistic Requisition Line"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "{'invisible': [('procurement_method', '=', 'fw_agreement')]}"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "onchange_sourcing_method(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_cost_estimate
+msgid "Create cost estimate of logistic requisition lines"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:71
+#, python-format
+msgid "Many Purchase order lines found for %s"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:241
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:246
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:249
+#, python-format
+msgid "Please correct selection"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:248
+#, python-format
+msgid "There should be at least one agreement line"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source,framework_agreement_id:0
+msgid "Agreement"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:245
+#, python-format
+msgid "There should be only one agreement line"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py:85
+#, python-format
+msgid "User Error"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.actions.act_window,name:framework_agreement_sourcing.action_view_create_agr_po_from_source
+msgid "Create Agreement Purchase Order"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source.create.agr.po,pricelist_id:0
+msgid "Pricelist / Currency"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source.create.agr.po,framework_currency_ids:0
+msgid "Available Currency"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source,supplier_id:0
+msgid "Agreement Supplier"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "                            Please note that: \n"
+" \n"
+"                            Requisition will only be created if: \n"
+"                            * Lines belong to the same company \n"
+"                            * There is only one agreement line in selection \n"
+"                            * Products are define on all selected lines \n"
+"                            * Non agreement line are of type other \n"
+"                            \n"
+" \n"
+"                            "
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/model/logistic_requisition_source.py:327
+#, python-format
+msgid "You have ask for a quantity of %s \n"
+" but there is only %s available for current agreement"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_logistic_requisition_source
+msgid "Logistic Requisition Source"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "You can only chose a pricelist with a currency that is included             in the framewrok agreement you have chosen."
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "onchange_quantity(procurement_method, requisition_line_id, proposed_qty, proposed_product_id)"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Create Purchase Order"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: code:addons/framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py:85
+#, python-format
+msgid "You must chose a pricelist that is in the same currency than one of the available in the framework agreement."
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: field:logistic.requisition.source,framework_agreement_po_id:0
+msgid "Agreement Purchase"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Cancel"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source:0
+msgid "onchange_product_id(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "Are you sure you want to create a Purchase Order from those lines ?"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: view:logistic.requisition.source.create.agr.po:0
+msgid "or"
+msgstr ""
+
+#. module: framework_agreement_sourcing
+#: model:ir.model,name:framework_agreement_sourcing.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "" 

=== added directory 'framework_agreement_sourcing/model'
=== added file 'framework_agreement_sourcing/model/__init__.py'
--- framework_agreement_sourcing/model/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/model/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import logistic_requisition
+from . import logistic_requisition_source
+from . import purchase
+from . import sale_order
+from . import logistic_requisition_cost_estimate

=== added file 'framework_agreement_sourcing/model/logistic_requisition.py'
--- framework_agreement_sourcing/model/logistic_requisition.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/model/logistic_requisition.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,243 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from collections import namedtuple
+from openerp.tools.translate import _
+from openerp.osv import orm
+from .logistic_requisition_source import AGR_PROC
+
+
+class logistic_requisition_line(orm.Model):
+    """Override to enable generation of source line"""
+
+    _inherit = "logistic.requisition.line"
+
+    def _prepare_line_source(self, cr, uid, line,
+                                      qty=None, agreement=None,
+                                      context=None):
+        """Prepare data dict for source line creation. If an agreement
+        is given, the procurement_method will be an LTA (AGR_PROC).
+        Otherwise, if it's a stockable product we'll go to tender
+        by setting procurement_method as 'procurement'. Finally marke the
+        rest as 'other'. Those are default value that can be changed afterward
+        by the user.
+
+        :params line: browse record of origin requistion.line
+        :params agreement: browse record of origin agreement
+        :params qty: quantity to be set on source line
+
+        :returns: dict to be used by Model.create
+
+        """
+        res = {}
+        res['proposed_product_id'] = line.product_id.id
+        res['requisition_line_id'] = line.id
+        res['proposed_uom_id'] = line.requested_uom_id.id
+        res['unit_cost'] = 0.0
+        res['proposed_qty'] = qty
+        res['framework_agreement_id'] = False
+        if agreement:
+            if not agreement.product_id.id == line.product_id.id:
+                raise ValueError("Product mismatch for agreement and requisition line")
+            res['framework_agreement_id'] = agreement.id
+            res['procurement_method'] = AGR_PROC
+        else:
+            if line.product_id.type == 'product':
+               res['procurement_method'] = 'procurement'
+            else:
+                res['procurement_method'] = 'other'
+        return res
+
+    def _sort_agreements(self, cr, uid, agreements, qty, currency=None,
+                         context=None):
+        """Sort agreements to be proposed
+
+        Agreement with negociated currency will first be taken in account
+        then they will be choosen by price converted in currency company
+
+        :param agreements: list of agreements to be sorted
+        :param currency: prefered currrency
+
+        :returns: sorted agreements list
+
+        """
+        if not agreements:
+            return agreements
+
+        def _best_company_price(cr, uid, agreement, qty):
+            """Returns the best price in company currency
+
+            For given agreement and price
+
+            """
+            comp_id = self.pool['framework.agreement']._company_get(cr, uid)
+            comp_obj = self.pool['res.company']
+            currency_obj = self.pool['res.currency']
+            comp_currency = comp_obj.browse(cr, uid, comp_id,
+                                            context=context).currency_id
+            prices = []
+            for pl in agreement.framework_agreement_pricelist_ids:
+                price = agreement.get_price(qty, currency=pl.currency_id)
+                comp_price = currency_obj.compute(cr, uid,
+                                                  pl.currency_id.id,
+                                                  comp_currency.id,
+                                                  price, False)
+                prices.append(comp_price)
+            return min(prices)
+
+        firsts = []
+        if currency:
+            firsts = [x for x in agreements if x.has_currency(currency)]
+            lasts = [x for x in agreements if not x.has_currency(currency)]
+            firsts.sort(key=lambda x: x.get_price(qty, currency=currency))
+            lasts.sort(key=lambda x: _best_company_price(cr, uid, x, qty))
+            return firsts + lasts
+        else:
+            agreements.sort(key=lambda x: _best_company_price(cr, uid, x, qty))
+            return agreements
+
+    def _generate_lines_from_agreements(self, cr, uid, container, line,
+                                        agreements, qty, currency=None, context=None):
+        """Generate 1/n source line(s) for one requisition line.
+
+        This is done using available agreements.
+        We first look for cheapeast agreement.
+        Then if no more quantity are available and there is still remaining
+        needs we look for next cheapest agreement or return remaining qty.
+        we prefer to use agreement with negociated currency first even
+        if they are cheaper in other currences. Then it will choose remaining
+        agreements ordered by price converted in company currency
+
+        :param container: list of agreements browse
+        :param qty: quantity to be sourced
+        :param line: origin requisition line
+
+        :returns: remaining quantity to source
+
+        """
+        agreements = agreements if agreements is not None else []
+        agreements = self._sort_agreements(cr, uid, agreements, qty,
+                                           currency=currency)
+        if not agreements:
+            return qty
+        current_agr = agreements.pop(0)
+        avail = current_agr.available_quantity
+        if not avail:
+            return qty
+        avail_sold = avail - qty
+        to_consume = qty if avail_sold >= 0 else avail
+
+        source_id = self.make_source_line(cr, uid, line, force_qty=to_consume,
+                                          agreement=current_agr, context=context)
+        container.append(source_id)
+        difference = qty - to_consume
+        if difference:
+            return self._generate_lines_from_agreements(cr, uid, container, line,
+                                                        agreements, difference,
+                                                        context=context)
+        else:
+            return 0
+
+    def _source_lines_for_agreements(self, cr, uid, line, agreements, currency=None, context=None):
+        """Generate 1/n source line(s) for one requisition line
+
+        This is done using available agreements.
+        We first look for cheapeast agreement.
+        Then if no more quantity are available and there is still remaining needs
+        we look for next cheapest agreement or we create a tender source line
+
+        :param line: requisition line browse record
+        :returns: (generated line ids, remaining qty not covered by agreement)
+
+        """
+        Sourced = namedtuple('Sourced', ['generated', 'remaining'])
+        qty = line.requested_qty
+        generated = []
+        remaining_qty = self._generate_lines_from_agreements(cr, uid, generated,
+                                                             line, agreements, qty,
+                                                             currency=currency, context=context)
+        return Sourced(generated, remaining_qty)
+
+    def make_source_line(self, cr, uid, line, force_qty=None, agreement=None, context=None):
+        """Generate a source line from a requisition line, see
+        _prepare_line_source for details.
+
+        :param line: browse record of origin logistic.request
+        :param force_qty: if set this quantity will be used instead
+        of requested quantity
+        :returns: id of generated source line
+
+        """
+        qty = force_qty if force_qty else line.requested_qty
+        src_obj = self.pool['logistic.requisition.source']
+        vals = self._prepare_line_source(cr, uid, line,
+                                                    qty=qty,
+                                                    agreement=agreement,
+                                                    context=None)
+        return src_obj.create(cr, uid, vals, context=context)
+
+    def _generate_source_line(self, cr, uid, line, context=None):
+        """Generate one or n source line(s) per requisition line.
+
+        Depending on the available resources. If there is framework agreement(s)
+        running we generate one or n source line using agreements otherwise we generate one
+        source line using tender process
+
+        :param line: browse record of origin logistic.request
+
+        :returns: list of generated source line ids
+
+        """
+        if line.source_ids:
+            return None
+        agr_obj = self.pool['framework.agreement']
+        date = line.requisition_id.date
+        currency = line.currency_id
+        product_id = line.product_id.id
+        agreements = agr_obj.get_all_product_agreements(cr, uid, product_id, date,
+                                                        context=context)
+        generated_lines = []
+        if agreements:
+            line_ids, missing_qty = self._source_lines_for_agreements(cr, uid, line,
+                                                                      agreements, currency=currency)
+            generated_lines.extend(line_ids)
+            if missing_qty:
+                generated_lines.append(self.make_source_line(cr, uid, line,
+                                                             force_qty=missing_qty))
+        else:
+            generated_lines.append(self.make_source_line(cr, uid, line))
+
+        return generated_lines
+
+    def _do_confirm(self, cr, uid, ids, context=None):
+        """Override to generate source lines from requision line.
+
+        Please refer to _generate_source_line documentation
+
+        """
+        # TODO refactor
+        # this should probably be in logistic_requisition module
+        # providing a mechanism to allow each type of sourcing method
+        # to generate source line
+        res = super(logistic_requisition_line, self)._do_confirm(cr, uid, ids,
+                                                                 context=context)
+        for line_br in self.browse(cr, uid, ids, context=context):
+            self._generate_source_line(cr, uid, line_br, context=context)
+        return res

=== added file 'framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py'
--- framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/model/logistic_requisition_cost_estimate.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm
+from openerp.tools.translate import _
+from .logistic_requisition_source import AGR_PROC
+
+
+class logistic_requisition_cost_estimate(orm.Model):
+    """Add update of agreement price"""
+
+    _inherit = "logistic.requisition.cost.estimate"
+
+
+    def _prepare_cost_estimate_line(self, cr, uid, sourcing, context=None):
+        """Override in order to update agreement source line
+
+        """
+        res = super(logistic_requisition_cost_estimate,
+                    self)._prepare_cost_estimate_line(cr, uid, sourcing,
+                                                      context=context)
+
+        if sourcing.procurement_method == AGR_PROC:
+            res['type'] = 'make_to_order'
+            res['sale_flow'] = 'direct_delivery'
+        return res
+
+    def _link_po_lines_to_so_lines(self, cr, uid, so, sources, context=None):
+        """Naive implementation to link all PO lines to SO lines.
+
+        For our actuall need we want to link all service line
+        to SO real product lines.
+
+        There should not be twice the same product on differents
+        Agreement PO line so this case in not handled
+
+        """
+
+        so_lines = [x for x in so.order_line if x.product_id]
+        po_lines = set(x.purchase_line_id for x in sources
+                       if x.purchase_line_id)
+        product_dict = dict((x.product_id.id, x.id) for x in so_lines
+                            if x.product_id)
+        default = product_dict[product_dict.keys()[0]]
+        if not product_dict:
+            raise orm.except_orm(_('No stockable product in related PO'),
+                                 _('Please add one'))
+        for po_line in po_lines:
+            key = po_line.product_id.id if po_line.product_id else False
+            po_line.write({'sale_order_line_id': product_dict.get(key, default)})
+
+    def cost_estimate(self, cr, uid, ids, context=None):
+        """Override to link PO to cost_estimate$
+
+        In a normal flow, when you chose a bid as the winning one, the bid is
+        dupplicated to generate the draft PO. On this action, it link the LRS
+        to the generated PO line.
+
+        In a tender flow, we don't dupplicate the bid, it's only a PO. The link
+        between the LRS and the PO line should then be created here.
+
+        This is for the drop shipping to work propely cause in that case, SO
+        and PO are linked together.
+        """
+        so_model = self.pool['sale.order']
+        po_model = self.pool['purchase.order']
+        res = super(logistic_requisition_cost_estimate,
+                    self).cost_estimate(cr, uid, ids, context=context)
+        so_id = res['res_id']
+        order = so_model.browse(cr, uid, so_id, context=context)
+        # Can be optimized with a SQL or a search but
+        # gain of perfo will not worth readability loss
+        # for such small data set
+        sources = [x.logistic_requisition_source_id for x in order.order_line
+                   if x and x.logistic_requisition_source_id.procurement_method == AGR_PROC]
+        po_ids = set(x.purchase_line_id.order_id.id for x in sources
+                     if x.purchase_line_id)
+        po_model.write(cr, uid, list(po_ids),
+                       {'sale_id': so_id,
+                        'sale_flow': 'direct_delivery'})
+        self._link_po_lines_to_so_lines(cr, uid, order, sources, context=context)
+        return res

=== added file 'framework_agreement_sourcing/model/logistic_requisition_source.py'
--- framework_agreement_sourcing/model/logistic_requisition_source.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/model/logistic_requisition_source.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,389 @@
+ # -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from itertools import chain
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+from openerp.addons.framework_agreement.model.framework_agreement import\
+    FrameworkAgreementObservable
+from openerp.addons.framework_agreement.utils import id_boilerplate
+
+
+AGR_PROC = 'fw_agreement'
+
+
+class logistic_requisition_source(orm.Model, FrameworkAgreementObservable):
+    """Adds support of framework agreement to source line"""
+
+    _inherit = "logistic.requisition.source"
+
+    _columns = {'framework_agreement_id': fields.many2one('framework.agreement',
+                                                          'Agreement'),
+                'framework_agreement_po_id': fields.many2one('purchase.order',
+                                                             'Agreement Purchase'),
+                'supplier_id': fields.related('framework_agreement_id', 'supplier_id',
+                                              type='many2one',  relation='res.partner',
+                                              string='Agreement Supplier')}
+
+    def _get_procur_method_hook(self, cr, uid, context=None):
+        """Adds framework agreement as a procurement method in selection field"""
+        res = super(logistic_requisition_source, self)._get_procur_method_hook(cr, uid,
+                                                                               context=context)
+        res.append((AGR_PROC, 'Framework agreement'))
+        return res
+
+    def _get_purchase_line_id(self, cr, uid, ids, field_name, arg, context=None):
+        """For each source line, get the related purchase order line
+
+        For more detail please refer to function fields documentation
+
+        """
+        po_line_model = self.pool['purchase.order.line']
+        res = super(logistic_requisition_source, self)._get_purchase_line_id(cr, uid, ids,
+                                                                             field_name,
+                                                                             arg,
+                                                                             context=context)
+        for line in self.browse(cr, uid, ids, context=context):
+            if line.procurement_method == AGR_PROC:
+                po_l_ids = po_line_model.search(cr, uid,
+                                                [('lr_source_line_id', '=', line.id),
+                                                 ('state', '!=', 'cancel')],
+                                                context=context)
+                if po_l_ids:
+                    if len(po_l_ids) > 1:
+                        raise orm.except_orm(_('Many Purchase order lines found for %s') % line.name,
+                                             _('Please cancel uneeded one'))
+                    res[line.id] = po_l_ids[0]
+                else:
+                    res[line.id] = False
+        return res
+
+    #------------------ adapting source line to po -----------------------------
+    def _company(self, cr, uid, context):
+        """Return company id
+
+        :returns: company id
+
+        """
+        return self.pool['res.company']._company_default_get(cr, uid, self._name,
+                                                             context=context)
+
+    def _prepare_purchase_order(self, cr, uid, line, po_pricelist, context=None):
+        """Prepare the dict of values to create the PO from a
+           source line.
+
+        :param browse_record line: logistic.requisition.source
+        :param browse_record pricelist: product.pricelist
+        :returns: data dict to be used by orm.Model.create
+
+        """
+        supplier = line.framework_agreement_id.supplier_id
+        add = line.requisition_id.consignee_shipping_id
+        term = supplier.property_supplier_payment_term
+        term = term.id if term else False
+        position = supplier.property_account_position
+        position = position.id if position else False
+        requisition = line.requisition_id
+        data = {}
+        data['framework_agreement_id'] = line.framework_agreement_id.id
+        data['partner_id'] = supplier.id
+        data['company_id'] = self._company(cr, uid, context)
+        data['pricelist_id'] = po_pricelist.id
+        data['dest_address_id'] = add.id
+        data['location_id'] = add.property_stock_customer.id
+        data['payment_term_id'] = term
+        data['fiscal_position'] = position
+        data['origin'] = requisition.name
+        data['date_order'] = requisition.date
+        # data['name'] = requisition.name
+        data['consignee_id'] = requisition.consignee_id.id
+        data['incoterm_id'] = requisition.incoterm_id.id
+        data['incoterm_address'] = requisition.incoterm_address
+        data['type'] = 'purchase'
+        return data
+
+    def _prepare_purchase_order_line(self, cr, uid, po_id, line,
+                               po_supplier, po_pricelist, context=None):
+        """Prepare the dict of values to create the PO Line from args.
+
+        :param integer po_id: ids of purchase.order
+        :param browse_record line: logistic.requisition.source
+        :param browse_record po_supplier: res.partner
+        :param browse_record po_pricelist: product.pricelist
+        :returns: data dict to be used by orm.Model.create
+
+        """
+        data = {}
+        acc_pos_obj = self.pool['account.fiscal.position']
+        pl_model = self.pool['product.pricelist']
+        currency = po_pricelist.currency_id
+
+        if line.framework_agreement_id:
+            price = line.framework_agreement_id.get_price(line.proposed_qty, currency=currency)
+            lead_time = line.framework_agreement_id.delay
+            supplier = line.framework_agreement_id.supplier_id
+            data['framework_agreement_id'] = line.framework_agreement_id.id
+        else:
+            supplier = po_supplier
+            lead_time = 0
+            price = 0.0
+            if po_pricelist:
+                price = pl_model.price_get(cr, uid,
+                                           [po_pricelist.id],
+                                           line.proposed_product_id.id,
+                                           line.proposed_qty or 1.0,
+                                           po_supplier.id,
+                                           {'uom': line.proposed_uom_id.id})[po_pricelist.id]
+
+        if not price:
+            price = line.proposed_product_id.standard_price or 1.00
+        taxes_ids = line.proposed_product_id.supplier_taxes_id
+        taxes = acc_pos_obj.map_tax(cr, uid, supplier.property_account_position,
+                                    taxes_ids)
+
+        data['order_id'] = po_id
+        data['product_qty'] = line.proposed_qty
+        data['product_id'] = line.proposed_product_id.id
+        data['product_uom'] = line.proposed_uom_id.id
+        data['lr_source_line_id']= line.id
+        data['product_lead_time'] = lead_time
+        data['price_unit'] = price
+        data['name'] = line.proposed_product_id.name
+        data['date_planned'] = line.requisition_id.date_delivery
+        data['taxes_id'] = [(6, 0, taxes)]
+        return data
+
+    def _make_po_from_source_lines(self, cr, uid, main_source, other_sources,
+                                   pricelist, context=None):
+        """Create a purchase order from a source line. After creating it,
+        it'll update the unit_cost of the source line accoring to the PO
+        price. We do this because the currency of the PO may not be the same
+        than the LRS so it may happends that value vary because of exchange
+        rate.
+
+        :param browse_record main_source: logistic.requisition.source of
+            type LTA from which you want to generate to PO
+        :param browse_record other_sources: logistic.requisition.source of
+            type other to indlue in the PO
+        :param browse_record pricelist: product.pricelist to be used in PO to
+            know the currency mainly (as the prices will be computed from LTA)
+        :returns integer : generated PO id
+
+        """
+        if context is None:
+            context = {}
+        context['draft_po'] = True
+        currency_obj = self.pool['res.currency']
+        po_obj = self.pool['purchase.order']
+        po_l_obj = self.pool['purchase.order.line']
+        supplier = main_source.framework_agreement_id.supplier_id
+        to_curr = pricelist.currency_id.id
+        po_vals = self._prepare_purchase_order(cr, uid, main_source,
+                                         pricelist, context=context)
+        po_id = po_obj.create(cr, uid, po_vals, context=context)
+        other_sources = other_sources if other_sources else []
+        for source in chain([main_source], other_sources):
+            line_vals = self._prepare_purchase_order_line(cr, uid, po_id,
+                                                    source, supplier,
+                                                    pricelist, context=context)
+            po_l_obj.create(cr, uid, line_vals, context=context)
+            # TODO: Update LRS unit_cost from po line, with currency conversion
+            from_curr = source.requisition_id.currency_id.id
+            # Compute from bid currency to LRS currency
+            price = currency_obj.compute(cr, uid, from_curr, to_curr,
+                    line_vals['price_unit'], False)
+            source.write({'framework_agreement_po_id': po_id, 'unit_cost':price})
+        return po_id
+
+    def make_purchase_order(self, cr, uid, ids, pricelist, context=None):
+        """Create a purchase order from the LRS ids list. This method will
+        create one PO with all lines. Between them, you'll have line of type
+        LTA (framewrok agreement) and line of type other.
+        Currently, only one line of type LTA is accepted at a time.
+
+        We'll raise an error if other types are selected here.
+        We accept line of type other here to include products not included
+        in the LTA for example : you order Product A under LTA + the transport
+        as a LRS of type other.
+
+        :param integer list ids: ids of logistic.requisition.source
+        :param browse_record pricelist: product.pricelist
+        :returns integer : generated PO id
+
+        """
+        sources = self.browse(cr, uid, ids, context=context)
+        # LRS of type LTA (framework agreement)
+        agreement_sources = []
+        # LRS of type other
+        other_sources =  []
+        for source in sources:
+            if source.procurement_method == AGR_PROC:
+                agreement_sources.append(source)
+            elif source.procurement_method == 'other':
+                other_sources.append(source)
+            else:
+                raise orm.except_orm(_('Source line must be of type other or agreement'),
+                                     _('Please correct selection'))
+
+        main_source = agreement_sources[0] if agreement_sources else False
+        if len(agreement_sources) > 1:
+            raise orm.except_orm(_('There should be only one agreement line'),
+                                 _('Please correct selection'))
+        if not main_source:
+            raise orm.except_orm(_('There should be at least one agreement line'),
+                                 _('Please correct selection'))
+        fback = main_source.framework_agreement_id.supplier_id.property_product_pricelist_purchase
+        pricelist = pricelist if pricelist else fback
+        po_id = self._make_po_from_source_lines(cr, uid, main_source,
+                                                other_sources, pricelist, context=None)
+        return po_id
+
+    def _is_sourced_other(self, cr, uid, source, context=None):
+        """Predicate function to test if line on other
+        method are sourced"""
+        tender_ok = self._is_sourced_procurement(cr, uid, source,
+                                                 context=context)
+        agr_ok = self._is_sourced_fw_agreement(cr, uid, source,
+                                                 context=context)
+        return (tender_ok or agr_ok)
+
+    def _is_sourced_fw_agreement(self, cr, uid, source, context=None):
+        """Predicate that tells if source line of type agreement are sourced
+
+        :retuns: boolean True if sourced
+
+        """
+        po_line_obj = self.pool['purchase.order.line']
+        sources_ids = po_line_obj.search(cr, uid,
+                                         [('lr_source_line_id', '=', source.id)],
+                                         context=context)
+        # predicate
+        return bool(sources_ids)
+
+    #---------------OpenERP tedious onchange management ------------------------
+
+    def _get_date(self, cr, uid, requision_line_id, context=None):
+        """helper to retrive date to be used by framework agreement
+        when in source line context
+
+        :param source_id: requisition.line.source id that should
+            provide date
+
+        :returns: date/datetime string
+
+        """
+        req_obj = self.pool['logistic.requisition.line']
+        current = req_obj.browse(cr, uid, requision_line_id, context=context)
+        now = fields.datetime.now()
+        return current.requisition_id.date or now
+
+    @id_boilerplate
+    def onchange_sourcing_method(self, cr, uid, ids, method, req_line_id, proposed_product_id,
+                                 proposed_qty=0, context=None):
+        """
+        Called when source method is set on a source line.
+
+        If sourcing method is framework agreement
+        it will set price, agreement and supplier if possible
+        and raise quantity warning.
+
+        """
+        line_source = self.browse(cr, uid, ids, context=context)
+        res = {'value': {'framework_agreement_id': False}}
+        if (method != AGR_PROC or not proposed_product_id):
+            return res
+        currency = line_source.currency_id
+        agreement_obj = self.pool['framework.agreement']
+        date = self._get_date(cr, uid, req_line_id, context=context)
+        agreement, enough_qty = agreement_obj.get_cheapest_agreement_for_qty(cr, uid,
+                                                                             proposed_product_id,
+                                                                             date,
+                                                                             proposed_qty,
+                                                                             currency=currency,
+                                                                             context=context)
+        if not agreement:
+            return res
+        price = agreement.get_price(proposed_qty, currency=currency)
+        res['value'] = {'framework_agreement_id': agreement.id,
+                        'unit_cost': price,
+                        'total_cost': price * proposed_qty,
+                        'supplier_id': agreement.supplier_id.id}
+        if not enough_qty:
+            msg = _("You have ask for a quantity of %s \n"
+                    " but there is only %s available"
+                    " for current agreement") % (proposed_qty,
+                                                 agreement.available_quantity)
+            res['warning'] = msg
+        return res
+
+    @id_boilerplate
+    def onchange_quantity(self, cr, uid, ids, method, req_line_id, qty,
+                          proposed_product_id, context=None):
+        """Raise a warning if agreed qty is not sufficient"""
+        line_source = self.browse(cr, uid, ids, context=context)
+        if (method != AGR_PROC or not proposed_product_id):
+            return {}
+        currency = line_source.currency_id
+        date = self._get_date(cr, uid, req_line_id, context=context)
+        return self.onchange_quantity_obs(cr, uid, ids, qty, date,
+                                          proposed_product_id,
+                                          currency=currency,
+                                          price_field='dummy',
+                                          context=context)
+
+    @id_boilerplate
+    def onchange_product_id(self, cr, uid, ids, method, req_line_id,
+                            proposed_product_id, proposed_qty,
+                            context=None):
+        """Call when product is set on a source line.
+
+        If sourcing method is framework agreement
+        it will set price, agreement and supplier if possible
+        and raise quantity warning.
+
+        """
+        if method != AGR_PROC:
+            if proposed_product_id:
+                value = {'proposed_uom_id': ''}
+                if proposed_product_id:
+                    prod_obj = self.pool.get('product.product')
+                    prod = prod_obj.browse(cr, uid, proposed_product_id, context=context)
+                    value = {
+                        'proposed_uom_id': prod.uom_id.id,
+                    }
+                return {'value': value}
+            return {}
+
+        return self.onchange_sourcing_method(cr, uid, ids, method, req_line_id,
+                                             proposed_product_id,
+                                             proposed_qty=proposed_qty,
+                                             context=context)
+
+    @id_boilerplate
+    def onchange_agreement(self, cr, uid, ids, agreement_id, req_line_id, qty,
+                           proposed_product_id, context=None):
+        line_source = self.browse(cr, uid, ids, context=context)
+        if not proposed_product_id or not agreement_id:
+            return {}
+        currency = line_source.currency_id
+        date = self._get_date(cr, uid, req_line_id, context=context)
+        return self.onchange_agreement_obs(cr, uid, ids, agreement_id, qty,
+                                           date, proposed_product_id,
+                                           currency=currency, price_field='dummy')

=== added file 'framework_agreement_sourcing/model/purchase.py'
--- framework_agreement_sourcing/model/purchase.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/model/purchase.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import orm
+
+class purchase_order(orm.Model):
+    """ Override action_confirm to set quantity bid if LTA
+    """
+
+    _inherit = "purchase.order"
+
+
+    def action_confirm(self, cr, uid, ids, context=None):
+        super(purchase_order_line, self).action_confirm(cr, uid, ids, context=context)
+        for element in self.browse(cr, uid, ids, context=context):
+            if not element.quantity_bid and not element.framework_agreement_id:
+                self.write(cr, uid, ids, {'quantity_bid': element.product_qty}, context=context)
+        return True
+

=== added file 'framework_agreement_sourcing/model/sale_order.py'
--- framework_agreement_sourcing/model/sale_order.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/model/sale_order.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp import netsvc
+from openerp.osv import orm
+from .logistic_requisition_source import AGR_PROC
+
+
+class sale_order_line(orm.Model):
+    """Pass agreement PO into state confirmed when SO is confirmed"""
+
+    _inherit = "sale.order.line"
+
+    def button_confirm(self, cr, uid, ids, context=None):
+        """Override confirmation of request of cotation to support LTA
+
+        Related PO generated by agreement source line will be passed to state confirm.
+
+        """
+        def source_valid(source):
+            if source and source.procurement_method == AGR_PROC:
+                return True
+            return False
+        result = super(sale_order_line, self).button_confirm(cr, uid, ids,
+                                                             context=context)
+        po_line_model = self.pool['purchase.order.line']
+        po_model = self.pool['purchase.order']
+
+        lines = self.browse(cr, uid, ids, context=context)
+        source_ids = [x.logistic_requisition_source_id.id for x in lines
+                           if source_valid(x.logistic_requisition_source_id)]
+        po_line_ids = po_line_model.search(cr, uid,
+                                           [('lr_source_line_id', 'in', source_ids)],
+                                           context=context)
+        po_lines = po_line_model.read(cr, uid, po_line_ids, ['order_id'],
+                                      load='_classic_write')
+        po_ids = set(x['order_id'] for x in po_lines)
+        wf_service = netsvc.LocalService("workflow")
+        for po in po_model.browse(cr, uid, list(po_ids), context=context):
+            wf_service.trg_validate(uid, 'purchase.order', po.id,
+                                    'draft_po', cr)
+        return result

=== added directory 'framework_agreement_sourcing/security'
=== added file 'framework_agreement_sourcing/security/ir.model.access.csv'
--- framework_agreement_sourcing/security/ir.model.access.csv	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/security/ir.model.access.csv	2014-03-10 15:39:56 +0000
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_po_creator,po_creator,model_logistic_requisition_source_create_agr_po,purchase.group_purchase_user,1,1,1,1

=== added directory 'framework_agreement_sourcing/tests'
=== added file 'framework_agreement_sourcing/tests/__init__.py'
--- framework_agreement_sourcing/tests/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/tests/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import common
+from . import test_logistic_order_line_to_source_line
+from . import test_agreement_souce_line_to_po
+checks = [test_logistic_order_line_to_source_line,
+          test_agreement_souce_line_to_po]

=== added file 'framework_agreement_sourcing/tests/common.py'
--- framework_agreement_sourcing/tests/common.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/tests/common.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from datetime import timedelta
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
+import openerp.tests.common as test_common
+from openerp.addons.logistic_requisition.tests import logistic_requisition
+from openerp.addons.framework_agreement.tests.common import BaseAgreementTestMixin
+
+
+class CommonSourcingSetUp(test_common.TransactionCase, BaseAgreementTestMixin):
+
+    def setUp(self):
+        """
+        Setup a standard configuration for test
+        """
+        super(CommonSourcingSetUp, self).setUp()
+        self.commonsetUp()
+        self.requisition_model = self.registry('logistic.requisition')
+        self.requisition_line_model = self.registry('logistic.requisition.line')
+        self.source_line_model = self.registry('logistic.requisition.source')
+        self.make_common_agreements()
+        self.make_common_requisition()
+
+    def make_common_requisition(self):
+        """Create a standard logistic requisition"""
+        start_date = self.now + timedelta(days=12)
+        start_date = start_date.strftime(DEFAULT_SERVER_DATE_FORMAT)
+        req = {
+            'partner_id': self.ref('base.res_partner_1'),
+            'consignee_id': self.ref('base.res_partner_3'),
+            'date_delivery': start_date,
+            'date': start_date,
+            'user_id': self.uid,
+            'budget_holder_id': self.uid,
+            'finance_officer_id': self.uid,
+            'pricelist_id': self.ref('product.list0'),
+        }
+        agr_line = {
+            'product_id': self.product_id,
+            'requested_qty': 100,
+            'requested_uom_id': self.ref('product.product_uom_unit'),
+            'date_delivery': self.now.strftime(DEFAULT_SERVER_DATE_FORMAT),
+            'budget_tot_price': 100000000,
+        }
+        product_line = {
+            'product_id': self.ref('product.product_product_7'),
+            'requested_qty': 10,
+            'requested_uom_id': self.ref('product.product_uom_unit'),
+            'date_delivery': self.now.strftime(DEFAULT_SERVER_DATE_FORMAT),
+            'budget_tot_price': 100000000,
+        }
+
+        other_line = {
+            'product_id': self.ref('logistic_requisition.product_transport'),
+            'requested_qty': 1,
+            'requested_uom_id': self.ref('product.product_uom_unit'),
+            'date_delivery': self.now.strftime(DEFAULT_SERVER_DATE_FORMAT),
+            'budget_tot_price': 100000000,
+        }
+
+
+        requisition_id = logistic_requisition.create(self, req)
+        logistic_requisition.add_line(self, requisition_id,
+                                      agr_line)
+        logistic_requisition.add_line(self, requisition_id,
+                                      product_line)
+        logistic_requisition.add_line(self, requisition_id,
+                                      other_line)
+        self.requisition = self.requisition_model.browse(self.cr, self.uid, requisition_id)
+
+    def make_common_agreements(self):
+        """Create two default agreements.
+
+        We have two agreement for same product but using
+        different suppliers
+
+        One supplier has a better price for lower qty the other
+        has better price for higher qty
+
+        We also create one requisition with one line of agreement product
+        And one line of other product
+
+        """
+
+        cr, uid = self.cr, self.uid
+        start_date = self.now + timedelta(days=10)
+        start_date = start_date.strftime(DEFAULT_SERVER_DATE_FORMAT)
+        end_date = self.now + timedelta(days=20)
+        end_date = end_date.strftime(DEFAULT_SERVER_DATE_FORMAT)
+        # Agreement 1
+        agr_id = self.agreement_model.create(cr, uid,
+                                             {'supplier_id': self.supplier_id,
+                                              'product_id': self.product_id,
+                                              'start_date': start_date,
+                                              'end_date': end_date,
+                                              'draft': False,
+                                              'delay': 5,
+                                              'quantity': 2000})
+
+        pl_id = self.agreement_pl_model.create(cr, uid,
+                                               {'framework_agreement_id': agr_id,
+                                                'currency_id': self.ref('base.EUR')})
+        self.agreement_line_model.create(cr, uid,
+                                         {'framework_agreement_pricelist_id': pl_id,
+                                          'quantity': 0,
+                                          'price': 77.0})
+
+        self.agreement_line_model.create(cr, uid,
+                                         {'framework_agreement_pricelist_id': pl_id,
+                                          'quantity': 1000,
+                                          'price': 30.0})
+
+        self.cheap_on_high_agreement = self.agreement_model.browse(cr, uid, agr_id)
+
+        # Agreement 2
+        agr_id = self.agreement_model.create(cr, uid,
+                                             {'supplier_id': self.ref('base.res_partner_3'),
+                                              'product_id': self.product_id,
+                                              'start_date': start_date,
+                                              'end_date': end_date,
+                                              'draft': False,
+                                              'delay': 5,
+                                              'quantity': 1200})
+
+        pl_id = self.agreement_pl_model.create(cr, uid,
+                                               {'framework_agreement_id': agr_id,
+                                                'currency_id': self.ref('base.EUR')})
+
+        self.agreement_line_model.create(cr, uid,
+                                         {'framework_agreement_pricelist_id': pl_id,
+                                          'quantity': 0,
+                                          'price': 50.0})
+        self.agreement_line_model.create(cr, uid,
+                                         {'framework_agreement_pricelist_id': pl_id,
+                                          'quantity': 1000,
+                                          'price': 45.0})
+        self.cheap_on_low_agreement = self.agreement_model.browse(cr, uid, agr_id)

=== added file 'framework_agreement_sourcing/tests/test_agreement_souce_line_to_po.py'
--- framework_agreement_sourcing/tests/test_agreement_souce_line_to_po.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/tests/test_agreement_souce_line_to_po.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from .common import CommonSourcingSetUp
+
+
+class TestSourceToPo(CommonSourcingSetUp):
+
+    def setUp(self):
+        # we generate a source line
+        super(TestSourceToPo, self).setUp()
+        cr, uid = self.cr, self.uid
+        lines = self.requisition.line_ids
+        agr_line = None
+        self.wiz_model = self.registry('logistic.requisition.source.create.agr.po')
+        for line in lines:
+            if line.product_id == self.cheap_on_low_agreement.product_id:
+                agr_line = line
+                break
+        self.assertTrue(agr_line)
+        agr_line.write({'requested_qty': 400})
+        agr_line.refresh()
+        source_ids = []
+        for line in lines:
+            if (line.product_id.id == self.product_id or
+                    line.product_id.type == 'service'):
+                lid = self.requisition_line_model._generate_source_line(cr, uid, line)
+                source_ids += lid
+        self.assertTrue(len(source_ids) == 2)
+        self.source_lines = self.source_line_model.browse(cr, uid, source_ids)
+        self.lta_source = next(x for x in self.source_lines
+                               if x.procurement_method == 'fw_agreement')
+        self.other_source = next(x for x in self.source_lines
+                                 if x.procurement_method == 'other')
+
+    def test_01_transform_source_to_agreement(self):
+        """Test transformation of an agreement source line into PO"""
+        cr, uid = self.cr, self.uid
+        self.assertTrue(self.lta_source)
+        self.lta_source.refresh()
+        active_ids = [x.id for x in self.source_lines]
+        wiz_id = self.wiz_model.create(self.cr, self.uid, {},
+                                       context={'active_ids': active_ids})
+
+        wiz = self.wiz_model.browse(self.cr, self.uid, wiz_id)
+        po_id = wiz.action_create_agreement_po_requisition(
+            context={'active_ids': active_ids}
+        )['res_id']
+        self.assertTrue(po_id)
+        supplier = self.lta_source.framework_agreement_id.supplier_id
+        add = self.lta_source.requisition_id.consignee_shipping_id
+        consignee = self.lta_source.requisition_id.consignee_id
+        po = self.registry('purchase.order').browse(cr, uid, po_id)
+        date_order = self.lta_source.requisition_id.date
+        date_delivery = self.lta_source.requisition_id.date_delivery
+        self.assertEqual(po.partner_id, supplier)
+        self.assertEqual(po.pricelist_id, supplier.property_product_pricelist_purchase)
+        self.assertEqual(po.date_order, date_order)
+        self.assertEqual(po.dest_address_id, add)
+        self.assertEqual(po.consignee_id, consignee)
+        self.assertEqual(po.state, 'draftpo')
+
+        self.assertEqual(len(po.order_line), 2)
+
+        po_line = next(x for x in po.order_line
+                       if x.product_id == self.lta_source.framework_agreement_id.product_id)
+        self.assertEqual(po_line.product_qty, self.lta_source.proposed_qty)
+        self.assertEqual(po_line.product_id, self.lta_source.proposed_product_id)
+        self.assertEqual(po_line.product_qty, self.lta_source.proposed_qty)
+        self.assertEqual(po_line.product_uom, self.lta_source.proposed_uom_id)
+        self.assertAlmostEqual(po_line.price_unit, 50.0)
+        self.assertEqual(po_line.lr_source_line_id, self.lta_source)
+        self.assertEqual(po_line.date_planned, date_delivery)
+
+        po_line = next(x for x in po.order_line
+                       if x.product_id == self.other_source.proposed_product_id)
+        self.assertEqual(po_line.product_qty, self.other_source.proposed_qty)
+        self.assertEqual(po_line.product_id, self.other_source.proposed_product_id)
+        self.assertEqual(po_line.product_qty, self.other_source.proposed_qty)
+        self.assertEqual(po_line.product_uom, self.other_source.proposed_uom_id)
+        self.assertAlmostEqual(po_line.price_unit, 1.0)
+        self.assertEqual(po_line.lr_source_line_id, self.other_source)

=== added file 'framework_agreement_sourcing/tests/test_logistic_order_line_to_source_line.py'
--- framework_agreement_sourcing/tests/test_logistic_order_line_to_source_line.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/tests/test_logistic_order_line_to_source_line.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from ..model.logistic_requisition_source import AGR_PROC
+from .common import CommonSourcingSetUp
+
+
+class TestTransformation(CommonSourcingSetUp):
+
+    def test_01_enough_qty_on_first_agr(self):
+        """Test that we can source a line with one agreement and low qty"""
+        cr, uid = self.cr, self.uid
+        lines = self.requisition.line_ids
+        agr_line = None
+        for line in lines:
+            if line.product_id == self.cheap_on_low_agreement.product_id:
+                agr_line = line
+                break
+        self.assertTrue(agr_line)
+        agr_line.write({'requested_qty': 400})
+        agr_line.refresh()
+        to_validate_ids = self.requisition_line_model._generate_source_line(cr, uid, agr_line)
+        self.assertTrue(len(to_validate_ids) == 1)
+        to_validate = self.source_line_model.browse(cr, uid, to_validate_ids[0])
+        self.assertEqual(to_validate.procurement_method, AGR_PROC)
+        self.assertAlmostEqual(to_validate.unit_cost, 0.0)
+        self.assertEqual(to_validate.proposed_qty, 400)
+
+    def test_02_enough_qty_on_high_agr(self):
+        """Test that we can source a line correctly on both agreement"""
+        cr, uid = self.cr, self.uid
+        lines = self.requisition.line_ids
+        agr_line = None
+        for line in lines:
+            if line.product_id == self.cheap_on_high_agreement.product_id:
+                agr_line = line
+                break
+        self.assertTrue(agr_line)
+        agr_line.write({'requested_qty': 1500})
+        agr_line.refresh()
+        to_validate_ids = self.requisition_line_model._generate_source_line(cr, uid, agr_line)
+        self.assertTrue(len(to_validate_ids) == 1)
+        to_validate = self.source_line_model.browse(cr, uid, to_validate_ids[0])
+        self.assertEqual(to_validate.procurement_method, AGR_PROC)
+        self.assertAlmostEqual(to_validate.unit_cost, 0.0)
+        self.assertEqual(to_validate.proposed_qty, 1500)
+
+    def test_03_not_enough_qty_on_high_agreement(self):
+        """Test that we can source a line with one agreement and high qty"""
+        cr, uid = self.cr, self.uid
+        lines = self.requisition.line_ids
+        agr_line = None
+        for line in lines:
+            if line.product_id == self.cheap_on_high_agreement.product_id:
+                agr_line = line
+                break
+        self.assertTrue(agr_line)
+        agr_line.write({'requested_qty': 2400})
+        agr_line.refresh()
+        to_validate_ids = self.requisition_line_model._generate_source_line(cr, uid, agr_line)
+        self.assertTrue(len(to_validate_ids) == 2)
+        # We validate generated line
+        to_validates = self.source_line_model.browse(cr, uid, to_validate_ids)
+        # high_line
+        # idiom taken from Python cookbook
+        high_line = next((x for x in to_validates
+                              if x.framework_agreement_id == self.cheap_on_high_agreement), None)
+        self.assertTrue(high_line, msg="High agreement was not used")
+        self.assertEqual(high_line.procurement_method, AGR_PROC)
+        self.assertEqual(high_line.proposed_qty, 2000)
+        self.assertAlmostEqual(high_line.unit_cost, 0.0)
+
+        # low_line
+        low_line = next((x for x in to_validates
+                              if x.framework_agreement_id == self.cheap_on_low_agreement), None)
+        self.assertTrue(low_line, msg="Low agreement was not used")
+        self.assertEqual(low_line.procurement_method, AGR_PROC)
+        self.assertEqual(low_line.proposed_qty, 400)
+        self.assertAlmostEqual(low_line.unit_cost, 0.0)
+
+    def test_03_not_enough_qty_on_all_agreemenst(self):
+        """Test that we have generate correct line when not enough qty on all agreements
+
+        That means last source line must be of type other or procurement
+        """
+        cr, uid = self.cr, self.uid
+        lines = self.requisition.line_ids
+        agr_line = None
+        for line in lines:
+            if line.product_id == self.cheap_on_high_agreement.product_id:
+                agr_line = line
+                break
+        self.assertTrue(agr_line)
+        agr_line.write({'requested_qty': 5000})
+        agr_line.refresh()
+        to_validate_ids = self.requisition_line_model._generate_source_line(cr, uid, agr_line)
+        self.assertTrue(len(to_validate_ids) == 3)
+        # We validate generated line
+        to_validates = self.source_line_model.browse(cr, uid, to_validate_ids)
+        # high_line
+        # idiom taken from Python cookbook
+        high_line = next((x for x in to_validates
+                              if x.framework_agreement_id == self.cheap_on_high_agreement), None)
+        self.assertTrue(high_line, msg="High agreement was not used")
+        self.assertEqual(high_line.procurement_method, AGR_PROC)
+        self.assertEqual(high_line.proposed_qty, 2000)
+        self.assertAlmostEqual(high_line.unit_cost, 0.0)
+
+        # low_line
+        low_line = next((x for x in to_validates
+                              if x.framework_agreement_id == self.cheap_on_low_agreement), None)
+        self.assertTrue(low_line, msg="Low agreement was not used")
+        self.assertEqual(low_line.procurement_method, AGR_PROC)
+        self.assertEqual(low_line.proposed_qty, 1200)
+        self.assertAlmostEqual(low_line.unit_cost, 0.0)
+
+        # Tender line
+        tender_line = next((x for x in to_validates
+                                if not x.framework_agreement_id), None)
+        self.assertTrue(tender_line, msg="Tender line was not generated")
+        self.assertNotEqual(tender_line.procurement_method, AGR_PROC)

=== added directory 'framework_agreement_sourcing/view'
=== added file 'framework_agreement_sourcing/view/requisition_view.xml'
--- framework_agreement_sourcing/view/requisition_view.xml	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/view/requisition_view.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data>
+    <record id="add_supplier_and_agreement_on_source_line" model="ir.ui.view">
+      <field name="name">add supplier and agrement on source line</field>
+      <field name="model">logistic.requisition.source</field>
+      <field name="inherit_id" ref="logistic_requisition.view_logistic_requisition_source_form"/>
+      <field name="arch" type="xml">
+        <field name="unit_cost"
+               position="before">
+          <field name="framework_agreement_id"
+                 domain="[('draft', '=', False)]"
+                 attrs="{'required': [('procurement_method', '=', 'fw_agreement')],
+                        'invisible': [('procurement_method', '!=', 'fw_agreement')]}"
+                 on_change="onchange_agreement(framework_agreement_id, requisition_line_id, proposed_qty, proposed_product_id, context)"/>
+          <field name="framework_agreement_po_id"
+                 readonly="1"
+                 attrs="{'invisible': [('procurement_method', 'not in', ['fw_agreement','other'])]}"
+                                  
+                 />
+
+          <field name="supplier_id"
+                 invisible="1"/>
+        </field>
+        <field name="proposed_uom_id"
+               position="attributes">
+          <attribute name="attrs">{'invisible': [('procurement_method', '=', 'fw_agreement')]}</attribute>
+        </field>
+        <field name="unit_cost"
+               position="attributes">
+          <attribute name="attrs">{'invisible': [('procurement_method', '=', 'fw_agreement')]}</attribute>
+        </field>
+        <field name="total_cost"
+               position="attributes">
+          <attribute name="attrs">{'invisible': [('procurement_method', '=', 'fw_agreement')]}</attribute>
+        </field>
+        <field name="price_is"
+               position="attributes">
+          <attribute name="attrs">{'invisible': [('procurement_method', '=', 'fw_agreement')]}</attribute>
+        </field>
+      </field>
+    </record>
+
+    <record id="addd_agreement_source_line_onchange" model="ir.ui.view">
+      <field name="name">ad agreement source line onchange</field>
+      <field name="model">logistic.requisition.source</field>
+      <field name="inherit_id" ref="logistic_requisition.view_logistic_requisition_source_form"/>
+      <field name="arch" type="xml">
+        <data>
+          <field name="procurement_method"
+                 position="attributes">
+            <attribute name="on_change">onchange_sourcing_method(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)</attribute>
+          </field>
+
+          <field name="proposed_qty"
+                 position="attributes">
+            <attribute name="on_change">onchange_quantity(procurement_method, requisition_line_id, proposed_qty, proposed_product_id)</attribute>
+          </field>
+          <field name="proposed_product_id"
+                 position="attributes">
+            <attribute name="on_change">onchange_product_id(procurement_method, requisition_line_id, proposed_product_id, proposed_qty)</attribute>
+          </field>
+
+        </data>
+      </field>
+    </record>
+
+  </data>
+</openerp>

=== added directory 'framework_agreement_sourcing/wizard'
=== added file 'framework_agreement_sourcing/wizard/__init__.py'
--- framework_agreement_sourcing/wizard/__init__.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/wizard/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: joel Grand-Guillaume
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import logistic_requisition_source_create_po

=== added file 'framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py'
--- framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/wizard/logistic_requisition_source_create_po.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Nicolas Bessi
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+class logistic_requisition_source_po_creator(orm.TransientModel):
+
+    _name = 'logistic.requisition.source.create.agr.po'
+
+    _columns = {
+        'pricelist_id': fields.many2one('product.pricelist',
+                                          string='Pricelist / Currency',
+                                          required=True),
+        'framework_currency_ids': fields.many2many('framework.agreement.pricelist',
+                                                   rel='framework_agr_id_po_create_rel',
+                                                   string='Available Currency',
+                                                   readonly=True)
+    }
+
+    def default_get(self, cr, uid, fields_list, context=None):
+        """ Take the pricelist of the lrs by default. Show the
+        available choice for the user.
+        """
+        if context is None:
+            context = {}
+        defaults = super(logistic_requisition_source_po_creator, self).\
+            default_get(cr, uid, fields_list, context=context)
+        line_obj = self.pool.get('logistic.requisition.source')
+        fmwk_price_obj = self.pool.get('framework.agreement.pricelist')
+        line_ids = context['active_ids']
+        pricelist_id = None
+        line = next((x for x in line_obj.browse(cr, uid, line_ids, context=context)
+                    if x.framework_agreement_id), None)
+        if not line:
+            raise orm.except_orm(_('No sourcing line with agreement selected'),
+                                 _('Please correct selection'))
+
+        pricelist_id = line_obj._get_purchase_pricelist_from_currency(
+                cr,
+                uid,
+                line.requisition_id.pricelist_id.currency_id.id,
+                context=context
+                )
+        defaults['pricelist_id'] = pricelist_id
+
+        frwk_ids = fmwk_price_obj.search(
+            cr, uid,
+            [('framework_agreement_id', '=', line.framework_agreement_id.id)],
+            context=context
+        )
+        defaults['framework_currency_ids'] = frwk_ids
+        return defaults
+
+    def _make_purchase_order(self, cr, uid, pricelist, source_ids, context=None):
+        """Create PO from source line ids"""
+        lr_model = self.pool['logistic.requisition.source']
+        po_id = lr_model.make_purchase_order(cr, uid, source_ids,
+                                              pricelist, context=context)
+        return po_id
+
+    def action_create_agreement_po_requisition(self, cr, uid, ids, context=None):
+        """ Implement buttons that create PO from selected source lines"""
+        act_obj = self.pool['ir.actions.act_window']
+        source_ids = context['active_ids']
+        form = self.browse(cr, uid, ids, context=context)[0]
+        pricelist=form.pricelist_id
+
+        available_currency = [x.currency_id for x in form.framework_currency_ids]
+        if available_currency and pricelist.currency_id not in available_currency:
+            raise orm.except_orm(_('User Error'), _(
+                'You must chose a pricelist that is in the same currency '
+                'than one of the available in the framework agreement.'))
+        po_id = self._make_purchase_order(cr, uid, pricelist, source_ids,
+                                           context=context)
+        # TODO : update LRS price from PO depending on the chosen currency
+
+        res = act_obj.for_xml_id(cr, uid,
+                                 'purchase', 'purchase_rfq', context=context)
+        res.update({'domain': [('id', '=', po_id)],
+                    'res_id': po_id,
+                    'context': '{}',
+                    'search_view_id': False,
+                    })
+        return res

=== added file 'framework_agreement_sourcing/wizard/logistic_requisition_source_create_po_view.xml'
--- framework_agreement_sourcing/wizard/logistic_requisition_source_create_po_view.xml	1970-01-01 00:00:00 +0000
+++ framework_agreement_sourcing/wizard/logistic_requisition_source_create_po_view.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data>
+
+    <record id="view_create_agr_po_from_source" model="ir.ui.view">
+      <field name="name">Create Purchase Order From Requisition Source</field>
+      <field name="model">logistic.requisition.source.create.agr.po</field>
+      <field name="arch" type="xml">
+        <form string="Create Purchase Order" version="7.0">
+          <separator string="Which pricelist / currency you want ?"/>
+          <label string="You can only chose a pricelist with a currency that is included
+            in the framewrok agreement you have chosen." colspan="4"/>
+          <field name="framework_currency_ids"/>
+          <field name="pricelist_id" domain="[('type','=','purchase')]"/>
+
+          <group>
+            <separator string="Are you sure you want to create a Purchase Order from those lines ?"/>
+            <label string="
+                           Please note that: &#10; &#10;
+                           Requisition will only be created if: &#10;
+                           * Lines belong to the same company &#10;
+                           * There is only one agreement line in selection &#10;
+                           * Products are define on all selected lines &#10;
+                           * Non agreement line are of type other &#10;
+                           &#10; &#10;
+                           " colspan="4"/>
+          </group>
+          <footer>
+            <button name="action_create_agreement_po_requisition"
+                    string="Create Purchase Order"
+                    type="object" class="oe_highlight"/>
+            or
+            <button string="Cancel"
+                    class="oe_link"
+                    special="cancel" />
+          </footer>
+        </form>
+      </field>
+    </record>
+
+    <act_window
+        name="Create Agreement Purchase Order"
+        res_model="logistic.requisition.source.create.agr.po"
+        src_model="logistic.requisition.source"
+        view_mode="form"
+        target="new"
+        multi="True"
+        key2="client_action_multi"
+        id="action_view_create_agr_po_from_source"/>
+
+  </data>
+</openerp>

=== modified file 'logistic_order/__openerp__.py'
--- logistic_order/__openerp__.py	2014-02-06 16:20:00 +0000
+++ logistic_order/__openerp__.py	2014-03-10 15:39:56 +0000
@@ -35,9 +35,15 @@
              "sale_validity",
              "transport_plan",
              "delivery",
+<<<<<<< TREE
              "stock_location_ownership",
              "sale_sourced_by_line",
              "sale_dropshipping",
+=======
+             'stock_location_ownership',
+             'sale_sourced_by_line',
+             'sale_dropshipping',
+>>>>>>> MERGE-SOURCE
              "sale_order_webkit",
              ],
  "demo": [],

=== modified file 'logistic_requisition/__openerp__.py'
--- logistic_requisition/__openerp__.py	2013-09-20 07:12:14 +0000
+++ logistic_requisition/__openerp__.py	2014-03-10 15:39:56 +0000
@@ -31,8 +31,38 @@
 This module allows you to manage your Logistic Requisitions.
 ============================================================
 
-A Logistic requisition express a need that is requested somewhere.
-
+A Logistic requisition express a need that is requested somewhere. It allows to 
+manage the sourcing of the needs before making a cost estimate to the requestor.
+
+This invert the logic that is in standard in OpenERP in the way that the sourcing 
+of the procuremnt is made before the order confirmation and we built the link incase 
+of validation. In standard, th SO confirmation generate the procurement then it
+generate the needed procurement.
+
+The sourcing can be of various type:
+ 
+ * Warehouse dispatch: You will deliver the requested goods from one of your 
+ stock location
+ * Procurement : You will go for tender to chose the best supplier for the 
+ requiredgoods
+ * Framework agreement : You will use the existing Framework agreement
+ * Other : Nothing of those choices. In that case, the line can be selected
+and included in either a PO or a tender
+
+The simple process is the following:
+
+ * LR are recorded as the to represent the need of the customer/requestor
+ * LR are confirm and sourced of different way (dispatch, tender, ..)
+ * If sourced from tender, you need to go all along the tendering process (CBA).
+ Once you chose one bid, the system will automatically put back the prices 
+ information on the sourcing line of the LR.
+  * You can create a cost estimate from sourced LR lines for your 
+ resquestor/customer
+ * If the requestor accept the cost estimate, his validation will automatically:
+   * Create the link between the chosen winning bid and the line sourced this way. 
+     A new draft PO will be generatedand managed as drop shipping.
+   * Lines sourced as a dispatch will create a delivery order. 
+   * Lines sourced a LTA will create a PO of type LTA
 """,
  "depends": ["transport_plan",
              "purchase",

=== modified file 'logistic_requisition/i18n/en_US.po'
--- logistic_requisition/i18n/en_US.po	2013-08-29 09:53:01 +0000
+++ logistic_requisition/i18n/en_US.po	2014-03-10 15:39:56 +0000
@@ -6,8 +6,8 @@
 msgstr ""
 "Project-Id-Version: OpenERP Server 7.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-08-29 09:51+0000\n"
-"PO-Revision-Date: 2013-08-29 09:51+0000\n"
+"POT-Creation-Date: 2014-02-04 13:11+0000\n"
+"PO-Revision-Date: 2014-02-04 13:11+0000\n"
 "Last-Translator: <>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
@@ -21,14 +21,14 @@
 msgstr "Logistic Specialist"
 
 #. module: logistic_requisition
-#: field:logistic.requisition.source,offer_ids:0
-msgid "Sales Quotation Lines"
-msgstr "Sales Quotation Lines"
+#: field:logistic.requisition.line,amount_total:0
+msgid "Total Amount"
+msgstr "Total Amount"
 
 #. module: logistic_requisition
-#: field:logistic.requisition,finance_officer_id:0
-msgid "Finance Officer"
-msgstr "Finance Officer"
+#: view:logistic.requisition.line:0
+msgid "View Stock"
+msgstr "View Stock"
 
 #. module: logistic_requisition
 #: view:logistic.requisition:0
@@ -49,6 +49,11 @@
 msgstr "Shipping / Transport"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:140
+msgid "Preferred transport"
+msgstr "Preferred transport"
+
+#. module: logistic_requisition
 #: model:ir.actions.act_window,name:logistic_requisition.act_window_requisition_source_transport
 #: model:ir.actions.act_window,name:logistic_requisition.action_requisition_source_transport
 msgid "Create Transport Plan"
@@ -70,10 +75,20 @@
 msgstr "View Lines"
 
 #. module: logistic_requisition
-#: selection:logistic.requisition.source,price_is:0
-#: selection:sale.order.line,price_is:0
-msgid "Fixed"
-msgstr "Fixed"
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:119
+msgid "Consignee address:"
+msgstr "Consignee address:"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:634
+#, python-format
+msgid "This new requisition concerns %s and is due for %s."
+msgstr "This new requisition concerns %s and is due for %s."
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:139
+msgid "Desired delivery date"
+msgstr "Desired delivery date"
 
 #. module: logistic_requisition
 #: field:logistic.requisition,message_unread:0
@@ -93,6 +108,11 @@
 msgstr "Company"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:149
+msgid "No"
+msgstr "No"
+
+#. module: logistic_requisition
 #: selection:logistic.requisition.source,procurement_method:0
 msgid "Framework Agreement"
 msgstr "Framework Agreement"
@@ -114,15 +134,11 @@
 msgstr "Just for Quotation"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Requestor is External or National Societe"
-msgstr "Requestor is External or National Societe"
-
-#. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/transport_plan.py:154
 #: model:ir.model,name:logistic_requisition.model_transport_plan
 #: view:logistic.requisition.source:0
 #: field:logistic.requisition.source,transport_plan_id:0
+#, python-format
 msgid "Transport Plan"
 msgstr "Transport Plan"
 
@@ -138,9 +154,14 @@
 msgstr "Delivery Address"
 
 #. module: logistic_requisition
-#: field:logistic.requisition.line,budget_unit_price:0
-msgid "Budget Unit Price"
-msgstr "Budget Unit Price"
+#: help:logistic.requisition.line.assign,logistic_user_id:0
+msgid "Logistic Specialist in charge of the Logistic Requisition Line"
+msgstr "Logistic Specialist in charge of the Logistic Requisition Line"
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:163
+msgid "UoM"
+msgstr "UoM"
 
 #. module: logistic_requisition
 #: view:logistic.requisition:0
@@ -149,6 +170,12 @@
 msgstr "Business Unit Officer"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:262
+#, python-format
+msgid "The cost estimate cannot be created, because no lines are sourced."
+msgstr "The cost estimate cannot be created, because no lines are sourced."
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 #: field:logistic.requisition.line,note:0
 msgid "Notes"
@@ -162,9 +189,9 @@
 msgstr "Messages"
 
 #. module: logistic_requisition
-#: constraint:logistic.requisition.source:0
-msgid "The total cost cannot be more than the total budget."
-msgstr "The total cost cannot be more than the total budget."
+#: view:logistic.requisition.line:0
+msgid "Total Proposed"
+msgstr "Total Proposed"
 
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_purchase_order
@@ -172,12 +199,19 @@
 msgstr "Purchase Order"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:142
 #: view:logistic.requisition:0
 #: field:logistic.requisition,analytic_id:0
 msgid "Project"
 msgstr "Project"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:522
+#, python-format
+msgid "Please create source ressource using various source line actions"
+msgstr "Please create source ressource using various source line actions"
+
+#. module: logistic_requisition
 #: help:logistic.requisition.source,date_eta:0
 msgid "Estimated Date of Arrival"
 msgstr "Estimated Date of Arrival"
@@ -202,11 +236,10 @@
 "                    sourced logistic requisition lines."
 
 #. module: logistic_requisition
-#: selection:logistic.requisition,requester_type:0
-#: selection:logistic.requisition.line,requester_type:0
-#: selection:res.partner,requester_type:0
-msgid "External Organization"
-msgstr "External Organization"
+#: selection:logistic.requisition.source,price_is:0
+#: selection:sale.order.line,price_is:0
+msgid "Fixed"
+msgstr "Fixed"
 
 #. module: logistic_requisition
 #: help:logistic.requisition,message_unread:0
@@ -221,9 +254,28 @@
 msgstr "Incoterm Place"
 
 #. module: logistic_requisition
-#: field:logistic.requisition,date_budget_holder:0
-msgid "Budget Holder Validation Date"
-msgstr "Budget Holder Validation Date"
+#: code:addons/logistic_requisition/model/purchase.py:174
+#: code:addons/logistic_requisition/model/purchase.py:194
+#, python-format
+msgid "UserError"
+msgstr "UserError"
+
+#. module: logistic_requisition
+#: field:logistic.requisition.source,unit_cost:0
+msgid "Unit Cost"
+msgstr "Unit Cost"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:588
+#, python-format
+msgid "Prices for location"
+msgstr "Prices for location"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1067
+#, python-format
+msgid "The sourcing lines do not have the same delivery address."
+msgstr "The sourcing lines do not have the same delivery address."
 
 #. module: logistic_requisition
 #: field:logistic.requisition,name:0
@@ -244,11 +296,6 @@
 msgstr "Desired Delivery Date"
 
 #. module: logistic_requisition
-#: view:logistic.requisition.line:0
-msgid "View Stock"
-msgstr "View Stock"
-
-#. module: logistic_requisition
 #: field:logistic.requisition,consignee_id:0
 msgid "Consignee"
 msgstr "Consignee"
@@ -293,19 +340,17 @@
 msgstr "Partner"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/purchase.py:178
+#, python-format
+msgid "You cannot change the informations because this PO line is already linked to a Logistic Requsition Line %s marked as sourced or quoted."
+msgstr "You cannot change the informations because this PO line is already linked to a Logistic Requsition Line %s marked as sourced or quoted."
+
+#. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_sale_order
 msgid "Sales Order"
 msgstr "Sales Order"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: field:logistic.requisition,amount_total:0
-#: view:logistic.requisition.line:0
-#: view:logistic.requisition.source:0
-msgid "Total Budget"
-msgstr "Total Budget"
-
-#. module: logistic_requisition
 #: help:logistic.requisition,incoterm_id:0
 msgid "International Commercial Terms are a series of predefined commercial terms used in international transactions."
 msgstr "International Commercial Terms are a series of predefined commercial terms used in international transactions."
@@ -365,6 +410,11 @@
 msgstr "State"
 
 #. module: logistic_requisition
+#: view:logistic.requisition.source.create.requisition:0
+msgid "Which pricelist / currency you want ?"
+msgstr "Which pricelist / currency you want ?"
+
+#. module: logistic_requisition
 #: field:logistic.requisition,message_follower_ids:0
 #: field:logistic.requisition.line,message_follower_ids:0
 #: field:logistic.requisition.source,message_follower_ids:0
@@ -393,17 +443,13 @@
 msgstr "Unassigned Requisition"
 
 #. module: logistic_requisition
-#: selection:logistic.requisition,requester_type:0
-#: selection:logistic.requisition.line,requester_type:0
-#: selection:res.partner,requester_type:0
-msgid "National Society"
-msgstr "National Society"
-
-#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1146
+#: code:addons/logistic_requisition/wizard/logistic_line_create_requisition.py:63
 #: model:ir.model,name:logistic_requisition.model_purchase_requisition
 #: view:logistic.requisition.line:0
 #: view:logistic.requisition.source:0
 #: field:logistic.requisition.source,po_requisition_id:0
+#, python-format
 msgid "Purchase Requisition"
 msgstr "Call for Bids"
 
@@ -418,14 +464,9 @@
 msgstr "Skipped"
 
 #. module: logistic_requisition
-#: field:logistic.requisition.source,selected_po_id:0
-msgid "Selected Purchase Order"
-msgstr "Selected Purchase Order"
-
-#. module: logistic_requisition
-#: constraint:logistic.requisition.source:0
-msgid "A purchase requisition cannot be linked to lines of different logistics requisitions."
-msgstr "A call for bids cannot be linked to lines of different logistics requisitions."
+#: help:logistic.requisition.line,logistic_user_id:0
+msgid "User in charge of the Logistic Requisition Line"
+msgstr "User in charge of the Logistic Requisition Line"
 
 #. module: logistic_requisition
 #: model:logistic.requisition.cancel.reason,name:logistic_requisition.cancel_reason_other_provider
@@ -443,9 +484,27 @@
 msgstr "Skipped Lines"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-msgid "View Sourcing Lines"
-msgstr "View Sourcing Lines"
+#: field:logistic.requisition.source,selected_bid_id:0
+msgid "Selected Bid"
+msgstr "Selected Bid"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:566
+#, python-format
+msgid "Stock by Location"
+msgstr "Stock by Location"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1092
+#, python-format
+msgid "The logistic requisition sourcing line %s is already linked to a Purchase Requisition."
+msgstr "The logistic requisition sourcing line %s is already linked to a Purchase Requisition."
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:219
+#, python-format
+msgid "Cannot create a cost estimate because:"
+msgstr "Cannot create a cost estimate because:"
 
 #. module: logistic_requisition
 #: field:logistic.requisition.source,price_is:0
@@ -459,6 +518,12 @@
 msgstr "Reset to Draft"
 
 #. module: logistic_requisition
+#: view:logistic.requisition:0
+#: view:logistic.requisition.line:0
+msgid "Show cost estimate only"
+msgstr "Show cost estimate only"
+
+#. module: logistic_requisition
 #: view:logistic.requisition.cost.estimate:0
 msgid "The lines in the Skipped section will be ignored\n"
 "                    because they are not sourced or are already linked\n"
@@ -468,11 +533,22 @@
 "                    to a cost estimate."
 
 #. module: logistic_requisition
+#: field:logistic.requisition,pricelist_id:0
+msgid "Pricelist"
+msgstr "Pricelist"
+
+#. module: logistic_requisition
 #: field:logistic.requisition.source,dispatch_location_id:0
 msgid "Dispatch From"
 msgstr "Dispatch From"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1113
+#, python-format
+msgid "There should be at least one selectedline with procurement method Procurement"
+msgstr "There should be at least one selectedline with procurement method Procurement"
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 #: field:logistic.requisition.line,logistic_user_id:0
 msgid "Assigned To"
@@ -489,10 +565,25 @@
 msgstr "draft,confirmed,exception"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Show cost estimate only"
-msgstr "Show cost estimate only"
+#: field:logistic.requisition.source,transport_applicable:0
+msgid "Transport Applicable"
+msgstr "Transport Applicable"
+
+#. module: logistic_requisition
+#: field:logistic.requisition.source,default_source_address:0
+msgid "Default source"
+msgstr "Default source"
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:141
+msgid "Cost estimate only"
+msgstr "Cost estimate only"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/purchase.py:198
+#, python-format
+msgid "You cannot delete this PO line because it is already linked to a Logistic Requsition Line %s marked as sourced or quoted."
+msgstr "You cannot delete this PO line because it is already linked to a Logistic Requsition Line %s marked as sourced or quoted."
 
 #. module: logistic_requisition
 #: view:logistic.requisition:0
@@ -521,6 +612,11 @@
 msgstr "Logistic Requisition Reference must be unique!"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:192
+msgid "Signature"
+msgstr "Signature"
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 msgid "Country:"
 msgstr "Country:"
@@ -531,14 +627,21 @@
 msgstr "Your assigned Requisition"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:196
+#, python-format
+msgid "Sourcing %s: no account code has been stored"
+msgstr "Sourcing %s: no account code has been stored"
+
+#. module: logistic_requisition
 #: field:logistic.requisition.source,proposed_qty:0
 msgid "Proposed Qty"
 msgstr "Proposed Qty"
 
 #. module: logistic_requisition
-#: field:purchase.order.line,po_line_from_bid_ids:0
-msgid "Lines generated by the bid"
-msgstr "Lines generated by the bid"
+#: selection:logistic.requisition.source,price_is:0
+#: selection:sale.order.line,price_is:0
+msgid "Estimated"
+msgstr "Estimated"
 
 #. module: logistic_requisition
 #: model:ir.actions.act_window,name:logistic_requisition.action_requisition_line_assign
@@ -552,19 +655,32 @@
 msgstr "Purchase Cancel Reasons"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1045
+#, python-format
+msgid "The lines are not assigned to the same User."
+msgstr "The lines are not assigned to the same User."
+
+#. module: logistic_requisition
 #: constraint:logistic.requisition.cost.estimate:0
 msgid "All the lines should belong to the same requisition."
 msgstr "All the lines should belong to the same requisition."
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1118
+#, python-format
+msgid "Selected line procurement method should be procurement or other"
+msgstr "Selected line procurement method should be procurement or other"
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 msgid "Delivery Date"
 msgstr "Delivery Date"
 
 #. module: logistic_requisition
-#: field:logistic.requisition,budget_holder_id:0
-msgid "Budget Holder"
-msgstr "Budget Holder"
+#: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition_cancel
+#: view:logistic.requisition.cancel:0
+msgid "Reason for the cancellation"
+msgstr "Reason for the cancellation"
 
 #. module: logistic_requisition
 #: constraint:logistic.requisition.source:0
@@ -573,7 +689,6 @@
 
 #. module: logistic_requisition
 #: view:logistic.requisition.source:0
-#: field:purchase.requisition,logistic_requisition_source_ids:0
 msgid "Logistic Requisition Sourcing Lines"
 msgstr "Logistic Requisition Sourcing Lines"
 
@@ -583,8 +698,11 @@
 msgstr "Line's State"
 
 #. module: logistic_requisition
+#: view:logistic.requisition:0
 #: field:logistic.requisition,currency_id:0
+#: view:logistic.requisition.line:0
 #: field:logistic.requisition.line,currency_id:0
+#: field:logistic.requisition.source,currency_id:0
 msgid "Currency"
 msgstr "Currency"
 
@@ -600,36 +718,53 @@
 msgstr "Incoterm Place of Delivery. International Commercial Terms are a series of predefined commercial terms used in international transactions."
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:191
+#, python-format
+msgid "Sourcing %s: no quantity has been proposed"
+msgstr "Sourcing %s: no quantity has been proposed"
+
+#. module: logistic_requisition
 #: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition
 #: model:ir.ui.menu,name:logistic_requisition.menu_logistic_requisition
 msgid "Requisitions"
 msgstr "Requisitions"
 
 #. module: logistic_requisition
-#: field:logistic.requisition,date_finance_officer:0
-msgid "Finance Officer Validation Date"
-msgstr "Finance Officer Validation Date"
-
-#. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Internal (Federation)"
-msgstr "Internal (Federation)"
-
-#. module: logistic_requisition
-#: field:logistic.requisition.source,transport_applicable:0
-msgid "Transport Applicable"
-msgstr "Transport Applicable"
-
-#. module: logistic_requisition
-#: field:logistic.requisition.source,purchase_requisition_line_ids:0
-msgid "Purchase Requisition Lines"
-msgstr "Call for Bids Lines"
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:149
+msgid "Yes"
+msgstr "Yes"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1115
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1120
+#, python-format
+msgid "Please correct selection"
+msgstr "Please correct selection"
+
+#. module: logistic_requisition
+#: field:logistic.requisition.source,offer_ids:0
+msgid "Sales Quotation Lines"
+msgstr "Sales Quotation Lines"
+
+#. module: logistic_requisition
+#: constraint:logistic.requisition.source:0
+msgid "A purchase requisition cannot be linked to lines of different logistics requisitions."
+msgstr "A call for bids cannot be linked to lines of different logistics requisitions."
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:136
+msgid "Logistic requisition"
+msgstr "Logistic requisition"
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:190
+msgid "Requesting entity"
+msgstr "Requesting entity"
 
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_purchase_order_line
-#: field:logistic.requisition.source,bid_line_id:0
 #: field:logistic.requisition.source,purchase_line_id:0
+#: field:logistic.requisition.source,selected_bid_line_id:0
 msgid "Purchase Order Line"
 msgstr "Purchase Order Line"
 
@@ -644,6 +779,12 @@
 msgstr "Assigned Specialist"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:521
+#, python-format
+msgid "line %s is not sourced"
+msgstr "line %s is not sourced"
+
+#. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_logistic_requisition_source_transport_plan
 msgid "Create a transport plan for logistic requisition source lines"
 msgstr "Create a transport plan for logistic requisition source lines"
@@ -703,18 +844,13 @@
 msgstr "Activity Code"
 
 #. module: logistic_requisition
+#: field:purchase.requisition.line,logistic_requisition_source_ids:0
 #: view:transport.plan:0
 #: field:transport.plan,logistic_requisition_source_ids:0
 msgid "Logistic Requisition Source Lines"
 msgstr "Logistic Requisition Source Lines"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "External (NS, Others)"
-msgstr "External (NS, Others)"
-
-#. module: logistic_requisition
 #: field:logistic.requisition.source.transport.plan,transport_estimated_cost:0
 msgid "Transportation Estimated Costs"
 msgstr "Transportation Estimated Costs"
@@ -750,16 +886,6 @@
 msgstr "offers"
 
 #. module: logistic_requisition
-#: field:purchase.requisition.line,logistic_requisition_source_id:0
-msgid "Logistic Requisition Source Line"
-msgstr "Logistic Requisition Source Line"
-
-#. module: logistic_requisition
-#: view:logistic.requisition:0
-msgid "Validation"
-msgstr "Validation"
-
-#. module: logistic_requisition
 #: help:logistic.requisition.source.transport.plan,date_eta:0
 msgid "Estimated Date of Arrival if not set requisition ETA will be used"
 msgstr "Estimated Date of Arrival if not set requisition ETA will be used"
@@ -772,9 +898,15 @@
 msgstr "Is a Follower"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-msgid " validated on "
-msgstr " validated on "
+#: code:addons/logistic_requisition/model/sale_order.py:45
+#, python-format
+msgid "The logistic requisition line %s has no purchase order line."
+msgstr "The logistic requisition line %s has no purchase order line."
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:187
+msgid "Approval"
+msgstr "Approval"
 
 #. module: logistic_requisition
 #: help:logistic.requisition.source,date_etd:0
@@ -788,6 +920,11 @@
 msgstr "Create Call for Bids From Requisition Source"
 
 #. module: logistic_requisition
+#: help:logistic.requisition,pricelist_id:0
+msgid "Pricelist that represent the currency for current logistic request."
+msgstr "Pricelist that represent the currency for current logistic request."
+
+#. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_stock_incoterms
 msgid "Incoterms"
 msgstr "Incoterms"
@@ -813,7 +950,6 @@
 
 #. module: logistic_requisition
 #: view:logistic.requisition:0
-#: field:logistic.requisition,partner_id:0
 msgid "Requesting Entity"
 msgstr "Requesting Entity"
 
@@ -848,6 +984,17 @@
 msgstr "View Prices"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1044
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1052
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1059
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1066
+#: code:addons/logistic_requisition/model/sale_order.py:44
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:261
+#, python-format
+msgid "Error"
+msgstr "Error"
+
+#. module: logistic_requisition
 #: model:logistic.requisition.cancel.reason,name:logistic_requisition.cancel_reason_no_service_needed
 msgid "No service needed anymore"
 msgstr "No service needed anymore"
@@ -859,11 +1006,7 @@
 msgstr "Assign"
 
 #. module: logistic_requisition
-#: field:logistic.requisition.source,unit_cost:0
-msgid "Unit Cost"
-msgstr "Unit Cost"
-
-#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:162
 #: view:logistic.requisition:0
 #: field:logistic.requisition.line,requested_qty:0
 msgid "Quantity"
@@ -891,12 +1034,9 @@
 msgstr "Line Sourced"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: field:logistic.requisition,requester_type:0
-#: view:logistic.requisition.line:0
-#: field:logistic.requisition.line,requester_type:0
-msgid "Type of Requestor"
-msgstr "Type of Requestor"
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:160
+msgid "Number"
+msgstr "Number"
 
 #. module: logistic_requisition
 #: view:logistic.requisition.source.create.requisition:0
@@ -904,6 +1044,12 @@
 msgstr "Create Requisition"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1091
+#, python-format
+msgid "Existing"
+msgstr "Existing"
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 #: selection:logistic.requisition.line,state:0
 #: selection:logistic.requisition.source,state:0
@@ -911,9 +1057,10 @@
 msgstr "Assigned"
 
 #. module: logistic_requisition
-#: field:logistic.requisition.line,budget_tot_price:0
-msgid "Budget Total Price"
-msgstr "Budget Total Price"
+#: view:logistic.requisition.line:0
+#: view:logistic.requisition.source:0
+msgid "Total Budget"
+msgstr "Total Budget"
 
 #. module: logistic_requisition
 #: view:logistic.requisition:0
@@ -947,16 +1094,9 @@
 msgstr "Create Cost Estimate"
 
 #. module: logistic_requisition
-#: selection:logistic.requisition.source,price_is:0
-#: selection:sale.order.line,price_is:0
-msgid "Estimated"
-msgstr "Estimated"
-
-#. module: logistic_requisition
-#: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition_cancel
-#: view:logistic.requisition.cancel:0
-msgid "Reason for the cancellation"
-msgstr "Reason for the cancellation"
+#: field:purchase.order.line,po_line_from_bid_ids:0
+msgid "Lines generated by the bid"
+msgstr "Lines generated by the bid"
 
 #. module: logistic_requisition
 #: field:logistic.requisition.line,name:0
@@ -979,18 +1119,16 @@
 msgstr "Your assigned Requisition Line"
 
 #. module: logistic_requisition
-#: selection:logistic.requisition,requester_type:0
-#: selection:logistic.requisition.line,requester_type:0
-#: selection:res.partner,requester_type:0
-msgid "Federation (internal)"
-msgstr "Federation (internal)"
-
-#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 msgid "Req. Date:"
 msgstr "Req. Date:"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:182
+msgid "General Remarks"
+msgstr "General Remarks"
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 #: field:logistic.requisition,cost_estimate_only:0
 #: view:logistic.requisition.line:0
@@ -1014,9 +1152,9 @@
 msgstr "Supplier Address"
 
 #. module: logistic_requisition
-#: field:res.partner,requester_type:0
-msgid "Requester Type"
-msgstr "Requester Type"
+#: selection:logistic.requisition.source,procurement_method:0
+msgid "Other"
+msgstr "Other"
 
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_logistic_requisition_line
@@ -1042,6 +1180,7 @@
 
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_purchase_requisition_line
+#: field:logistic.requisition.source,purchase_requisition_line_id:0
 msgid "Purchase Requisition Line"
 msgstr "Call for Bids Line"
 
@@ -1058,6 +1197,7 @@
 msgstr "Product"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:161
 #: field:logistic.requisition.line,description:0
 msgid "Description"
 msgstr "Description"
@@ -1069,10 +1209,10 @@
 msgstr "Procurement"
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Requestor is the Federation"
-msgstr "Requestor is the Federation"
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1053
+#, python-format
+msgid "The sourcing lines do not belong to the same company."
+msgstr "The sourcing lines do not belong to the same company."
 
 #. module: logistic_requisition
 #: help:transport.plan,product_id:0
@@ -1080,6 +1220,12 @@
 msgstr "Product used for the transport, will be used in the cost estimate"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1097
+#, python-format
+msgid "The sourcing line %d does not have any product defined, please choose one."
+msgstr "The sourcing line %d does not have any product defined, please choose one."
+
+#. module: logistic_requisition
 #: field:logistic.requisition.source.transport.plan,transport_mode_id:0
 msgid "Transport by"
 msgstr "Transport by"
@@ -1090,9 +1236,15 @@
 msgstr "Cancellation reason:"
 
 #. module: logistic_requisition
-#: help:logistic.requisition.line,logistic_user_id:0
-msgid "User in charge of the Logistic Requisition Line"
-msgstr "User in charge of the Logistic Requisition Line"
+#: code:addons/logistic_requisition/model/logistic_requisition.py:632
+#, python-format
+msgid "Logistic Requisition Line %s Assigned"
+msgstr "Logistic Requisition Line %s Assigned"
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:191
+msgid "Requested date"
+msgstr "Requested date"
 
 #. module: logistic_requisition
 #: view:logistic.requisition.line:0
@@ -1100,9 +1252,9 @@
 msgstr "My Requisition Line"
 
 #. module: logistic_requisition
-#: field:logistic.requisition,allowed_budget:0
-msgid "Allowed Budget"
-msgstr "Allowed Budget"
+#: field:logistic.requisition,partner_id:0
+msgid "Customer"
+msgstr "Customer"
 
 #. module: logistic_requisition
 #: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition_source
@@ -1110,11 +1262,6 @@
 msgstr "Requisitions Sourcing Lines"
 
 #. module: logistic_requisition
-#: help:logistic.requisition.line.assign,logistic_user_id:0
-msgid "Logistic Specialist in charge of the Logistic Requisition Line"
-msgstr "Logistic Specialist in charge of the Logistic Requisition Line"
-
-#. module: logistic_requisition
 #: field:logistic.requisition,line_ids:0
 msgid "Products to Purchase"
 msgstr "Products to Purchase"
@@ -1125,6 +1272,7 @@
 msgstr "Mobilization Officer or Logistic Coordinator in charge of the Logistic Requisition"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:143
 #: view:logistic.requisition:0
 #: field:logistic.requisition,country_id:0
 #: view:logistic.requisition.line:0
@@ -1133,8 +1281,11 @@
 msgstr "Country"
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:693
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:293
 #: view:logistic.requisition.cost.estimate:0
 #: field:logistic.requisition.line,cost_estimate_id:0
+#, python-format
 msgid "Cost Estimate"
 msgstr "Cost Estimate"
 
@@ -1154,17 +1305,13 @@
 msgstr "Product UoM"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:144
 #: view:logistic.requisition:0
 #: field:logistic.requisition,date:0
 msgid "Requisition Date"
 msgstr "Requisition Date"
 
 #. module: logistic_requisition
-#: view:logistic.requisition.line:0
-msgid "Total Proposed"
-msgstr "Total Proposed"
-
-#. module: logistic_requisition
 #: view:logistic.requisition.cancel:0
 msgid "Choose the reason for the cancellation of the\n"
 "                    logistic requisition."
@@ -1172,6 +1319,11 @@
 "                    logistic requisition."
 
 #. module: logistic_requisition
+#: field:logistic.requisition.source,proposed_product_id:0
+msgid "Proposed Product"
+msgstr "Proposed Product"
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line.assign:0
 msgid "Select the assignee"
 msgstr "Select the assignee"
@@ -1179,6 +1331,7 @@
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_logistic_requisition_source
 #: view:logistic.requisition.source:0
+#: field:purchase.order.line,lr_source_line_id:0
 msgid "Logistic Requisition Source"
 msgstr "Logistic Requisition Source"
 
@@ -1197,6 +1350,11 @@
 msgstr "Messages and communication history"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:102
+msgid "Shipping address:"
+msgstr "Shipping address:"
+
+#. module: logistic_requisition
 #: view:logistic.requisition.source.create.requisition:0
 msgid " Please note that: \n"
 " \n"
@@ -1224,7 +1382,13 @@
 msgstr "Sourced"
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:178
+msgid "Delivery Remarks"
+msgstr "Delivery Remarks"
+
+#. module: logistic_requisition
 #: field:logistic.requisition.line,account_code:0
+#: field:sale.order.line,account_code:0
 msgid "Account Code"
 msgstr "Account Code"
 
@@ -1234,6 +1398,17 @@
 msgstr "Generated from bid"
 
 #. module: logistic_requisition
+#: field:logistic.requisition.source.create.requisition,pricelist_id:0
+msgid "Pricelist / Currency"
+msgstr "Pricelist / Currency"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1060
+#, python-format
+msgid "The sourcing lines do not have the same consignee."
+msgstr "The sourcing lines do not have the same consignee."
+
+#. module: logistic_requisition
 #: view:logistic.requisition.cancel:0
 #: view:logistic.requisition.cost.estimate:0
 #: view:logistic.requisition.line.assign:0
@@ -1243,7 +1418,24 @@
 msgstr "or"
 
 #. module: logistic_requisition
+#: view:logistic.requisition:0
+msgid "View Sourcing Lines"
+msgstr "View Sourcing Lines"
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1096
+#, python-format
+msgid "Missing information"
+msgstr "Missing information"
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 msgid "Open Cost Estimate"
 msgstr "Open Cost Estimate"
 
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:105
+#, python-format
+msgid "Transport from %s to %s by %s (Ref. %s)"
+msgstr "Transport from %s to %s by %s (Ref. %s)"
+

=== modified file 'logistic_requisition/i18n/logistic_requisition.pot'
--- logistic_requisition/i18n/logistic_requisition.pot	2013-08-29 09:53:01 +0000
+++ logistic_requisition/i18n/logistic_requisition.pot	2014-03-10 15:39:56 +0000
@@ -1,13 +1,13 @@
 # Translation of OpenERP Server.
 # This file contains the translation of the following modules:
-#	* logistic_requisition
+#       * logistic_requisition
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: OpenERP Server 7.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-08-29 09:50+0000\n"
-"PO-Revision-Date: 2013-08-29 09:50+0000\n"
+"POT-Creation-Date: 2014-02-04 13:09+0000\n"
+"PO-Revision-Date: 2014-02-04 13:09+0000\n"
 "Last-Translator: <>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
@@ -21,13 +21,13 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition.source,offer_ids:0
-msgid "Sales Quotation Lines"
+#: field:logistic.requisition.line,amount_total:0
+msgid "Total Amount"
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition,finance_officer_id:0
-msgid "Finance Officer"
+#: view:logistic.requisition.line:0
+msgid "View Stock"
 msgstr ""
 
 #. module: logistic_requisition
@@ -49,6 +49,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:140
+msgid "Preferred transport"
+msgstr ""
+
+#. module: logistic_requisition
 #: model:ir.actions.act_window,name:logistic_requisition.act_window_requisition_source_transport
 #: model:ir.actions.act_window,name:logistic_requisition.action_requisition_source_transport
 msgid "Create Transport Plan"
@@ -70,9 +75,19 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: selection:logistic.requisition.source,price_is:0
-#: selection:sale.order.line,price_is:0
-msgid "Fixed"
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:119
+msgid "Consignee address:"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:634
+#, python-format
+msgid "This new requisition concerns %s and is due for %s."
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:139
+msgid "Desired delivery date"
 msgstr ""
 
 #. module: logistic_requisition
@@ -93,6 +108,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:149
+msgid "No"
+msgstr ""
+
+#. module: logistic_requisition
 #: selection:logistic.requisition.source,procurement_method:0
 msgid "Framework Agreement"
 msgstr ""
@@ -114,15 +134,11 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Requestor is External or National Societe"
-msgstr ""
-
-#. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/transport_plan.py:154
 #: model:ir.model,name:logistic_requisition.model_transport_plan
 #: view:logistic.requisition.source:0
 #: field:logistic.requisition.source,transport_plan_id:0
+#, python-format
 msgid "Transport Plan"
 msgstr ""
 
@@ -138,8 +154,13 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition.line,budget_unit_price:0
-msgid "Budget Unit Price"
+#: help:logistic.requisition.line.assign,logistic_user_id:0
+msgid "Logistic Specialist in charge of the Logistic Requisition Line"
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:163
+msgid "UoM"
 msgstr ""
 
 #. module: logistic_requisition
@@ -149,6 +170,12 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:262
+#, python-format
+msgid "The cost estimate cannot be created, because no lines are sourced."
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 #: field:logistic.requisition.line,note:0
 msgid "Notes"
@@ -162,8 +189,8 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: constraint:logistic.requisition.source:0
-msgid "The total cost cannot be more than the total budget."
+#: view:logistic.requisition.line:0
+msgid "Total Proposed"
 msgstr ""
 
 #. module: logistic_requisition
@@ -172,12 +199,19 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:142
 #: view:logistic.requisition:0
 #: field:logistic.requisition,analytic_id:0
 msgid "Project"
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:522
+#, python-format
+msgid "Please create source ressource using various source line actions"
+msgstr ""
+
+#. module: logistic_requisition
 #: help:logistic.requisition.source,date_eta:0
 msgid "Estimated Date of Arrival"
 msgstr ""
@@ -201,10 +235,9 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: selection:logistic.requisition,requester_type:0
-#: selection:logistic.requisition.line,requester_type:0
-#: selection:res.partner,requester_type:0
-msgid "External Organization"
+#: selection:logistic.requisition.source,price_is:0
+#: selection:sale.order.line,price_is:0
+msgid "Fixed"
 msgstr ""
 
 #. module: logistic_requisition
@@ -220,8 +253,27 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition,date_budget_holder:0
-msgid "Budget Holder Validation Date"
+#: code:addons/logistic_requisition/model/purchase.py:174
+#: code:addons/logistic_requisition/model/purchase.py:194
+#, python-format
+msgid "UserError"
+msgstr ""
+
+#. module: logistic_requisition
+#: field:logistic.requisition.source,unit_cost:0
+msgid "Unit Cost"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:588
+#, python-format
+msgid "Prices for location"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1067
+#, python-format
+msgid "The sourcing lines do not have the same delivery address."
 msgstr ""
 
 #. module: logistic_requisition
@@ -243,11 +295,6 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition.line:0
-msgid "View Stock"
-msgstr ""
-
-#. module: logistic_requisition
 #: field:logistic.requisition,consignee_id:0
 msgid "Consignee"
 msgstr ""
@@ -292,19 +339,17 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/purchase.py:178
+#, python-format
+msgid "You cannot change the informations because this PO line is already linked to a Logistic Requsition Line %s marked as sourced or quoted."
+msgstr ""
+
+#. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_sale_order
 msgid "Sales Order"
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: field:logistic.requisition,amount_total:0
-#: view:logistic.requisition.line:0
-#: view:logistic.requisition.source:0
-msgid "Total Budget"
-msgstr ""
-
-#. module: logistic_requisition
 #: help:logistic.requisition,incoterm_id:0
 msgid "International Commercial Terms are a series of predefined commercial terms used in international transactions."
 msgstr ""
@@ -364,6 +409,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: view:logistic.requisition.source.create.requisition:0
+msgid "Which pricelist / currency you want ?"
+msgstr ""
+
+#. module: logistic_requisition
 #: field:logistic.requisition,message_follower_ids:0
 #: field:logistic.requisition.line,message_follower_ids:0
 #: field:logistic.requisition.source,message_follower_ids:0
@@ -392,17 +442,13 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: selection:logistic.requisition,requester_type:0
-#: selection:logistic.requisition.line,requester_type:0
-#: selection:res.partner,requester_type:0
-msgid "National Society"
-msgstr ""
-
-#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1146
+#: code:addons/logistic_requisition/wizard/logistic_line_create_requisition.py:63
 #: model:ir.model,name:logistic_requisition.model_purchase_requisition
 #: view:logistic.requisition.line:0
 #: view:logistic.requisition.source:0
 #: field:logistic.requisition.source,po_requisition_id:0
+#, python-format
 msgid "Purchase Requisition"
 msgstr ""
 
@@ -417,13 +463,8 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition.source,selected_po_id:0
-msgid "Selected Purchase Order"
-msgstr ""
-
-#. module: logistic_requisition
-#: constraint:logistic.requisition.source:0
-msgid "A purchase requisition cannot be linked to lines of different logistics requisitions."
+#: help:logistic.requisition.line,logistic_user_id:0
+msgid "User in charge of the Logistic Requisition Line"
 msgstr ""
 
 #. module: logistic_requisition
@@ -442,8 +483,26 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-msgid "View Sourcing Lines"
+#: field:logistic.requisition.source,selected_bid_id:0
+msgid "Selected Bid"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:566
+#, python-format
+msgid "Stock by Location"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1092
+#, python-format
+msgid "The logistic requisition sourcing line %s is already linked to a Purchase Requisition."
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:219
+#, python-format
+msgid "Cannot create a cost estimate because:"
 msgstr ""
 
 #. module: logistic_requisition
@@ -458,6 +517,12 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: view:logistic.requisition:0
+#: view:logistic.requisition.line:0
+msgid "Show cost estimate only"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.cost.estimate:0
 msgid "The lines in the Skipped section will be ignored\n"
 "                    because they are not sourced or are already linked\n"
@@ -465,11 +530,22 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: field:logistic.requisition,pricelist_id:0
+msgid "Pricelist"
+msgstr ""
+
+#. module: logistic_requisition
 #: field:logistic.requisition.source,dispatch_location_id:0
 msgid "Dispatch From"
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1113
+#, python-format
+msgid "There should be at least one selectedline with procurement method Procurement"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 #: field:logistic.requisition.line,logistic_user_id:0
 msgid "Assigned To"
@@ -486,9 +562,24 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Show cost estimate only"
+#: field:logistic.requisition.source,transport_applicable:0
+msgid "Transport Applicable"
+msgstr ""
+
+#. module: logistic_requisition
+#: field:logistic.requisition.source,default_source_address:0
+msgid "Default source"
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:141
+msgid "Cost estimate only"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/purchase.py:198
+#, python-format
+msgid "You cannot delete this PO line because it is already linked to a Logistic Requsition Line %s marked as sourced or quoted."
 msgstr ""
 
 #. module: logistic_requisition
@@ -518,6 +609,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:192
+msgid "Signature"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 msgid "Country:"
 msgstr ""
@@ -528,13 +624,20 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:196
+#, python-format
+msgid "Sourcing %s: no account code has been stored"
+msgstr ""
+
+#. module: logistic_requisition
 #: field:logistic.requisition.source,proposed_qty:0
 msgid "Proposed Qty"
 msgstr ""
 
 #. module: logistic_requisition
-#: field:purchase.order.line,po_line_from_bid_ids:0
-msgid "Lines generated by the bid"
+#: selection:logistic.requisition.source,price_is:0
+#: selection:sale.order.line,price_is:0
+msgid "Estimated"
 msgstr ""
 
 #. module: logistic_requisition
@@ -549,18 +652,31 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1045
+#, python-format
+msgid "The lines are not assigned to the same User."
+msgstr ""
+
+#. module: logistic_requisition
 #: constraint:logistic.requisition.cost.estimate:0
 msgid "All the lines should belong to the same requisition."
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1118
+#, python-format
+msgid "Selected line procurement method should be procurement or other"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 msgid "Delivery Date"
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition,budget_holder_id:0
-msgid "Budget Holder"
+#: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition_cancel
+#: view:logistic.requisition.cancel:0
+msgid "Reason for the cancellation"
 msgstr ""
 
 #. module: logistic_requisition
@@ -570,7 +686,6 @@
 
 #. module: logistic_requisition
 #: view:logistic.requisition.source:0
-#: field:purchase.requisition,logistic_requisition_source_ids:0
 msgid "Logistic Requisition Sourcing Lines"
 msgstr ""
 
@@ -580,8 +695,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: view:logistic.requisition:0
 #: field:logistic.requisition,currency_id:0
+#: view:logistic.requisition.line:0
 #: field:logistic.requisition.line,currency_id:0
+#: field:logistic.requisition.source,currency_id:0
 msgid "Currency"
 msgstr ""
 
@@ -597,36 +715,53 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:191
+#, python-format
+msgid "Sourcing %s: no quantity has been proposed"
+msgstr ""
+
+#. module: logistic_requisition
 #: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition
 #: model:ir.ui.menu,name:logistic_requisition.menu_logistic_requisition
 msgid "Requisitions"
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition,date_finance_officer:0
-msgid "Finance Officer Validation Date"
-msgstr ""
-
-#. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Internal (Federation)"
-msgstr ""
-
-#. module: logistic_requisition
-#: field:logistic.requisition.source,transport_applicable:0
-msgid "Transport Applicable"
-msgstr ""
-
-#. module: logistic_requisition
-#: field:logistic.requisition.source,purchase_requisition_line_ids:0
-msgid "Purchase Requisition Lines"
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:149
+msgid "Yes"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1115
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1120
+#, python-format
+msgid "Please correct selection"
+msgstr ""
+
+#. module: logistic_requisition
+#: field:logistic.requisition.source,offer_ids:0
+msgid "Sales Quotation Lines"
+msgstr ""
+
+#. module: logistic_requisition
+#: constraint:logistic.requisition.source:0
+msgid "A call for bids cannot be linked to lines of different logistics requisitions."
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:136
+msgid "Logistic requisition"
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:190
+msgid "Requesting entity"
 msgstr ""
 
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_purchase_order_line
-#: field:logistic.requisition.source,bid_line_id:0
 #: field:logistic.requisition.source,purchase_line_id:0
+#: field:logistic.requisition.source,selected_bid_line_id:0
 msgid "Purchase Order Line"
 msgstr ""
 
@@ -641,6 +776,12 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:521
+#, python-format
+msgid "line %s is not sourced"
+msgstr ""
+
+#. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_logistic_requisition_source_transport_plan
 msgid "Create a transport plan for logistic requisition source lines"
 msgstr ""
@@ -695,18 +836,13 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: field:purchase.requisition.line,logistic_requisition_source_ids:0
 #: view:transport.plan:0
 #: field:transport.plan,logistic_requisition_source_ids:0
 msgid "Logistic Requisition Source Lines"
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "External (NS, Others)"
-msgstr ""
-
-#. module: logistic_requisition
 #: field:logistic.requisition.source.transport.plan,transport_estimated_cost:0
 msgid "Transportation Estimated Costs"
 msgstr ""
@@ -742,16 +878,6 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:purchase.requisition.line,logistic_requisition_source_id:0
-msgid "Logistic Requisition Source Line"
-msgstr ""
-
-#. module: logistic_requisition
-#: view:logistic.requisition:0
-msgid "Validation"
-msgstr ""
-
-#. module: logistic_requisition
 #: help:logistic.requisition.source.transport.plan,date_eta:0
 msgid "Estimated Date of Arrival if not set requisition ETA will be used"
 msgstr ""
@@ -764,8 +890,14 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-msgid " validated on "
+#: code:addons/logistic_requisition/model/sale_order.py:45
+#, python-format
+msgid "The logistic requisition line %s has no purchase order line."
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:187
+msgid "Approval"
 msgstr ""
 
 #. module: logistic_requisition
@@ -780,6 +912,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: help:logistic.requisition,pricelist_id:0
+msgid "Pricelist that represent the currency for current logistic request."
+msgstr ""
+
+#. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_stock_incoterms
 msgid "Incoterms"
 msgstr ""
@@ -805,7 +942,6 @@
 
 #. module: logistic_requisition
 #: view:logistic.requisition:0
-#: field:logistic.requisition,partner_id:0
 msgid "Requesting Entity"
 msgstr ""
 
@@ -840,6 +976,17 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1044
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1052
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1059
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1066
+#: code:addons/logistic_requisition/model/sale_order.py:44
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:261
+#, python-format
+msgid "Error"
+msgstr ""
+
+#. module: logistic_requisition
 #: model:logistic.requisition.cancel.reason,name:logistic_requisition.cancel_reason_no_service_needed
 msgid "No service needed anymore"
 msgstr ""
@@ -851,11 +998,7 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition.source,unit_cost:0
-msgid "Unit Cost"
-msgstr ""
-
-#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:162
 #: view:logistic.requisition:0
 #: field:logistic.requisition.line,requested_qty:0
 msgid "Quantity"
@@ -883,11 +1026,8 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: field:logistic.requisition,requester_type:0
-#: view:logistic.requisition.line:0
-#: field:logistic.requisition.line,requester_type:0
-msgid "Type of Requestor"
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:160
+msgid "Number"
 msgstr ""
 
 #. module: logistic_requisition
@@ -896,6 +1036,12 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1091
+#, python-format
+msgid "Existing"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 #: selection:logistic.requisition.line,state:0
 #: selection:logistic.requisition.source,state:0
@@ -903,8 +1049,9 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition.line,budget_tot_price:0
-msgid "Budget Total Price"
+#: view:logistic.requisition.line:0
+#: view:logistic.requisition.source:0
+msgid "Total Budget"
 msgstr ""
 
 #. module: logistic_requisition
@@ -939,15 +1086,8 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: selection:logistic.requisition.source,price_is:0
-#: selection:sale.order.line,price_is:0
-msgid "Estimated"
-msgstr ""
-
-#. module: logistic_requisition
-#: model:ir.actions.act_window,name:logistic_requisition.action_logistic_requisition_cancel
-#: view:logistic.requisition.cancel:0
-msgid "Reason for the cancellation"
+#: field:purchase.order.line,po_line_from_bid_ids:0
+msgid "Lines generated by the bid"
 msgstr ""
 
 #. module: logistic_requisition
@@ -971,18 +1111,16 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: selection:logistic.requisition,requester_type:0
-#: selection:logistic.requisition.line,requester_type:0
-#: selection:res.partner,requester_type:0
-msgid "Federation (internal)"
-msgstr ""
-
-#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 msgid "Req. Date:"
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:182
+msgid "General Remarks"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition:0
 #: field:logistic.requisition,cost_estimate_only:0
 #: view:logistic.requisition.line:0
@@ -1006,8 +1144,8 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:res.partner,requester_type:0
-msgid "Requester Type"
+#: selection:logistic.requisition.source,procurement_method:0
+msgid "Other"
 msgstr ""
 
 #. module: logistic_requisition
@@ -1034,6 +1172,7 @@
 
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_purchase_requisition_line
+#: field:logistic.requisition.source,purchase_requisition_line_id:0
 msgid "Purchase Requisition Line"
 msgstr ""
 
@@ -1050,6 +1189,7 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:161
 #: field:logistic.requisition.line,description:0
 msgid "Description"
 msgstr ""
@@ -1061,9 +1201,9 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition:0
-#: view:logistic.requisition.line:0
-msgid "Requestor is the Federation"
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1053
+#, python-format
+msgid "The sourcing lines do not belong to the same company."
 msgstr ""
 
 #. module: logistic_requisition
@@ -1072,6 +1212,12 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1097
+#, python-format
+msgid "The sourcing line %d does not have any product defined, please choose one."
+msgstr ""
+
+#. module: logistic_requisition
 #: field:logistic.requisition.source.transport.plan,transport_mode_id:0
 msgid "Transport by"
 msgstr ""
@@ -1082,8 +1228,14 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: help:logistic.requisition.line,logistic_user_id:0
-msgid "User in charge of the Logistic Requisition Line"
+#: code:addons/logistic_requisition/model/logistic_requisition.py:632
+#, python-format
+msgid "Logistic Requisition Line %s Assigned"
+msgstr ""
+
+#. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:191
+msgid "Requested date"
 msgstr ""
 
 #. module: logistic_requisition
@@ -1092,8 +1244,8 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: field:logistic.requisition,allowed_budget:0
-msgid "Allowed Budget"
+#: field:logistic.requisition,partner_id:0
+msgid "Customer"
 msgstr ""
 
 #. module: logistic_requisition
@@ -1102,11 +1254,6 @@
 msgstr ""
 
 #. module: logistic_requisition
-#: help:logistic.requisition.line.assign,logistic_user_id:0
-msgid "Logistic Specialist in charge of the Logistic Requisition Line"
-msgstr ""
-
-#. module: logistic_requisition
 #: field:logistic.requisition,line_ids:0
 msgid "Products to Purchase"
 msgstr ""
@@ -1117,6 +1264,7 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:143
 #: view:logistic.requisition:0
 #: field:logistic.requisition,country_id:0
 #: view:logistic.requisition.line:0
@@ -1125,8 +1273,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:693
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:293
 #: view:logistic.requisition.cost.estimate:0
 #: field:logistic.requisition.line,cost_estimate_id:0
+#, python-format
 msgid "Cost Estimate"
 msgstr ""
 
@@ -1146,23 +1297,24 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:144
 #: view:logistic.requisition:0
 #: field:logistic.requisition,date:0
 msgid "Requisition Date"
 msgstr ""
 
 #. module: logistic_requisition
-#: view:logistic.requisition.line:0
-msgid "Total Proposed"
-msgstr ""
-
-#. module: logistic_requisition
 #: view:logistic.requisition.cancel:0
 msgid "Choose the reason for the cancellation of the\n"
 "                    logistic requisition."
 msgstr ""
 
 #. module: logistic_requisition
+#: field:logistic.requisition.source,proposed_product_id:0
+msgid "Proposed Product"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line.assign:0
 msgid "Select the assignee"
 msgstr ""
@@ -1170,6 +1322,7 @@
 #. module: logistic_requisition
 #: model:ir.model,name:logistic_requisition.model_logistic_requisition_source
 #: view:logistic.requisition.source:0
+#: field:purchase.order.line,lr_source_line_id:0
 msgid "Logistic Requisition Source"
 msgstr ""
 
@@ -1188,6 +1341,11 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:102
+msgid "Shipping address:"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.source.create.requisition:0
 msgid " Please note that: \n"
 " \n"
@@ -1208,7 +1366,13 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: report:addons/logistic_requisition/report/logistic_requisition.mako:178
+msgid "Delivery Remarks"
+msgstr ""
+
+#. module: logistic_requisition
 #: field:logistic.requisition.line,account_code:0
+#: field:sale.order.line,account_code:0
 msgid "Account Code"
 msgstr ""
 
@@ -1218,6 +1382,17 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: field:logistic.requisition.source.create.requisition,pricelist_id:0
+msgid "Pricelist / Currency"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1060
+#, python-format
+msgid "The sourcing lines do not have the same consignee."
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.cancel:0
 #: view:logistic.requisition.cost.estimate:0
 #: view:logistic.requisition.line.assign:0
@@ -1227,7 +1402,24 @@
 msgstr ""
 
 #. module: logistic_requisition
+#: view:logistic.requisition:0
+msgid "View Sourcing Lines"
+msgstr ""
+
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/model/logistic_requisition.py:1096
+#, python-format
+msgid "Missing information"
+msgstr ""
+
+#. module: logistic_requisition
 #: view:logistic.requisition.line:0
 msgid "Open Cost Estimate"
 msgstr ""
 
+#. module: logistic_requisition
+#: code:addons/logistic_requisition/wizard/cost_estimate.py:105
+#, python-format
+msgid "Transport from %s to %s by %s (Ref. %s)"
+msgstr ""
+ 

=== modified file 'logistic_requisition/model/logistic_requisition.py'
--- logistic_requisition/model/logistic_requisition.py	2013-11-01 09:32:02 +0000
+++ logistic_requisition/model/logistic_requisition.py	2014-03-10 15:39:56 +0000
@@ -158,40 +158,22 @@
             readonly=True,
             required=True
         ),
-        'amount_total': fields.function(
-            lambda self, *args, **kwargs: self._get_amount(*args, **kwargs),
-            digits_compute=dp.get_precision('Account'),
-            string='Total Budget',
-            store={
-                'logistic.requisition': (
-                    lambda self, cr, uid, ids, c=None: ids,
-                    ['line_ids'], 20),
-                'logistic.requisition.line': (
-                    lambda self, *a, **kw: self._store_get_requisition_ids(*a, **kw),
-                    ['requested_qty', 'budget_unit_price', 'budget_tot_price', 'requisition_id'], 20),
-            }),
         'sourced': fields.function(
             lambda self, *args, **kwargs: self._get_sourced(*args, **kwargs),
             string='Sourced',
             type='float'
         ),
-        'allowed_budget': fields.boolean('Allowed Budget'),
-        'currency_id': fields.related('company_id',
+        'pricelist_id': fields.many2one('product.pricelist',
+            'Pricelist',
+            required=True,
+            states=REQ_STATES,
+            help="Pricelist that represent the currency for current logistic request."),
+        'currency_id': fields.related('pricelist_id',
                                       'currency_id',
                                       type='many2one',
                                       relation='res.currency',
                                       string='Currency',
                                       readonly=True),
-        'budget_holder_id': fields.many2one(
-            'res.users',
-            string='Budget Holder'),
-        'date_budget_holder': fields.datetime(
-            'Budget Holder Validation Date'),
-        'finance_officer_id': fields.many2one(
-            'res.users',
-            string='Finance Officer'),
-        'date_finance_officer': fields.datetime(
-            'Finance Officer Validation Date'),
         'cancel_reason_id': fields.many2one(
             'logistic.requisition.cancel.reason',
             string='Reason for Cancellation',
@@ -214,13 +196,6 @@
          'Logistic Requisition Reference must be unique!'),
     ]
 
-    def _get_amount(self, cr, uid, ids, name, args, context=None):
-        res = {}
-        for requisition in self.browse(cr, uid, ids, context=context):
-            res[requisition.id] = sum(line.budget_tot_price for line
-                                      in requisition.line_ids)
-        return res
-
     def _get_sourced(self, cr, uid, ids, name, args, context=None):
         res = {}
         for requisition in self.browse(cr, uid, ids, context=context):
@@ -268,10 +243,6 @@
             line_obj = self.pool.get('logistic.requisition.line')
             line_obj._do_draft(cr, uid, line_ids, context=context)
         vals = {'state': 'draft',
-                'budget_holder_id': False,
-                'date_budget_holder': False,
-                'finance_officer_id': False,
-                'date_finance_officer': False,
                 'cancel_reason_id': False,
                 }
         self.write(cr, uid, ids, vals, context=context)
@@ -296,13 +267,24 @@
         default.update({
             'state': 'draft',
             'name': '/',
-            'budget_holder_id': False,
-            'date_budget_holder': False,
-            'finance_officer_id': False,
-            'date_finance_officer': False,
         })
         return super(logistic_requisition, self).copy(cr, uid, id, default=default, context=context)
 
+    def onchange_partner_id(self, cr, uid, ids, part, context=None):
+        """We take the pricelist of the chosen partner"""
+        values = {'pricelist_id': False}
+        if not part:
+            return {'value': values}
+
+        part = self.pool.get('res.partner').browse(cr, uid, part,
+                                                   context=context)
+        pricelist = part.property_product_pricelist
+        pricelist = pricelist.id if pricelist else False
+        values = {}
+        if pricelist:
+            values['pricelist_id'] = pricelist
+        return {'value': values}
+
     def onchange_consignee_id(self, cr, uid, ids, consignee_id, context=None):
         values = {'consignee_shipping_id': False}
         if not consignee_id:
@@ -425,13 +407,9 @@
                                             'Product UoM',
                                             states=REQUEST_STATES,
                                             required=True),
-        'budget_tot_price': fields.float(
-            'Budget Total Price',
-            states=REQUEST_STATES,
-            digits_compute=dp.get_precision('Account')),
-        'budget_unit_price': fields.function(
-            lambda self, *args, **kwargs: self._get_unit_amount_line(*args, **kwargs),
-            string='Budget Unit Price',
+        'amount_total': fields.function(
+            lambda self, *args, **kwargs: self._get_total_cost(*args, **kwargs),
+            string='Total Amount',
             type="float",
             digits_compute=dp.get_precision('Account'),
             store=True),
@@ -572,11 +550,13 @@
                          context=context, load='_classic_write')
         return list(set([x['requisition_id'] for x in reqs]))
 
-    def _get_unit_amount_line(self, cr, uid, ids, prop, unknow_none, unknow_dict, context=None):
+    def _get_total_cost(self, cr, uid, ids, name, args, context=None):
         res = {}
+        for i in ids:
+            res[i] = 0.0
         for line in self.browse(cr, uid, ids, context=context):
-            price = line.budget_tot_price / line.requested_qty
-            res[line.id] = price
+            for source_line in line.source_ids:
+                res[line.id] += source_line.total_cost
         return res
 
     def view_stock_by_location(self, cr, uid, ids, context=None):
@@ -749,25 +729,6 @@
                       'quoted': [('readonly', True)]
                       }
 
-    def _purchase_line_id(self, cr, uid, ids, field_name, arg, context=None):
-        """ For each line, returns the generated purchase line from the
-        purchase requisition.
-        """
-        result = {}
-        for line in self.browse(cr, uid, ids, context=context):
-            result[line.id] = False
-            bid_line = line.bid_line_id
-            if not bid_line:
-                continue
-            po_lines = bid_line.po_line_from_bid_ids
-            if not po_lines:
-                continue
-            assert len(po_lines) == 1, (
-                "We should not have several purchase order lines "
-                "for a logistic requisition line")
-            result[line.id] = po_lines[0].id if po_lines else False
-        return result
-
     def _default_source_address(self, cr, uid, ids, field_name, arg, context=None):
         """Return the default source address depending of the procurment method"""
         res = {}
@@ -818,6 +779,7 @@
             [('procurement', 'Procurement'),
              ('wh_dispatch', 'Warehouse Dispatch'),
              ('fw_agreement', 'Framework Agreement'),
+             ('other', 'Other'),
              ],
             string='Procurement Method',
             required=True,
@@ -859,6 +821,12 @@
             type='float',
             digits_compute=dp.get_precision('Account'),
             store=True),
+        'currency_id': fields.related('requisition_id',
+                                      'currency_id',
+                                      type='many2one',
+                                      relation='res.currency',
+                                      string='Currency',
+                                      readonly=True),
         'transport_applicable': fields.boolean(
             'Transport Applicable',
             states=SOURCED_STATES),
@@ -928,6 +896,8 @@
         'transport_applicable': False,
         'price_is': 'fixed',
         'name': '/',
+        'procurement_method': 'other',
+        'proposed_qty': 1
     }
     _constraints = [
         (lambda self, *a, **kw: self._check_transport_plan(*a, **kw),
@@ -938,9 +908,6 @@
          "A transport plan cannot be linked to lines of different "
          "logistic requisitions.",
          ['transport_plan_id', 'requisition_id']),
-        (lambda self, *a, **kw: self._check_source_lines_total_amount(*a, **kw),
-         'The total cost cannot be more than the total budget.',
-         ['proposed_qty', 'unit_cost', 'requisition_line_id']),
         (lambda self, *a, **kw: self._check_purchase_requisition_unique(*a, **kw),
          "A call for bids cannot be linked to lines of different "
          "logistics requisitions.",
@@ -955,10 +922,16 @@
             return False
         return True
 
+    def _is_sourced_other(self, cr, uid, source, context=None):
+        """Predicate function to test if line on other
+        method are sourced"""
+        return self._is_sourced_procurement(cr, uid, source,
+                                            context=context)
+
     def _is_sourced_wh_dispatch(self, cr, uid, source, context=None):
-       """Predicate function to test if line on warehouse
-       method are sourced"""
-       return True
+        """Predicate function to test if line on warehouse
+        method are sourced"""
+        return True
 
     def _is_sourced(self, cr, uid, source_id, context=None):
         """ check if line is source using predicate function
@@ -1011,32 +984,32 @@
                         return False
         return True
 
-    def _check_source_lines_total_amount(self, cr, uid, ids, context=None):
-        for source in self.browse(cr, uid, ids, context=context):
-            line = source.requisition_line_id
-            total = sum(source.unit_cost * source.proposed_qty
-                        for source in line.source_ids)
-            if total > line.budget_tot_price:
-                return False
-        return True
-
     def _get_purchase_line_id(self, cr, uid, ids, field_name, arg, context=None):
         """ For each line, returns the generated purchase line from the
         purchase requisition.
         """
         result = {}
+        po_line_model = self.pool['purchase.order.line']
+        po_lines = None
         for line in self.browse(cr, uid, ids, context=context):
             result[line.id] = False
-            bid_line = line.selected_bid_line_id
-            if not bid_line:
-                continue
-            po_lines = bid_line.po_line_from_bid_ids
-            if not po_lines:
-                continue
+            if line.selected_bid_line_id:
+                bid_line = line.selected_bid_line_id
+                if not bid_line:
+                    continue
+                po_lines = [x.id for x in bid_line.po_line_from_bid_ids]
+                if not po_lines:
+                    continue
+            else:
+                po_lines = po_line_model.search(cr, uid,
+                                                [('lr_source_line_id', '=', line.id),
+                                                 ('state', '!=', 'cancel')],
+                                                context=context)
             assert len(po_lines) == 1, (
                 "We should not have several purchase order lines "
                 "for a logistic requisition line")
-            result[line.id] = po_lines[0].id if po_lines else False
+            result[line.id] = po_lines[0] if po_lines else False
+
         return result
 
     def create(self, cr, uid, vals, context=None):
@@ -1046,7 +1019,18 @@
         return super(logistic_requisition_source, self).create(cr, uid, vals,
                                                                context=context)
 
-    def _prepare_po_requisition(self, cr, uid, sources, purch_req_lines, context=None):
+    def _get_purchase_pricelist_from_currency(self, cr, uid, currency_id, context=None):
+        """ This method will look for a pricelist of type 'purchase' using
+        the same currency than than the given one.
+        return : ID of product.pricelist type Integer
+        """
+        pricelist_obj = self.pool.get('product.pricelist')
+        pricelist_id = pricelist_obj.search(cr, uid,
+            [('currency_id','=',currency_id),('type','=','purchase')], limit=1)
+        return pricelist_id[0]
+
+    def _prepare_po_requisition(self, cr, uid, sources, purch_req_lines,
+            pricelist=None, context=None):
         company_id = None
         user_id = None
         consignee_id = None
@@ -1084,12 +1068,24 @@
                     _('Error'),
                     _('The sourcing lines do not have the '
                       'same delivery address.'))
+            line_pricelist_id = self._get_purchase_pricelist_from_currency(
+                cr,
+                uid,
+                line.requisition_id.pricelist_id.currency_id.id,
+                context=context
+                )
+            if pricelist is None:
+                pricelist = line_pricelist_id
         return {'user_id': user_id or uid,
                 'company_id': company_id,
                 'consignee_id': consignee_id,
                 'dest_address_id': dest_address_id,
                 'line_ids': [(0, 0, rline) for rline in purch_req_lines],
                 'origin': ", ".join(origin),
+                'req_incoterm_id': line.requisition_id.incoterm_id.id,
+                'req_incoterm_address': line.requisition_id.incoterm_address,
+                'pricelist_id': pricelist,
+                'schedule_date': line.requisition_id.date_delivery,
                 }
 
     def _prepare_po_requisition_line(self, cr, uid, line, context=None):
@@ -1111,17 +1107,27 @@
                 'logistic_requisition_source_ids': [(4, line.id)],
                 }
 
-    def _action_create_po_requisition(self, cr, uid, ids, context=None):
+    def _action_create_po_requisition(self, cr, uid, ids, pricelist=None, context=None):
         purch_req_obj = self.pool.get('purchase.requisition')
         purch_req_lines = []
         lines = self.browse(cr, uid, ids, context=context)
+        if not next((x for x in lines
+                     if x.procurement_method == 'procurement'), None):
+            raise orm.except_orm(_('There should be at least one selected'
+                                   ' line with procurement method Procurement'),
+                                 _('Please correct selection'))
         for line in lines:
+            if line.procurement_method not in ('other', 'procurement'):
+                raise orm.except_orm(_('Selected line procurement method should'
+                                       ' be procurement or other'),
+                                     _('Please correct selection'))
             vals = self._prepare_po_requisition_line(cr, uid, line,
                                                      context=context)
             purch_req_lines.append(vals)
         vals = self._prepare_po_requisition(cr, uid,
                                             lines,
                                             purch_req_lines,
+                                            pricelist=pricelist,
                                             context=context)
         purch_req_id = purch_req_obj.create(cr, uid, vals, context=context)
         self.write(cr, uid, ids,
@@ -1129,8 +1135,10 @@
                    context=context)
         return purch_req_id
 
-    def action_create_po_requisition(self, cr, uid, ids, context=None):
-        self._action_create_po_requisition(cr, uid, ids, context=context)
+    def action_create_po_requisition(self, cr, uid, ids,
+            pricelist=None, context=None):
+        self._action_create_po_requisition(cr, uid, ids,
+                pricelist=pricelist, context=context)
         return self.action_open_po_requisition(cr, uid, ids, context=context)
 
     def action_open_po_requisition(self, cr, uid, ids, context=None):

=== modified file 'logistic_requisition/model/purchase.py'
--- logistic_requisition/model/purchase.py	2013-09-20 07:12:14 +0000
+++ logistic_requisition/model/purchase.py	2014-03-10 15:39:56 +0000
@@ -21,11 +21,35 @@
 
 from openerp.osv import orm, fields
 from openerp import netsvc
+from openerp.tools.translate import _
 
 
 class purchase_order(orm.Model):
     _inherit = 'purchase.order'
 
+    def validate_service_product_procurement(self, cr, uid, ids, context=None):
+        """ As action_picking_create only take care of non-service product
+        by looping on the moves, we need then to pass through all line with
+        product of type service and confirm them.
+        This way all procurements will reach the done state once the picking
+        related to the PO will be done and in the mean while the SO will be
+        then marked as delivered.
+        """
+        wf_service = netsvc.LocalService("workflow")
+        proc_obj = self.pool.get('procurement.order')
+        # Proc product of type service should be confirm at this
+        # stage, otherwise, when picking of related PO is created
+        # then done, it stay blocked at running stage
+        proc_ids = proc_obj.search(cr, uid, [('purchase_id', 'in', ids)],
+                                   context=context)
+        for proc in proc_obj.browse(cr, uid, proc_ids, context=context):
+            if proc.product_id.type == 'service':
+                wf_service.trg_validate(uid, 'procurement.order',
+                                        proc.id, 'button_confirm', cr)
+                wf_service.trg_validate(uid, 'procurement.order',
+                                        proc.id, 'button_check', cr)
+        return True
+
     def action_picking_create(self, cr, uid, ids, context=None):
         """ When the picking is created, we'll:
 
@@ -62,7 +86,7 @@
                 if purchase_line is not None:
                     wf_service.trg_validate(uid, 'procurement.order',
                                             procurement.id, 'button_check', cr)
-
+        self.validate_service_product_procurement(cr, uid, ids, context)
         return picking_id
 
 
@@ -85,3 +109,93 @@
             'Lines generated by the bid',
             readonly=True),
     }
+
+    def _prepare_lrs_update_from_po_line(self, cr, uid, vals,
+            po_line, context=None):
+        """ Take the vals dict from po line and return a vals dict for LRS
+
+        :param dict vals: value of to be written in new po line
+        :param browse_record po_line: purchase.order.line
+        :returns dict : vals to be written on logistic.requisition.source
+
+        """
+        lrs_vals = {}
+        if vals.get('product_qty'):
+            lrs_vals['proposed_qty'] = vals.get('product_qty')
+        if vals.get('product_id'):
+            lrs_vals['proposed_product_id'] = vals.get('product_id')
+        if vals.get('product_uom'):
+            lrs_vals['proposed_uom_id'] = vals.get('product_uom')
+        if vals.get('price_unit'):
+            currency_obj = self.pool['res.currency']
+            to_curr = po_line.lr_source_line_id.requisition_id.currency_id.id
+            from_curr = po_line.order_id.pricelist_id.currency_id.id
+            price = currency_obj.compute(cr, uid, from_curr, to_curr,
+                    vals.get('price_unit'), False)
+            lrs_vals['unit_cost'] = price
+        if vals.get('date_planned'):
+            if po_line.lr_source_line_id.transport_applicable:
+                if pr_bid_line.order_id.transport == 'included':
+                    lrs_vals['date_etd'] = False
+                    lrs_vals['date_eta'] = vals.get('date_planned')
+
+                else:
+                    lrs_vals['date_etd'] = vals.get('date_planned')
+                    lrs_vals['date_eta'] = False
+            else:
+                lrs_vals['date_etd'] = vals.get('date_planned')
+                lrs_vals['date_eta'] = vals.get('date_planned')
+        return lrs_vals
+
+    def write(self, cr, uid, ids, vals, context=None):
+        """ Here we implement something to allow the update of LRS when some
+        information are changed in PO line. It should be possible to do it when :
+        PO is still in draft
+        LRL is not marked as sourced
+        Once done, nobody should be able to change the PO line infos
+        """
+        if context is None:
+            context = {}
+        if not ids:
+            return True
+        #We have to enforce list as it is called by function_inv
+        if not isinstance(ids, list):
+            ids = [ids]
+        if (vals.get('product_qty') or vals.get('product_id')
+                                    or vals.get('product_uom')
+                                    or vals.get('price_unit')
+                                    or vals.get('date_planned')):
+            lrs_obj = self.pool.get('logistic.requisition.source')
+            for line in self.browse(cr, uid, ids, context=context):
+                if line.lr_source_line_id:
+                    if (line.lr_source_line_id.requisition_line_id in
+                                                ('sourced', 'quoted')):
+                        raise osv.except_osv(
+                            _('UserError'),
+                            _(
+                                "You cannot change the informations because this PO line "
+                                "is already linked to a Logistic Requsition Line %s marked "
+                                "as sourced or quoted." % (line.lr_source_line_id.name)
+                            )
+                    )
+                    else:
+                        lrs_vals = self._prepare_lrs_update_from_po_line(cr,
+                            uid, vals, line, context=context)
+                        lrs_obj.write(cr, uid, [line.lr_source_line_id.id],
+                            lrs_vals, context=context)
+        return super(purchase_order_line, self).write(cr, uid, ids, vals,
+                                                      context=context)
+    def unlink(self, cr, uid, ids, context=None):
+        for line in self.browse(cr, uid, ids, context=context):
+            if line.lr_source_line_id:
+                if (line.lr_source_line_id.requisition_line_id in
+                                            ('sourced', 'quoted')):
+                    raise osv.except_osv(
+                        _('UserError'),
+                        _(
+                            "You cannot delete this PO line because it is "
+                            "already linked to a Logistic Requsition Line %s marked "
+                            "as sourced or quoted." % (line.lr_source_line_id.name)
+                        )
+                )
+        return super(purchase_order_line, self).unlink(cr, uid, ids, context=context)

=== modified file 'logistic_requisition/model/purchase_requisition.py'
--- logistic_requisition/model/purchase_requisition.py	2013-11-01 09:05:44 +0000
+++ logistic_requisition/model/purchase_requisition.py	2014-03-10 15:39:56 +0000
@@ -31,6 +31,7 @@
         For each selected bid line, we ensure there is a corresponding source
         (one2one relation) and we update the source data with the bid line data.
         """
+        currency_obj = self.pool['res.currency']
         if isinstance(id, (tuple, list)):
             assert len(id) == 1, (
                 "_split_requisition_source_lines() accepts only 1 ID, "
@@ -43,16 +44,24 @@
                 # this call for bid line has been added manually
                 continue
             source = pr_line.logistic_requisition_source_ids[0]
+            has_requisition = source.requisition_id
+            if not has_requisition:
+                continue
+            to_curr = source.requisition_id.currency_id.id
             set_sources = set()
             # Look for po lines of this purchase_requisition line
             for pr_bid_line in pr_line.purchase_line_ids:
+                # Compute from bid currency to LRS currency
+                from_curr = pr_bid_line.order_id.pricelist_id.currency_id.id
+                price = currency_obj.compute(cr, uid, from_curr, to_curr,
+                    pr_bid_line.price_unit, False)
                 vals = {
                     'price_is': 'fixed',
                     'proposed_qty': pr_bid_line.quantity_bid,
                     'proposed_product_id': pr_bid_line.product_id.id,
                     'proposed_uom_id': pr_bid_line.product_uom.id,
                     'selected_bid_line_id': pr_bid_line.id,
-                    'unit_cost': pr_bid_line.price_unit,
+                    'unit_cost': price,
                     #FIXME: we need to take care of the scheduled date
                     # set eta or etd depending if transport is included
                     }
@@ -119,19 +128,6 @@
         vals['from_bid_line_id'] = line.id
         return vals
 
-    #FIXME: we should not do that, the location must be known from the beginning of the RFQ-Bid process
-    #def _prepare_purchase_order(self, cr, uid, requisition, supplier, context=None):
-    #    vals = super(purchase_requisition, self)._prepare_purchase_order(
-    #        cr, uid, requisition, supplier, context=context)
-    #    if requisition.logistic_requisition_source_ids:
-    #        # comes from a logistic.requisition -> generate direct
-    #        # delivery purchases, so we put the location customer
-    #        # of the first consignee_id (same consignee on all lines)
-    #        source = requisition.logistic_requisition_source_ids[0]
-    #        req = source.requisition_id
-    #        vals['location_id'] = req.consignee_id.property_stock_customer.id
-    #    return vals
-
 
 class purchase_requisition_line(orm.Model):
     _inherit = 'purchase.requisition.line'

=== modified file 'logistic_requisition/model/sale_order.py'
--- logistic_requisition/model/sale_order.py	2013-09-10 11:08:34 +0000
+++ logistic_requisition/model/sale_order.py	2014-03-10 15:39:56 +0000
@@ -72,7 +72,6 @@
             # with it
             vals['purchase_id'] = purchase_line.order_id.id
             proc_id = proc_obj.create(cr, uid, vals, context=context)
-
             sale_line.write({'procurement_id': proc_id})
             # We do not confirm the procurement. It will stay in 'draft'
             # without reservation move. At the moment when the picking
@@ -80,6 +79,8 @@
             # the id of the picking's move in this procurement and
             # confirm the procurement
             # (see in purchase_order.action_picking_create())
+            # In there, we'll also take care and confirm all procurements
+            # with product of type service.
 
         # set the purchases to direct delivery
         purchase_obj = self.pool.get('purchase.order')
@@ -133,6 +134,14 @@
                 cr, uid, order, list(lines), picking_id=False, context=context)
         return True
 
+    def copy(self, cr, uid, id, default=None, context=None):
+        if not default:
+            default = {}
+        default['invoice_ids'] = False
+        default['requisition_id'] = False
+        return super(sale_order, self).copy(cr, uid, id,
+                                            default=default, context=context)
+
 
 class sale_order_line(orm.Model):
     _inherit = "sale.order.line"

=== modified file 'logistic_requisition/report/logistic_requisition.mako'
--- logistic_requisition/report/logistic_requisition.mako	2013-08-14 14:26:08 +0000
+++ logistic_requisition/report/logistic_requisition.mako	2014-03-10 15:39:56 +0000
@@ -197,29 +197,6 @@
             <td>&nbsp;</td>
         </tr>
     </table>
-    <p><b>${_("Budget")}</b></p>
-    <p>${_("Budget limit:")} ${formatLang(requisition.allowed_budget)}</p>
-    <table class="basic_table" width="100%">
-        <tr>
-            <td style="font-weight:bold;width:40%">${_("Budget/financial holder")}</td>
-            <td style="font-weight:bold;width:30%">${_("Validation date")}</td>
-            <td style="font-weight:bold;">${_("Signature")}</td>
-        </tr>
-        %if requisition.budget_holder_id:
-        <tr>
-            <td>${requisition.budget_holder_id.name}</td>
-            <td>${requisition.date_budget_holder if requisition.date_budget_holder else 'N/A'}</td>
-            <td>&nbsp;</td>
-        </tr>
-        %endif
-        %if requisition.finance_officer_id:
-        <tr>
-            <td>${requisition.finance_officer_id.name}</td>
-            <td>${requisition.date_finance_officer if requisition.date_finance_officer else 'N/A'}</td>
-            <td>&nbsp;</td>
-        </tr>
-        %endif
-    </table>
     <p style="page-break-after: always"/>
     %endfor
 </body>

=== modified file 'logistic_requisition/security/ir.model.access.csv'
--- logistic_requisition/security/ir.model.access.csv	2013-08-06 14:04:56 +0000
+++ logistic_requisition/security/ir.model.access.csv	2014-03-10 15:39:56 +0000
@@ -3,3 +3,5 @@
 access_logistic_requisition_line_purchase_user,logistic.requisition.line,model_logistic_requisition_line,purchase.group_purchase_user,1,1,1,1
 access_logreq_cancel_reason_user,access_logistic_requisition_cancel_reason user,model_logistic_requisition_cancel_reason,purchase.group_purchase_user,1,0,0,0
 access_logreq_cancel_reason_manager,access_logistic_requisition_cancel_reason manager,model_logistic_requisition_cancel_reason,purchase.group_purchase_manager,1,1,1,1
+access_log_cost_create_user,logistic.requisition.cost.estimate,model_logistic_requisition_cost_estimate,base.group_sale_salesman,1,1,1,1
+access_log_cost_create_manager,logistic.requisition.cost.estimate,model_logistic_requisition_cost_estimate,base.group_sale_manager,1,1,1,1

=== modified file 'logistic_requisition/test/line_assigned.yml'
--- logistic_requisition/test/line_assigned.yml	2013-08-26 18:20:48 +0000
+++ logistic_requisition/test/line_assigned.yml	2014-03-10 15:39:56 +0000
@@ -6,6 +6,7 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
+    pricelist_id: product.list0
 -
   And I add a line with an assignee
 -
@@ -14,7 +15,6 @@
     product_id: product.product_product_7
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a line without assignee
@@ -24,7 +24,6 @@
     product_id: product.product_product_8
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
 -
   When I confirm the logistic requisition
 -

=== modified file 'logistic_requisition/test/logistic_requisition_report_test.yml'
--- logistic_requisition/test/logistic_requisition_report_test.yml	2013-08-27 14:33:41 +0000
+++ logistic_requisition/test/logistic_requisition_report_test.yml	2014-03-10 15:39:56 +0000
@@ -8,11 +8,11 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
+    pricelist_id: product.list0
     line_ids:
       - product_id: product.product_product_7
         requested_qty: 100
         date_delivery: !eval "time.strftime('%Y-%m-%d')"
-        budget_tot_price: 1000
         logistic_user_id: base.user_demo
         account_code: 'Shazam!'
 -

=== modified file 'logistic_requisition/test/requisition_cancel_reason.yml'
--- logistic_requisition/test/requisition_cancel_reason.yml	2013-08-06 14:04:56 +0000
+++ logistic_requisition/test/requisition_cancel_reason.yml	2014-03-10 15:39:56 +0000
@@ -12,6 +12,7 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
+    pricelist_id: product.list0
 -
   When I cancel it with the wizard asking for the reason
 -

=== modified file 'logistic_requisition/test/requisition_create_cost_estimate.yml'
--- logistic_requisition/test/requisition_create_cost_estimate.yml	2013-11-01 11:17:26 +0000
+++ logistic_requisition/test/requisition_create_cost_estimate.yml	2014-03-10 15:39:56 +0000
@@ -9,6 +9,7 @@
     incoterm_id: stock.incoterm_FCA
     incoterm_address: incoterm address as text
     analytic_id: account.analytic_consultancy
+    pricelist_id: product.list0
 -
   And I add a line 1
 -
@@ -18,7 +19,6 @@
     requested_qty: 100
     requested_uom_id: product.product_uom_unit
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a source line to the line 1
@@ -42,7 +42,6 @@
     requested_qty: 100
     requested_uom_id: product.product_uom_unit
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a source line to the line 2
@@ -88,8 +87,6 @@
     try:
         self.cost_estimate(cr, uid, wizard_id)
     except orm.except_orm as err:
-        assert 'NO_BUDGET_VALID' in err.error_codes, (
-                'Expected an error because the budget holder is missing')
         assert 'NO_ACCOUNT_CODE' in err.error_codes, (
                 'Expected an error because the account code is missing')
     else:
@@ -97,9 +94,6 @@
 -
   I set some data to fulfill the business rules
 -
-  !record {model: logistic.requisition, id: logistic_requisition_cost_estimate_01}:
-    budget_holder_id: base.user_demo
--
   !record {model: logistic.requisition.line, id: logistic_requisition_line_cost_estimate_01}:
     account_code: 'XXXX'
 -

=== modified file 'logistic_requisition/test/transport_plan.yml'
--- logistic_requisition/test/transport_plan.yml	2013-11-01 11:17:26 +0000
+++ logistic_requisition/test/transport_plan.yml	2014-03-10 15:39:56 +0000
@@ -23,6 +23,7 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
+    pricelist_id: product.list0
 -
   And I add a line 1
 -
@@ -31,7 +32,6 @@
     product_id: product.product_product_7
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a source line 1
@@ -52,7 +52,6 @@
     product_id: product.product_product_8
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a source line 2
@@ -93,6 +92,7 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
+    pricelist_id: product.list0
 -
   With a line
 -
@@ -101,7 +101,6 @@
     product_id: product.product_product_7
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a source line

=== modified file 'logistic_requisition/test/transport_plan_from_lr_line_wizard.yml'
--- logistic_requisition/test/transport_plan_from_lr_line_wizard.yml	2013-11-01 11:17:26 +0000
+++ logistic_requisition/test/transport_plan_from_lr_line_wizard.yml	2014-03-10 15:39:56 +0000
@@ -7,6 +7,7 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
+    pricelist_id: product.list0
 -
   And I add a first line with an assignee
 -
@@ -15,7 +16,6 @@
     product_id: product.product_product_7
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a first source line
@@ -34,7 +34,6 @@
     product_id: product.product_product_8
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
 -
   And I add a second source line

=== modified file 'logistic_requisition/test/transport_plan_to_cost_estimate.yml'
--- logistic_requisition/test/transport_plan_to_cost_estimate.yml	2013-11-01 11:17:26 +0000
+++ logistic_requisition/test/transport_plan_to_cost_estimate.yml	2014-03-10 15:39:56 +0000
@@ -27,8 +27,7 @@
     consignee_id: base.res_partner_3
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
     user_id: base.user_demo
-    budget_holder_id: base.user_demo
-    finance_officer_id: base.user_demo
+    pricelist_id: product.list0
 -
   And I add a line 1
 -
@@ -37,7 +36,6 @@
     product_id: product.product_product_7
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
     account_code: 'XXXX'
 -
@@ -60,7 +58,6 @@
     product_id: product.product_product_8
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
     account_code: 'YYYY'
 -
@@ -83,7 +80,6 @@
     product_id: product.product_product_8
     requested_qty: 100
     date_delivery: !eval "time.strftime('%Y-%m-%d')"
-    budget_tot_price: 1000
     logistic_user_id: base.user_demo
     account_code: 'ZZZZ'
 -

=== modified file 'logistic_requisition/tests/__init__.py'
--- logistic_requisition/tests/__init__.py	2013-08-27 14:13:33 +0000
+++ logistic_requisition/tests/__init__.py	2014-03-10 15:39:56 +0000
@@ -22,6 +22,7 @@
 from . import test_sale_order_from_lr_confirm
 from . import test_mto_workflow
 from . import transport_plan_date
+from . import test_mutlicurrency_update_po_line
 
 
 fast_suite = [
@@ -32,4 +33,5 @@
     test_sale_order_from_lr_confirm,
     test_mto_workflow,
     transport_plan_date,
+    test_mutlicurrency_update_po_line,
 ]

=== modified file 'logistic_requisition/tests/logistic_requisition.py'
--- logistic_requisition/tests/logistic_requisition.py	2013-11-01 11:17:26 +0000
+++ logistic_requisition/tests/logistic_requisition.py	2014-03-10 15:39:56 +0000
@@ -43,20 +43,6 @@
         log_req_obj.onchange_consignee_id(
             cr, uid, [], vals.get('consignee_id'))['value']
     )
-    vals.update(
-        log_req_obj.onchange_validate(
-            cr, uid, [],
-            vals.get('budget_holder_id'),
-            False,
-            'date_budget_holder')['value']
-    )
-    vals.update(
-        log_req_obj.onchange_validate(
-            cr, uid, [],
-            vals.get('finance_officer_id'),
-            False,
-            'date_finance_officer')['value']
-    )
     return log_req_obj.create(cr, uid, vals)
 
 
@@ -135,6 +121,24 @@
     log_req_line_obj.button_sourced(test.cr, test.uid, line_ids)
 
 
+def check_line_unit_cost(test, line_id, bid_price, bid_pricelist):
+    cr, uid = test.cr, test.uid
+    log_req_source_obj = test.registry('logistic.requisition.source')
+    pricelist_obj = test.registry('product.pricelist')
+    currency_obj = test.registry('res.currency')
+    lrs = log_req_source_obj.browse(cr, uid, line_id)
+    pricelist = pricelist_obj.browse(cr, uid, bid_pricelist)
+    to_curr = lrs.requisition_id.currency_id.id
+    from_curr = pricelist.currency_id.id
+    price = currency_obj.compute(cr, uid, from_curr, to_curr,
+            bid_price, False)
+    test.assertEquals(lrs.unit_cost,
+                      price,
+                      "The unit cost of the LRS should be the selected "
+                      "bid value converted regarding the different currency")
+
+
+
 def create_quotation(test, requisition_id, line_ids):
     """ Create the quotation / cost estimate (sale.order)
 
@@ -174,10 +178,10 @@
     return sale_id, sale_line_ids
 
 
-def create_purchase_requisition(test, source_id):
+def create_purchase_requisition(test, source_id, pricelist=None):
     """ Create a purchase requisition for a logistic requisition line """
     log_req_source_obj = test.registry('logistic.requisition.source')
     purch_req_id = log_req_source_obj._action_create_po_requisition(
-        test.cr, test.uid, [source_id])
+        test.cr, test.uid, [source_id], pricelist=pricelist)
     assert purch_req_id
     return purch_req_id

=== modified file 'logistic_requisition/tests/purchase_requisition.py'
--- logistic_requisition/tests/purchase_requisition.py	2013-08-27 14:13:33 +0000
+++ logistic_requisition/tests/purchase_requisition.py	2014-03-10 15:39:56 +0000
@@ -45,6 +45,12 @@
     purch_req_obj.close_callforbids_ok(test.cr, test.uid,
                                        [purchase_requisition_id])
 
+def change_pricelist(test, purchase_requisition_id, pricelist_id):
+    """ Change the pricelist """
+    purch_req_obj = test.registry('purchase.requisition')
+    purch_req_obj.write(test.cr, test.uid, [purchase_requisition_id],
+        {'pricelist_id': pricelist_id})
+
 
 def create_draft_purchase_order(test, purchase_requisition_id, partner_id):
     """ Create a draft purchase order for a purchase requisition.

=== modified file 'logistic_requisition/tests/test_mto_workflow.py'
--- logistic_requisition/tests/test_mto_workflow.py	2013-11-01 11:17:26 +0000
+++ logistic_requisition/tests/test_mto_workflow.py	2014-03-10 15:39:56 +0000
@@ -80,20 +80,19 @@
         self.product_7 = self.ref('product.product_product_7')
         self.product_8 = self.ref('product.product_product_8')
         self.product_uom_pce = self.ref('product.product_uom_unit')
+        self.pricelist_sale = self.ref('product.list0')
         self.vals = {
             'partner_id': self.partner_4,
             'consignee_id': self.partner_3,
             'date_delivery': time.strftime(D_FMT),
             'user_id': self.user_demo,
-            'budget_holder_id': self.user_demo,
-            'finance_officer_id': self.user_demo,
+            'pricelist_id' : self.pricelist_sale,
         }
         self.line = {
             'product_id': self.product_7,
             'requested_qty': 100,
             'requested_uom_id': self.product_uom_pce,
             'date_delivery': time.strftime(D_FMT),
-            'budget_tot_price': 1000,
             'account_code': 'a code',
             'source_ids': [{'proposed_qty': 100,
                             'proposed_product_id': self.product_7,
@@ -223,7 +222,6 @@
             'requested_qty': 200,
             'requested_uom_id': self.product_uom_pce,
             'date_delivery': time.strftime(D_FMT),
-            'budget_tot_price': 4000,
             'account_code': 'a code',
             'source_ids': [{'proposed_qty': 200,
                             'proposed_product_id': self.product_8,

=== added file 'logistic_requisition/tests/test_mutlicurrency_update_po_line.py'
--- logistic_requisition/tests/test_mutlicurrency_update_po_line.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition/tests/test_mutlicurrency_update_po_line.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Guewen Baconnier
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+import unittest2
+from functools import partial
+
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as D_FMT
+import openerp.tests.common as common
+from . import logistic_requisition
+from . import purchase_requisition
+from . import purchase_order
+
+
+class test_sale_order_from_lr_confirm(common.TransactionCase):
+    """ Test the multi-currency in the LR -> PO -> LRS process
+    and ensure that updating the PO line update properly the LRS values
+    while there still not marked as sourced or quoted.
+    """
+
+    def setUp(self):
+        super(test_sale_order_from_lr_confirm, self).setUp()
+        self.purch_req_model = self.registry('purchase.requisition')
+        self.log_req_model = self.registry('logistic.requisition')
+        self.log_req_line_model = self.registry('logistic.requisition.line')
+        self.sale_model = self.registry('sale.order')
+        self.purchase_model = self.registry('purchase.order')
+        data_model = self.registry('ir.model.data')
+        self.get_ref = partial(data_model.get_object_reference,
+                               self.cr, self.uid)
+        __, self.partner_1 = self.get_ref('base', 'res_partner_1')
+        __, self.partner_3 = self.get_ref('base', 'res_partner_3')
+        __, self.partner_4 = self.get_ref('base', 'res_partner_4')
+        __, self.user_demo = self.get_ref('base', 'user_demo')
+        __, self.lr_currency_usd = self.get_ref('base', 'USD')
+        __, self.purchase_pricelist_eur = self.get_ref('purchase', 'list0')
+        __, self.pricelist_sale = self.get_ref('product', 'list0')
+        # Computer Case: make_to_order
+        __, self.product_16 = self.get_ref('product', 'product_product_16')
+        __, self.product_uom_pce = self.get_ref('product', 'product_uom_unit')
+        self.vals = {
+            'partner_id': self.partner_4,
+            'consignee_id': self.partner_3,
+            'date_delivery': time.strftime(D_FMT),
+            'user_id': self.user_demo,
+            'currency_id': self.lr_currency_usd,
+            'pricelist_id': self.pricelist_sale,
+        }
+
+        self.line1 = {
+            'product_id': self.product_16,  # MTO
+            'requested_qty': 100,
+            'requested_uom_id': self.product_uom_pce,
+            'date_delivery': time.strftime(D_FMT),
+            'account_code': '1234',
+        }
+        self.source1 = {
+            'proposed_qty': 100,
+            'proposed_product_id': self.product_16,
+            'proposed_uom_id': self.product_uom_pce,
+            'unit_cost': 10,
+            'transport_applicable': 0,
+            'procurement_method': 'procurement',
+            'price_is': 'estimated',
+        }
+
+    def test_lrs_price_from_po_price_multicurrency(self):
+        """ The purchase requisition must generate the purchase orders on confirmation of sale order.
+
+        When a logistic requisition creates a sale order with MTO lines,
+        the confirmation of the lines should generates the purchase
+        orders on the purchase requisition linked to the logistic
+        requisition lines.
+
+        The price from USD to EUr should be respected.
+        """
+        cr, uid = self.cr, self.uid
+        requisition_id = logistic_requisition.create(self, self.vals)
+        line_id = logistic_requisition.add_line(self, requisition_id, self.line1)
+        source_id = logistic_requisition.add_source(self, line_id, self.source1)
+        logistic_requisition.confirm(self, requisition_id)
+        logistic_requisition.assign_lines(self, [line_id], self.user_demo)
+        purch_req_id = logistic_requisition.create_purchase_requisition(
+            self, source_id)
+        purchase_requisition.change_pricelist(self, purch_req_id,
+            self.purchase_pricelist_eur)
+        purchase_requisition.confirm_call(self, purch_req_id)
+        bid, bid_line = purchase_requisition.create_draft_purchase_order(
+            self, purch_req_id, self.partner_1)
+        bid_line.write({'price_unit': 10})
+        purchase_order.select_line(self, bid_line.id, 100)
+        purchase_order.bid_encoded(self, bid.id)
+        purchase_requisition.close_call(self, purch_req_id)
+        purchase_requisition.bids_selected(self, purch_req_id)
+
+        logistic_requisition.check_line_unit_cost(self, source_id, 10,
+            self.purchase_pricelist_eur)
+        # Change po value to check
+
+        logistic_requisition.source_lines(self, [line_id])
+
+        # Try to change again
+        sale_id, __ = logistic_requisition.create_quotation(
+            self, requisition_id, [line_id])
+        # the confirmation of the sale order should generate the
+        # purchase order of the purchase requisition
+        self.sale_model.action_button_confirm(cr, uid, [sale_id])
+        purch_req = self.purch_req_model.browse(cr, uid, purch_req_id)
+        self.assertEquals(purch_req.state,
+                          'done',
+                          "The purchase requisition should be in 'done' state.")
+        self.assertEquals(len(purch_req.purchase_ids), 1,
+                          "We should have only 1 purchase order.")

=== modified file 'logistic_requisition/tests/test_purchase_split_requisition.py'
--- logistic_requisition/tests/test_purchase_split_requisition.py	2013-11-01 11:17:26 +0000
+++ logistic_requisition/tests/test_purchase_split_requisition.py	2014-03-10 15:39:56 +0000
@@ -71,20 +71,20 @@
         __, self.user_demo = self.get_ref('base', 'user_demo')
         __, self.product_7 = self.get_ref('product', 'product_product_7')
         __, self.product_uom_pce = self.get_ref('product', 'product_uom_unit')
+        __, self.pricelist_sale = self.get_ref('product','list0')
+        
         vals = {
             'partner_id': self.partner_4,
             'consignee_id': self.partner_3,
             'date_delivery': time.strftime(D_FMT),
             'user_id': self.user_demo,
-            'budget_holder_id': self.user_demo,
-            'finance_officer_id': self.user_demo,
+            'pricelist_id': self.pricelist_sale,
         }
         line = {
             'product_id': self.product_7,
             'requested_qty': 100,
             'requested_uom_id': self.product_uom_pce,
             'date_delivery': time.strftime(D_FMT),
-            'budget_tot_price': 1000,
         }
         source = {
             'proposed_qty': 100,
@@ -141,7 +141,8 @@
             self.assertEquals(source.unit_cost,
                               bid_line.price_unit,
                               "The requisition line should have the price "
-                              "proposed on the purchase order line. ")
+                              "proposed on the purchase order line as long as "
+                              "their currency are the same ")
 
     def test_split_1_line_selected(self):
         """ Create a call for bids from the logistic requisition, 1 po line choosed """
@@ -214,38 +215,6 @@
                           "We should have 2 lines linked with the purchase "
                           "lines and no remaining line.")
 
-    def test_split_too_many_products_selected_budget_exceeded(self):
-        """ Create a call for bids from the logistic requisition, 2 po line choosed (budget exceeded)
-
-        30 items in a first purchase order and 80 items in a second one,
-        for a total of 110 items. That means 110 products have been ordered
-        but 100 only have been ordered at the origin.
-
-        The total cost is greater than the requested budget.
-        We should not be able to propose more than requested financially.
-        """
-        # create a first draft bid and select a part of the line
-        purchase1, bid_line1 = purchase_requisition.create_draft_purchase_order(
-            self, self.purchase_requisition.id, self.partner_1)
-        bid_line1.write({'price_unit': 15})
-        purchase_order.select_line(self, bid_line1.id, 30)
-        purchase_order.bid_encoded(self, purchase1.id)
-
-        # create a second draft bid and select a part of the line
-        purchase2, bid_line2 = purchase_requisition.create_draft_purchase_order(
-            self, self.purchase_requisition.id, self.partner_12)
-        bid_line2.write({'price_unit': 13})
-        purchase_order.select_line(self, bid_line2.id, 80)
-        purchase_order.bid_encoded(self, purchase2.id)
-
-        # close the call for bids
-        purchase_requisition.close_call(self, self.purchase_requisition.id)
-        # selection of bids will trigger the split of lines
-        # the generation of po fails because the budget is exceeded
-        with self.assertRaises(orm.except_orm):
-            purchase_requisition.bids_selected(self,
-                                               self.purchase_requisition.id)
-
     def test_split_too_many_products_selected(self):
         """ Create a call for bids from the logistic requisition, 2 po line choosed (too many)
 

=== modified file 'logistic_requisition/tests/test_sale_order_from_lr_confirm.py'
--- logistic_requisition/tests/test_sale_order_from_lr_confirm.py	2013-11-01 11:17:26 +0000
+++ logistic_requisition/tests/test_sale_order_from_lr_confirm.py	2014-03-10 15:39:56 +0000
@@ -55,13 +55,13 @@
         # Computer Case: make_to_order
         __, self.product_16 = self.get_ref('product', 'product_product_16')
         __, self.product_uom_pce = self.get_ref('product', 'product_uom_unit')
+        __, self.pricelist_sale = self.get_ref('product', 'list0')
         self.vals = {
             'partner_id': self.partner_4,
             'consignee_id': self.partner_3,
             'date_delivery': time.strftime(D_FMT),
             'user_id': self.user_demo,
-            'budget_holder_id': self.user_demo,
-            'finance_officer_id': self.user_demo,
+            'pricelist_id': self.pricelist_sale,
         }
 
         self.line1 = {
@@ -69,7 +69,6 @@
             'requested_qty': 100,
             'requested_uom_id': self.product_uom_pce,
             'date_delivery': time.strftime(D_FMT),
-            'budget_tot_price': 10000,
             'account_code': '1234',
         }
         self.source1 = {

=== modified file 'logistic_requisition/view/logistic_requisition.xml'
--- logistic_requisition/view/logistic_requisition.xml	2014-02-07 17:21:33 +0000
+++ logistic_requisition/view/logistic_requisition.xml	2014-03-10 15:39:56 +0000
@@ -57,7 +57,7 @@
                     </div>
                     <group>
                         <group>
-                            <field name="partner_id"/>
+                            <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
                             <field name="consignee_id"
                                    on_change="onchange_consignee_id(consignee_id)"
                                    attrs="{'required': [('cost_estimate_only', '=', False)]}"/>
@@ -66,6 +66,8 @@
                                    context="{'default_type':'delivery'}"
                                    attrs="{'required': [('cost_estimate_only', '=', False)]}"/>
                             <field name="analytic_id"/>
+                            <field name="pricelist_id" domain="[('type','=','sale')]"/>
+                            <field name="currency_id"/>
                         </group>
                         <group>
                             <field name="date"/>
@@ -91,46 +93,12 @@
                                     <field name="requested_qty" string="Quantity"/>
                                     <field name="requested_uom_id"/>
                                     <field name="date_delivery"/>
-                                    <field name="budget_unit_price"/>
-                                    <field name="budget_tot_price"/>
                                     <field name="account_id"/>
                                     <field name="account_code"/>
                                     <field name="state"/>
                                     <field name="logistic_user_id" string="Assigned To"/>
                                 </tree>
-                        </field>
-                        <group class="oe_subtotal_footer oe_right">
-                            <field name="currency_id" invisible="1"/>
-                            <field name="amount_total"
-                                class="oe_subtotal_footer_separator"
-                                widget="monetary"
-                                options="{'currency_field': 'currency_id'}"/>
-                        </group>
-                        <div class="oe_clear"/>
-                        <group string="Validation">
-                            <div colspan="4">
-                                <label for="budget_holder_id"/>
-                                <field name="budget_holder_id"
-                                    on_change="onchange_validate(budget_holder_id, date_budget_holder, 'date_budget_holder')"
-                                    class="oe_inline"/>
-                                <label string=" validated on "
-                                    attrs="{'invisible': [('budget_holder_id', '=', False)]}" />
-                                <field name="date_budget_holder"
-                                    attrs="{'invisible': [('budget_holder_id', '=', False)]}"
-                                    class="oe_inline"/>
-                            </div>
-                            <div colspan="4">
-                                <label for="finance_officer_id"/>
-                                <field name="finance_officer_id"
-                                    on_change="onchange_validate(finance_officer_id, date_finance_officer, 'date_finance_officer')"
-                                    class="oe_inline"/>
-                                <label string=" validated on "
-                                    attrs="{'invisible': [('finance_officer_id', '=', False)]}"/>
-                                <field name="date_finance_officer"
-                                    attrs="{'invisible': [('finance_officer_id', '=', False)]}"
-                                    class="oe_inline"/>
-                            </div>
-                        </group>
+                            </field>
                     </page>
                     <page string="Transportation and Delivery">
                         <group>
@@ -172,7 +140,6 @@
                 <field name="date_delivery"/>
                 <field name="country_id"/>
                 <field name="analytic_id"/>
-                <field name="amount_total" sum="Total Budget"/>
                 <field name="currency_id"/>
                 <field name="state"/>
                 <field name="sourced" widget="progressbar"/>
@@ -209,11 +176,13 @@
                 <field name="user_id" />
                 <field name="partner_id" />
                 <field name="analytic_id" />
+                <field name="currency_id" />
                 <group expand="0" string="Group By...">
                     <filter string="Business Unit Officer" domain="[]" context="{'group_by':'user_id'}"/>
                     <filter name="partner_id" string="Requesting Entity" domain="[]" context="{'group_by':'partner_id'}"/>
                     <filter string="Country" domain="[]" context="{'group_by':'country_id'}"/>
                     <filter string="Project" domain="[]" context="{'group_by':'analytic_id'}"/>
+                    <filter string="Currency" domain="[]" context="{'group_by':'currency_id'}"/>
                     <separator/>
                     <filter string="State" domain="[]" context="{'group_by':'state'}"/>
                     <separator/>
@@ -254,7 +223,7 @@
              <field name="requested_qty"/>
              <field name="requested_uom_id"/>
              <field name="logistic_user_id"/>
-             <field name="budget_tot_price" sum="Total Budget"/>
+             <field name="currency_id"/>
              <field name="state"/>
              <field name="country_id" invisible="1"/>
            </tree>
@@ -370,21 +339,17 @@
                             </div>
                             <field name="date_delivery"/>
                             <field name="currency_id" invisible="1"/>
-                            <field name="budget_unit_price" widget="monetary"
-                                options="{'currency_field': 'currency_id'}"/>
-                            <field name="budget_tot_price" widget="monetary"
-                                options="{'currency_field': 'currency_id'}"/>
                         </group>
                         <group>
                             <field name="cost_estimate_only"/>
                             <field name="logistic_user_id"/>
                             <field name="account_id"/>
                             <field name="account_code"/>
+                            <field name="currency_id"/>
                         </group>
                     </group>
                     <notebook>
                         <page string="Sourcing">
-                            <group>
                               <field name="source_ids" nolabel="1"
                                 options='{"reload_on_button": true}'
                                 context="{'default_requisition_line_id': active_id,
@@ -398,17 +363,22 @@
                                         <field name="proposed_uom_id"/>
                                         <field name="proposed_qty" sum="Total Proposed"/>
                                         <field name="unit_cost"/>
-                                        <field name="total_cost" sum="Total Budget"/>
+                                        <field name="total_cost" sum="Total Budget" 
+                                            class="oe_subtotal_footer_separator"
+                                            widget="monetary"
+                                            options="{'currency_field': 'parent.currency_id'}"/>
                                         <field name="po_requisition_id" invisible="1"/>
-                                        <button name="action_create_po_requisition" icon="gtk-execute"
-                                            string="Purchase Requisition" type="object"
-                                            attrs="{'invisible': ['|', '|', ('procurement_method', 'not in', ['procurement', 'fw_agreement']), ('state', '!=', 'assigned'), ('po_requisition_id', '!=', False)]}" />
                                         <button name="action_open_po_requisition" icon="terp-stock_zoom"
                                             string="Purchase Requisition" type="object"
                                             attrs="{'invisible': [('po_requisition_id', '=', False)]}" />
                                     </tree>
                                 </field>
-                            </group>
+                                 <group class="oe_subtotal_footer oe_right">
+                                    <field name="amount_total"
+                                        class="oe_subtotal_footer_separator"
+                                        widget="monetary"
+                                        options="{'currency_field': 'currency_id'}"/>
+                                </group>
                         </page>
                     </notebook>
                     <group>
@@ -461,6 +431,7 @@
                 <field name="name"/>
                 <field name="description" />
                 <field name="logistic_user_id" />
+                <field name="currency_id" />
 
                 <group expand="0" string="Group By...">
                     <filter name="groupby_logistic_user_id" string="Assigned Specialist"
@@ -475,6 +446,8 @@
                         domain="[]" context="{'group_by':'product_id'}"/>
                     <filter name="groupby_country_id" string="Country"
                         domain="[]" context="{'group_by':'country_id'}"/>
+                    <filter name="groupby_currency_id" string="Currency"
+                        domain="[]" context="{'group_by':'currency_id'}"/>
                 </group>
             </search>
         </field>
@@ -510,6 +483,7 @@
                <field name="proposed_qty"/>
                <field name="proposed_uom_id"/>
                <field name="total_cost" sum="Total Budget"/>
+               <field name="currency_id"/>
                <field name="po_requisition_id"/>
                <button name="action_create_po_requisition" icon="gtk-execute"
                    string="Purchase Requisition" type="object"
@@ -546,6 +520,7 @@
                                     <field name="proposed_qty" class="oe_inline"/>
                                     <field name="proposed_uom_id" class="oe_inline"/>
                                 </div>
+                                <field name="currency_id"/>
                                 <field name="unit_cost" widget="monetary"
                                     options="{'currency_field': 'currency_id'}"/>
                                 <field name="total_cost" widget="monetary"
@@ -555,14 +530,11 @@
                             </group>
                             <group>
                                 <group string="Purchase Requisition"
-                                    attrs="{'invisible': [('procurement_method', 'not in', ['procurement', 'fw_agreement'])]}"
+                                    attrs="{'invisible': [('procurement_method', 'not in', ['procurement','other'])]}"
                                     colspan="4">
                                     <label for="po_requisition_id"/>
                                     <div>
                                         <field name="po_requisition_id" class="oe_inline"/>
-                                        <button name="action_create_po_requisition"
-                                            string="Purchase Requisition" type="object"
-                                            attrs="{'invisible': [('po_requisition_id', '!=', False)]}" />
                                     </div>
                                     <field name="selected_bid_id"
                                         on_change="onchange_selected_bid_id(selected_bid_id)"/>
@@ -571,8 +543,8 @@
                                     colspan="4"
                                     attrs="{'invisible': [('procurement_method', '!=', 'wh_dispatch')]}">
                                     <field name="dispatch_location_id"
-                                        on_change="onchange_dispatch_location_id(dispatch_location_id)" 
-                                        attrs="{'required': [('procurement_method', '=', 'wh_dispatch')]}" 
+                                        on_change="onchange_dispatch_location_id(dispatch_location_id)"
+                                        attrs="{'required': [('procurement_method', '=', 'wh_dispatch')]}"
                                         domain="[('usage', '!=', 'view')]"/>
                                     <field name="stock_owner" />
                                 </group>
@@ -624,7 +596,7 @@
         <field name="res_model">logistic.requisition.source</field>
         <field name="view_type">form</field>
         <field name="view_mode">tree,form</field>
-        <field name="context">{"search_default_groupby_procurement_method" : True}</field>
+        <field name="context">{}</field>
         <field name="search_view_id" ref="view_logistic_requisition_source_filter"/>
         <field name="help"></field>
     </record>

=== modified file 'logistic_requisition/wizard/cost_estimate.py'
--- logistic_requisition/wizard/cost_estimate.py	2013-10-31 15:46:50 +0000
+++ logistic_requisition/wizard/cost_estimate.py	2014-03-10 15:39:56 +0000
@@ -149,17 +149,17 @@
                 }
         if sourcing.dispatch_location_id:
             vals['location_id'] = sourcing.dispatch_location_id.id
-        if sourcing.procurement_method == 'wh_dispatch':
+        if sourcing.procurement_method in ('wh_dispatch'):
             vals['type'] = 'make_to_stock'
         else:
-            vals['type'] = 'make_to_order'
+            vals['type'] = sourcing.proposed_product_id.procure_method
             vals['sale_flow'] = 'direct_delivery'
 
         requisition = sourcing.requisition_line_id.requisition_id
         onchange_vals = sale_line_obj.product_id_change(
             cr, uid, [],
             requisition.consignee_id.property_product_pricelist.id,
-            sourcing.requisition_line_id.product_id.id,
+            sourcing.proposed_product_id.id,
             partner_id=requisition.consignee_id.id,
             qty=sourcing.proposed_qty,
             uom=sourcing.proposed_uom_id.id).get('value', {})
@@ -178,11 +178,6 @@
         :returns: list of tuples ('message, 'error_code')
         """
         errors = []
-        if not requisition.budget_holder_id:
-            error = (_('The requisition must be validated '
-                       'by the Budget Holder.'),
-                     'NO_BUDGET_VALID')
-            errors.append(error)
         return errors
 
     def _check_line(self, cr, uid, line, context=None):
@@ -243,12 +238,13 @@
                 'incoterm': requisition.incoterm_id.id,
                 'incoterm_address': requisition.incoterm_address,
                 'requisition_id': requisition.id,
+                'origin': requisition.name,
                 'project_id': requisition.analytic_id.id if requisition.analytic_id else False,
                 }
-
         onchange_vals = sale_obj.onchange_partner_id(
             cr, uid, [], partner_id, context=context).get('value', {})
         vals.update(onchange_vals)
+        vals.update({'pricelist_id':requisition.pricelist_id.id})
         return vals
 
     def cost_estimate(self, cr, uid, ids, context=None):

=== modified file 'logistic_requisition/wizard/logistic_line_create_requisition.py'
--- logistic_requisition/wizard/logistic_line_create_requisition.py	2013-08-23 13:34:36 +0000
+++ logistic_requisition/wizard/logistic_line_create_requisition.py	2014-03-10 15:39:56 +0000
@@ -19,18 +19,46 @@
 #
 ##############################################################################
 
-from openerp.osv import orm
 from openerp.tools.translate import _
+from openerp.osv import fields, orm
 
 
 class LogisticRequisitionSourceCreateRequisition(orm.TransientModel):
     _name = "logistic.requisition.source.create.requisition"
     _description = "Create Purchase Requisition From Requisition Source"
 
+
+    _columns = {
+        'pricelist_id': fields.many2one('product.pricelist',
+                                          string='Pricelist / Currency',
+                                          required=True),
+    }
+
+    def default_get(self, cr, uid, fields_list, context=None):
+        """Take the first line pricelist as default"""
+        if context is None:
+            context = {}
+        defaults = super(LogisticRequisitionSourceCreateRequisition, self).\
+            default_get(cr, uid, fields_list, context=context)
+        line_obj = self.pool.get('logistic.requisition.source')
+        line_ids = context['active_ids']
+        pricelist_id = None
+        line = line_obj.browse(cr, uid, line_ids, context=context)[0]
+        pricelist_id = line_obj._get_purchase_pricelist_from_currency(
+                cr,
+                uid,
+                line.requisition_id.pricelist_id.currency_id.id,
+                context=context
+                )
+        defaults['pricelist_id'] = pricelist_id
+        return defaults
+
     def create_po_requisition(self, cr, uid, ids, context=None):
+        form = self.browse(cr, uid, ids, context=context)[0]
         source_obj = self.pool.get('logistic.requisition.source')
         requisition_id = source_obj._action_create_po_requisition(
-            cr, uid, context.get('active_ids', []), context=context)
+            cr, uid, context.get('active_ids', []), 
+            pricelist=form.pricelist_id.id, context=context)
         return {
             'name': _('Purchase Requisition'),
             'view_type': 'form',

=== modified file 'logistic_requisition/wizard/logistic_line_create_requisition_view.xml'
--- logistic_requisition/wizard/logistic_line_create_requisition_view.xml	2013-08-23 13:34:36 +0000
+++ logistic_requisition/wizard/logistic_line_create_requisition_view.xml	2014-03-10 15:39:56 +0000
@@ -6,6 +6,8 @@
             <field name="model">logistic.requisition.source.create.requisition</field>
             <field name="arch" type="xml">
                <form string="Create Requisition" version="7.0">
+                    <separator string="Which pricelist / currency you want ?"/>
+                    <field name="pricelist_id" domain="[('type','=','purchase')]"/>
                     <group>
                         <separator string="Are you sure you want to create a requisition from those lines ?"/>
                         <label string="

=== added directory 'logistic_requisition_budget'
=== added file 'logistic_requisition_budget/__init__.py'
--- logistic_requisition_budget/__init__.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Romain Deheele
+#    Copyright 2014 Camptocamp SA
+#
+#    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 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 Affero General Public License for more description.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import model
+from . import wizard

=== added file 'logistic_requisition_budget/__openerp__.py'
--- logistic_requisition_budget/__openerp__.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/__openerp__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author:  Joël Grand-Guillaume, Jacques-Etienne Baudoux, Guewen Baconnier
+#    Copyright 2013 Camptocamp SA
+#
+#    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 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 Affero General Public License for more description.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{"name": "Logistic Requisition Budget",
+ "version": "0.1",
+ "author": "Camptocamp",
+ "license": "AGPL-3",
+ "category": "Purchase Management",
+ 'complexity': "normal",
+ "images": [],
+ "website": "http://www.camptocamp.com";,
+ "description": """
+This logisitc requisiton budget
+===============================
+
+This module add a notion of budget on logistic requisition.
+Each requisition lines have now a budget holder and a budget Value.
+
+Requisiton must be approves by budget manager.
+
+If budget is exceeded requisiton flow is block unitl adaptation of price
+or budget.
+
+""",
+ "depends": ["logistic_requisition",
+             ],
+ "demo": [],
+ "data": ["view/logistic_requisition.xml",
+          "report/logistic_requisition_report.xml",
+          ],
+ "auto_install": False,
+ "test": ['test/requisition_create_cost_estimate.yml',
+          ],
+ "installable": True,
+ }

=== added directory 'logistic_requisition_budget/i18n'
=== added file 'logistic_requisition_budget/i18n/en_US.po'
--- logistic_requisition_budget/i18n/en_US.po	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/i18n/en_US.po	2014-03-10 15:39:56 +0000
@@ -0,0 +1,227 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* logistic_requisition_budget
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-02-04 09:22+0000\n"
+"PO-Revision-Date: 2014-02-04 09:22+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: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:149
+msgid "No"
+msgstr "No"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:182
+msgid "General Remarks"
+msgstr "General Remarks"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:136
+msgid "Logistic requisition"
+msgstr "Logistic requisition"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:192
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:206
+msgid "Signature"
+msgstr "Signature"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,finance_officer_id:0
+msgid "Finance Officer"
+msgstr "Finance Officer"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:102
+msgid "Shipping address:"
+msgstr "Shipping address:"
+
+#. module: logistic_requisition_budget
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition_line
+msgid "Logistic Requisition Line"
+msgstr "Logistic Requisition Line"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:140
+msgid "Preferred transport"
+msgstr "Preferred transport"
+
+#. module: logistic_requisition_budget
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition_cost_estimate
+msgid "Create cost estimate of logistic requisition lines"
+msgstr "Create cost estimate of logistic requisition lines"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:119
+msgid "Consignee address:"
+msgstr "Consignee address:"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:161
+msgid "Description"
+msgstr "Description"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:139
+msgid "Desired delivery date"
+msgstr "Desired delivery date"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:205
+msgid "Validation date"
+msgstr "Validation date"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:201
+msgid "Budget limit:"
+msgstr "Budget limit:"
+
+#. module: logistic_requisition_budget
+#: model:ir.actions.report.xml,name:logistic_requisition_budget.report_logistic_requisition
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition
+msgid "Logistic Requisition"
+msgstr "Logistic Requisition"
+
+#. module: logistic_requisition_budget
+#: code:addons/logistic_requisition_budget/wizard/cost_estimate.py:36
+#, python-format
+msgid "The requisition must be validated by the Budget Holder."
+msgstr "The requisition must be validated by the Budget Holder."
+
+#. module: logistic_requisition_budget
+#: view:logistic.requisition:0
+msgid " validated on "
+msgstr " validated on "
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:141
+msgid "Cost estimate only"
+msgstr "Cost estimate only"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:187
+msgid "Approval"
+msgstr "Approval"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:191
+msgid "Requested date"
+msgstr "Requested date"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition.line,budget_unit_price:0
+msgid "Budget Unit Price"
+msgstr "Budget Unit Price"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:163
+msgid "UoM"
+msgstr "UoM"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:143
+msgid "Country"
+msgstr "Country"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:200
+msgid "Budget"
+msgstr "Budget"
+
+#. module: logistic_requisition_budget
+#: constraint:logistic.requisition.source:0
+msgid "The total cost cannot be more than the total budget."
+msgstr "The total cost cannot be more than the total budget."
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:142
+msgid "Project"
+msgstr "Project"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:144
+msgid "Requisition Date"
+msgstr "Requisition Date"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:190
+msgid "Requesting entity"
+msgstr "Requesting entity"
+
+#. module: logistic_requisition_budget
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition_source
+msgid "Logistic Requisition Source"
+msgstr "Logistic Requisition Source"
+
+#. module: logistic_requisition_budget
+#: view:logistic.requisition:0
+msgid "Validation"
+msgstr "Validation"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:162
+msgid "Quantity"
+msgstr "Quantity"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,date_budget_holder:0
+msgid "Budget Holder Validation Date"
+msgstr "Budget Holder Validation Date"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:204
+msgid "Budget/financial holder"
+msgstr "Budget/financial holder"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:178
+msgid "Delivery Remarks"
+msgstr "Delivery Remarks"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition.line,budget_tot_price:0
+msgid "Budget Total Price"
+msgstr "Budget Total Price"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,budget_holder_id:0
+msgid "Budget Holder"
+msgstr "Budget Holder"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:160
+msgid "Number"
+msgstr "Number"
+
+#. module: logistic_requisition_budget
+#: view:logistic.requisition:0
+#: field:logistic.requisition,amount_total:0
+#: view:logistic.requisition.line:0
+msgid "Total Budget"
+msgstr "Total Budget"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,allowed_budget:0
+msgid "Allowed Budget"
+msgstr "Allowed Budget"
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,date_finance_officer:0
+msgid "Finance Officer Validation Date"
+msgstr "Finance Officer Validation Date"
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:149
+msgid "Yes"
+msgstr "Yes"
+

=== added file 'logistic_requisition_budget/i18n/logistic_requisition_budget.pot'
--- logistic_requisition_budget/i18n/logistic_requisition_budget.pot	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/i18n/logistic_requisition_budget.pot	2014-03-10 15:39:56 +0000
@@ -0,0 +1,227 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* logistic_requisition_budget
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-02-04 09:22+0000\n"
+"PO-Revision-Date: 2014-02-04 09:22+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: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:149
+msgid "No"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:182
+msgid "General Remarks"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:136
+msgid "Logistic requisition"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:192
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:206
+msgid "Signature"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,finance_officer_id:0
+msgid "Finance Officer"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:102
+msgid "Shipping address:"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition_line
+msgid "Logistic Requisition Line"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:140
+msgid "Preferred transport"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition_cost_estimate
+msgid "Create cost estimate of logistic requisition lines"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:119
+msgid "Consignee address:"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:161
+msgid "Description"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:139
+msgid "Desired delivery date"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:205
+msgid "Validation date"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:201
+msgid "Budget limit:"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: model:ir.actions.report.xml,name:logistic_requisition_budget.report_logistic_requisition
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition
+msgid "Logistic Requisition"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: code:addons/logistic_requisition_budget/wizard/cost_estimate.py:36
+#, python-format
+msgid "The requisition must be validated by the Budget Holder."
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: view:logistic.requisition:0
+msgid " validated on "
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:141
+msgid "Cost estimate only"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:187
+msgid "Approval"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:191
+msgid "Requested date"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition.line,budget_unit_price:0
+msgid "Budget Unit Price"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:163
+msgid "UoM"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:143
+msgid "Country"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:200
+msgid "Budget"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: constraint:logistic.requisition.source:0
+msgid "The total cost cannot be more than the total budget."
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:142
+msgid "Project"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:144
+msgid "Requisition Date"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:190
+msgid "Requesting entity"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: model:ir.model,name:logistic_requisition_budget.model_logistic_requisition_source
+msgid "Logistic Requisition Source"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: view:logistic.requisition:0
+msgid "Validation"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:162
+msgid "Quantity"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,date_budget_holder:0
+msgid "Budget Holder Validation Date"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:204
+msgid "Budget/financial holder"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:178
+msgid "Delivery Remarks"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition.line,budget_tot_price:0
+msgid "Budget Total Price"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,budget_holder_id:0
+msgid "Budget Holder"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:160
+msgid "Number"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: view:logistic.requisition:0
+#: field:logistic.requisition,amount_total:0
+#: view:logistic.requisition.line:0
+msgid "Total Budget"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,allowed_budget:0
+msgid "Allowed Budget"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: field:logistic.requisition,date_finance_officer:0
+msgid "Finance Officer Validation Date"
+msgstr ""
+
+#. module: logistic_requisition_budget
+#: report:addons/logistic_requisition_budget/report/logistic_requisition.mako:149
+msgid "Yes"
+msgstr ""
+

=== added directory 'logistic_requisition_budget/model'
=== added file 'logistic_requisition_budget/model/__init__.py'
--- logistic_requisition_budget/model/__init__.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/model/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author:  Joël Grand-Guillaume, Jacques-Etienne Baudoux, Guewen Baconnier,
+#             Romain Deheele
+#    Copyright 2013 Camptocamp SA
+#
+#    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 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 Affero General Public License for more description.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from . import logistic_requisition

=== added file 'logistic_requisition_budget/model/logistic_requisition.py'
--- logistic_requisition_budget/model/logistic_requisition.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/model/logistic_requisition.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author:  Romain Deheele
+#    Copyright 2014 Camptocamp SA
+#
+#    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 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 Affero General Public License for more description.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import logging
+
+from openerp.osv import fields, orm
+import openerp.addons.decimal_precision as dp
+
+_logger = logging.getLogger(__name__)
+
+
+class logistic_requisition(orm.Model):
+    _inherit = "logistic.requisition"
+
+    REQ_STATES = {'confirmed': [('readonly', True)],
+                  'done': [('readonly', True)]
+                  }
+
+    _columns = {
+        'amount_total': fields.function(
+            lambda self, *args, **kwargs: self._get_amount(*args, **kwargs),
+            digits_compute=dp.get_precision('Account'),
+            string='Total Budget',
+            store={
+                'logistic.requisition': (
+                    lambda self, cr, uid, ids, c=None: ids,
+                    ['line_ids'], 20),
+                'logistic.requisition.line': (
+                    lambda self, *a, **kw: self._store_get_requisition_ids(*a, **kw),
+                    ['requested_qty', 'budget_unit_price', 'budget_tot_price', 'requisition_id'], 20),
+            }),
+        'allowed_budget': fields.boolean('Allowed Budget'),
+        'budget_holder_id': fields.many2one(
+            'res.users',
+            string='Budget Holder'),
+        'date_budget_holder': fields.datetime(
+            'Budget Holder Validation Date'),
+        'finance_officer_id': fields.many2one(
+            'res.users',
+            string='Finance Officer'),
+        'date_finance_officer': fields.datetime(
+            'Finance Officer Validation Date'),
+    }
+
+    def _get_amount(self, cr, uid, ids, name, args, context=None):
+        """Compute the requisiton total budget"""
+        res = {}
+        for requisition in self.browse(cr, uid, ids, context=context):
+            res[requisition.id] = sum(line.budget_tot_price for line
+                                      in requisition.line_ids)
+        return res
+
+    def _do_draft(self, cr, uid, ids, context=None):
+        """Cancel LR and related budget"""
+        super(logistic_requisition, self)._do_draft(cr, uid, ids,
+                                                    context=context)
+        vals = {'state': 'draft',
+                'budget_holder_id': False,
+                'date_budget_holder': False,
+                'finance_officer_id': False,
+                'date_finance_officer': False,
+                'cancel_reason_id': False,
+                }
+        self.write(cr, uid, ids, vals, context=context)
+
+    def copy(self, cr, uid, id, default=None, context=None):
+        if not default:
+            default = {}
+        default.update({
+            'budget_holder_id': False,
+            'date_budget_holder': False,
+            'finance_officer_id': False,
+            'date_finance_officer': False,
+        })
+        return super(logistic_requisition, self).copy(cr, uid, id, default=default, context=context)
+
+
+class logistic_requisition_line(orm.Model):
+    _inherit = "logistic.requisition.line"
+
+    REQUEST_STATES = {'assigned': [('readonly', True)],
+                      'sourced': [('readonly', True)],
+                      'quoted': [('readonly', True)],
+                      }
+    STATES = [('draft', 'Draft'),
+              ('confirmed', 'Confirmed'),
+              ('assigned', 'Assigned'),
+              ('sourced', 'Sourced'),
+              ('quoted', 'Quoted'),
+              ('cancel', 'Cancelled')
+              ]
+
+    _columns = {
+        'budget_tot_price': fields.float(
+            'Budget Total Price',
+            states=REQUEST_STATES,
+            digits_compute=dp.get_precision('Account')),
+        'budget_unit_price': fields.function(
+            lambda self, *args, **kwargs: self._get_unit_amount_line(*args, **kwargs),
+            string='Budget Unit Price',
+            type="float",
+            digits_compute=dp.get_precision('Account'),
+            store=True),
+    }
+
+    def _get_unit_amount_line(self, cr, uid, ids, prop, unknow_none,
+                              unknow_dict, context=None):
+        res = {}
+        for line in self.browse(cr, uid, ids, context=context):
+            price = line.budget_tot_price / line.requested_qty
+            res[line.id] = price
+        return res
+
+
+class logistic_requisition_source(orm.Model):
+    _inherit = "logistic.requisition.source"
+
+    _constraints = [
+        (lambda self, *a, **kw: self._check_source_lines_total_amount(*a, **kw),
+         'The total cost cannot be more than the total budget.',
+         ['proposed_qty', 'unit_cost', 'requisition_line_id']),
+    ]
+
+    def _check_source_lines_total_amount(self, cr, uid, ids, context=None):
+        for source in self.browse(cr, uid, ids, context=context):
+            line = source.requisition_line_id
+            total = sum(source.unit_cost * source.proposed_qty
+                        for source in line.source_ids)
+            if total > line.budget_tot_price:
+                return False
+        return True

=== added directory 'logistic_requisition_budget/report'
=== added file 'logistic_requisition_budget/report/logistic_requisition.mako'
--- logistic_requisition_budget/report/logistic_requisition.mako	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/report/logistic_requisition.mako	2014-03-10 15:39:56 +0000
@@ -0,0 +1,226 @@
+<html>
+<head>
+    <style type="text/css">
+        ${css}
+
+.list_sale_table {
+    border:thin solid #E3E4EA;
+    text-align:center;
+    border-collapse: collapse;
+}
+.list_sale_table th {
+    background-color: #EEEEEE;
+    border: thin solid #000000;
+    text-align:center;
+    font-size:12;
+    font-weight:bold;
+    padding-right:3px;
+    padding-left:3px;
+}
+.list_sale_table td {
+    border-top: thin solid #EEEEEE;
+    text-align:left;
+    font-size:12;
+    padding-right:3px;
+    padding-left:3px;
+    padding-top:3px;
+    padding-bottom:3px;
+}
+.list_sale_table thead {
+    display:table-header-group;
+}
+
+td.formatted_note {
+    text-align:left;
+    border-right:thin solid #EEEEEE;
+    border-left:thin solid #EEEEEE;
+    border-top:thin solid #EEEEEE;
+    padding-left:10px;
+    font-size:11;
+}
+
+
+
+.no_bloc {
+    border-top: thin solid  #ffffff ;
+}
+
+.right_table {
+    right: 4cm;
+    width:"100%";
+}
+
+.std_text {
+    font-size:12;
+}
+
+tfoot.totals tr:first-child td{
+    padding-top: 15px;
+}
+
+
+td.amount, th.amount {
+    text-align: right;
+    white-space: nowrap;
+}
+
+
+.address .recipient .shipping .invoice {
+    font-size: 12px;
+}
+
+    </style>
+</head>
+<body>
+    <%page expression_filter="entity"/>
+    <%
+    def carriage_returns(text):
+        return text.replace('\n', '<br />')
+
+    %>
+    %for requisition in objects:
+    <% setLang(requisition.partner_id.lang) %>
+
+    <div class="address">
+        <table class="recipient">
+            %if requisition.partner_id.parent_id:
+            <tr><td class="name">${requisition.partner_id.parent_id.name or ''}</td></tr>
+            <tr><td>${requisition.partner_id.title.name if requisition.partner_id.title else ''} ${requisition.partner_id.name }</td></tr>
+            <% address_lines = requisition.partner_id.contact_address.split("\n")[1:] %>
+            %else:
+            <tr><td class="name">${requisition.partner_id.title.name if requisition.partner_id.title else ''} ${requisition.partner_id.name }</td></tr>
+            <% address_lines = requisition.partner_id.contact_address.split("\n") %>
+            %endif
+            %for part in address_lines:
+                %if part:
+                <tr><td>${part}</td></tr>
+                %endif
+            %endfor
+        </table>
+
+        <table class="shipping">
+            <tr><td class="address_title">${_("Shipping address:")}</td></tr>
+            %if requisition.consignee_shipping_id.parent_id:
+            <tr><td>${requisition.consignee_shipping_id.parent_id.name or ''}</td></tr>
+            <tr><td>${requisition.consignee_shipping_id.title.name if requisition.consignee_shipping_id.title else ''} ${requisition.consignee_shipping_id.name }</td></tr>
+            <% address_lines = requisition.consignee_shipping_id.contact_address.split("\n")[1:] %>
+            %else:
+            <tr><td>${requisition.consignee_shipping_id.title and requisition.consignee_shipping_id.title.name or ''} ${requisition.consignee_shipping_id.name }</td></tr>
+            <% address_lines = requisition.consignee_shipping_id.contact_address.split("\n") %>
+            %endif
+            %for part in address_lines:
+                %if part:
+                <tr><td>${part}</td></tr>
+                %endif
+            %endfor
+        </table>
+
+        <table class="invoice">
+            <tr><td class="address_title">${_("Consignee address:")}</td></tr>
+            %if requisition.consignee_id.parent_id:
+            <tr><td>${requisition.consignee_id.parent_id.name or ''}</td></tr>
+            <tr><td>${requisition.consignee_id.title.name if requisition.consignee_id.title else ''} ${requisition.consignee_id.name }</td></tr>
+            <% address_lines = requisition.consignee_id.contact_address.split("\n")[1:] %>
+            %else:
+            <tr><td>${requisition.consignee_id.title.name if requisition.consignee_id.title else ''} ${requisition.consignee_id.name }</td></tr>
+            <% address_lines = requisition.consignee_id.contact_address.split("\n") %>
+            %endif
+            %for part in address_lines:
+                %if part:
+                <tr><td>${part}</td></tr>
+                %endif
+            %endfor
+        </table>
+    </div>
+
+    <h1 style="clear:both;">${_('Logistic requisition')} ${requisition.name}</h1>
+    <table class="basic_table" width="100%">
+        <tr>
+            <td style="font-weight:bold;">${_("Desired delivery date")}</td>
+            <td style="font-weight:bold;">${_("Preferred transport")}</td>
+            <td style="font-weight:bold;">${_("Cost estimate only")}</td>
+            <td style="font-weight:bold;">${_("Project")}</td>
+            <td style="font-weight:bold;">${_("Country")}</td>
+            <td style="font-weight:bold;">${_("Requisition Date")}</td>
+        </tr>
+        <tr>
+            <td>${formatLang(requisition.date_delivery, date=True)}</td>
+            <td>${requisition.preferred_transport.name if requisition.preferred_transport else ''}</td>
+            <td>${_("Yes") if requisition.cost_estimate_only else _("No")}</td>
+            <td>${requisition.analytic_id.name if requisition.analytic_id else ''}</td>
+            <td>${requisition.country_id.name}</td>
+            <td>${formatLang(requisition.date, date=True)}</td>
+        </tr>
+    </table>
+    <br/>
+
+    <table class="list_sale_table" width="100%" style="margin-top: 20px;">
+        <thead>
+            <tr>
+                <th>${_("Number")}</th>
+                <th>${_("Description")}</th>
+                <th class="amount">${_("Quantity")}</th>
+                <th class="amount">${_("UoM")}</th>
+            </tr>
+        </thead>
+        <tbody>
+        %for line in requisition.line_ids:
+            <tr class="line">
+                <td style="text-align:left; " >${line.name}</td>
+                <td style="text-align:left; " >${(line.product_id.code or '') if line.product_id else ''} ${line.product_id.name if line.product_id else ''}</td>
+
+                <td class="amount" width="15%">${formatLang(line.requested_qty)}</td>
+                <td style="text-align:center;">${line.requested_uom_id.category_id.name}</td>
+        %endfor
+        </tbody>
+    </table>
+    %if requisition.shipping_note :
+    <p><b>${_('Delivery Remarks')}</b></p>
+        <p class="std_text">${requisition.note | carriage_returns}</p>
+    %endif
+    %if requisition.note :
+    <p><b>${_("General Remarks")}</b></p>
+        <p class="std_text">${requisition.note | carriage_returns}</p>
+    %endif
+    <br/>
+    <br/>
+    <p><b>${_("Approval")}</b></p>
+    <table class="basic_table" width="100%">
+        <tr>
+            <td style="font-weight:bold;width:40%">${_("Requesting entity")}</td>
+            <td style="font-weight:bold;width:30%">${_("Requested date")}</td>
+            <td style="font-weight:bold;">${_("Signature")}</td>
+        </tr>
+        <tr>
+            <td>${requisition.partner_id.name}</td>
+            <td>${requisition.date or 'N/A'}</td>
+            <td>&nbsp;</td>
+        </tr>
+    </table>
+    <p><b>${_("Budget")}</b></p>
+    <p>${_("Budget limit:")} ${formatLang(requisition.allowed_budget)}</p>
+    <table class="basic_table" width="100%">
+        <tr>
+            <td style="font-weight:bold;width:40%">${_("Budget/financial holder")}</td>
+            <td style="font-weight:bold;width:30%">${_("Validation date")}</td>
+            <td style="font-weight:bold;">${_("Signature")}</td>
+        </tr>
+        %if requisition.budget_holder_id:
+        <tr>
+            <td>${requisition.budget_holder_id.name}</td>
+            <td>${requisition.date_budget_holder if requisition.date_budget_holder else 'N/A'}</td>
+            <td>&nbsp;</td>
+        </tr>
+        %endif
+        %if requisition.finance_officer_id:
+        <tr>
+            <td>${requisition.finance_officer_id.name}</td>
+            <td>${requisition.date_finance_officer if requisition.date_finance_officer else 'N/A'}</td>
+            <td>&nbsp;</td>
+        </tr>
+        %endif
+    </table>
+    <p style="page-break-after: always"/>
+    %endfor
+</body>
+</html>

=== added file 'logistic_requisition_budget/report/logistic_requisition_report.xml'
--- logistic_requisition_budget/report/logistic_requisition_report.xml	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/report/logistic_requisition_report.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <report id="report_logistic_requisition"
+                auto="False"
+                name="logistic.requisition"
+                model="logistic.requisition"
+                file="logistic_requisition_with_budget/report/logistic_requisition.mako"
+                webkit_header="base_headers_webkit.base_reports_portrait_header"
+                report_type="webkit"
+                string="Logistic Requisition"/>
+    </data>
+</openerp>

=== added directory 'logistic_requisition_budget/test'
=== added file 'logistic_requisition_budget/test/requisition_create_cost_estimate.yml'
--- logistic_requisition_budget/test/requisition_create_cost_estimate.yml	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/test/requisition_create_cost_estimate.yml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,197 @@
+-
+  Given I create a logistic requisition
+-
+  !record {model: logistic.requisition, id: logistic_requisition_cost_estimate_01}:
+    partner_id: base.res_partner_4
+    consignee_id: base.res_partner_3
+    date_delivery: !eval "time.strftime('%Y-%m-%d')"
+    user_id: base.user_demo
+    incoterm_id: stock.incoterm_FCA
+    incoterm_address: incoterm address as text
+    analytic_id: account.analytic_consultancy
+    pricelist_id: product.list0
+-
+  And I add a line 1
+-
+  !record {model: logistic.requisition.line, id: logistic_requisition_line_cost_estimate_01}:
+    requisition_id: logistic_requisition_cost_estimate_01
+    product_id: product.product_product_7
+    requested_qty: 100
+    requested_uom_id: product.product_uom_unit
+    date_delivery: !eval "time.strftime('%Y-%m-%d')"
+    budget_tot_price: 1000
+    logistic_user_id: base.user_demo
+-
+  And I add a source line to the line 1
+-
+  !record {model: logistic.requisition.source, id: logistic_requisition_source_cost_estimate_01}:
+    requisition_line_id: logistic_requisition_line_cost_estimate_01
+    proposed_qty: 110
+    proposed_product_id: product.product_product_7
+    proposed_uom_id: product.product_uom_unit
+    unit_cost: 8
+    transport_applicable: 0
+    procurement_method: wh_dispatch
+    price_is: fixed
+    dispatch_location_id: stock.stock_location_shop1
+-
+  And I add a line 2
+-
+  !record {model: logistic.requisition.line, id: logistic_requisition_line_cost_estimate_02}:
+    requisition_id: logistic_requisition_cost_estimate_01
+    product_id: product.product_product_8
+    requested_qty: 100
+    requested_uom_id: product.product_uom_unit
+    date_delivery: !eval "time.strftime('%Y-%m-%d')"
+    budget_tot_price: 1000
+    logistic_user_id: base.user_demo
+-
+  And I add a source line to the line 2
+-
+  !record {model: logistic.requisition.source, id: logistic_requisition_source_cost_estimate_02}:
+    requisition_line_id: logistic_requisition_line_cost_estimate_02
+    proposed_qty: 90
+    proposed_product_id: product.product_product_8
+    proposed_uom_id: product.product_uom_unit
+    unit_cost: 8
+    transport_applicable: 0
+    procurement_method: wh_dispatch
+    price_is: estimated
+    dispatch_location_id: stock.stock_location_shop1
+-
+  When I confirm the logistic requisition
+-
+  !python {model: logistic.requisition}: |
+    req = self.browse(cr, uid, ref("logistic_requisition_cost_estimate_01"))
+    req.button_confirm()
+-
+  And I source the lines
+-
+  !python {model: logistic.requisition.line}: |
+    line1_id = ref("logistic_requisition_line_cost_estimate_01")
+    line2_id = ref("logistic_requisition_line_cost_estimate_02")
+    ids = [line1_id, line2_id]
+    # The initial yaml does not set it to false, probably
+    # a bug related to the application of the default values
+    # However, we need to not have this flag to source the lines
+    self.write(cr, uid, ids, {'transport_applicable': False})
+    self.button_sourced(cr, uid, ids)
+-
+  I open the wizard to create a cost estimate from the logistic requisition,
+  but it fails because the business rules are not satisfied.
+-
+  !python {model: logistic.requisition.cost.estimate}: |
+    from openerp.osv import orm
+    context = {'active_model': 'logistic.requisition',
+               'active_ids': [ref('logistic_requisition_cost_estimate_01')],
+               }
+    wizard_id = self.create(cr, uid, {}, context=context)
+    try:
+        self.cost_estimate(cr, uid, wizard_id)
+    except orm.except_orm as err:
+        assert 'NO_BUDGET_VALID' in err.error_codes, (
+                'Expected an error because the budget holder is missing')
+        assert 'NO_ACCOUNT_CODE' in err.error_codes, (
+                'Expected an error because the account code is missing')
+    else:
+        raise AssertionError('Expected an orm.except_orm error, got nothing')
+-
+  I set some data to fulfill the business rules
+-
+  !record {model: logistic.requisition, id: logistic_requisition_cost_estimate_01}:
+    budget_holder_id: base.user_demo
+-
+  !record {model: logistic.requisition.line, id: logistic_requisition_line_cost_estimate_01}:
+    account_code: 'XXXX'
+-
+  !record {model: logistic.requisition.line, id: logistic_requisition_line_cost_estimate_02}:
+    account_code: 'YYYY'
+-
+  I open the wizard to create a cost estimate from the logistic requisition
+-
+  !python {model: logistic.requisition.cost.estimate}: |
+    context = {'active_model': 'logistic.requisition',
+               'active_ids': [ref('logistic_requisition_cost_estimate_01')],
+               }
+    wizard_id = self.create(cr, uid, {}, context=context)
+    open_action = self.cost_estimate(cr, uid, wizard_id)
+    cost_estimate_id = open_action['res_id']
+    cost_estimate_obj = self.pool.get('sale.order')
+    cost_estimate = cost_estimate_obj.browse(cr, uid, cost_estimate_id)
+    assert len(cost_estimate.order_line) == 2, (
+        "Cost Estimate should have 2 lines, 1 per logistic requisition line")
+-
+  I check if the information of the logistic requisition are propagated correctly
+-
+  !python {model: logistic.requisition}: |
+    req = self.browse(cr, uid, ref("logistic_requisition_cost_estimate_01"))
+    sale_obj = self.pool.get('sale.order')
+    sale_ids = sale_obj.search(cr, uid, [('requisition_id', '=', req.id)])
+    assert len(sale_ids) == 1
+    sale = sale_obj.browse(cr, uid, sale_ids[0])
+    assert sale.partner_id == req.partner_id
+    assert sale.partner_invoice_id == req.partner_id
+    assert sale.consignee_id == req.consignee_id
+    assert sale.incoterm == req.incoterm_id
+    assert sale.incoterm_address == req.incoterm_address
+    assert sale.project_id == req.analytic_id
+-
+  I check if the information of the lines is correct
+-
+  !python {model: logistic.requisition.source}: |
+    def check_line(self, cr, uid, line_id):
+        # the upper scope is not accessible here,
+        # that's why self, cr, uid are passed as arguments
+        sale_line_obj = self.pool.get('sale.order.line')
+        sale_line_ids = sale_line_obj.search(
+            cr, uid, [('logistic_requisition_source_id', '=', line_id)])
+        assert len(sale_line_ids) == 1
+        sale_line = sale_line_obj.browse(cr, uid, sale_line_ids[0])
+        source = self.browse(cr, uid, line_id)
+        line = source.requisition_line_id
+        assert sale_line.product_id == source.proposed_product_id, (
+            "product_id should be %s, received %s" %
+            (source.proposed_product_id, sale_line.product_id))
+
+        assert sale_line.name == line.description, (
+            "name should be %s, received %s" %
+            (line.description, sale_line.name))
+
+        assert sale_line.product_uom_qty == source.proposed_qty, (
+            "qty should be %s, received %s" %
+            (source.proposed_qty, sale_line.product_uom_qty))
+
+        assert sale_line.product_uom == source.proposed_uom_id, (
+            "unit of measure should be %s, received %s" %
+            (source.proposed_uom_id, sale_line.product_uom))
+
+        assert sale_line.price_unit == source.unit_cost, (
+            "price_unit should be %s, received %s" %
+            (source.unit_cost, sale_line.price_unit))
+
+        assert sale_line.price_is == source.price_is, (
+            "price_is should be %s, received %s" %
+            (source.price_is, sale_line.price_is))
+        assert_type = ('make_to_stock'
+                       if source.procurement_method == 'wh_dispatch'
+                       else 'make_to_order')
+        assert sale_line.type == assert_type, (
+            "Type should be %s, received: %s" % (assert_type, sale_line.type))
+
+        if source.procurement_method != 'wh_dispatch':
+            assert sale_line.sale_flow == 'direct_delivery', (
+                "A line not in 'Warehouse dispatch' should be in direct delivery")
+
+        if source.dispatch_location_id:
+            assert sale_line.location_id == source.dispatch_location_id, (
+                "dispatch should be %s, received %s" %
+                (source.dispatch_location_id, sale_line.location_id))
+        else:
+            assert not sale_line.location_id, (
+                "No dispatch location on requisition line, but received a "
+                "location in sale order line")
+
+    source1_id = ref("logistic_requisition_source_cost_estimate_01")
+    source2_id = ref("logistic_requisition_source_cost_estimate_02")
+    check_line(self, cr, uid, source1_id)
+    check_line(self, cr, uid, source2_id)

=== added directory 'logistic_requisition_budget/tests'
=== added file 'logistic_requisition_budget/tests/__init__.py'
--- logistic_requisition_budget/tests/__init__.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/tests/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Romain Deheele
+#    Copyright 2014 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import test_purchase_split_requisition
+
+
+fast_suite = [
+]
+
+checks = [
+    test_purchase_split_requisition,
+]

=== added file 'logistic_requisition_budget/tests/test_purchase_split_requisition.py'
--- logistic_requisition_budget/tests/test_purchase_split_requisition.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/tests/test_purchase_split_requisition.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author: Guewen Baconnier
+#    Copyright 2013 Camptocamp SA
+#
+#    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
+#    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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+import unittest2
+from functools import partial
+
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as D_FMT
+from openerp.osv import orm
+import openerp.tests.common as common
+from openerp import SUPERUSER_ID
+from openerp.addons.logistic_requisition.tests import logistic_requisition
+from openerp.addons.logistic_requisition.tests import purchase_requisition
+from openerp.addons.logistic_requisition.tests import purchase_order
+
+
+class test_purchase_split_requisition(common.TransactionCase):
+    """ Test the split of the logistics requisition lines
+    according to the purchase order lines choosed during the
+    purchase requisition process.
+
+    A bit of context:
+
+    We create a logistics requisition with several lines.
+    For each line, we create a purchase requisition.
+    During the purchase requisition process, we'll send requests
+    for quotations to several suppliers. Once the call is closed,
+    we'll have a few RfQ with different amounts. We'll choose
+    which lines we want to confirm.
+    A purchase order will be generated with the final choice, at this
+    point, for 1 logistics requisition line, we may have several
+    purchase order line. We have to split the logistics requisition
+    lines in order to have the same quantities than the purchase lines.
+
+    The purpose of the tests here is to check if the split is done
+    correctly.
+    """
+
+    def setUp(self):
+        super(test_purchase_split_requisition, self).setUp()
+        cr, uid = self.cr, self.uid
+        self.ir_model_data = self.registry('ir.model.data')
+        self.log_req = self.registry('logistic.requisition')
+        self.log_req_line = self.registry('logistic.requisition.line')
+        self.purchase_order = self.registry('purchase.order')
+        self.get_ref = partial(self.ir_model_data.get_object_reference,
+                               self.cr, self.uid)
+
+        __, self.partner_1 = self.get_ref('base', 'res_partner_1')
+        __, self.partner_3 = self.get_ref('base', 'res_partner_3')
+        __, self.partner_4 = self.get_ref('base', 'res_partner_4')
+        __, self.partner_12 = self.get_ref('base', 'res_partner_12')
+        __, self.user_demo = self.get_ref('base', 'user_demo')
+        __, self.product_7 = self.get_ref('product', 'product_product_7')
+        __, self.product_uom_pce = self.get_ref('product', 'product_uom_unit')
+        __, self.pricelist_sale = self.get_ref('product','list0')
+        
+        vals = {
+            'partner_id': self.partner_4,
+            'consignee_id': self.partner_3,
+            'date_delivery': time.strftime(D_FMT),
+            'user_id': self.user_demo,
+            'pricelist_id': self.pricelist_sale,
+        }
+        line = {
+            'product_id': self.product_7,
+            'requested_qty': 100,
+            'requested_uom_id': self.product_uom_pce,
+            'date_delivery': time.strftime(D_FMT),
+        }
+        source = {
+            'proposed_qty': 100,
+            'proposed_product_id': self.product_7,
+            'proposed_uom_id': self.product_uom_pce,
+            'transport_applicable': 0,
+            'procurement_method': 'procurement',
+            'price_is': 'estimated',
+        }
+        self.requisition_id = logistic_requisition.create(self, vals)
+        self.line_id = logistic_requisition.add_line(self, self.requisition_id,
+                                                     line)
+        self.source_id = logistic_requisition.add_source(self, self.line_id,
+                                                         source)
+        logistic_requisition.confirm(self, self.requisition_id)
+        logistic_requisition.assign_lines(self, [self.line_id], self.user_demo)
+        purch_req_id = logistic_requisition.create_purchase_requisition(
+            self, self.source_id)
+        purchase_requisition.confirm_call(self, purch_req_id)
+        purch_req_model = self.registry('purchase.requisition')
+        self.purchase_requisition = purch_req_model.browse(
+            cr, uid, purch_req_id)
+        dp_obj = self.registry('decimal.precision')
+        self.uom_precision = dp_obj.precision_get(cr, SUPERUSER_ID,
+                                                  'Product Unit of Measure')
+
+    def test_split_too_many_products_selected_budget_exceeded(self):
+        """ Create a call for bids from the logistic requisition, 2 po line choosed (budget exceeded)
+
+        30 items in a first purchase order and 80 items in a second one,
+        for a total of 110 items. That means 110 products have been ordered
+        but 100 only have been ordered at the origin.
+
+        The total cost is greater than the requested budget.
+        We should not be able to propose more than requested financially.
+        """
+        # create a first draft bid and select a part of the line
+        purchase1, bid_line1 = purchase_requisition.create_draft_purchase_order(
+            self, self.purchase_requisition.id, self.partner_1)
+        bid_line1.write({'price_unit': 15})
+        purchase_order.select_line(self, bid_line1.id, 30)
+        purchase_order.bid_encoded(self, purchase1.id)
+
+        # create a second draft bid and select a part of the line
+        purchase2, bid_line2 = purchase_requisition.create_draft_purchase_order(
+            self, self.purchase_requisition.id, self.partner_12)
+        bid_line2.write({'price_unit': 13})
+        purchase_order.select_line(self, bid_line2.id, 80)
+        purchase_order.bid_encoded(self, purchase2.id)
+
+        # close the call for bids
+        purchase_requisition.close_call(self, self.purchase_requisition.id)
+        # selection of bids will trigger the split of lines
+        # the generation of po fails because the budget is exceeded
+        with self.assertRaises(orm.except_orm):
+            purchase_requisition.bids_selected(self,
+                                               self.purchase_requisition.id)

=== added directory 'logistic_requisition_budget/view'
=== added file 'logistic_requisition_budget/view/logistic_requisition.xml'
--- logistic_requisition_budget/view/logistic_requisition.xml	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/view/logistic_requisition.xml	2014-03-10 15:39:56 +0000
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+
+    <record model="ir.ui.view" id="view_logistic_requisition_budget_form">
+        <field name="name">logistic.requisition.budget.form</field>
+        <field name="model">logistic.requisition</field>
+        <field name="inherit_id" ref="logistic_requisition.view_logistic_requisition_form"/>
+        <field name="arch" type="xml">
+             <xpath expr="//page[@string='Requisition Lines']/field[@name='line_ids']/tree/field[@name='date_delivery']" position="after">
+                 <field name="budget_unit_price"/>
+                 <field name="budget_tot_price"/>
+             </xpath>
+             <xpath expr="//page[@string='Requisition Lines']/field[@name='line_ids']" position="after">
+                        <group class="oe_subtotal_footer oe_right">
+                            <field name="amount_total"
+                                class="oe_subtotal_footer_separator"
+                                widget="monetary"
+                                options="{'currency_field': 'currency_id'}"/>
+                        </group>
+                        <div class="oe_clear"/>
+                        <group string="Validation">
+                            <div colspan="4">
+                                <label for="budget_holder_id"/>
+                                <field name="budget_holder_id"
+                                    on_change="onchange_validate(budget_holder_id, date_budget_holder, 'date_budget_holder')"
+                                    class="oe_inline"/>
+                                <label string=" validated on "
+                                    attrs="{'invisible': [('budget_holder_id', '=', False)]}" />
+                                <field name="date_budget_holder"
+                                    attrs="{'invisible': [('budget_holder_id', '=', False)]}"
+                                    class="oe_inline"/>
+                            </div>
+                            <div colspan="4">
+                                <label for="finance_officer_id"/>
+                                <field name="finance_officer_id"
+                                    on_change="onchange_validate(finance_officer_id, date_finance_officer, 'date_finance_officer')"
+                                    class="oe_inline"/>
+                                <label string=" validated on "
+                                    attrs="{'invisible': [('finance_officer_id', '=', False)]}"/>
+                                <field name="date_finance_officer"
+                                    attrs="{'invisible': [('finance_officer_id', '=', False)]}"
+                                    class="oe_inline"/>
+                            </div>
+                        </group>
+             </xpath>
+        </field>
+       </record>
+
+    
+    <record model="ir.ui.view" id="view_logistic_requisition_budget_tree">
+        <field name="name">logistic.requisition.budget.tree</field>
+        <field name="model">logistic.requisition</field>
+        <field name="inherit_id" ref="logistic_requisition.view_logistic_requisition_tree"/>
+        <field name="arch" type="xml">
+             <xpath expr="//field[@name='analytic_id']" position="after">
+                <field name="amount_total" sum="Total Budget"/>
+             </xpath>
+        </field>
+       </record>
+
+    <record model="ir.ui.view" id="view_logistic_requisition_line_budget_tree">
+        <field name="name">logistic.requisition.line.budget.tree</field>
+        <field name="model">logistic.requisition.line</field>
+        <field name="inherit_id" ref="logistic_requisition.view_logistic_requisition_line_tree"/>
+        <field name="arch" type="xml">
+             <xpath expr="//field[@name='logistic_user_id']" position="after">
+                <field name="budget_tot_price" sum="Total Budget"/>
+             </xpath>
+        </field>
+       </record>
+
+    <record model="ir.ui.view" id="view_logistic_requisition_line_budget_form">
+        <field name="name">logistic.requisition.line.budget.form</field>
+        <field name="model">logistic.requisition.line</field>
+        <field name="inherit_id" ref="logistic_requisition.view_logistic_requisition_line_form"/>        
+        <field name="arch" type="xml">
+             <xpath expr="//form[@string='Logistic Requisition Line']/sheet/group/group/field[@name='currency_id']" position="after">
+                            <field name="budget_unit_price" widget="monetary"
+                                options="{'currency_field': 'currency_id'}"/>
+                            <field name="budget_tot_price" widget="monetary"
+                                options="{'currency_field': 'currency_id'}"/>
+             </xpath>
+        </field>
+       </record>                                
+
+
+    </data>
+</openerp>

=== added directory 'logistic_requisition_budget/wizard'
=== added file 'logistic_requisition_budget/wizard/__init__.py'
--- logistic_requisition_budget/wizard/__init__.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/wizard/__init__.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author:  Joël Grand-Guillaume
+#    Copyright 2013 Camptocamp SA
+#
+#    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 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 Affero General Public License for more description.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import cost_estimate

=== added file 'logistic_requisition_budget/wizard/cost_estimate.py'
--- logistic_requisition_budget/wizard/cost_estimate.py	1970-01-01 00:00:00 +0000
+++ logistic_requisition_budget/wizard/cost_estimate.py	2014-03-10 15:39:56 +0000
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Author:  Joël Grand-Guillaume
+#    Copyright 2013 Camptocamp SA
+#
+#    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 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 Affero General Public License for more description.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv import fields, orm
+from openerp.tools.translate import _
+
+
+class logistic_requisition_cost_estimate(orm.TransientModel):
+    _inherit = 'logistic.requisition.cost.estimate'
+
+    def _check_requisition(self, cr, uid, requisition, context=None):
+        """ Check the rules to create a cost estimate from the
+        requisition
+
+        :returns: list of tuples ('message, 'error_code')
+        """
+        errors = []
+        if not requisition.budget_holder_id:
+            error = (_('The requisition must be validated '
+                       'by the Budget Holder.'),
+                     'NO_BUDGET_VALID')
+            errors.append(error)
+        return errors


Follow ups