From 6b1ec21cb617c1716d2e5297342df2ec3f369448 Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 15 Jan 2014 14:37:19 +0100
Subject: [PATCH 01/40] [IMP] Make sure the quant has lot when we restrict lot
in pickingless move
bzr revid: jco@openerp.com-20140115133719-ivn71uatgd7gtin6
---
addons/mrp/stock.py | 5 +++--
addons/stock/stock.py | 6 +++---
addons/stock/wizard/stock_move_view.xml | 3 ++-
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py
index 94a0913ca29..37929d500a1 100644
--- a/addons/mrp/stock.py
+++ b/addons/mrp/stock.py
@@ -124,7 +124,7 @@ class StockMove(osv.osv):
res.append(new_move)
return res
- def action_scrap(self, cr, uid, ids, product_qty, location_id, context=None):
+ def action_scrap(self, cr, uid, ids, product_qty, location_id, restrict_lot_id = False, context=None):
""" Move the scrap/damaged product into scrap location
@param product_qty: Scraped product quantity
@param location_id: Scrap location
@@ -133,7 +133,8 @@ class StockMove(osv.osv):
res = []
production_obj = self.pool.get('mrp.production')
for move in self.browse(cr, uid, ids, context=context):
- new_moves = super(StockMove, self).action_scrap(cr, uid, [move.id], product_qty, location_id, context=context)
+ new_moves = super(StockMove, self).action_scrap(cr, uid, [move.id], product_qty, location_id,
+ restrict_lot_id = restrict_lot_id, context=context)
#If we are not scrapping our whole move, tracking and lot references must not be removed
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
for prod_id in production_ids:
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 7c64cdab2d7..c94c7bbcfb6 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -818,11 +818,11 @@ class stock_picking(osv.osv):
return True
def cancel_assign(self, cr, uid, ids, context=None):
- """ Cancels picking and moves.
+ """ Cancels picking for the moves that are in the assigned state
@return: True
"""
for pick in self.browse(cr, uid, ids, context=context):
- move_ids = [x.id for x in pick.move_lines]
+ move_ids = [x.id for x in pick.move_lines if x not in ['done', 'cancel']]
self.pool.get('stock.move').cancel_assign(cr, uid, move_ids, context=context)
return True
@@ -1812,7 +1812,7 @@ class stock_move(osv.osv):
if qty > 0:
self.check_tracking(cr, uid, move, move.restrict_lot_id.id, context=context)
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain, prefered_domain=prefered_domain, fallback_domain=fallback_domain, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)
- quant_obj.quants_move(cr, uid, quants, move, context=context)
+ quant_obj.quants_move(cr, uid, quants, move, lot_id = move.restrict_lot_id.id, owner_id = move.restrict_partner_id.id, context=context)
#unreserve the quants and make them available for other operations/moves
quant_obj.quants_unreserve(cr, uid, move, context=context)
diff --git a/addons/stock/wizard/stock_move_view.xml b/addons/stock/wizard/stock_move_view.xml
index f8121a89ee9..0a567be651e 100644
--- a/addons/stock/wizard/stock_move_view.xml
+++ b/addons/stock/wizard/stock_move_view.xml
@@ -15,7 +15,8 @@
-
+
From d2605491ff537298a8654f00ab9a5712a5b814fe Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 15 Jan 2014 15:16:59 +0100
Subject: [PATCH 02/40] [IMP] Add dependence on partner
bzr revid: jco@openerp.com-20140115141659-3ek1usz8ugllsn9e
---
addons/mrp/stock.py | 10 ++++++----
addons/stock/stock.py | 14 +++++++++-----
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py
index 37929d500a1..ff59fcd5118 100644
--- a/addons/mrp/stock.py
+++ b/addons/mrp/stock.py
@@ -100,7 +100,7 @@ class StockMove(osv.osv):
procurement_obj.signal_button_wait_done(cr, uid, procurement_ids)
return processed_ids
- def action_consume(self, cr, uid, ids, product_qty, location_id=False, restrict_lot_id = False, context=None):
+ def action_consume(self, cr, uid, ids, product_qty, location_id=False, restrict_lot_id = False, restrict_partner_id = False, context=None):
""" Consumed product with specific quatity from specific source location.
@param product_qty: Consumed product quantity
@param location_id: Source location
@@ -110,7 +110,8 @@ class StockMove(osv.osv):
production_obj = self.pool.get('mrp.production')
for move in self.browse(cr, uid, ids, context=context):
self.action_confirm(cr, uid, [move.id], context=context)
- new_moves = super(StockMove, self).action_consume(cr, uid, [move.id], product_qty, location_id, restrict_lot_id = restrict_lot_id, context=context)
+ new_moves = super(StockMove, self).action_consume(cr, uid, [move.id], product_qty, location_id, restrict_lot_id = restrict_lot_id,
+ restrict_partner_id = restrict_partner_id, context=context)
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
for prod in production_obj.browse(cr, uid, production_ids, context=context):
if prod.state == 'confirmed':
@@ -124,7 +125,7 @@ class StockMove(osv.osv):
res.append(new_move)
return res
- def action_scrap(self, cr, uid, ids, product_qty, location_id, restrict_lot_id = False, context=None):
+ def action_scrap(self, cr, uid, ids, product_qty, location_id, restrict_lot_id = False, restrict_partner_id = False, context=None):
""" Move the scrap/damaged product into scrap location
@param product_qty: Scraped product quantity
@param location_id: Scrap location
@@ -134,7 +135,8 @@ class StockMove(osv.osv):
production_obj = self.pool.get('mrp.production')
for move in self.browse(cr, uid, ids, context=context):
new_moves = super(StockMove, self).action_scrap(cr, uid, [move.id], product_qty, location_id,
- restrict_lot_id = restrict_lot_id, context=context)
+ restrict_lot_id = restrict_lot_id,
+ restrict_partner_id = restrict_partner_id, context=context)
#If we are not scrapping our whole move, tracking and lot references must not be removed
production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])])
for prod_id in production_ids:
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index c94c7bbcfb6..8226c36c553 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1843,7 +1843,7 @@ class stock_move(osv.osv):
raise osv.except_osv(_('User Error!'), _('You can only delete draft moves.'))
return super(stock_move, self).unlink(cr, uid, ids, context=context)
- def action_scrap(self, cr, uid, ids, quantity, location_id, restrict_lot_id=False, context=None):
+ def action_scrap(self, cr, uid, ids, quantity, location_id, restrict_lot_id=False, restrict_partner_id=False, context=None):
""" Move the scrap/damaged product into scrap location
@param cr: the database cursor
@param uid: the user id
@@ -1875,6 +1875,7 @@ class stock_move(osv.osv):
'scrapped': True,
'location_dest_id': location_id,
'restrict_lot_id': restrict_lot_id,
+ 'restrict_partner_id': restrict_partner_id,
}
new_move = self.copy(cr, uid, move.id, default_val)
@@ -1889,7 +1890,7 @@ class stock_move(osv.osv):
self.action_done(cr, uid, res, context=context)
return res
- def action_consume(self, cr, uid, ids, quantity, location_id=False, restrict_lot_id=False, context=None):
+ def action_consume(self, cr, uid, ids, quantity, location_id=False, restrict_lot_id=False, restrict_partner_id=False, context=None):
""" Consumed product with specific quantity from specific source location. This correspond to a split of the move (or write if the quantity to consume is >= than the quantity of the move) followed by an action_done
@param ids: ids of stock move object to be consumed
@param quantity : specify consume quantity (given in move UoM)
@@ -1912,16 +1913,18 @@ class stock_move(osv.osv):
ctx = context.copy()
if location_id:
ctx['source_location_id'] = location_id
- res.append(self.split(cr, uid, move, move_qty - quantity_rest, restrict_lot_id=restrict_lot_id, context=ctx))
+ res.append(self.split(cr, uid, move, move_qty - quantity_rest, restrict_lot_id=restrict_lot_id,
+ restrict_partner_id = restrict_partner_id, context=ctx))
else:
res.append(move.id)
if location_id:
- self.write(cr, uid, [move.id], {'location_id': location_id, 'restrict_lot_id': restrict_lot_id}, context=context)
+ self.write(cr, uid, [move.id], {'location_id': location_id, 'restrict_lot_id': restrict_lot_id,
+ 'restrict_partner_id': restrict_partner_id}, context=context)
self.action_done(cr, uid, res, context=context)
return res
- def split(self, cr, uid, move, qty, restrict_lot_id=False, context=None):
+ def split(self, cr, uid, move, qty, restrict_lot_id=False, restrict_partner_id = False, context=None):
""" Splits qty from move move into a new move
:param move: browse record
:param qty: float. quantity to split (given in product UoM)
@@ -1947,6 +1950,7 @@ class stock_move(osv.osv):
'move_dest_id': False,
'reserved_quant_ids': [],
'restrict_lot_id': restrict_lot_id,
+ 'restrict_partner_id': restrict_partner_id
}
if context.get('source_location_id'):
defaults['location_id'] = context['source_location_id']
From dc316e2344e4f2029a8df5a07350c74bf9186f6a Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 15 Jan 2014 15:48:32 +0100
Subject: [PATCH 03/40] [TEST] test if product_id passing is problem
bzr revid: jco@openerp.com-20140115144832-mfn212m26w57gmpa
---
addons/stock/wizard/stock_move_view.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/stock/wizard/stock_move_view.xml b/addons/stock/wizard/stock_move_view.xml
index 0a567be651e..d562c0e74a0 100644
--- a/addons/stock/wizard/stock_move_view.xml
+++ b/addons/stock/wizard/stock_move_view.xml
@@ -16,7 +16,7 @@
+ context="{'product_id': product_id}"/>
@@ -51,7 +51,7 @@
+ context="{'product_id': product_id}"/>
From 1369cbeb4eee6551e4d0c8f219ae40dc0511a753 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Wed, 15 Jan 2014 16:43:04 +0100
Subject: [PATCH 04/40] [FIX]inventory button on product form view should open
quant view group by location for that product
lp bug: https://launchpad.net/bugs/1268989 fixed
bzr revid: csn@openerp.com-20140115154304-nyw53jcbh1giq01w
---
addons/stock/stock_view.xml | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 977e7238a62..2068b64c0ba 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -1846,7 +1846,7 @@
stock.warehouse.orderpoint
- {'search_default_product_id': active_id}
+ {'search_default_product_id': active_id, 'search_default_locationgroup':1}
Quants
stock.quant
@@ -1889,10 +1889,9 @@
-
+
-
From bec9914b05eb1102f7f23fb140c9e9f3112599ee Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Wed, 15 Jan 2014 17:50:00 +0100
Subject: [PATCH 05/40] [TEST] Revert test
bzr revid: jco@openerp.com-20140115165000-mpl6bhlvkv71etuv
---
addons/stock/wizard/stock_move_view.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/stock/wizard/stock_move_view.xml b/addons/stock/wizard/stock_move_view.xml
index d562c0e74a0..0a567be651e 100644
--- a/addons/stock/wizard/stock_move_view.xml
+++ b/addons/stock/wizard/stock_move_view.xml
@@ -16,7 +16,7 @@
+ context="{'default_product_id': product_id}"/>
@@ -51,7 +51,7 @@
+ context="{'default_product_id': product_id}"/>
From 3e87ec567ee73b754b06088df2d82294bcf7a30c Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Thu, 16 Jan 2014 14:39:05 +0100
Subject: [PATCH 06/40] [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.inherit
product.template
From 9dc64a216be3b3b5b893c7c9be6b9c14ef6b56c3 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Fri, 17 Jan 2014 10:20:11 +0100
Subject: [PATCH 07/40] [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 2b820d5e428c7ce09c3a8cb99d1a234a4b980d8d Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Fri, 17 Jan 2014 18:38:51 +0100
Subject: [PATCH 08/40] [IMP] Remove automatic orderpoint
bzr revid: jco@openerp.com-20140117173851-60246vguu1y3hiq2
---
addons/procurement/procurement_data.xml | 2 +-
addons/stock/procurement.py | 54 +------------------
addons/stock/wizard/orderpoint_procurement.py | 9 +---
.../wizard/orderpoint_procurement_view.xml | 3 --
4 files changed, 4 insertions(+), 64 deletions(-)
diff --git a/addons/procurement/procurement_data.xml b/addons/procurement/procurement_data.xml
index 6f39669f034..fdaab5852ea 100644
--- a/addons/procurement/procurement_data.xml
+++ b/addons/procurement/procurement_data.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py
index b47908c73bb..96c05487192 100644
--- a/addons/stock/procurement.py
+++ b/addons/stock/procurement.py
@@ -275,7 +275,7 @@ class procurement_order(osv.osv):
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
move_obj = self.pool.get('stock.move')
#Minimum stock rules
- self. _procure_orderpoint_confirm(cr, uid, automatic=False,use_new_cursor=False, context=context, user_id=False)
+ self. _procure_orderpoint_confirm(cr, uid, use_new_cursor=False, context=context, user_id=False)
#Search all confirmed stock_moves and try to assign them
confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed'), ('company_id','=', company.id)], limit=None, order='picking_priority desc, date_expected asc', context=context)
@@ -295,54 +295,6 @@ class procurement_order(osv.osv):
pass
return {}
- def _prepare_automatic_op_procurement(self, cr, uid, product, warehouse, location_id, context=None):
- return {'name': _('Automatic OP: %s') % (product.name,),
- 'origin': _('SCHEDULER'),
- 'date_planned': datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
- 'product_id': product.id,
- 'product_qty': -product.virtual_available,
- 'product_uom': product.uom_id.id,
- 'location_id': location_id,
- 'company_id': warehouse.company_id.id,
- }
-
- def create_automatic_op(self, cr, uid, context=None):
- """
- Create procurement of virtual stock < 0
-
- @param self: The object pointer
- @param cr: The current row, from the database cursor,
- @param uid: The current user ID for security checks
- @param context: A standard dictionary for contextual values
- @return: Dictionary of values
- """
- if context is None:
- context = {}
- product_obj = self.pool.get('product.product')
- proc_obj = self.pool.get('procurement.order')
- warehouse_obj = self.pool.get('stock.warehouse')
-
- warehouse_ids = warehouse_obj.search(cr, uid, [], context=context)
- products_ids = product_obj.search(cr, uid, [], order='id', context=context)
-
- for warehouse in warehouse_obj.browse(cr, uid, warehouse_ids, context=context):
- context['warehouse'] = warehouse
- # Here we check products availability.
- # We use the method 'read' for performance reasons, because using the method 'browse' may crash the server.
- for product_read in product_obj.read(cr, uid, products_ids, ['virtual_available'], context=context):
- if product_read['virtual_available'] >= 0.0:
- continue
-
- product = product_obj.browse(cr, uid, [product_read['id']], context=context)[0]
-
- location_id = warehouse.lot_stock_id.id
-
- proc_id = proc_obj.create(cr, uid,
- self._prepare_automatic_op_procurement(cr, uid, product, warehouse, location_id, context=context),
- context=context)
- self.assign(cr, uid, [proc_id])
- self.run(cr, uid, [proc_id])
- return True
def _get_orderpoint_date_planned(self, cr, uid, orderpoint, start_date, context=None):
date_planned = start_date + \
@@ -365,7 +317,7 @@ class procurement_order(osv.osv):
[order_point.product_id.id],
{'location': order_point.location_id.id})[order_point.product_id.id]['virtual_available']
- def _procure_orderpoint_confirm(self, cr, uid, automatic=False,\
+ def _procure_orderpoint_confirm(self, cr, uid, \
use_new_cursor=False, context=None, user_id=False):
'''
Create procurement based on Orderpoint
@@ -388,8 +340,6 @@ class procurement_order(osv.osv):
procurement_obj = self.pool.get('procurement.order')
offset = 0
ids = [1]
- if automatic:
- self.create_automatic_op(cr, uid, context=context)
while ids:
ids = orderpoint_obj.search(cr, uid, [], offset=offset, limit=100)
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
diff --git a/addons/stock/wizard/orderpoint_procurement.py b/addons/stock/wizard/orderpoint_procurement.py
index afc8e2a721f..dc13471c186 100644
--- a/addons/stock/wizard/orderpoint_procurement.py
+++ b/addons/stock/wizard/orderpoint_procurement.py
@@ -31,13 +31,6 @@ class procurement_compute(osv.osv_memory):
_name = 'procurement.orderpoint.compute'
_description = 'Automatic Order Point'
- _columns = {
- 'automatic': fields.boolean('Automatic Orderpoint', help='If the stock of a product is under 0, it will act like an orderpoint'),
- }
-
- _defaults = {
- 'automatic': False,
- }
def _procure_calculation_orderpoint(self, cr, uid, ids, context=None):
"""
@@ -51,7 +44,7 @@ class procurement_compute(osv.osv_memory):
#As this function is in a new thread, I need to open a new cursor, because the old one may be closed
new_cr = self.pool.db.cursor()
for proc in self.browse(new_cr, uid, ids, context=context):
- proc_obj._procure_orderpoint_confirm(new_cr, uid, automatic=proc.automatic, use_new_cursor=new_cr.dbname, context=context)
+ proc_obj._procure_orderpoint_confirm(new_cr, uid, use_new_cursor=new_cr.dbname, context=context)
#close the new cursor
new_cr.close()
return {}
diff --git a/addons/stock/wizard/orderpoint_procurement_view.xml b/addons/stock/wizard/orderpoint_procurement_view.xml
index 20250bb78dd..676dfb144d6 100644
--- a/addons/stock/wizard/orderpoint_procurement_view.xml
+++ b/addons/stock/wizard/orderpoint_procurement_view.xml
@@ -12,9 +12,6 @@
-
-
-
or
From 0f7ca6e784b51abac7d32094fcc634aa8bd39394 Mon Sep 17 00:00:00 2001
From: "Jitendra Prajapati (OpenERP)"
Date: Mon, 20 Jan 2014 12:22:22 +0530
Subject: [PATCH 09/40] [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 2b47ad2694b6e3c83c9dc02f93d102e532b10e9b Mon Sep 17 00:00:00 2001
From: Josse Colpaert
Date: Mon, 20 Jan 2014 10:06:28 +0100
Subject: [PATCH 10/40] Parameters in cron job need to be tuple
bzr revid: jco@openerp.com-20140120090628-6uqd51mweoelxu9g
---
addons/procurement/procurement_data.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/procurement/procurement_data.xml b/addons/procurement/procurement_data.xml
index fdaab5852ea..b0728ccf021 100644
--- a/addons/procurement/procurement_data.xml
+++ b/addons/procurement/procurement_data.xml
@@ -12,7 +12,7 @@
-
+
From 49104e91081adef130424db0414d0a51f2f9f0d3 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Mon, 20 Jan 2014 11:30:48 +0100
Subject: [PATCH 11/40] [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 86e7d60e23643b4cadd32a7273824e5845fc2dc9 Mon Sep 17 00:00:00 2001
From: Cedric Snauwaert
Date: Tue, 21 Jan 2014 11:51:00 +0100
Subject: [PATCH 12/40] [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 13/40] [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 14/40] [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 15/40] [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 16/40] [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 17/40] [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 18/40] [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 19/40] [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 20/40] [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 21/40] [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 @@