diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 5c1189b3249..0626f785241 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -19,7 +19,6 @@
#
##############################################################################
-import time
import pytz
from openerp import SUPERUSER_ID, workflow
from datetime import datetime
@@ -154,11 +153,11 @@ class purchase_order(osv.osv):
obj_data = self.pool.get('ir.model.data')
return obj_data.get_object_reference(cr, uid, 'stock','picking_type_in') and obj_data.get_object_reference(cr, uid, 'stock','picking_type_in')[1] or False
- def _get_picking_ids(self, cr, uid, ids, name, args, context=None):
+ def _get_picking_ids(self, cr, uid, ids, field_names, args, context=None):
res = {}
for purchase_id in ids:
picking_ids = set()
- move_ids = self.pool.get('stock.move').search(cr, uid, [('purchase_line_id.order_id','=', purchase_id)] , context=context)
+ move_ids = self.pool.get('stock.move').search(cr, uid, [('purchase_line_id.order_id', '=', purchase_id)], context=context)
for move in self.pool.get('stock.move').browse(cr, uid, move_ids, context=context):
picking_ids.add(move.picking_id.id)
res[purchase_id] = list(picking_ids)
@@ -206,7 +205,7 @@ class purchase_order(osv.osv):
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
'notes': fields.text('Terms and Conditions'),
'invoice_ids': fields.many2many('account.invoice', 'purchase_invoice_rel', 'purchase_id', 'invoice_id', 'Invoices', help="Invoices generated for a purchase order"),
- 'picking_ids': fields.function(_get_picking_ids, method=True, type='one2many', relation='stock.picking', string='Picking List', help="This is the list of operations that have been generated for this purchase order."),
+ 'picking_ids': fields.function(_get_picking_ids, method=True, type='one2many', relation='stock.picking', string='Picking List', help="This is the list of reception operations that have been generated for this purchase order."),
'shipped':fields.boolean('Received', readonly=True, select=True, help="It indicates that a picking has been done"),
'shipped_rate': fields.function(_shipped_rate, string='Received Ratio', type='float'),
'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been paid"),
@@ -408,6 +407,7 @@ class purchase_order(osv.osv):
action = self.pool.get('ir.actions.act_window').read(cr, uid, action_id, context=context)
pick_ids = []
+ #TODO: might need to change this function in order to return the whole set of operations and not only the reception(s) to input
for po in self.browse(cr, uid, ids, context=context):
pick_ids += [picking.id for picking in po.picking_ids]
@@ -673,11 +673,10 @@ class purchase_order(osv.osv):
if order.currency_id.id != order.company_id.currency_id.id:
#we don't round the price_unit, as we may want to store the standard price with more digits than allowed by the currency
price_unit = self.pool.get('res.currency').compute(cr, uid, order.currency_id.id, order.company_id.currency_id.id, price_unit, round=False, context=context)
- res = [{
+ res = []
+ move_template = {
'name': order_line.name or '',
'product_id': order_line.product_id.id,
- 'product_uom_qty': order_line.product_qty,
- 'product_uos_qty': order_line.product_qty,
'product_uom': order_line.product_uom.id,
'product_uos': order_line.product_uom.id,
'date': self.date_to_datetime(cr, uid, order.date_order, context),
@@ -686,34 +685,37 @@ class purchase_order(osv.osv):
'location_dest_id': order.location_id.id,
'picking_id': picking_id,
'partner_id': order.dest_address_id.id or order.partner_id.id,
- 'move_dest_id': order_line.move_dest_id.id,
+ 'move_dest_id': False,
'state': 'draft',
'purchase_line_id': order_line.id,
'company_id': order.company_id.id,
'price_unit': price_unit,
'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,
+ 'procurement_id': 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 [],
- }]
+ }
+
+ diff_quantity = order_line.product_qty
+ for procurement in order_line.procurement_ids:
+ procurement_qty = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, to_uom_id=order_line.product_uom.id)
+ tmp = move_template.copy()
+ tmp.update({
+ 'product_uom_qty': min(procurement_qty, diff_quantity),
+ 'product_uos_qty': min(procurement_qty, diff_quantity),
+ 'move_dest_id': procurement.move_dest_id.id, # blabla
+ 'group_id': procurement.group_id.id or group_id, # blabla to check ca devrait etre bon et groupé dans le meme picking qd meme
+ 'procurement_id': procurement.id,
+ })
+ diff_quantity -= min(procurement_qty, diff_quantity)
+ res.append(tmp)
#if the order line has a bigger quantity than the procurement it was for (manually changed or minimal quantity), then
#split the future stock move in two because the route followed may be different.
- if order_line.procurement_ids:
- procurement = order_line.procurement_ids[0]
- procurement_quantity = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, to_uom_id=order_line.product_uom.id)
- diff_quantity = order_line.product_qty - procurement_quantity
- if diff_quantity > 0:
- tmp = res[0].copy()
- res[0]['product_uom_qty'] = diff_quantity
- res[0]['product_uos_qty'] = diff_quantity
- res[0]['procurement_id'] = False
- res[0]['move_dest_id'] = False
- tmp['product_uom_qty'] = procurement.product_qty
- tmp['product_uos_qty'] = procurement.product_qty
- tmp['product_uom'] = procurement.product_uom.id
- tmp['product_uos'] = procurement.product_uom.id
- res.append(tmp)
+ if diff_quantity > 0:
+ move_template['product_uom_qty'] = diff_quantity
+ move_template['product_uos_qty'] = diff_quantity
+ res.append(move_template)
return res
def _create_stock_moves(self, cr, uid, order, order_lines, picking_id=False, context=None):
@@ -737,17 +739,14 @@ class purchase_order(osv.osv):
"""
stock_move = self.pool.get('stock.move')
todo_moves = []
- new_group = False
- if any([(not x.group_id) for x in order_lines]):
- new_group = self.pool.get("procurement.group").create(cr, uid, {'name': order.name, 'partner_id': order.partner_id.id}, context=context)
+ new_group = self.pool.get("procurement.group").create(cr, uid, {'name': order.name, 'partner_id': order.partner_id.id}, context=context)
for order_line in order_lines:
if not order_line.product_id:
continue
if order_line.product_id.type in ('product', 'consu'):
- group_id = order_line.group_id and order_line.group_id.id or new_group
- for vals in self._prepare_order_line_move(cr, uid, order, order_line, picking_id, group_id, context=context):
+ for vals in self._prepare_order_line_move(cr, uid, order, order_line, picking_id, new_group, context=context):
move = stock_move.create(cr, uid, vals, context=context)
todo_moves.append(move)
@@ -785,7 +784,8 @@ class purchase_order(osv.osv):
def action_picking_create(self, cr, uid, ids, context=None):
for order in self.browse(cr, uid, ids):
- self._create_stock_moves(cr, uid, order, order.order_line, None, context=context)
+ picking_id = self.pool.get('stock.picking').create(cr, uid, {'picking_type_id': order.picking_type_id.id, 'partner_id': order.partner_id.id}, context=context)
+ self._create_stock_moves(cr, uid, order, order.order_line, picking_id, context=context)
def picking_done(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'shipped':1,'state':'approved'}, context=context)
@@ -800,8 +800,7 @@ class purchase_order(osv.osv):
'shipped':False,
'invoiced':False,
'invoice_ids': [],
- 'picking_ids': [],
- 'origin' : '',
+ 'origin': '',
'partner_ref': '',
'name': self.pool.get('ir.sequence').get(cr, uid, 'purchase.order'),
})
@@ -832,7 +831,7 @@ class purchase_order(osv.osv):
list_key = []
for field in fields:
field_val = getattr(br, field)
- if field in ('product_id', 'move_dest_id', 'account_analytic_id'):
+ if field in ('product_id', 'account_analytic_id'):
if not field_val:
field_val = False
if isinstance(field_val, browse_record):
@@ -939,7 +938,6 @@ class purchase_order_line(osv.osv):
'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)], change_default=True),
'move_ids': fields.one2many('stock.move', 'purchase_line_id', 'Reservation', readonly=True, ondelete='set null'),
- 'move_dest_id': fields.many2one('stock.move', 'Reservation Destination', ondelete='set null'),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')),
'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
'order_id': fields.many2one('purchase.order', 'Order Reference', select=True, required=True, ondelete='cascade'),
@@ -955,7 +953,6 @@ class purchase_order_line(osv.osv):
'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner", store=True),
'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date"),
'procurement_ids': fields.one2many('procurement.order', 'purchase_line_id', string='Associated procurements'),
- 'group_id': fields.related('procurement_ids', 'group_id', type='many2one', relation='procurement.group', string='Procurement Group'),
}
_defaults = {
'product_uom' : _get_uom_id,
@@ -1178,15 +1175,6 @@ class procurement_order(osv.osv):
return True
- #def action_po_assign(self, cr, uid, ids, context=None):
- # """ This is action which call from workflow to assign purchase order to procurements
- # @return: True
- # """
- # res = self.make_po(cr, uid, ids, context=context)
- # res = res.values()
- # return len(res) and res[0] or 0 #TO CHECK: why workflow is generated error if return not integer value
-
-
def create_procurement_purchase_order(self, cr, uid, procurement, po_vals, line_vals, context=None):
"""Create the purchase order from the procurement, using
the provided field values, after adding the given purchase
@@ -1267,7 +1255,6 @@ class procurement_order(osv.osv):
'product_uom': uom_id,
'price_unit': price or 0.0,
'date_planned': schedule_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
- 'move_dest_id': procurement.move_dest_id and procurement.move_dest_id.id or False,
'taxes_id': [(6, 0, taxes)],
}
@@ -1282,6 +1269,7 @@ class procurement_order(osv.osv):
seq_obj = self.pool.get('ir.sequence')
pass_ids = []
linked_po_ids = []
+ sum_po_line_ids = []
for procurement in self.browse(cr, uid, ids, context=context):
partner = self._get_product_supplier(cr, uid, procurement, context=context)
if not partner:
@@ -1296,9 +1284,17 @@ class procurement_order(osv.osv):
('location_id', '=', procurement.location_id.id), ('company_id', '=', procurement.company_id.id)], context=context)
if available_draft_po_ids:
po_id = available_draft_po_ids[0]
- line_vals.update(order_id=po_id)
- po_line_id = po_line_obj.create(cr, uid, line_vals, context=context)
- linked_po_ids.append(procurement.id)
+ #look for any other PO line in the selected PO with same product and UoM to sum quantities instead of creating a new po line
+ available_po_line_ids = po_line_obj.search(cr, uid, [('order_id', '=', po_id), ('product_id', '=', line_vals['product_id']), ('product_uom', '=', line_vals['product_uom'])], context=context)
+ if available_po_line_ids:
+ po_line = po_line_obj.browse(cr, uid, available_po_line_ids[0], context=context)
+ po_line_obj.write(cr, uid, po_line.id, {'product_qty': po_line.product_qty + line_vals['product_qty']}, context=context)
+ po_line_id = po_line.id
+ sum_po_line_ids.append(procurement.id)
+ else:
+ line_vals.update(order_id=po_id)
+ po_line_id = po_line_obj.create(cr, uid, line_vals, context=context)
+ linked_po_ids.append(procurement.id)
else:
purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context)
name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name
@@ -1323,6 +1319,8 @@ class procurement_order(osv.osv):
self.message_post(cr, uid, pass_ids, body=_("Draft Purchase Order created"), context=context)
if linked_po_ids:
self.message_post(cr, uid, linked_po_ids, body=_("Purchase line created and linked to an existing Purchase Order"), context=context)
+ if sum_po_line_ids:
+ self.message_post(cr, uid, sum_po_line_ids, body=_("Quantity added in existing Purchase Order Line"), context=context)
return res
def _product_virtual_get(self, cr, uid, order_point):
diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml
index d0c1bb7718f..fe6b5a3f045 100644
--- a/addons/purchase/purchase_workflow.xml
+++ b/addons/purchase/purchase_workflow.xml
@@ -189,9 +189,7 @@
- stock.move
- move_lines_get()
- test_moves_except()
+ picking_cancel
@@ -201,9 +199,7 @@
- stock.move
- move_lines_get()
- test_moves_done()
+ picking_done
@@ -225,33 +221,5 @@
invoiced
-
-
-
diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py
index f0adb7b2afc..5989584793d 100644
--- a/addons/purchase/stock.py
+++ b/addons/purchase/stock.py
@@ -35,10 +35,26 @@ class stock_move(osv.osv):
ids = [ids]
res = super(stock_move, self).write(cr, uid, ids, vals, context=context)
from openerp import workflow
- for id in ids:
- workflow.trg_trigger(uid, 'stock.move', id, cr)
+ if 'state' in vals:
+ for move in self.browse(cr, uid, ids, context=context):
+ if move.purchase_line_id and move.purchase_line_id.order_id:
+ order_id = move.purchase_line_id.order_id.id
+ if self.pool.get('purchase.order').test_moves_done(cr, uid, [order_id], context=context):
+ workflow.trg_validate(uid, 'purchase.order', order_id, 'picking_done', cr)
+ if self.pool.get('purchase.order').test_moves_except(cr, uid, [order_id], context=context):
+ workflow.trg_validate(uid, 'purchase.order', order_id, 'picking_cancel', cr)
return res
+ def copy(self, cr, uid, id, default=None, context=None):
+ if not default:
+ default = {}
+ if not default.get('split_from'):
+ #we don't want to propagate the link to the purchase order line except in case of move split
+ default.update({
+ 'purchase_line_id': False,
+ })
+ return super(stock_move, self).copy(cr, uid, id, default, context)
+
class stock_picking(osv.osv):
_inherit = 'stock.picking'
diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py
index b670fa81f99..cdc56e3ad15 100644
--- a/addons/purchase_requisition/purchase_requisition.py
+++ b/addons/purchase_requisition/purchase_requisition.py
@@ -52,7 +52,7 @@ class purchase_requisition(osv.osv):
'purchase_ids': fields.one2many('purchase.order', 'requisition_id', 'Purchase Orders', states={'done': [('readonly', True)]}),
'po_line_ids': fields.function(_get_po_line, method=True, type='one2many', relation='purchase.order.line', string='Products by supplier'),
'line_ids': fields.one2many('purchase.requisition.line', 'requisition_id', 'Products to Purchase', states={'done': [('readonly', True)]}),
- 'move_dest_id': fields.many2one('stock.move', 'Reservation Destination', ondelete='set null'),
+ 'procurement_id': fields.many2one('procurement.order', 'Procurement', ondelete='set null'),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
'state': fields.selection([('draft', 'Draft'), ('in_progress', 'Confirmed'), ('open', 'Bid Selection'), ('done', 'PO Created'), ('cancel', 'Cancelled')],
'Status', track_visibility='onchange', required=True),
@@ -169,7 +169,6 @@ class purchase_requisition(osv.osv):
vals.update({
'order_id': purchase_id,
'product_id': product.id,
- 'move_dest_id': requisition.move_dest_id.id,
'account_analytic_id': requisition_line.account_analytic_id.id,
})
return vals
@@ -363,6 +362,13 @@ class purchase_order(osv.osv):
default.update({'requisition_id': False})
return super(purchase_order, self).copy(cr, uid, id, default=default, context=context)
+ def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, group_id, context=None):
+ stock_move_lines = super(purchase_order, self)._prepare_order_line_move(cr, uid, order, order_line, picking_id, group_id, context=context)
+ if order.requisition_id and order.requisition_id.procurement_id and order.requisition_id.procurement_id.move_dest_id:
+ for i in range(0, len(stock_move_lines)):
+ stock_move_lines[i]['move_dest_id'] = order.requisition_id.procurement_id.move_dest_id.id
+ return stock_move_lines
+
class purchase_order_line(osv.osv):
_inherit = 'purchase.order.line'
@@ -410,7 +416,7 @@ class procurement_order(osv.osv):
'date_end': procurement.date_planned,
'warehouse_id': warehouse_id and warehouse_id[0] or False,
'company_id': procurement.company_id.id,
- 'move_dest_id': procurement.move_dest_id and procurement.move_dest_id.id or False,
+ 'procurement_id': procurement.id,
'line_ids': [(0, 0, {
'product_id': procurement.product_id.id,
'product_uom_id': procurement.product_uom.id,
@@ -418,8 +424,17 @@ class procurement_order(osv.osv):
})],
})
+ self.message_post(cr, uid, [procurement.id], body=_("Purchase Requisition created"), context=context)
return self.write(cr, uid, [procurement.id], {'requisition_id': requisition_id}, context=context)
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
+ def _check(self, cr, uid, procurement, context=None):
+ requisition_obj = self.pool.get('purchase.requisition')
+ if procurement.rule_id and procurement.rule_id.action == 'buy' and procurement.product_id.purchase_requisition:
+ if procurement.requisition_id.state == 'done':
+ if any([purchase.shipped for purchase in procurement.requisition_id.purchase_ids]):
+ return True
+ return False
+ return super(procurement_order, self)._check(cr, uid, procurement, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py
index 0ea7d0e13e1..4e16dc93d2c 100644
--- a/addons/stock/procurement.py
+++ b/addons/stock/procurement.py
@@ -216,6 +216,7 @@ class procurement_order(osv.osv):
move_obj = self.pool.get('stock.move')
move_dict = self._run_move_create(cr, uid, procurement, context=context)
move_id = move_obj.create(cr, uid, move_dict, context=context)
+ self.message_post(cr, uid, [procurement.id], body=_("Supply Move created"), context=context)
move_obj.action_confirm(cr, uid, [move_id], context=context)
return True
return super(procurement_order, self)._run(cr, uid, procurement, context)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index e67ecf3e7ec..0824010fcc7 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1792,13 +1792,15 @@ class stock_move(osv.osv):
states[state].append(move.id)
self._picking_assign(cr, uid, move, context=context)
+ for move in self.browse(cr, uid, states['confirmed'], context=context):
+ if move.procure_method == 'make_to_order':
+ self._create_procurement(cr, uid, move, context=context)
+ states['waiting'].append(move.id)
+ states['confirmed'].remove(move.id)
+
for state, write_ids in states.items():
if len(write_ids):
self.write(cr, uid, write_ids, {'state': state})
- if state == 'confirmed':
- for move in self.browse(cr, uid, write_ids, context=context):
- if move.procure_method == 'make_to_order':
- self._create_procurement(cr, uid, move, context=context)
moves = self.browse(cr, uid, ids, context=context)
self._push_apply(cr, uid, moves, context=context)
return ids