diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 28f508ea1c0..b82b8756a1c 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -2012,7 +2012,10 @@ class AccountInvoiceLine(models.Model): return if not self.product_id: fpos = self.invoice_id.fiscal_position_id - default_tax = self.invoice_id.type in ('out_invoice', 'out_refund') and self.invoice_id.company_id.account_sale_tax_id or self.invoice_id.company_id.account_purchase_tax_id + if self.invoice_id.type in ('out_invoice', 'out_refund'): + default_tax = self.invoice_id.company_id.account_sale_tax_id + else: + default_tax = self.invoice_id.company_id.account_purchase_tax_id self.invoice_line_tax_ids = fpos.map_tax(self.account_id.tax_ids or default_tax, partner=self.partner_id).ids elif not self.price_unit: self._set_taxes() diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py index 614aba000ab..f6e312b2110 100644 --- a/addons/account/report/account_invoice_report.py +++ b/addons/account/report/account_invoice_report.py @@ -189,10 +189,9 @@ class ReportInvoiceWithPayment(models.AbstractModel): @api.model def _get_report_values(self, docids, data=None): - report = self.env['ir.actions.report']._get_report_from_name('account.report_invoice_with_payments') return { 'doc_ids': docids, - 'doc_model': report.model, - 'docs': self.env[report.model].browse(docids), + 'doc_model': 'account.invoice', + 'docs': self.env['account.invoice'].browse(docids), 'report_type': data.get('report_type') if data else '', } diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index 985bcd15496..f7f29efb011 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -932,7 +932,7 @@ var StatementModel = BasicModel.extend({ 'link': prop.id, 'tax_ids': [tax.id], 'amount': tax.amount, - 'label': tax.name, + 'label': prop.label ? prop.label + " " + tax.name : tax.name, 'date': prop.date, 'account_id': tax.account_id ? [tax.account_id, null] : prop.account_id, 'analytic': tax.analytic, diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js index e6be300714d..7103e3f7d71 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js @@ -794,6 +794,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, { */ _onSelectMoveLine: function (event) { var $el = $(event.target); + $el.prop('disabled', true); this._destroyPopover($el); var moveLineId = $el.closest('.mv_line').data('line-id'); this.trigger_up('add_proposition', {'data': moveLineId}); diff --git a/addons/account/static/tests/reconciliation_tests.js b/addons/account/static/tests/reconciliation_tests.js index d2f52cb382d..e565ec91ce2 100644 --- a/addons/account/static/tests/reconciliation_tests.js +++ b/addons/account/static/tests/reconciliation_tests.js @@ -1299,14 +1299,14 @@ QUnit.module('account', { await testUtils.dom.click(widget.$('.create .quick_add button:contains(ATOS)')); assert.strictEqual(widget.$('.accounting_view tbody .cell_label, .accounting_view tbody .cell_right').text().replace(/[\n\r\s$,]+/g, ' '), - " ATOS Banque 1145.62 ATOS Frais 26.71 Tax 20.00% 229.12 Tax 10.00% include 2.67 ", "should display 4 lines"); + " ATOS Banque 1145.62 ATOS Frais 26.71 ATOS Banque Tax 20.00% 229.12 ATOS Frais Tax 10.00% include 2.67 ", "should display 4 lines"); assert.strictEqual(widget.$('.accounting_view tfoot .cell_label, .accounting_view tfoot .cell_left').text().replace(/[\n\r\s$,]+/g, ' '), "Open balance229.12", "should display the 'Open balance' line with value in left column"); await testUtils.fields.editAndTrigger(widget.$('.create .create_amount input'), '100',['input']); assert.strictEqual(widget.$('.accounting_view tbody').text().replace(/[\n\r\s$,]+/g, ' '), - " 101120 New ATOS Banque 1075.00 101130 New ATOS Frais 90.91 101120 New Tax 20.00% 215.00 101300 New Tax 10.00% include 9.09 ", + " 101120 New ATOS Banque 1075.00 101130 New ATOS Frais 90.91 101120 New ATOS Banque Tax 20.00% 215.00 101300 New ATOS Frais Tax 10.00% include 9.09 ", "should update the value of the 4 lines (because the line must have 100% of the value)"); assert.strictEqual(widget.$('.accounting_view tfoot .cell_label, .accounting_view tfoot .cell_left').text().replace(/[\n\r\s$,]+/g, ' '), "Open balance215.00", "should change the 'Open balance' line because the 20.00% tax is not an include tax"); diff --git a/addons/account/wizard/account_invoice_send_views.xml b/addons/account/wizard/account_invoice_send_views.xml index eac9adda58e..cae3b296b63 100644 --- a/addons/account/wizard/account_invoice_send_views.xml +++ b/addons/account/wizard/account_invoice_send_views.xml @@ -14,7 +14,6 @@ -
diff --git a/addons/account_analytic_default/models/account_analytic_default.py b/addons/account_analytic_default/models/account_analytic_default.py index 34052a51560..707e9920ac0 100644 --- a/addons/account_analytic_default/models/account_analytic_default.py +++ b/addons/account_analytic_default/models/account_analytic_default.py @@ -73,8 +73,9 @@ class AccountInvoiceLine(models.Model): fields.Date.today(), company_id=self.company_id.id ) - self.account_analytic_id = rec.analytic_id.id - self.analytic_tag_ids = rec.analytic_tag_ids.ids + if rec: + self.account_analytic_id = rec.analytic_id.id + self.analytic_tag_ids = rec.analytic_tag_ids.ids return res def _set_additional_fields(self, invoice): diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index 3cb54bf3b43..a34367ddedd 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -347,10 +347,13 @@ class AccountVoucher(models.Model): } if company_currency != current_currency: ctx = {} + sign = temp['credit'] and -1 or 1 + amount_currency = company_cur._convert(tax_vals['amount'], current_cur, line.company_id, + self.account_date or fields.Date.today(), round=True) if self.account_date: ctx['date'] = self.account_date temp['currency_id'] = current_currency - temp['amount_currency'] = company_cur._convert(tax_vals['amount'], current_cur, line.company_id, self.account_date or fields.Date.today(), round=True) + temp['amount_currency'] = sign * abs(amount_currency) self.env['account.move.line'].create(temp) # When global rounding is activated, we must wait until all tax lines are computed to diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml index e6857e7f4ad..cf2480aa1f5 100644 --- a/addons/crm/views/crm_lead_views.xml +++ b/addons/crm/views/crm_lead_views.xml @@ -92,7 +92,7 @@
- + diff --git a/addons/digest/views/digest_templates.xml b/addons/digest/views/digest_templates.xml index 0010ad6a1c0..e7cd42d5df5 100644 --- a/addons/digest/views/digest_templates.xml +++ b/addons/digest/views/digest_templates.xml @@ -6,7 +6,7 @@

Digest Subscriptions

-

You have been successfully unsubscribed from

+

You have been successfully unsubscribed from

diff --git a/addons/google_drive/models/res_config_settings.py b/addons/google_drive/models/res_config_settings.py index 49d7ff7d86d..eff3d6c3f6f 100644 --- a/addons/google_drive/models/res_config_settings.py +++ b/addons/google_drive/models/res_config_settings.py @@ -28,10 +28,12 @@ class ResConfigSettings(models.TransientModel): params = self.env['ir.config_parameter'].sudo() authorization_code_before = params.get_param('google_drive_authorization_code') authorization_code = self.google_drive_authorization_code - refresh_token = False - if authorization_code and authorization_code != authorization_code_before: - refresh_token = self.env['google.service'].generate_refresh_token('drive', authorization_code) - params.set_param('google_drive_refresh_token', refresh_token) + if authorization_code != authorization_code_before: + refresh_token = ( + self.env['google.service'].generate_refresh_token('drive', authorization_code) + if authorization_code else False + ) + params.set_param('google_drive_refresh_token', refresh_token) @api.multi def action_setup_token(self): diff --git a/addons/hr/security/hr_security.xml b/addons/hr/security/hr_security.xml index 8d435e67463..30958ef43d1 100644 --- a/addons/hr/security/hr_security.xml +++ b/addons/hr/security/hr_security.xml @@ -47,5 +47,12 @@ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + Employee multi company rule + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 97bf33abc7f..a9bc53d1bae 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -554,6 +554,8 @@ class HolidaysRequest(models.Model): if not values.get('department_id'): values.update({'department_id': self.env['hr.employee'].browse(employee_id).department_id.id}) holiday = super(HolidaysRequest, self.with_context(mail_create_nosubscribe=True)).create(values) + if self._context.get('import_file'): + holiday._onchange_leave_dates() if not self._context.get('leave_fast_create'): holiday.add_follower(employee_id) if holiday.validation_type == 'hr': diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 91bf5658093..50f71e713a0 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -367,7 +367,8 @@ class HolidaysAllocation(models.Model): holiday.message_subscribe(partner_ids=(holiday.employee_id.parent_id.user_id.partner_id | holiday.employee_id.leave_manager_id.partner_id).ids) if 'employee_id' in values: holiday._onchange_employee() - holiday.activity_update() + if not self._context.get('import_file'): + holiday.activity_update() return holiday @api.multi diff --git a/addons/hr_timesheet/views/res_config_settings_views.xml b/addons/hr_timesheet/views/res_config_settings_views.xml index 6588b0b2d14..2cb4437556a 100644 --- a/addons/hr_timesheet/views/res_config_settings_views.xml +++ b/addons/hr_timesheet/views/res_config_settings_views.xml @@ -105,5 +105,5 @@ + action="hr_timesheet_config_settings_action" sequence="0" groups="base.group_system"/> diff --git a/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py b/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py index 572ba6d5ce9..166e6f23065 100644 --- a/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py +++ b/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models +from odoo import api, fields, models, tools class TimesheetAttendance(models.Model): @@ -17,7 +17,7 @@ class TimesheetAttendance(models.Model): @api.model_cr def init(self): - self._cr.execute("DROP VIEW IF EXISTS hr_timesheet_attendance_report") + tools.drop_view_if_exists(self.env.cr, self._table) self._cr.execute("""CREATE OR REPLACE VIEW %s AS ( SELECT max(id) AS id, diff --git a/addons/l10n_es/data/account.account.template-common.csv b/addons/l10n_es/data/account.account.template-common.csv index 21c952cf79c..4e5121d061e 100644 --- a/addons/l10n_es/data/account.account.template-common.csv +++ b/addons/l10n_es/data/account.account.template-common.csv @@ -276,7 +276,7 @@ "account_common_523","Proveedores de inmovilizado a corto plazo","523","account.data_account_type_payable","l10n_es.account_chart_template_common","l10n_es.account_group_523","True" "account_common_524","Acreedores por arrendamiento financiero a corto plazo","524","account.data_account_type_current_liabilities","l10n_es.account_chart_template_common","l10n_es.account_group_524","False" "account_common_525","Efectos a pagar a corto plazo","525","account.data_account_type_current_liabilities","l10n_es.account_chart_template_common","l10n_es.account_group_525","False" -"account_common_526","Dividendo activo a pagar","526","account.data_account_type_current_liabilities","l10n_es.account_chart_template_common","l10n_es.account_group_526","False" +"account_common_526","Dividendo activo a pagar","526","account.data_account_type_payable","l10n_es.account_chart_template_common","l10n_es.account_group_526","True" "account_common_527","Intereses a corto plazo de deudas con entidades de crédito","527","account.data_account_type_current_liabilities","l10n_es.account_chart_template_common","l10n_es.account_group_527","False" "account_common_528","Intereses a corto plazo de deudas","528","account.data_account_type_current_liabilities","l10n_es.account_chart_template_common","l10n_es.account_group_528","False" "account_common_5290","Provisión a corto plazo por retribuciones al personal","5290","account.data_account_type_current_liabilities","l10n_es.account_chart_template_common","l10n_es.account_group_5290","True" diff --git a/addons/l10n_es/data/account_tax_data.xml b/addons/l10n_es/data/account_tax_data.xml index 9461c865a72..dca71560db1 100644 --- a/addons/l10n_es/data/account_tax_data.xml +++ b/addons/l10n_es/data/account_tax_data.xml @@ -445,6 +445,7 @@ P_IVA21_SP_IN purchase + percent @@ -550,6 +551,7 @@ purchase percent + percent purchase + IVA 4% Adquisición de servicios extracomunitarios P_IVA10_SP_EX percent + purchase IVA 10% Adquisición de servicios extracomunitarios @@ -820,6 +824,7 @@ purchase + percent P_IVA4_IC_BC + percent purchase IVA 4% Adquisición Intracomunitario. Bienes corrientes @@ -924,6 +930,7 @@ percent purchase IVA 4% Adquisición Intracomunitario. Bienes de inversión + P_IVA10_IC_BC + percent purchase IVA 10% Adquisición Intracomunitario. Bienes corrientes @@ -1026,6 +1034,7 @@ percent purchase IVA 10% Adquisición Intracomunitario. Bienes de inversión + percent purchase IVA 10% Adquisición de servicios intracomunitarios + percent purchase IVA 4% Adquisición de servicios intracomunitarios + P_IVA4_ISP IVA 4% Compra con Inversión del Sujeto Pasivo Nacional purchase + percent @@ -3443,6 +3455,7 @@ P_IVA10_ISP IVA 10% Compra con Inversión del Sujeto Pasivo Nacional purchase + percent @@ -3496,6 +3509,7 @@ purchase percent + + + lunch.order: Don't change confirmed order + + [('state', '!=', 'confirmed'), ('user_id', '=', user.id)] + + + + + + + + manager can do whatever + + [(1, '=', 1)] + + + + + + diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index bf0b0141604..16e0b261291 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -313,6 +313,12 @@ class MailActivity(models.Model): @api.model def create(self, values): activity = super(MailActivity, self).create(values) + need_sudo = False + try: # in multicompany, reading the partner might break + partner_id = activity.user_id.partner_id.id + except exceptions.AccessError: + need_sudo = True + partner_id = activity.user_id.sudo().partner_id.id # send a notification to assigned user; in case of manually done activity also check # target has rights on document otherwise we prevent its creation. Automated activities @@ -321,9 +327,12 @@ class MailActivity(models.Model): if not activity.automated: activity._check_access_assignation() if not self.env.context.get('mail_activity_quick_update', False): - activity.action_notify() + if need_sudo: + activity.sudo().action_notify() + else: + activity.action_notify() - self.env[activity.res_model].browse(activity.res_id).message_subscribe(partner_ids=[activity.user_id.partner_id.id]) + self.env[activity.res_model].browse(activity.res_id).message_subscribe(partner_ids=[partner_id]) if activity.date_deadline <= fields.Date.today(): self.env['bus.bus'].sendone( (self._cr.dbname, 'res.partner', activity.user_id.partner_id.id), diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 9ed782b40a8..dd92247078f 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -431,7 +431,7 @@ class MailThread(models.AbstractModel): # ------------------------------------------------------ def with_lang(self): - if 'lang' not in self._context: + if not self._context.get("lang"): return self.with_context(lang=self.env.user.lang) return self diff --git a/addons/mail/static/src/js/emojis.js b/addons/mail/static/src/js/emojis.js index 54b995f3bb6..f8684cde541 100644 --- a/addons/mail/static/src/js/emojis.js +++ b/addons/mail/static/src/js/emojis.js @@ -73,6 +73,7 @@ var data = { "<3": "❤️", ":heart": "❤️", // alt. "