diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index 467ed1c4533..a022f72e66c 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -182,7 +182,8 @@ class AccountVoucher(models.Model): 'amount_currency': (sign * abs(self.amount) # amount < 0 for refunds if company_currency != current_currency else 0.0), 'date': self.account_date, - 'date_maturity': self.date_due + 'date_maturity': self.date_due, + 'payment_id': self._context.get('payment_id'), } return move_line @@ -221,6 +222,24 @@ class AccountVoucher(models.Model): for voucher in self: return voucher.currency_id.compute(amount, voucher.company_id.currency_id) + @api.multi + def voucher_pay_now_payment_create(self): + payment_methods = self.journal_id.outbound_payment_method_ids + return { + 'payment_type': 'outbound', + 'payment_method_id': payment_methods and payment_methods[0].id or False, + 'partner_type': 'supplier', + 'partner_id': self.partner_id.id, + 'amount': self.amount, + 'currency_id': self.currency_id.id, + 'payment_date': self.date, + 'journal_id': self.journal_id.id, + 'company_id': self.company_id.id, + 'communication': self.name, + 'name': self.name, + 'state': 'reconciled', + } + @api.multi def voucher_move_line_create(self, line_total, move_id, company_currency, current_currency): ''' @@ -258,8 +277,8 @@ class AccountVoucher(models.Model): 'tax_ids': [(4,t.id) for t in line.tax_ids], 'amount_currency': line.price_subtotal if current_currency != company_currency else 0.0, 'currency_id': company_currency != current_currency and current_currency or False, + 'payment_id': self._context.get('payment_id'), } - self.env['account.move.line'].with_context(apply_taxes=True).create(move_line) return line_total @@ -279,6 +298,9 @@ class AccountVoucher(models.Model): ctx = local_context.copy() ctx['date'] = voucher.account_date ctx['check_move_validity'] = False + # Create a payment to allow the reconciliation when pay_now = 'pay_now'. + if self.pay_now == 'pay_now' and self.amount > 0: + ctx['payment_id'] = self.env['account.payment'].create(self.voucher_pay_now_payment_create()).id # Create the account move record. move = self.env['account.move'].create(voucher.account_move_get()) # Get the name of the account_move just created diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py index a2cc6fb10e6..3143d5e2165 100644 --- a/addons/base_automation/models/base_automation.py +++ b/addons/base_automation/models/base_automation.py @@ -304,7 +304,15 @@ class BaseAutomation(models.Model): # retrieve all actions, and patch their corresponding model for action_rule in self.with_context({}).search([]): - Model = self.env[action_rule.model_name] + Model = self.env.get(action_rule.model_name) + + # Do not crash if the model of the base_action_rule was uninstalled + if Model is None: + _logger.warning("Action rule with ID %d depends on model %s" % + (action_rule.id, + action_rule.model_name)) + continue + if action_rule.trigger == 'on_create': patch(Model, 'create', make_create()) diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index ccbdf40edd8..fead382b695 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1550,6 +1550,7 @@ exports.Orderline = Backbone.Model.extend({ return t.id === el; })); }); + product_taxes = _.map(product_taxes, this._map_tax_fiscal_position.bind(this)); var all_taxes = this.compute_all(product_taxes, price_unit, this.get_quantity(), this.pos.currency.rounding); _(all_taxes.taxes).each(function(tax) { diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py index faa5521b51f..fd2bfdb9dec 100644 --- a/addons/product/models/product_pricelist.py +++ b/addons/product/models/product_pricelist.py @@ -438,7 +438,7 @@ class PricelistItem(models.Model): elif self.compute_price == 'percentage': self.price = _("%s %% discount") % (self.percent_price) else: - self.price = _("%s %% discount and %s surcharge") % (abs(self.price_discount), self.price_surcharge) + self.price = _("%s %% discount and %s surcharge") % (self.price_discount, self.price_surcharge) @api.onchange('applied_on') def _onchange_applied_on(self): diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index c7080dc306f..6d3199f4a18 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -857,15 +857,16 @@ class SaleOrderLine(models.Model): # TO DO: move me in master/saas-16 on sale.order if self.order_id.pricelist_id.discount_policy == 'with_discount': return product.with_context(pricelist=self.order_id.pricelist_id.id).price - price, rule_id = self.order_id.pricelist_id.get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id) + final_price, rule_id = self.order_id.pricelist_id.get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id) pricelist_item = self.env['product.pricelist.item'].browse(rule_id) - if (pricelist_item.base == 'pricelist' and pricelist_item.base_pricelist_id.discount_policy == 'with_discount'): - price, rule_id = pricelist_item.base_pricelist_id.get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id) - return price + if pricelist_item.base == 'pricelist': + base_price, rule_id = pricelist_item.base_pricelist_id.get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id) + base_price = pricelist_item.base_pricelist_id.currency_id.compute(base_price, self.order_id.pricelist_id.currency_id) else: - from_currency = self.order_id.company_id.currency_id - product_price = product[pricelist_item.base] if (pricelist_item and pricelist_item.base != 'pricelist') else product.lst_price - return from_currency.compute(product_price, self.order_id.pricelist_id.currency_id) + base_price = product[pricelist_item.base] if pricelist_item else product.lst_price + base_price = product.currency_id.compute(base_price, self.order_id.pricelist_id.currency_id) + # negative discounts (= surcharge) are included in the display price (= unit price) + return max(base_price, final_price) @api.multi @api.onchange('product_id') diff --git a/addons/stock/models/stock_inventory.py b/addons/stock/models/stock_inventory.py index 271e12759b3..996dfec0b5d 100644 --- a/addons/stock/models/stock_inventory.py +++ b/addons/stock/models/stock_inventory.py @@ -310,7 +310,7 @@ class InventoryLine(models.Model): 'product.product', 'Product', index=True, required=True) product_name = fields.Char( - 'Product Name', related='product_id.name', store=True) + 'Product Name', related='product_id.name', store=True, readonly=True) product_code = fields.Char( 'Product Code', related='product_id.default_code', store=True) product_uom_id = fields.Many2one( @@ -373,8 +373,14 @@ class InventoryLine(models.Model): self._compute_theoretical_qty() self.product_qty = self.theoretical_qty + @api.model + def write(self, values): + values.pop('product_name', False) + res = super(InventoryLine, self).write(values) + @api.model def create(self, values): + values.pop('product_name', False) if 'product_id' in values and 'product_uom_id' not in values: values['product_uom_id'] = self.env['product.product'].browse(values['product_id']).uom_id.id existings = self.search([ diff --git a/addons/stock/views/stock_quant_views.xml b/addons/stock/views/stock_quant_views.xml index 16050b03530..ea215dc23e7 100644 --- a/addons/stock/views/stock_quant_views.xml +++ b/addons/stock/views/stock_quant_views.xml @@ -13,6 +13,8 @@ + + @@ -123,7 +125,7 @@ stock.quant form tree,form,pivot - {'search_default_internal_loc': 1, 'group_by': ['product_id', 'location_id']} + {'search_default_internal_loc': 1, 'search_default_stockable': 1, 'group_by': ['product_id', 'location_id']} This analysis gives you a fast overview on the current stock level of your products and their current inventory value. diff --git a/odoo/sql_db.py b/odoo/sql_db.py index 3f70d10a38c..4cc6163a96f 100644 --- a/odoo/sql_db.py +++ b/odoo/sql_db.py @@ -606,7 +606,7 @@ class ConnectionPool(object): cnx.close() break else: - raise PoolError('This connection does not below to the pool') + raise PoolError('This connection does not belong to the pool') @locked def close_all(self, dsn=None):