[CHG] reverse cardinality: many stock.reservation have 1 sale.order.line. in fact usually it would be 1-1 but make more sense to have the relation on stock.reservation

This commit is contained in:
Guewen Baconnier
2013-09-09 10:59:48 +02:00
parent 1887ef284e
commit 88fef99a8e
7 changed files with 115 additions and 22 deletions

View File

@@ -55,6 +55,7 @@ insufficient at the order date, you may want to install the
'demo': [],
'data': ['wizard/sale_stock_reserve_view.xml',
'view/sale.xml',
'view/stock_reserve.xml',
],
'auto_install': False,
'test': [],

View File

@@ -20,3 +20,4 @@
##############################################################################
from . import sale
from . import stock_reserve

View File

@@ -33,7 +33,7 @@ class sale_order(orm.Model):
'is_stock_reservable': False}
for sale in self.browse(cr, uid, ids, context=context):
for line in sale.order_line:
if line.reservation_id:
if line.reservation_ids:
result[sale.id]['has_stock_reservation'] = True
if line.is_stock_reservable:
result[sale.id]['is_stock_reservable'] = True
@@ -81,13 +81,14 @@ class sale_order_line(orm.Model):
continue
if (not line.product_id or line.product_id.type == 'service'):
continue
if not line.reservation_id:
if not line.reservation_ids:
result[line.id] = True
return result
_columns = {
'reservation_id': fields.many2one(
'reservation_ids': fields.one2many(
'stock.reservation',
'sale_line_id',
string='Stock Reservation'),
'is_stock_reservable': fields.function(
_is_stock_reservable,
@@ -99,25 +100,27 @@ class sale_order_line(orm.Model):
def copy_data(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
default['reservation_id'] = False
default['reservation_ids'] = False
return super(sale_order_line, self).copy_data(
cr, uid, id, default=default, context=context)
def release_stock_reservation(self, cr, uid, ids, context=None):
lines = self.browse(cr, uid, ids, context=context)
reserv_ids = [line.reservation_id.id for line in lines
if line.reservation_id]
reserv_ids = [reserv.id for line in lines
for reserv in line.reservation_ids]
reserv_obj = self.pool.get('stock.reservation')
reserv_obj.release(cr, uid, reserv_ids, context=context)
self.write(cr, uid, ids, {'reservation_id': False}, context=context)
return True
def update_stock_reservation(self, cr, uid, ids, context=None):
reserv_obj = self.pool.get('stock.reservation')
for line in self.browse(cr, uid, ids, context=context):
if not line.reservation_id:
if not line.reservation_ids:
continue
line.reservation_id.write({'product_qty': line.product_uom_qty,
'product_uom': line.product_uom.id})
reserv_ids = [reserv.id for reserv in line.reservation_ids]
vals = {'product_qty': line.product_uom_qty,
'product_uom': line.product_uom.id}
reserv_obj.write(cr, uid, reserv_ids, vals, context=context)
return True
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
@@ -133,7 +136,7 @@ class sale_order_line(orm.Model):
return result
assert len(ids) == 1, "Expected 1 ID, got %r" % ids
line = self.browse(cr, uid, ids[0], context=context)
if qty != line.product_uom_qty and line.reservation_id:
if qty != line.product_uom_qty and line.reservation_ids:
msg = _("As you changed the quantity of the line, "
"the quantity of the stock reservation will "
"be automatically adjusted to %.2f.") % qty
@@ -157,7 +160,7 @@ class sale_order_line(orm.Model):
test_update = keys.intersection(update_on_reserve)
if test_block:
for line in self.browse(cr, uid, ids, context=context):
if not line.reservation_id:
if not line.reservation_ids:
continue
raise orm.except_orm(
_('Error'),
@@ -168,9 +171,17 @@ class sale_order_line(orm.Model):
res = super(sale_order_line, self).write(cr, uid, ids, vals, context=context)
if test_update:
for line in self.browse(cr, uid, ids, context=context):
if not line.reservation_id:
if not line.reservation_ids:
continue
line.reservation_id.write(
if len(line.reservation_ids) > 1:
raise orm.except_orm(
_('Error'),
_('Several stock reservations are linked with the '
'line. Impossible to adjust their quantity. '
'Please release the reservation '
'before changing the quantity.'))
line.reservation_ids[0].write(
{'price_unit': line.price_unit,
'product_qty': line.product_uom_qty,
'product_uos_qty': line.product_uos_qty,

View File

@@ -0,0 +1,50 @@
# -*- 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/>.
#
##############################################################################
from openerp.osv import orm, fields
class stock_reservation(orm.Model):
_inherit = 'stock.reservation'
_columns = {
'sale_line_id': fields.many2one(
'sale.order.line',
string='Sale Order Line',
ondelete='cascade'),
'sale_id': fields.related(
'sale_line_id', 'order_id',
type='many2one',
relation='sale.order',
string='Sale Order')
}
def release(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'sale_line_id': False}, context=context)
return super(stock_reservation, self).release(
cr, uid, ids, context=context)
def copy_data(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
default['sale_line_id'] = False
return super(stock_reservation, self).copy_data(
cr, uid, id, default=default, context=context)

View File

@@ -25,17 +25,17 @@
<button name="%(action_sale_stock_reserve)d"
type="action"
string="Reserve Stock"
attrs="{'invisible': ['|', ('reservation_id', '!=', False),
attrs="{'invisible': ['|', ('reservation_ids', '!=', []),
('state', '!=', 'draft')]}" />
<button name="release_stock_reservation"
type="object"
string="Release Reservation"
attrs="{'invisible': ['|', ('reservation_id', '=', False),
attrs="{'invisible': ['|', ('reservation_ids', '=', []),
('state', '!=', 'draft')]}" />
</xpath>
<xpath expr="//field[@name='order_line']/tree/field[@name='price_subtotal']" position="after">
<field name="reservation_id" invisible="1"/>
<field name="reservation_ids" invisible="1"/>
<field name="is_stock_reservable" invisible="1"/>
<button name="%(action_sale_stock_reserve)d"
type="action"
@@ -46,13 +46,13 @@
type="object"
string="Release Reservation"
icon="gtk-undo"
attrs="{'invisible': [('reservation_id', '=', False)]}" />
attrs="{'invisible': [('reservation_ids', '=', [])]}" />
</xpath>
<xpath expr="//field[@name='order_line']/form//field[@name='type']" position="after">
<label for="reservation_id" />
<div attrs="{'invisible': [('reservation_id', '=', False)]}">
<field name="reservation_id" readonly="1"
<label for="reservation_ids" />
<div attrs="{'invisible': [('reservation_ids', '=', False)]}">
<field name="reservation_ids" readonly="1"
class="oe_inline"/>
<button name="update_stock_reservation"
string="update"

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record id="view_stock_reservation_form" model="ir.ui.view">
<field name="name">stock.reservation.form</field>
<field name="model">stock.reservation</field>
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_form"/>
<field name="arch" type="xml">
<group name="location" position="after">
<group name="sale" string="Sales">
<field name="sale_id"/>
<field name="sale_line_id"/>
</group>
</group>
</field>
</record>
<record id="view_stock_reservation_tree" model="ir.ui.view">
<field name="name">stock.reservation.tree</field>
<field name="model">stock.reservation</field>
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_tree"/>
<field name="arch" type="xml">
<field name="move_id" position="before">
<field name="sale_id"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -69,6 +69,7 @@ class sale_stock_reserve(orm.TransientModel):
'product_uos_qty': line.product_uos_qty,
'product_uos': product_uos,
'price_unit': line.price_unit,
'sale_line_id': line.id,
}
def stock_reserve(self, cr, uid, ids, line_ids, context=None):
@@ -85,7 +86,6 @@ class sale_stock_reserve(orm.TransientModel):
context=context)
reserv_id = reserv_obj.create(cr, uid, vals, context=context)
reserv_obj.reserve(cr, uid, [reserv_id], context=context)
line.write({'reservation_id': reserv_id})
return True
def button_reserve(self, cr, uid, ids, context=None):