From 0f7ca6e784b51abac7d32094fcc634aa8bd39394 Mon Sep 17 00:00:00 2001
From: "Jitendra Prajapati (OpenERP)"
Date: Mon, 20 Jan 2014 12:22:22 +0530
Subject: [PATCH 01/29] [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 49104e91081adef130424db0414d0a51f2f9f0d3 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Mon, 20 Jan 2014 11:30:48 +0100
Subject: [PATCH 02/29] [FIX]add PO name to origin field when generating
picking from PO
lp bug: https://launchpad.net/bugs/1269353 fixed
bzr revid: csn@openerp.com-20140120103048-ebb2ow8rutn2gs21
---
addons/purchase/purchase.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 235b9d6c2bd..8f3ecbc05ce 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -694,6 +694,7 @@ class purchase_order(osv.osv):
'picking_type_id': order.picking_type_id.id,
'group_id': group_id,
'procurement_id': order_line.procurement_ids and order_line.procurement_ids[0].id or False,
+ 'origin': order.name,
'route_ids': order.picking_type_id.warehouse_id and [(6, 0, [x.id for x in order.picking_type_id.warehouse_id.route_ids])] or [],
}]
#if the order line has a bigger quantity than the procurement it was for (manually changed or minimal quantity), then
From fbd144c9e7e6f78556fbdc1b91eea66e36384f39 Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 22 Jan 2014 13:31:59 +0100
Subject: [PATCH 03/29] [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 e086290eb047966f2e05959009ccaab1ef047ac4 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Wed, 22 Jan 2014 14:04:11 +0100
Subject: [PATCH 04/29] [FIX]inventory adjustment: should not show negative qty
at start and prevent user should not input negative qty
lp bug: https://launchpad.net/bugs/1271244 fixed
bzr revid: csn@openerp.com-20140122130411-vab09j3bo5r7ks0f
---
addons/stock/stock.py | 5 +++++
addons/stock/stock_view.xml | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 91feb16bca5..66e40e8df5b 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -2018,6 +2018,7 @@ class stock_inventory(osv.osv):
'date': fields.datetime('Inventory Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Inventory Create Date."),
'date_done': fields.datetime('Date done', help="Inventory Validation Date."),
'line_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, states={'done': [('readonly', True)]}, help="Inventory Lines."),
+ 'line_view_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, domain=['|',('th_qty', '>=', 0),('th_qty', '=', False)], states={'done': [('readonly', True)]}, help="Inventory Lines."),
'move_ids': fields.one2many('stock.move', 'inventory_id', 'Created Moves', help="Inventory Moves."),
'state': fields.selection([('draft', 'Draft'), ('cancel', 'Cancelled'), ('confirm', 'In Progress'), ('done', 'Validated')], 'Status', readonly=True, select=True),
'company_id': fields.many2one('res.company', 'Company', required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
@@ -2073,6 +2074,10 @@ class stock_inventory(osv.osv):
context = {}
move_obj = self.pool.get('stock.move')
for inv in self.browse(cr, uid, ids, context=context):
+ if inv.line_ids:
+ for inventory_line in inv.line_ids:
+ if inventory_line.product_qty < 0 and inventory_line.th_qty >= 0:
+ raise osv.except_osv(_('Warning'),_('You cannot have a negative product quantity in an inventory line'))
if not inv.move_ids:
self.action_check(cr, uid, [inv.id], context=context)
inv.refresh()
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 7ba08b1a6f1..bd77f6f40c9 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -119,7 +119,7 @@
-
+
From 8eff4a3af825e692cc0fc6a63deedf4d304d751d Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Wed, 22 Jan 2014 14:27:30 +0100
Subject: [PATCH 05/29] [FIX]inventory adjustment: move_ids should be readonly
once inventory has been validated
lp bug: https://launchpad.net/bugs/1271262 fixed
bzr revid: csn@openerp.com-20140122132730-x0oiddxio1nkiwo3
---
addons/stock/stock.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 66e40e8df5b..2896bed07ee 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -2019,7 +2019,7 @@ class stock_inventory(osv.osv):
'date_done': fields.datetime('Date done', help="Inventory Validation Date."),
'line_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, states={'done': [('readonly', True)]}, help="Inventory Lines."),
'line_view_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, domain=['|',('th_qty', '>=', 0),('th_qty', '=', False)], states={'done': [('readonly', True)]}, help="Inventory Lines."),
- 'move_ids': fields.one2many('stock.move', 'inventory_id', 'Created Moves', help="Inventory Moves."),
+ 'move_ids': fields.one2many('stock.move', 'inventory_id', 'Created Moves', help="Inventory Moves.", states={'done': [('readonly', True)]}),
'state': fields.selection([('draft', 'Draft'), ('cancel', 'Cancelled'), ('confirm', 'In Progress'), ('done', 'Validated')], 'Status', readonly=True, select=True),
'company_id': fields.many2one('res.company', 'Company', required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
'location_id': fields.many2one('stock.location', 'Location', required=True, readonly=True, states={'draft': [('readonly', False)]}),
From f7d2d9e9189e9874652b88f8b61820e01ff0d56a Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Wed, 22 Jan 2014 15:11:23 +0100
Subject: [PATCH 06/29] [FIX]remove setting for stock_no_autopicking that has
been removed
lp bug: https://launchpad.net/bugs/1271466 fixed
bzr revid: csn@openerp.com-20140122141123-wbxk3exizay9cgf9
---
addons/mrp/res_config.py | 6 ------
addons/mrp/res_config_view.xml | 4 ----
2 files changed, 10 deletions(-)
diff --git a/addons/mrp/res_config.py b/addons/mrp/res_config.py
index e7da0ee82fb..71635cc9e6e 100644
--- a/addons/mrp/res_config.py
+++ b/addons/mrp/res_config.py
@@ -44,12 +44,6 @@ class mrp_config_settings(osv.osv_memory):
'Without this module: A + B + C -> D.\n'
'With this module: A + B + C -> D + E.\n'
'-This installs the module mrp_byproduct.'),
- 'module_stock_no_autopicking': fields.boolean("Manage manual picking to fulfill manufacturing orders ",
- help='This module allows an intermediate picking process to provide raw materials to production orders.\n'
- 'For example to manage production made by your suppliers (sub-contracting).\n'
- 'To achieve this, set the assembled product which is sub-contracted to "No Auto-Picking" '
- 'and put the location of the supplier in the routing of the assembly operation.\n'
- '-This installs the module stock_no_autopicking.'),
'group_mrp_routings': fields.boolean("Manage routings and work orders ",
implied_group='mrp.group_mrp_routings',
help='Routings allow you to create and manage the manufacturing operations that should be followed '
diff --git a/addons/mrp/res_config_view.xml b/addons/mrp/res_config_view.xml
index 25f3e0b0931..97301e60bf8 100644
--- a/addons/mrp/res_config_view.xml
+++ b/addons/mrp/res_config_view.xml
@@ -35,10 +35,6 @@
-
-
-
-
From a173b17ce3e96fb0e97bc7337a8bf8cf0d8af70a Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 22 Jan 2014 15:39:51 +0100
Subject: [PATCH 07/29] [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 08/29] [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 74315dabf9e7ecd5fe9fb92d90a13496be16d595 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Thu, 23 Jan 2014 11:23:04 +0100
Subject: [PATCH 09/29] [FIX]prevent doing an inventory when one product is in
negative qty
bzr revid: csn@openerp.com-20140123102304-l1ytvax5eqlqzky1
---
addons/stock/stock.py | 12 ++++++++++--
addons/stock/stock_view.xml | 2 +-
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 2896bed07ee..306b028f934 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -2018,7 +2018,6 @@ class stock_inventory(osv.osv):
'date': fields.datetime('Inventory Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Inventory Create Date."),
'date_done': fields.datetime('Date done', help="Inventory Validation Date."),
'line_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, states={'done': [('readonly', True)]}, help="Inventory Lines."),
- 'line_view_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, domain=['|',('th_qty', '>=', 0),('th_qty', '=', False)], states={'done': [('readonly', True)]}, help="Inventory Lines."),
'move_ids': fields.one2many('stock.move', 'inventory_id', 'Created Moves', help="Inventory Moves.", states={'done': [('readonly', True)]}),
'state': fields.selection([('draft', 'Draft'), ('cancel', 'Cancelled'), ('confirm', 'In Progress'), ('done', 'Validated')], 'Status', readonly=True, select=True),
'company_id': fields.many2one('res.company', 'Company', required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
@@ -2076,7 +2075,7 @@ class stock_inventory(osv.osv):
for inv in self.browse(cr, uid, ids, context=context):
if inv.line_ids:
for inventory_line in inv.line_ids:
- if inventory_line.product_qty < 0 and inventory_line.th_qty >= 0:
+ if inventory_line.product_qty < 0:
raise osv.except_osv(_('Warning'),_('You cannot have a negative product quantity in an inventory line'))
if not inv.move_ids:
self.action_check(cr, uid, [inv.id], context=context)
@@ -2185,17 +2184,26 @@ class stock_inventory(osv.osv):
GROUP BY product_id, location_id, lot_id, package_id, partner_id
''', args)
vals = []
+ negative_product_ids = []
for product_line in cr.dictfetchall():
#replace the None the dictionary by False, because falsy values are tested later on
for key, value in product_line.items():
if not value:
product_line[key] = False
+ if product_line['product_qty'] < 0:
+ negative_product_ids.append(product_line['product_id'])
product_line['inventory_id'] = inventory.id
product_line['th_qty'] = product_line['product_qty']
if product_line['product_id']:
product = product_obj.browse(cr, uid, product_line['product_id'], context=context)
product_line['product_uom_id'] = product.uom_id.id
vals.append(product_line)
+
+ if negative_product_ids:
+ summary = ''
+ for product in self.pool.get('product.product').browse(cr, uid, negative_product_ids, context=context):
+ summary += '- '+product.name+'\n'
+ raise osv.except_osv(_('Warning'),_('These products have a negative qty, please fix them before doing an inventory\n%s' % (summary)))
return vals
class stock_inventory_line(osv.osv):
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index bd77f6f40c9..7ba08b1a6f1 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -119,7 +119,7 @@
-
+
From 386f7c1212705a9cc3b2e73731bfcc4ca447dfbf Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Thu, 23 Jan 2014 18:27:41 +0100
Subject: [PATCH 10/29] [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 11/29] [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 @@