[FIX] purchase: update and cancel of purchase order line takes into account existing procurements
Update: When an existing purchase order line is updated, for example if a new procurement was required, we check if the sum of existing running linked procurements is larger than the quantity in the purchase order. If it is the case, we update the quantity and the unit price accordingly. Without this fix, we systematically add the procurement quantity (or the provider minimum quantity) to the purchase order line, even if the sum of the procurements is smaller than the ordered quantity. Cancel: When a procurement is cancelled, we recompute the unit price of the associated purchase order according to the quantity and make sure the provider minimum quantity is met. If the required quantity is zero, we cancel and unlink the purchase order line. opw: 632175 and 632176
This commit is contained in:
parent
5b6dcbb3a8
commit
610a461099
|
@ -1199,17 +1199,17 @@ class procurement_order(osv.osv):
|
|||
|
||||
def propagate_cancel(self, cr, uid, procurement, context=None):
|
||||
if procurement.rule_id.action == 'buy' and procurement.purchase_line_id:
|
||||
uom_obj = self.pool.get("product.uom")
|
||||
purchase_line_obj = self.pool.get('purchase.order.line')
|
||||
uom = procurement.purchase_line_id.product_uom
|
||||
product_qty = uom_obj._compute_qty_obj(cr, uid, procurement.product_uom, procurement.product_qty, uom, context=context)
|
||||
if procurement.purchase_line_id.state not in ('draft', 'cancel'):
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_('Can not cancel this procurement as the related purchase order has been confirmed already. Please cancel the purchase order first. '))
|
||||
if float_compare(procurement.purchase_line_id.product_qty, product_qty, 0, precision_rounding=uom.rounding) > 0:
|
||||
purchase_line_obj.write(cr, uid, [procurement.purchase_line_id.id], {'product_qty': procurement.purchase_line_id.product_qty - product_qty}, context=context)
|
||||
else:
|
||||
|
||||
new_qty, new_price = self._calc_new_qty_price(cr, uid, procurement, cancel=True, context=context)
|
||||
if new_qty != procurement.purchase_line_id.product_qty:
|
||||
purchase_line_obj.write(cr, uid, [procurement.purchase_line_id.id], {'product_qty': new_qty, 'price_unit': new_price}, context=context)
|
||||
if float_compare(new_qty, 0.0, precision_rounding=procurement.product_uom.rounding) != 1:
|
||||
purchase_line_obj.action_cancel(cr, uid, [procurement.purchase_line_id.id], context=context)
|
||||
purchase_line_obj.unlink(cr, uid, [procurement.purchase_line_id.id], context=context)
|
||||
return super(procurement_order, self).propagate_cancel(cr, uid, procurement, context=context)
|
||||
|
||||
def _run(self, cr, uid, procurement, context=None):
|
||||
|
@ -1339,6 +1339,41 @@ class procurement_order(osv.osv):
|
|||
'taxes_id': [(6, 0, taxes)],
|
||||
}
|
||||
|
||||
def _calc_new_qty_price(self, cr, uid, procurement, po_line=None, cancel=False, context=None):
|
||||
if not po_line:
|
||||
po_line = procurement.purchase_line_id
|
||||
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty,
|
||||
procurement.product_id.uom_po_id.id)
|
||||
if cancel:
|
||||
qty = -qty
|
||||
|
||||
# Make sure we use the minimum quantity of the partner corresponding to the PO
|
||||
if po_line.product_id.seller_id.id == po_line.order_id.partner_id.id:
|
||||
supplierinfo_min_qty = po_line.product_id.seller_qty
|
||||
else:
|
||||
supplierinfo_obj = self.pool.get('product.supplierinfo')
|
||||
supplierinfo_ids = supplierinfo_obj.search(cr, uid, [('name', '=', po_line.order_id.partner_id.id), ('product_tmpl_id', '=', po_line.product_id.product_tmpl_id.id)])
|
||||
supplierinfo_min_qty = supplierinfo_obj.browse(cr, uid, supplierinfo_ids).min_qty
|
||||
|
||||
if supplierinfo_min_qty == 0.0:
|
||||
qty += po_line.product_qty
|
||||
else:
|
||||
# Recompute quantity by adding existing running procurements.
|
||||
for proc in po_line.procurement_ids:
|
||||
qty += uom_obj._compute_qty(cr, uid, proc.product_uom.id, proc.product_qty,
|
||||
proc.product_id.uom_po_id.id) if proc.state == 'running' else 0.0
|
||||
qty = max(qty, supplierinfo_min_qty) if qty > 0.0 else 0.0
|
||||
|
||||
price = po_line.price_unit
|
||||
if qty != po_line.product_qty:
|
||||
pricelist_obj = self.pool.get('product.pricelist')
|
||||
pricelist_id = po_line.order_id.partner_id.property_product_pricelist_purchase.id
|
||||
price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, po_line.order_id.partner_id.id, {'uom': procurement.product_uom.id})[pricelist_id]
|
||||
|
||||
return qty, price
|
||||
|
||||
def make_po(self, cr, uid, ids, context=None):
|
||||
""" Resolve the purchase from procurement, which may result in a new PO creation, a new PO line creation or a quantity change on existing PO line.
|
||||
Note that some operations (as the PO creation) are made as SUPERUSER because the current user may not have rights to do it (mto product launched by a sale for example)
|
||||
|
@ -1376,9 +1411,12 @@ class procurement_order(osv.osv):
|
|||
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, SUPERUSER_ID, 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)
|
||||
new_qty, new_price = self._calc_new_qty_price(cr, uid, procurement, po_line=po_line, context=context)
|
||||
|
||||
if new_qty > po_line.product_qty:
|
||||
po_line_obj.write(cr, SUPERUSER_ID, po_line.id, {'product_qty': new_qty, 'price_unit': new_price}, context=context)
|
||||
sum_po_line_ids.append(procurement.id)
|
||||
else:
|
||||
line_vals.update(order_id=po_id)
|
||||
po_line_id = po_line_obj.create(cr, SUPERUSER_ID, line_vals, context=context)
|
||||
|
|
Loading…
Reference in New Issue