diff --git a/addons/account/controllers/mail.py b/addons/account/controllers/mail.py index f30c69e21ba..564856b909c 100644 --- a/addons/account/controllers/mail.py +++ b/addons/account/controllers/mail.py @@ -11,6 +11,7 @@ from odoo.tools.misc import consteq class MailController(MailController): + @classmethod def _redirect_to_record(cls, model, res_id, access_token=None): # If the current user doesn't have access to the invoice, but provided # a valid access token, redirect him to the front-end view. diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index c477ca91d77..30934695d07 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -318,7 +318,7 @@ class AccountMoveLine(models.Model): if not cr.fetchone(): cr.execute('CREATE INDEX account_move_line_partner_id_ref_idx ON account_move_line (partner_id, ref)') - @api.depends('debit', 'credit', 'amount_currency', 'currency_id', 'matched_debit_ids', 'matched_credit_ids', 'matched_debit_ids.amount', 'matched_credit_ids.amount', 'account_id.currency_id', 'move_id.state') + @api.depends('debit', 'credit', 'amount_currency', 'currency_id', 'matched_debit_ids', 'matched_credit_ids', 'matched_debit_ids.amount', 'matched_credit_ids.amount', 'move_id.state') def _amount_residual(self): """ Computes the residual amount of a move line from a reconcilable account in the company currency and the line's currency. This amount will be 0 for fully reconciled lines or lines from a non-reconcilable account, the original line amount diff --git a/addons/account/models/company.py b/addons/account/models/company.py index d73dbf82c64..8ae4230a7b2 100644 --- a/addons/account/models/company.py +++ b/addons/account/models/company.py @@ -4,7 +4,7 @@ from datetime import timedelta, datetime import calendar from odoo import fields, models, api, _ -from odoo.exceptions import ValidationError +from odoo.exceptions import ValidationError, UserError from odoo.exceptions import UserError from odoo.tools.float_utils import float_round, float_is_zero @@ -130,6 +130,12 @@ Best Regards,''')) if values.get('cash_account_code_prefix'): new_cash_code = values.get('cash_account_code_prefix') or company.cash_account_code_prefix company.reflect_code_prefix_change(company.cash_account_code_prefix, new_cash_code) + + #forbid the change of currency_id if there are already some accounting entries existing + if 'currency_id' in values and values['currency_id'] != company.currency_id.id: + if self.env['account.move.line'].search([('company_id', '=', company.id)]): + raise UserError(_('You cannot change the currency of the company since some journal items already exist')) + return super(ResCompany, self).write(values) @api.model diff --git a/addons/account/tests/test_payment.py b/addons/account/tests/test_payment.py index b527efa6be3..271a588dbe9 100644 --- a/addons/account/tests/test_payment.py +++ b/addons/account/tests/test_payment.py @@ -20,7 +20,9 @@ class TestPayment(AccountingTestCase): self.currency_chf_id = self.env.ref("base.CHF").id self.currency_usd_id = self.env.ref("base.USD").id self.currency_eur_id = self.env.ref("base.EUR").id - self.env.ref('base.main_company').write({'currency_id': self.currency_eur_id}) + + company = self.env.ref('base.main_company') + self.cr.execute("UPDATE res_company SET currency_id = %s WHERE id = %s", [self.currency_eur_id, company.id]) self.product = self.env.ref("product.product_product_4") self.payment_method_manual_in = self.env.ref("account.account_payment_method_manual_in") self.payment_method_manual_out = self.env.ref("account.account_payment_method_manual_out") diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index aa4fc950279..1180df172c9 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -27,7 +27,8 @@ class TestReconciliation(AccountingTestCase): self.currency_swiss_id = self.env.ref("base.CHF").id self.currency_usd_id = self.env.ref("base.USD").id self.currency_euro_id = self.env.ref("base.EUR").id - self.env.ref('base.main_company').write({'currency_id': self.currency_euro_id}) + company = self.env.ref('base.main_company') + self.cr.execute("UPDATE res_company SET currency_id = %s WHERE id = %s", [self.currency_euro_id, company.id]) self.account_rcv = partner_agrolait.property_account_receivable_id or self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_receivable').id)], limit=1) self.account_rsa = partner_agrolait.property_account_payable_id or self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_payable').id)], limit=1) self.product = self.env.ref("product.product_product_4") diff --git a/addons/barcodes/static/src/js/barcode_form_view.js b/addons/barcodes/static/src/js/barcode_form_view.js index fa5b27e2a9c..1730b42290e 100644 --- a/addons/barcodes/static/src/js/barcode_form_view.js +++ b/addons/barcodes/static/src/js/barcode_form_view.js @@ -155,7 +155,7 @@ FormController.include({ id: candidate.id, data: candidateChanges, }; - return this.model.notifyChanges(this.handle, changes); + return this.model.notifyChanges(this.handle, changes, {notifyChange: activeBarcode.notifyChange}); }, /** * @private @@ -211,6 +211,8 @@ FormController.include({ * @param {OdooEvent} event * @param {string} event.data.name: the current field name * @param {string} [event.data.fieldName] optional for x2many sub field + * @param {boolean} [event.data.notifyChange] optional for x2many sub field + * do not trigger on change server side if a candidate has been found * @param {string} [event.data.quantity] optional field to increase quantity * @param {Object} [event.data.commands] optional added methods * can use comand with specific barcode (with ReservedBarcodePrefixes) @@ -225,7 +227,9 @@ FormController.include({ handle: this.handle, target: event.target, widget: event.target.attrs && event.target.attrs.widget, + setQuantityWithKeypress: !! event.data.setQuantityWithKeypress, fieldName: event.data.fieldName, + notifyChange: (event.data.notifyChange !== undefined) ? event.data.notifyChange : true, quantity: event.data.quantity, commands: event.data.commands || {}, candidate: this.activeBarcode[name] && this.activeBarcode[name].handle === this.handle ? @@ -319,7 +323,7 @@ FormController.include({ // only catch the event if we're not focused in // another field and it's a number - if (!$(event.target).is('body') || !/[0-9]/.test(character)) { + if (!$(event.target).is('body, .modal') || !/[0-9]/.test(character)) { return; } diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 1679198caf3..fb233a50da6 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -971,6 +971,8 @@ class Lead(models.Model): 'nb_opportunities': 0, } + today = fields.Date.from_string(fields.Date.context_today(self)) + opportunities = self.search([('type', '=', 'opportunity'), ('user_id', '=', self._uid)]) for opp in opportunities: @@ -978,28 +980,28 @@ class Lead(models.Model): if opp.activity_date_deadline: if opp.date_deadline: date_deadline = fields.Date.from_string(opp.date_deadline) - if date_deadline == date.today(): + if date_deadline == today: result['closing']['today'] += 1 - if date.today() <= date_deadline <= date.today() + timedelta(days=7): + if today <= date_deadline <= today + timedelta(days=7): result['closing']['next_7_days'] += 1 - if date_deadline < date.today() and not opp.date_closed: + if date_deadline < today and not opp.date_closed: result['closing']['overdue'] += 1 # Next activities for activity in opp.activity_ids: date_deadline = fields.Date.from_string(activity.date_deadline) - if date_deadline == date.today(): + if date_deadline == today: result['activity']['today'] += 1 - if date.today() <= date_deadline <= date.today() + timedelta(days=7): + if today <= date_deadline <= today + timedelta(days=7): result['activity']['next_7_days'] += 1 - if date_deadline < date.today(): + if date_deadline < today: result['activity']['overdue'] += 1 # Won in Opportunities if opp.date_closed and opp.stage_id.probability == 100: date_closed = fields.Date.from_string(opp.date_closed) - if date.today().replace(day=1) <= date_closed <= date.today(): + if today.replace(day=1) <= date_closed <= today: if opp.planned_revenue: result['won']['this_month'] += opp.planned_revenue - elif date.today() + relativedelta(months=-1, day=1) <= date_closed < date.today().replace(day=1): + elif today + relativedelta(months=-1, day=1) <= date_closed < today.replace(day=1): if opp.planned_revenue: result['won']['last_month'] += opp.planned_revenue @@ -1024,9 +1026,9 @@ class Lead(models.Model): for activity in activites_done: if activity['date']: date_act = fields.Date.from_string(activity['date']) - if date.today().replace(day=1) <= date_act <= date.today(): + if today.replace(day=1) <= date_act <= today: result['done']['this_month'] += 1 - elif date.today() + relativedelta(months=-1, day=1) <= date_act < date.today().replace(day=1): + elif today + relativedelta(months=-1, day=1) <= date_act < today.replace(day=1): result['done']['last_month'] += 1 # Meetings @@ -1041,9 +1043,9 @@ class Lead(models.Model): for meeting in meetings: if meeting['start']: start = datetime.strptime(meeting['start'], tools.DEFAULT_SERVER_DATETIME_FORMAT).date() - if start == date.today(): + if start == today: result['meeting']['today'] += 1 - if date.today() <= start <= date.today() + timedelta(days=7): + if today <= start <= today + timedelta(days=7): result['meeting']['next_7_days'] += 1 result['done']['target'] = self.env.user.target_sales_done diff --git a/addons/delivery/models/__init__.py b/addons/delivery/models/__init__.py index 5229017a189..9e162e76592 100644 --- a/addons/delivery/models/__init__.py +++ b/addons/delivery/models/__init__.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import res_config_settings from . import delivery_carrier from . import delivery_grid from . import product_template diff --git a/addons/delivery/models/res_config_settings.py b/addons/delivery/models/res_config_settings.py new file mode 100644 index 00000000000..070f8dcdb29 --- /dev/null +++ b/addons/delivery/models/res_config_settings.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + def set_values(self): + super(ResConfigSettings, self).set_values() + rule = self.env.ref('delivery.delivery_carrier_comp_rule', False) + if rule: + rule.write({'active': not bool(self.company_share_product)}) diff --git a/addons/delivery/security/delivery_carrier_security.xml b/addons/delivery/security/delivery_carrier_security.xml index 8fad0891676..db718fbf361 100644 --- a/addons/delivery/security/delivery_carrier_security.xml +++ b/addons/delivery/security/delivery_carrier_security.xml @@ -6,6 +6,7 @@ ['|',('company_id','=',user.company_id.id),('company_id','=',False)] + diff --git a/addons/delivery/security/delivery_security.xml b/addons/delivery/security/delivery_security.xml new file mode 100644 index 00000000000..ae588bc245c --- /dev/null +++ b/addons/delivery/security/delivery_security.xml @@ -0,0 +1,12 @@ + + + + + Delivery multi-company + + + ['|',('product_id.company_id','=',user.company_id.id),('product_id.company_id','=',False)] + + + + diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 1cf1ee9b17f..3e0c3ea7ca1 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -88,7 +88,7 @@ class HolidaysRequest(models.Model): @api.onchange('employee_id') def _onchange_employee_id(self): self.manager_id = self.employee_id and self.employee_id.parent_id - self.department_id = self.employee_id and self.employee_id.department_id + self.department_id = self.employee_id.department_id @api.multi @api.depends('number_of_days_temp') diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py index ee1d5833fb0..ddfd68e0d56 100644 --- a/addons/hr_timesheet/models/hr_timesheet.py +++ b/addons/hr_timesheet/models/hr_timesheet.py @@ -14,7 +14,7 @@ class AccountAnalyticLine(models.Model): result['employee_id'] = self.env['hr.employee'].search([('user_id', '=', result['user_id'])], limit=1).id return result - task_id = fields.Many2one('project.task', 'Task') + task_id = fields.Many2one('project.task', 'Task', index=True) project_id = fields.Many2one('project.project', 'Project', domain=[('allow_timesheets', '=', True)]) employee_id = fields.Many2one('hr.employee', "Employee") diff --git a/addons/im_livechat/controllers/main.py b/addons/im_livechat/controllers/main.py index 11eabd18423..e228524893a 100644 --- a/addons/im_livechat/controllers/main.py +++ b/addons/im_livechat/controllers/main.py @@ -110,7 +110,8 @@ class LivechatController(http.Controller): @http.route('/im_livechat/history', type="json", auth="public") def history_pages(self, pid, channel_uuid, page_history=None): - channel = request.env['mail.channel'].search([('uuid', '=', channel_uuid)]) + partner_ids = (pid, request.env.user.partner_id.id) + channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid), ('channel_partner_ids', 'in', partner_ids)]) if channel: channel._send_history_message(pid, page_history) return True diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py index c2741fcef92..783fbd417ef 100644 --- a/addons/im_livechat/models/im_livechat_channel.py +++ b/addons/im_livechat/models/im_livechat_channel.py @@ -238,7 +238,7 @@ class ImLivechatChannelRule(models.Model): """ def _match(rules): for rule in rules: - if re.search(rule.regex_url, url): + if re.search(rule.regex_url or '', url): return rule return False # first, search the country specific rules (the first match is returned) diff --git a/addons/l10n_be_hr_payroll_fleet/views/res_config_settings_views.xml b/addons/l10n_be_hr_payroll_fleet/views/res_config_settings_views.xml index 4c095e2eea5..f4800282ec2 100644 --- a/addons/l10n_be_hr_payroll_fleet/views/res_config_settings_views.xml +++ b/addons/l10n_be_hr_payroll_fleet/views/res_config_settings_views.xml @@ -15,9 +15,9 @@