From 3e87ec567ee73b754b06088df2d82294bcf7a30c Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Thu, 16 Jan 2014 14:39:05 +0100
Subject: [PATCH 01/20] [FIX]remove unneeded code to compute qty available in
product module, use the one defined in stock instead
lp bug: https://launchpad.net/bugs/1268989 fixed
bzr revid: csn@openerp.com-20140116133905-en7y1b9tibstcou3
---
addons/product/product.py | 14 --------------
addons/product/product_view.xml | 4 +---
addons/stock/product_view.xml | 16 ++++++++++++++++
3 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/addons/product/product.py b/addons/product/product.py
index 4b63100dbee..20346d0a0ee 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -508,16 +508,6 @@ class product_product(osv.osv):
res.setdefault(id, 0.0)
return res
- def _get_product_available_func(states, what):
- def _product_available(self, cr, uid, ids, name, arg, context=None):
- return {}.fromkeys(ids, 0.0)
- return _product_available
-
- _product_qty_available = _get_product_available_func(('done',), ('in', 'out'))
- _product_virtual_available = _get_product_available_func(('confirmed','waiting','assigned','done'), ('in', 'out'))
- _product_outgoing_qty = _get_product_available_func(('confirmed','waiting','assigned'), ('out',))
- _product_incoming_qty = _get_product_available_func(('confirmed','waiting','assigned'), ('in',))
-
def _product_lst_price(self, cr, uid, ids, name, arg, context=None):
res = {}
product_uom_obj = self.pool.get('product.uom')
@@ -622,10 +612,6 @@ class product_product(osv.osv):
_inherit = ['mail.thread']
_order = 'default_code,name_template'
_columns = {
- 'qty_available': fields.function(_product_qty_available, type='float', string='Quantity On Hand'),
- 'virtual_available': fields.function(_product_virtual_available, type='float', string='Quantity Available'),
- 'incoming_qty': fields.function(_product_incoming_qty, type='float', string='Incoming'),
- 'outgoing_qty': fields.function(_product_outgoing_qty, type='float', string='Outgoing'),
'price': fields.function(_product_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
'lst_price' : fields.function(_product_lst_price, type='float', string='Public Price', digits_compute=dp.get_precision('Product Price')),
'code': fields.function(_product_code, type='char', string='Internal Reference'),
diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml
index e9aac7419c8..241087c56e2 100644
--- a/addons/product/product_view.xml
+++ b/addons/product/product_view.xml
@@ -33,14 +33,12 @@
product.product
-
+
-
-
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index 277ec5b40e5..583a9585374 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -14,6 +14,22 @@
+
+ product.stock.tree.inherit
+ product.product
+
+
+
+
+
+
+
+
+ {'red':virtual_available<0, 'blue':virtual_available>=0 and state in ('draft', 'end', 'obsolete'), 'black':virtual_available>=0 and state not in ('draft', 'end', 'obsolete')}
+
+
+
+
product.template.stock.property.form.inheritproduct.template
From 9dc64a216be3b3b5b893c7c9be6b9c14ef6b56c3 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Fri, 17 Jan 2014 10:20:11 +0100
Subject: [PATCH 02/20] [FIX]add search function and filter for
virtual_available and qty_available on product
bzr revid: csn@openerp.com-20140117092011-5c0qu2a2xor29g7u
---
addons/stock/product.py | 18 ++++++++++++++++++
addons/stock/product_view.xml | 6 ++++++
2 files changed, 24 insertions(+)
diff --git a/addons/stock/product.py b/addons/stock/product.py
index 6ca53a5ad0d..ff39190355a 100644
--- a/addons/stock/product.py
+++ b/addons/stock/product.py
@@ -148,12 +148,29 @@ class product_product(osv.osv):
return res
+ def _search_product_quantity(self, cr, uid, obj, name, args, context):
+ res = []
+ for field, operator, value in args:
+ if operator == '=':
+ operator = '=='
+
+ product_ids = self.search(cr, uid, [], context=context)
+ ids = []
+ if product_ids:
+ for element in self.browse(cr, uid, product_ids, context=context):
+ if eval(str(element[field]) + operator + str(value)):
+ ids.append(element.id)
+ res.append(('id', 'in', ids))
+ return res
+
+
_columns = {
'reception_count': fields.function(_stock_move_count, string="Reception", type='integer', multi='pickings'),
'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'),
'qty_available': fields.function(_product_available, multi='qty_available',
type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
string='Quantity On Hand',
+ fnct_search=_search_product_quantity,
help="Current quantity of products.\n"
"In a context with a single Stock Location, this includes "
"goods stored at this Location, or any of its children.\n"
@@ -167,6 +184,7 @@ class product_product(osv.osv):
'virtual_available': fields.function(_product_available, multi='qty_available',
type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
string='Forecasted Quantity',
+ fnct_search=_search_product_quantity,
help="Forecast quantity (computed as Quantity On Hand "
"- Outgoing + Incoming)\n"
"In a context with a single Stock Location, this includes "
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index 583a9585374..7a9218436af 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -11,6 +11,12 @@
+
+
+
+
+
+
From 0f7ca6e784b51abac7d32094fcc634aa8bd39394 Mon Sep 17 00:00:00 2001
From: "Jitendra Prajapati (OpenERP)"
Date: Mon, 20 Jan 2014 12:22:22 +0530
Subject: [PATCH 03/20] [FIX]mrp_repair:set unique constraint on name
bzr revid: prajapatijitendra7969@gmail.com-20140120065222-05hw8t0ca05mq7r4
---
addons/mrp_repair/mrp_repair.py | 4 ++++
addons/mrp_repair/mrp_repair_demo.yml | 3 ---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index b178d4e12a4..c287bbff56d 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -186,6 +186,10 @@ class mrp_repair(osv.osv):
'pricelist_id': lambda self, cr, uid,context : self.pool.get('product.pricelist').search(cr, uid, [('type','=','sale')])[0]
}
+ _sql_constraints = [
+ ('name', 'unique (name)', 'The name of the Repair Order must be unique!'),
+ ]
+
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
diff --git a/addons/mrp_repair/mrp_repair_demo.yml b/addons/mrp_repair/mrp_repair_demo.yml
index 1299cbfb6d2..93fc19a1f91 100644
--- a/addons/mrp_repair/mrp_repair_demo.yml
+++ b/addons/mrp_repair/mrp_repair_demo.yml
@@ -20,7 +20,6 @@
location_id: stock.stock_location_14
picking_type_id: stock.picking_type_out
move_id: 'stock_move_pcbasicpc0'
- name: RMA00004
operations:
- location_dest_id: stock.location_production
location_id: stock.stock_location_stock
@@ -62,7 +61,6 @@
location_id: stock.stock_location_14
picking_type_id: stock.picking_type_out
move_id: 'stock.stock_move_stockmvmrp1'
- name: RMA-00007
operations:
- location_dest_id: stock.location_production
location_id: stock.stock_location_stock
@@ -104,7 +102,6 @@
location_id: stock.stock_location_14
picking_type_id: stock.picking_type_out
move_id: 'stock.stock_move_stockmvmrp2'
- name: RMA-00011
operations:
- location_dest_id: stock.location_production
location_id: stock.stock_location_stock
From 86e7d60e23643b4cadd32a7273824e5845fc2dc9 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Tue, 21 Jan 2014 11:51:00 +0100
Subject: [PATCH 04/20] [FIX]add some filter to search product qty
bzr revid: csn@openerp.com-20140121105100-offsz1so77u4z0x8
---
addons/stock/product_view.xml | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index 7a9218436af..76ae15475ce 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -13,9 +13,11 @@
-
-
-
+
+
+
+
+
From fbd144c9e7e6f78556fbdc1b91eea66e36384f39 Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 22 Jan 2014 13:31:59 +0100
Subject: [PATCH 05/20] [WIP] Start changing move to quant
bzr revid: jco@openerp.com-20140122123159-v9tvkzrry61a6n39
---
addons/mrp_repair/mrp_repair.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index b178d4e12a4..9fd49d5840f 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -139,7 +139,7 @@ class mrp_repair(osv.osv):
\n* The \'Cancelled\' status is used when user cancel repair order.'),
'location_id': fields.many2one('stock.location', 'Current Location', select=True, readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
- 'move_id': fields.many2one('stock.move', 'Move',required=True, domain="[('product_id','=',product_id)]", readonly=True, states={'draft':[('readonly',False)]}),
+ 'quant_id': fields.many2one('stock.quant', 'Quant',required=True, domain="[('product_id','=',product_id)]", readonly=True, states={'draft':[('readonly',False)]}),
'guarantee_limit': fields.date('Warranty Expiration', help="The warranty expiration limit is computed as: last move date + warranty defined on selected product. If the current date is below the warranty expiration limit, each operation and fee you will add will be set as 'not to invoiced' by default. Note that you can change manually afterwards.", states={'confirmed':[('readonly',True)]}),
'operations' : fields.one2many('mrp.repair.line', 'repair_id', 'Operation Lines', readonly=True, states={'draft':[('readonly',False)]}),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', help='Pricelist of the selected partner.'),
@@ -205,25 +205,26 @@ class mrp_repair(osv.osv):
@return: Dictionary of values.
"""
return {'value': {
- 'move_id': False,
+ 'quant_id': False,
'guarantee_limit' :False,
'location_id': False,
'location_dest_id': False,
}
}
- def onchange_move_id(self, cr, uid, ids, prod_id=False, move_id=False):
+ def onchange_quant_id(self, cr, uid, ids, prod_id=False, quant_id=False):
""" On change of move id sets values of guarantee limit, source location,
destination location, partner and partner address.
@param prod_id: Id of product in current record.
- @param move_id: Changed move.
+ @param quant_id: Quant to handle
@return: Dictionary of values.
"""
data = {}
data['value'] = {'guarantee_limit': False, 'location_id': False, 'partner_id': False}
- if not prod_id:
+ if prod_id and
+ if not prod_id and not quant_id:
return data
- if move_id:
+ if quant_id:
move = self.pool.get('stock.move').browse(cr, uid, move_id)
product = self.pool.get('product.product').browse(cr, uid, prod_id)
limit = datetime.strptime(move.date_expected, '%Y-%m-%d %H:%M:%S') + relativedelta(months=int(product.warranty))
From a173b17ce3e96fb0e97bc7337a8bf8cf0d8af70a Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 22 Jan 2014 15:39:51 +0100
Subject: [PATCH 06/20] [IMP] Use quant instead of move
bzr revid: jco@openerp.com-20140122143951-vywil9totup32kib
---
addons/mrp_repair/mrp_repair.py | 58 +++++----------------------
addons/mrp_repair/mrp_repair_view.xml | 4 +-
2 files changed, 13 insertions(+), 49 deletions(-)
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index 9fd49d5840f..45db1cb4ede 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -139,7 +139,7 @@ class mrp_repair(osv.osv):
\n* The \'Cancelled\' status is used when user cancel repair order.'),
'location_id': fields.many2one('stock.location', 'Current Location', select=True, readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
- 'quant_id': fields.many2one('stock.quant', 'Quant',required=True, domain="[('product_id','=',product_id)]", readonly=True, states={'draft':[('readonly',False)]}),
+ 'quant_id': fields.many2one('stock.quant', 'Quant',required=True, domain="[('product_id','=',product_id), ('qty', '>', 0.0)]", readonly=True, states={'draft':[('readonly',False)]}),
'guarantee_limit': fields.date('Warranty Expiration', help="The warranty expiration limit is computed as: last move date + warranty defined on selected product. If the current date is below the warranty expiration limit, each operation and fee you will add will be set as 'not to invoiced' by default. Note that you can change manually afterwards.", states={'confirmed':[('readonly',True)]}),
'operations' : fields.one2many('mrp.repair.line', 'repair_id', 'Operation Lines', readonly=True, states={'draft':[('readonly',False)]}),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', help='Pricelist of the selected partner.'),
@@ -221,22 +221,16 @@ class mrp_repair(osv.osv):
"""
data = {}
data['value'] = {'guarantee_limit': False, 'location_id': False, 'partner_id': False}
- if prod_id and
if not prod_id and not quant_id:
return data
if quant_id:
- move = self.pool.get('stock.move').browse(cr, uid, move_id)
- product = self.pool.get('product.product').browse(cr, uid, prod_id)
- limit = datetime.strptime(move.date_expected, '%Y-%m-%d %H:%M:%S') + relativedelta(months=int(product.warranty))
+ quant = self.pool.get('stock.quant').browse(cr, uid, quant_id)
+ product = quant.product_id
+ data['value']['product_id'] = product.id
+ limit = quant.in_date and datetime.strptime(quant.in_date, '%Y-%m-%d %H:%M:%S') or datetime.strptime(quant.create_date, '%Y-%m-%d %H:%M:%S') + relativedelta(months=int(product.warranty))
data['value']['guarantee_limit'] = limit.strftime('%Y-%m-%d')
- data['value']['location_id'] = move.location_dest_id.id
- data['value']['location_dest_id'] = move.location_dest_id.id
- if move.partner_id:
- data['value']['partner_id'] = move.partner_id.id
- else:
- data['value']['partner_id'] = False
- d = self.onchange_partner_id(cr, uid, ids, data['value']['partner_id'], data['value']['partner_id'])
- data['value'].update(d['value'])
+ data['value']['location_id'] = quant.location_id.id
+ data['value']['location_dest_id'] = quant.location_id.id
return data
def button_dummy(self, cr, uid, ids, context=None):
@@ -268,39 +262,6 @@ class mrp_repair(osv.osv):
}
}
- def onchange_lot_id(self, cr, uid, ids, lot, product_id):
- """ On change of Serial Number sets the values of source location,
- destination location, move and guarantee limit.
- @param lot: Changed id of Serial Number.
- @param product_id: Product id from current record.
- @return: Dictionary of values.
- """
- move_obj = self.pool.get('stock.move')
- data = {}
- data['value'] = {
- 'location_id': False,
- 'location_dest_id': False,
- 'move_id': False,
- 'guarantee_limit': False
- }
-
- if not lot:
- return data
-
- if not len(move_ids):
- return data
-
- def get_last_move(lst_move):
- while lst_move.move_dest_id and lst_move.move_dest_id.state == 'done':
- lst_move = lst_move.move_dest_id
- return lst_move
-
- move_id = move_ids[0]
- move = get_last_move(move_obj.browse(cr, uid, move_id))
- data['value']['move_id'] = move.id
- d = self.onchange_move_id(cr, uid, ids, product_id, move.id)
- data['value'].update(d['value'])
- return data
def action_cancel_draft(self, cr, uid, ids, *args):
""" Cancels repair order when it is in 'Draft' state.
@@ -544,6 +505,9 @@ class mrp_repair(osv.osv):
'state': 'assigned',
})
pick_obj.signal_button_confirm(cr, uid, [picking])
+ quants = [(repair.quant_id, repair.quant_id.qty)]
+ move = move_obj.browse(cr, uid, move_id, context=context)
+ self.pool.get("stock.quant").quants_reserve(cr, uid, quants, move, context=context)
self.write(cr, uid, [repair.id], {'state': 'done', 'picking_id': picking})
res[repair.id] = picking
else:
@@ -609,7 +573,7 @@ class mrp_repair_line(osv.osv, ProductChangeMixin):
def copy_data(self, cr, uid, id, default=None, context=None):
if not default: default = {}
- default.update( {'invoice_line_id': False, 'move_id': False, 'invoiced': False, 'state': 'draft'})
+ default.update( {'invoice_line_id': False, 'quant_id': False, 'invoiced': False, 'state': 'draft'})
return super(mrp_repair_line, self).copy_data(cr, uid, id, default, context)
def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml
index 4e799ff8709..0a1578104fa 100644
--- a/addons/mrp_repair/mrp_repair_view.xml
+++ b/addons/mrp_repair/mrp_repair_view.xml
@@ -9,7 +9,7 @@
-
+
@@ -47,7 +47,7 @@
-
+
From 2213f6f102f06a0045cd157d613085006d5f3a4b Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 22 Jan 2014 16:35:19 +0100
Subject: [PATCH 07/20] [IMP] Add lot on mrp_repair operations
bzr revid: jco@openerp.com-20140122153519-zs2062b653l16qb5
---
addons/mrp_repair/mrp_repair.py | 2 ++
addons/mrp_repair/mrp_repair_view.xml | 1 +
2 files changed, 3 insertions(+)
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index 45db1cb4ede..d6c45ca6733 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -471,6 +471,7 @@ class mrp_repair(osv.osv):
move_id = move_obj.create(cr, uid, {
'name': move.name,
'product_id': move.product_id.id,
+ 'restrict_lot_id': move.lot_id.id,
'product_uom_qty': move.product_uom_qty,
'product_uom': move.product_uom.id,
'partner_id': repair.address_id and repair.address_id.id or False,
@@ -606,6 +607,7 @@ class mrp_repair_line(osv.osv, ProductChangeMixin):
'location_id': fields.many2one('stock.location', 'Source Location', required=True, select=True),
'location_dest_id': fields.many2one('stock.location', 'Dest. Location', required=True, select=True),
'move_id': fields.many2one('stock.move', 'Inventory Move', readonly=True),
+ 'lot_id': fields.many2one('stock.production.lot', 'Lot'),
'state': fields.selection([
('draft','Draft'),
('confirmed','Confirmed'),
diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml
index 0a1578104fa..cf4236743ce 100644
--- a/addons/mrp_repair/mrp_repair_view.xml
+++ b/addons/mrp_repair/mrp_repair_view.xml
@@ -94,6 +94,7 @@
+
From 386f7c1212705a9cc3b2e73731bfcc4ca447dfbf Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Thu, 23 Jan 2014 18:27:41 +0100
Subject: [PATCH 08/20] [WIP] Change repair orders not to use quants, but
always to create move that splits quant from a certain location and lot
bzr revid: jco@openerp.com-20140123172741-cjgzps1twsvv0n76
---
addons/mrp_repair/mrp_repair.py | 99 ++++++++-------------------
addons/mrp_repair/mrp_repair_view.xml | 10 +--
2 files changed, 33 insertions(+), 76 deletions(-)
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index d6c45ca6733..4fc9007b034 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -25,7 +25,6 @@ from dateutil.relativedelta import relativedelta
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
-# TODO: replace move_id by quant_id everywhere
class mrp_repair(osv.osv):
_name = 'mrp.repair'
@@ -137,9 +136,9 @@ class mrp_repair(osv.osv):
\n* The \'To be Invoiced\' status is used to generate the invoice before or after repairing done. \
\n* The \'Done\' status is set when repairing is completed.\
\n* The \'Cancelled\' status is used when user cancel repair order.'),
- 'location_id': fields.many2one('stock.location', 'Current Location', select=True, readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
- 'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
- 'quant_id': fields.many2one('stock.quant', 'Quant',required=True, domain="[('product_id','=',product_id), ('qty', '>', 0.0)]", readonly=True, states={'draft':[('readonly',False)]}),
+ 'location_id': fields.many2one('stock.location', 'Current Location', select=True, required = True, readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
+ 'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, required = True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
+ 'lot_id': fields.many2one('stock.production.lot', 'Lot', domain="[('product_id','=', product_id)]", help="Lot chosen"),
'guarantee_limit': fields.date('Warranty Expiration', help="The warranty expiration limit is computed as: last move date + warranty defined on selected product. If the current date is below the warranty expiration limit, each operation and fee you will add will be set as 'not to invoiced' by default. Note that you can change manually afterwards.", states={'confirmed':[('readonly',True)]}),
'operations' : fields.one2many('mrp.repair.line', 'repair_id', 'Operation Lines', readonly=True, states={'draft':[('readonly',False)]}),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', help='Pricelist of the selected partner.'),
@@ -151,13 +150,11 @@ class mrp_repair(osv.osv):
], "Invoice Method",
select=True, required=True, states={'draft':[('readonly',False)]}, readonly=True, help='Selecting \'Before Repair\' or \'After Repair\' will allow you to generate invoice before or after the repair is done respectively. \'No invoice\' means you don\'t want to generate invoice for this repair order.'),
'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
- 'picking_id': fields.many2one('stock.picking', 'Picking',readonly=True),
+ 'move_id': fields.many2one('stock.move', 'Move',readonly=True),
'fees_lines': fields.one2many('mrp.repair.fee', 'repair_id', 'Fees Lines', readonly=True, states={'draft':[('readonly',False)]}),
'internal_notes': fields.text('Internal Notes'),
'quotation_notes': fields.text('Quotation Notes'),
'company_id': fields.many2one('res.company', 'Company'),
- 'deliver_bool': fields.boolean('Deliver', help="Check this box if you want to manage the delivery once the product is repaired and create a picking with selected product. Note that you can select the locations in the Info tab, if you have the extended view.", states={'confirmed':[('readonly',True)]}),
- 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type'),
'invoiced': fields.boolean('Invoiced', readonly=True),
'repaired': fields.boolean('Repaired', readonly=True),
'amount_untaxed': fields.function(_amount_untaxed, string='Untaxed Amount',
@@ -175,15 +172,16 @@ class mrp_repair(osv.osv):
'mrp.repair': (lambda self, cr, uid, ids, c={}: ids, ['operations'], 10),
'mrp.repair.line': (_get_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
}),
+ 'product_qty': fields.integer('Quantity', help='Product Qty'),
}
_defaults = {
'state': lambda *a: 'draft',
- 'deliver_bool': lambda *a: True,
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'mrp.repair'),
'invoice_method': lambda *a: 'none',
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.repair', context=context),
- 'pricelist_id': lambda self, cr, uid,context : self.pool.get('product.pricelist').search(cr, uid, [('type','=','sale')])[0]
+ 'pricelist_id': lambda self, cr, uid,context : self.pool.get('product.pricelist').search(cr, uid, [('type','=','sale')])[0],
+ 'product_qty': 1.0,
}
def copy(self, cr, uid, id, default=None, context=None):
@@ -194,7 +192,7 @@ class mrp_repair(osv.osv):
'repaired':False,
'invoiced':False,
'invoice_id': False,
- 'picking_id': False,
+ 'move_id': False,
'name': self.pool.get('ir.sequence').get(cr, uid, 'mrp.repair'),
})
return super(mrp_repair, self).copy(cr, uid, id, default, context)
@@ -205,33 +203,15 @@ class mrp_repair(osv.osv):
@return: Dictionary of values.
"""
return {'value': {
- 'quant_id': False,
'guarantee_limit' :False,
- 'location_id': False,
- 'location_dest_id': False,
+ 'lot_id': False,
}
}
-
- def onchange_quant_id(self, cr, uid, ids, prod_id=False, quant_id=False):
- """ On change of move id sets values of guarantee limit, source location,
- destination location, partner and partner address.
- @param prod_id: Id of product in current record.
- @param quant_id: Quant to handle
- @return: Dictionary of values.
+
+ def onchange_location_id(self, cr, uid, ids, location_id=None):
+ """ On change of location
"""
- data = {}
- data['value'] = {'guarantee_limit': False, 'location_id': False, 'partner_id': False}
- if not prod_id and not quant_id:
- return data
- if quant_id:
- quant = self.pool.get('stock.quant').browse(cr, uid, quant_id)
- product = quant.product_id
- data['value']['product_id'] = product.id
- limit = quant.in_date and datetime.strptime(quant.in_date, '%Y-%m-%d %H:%M:%S') or datetime.strptime(quant.create_date, '%Y-%m-%d %H:%M:%S') + relativedelta(months=int(product.warranty))
- data['value']['guarantee_limit'] = limit.strftime('%Y-%m-%d')
- data['value']['location_id'] = quant.location_id.id
- data['value']['location_dest_id'] = quant.location_id.id
- return data
+ return {'value': {'location_dest_id': location_id}}
def button_dummy(self, cr, uid, ids, context=None):
return True
@@ -459,13 +439,12 @@ class mrp_repair(osv.osv):
return True
def action_repair_done(self, cr, uid, ids, context=None):
- """ Creates stock move and picking for repair order.
- @return: Picking ids.
+ """ Creates stock move for operation and stock move for final product of repair order.
+ @return: Move ids of final products
"""
res = {}
move_obj = self.pool.get('stock.move')
repair_line_obj = self.pool.get('mrp.repair.line')
- pick_obj = self.pool.get('stock.picking')
for repair in self.browse(cr, uid, ids, context=context):
for move in repair.operations:
move_id = move_obj.create(cr, uid, {
@@ -481,38 +460,20 @@ class mrp_repair(osv.osv):
})
move_obj.action_done(cr, uid, [move_id], context=context)
repair_line_obj.write(cr, uid, [move.id], {'move_id': move_id, 'state': 'done'}, context=context)
- if repair.deliver_bool:
- if not repair.picking_type_id:
- raise osv.except_osv(_('Warning!'), _('No picking type set.'))
- pick_name = self.pool.get('ir.sequence').get_id(cr, uid, repair.picking_type_id.sequence_id.id, 'id', context=context)
- picking = pick_obj.create(cr, uid, {
- 'name': pick_name,
- 'origin': repair.name,
- 'state': 'draft',
- 'move_type': 'one',
- 'partner_id': repair.address_id and repair.address_id.id or False,
- 'note': repair.internal_notes,
- 'invoice_state': 'none',
- 'picking_type_id': repair.picking_type_id.id,
- })
- move_id = move_obj.create(cr, uid, {
- 'name': repair.name,
- 'picking_id': picking,
- 'product_id': repair.product_id.id,
- 'product_uom': repair.product_id.uom_id.id,
- 'partner_id': repair.address_id and repair.address_id.id or False,
- 'location_id': repair.location_id.id,
- 'location_dest_id': repair.location_dest_id.id,
- 'state': 'assigned',
- })
- pick_obj.signal_button_confirm(cr, uid, [picking])
- quants = [(repair.quant_id, repair.quant_id.qty)]
- move = move_obj.browse(cr, uid, move_id, context=context)
- self.pool.get("stock.quant").quants_reserve(cr, uid, quants, move, context=context)
- self.write(cr, uid, [repair.id], {'state': 'done', 'picking_id': picking})
- res[repair.id] = picking
- else:
- self.write(cr, uid, [repair.id], {'state': 'done'})
+ move_id = move_obj.create(cr, uid, {
+ 'name': repair.name,
+ 'product_id': repair.product_id.id,
+ 'product_uom': repair.product_id.uom_id.id,
+ 'partner_id': repair.address_id and repair.address_id.id or False,
+ 'location_id': repair.location_id.id,
+ 'location_dest_id': repair.location_dest_id.id,
+ 'restrict_lot_id': repair.lot_id.id,
+ 'product_qty': repair.product_qty,
+ })
+ move_obj.signal_button_confirm(cr, uid, [move_id])
+ move_obj.action_done(cr, uid, [move_id], context=context)
+ self.write(cr, uid, [repair.id], {'state': 'done', 'move_id': move_id}, context=context)
+ res[repair.id] = move_id
return res
@@ -574,7 +535,7 @@ class mrp_repair_line(osv.osv, ProductChangeMixin):
def copy_data(self, cr, uid, id, default=None, context=None):
if not default: default = {}
- default.update( {'invoice_line_id': False, 'quant_id': False, 'invoiced': False, 'state': 'draft'})
+ default.update( {'invoice_line_id': False, 'move_id': False, 'invoiced': False, 'state': 'draft'})
return super(mrp_repair_line, self).copy_data(cr, uid, id, default, context)
def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml
index cf4236743ce..7c973470403 100644
--- a/addons/mrp_repair/mrp_repair_view.xml
+++ b/addons/mrp_repair/mrp_repair_view.xml
@@ -9,7 +9,6 @@
-
@@ -47,13 +46,10 @@
-
-
+
-
-
@@ -171,12 +167,12 @@
-
+
-
+
From 01679750c020d41e5d8741d8bd4ae1230f0b4e6c Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Fri, 24 Jan 2014 11:35:01 +0100
Subject: [PATCH 09/20] [IMP] Add product qty and UoM to repair order
bzr revid: jco@openerp.com-20140124103501-jhz0v3l1pj68i8nb
---
addons/mrp_repair/mrp_repair.py | 27 ++++++++++++++++++++++-----
addons/mrp_repair/mrp_repair_view.xml | 7 ++++++-
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index 4fc9007b034..66325ee500c 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -117,6 +117,9 @@ class mrp_repair(osv.osv):
_columns = {
'name': fields.char('Repair Reference',size=24, required=True, states={'confirmed':[('readonly',True)]}),
'product_id': fields.many2one('product.product', string='Product to Repair', required=True, readonly=True, states={'draft':[('readonly',False)]}),
+ 'product_qty': fields.float('Product Quantity', help='Product Qty', digits_compute=dp.get_precision('Product Unit of Measure'),
+ required=True, readonly=True, states={'draft':[('readonly',False)]}),
+ 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'partner_id' : fields.many2one('res.partner', 'Partner', select=True, help='Choose partner for whom the order will be invoiced and delivered.', states={'confirmed':[('readonly',True)]}),
'address_id': fields.many2one('res.partner', 'Delivery Address', domain="[('parent_id','=',partner_id)]", states={'confirmed':[('readonly',True)]}),
'default_address_id': fields.function(_get_default_address, type="many2one", relation="res.partner"),
@@ -172,7 +175,6 @@ class mrp_repair(osv.osv):
'mrp.repair': (lambda self, cr, uid, ids, c={}: ids, ['operations'], 10),
'mrp.repair.line': (_get_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
}),
- 'product_qty': fields.integer('Quantity', help='Product Qty'),
}
_defaults = {
@@ -181,7 +183,7 @@ class mrp_repair(osv.osv):
'invoice_method': lambda *a: 'none',
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.repair', context=context),
'pricelist_id': lambda self, cr, uid,context : self.pool.get('product.pricelist').search(cr, uid, [('type','=','sale')])[0],
- 'product_qty': 1.0,
+ 'product_qty': 1.0,
}
def copy(self, cr, uid, id, default=None, context=None):
@@ -202,12 +204,27 @@ class mrp_repair(osv.osv):
@param product_id: Changed product
@return: Dictionary of values.
"""
+ product = False
+ if product_id:
+ product = self.pool.get("product.product").browse(cr, uid, product_id)
return {'value': {
'guarantee_limit' :False,
'lot_id': False,
+ 'product_uom': product and product.uom_id.id or False,
}
}
-
+
+ def onchange_product_uom(self, cr, uid, ids, product_id, product_uom, context=None):
+ res = {'value':{}}
+ if not product_uom or not product_id:
+ return res
+ product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
+ uom = self.pool.get('product.uom').browse(cr, uid, product_uom, context=context)
+ if uom.category_id.id != product.uom_id.category_id.id:
+ res['warning'] = {'title': _('Warning'), 'message': _('The Product Unit of Measure you chose has a different category than in the product form.')}
+ res['value'].update({'product_uom': product.uom_id.id})
+ return res
+
def onchange_location_id(self, cr, uid, ids, location_id=None):
""" On change of location
"""
@@ -463,12 +480,12 @@ class mrp_repair(osv.osv):
move_id = move_obj.create(cr, uid, {
'name': repair.name,
'product_id': repair.product_id.id,
- 'product_uom': repair.product_id.uom_id.id,
+ 'product_uom': repair.product_uom.id,
+ 'product_qty': repair.product_qty,
'partner_id': repair.address_id and repair.address_id.id or False,
'location_id': repair.location_id.id,
'location_dest_id': repair.location_dest_id.id,
'restrict_lot_id': repair.lot_id.id,
- 'product_qty': repair.product_qty,
})
move_obj.signal_button_confirm(cr, uid, [move_id])
move_obj.action_done(cr, uid, [move_id], context=context)
diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml
index 7c973470403..972fef71c00 100644
--- a/addons/mrp_repair/mrp_repair_view.xml
+++ b/addons/mrp_repair/mrp_repair_view.xml
@@ -44,6 +44,11 @@
+
+
+
+
+
@@ -56,7 +61,7 @@
-
+
]]>
+watch your stock valuation, and track production lots (based on serial numbers).]]>
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 9ec583f89ff..ff542762c38 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -191,8 +191,7 @@