Impacted versions: 10.0

Steps to reproduce: Create Sale Order (line in step 1 product qty = 100, in step 2 line product qty = 1000) with two or more purchase procurements  and Cancel it.

Current behavior:

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 640, in _handle_exception
    return super(JsonRequest, self)._handle_exception(exception)
  File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 677, in dispatch
    result = self._call_function(**self.params)
  File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 333, in _call_function
    return checked_call(self.db, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/odoo/service/model.py", line 101, in wrapper
    return f(dbname, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 326, in checked_call
    result = self.endpoint(*a, **kw)
  File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 935, in __call__
    return self.method(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/odoo/http.py", line 506, in response_wrap
    response = f(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/odoo/addons/web/controllers/main.py", line 889, in call_button
    action = self._call_kw(model, method, args, {})
  File "/usr/lib/python2.7/dist-packages/odoo/addons/web/controllers/main.py", line 877, in _call_kw
    return call_kw(request.env[model], method, args, kwargs)
  File "/usr/lib/python2.7/dist-packages/odoo/api.py", line 689, in call_kw
    return call_kw_multi(method, model, args, kwargs)
  File "/usr/lib/python2.7/dist-packages/odoo/api.py", line 680, in call_kw_multi
    result = method(recs, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/odoo/addons/sale_stock/models/sale_order.py", line 66, in action_cancel
    self.mapped('order_line').mapped('procurement_ids').cancel()
  File "/usr/lib/python2.7/dist-packages/odoo/addons/stock/models/procurement.py", line 85, in cancel
    propagated_procurements = self.filtered(lambda order: order.state != 'done').propagate_cancels()
  File "/usr/lib/python2.7/dist-packages/odoo/addons/purchase/models/purchase.py", line 898, in propagate_cancels
    price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, procurement.purchase_line_id.product_id.supplier_taxes_id, procurement.purchase_line_id.taxes_id, self.company_id) if seller else 0.0
  File "/usr/lib/python2.7/dist-packages/odoo/fields.py", line 904, in __get__
    record.ensure_one()
  File "/usr/lib/python2.7/dist-packages/odoo/models.py", line 4823, in ensure_one
    raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: procurement.order(37, 38)

Expected behavior:

Order Canceled

Comment:

Error exist in line:

 price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, procurement.purchase_line_id.product_id.supplier_taxes_id, procurement.purchase_line_id.taxes_id, self.company_id) if seller else 0.0

the problem is with value: self.company_id

should be: procurement.company_id





addons/purchase/models/purchase.py
if procurement.rule_id.action == 'buy' and procurement.purchase_line_id:
                if procurement.purchase_line_id.order_id.state not in ('draft', 'cancel', 'sent', 'to validate'):
                    raise UserError(
                        _('Can not cancel a procurement related to a purchase order. Please cancel the purchase order first.'))
            if procurement.purchase_line_id:
                price_unit = 0.0
                product_qty = 0.0
                others_procs = procurement.purchase_line_id.procurement_ids.filtered(lambda r: r != procurement)
                for other_proc in others_procs:
                    if other_proc.state not in ['cancel', 'draft']:
                        product_qty += other_proc.product_uom._compute_quantity(other_proc.product_qty, procurement.purchase_line_id.product_uom)
                precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
                if not float_is_zero(product_qty, precision_digits=precision):
                    seller = procurement.product_id._select_seller(
                        partner_id=procurement.purchase_line_id.partner_id,
                        quantity=product_qty,
                        date=procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10],
                        uom_id=procurement.purchase_line_id.product_uom)
                    price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, procurement.purchase_line_id.product_id.supplier_taxes_id, procurement.purchase_line_id.taxes_id, self.company_id) if seller else 0.0
                    if price_unit and seller and procurement.purchase_line_id.order_id.currency_id and seller.currency_id != procurement.purchase_line_id.order_id.currency_id:
                        price_unit = seller.currency_id.compute(price_unit, procurement.purchase_line_id.order_id.currency_id)
                    if seller and seller.product_uom != procurement.purchase_line_id.product_uom:
                        price_unit = seller.product_uom._compute_price(price_unit, procurement.purchase_line_id.product_uom)
                    procurement.purchase_line_id.product_qty = product_qty
                    procurement.purchase_line_id.price_unit = price_unit
                else:
                    procurement.purchase_line_id.unlink()
        return result
    @api.multi
    def _run(self):