diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index e4a0d67e202..56b95ab8feb 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -666,7 +666,7 @@ class AccountInvoice(models.Model): self.ensure_one() credit_aml = self.env['account.move.line'].browse(credit_aml_id) if not credit_aml.currency_id and self.currency_id != self.company_id.currency_id: - credit_aml.with_context(allow_amount_currency=True).write({ + credit_aml.with_context(allow_amount_currency=True, check_move_validity=False).write({ 'amount_currency': self.company_id.currency_id.with_context(date=credit_aml.date).compute(credit_aml.balance, self.currency_id), 'currency_id': self.currency_id.id}) if credit_aml.payment_id: diff --git a/addons/account/models/res_config.py b/addons/account/models/res_config.py index 4c16d8726c6..45744ded185 100644 --- a/addons/account/models/res_config.py +++ b/addons/account/models/res_config.py @@ -233,10 +233,8 @@ class AccountConfigSettings(models.TransientModel): def set_product_taxes(self): """ Set the product taxes if they have changed """ ir_values_obj = self.env['ir.values'] - if self.default_sale_tax_id: - ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id], for_all_users=True, company_id=self.company_id.id) - if self.default_purchase_tax_id: - ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id], for_all_users=True, company_id=self.company_id.id) + ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id] if self.default_sale_tax_id else False, for_all_users=True, company_id=self.company_id.id) + ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id] if self.default_purchase_tax_id else False, for_all_users=True, company_id=self.company_id.id) @api.multi def set_chart_of_accounts(self): diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py index 2d05512b0e3..e922b7f42ea 100644 --- a/addons/account/wizard/account_invoice_refund.py +++ b/addons/account/wizard/account_invoice_refund.py @@ -74,7 +74,7 @@ class AccountInvoiceRefund(models.TransientModel): for tmpline in refund.move_id.line_ids: if tmpline.account_id.id == inv.account_id.id: to_reconcile_lines += tmpline - to_reconcile_lines.filtered(lambda l: l.reconciled == False).reconcile() + to_reconcile_lines.filtered(lambda l: l.reconciled == False).reconcile() if mode == 'modify': invoice = inv.read(inv_obj._get_refund_modify_read_fields()) invoice = invoice[0] diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index 0f120e000d8..48b38c90487 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -393,7 +393,7 @@ class AccountVoucherLine(models.Model): if product.description_purchase: values['name'] += '\n' + product.description_purchase else: - values['price_unit'] = product.lst_price + values['price_unit'] = price_unit or product.lst_price taxes = product.taxes_id or account.tax_ids if product.description_sale: values['name'] += '\n' + product.description_sale @@ -403,7 +403,7 @@ class AccountVoucherLine(models.Model): if company and currency: if company.currency_id != currency: if type == 'purchase': - values['price_unit'] = product.standard_price + values['price_unit'] = price_unit or product.standard_price values['price_unit'] = values['price_unit'] * currency.rate return {'value': values, 'domain': {}} diff --git a/addons/google_account/models/google_service.py b/addons/google_account/models/google_service.py index 4c9ee092104..7ce9d9a3333 100644 --- a/addons/google_account/models/google_service.py +++ b/addons/google_account/models/google_service.py @@ -8,6 +8,7 @@ import urllib2 import werkzeug.urls from odoo import api, fields, models, registry, _ +from odoo.exceptions import UserError from odoo.http import request @@ -124,6 +125,9 @@ class GoogleService(models.TransientModel): client_id = Parameters.get_param('google_%s_client_id' % (service,), default=False) client_secret = Parameters.get_param('google_%s_client_secret' % (service,), default=False) + if not client_id or not client_secret: + raise UserError(_("The account for the Google service '%s' is not configured") % service) + headers = {"content-type": "application/x-www-form-urlencoded"} data = werkzeug.url_encode({ 'refresh_token': refresh_token, diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index 99085ee581b..7fd5592fa66 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -117,7 +117,7 @@ class MailController(http.Controller): follower_id = None follower_recs = request.env['mail.followers'].sudo().browse(follower_ids) res_ids = follower_recs.mapped('res_id') - request.env[res_model].browse(res_ids).check_access_rule("write") + request.env[res_model].browse(res_ids).check_access_rule("read") for follower in follower_recs: is_uid = partner_id == follower.partner_id follower_id = follower.id if is_uid else follower_id diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 55446e37263..4bc958684f9 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -294,8 +294,11 @@ class MailComposer(models.TransientModel): 'no_auto_thread': self.no_auto_thread, 'mail_server_id': self.mail_server_id.id, } + # mass mailing: rendering override wizard static values if mass_mail_mode and self.model: + if self.model in self.env and hasattr(self.env[self.model], 'message_get_email_values'): + mail_values.update(self.env[self.model].browse(res_id).message_get_email_values()) # keep a copy unless specifically requested, reset record name (avoid browsing records) mail_values.update(notification=not self.auto_delete_message, model=self.model, res_id=res_id, record_name=False) # auto deletion of mail_mail diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index df9838ba1f7..5ae2b039839 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -63,7 +63,7 @@ class SaleOrder(models.Model): @api.multi def action_cancel(self): - self.order_line.mapped('procurement_ids').cancel() + self.mapped('order_line').mapped('procurement_ids').cancel() return super(SaleOrder, self).action_cancel() @api.multi diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 3470f816b6a..0455c5b95e3 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -156,7 +156,8 @@ class StockMove(models.Model): @api.depends('product_id', 'product_uom', 'product_uom_qty') def _compute_product_qty(self): if self.product_uom: - self.product_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id) + rounding_method = self._context.get('rounding_method', 'UP') + self.product_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id, rounding_method=rounding_method) def _set_product_qty(self): """ The meaning of product_qty field changed lately and is now a functional field computing the quantity @@ -953,11 +954,11 @@ class StockMove(models.Model): # TDE CLEANME: remove context key + add as parameter if self.env.context.get('source_location_id'): defaults['location_id'] = self.env.context['source_location_id'] - new_move = self.copy(defaults) + new_move = self.with_context(rounding_method='HALF-UP').copy(defaults) # ctx = context.copy() # TDE CLEANME: used only in write in this file, to clean # ctx['do_not_propagate'] = True - self.with_context(do_not_propagate=True).write({'product_uom_qty': self.product_uom_qty - uom_qty}) + self.with_context(do_not_propagate=True, rounding_method='HALF-UP').write({'product_uom_qty': self.product_uom_qty - uom_qty}) if self.move_dest_id and self.propagate and self.move_dest_id.state not in ('done', 'cancel'): new_move_prop = self.move_dest_id.split(qty) diff --git a/doc/cla/individual/NothingCtrl.md b/doc/cla/individual/NothingCtrl.md new file mode 100644 index 00000000000..bf58b0034d3 --- /dev/null +++ b/doc/cla/individual/NothingCtrl.md @@ -0,0 +1,9 @@ +Vietnam, 2017-08-15 + +I hereby agree to the terms of the Odoo Individual Contributor License Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Duong Bao Thang nothingctrl@gmail.com https://github.com/NothingCtrl diff --git a/doc/reference/views.rst b/doc/reference/views.rst index 3dd6d885ce4..e7e109180dd 100644 --- a/doc/reference/views.rst +++ b/doc/reference/views.rst @@ -844,17 +844,13 @@ attributes: Possible children of the view element are: ``field`` - declares fields to aggregate or to use in kanban *logic*. If the field is - simply displayed in the kanban view, it does not need to be pre-declared. + declares fields to use in kanban *logic*. If the field is simply displayed in + the kanban view, it does not need to be pre-declared. Possible attributes are: ``name`` (required) the name of the field to fetch - ``sum``, ``avg``, ``min``, ``max``, ``count`` - displays the corresponding aggregation at the top of a kanban column, the - field's value is the label of the aggregation (a string). Only one - aggregate operation per field is supported. ``templates`` defines a list of :ref:`reference/qweb` templates. Cards definition may be diff --git a/odoo/addons/base/ir/ir_model.py b/odoo/addons/base/ir/ir_model.py index dd5e68d7364..f33fe6f2867 100644 --- a/odoo/addons/base/ir/ir_model.py +++ b/odoo/addons/base/ir/ir_model.py @@ -438,7 +438,8 @@ class IrModelFields(models.Model): if field.state == 'manual' and field.ttype == 'many2many': rel_name = field.relation_table or model._fields[field.name].relation tables_to_drop.add(rel_name) - model._pop_field(field.name) + if field.state == 'manual': + model._pop_field(field.name) if tables_to_drop: # drop the relation tables that are not used by other fields