diff --git a/.tx/config b/.tx/config index ba9318f5a58..da3e448a067 100644 --- a/.tx/config +++ b/.tx/config @@ -362,6 +362,11 @@ file_filter = addons/im_livechat/i18n/.po source_file = addons/im_livechat/i18n/im_livechat.pot source_lang = en +[odoo-master.im_support] +file_filter = addons/im_support/i18n/.po +source_file = addons/im_support/i18n/im_support.pot +source_lang = en + [odoo-master.link_tracker] file_filter = addons/link_tracker/i18n/.po source_file = addons/link_tracker/i18n/link_tracker.pot @@ -407,6 +412,11 @@ file_filter = addons/mrp/i18n/.po source_file = addons/mrp/i18n/mrp.pot source_lang = en +[odoo-master.mrp_bom_cost] +file_filter = addons/mrp_bom_cost/i18n/.po +source_file = addons/mrp_bom_cost/i18n/mrp_bom_cost.pot +source_lang = en + [odoo-master.mrp_byproduct] file_filter = addons/mrp_byproduct/i18n/.po source_file = addons/mrp_byproduct/i18n/mrp_byproduct.pot @@ -552,11 +562,6 @@ file_filter = addons/product_expiry/i18n/.po source_file = addons/product_expiry/i18n/product_expiry.pot source_lang = en -[odoo-master.product_extended] -file_filter = addons/product_extended/i18n/.po -source_file = addons/product_extended/i18n/product_extended.pot -source_lang = en - [odoo-master.product_margin] file_filter = addons/product_margin/i18n/.po source_file = addons/product_margin/i18n/product_margin.pot @@ -722,6 +727,11 @@ file_filter = addons/transifex/i18n/.po source_file = addons/transifex/i18n/transifex.pot source_lang = en +[odoo-master.uom] +file_filter = addons/uom/i18n/.po +source_file = addons/uom/i18n/uom.pot +source_lang = en + [odoo-master.utm] file_filter = addons/utm/i18n/.po source_file = addons/utm/i18n/utm.pot diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 08e625752c8..cf0f5ae2856 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -912,7 +912,7 @@ class AccountMoveLine(models.Model): """ Create a writeoff move per journal for the account.move.lines in self. If debit/credit is not specified in vals, the writeoff amount will be computed as the sum of amount_residual of the given recordset. - :param writeoff_vals: dict containing values suitable for account_move_line.create(). The data in vals will + :param writeoff_vals: list of dicts containing values suitable for account_move_line.create(). The data in vals will be processed to create bot writeoff acount.move.line and their enclosing account.move. """ def compute_writeoff_counterpart_vals(values): diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index b529cfa3b28..5245c4b97a9 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -135,10 +135,17 @@ class AccountChartTemplate(models.Model): ''' digits = self.code_digits prefix = self.transfer_account_code_prefix or '' + # Flatten the hierarchy of chart templates. + chart_template = self + chart_templates = self + while chart_template.parent_id: + chart_templates += chart_template.parent_id + chart_template = chart_template.parent_id new_code = '' for num in range(1, 100): new_code = str(prefix.ljust(digits - 1, '0')) + str(num) - rec = self.env['account.account.template'].search([('code', '=', new_code), ('chart_template_id', '=', self.id)], limit=1) + rec = self.env['account.account.template'].search( + [('code', '=', new_code), ('chart_template_id', 'in', chart_templates.ids)], limit=1) if not rec: break else: @@ -1043,8 +1050,14 @@ class IrModelData(models.Model): # - an entry in ir_model_data: this allow to still use the method create_record_with_xmlid() and don't make any difference between # regular accounts created and that liquidity transfer account if model == 'account.chart.template' and xml_id and module: + chart_template = self.env[model].browse(record_id) + + # Create the transfer account only for leaf chart template in the hierarchy. + if chart_template.parent_id: + return record_id + new_xml_id = xml_id + '_liquidity_transfer' if not self.search([('model', '=', 'account.account.template'), ('module', '=', module), ('name', '=', new_xml_id)]): - vals = self.env[model].browse(record_id)._prepare_transfer_account_template() + vals = chart_template._prepare_transfer_account_template() self._update('account.account.template', module, vals, xml_id=new_xml_id, store=True, noupdate=noupdate, mode=mode, res_id=False) return record_id diff --git a/addons/account/models/company.py b/addons/account/models/company.py index 28705c1369d..65162b07490 100644 --- a/addons/account/models/company.py +++ b/addons/account/models/company.py @@ -301,40 +301,6 @@ Best Regards,''')) 'domain': domain, } - @api.model - def setting_opening_move_action(self): - """ Called by the 'Initial Balances' button of the setup bar.""" - company = self.env.user.company_id - - # If the opening move has already been posted, we open its form view - if company.opening_move_posted(): - form_view_id = self.env.ref('account.setup_posted_move_form').id - return { - 'type': 'ir.actions.act_window', - 'name': _('Initial Balances'), - 'view_mode': 'form', - 'res_model': 'account.move', - 'target': 'new', - 'res_id': company.account_opening_move_id.id, - 'views': [[form_view_id, 'form']], - } - - # Otherwise, we open a custom wizard to post it. - company.create_op_move_if_non_existant() - new_wizard = self.env['account.opening'].create({'company_id': company.id}) - view_id = self.env.ref('account.setup_opening_move_wizard_form').id - - return { - 'type': 'ir.actions.act_window', - 'name': _('Initial Balances'), - 'view_mode': 'form', - 'res_model': 'account.opening', - 'target': 'new', - 'res_id': new_wizard.id, - 'views': [[view_id, 'form']], - 'context': {'check_move_validity': False}, - } - @api.model def setting_hide_setup_bar(self): """ Called by the cross button of the setup bar, to close it.""" diff --git a/addons/account/models/product.py b/addons/account/models/product.py index c52355f6f4f..b72bc31d7bd 100644 --- a/addons/account/models/product.py +++ b/addons/account/models/product.py @@ -35,22 +35,6 @@ class ProductTemplate(models.Model): domain=[('deprecated', '=', False)], help="The expense is accounted for when a vendor bill is validated, except in anglo-saxon accounting with perpetual inventory valuation in which case the expense (Cost of Goods Sold account) is recognized at the customer invoice validation. If the field is empty, it uses the one defined in the product category.") - @api.multi - def write(self, vals): - #TODO: really? i don't see the reason we'd need that constraint.. - check = self.ids and 'uom_po_id' in vals - if check: - self._cr.execute("SELECT id, uom_po_id FROM product_template WHERE id IN %s", [tuple(self.ids)]) - uoms = dict(self._cr.fetchall()) - res = super(ProductTemplate, self).write(vals) - if check: - self._cr.execute("SELECT id, uom_po_id FROM product_template WHERE id IN %s", [tuple(self.ids)]) - if dict(self._cr.fetchall()) != uoms: - products = self.env['product.product'].search([('product_tmpl_id', 'in', self.ids)]) - if self.env['account.move.line'].search_count([('product_id', 'in', products.ids)]): - raise UserError(_('You can not change the unit of measure of a product that has been already used in an account journal item. If you need to change the unit of measure, you should archive this product and create a new one.')) - return res - @api.multi def _get_product_accounts(self): return { diff --git a/addons/account/models/reconciliation_widget.py b/addons/account/models/reconciliation_widget.py index b0ce440093f..ca9513e4f39 100644 --- a/addons/account/models/reconciliation_widget.py +++ b/addons/account/models/reconciliation_widget.py @@ -743,7 +743,7 @@ class AccountReconciliation(models.AbstractModel): if writeoff_currency != company_currency: mv_line_dict['debit'] = writeoff_currency._convert(mv_line_dict['debit'], company_currency, company, date) mv_line_dict['credit'] = writeoff_currency._convert(mv_line_dict['credit'], company_currency, company, date) - writeoff_lines += account_move_line._create_writeoff(mv_line_dict) + writeoff_lines += account_move_line._create_writeoff([mv_line_dict]) (account_move_line + writeoff_lines).reconcile() else: diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py index 01b2a9a3bd8..7b9c5c33f93 100644 --- a/addons/account/report/account_aged_partner_balance.py +++ b/addons/account/report/account_aged_partner_balance.py @@ -205,7 +205,7 @@ class ReportAgedPartnerBalance(models.AbstractModel): values['name'] = _('Unknown Partner') values['trust'] = False - if at_least_one_amount or self._context.get('include_nullified_amount'): + if at_least_one_amount or (self._context.get('include_nullified_amount') and lines[partner['partner_id']]): res.append(values) return res, total, lines diff --git a/addons/account/report/account_general_ledger.py b/addons/account/report/account_general_ledger.py index 922ec24ff0a..be46e7b361b 100644 --- a/addons/account/report/account_general_ledger.py +++ b/addons/account/report/account_general_ledger.py @@ -38,7 +38,7 @@ class ReportGeneralLedger(models.AbstractModel): init_wheres.append(init_where_clause.strip()) init_filters = " AND ".join(init_wheres) filters = init_filters.replace('account_move_line__move_id', 'm').replace('account_move_line', 'l') - sql = ("""SELECT 0 AS lid, l.account_id AS account_id, '' AS ldate, '' AS lcode, NULL AS amount_currency, '' AS lref, 'Initial Balance' AS lname, COALESCE(SUM(l.debit),0.0) AS debit, COALESCE(SUM(l.credit),0.0) AS credit, COALESCE(SUM(l.debit),0) - COALESCE(SUM(l.credit), 0) as balance, '' AS lpartner_id,\ + sql = ("""SELECT 0 AS lid, l.account_id AS account_id, '' AS ldate, '' AS lcode, 0.0 AS amount_currency, '' AS lref, 'Initial Balance' AS lname, COALESCE(SUM(l.debit),0.0) AS debit, COALESCE(SUM(l.credit),0.0) AS credit, COALESCE(SUM(l.debit),0) - COALESCE(SUM(l.credit), 0) as balance, '' AS lpartner_id,\ '' AS move_name, '' AS mmove_id, '' AS currency_code,\ NULL AS currency_id,\ '' AS invoice_id, '' AS invoice_type, '' AS invoice_number,\ diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index 814fda8c7d7..cf104b14073 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -760,6 +760,63 @@ class TestReconciliation(AccountingTestCase): self.assertEqual(reversed_bank_line.full_reconcile_id.id, bank_line.full_reconcile_id.id) self.assertEqual(reversed_customer_line.full_reconcile_id.id, customer_line.full_reconcile_id.id) + def create_invoice_partner(self, type='out_invoice', invoice_amount=50, currency_id=None, partner_id=False): + #we create an invoice in given currency + invoice = self.account_invoice_model.create({'partner_id': partner_id, + 'reference_type': 'none', + 'currency_id': currency_id, + 'name': type == 'out_invoice' and 'invoice to client' or 'invoice to vendor', + 'account_id': self.account_rcv.id, + 'type': type, + 'date_invoice': time.strftime('%Y') + '-07-01', + }) + self.account_invoice_line_model.create({'product_id': self.product.id, + 'quantity': 1, + 'price_unit': invoice_amount, + 'invoice_id': invoice.id, + 'name': 'product that cost ' + str(invoice_amount), + 'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id, + }) + + #validate invoice + invoice.action_invoice_open() + return invoice + + def test_aged_report(self): + AgedReport = self.env['report.account.report_agedpartnerbalance'].with_context(include_nullified_amount=True) + account_type = ['receivable'] + report_date_to = time.strftime('%Y') + '-07-16' + partner = self.env['res.partner'].create({'name': 'AgedPartner'}) + currency = self.env.user.company_id.currency_id + + invoice = self.create_invoice_partner(currency_id=currency.id, partner_id=partner.id) + journal = self.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'THE', 'currency_id': currency.id}) + + statement = self.make_payment(invoice, journal, 50) + + # Case 1: The invoice and payment are reconciled: Nothing should appear + report_lines, total, amls = AgedReport._get_partner_move_lines(account_type, report_date_to, 'posted', 30) + + partner_lines = [line for line in report_lines if line['partner_id'] == partner.id] + self.assertEqual(partner_lines, [], 'The aged receivable shouldn\'t have lines at this point') + self.assertFalse(partner.id in amls, 'The aged receivable should not have amls either') + + # Case 2: The invoice and payment are not reconciled: we should have one line on the report + # and 2 amls + invoice.move_id.line_ids.with_context(invoice_id=invoice.id).remove_move_reconcile() + report_lines, total, amls = AgedReport._get_partner_move_lines(account_type, report_date_to, 'posted', 30) + + partner_lines = [line for line in report_lines if line['partner_id'] == partner.id] + self.assertEqual(partner_lines, [{'trust': 'normal', '1': 0.0, '0': 0.0, 'direction': 0.0, 'partner_id': partner.id, '3': 0.0, 'total': 0.0, 'name': 'AgedPartner', '4': 0.0, '2': 0.0}], + 'We should have a line in the report for the partner') + self.assertEqual(len(amls[partner.id]), 2, 'We should have 2 account move lines for the partner') + + positive_line = [line for line in amls[partner.id] if line['line'].balance > 0] + negative_line = [line for line in amls[partner.id] if line['line'].balance < 0] + + self.assertEqual(positive_line[0]['amount'], 50.0, 'The amount of the amls should be 50') + self.assertEqual(negative_line[0]['amount'], -50.0, 'The amount of the amls should be -50') + def test_partial_reconcile_currencies_02(self): #### # Day 1: Invoice Cust/001 to customer (expressed in USD) diff --git a/addons/account/wizard/setup_wizards_view.xml b/addons/account/wizard/setup_wizards_view.xml index e0864a868d3..4f4e1f73d88 100644 --- a/addons/account/wizard/setup_wizards_view.xml +++ b/addons/account/wizard/setup_wizards_view.xml @@ -75,7 +75,6 @@
-
diff --git a/addons/account_check_printing/models/account_payment.py b/addons/account_check_printing/models/account_payment.py index 15421a6e7c2..51870ebeeb3 100644 --- a/addons/account_check_printing/models/account_payment.py +++ b/addons/account_check_printing/models/account_payment.py @@ -162,12 +162,12 @@ class AccountPayment(models.Model): # Prepare the stub lines if not credits: - stub_lines = [self.make_stub_line(inv) for inv in invoices] + stub_lines = [self._check_make_stub_line(inv) for inv in invoices] else: stub_lines = [{'header': True, 'name': "Bills"}] - stub_lines += [self.make_stub_line(inv) for inv in debits] + stub_lines += [self._check_make_stub_line(inv) for inv in debits] stub_lines += [{'header': True, 'name': "Refunds"}] - stub_lines += [self.make_stub_line(inv) for inv in credits] + stub_lines += [self._check_make_stub_line(inv) for inv in credits] # Crop the stub lines or split them on multiple pages if not multi_stub: diff --git a/addons/account_payment/controllers/payment.py b/addons/account_payment/controllers/payment.py index 7f08570de8e..5c3f6f0ea31 100644 --- a/addons/account_payment/controllers/payment.py +++ b/addons/account_payment/controllers/payment.py @@ -17,7 +17,6 @@ class PaymentPortal(http.Controller): :return html: form containing all values related to the acquirer to redirect customers to the acquirer website """ success_url = kwargs.get('success_url', '/my') - callback_method = kwargs.get('callback_method', '') invoice_sudo = request.env['account.invoice'].sudo().browse(invoice_id) if not invoice_sudo: @@ -28,11 +27,10 @@ class PaymentPortal(http.Controller): except: return False + if request.env.user == request.env.ref('base.public_user'): + save_token = False # we avoid to create a token for the public user vals = { 'acquirer_id': acquirer_id, - 'callback_model_id': request.env['ir.model'].sudo().search([('model', '=', invoice_sudo._name)], limit=1).id, - 'callback_res_id': invoice_sudo.id, - 'callback_method': callback_method, } if save_token: @@ -55,7 +53,6 @@ class PaymentPortal(http.Controller): """ Use a token to perform a s2s transaction """ error_url = kwargs.get('error_url', '/my') success_url = kwargs.get('success_url', '/my') - callback_method = kwargs.get('callback_method', '') access_token = kwargs.get('access_token') params = {} if access_token: @@ -67,18 +64,17 @@ class PaymentPortal(http.Controller): return request.redirect(_build_url_w_params(error_url, params)) try: - pm_id = int(pm_id) + token = request.env['payment.token'].sudo().browse(int(pm_id)) except (ValueError, TypeError): + token = False + token_owner = invoice_sudo.partner_id if request.env.user == request.env.ref('base.public_user') else request.env.user.partner_id + if not token or token.partner_id != token_owner: params['error'] = 'pay_invoice_invalid_token' return request.redirect(_build_url_w_params(error_url, params)) vals = { - 'payment_token_id': pm_id, + 'payment_token_id': token.id, 'type': 'server2server', - 'callback_model_id': request.env['ir.model'].sudo().search([('model', '=', invoice_sudo._name)], - limit=1).id, - 'callback_res_id': invoice_sudo.id, - 'callback_method': callback_method, } invoice_sudo._create_payment_transaction(vals) diff --git a/addons/account_payment/controllers/portal.py b/addons/account_payment/controllers/portal.py index a2247288fdb..28bca2a12a8 100644 --- a/addons/account_payment/controllers/portal.py +++ b/addons/account_payment/controllers/portal.py @@ -9,5 +9,18 @@ class PortalAccount(PortalAccount): def _invoice_get_page_view_values(self, invoice, access_token, **kwargs): values = super(PortalAccount, self)._invoice_get_page_view_values(invoice, access_token, **kwargs) - values.update(request.env['payment.acquirer']._get_available_payment_input(invoice.partner_id, invoice.company_id)) + payment_inputs = request.env['payment.acquirer']._get_available_payment_input(company=invoice.company_id) + # if not connected (using public user), the method _get_available_payment_input will return public user tokens + is_public_user = request.env.ref('base.public_user') == request.env.user + if is_public_user: + # we should not display payment tokens owned by the public user + payment_inputs.pop('pms', None) + token_count = request.env['payment.token'].sudo().search_count([('acquirer_id.company_id', '=', invoice.company_id.id), + ('partner_id', '=', invoice.partner_id.id), + ]) + values['existing_token'] = token_count > 0 + values.update(payment_inputs) + # if the current user is connected we set partner_id to his partner otherwise we set it as the invoice partner + # we do this to force the creation of payment tokens to the correct partner and avoid token linked to the public user + values['partner_id'] = invoice.partner_id if is_public_user else request.env.user.partner_id, return values diff --git a/addons/account_payment/views/account_portal_templates.xml b/addons/account_payment/views/account_portal_templates.xml index f369ceade36..6f00f6e750b 100644 --- a/addons/account_payment/views/account_portal_templates.xml +++ b/addons/account_payment/views/account_portal_templates.xml @@ -97,6 +97,11 @@ +
+
+ You have credits card registered, you can log-in to be able to use them. +
+
diff --git a/addons/auth_signup/models/res_users.py b/addons/auth_signup/models/res_users.py index 2dcd9cb373a..598d390dbd5 100644 --- a/addons/auth_signup/models/res_users.py +++ b/addons/auth_signup/models/res_users.py @@ -196,5 +196,5 @@ class ResUsers(models.Model): sup = super(ResUsers, self) if not default or not default.get('email'): # avoid sending email to the user we are duplicating - sup = super(ResUsers, self.with_context(reset_password=False)) + sup = super(ResUsers, self.with_context(no_reset_password=True)) return sup.copy(default=default) diff --git a/addons/barcodes/static/src/js/barcode_events.js b/addons/barcodes/static/src/js/barcode_events.js index 9f2863dfdfd..2d602a36b97 100644 --- a/addons/barcodes/static/src/js/barcode_events.js +++ b/addons/barcodes/static/src/js/barcode_events.js @@ -65,7 +65,6 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, { 'top': '50%', 'transform': 'translateY(-50%)', 'z-index': '-1', - 'visibility': 'hidden', }, }); // Avoid to show autocomplete for a non appearing input diff --git a/addons/barcodes/static/src/js/barcode_parser.js b/addons/barcodes/static/src/js/barcode_parser.js index d834f3cbd27..cf357a438b2 100644 --- a/addons/barcodes/static/src/js/barcode_parser.js +++ b/addons/barcodes/static/src/js/barcode_parser.js @@ -18,6 +18,9 @@ var BarcodeParser = Class.extend({ // only when those data have been loaded load: function(){ var self = this; + if (!this.nomenclature_id) { + return; + } var id = this.nomenclature_id[0]; rpc.query({ model: 'barcode.nomenclature', diff --git a/addons/base_address_extended/__manifest__.py b/addons/base_address_extended/__manifest__.py index c9c78846b26..adb27e8bb90 100644 --- a/addons/base_address_extended/__manifest__.py +++ b/addons/base_address_extended/__manifest__.py @@ -16,7 +16,8 @@ For example, in legal reports, some countries need to split the street into seve with the street name, the house number, and room number. """, 'data': [ - 'views/base_address_extended.xml' + 'views/base_address_extended.xml', + 'data/base_address_extended_data.xml', ], 'depends': ['base'], } diff --git a/addons/base_address_extended/data/base_address_extended_data.xml b/addons/base_address_extended/data/base_address_extended_data.xml new file mode 100644 index 00000000000..1e76cb4c5df --- /dev/null +++ b/addons/base_address_extended/data/base_address_extended_data.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/addons/bus/static/src/js/bus.js b/addons/bus/static/src/js/bus.js index e93d2112d2f..d0da7676f9f 100644 --- a/addons/bus/static/src/js/bus.js +++ b/addons/bus/static/src/js/bus.js @@ -85,7 +85,7 @@ bus.Bus = Widget.extend({ } var data = {channels: self.channels, last: self.last, options: options}; // The backend has a maximum cycle time of 50 seconds so give +10 seconds - this._pollRpc = session.rpc(this.pollRoute, data, {shadow : true, timeout: 60000}); + this._pollRpc = this.session.rpc(this.pollRoute, data, {shadow : true, timeout: 60000}); this._pollRpc.then(function (result) { self._pollRpc = false; self.on_notification(result); diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 6ae096d7eb1..06272c99925 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -4,7 +4,7 @@ import base64 import babel.dates import collections -from datetime import datetime, timedelta +from datetime import datetime, timedelta, MAXYEAR from dateutil import parser from dateutil import rrule from dateutil.relativedelta import relativedelta @@ -633,7 +633,7 @@ class Meeting(models.Model): recurring_date = todate(meeting.recurrent_id_date) rset1.exdate(recurring_date) invalidate = True - return [d.astimezone(pytz.UTC) if d.tzinfo else d for d in rset1] + return [d.astimezone(pytz.UTC) if d.tzinfo else d for d in rset1 if d.year < MAXYEAR] @api.multi def _get_recurrency_end_date(self): @@ -903,8 +903,8 @@ class Meeting(models.Model): startdate = startdate.astimezone(pytz.utc) # Convert to UTC meeting.start = fields.Datetime.to_string(startdate) else: - meeting.start = meeting.start_datetime - meeting.stop = meeting.stop_datetime + meeting.write({'start': meeting.start_datetime, + 'stop': meeting.stop_datetime}) @api.depends('byday', 'recurrency', 'final_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list') def _compute_rrule(self): diff --git a/addons/calendar/static/src/js/base_calendar.js b/addons/calendar/static/src/js/base_calendar.js index 3752b7aa94a..e09222b6025 100644 --- a/addons/calendar/static/src/js/base_calendar.js +++ b/addons/calendar/static/src/js/base_calendar.js @@ -40,8 +40,10 @@ var CalendarNotification = Notification.extend({ }, 'click .link2showed': function() { - this.destroy(true); - this._rpc({route: '/calendar/notify_ack'}); + var self = this; + this._rpc({route: '/calendar/notify_ack'}).always(function() { + self.destroy(); + }); }, }); }, diff --git a/addons/crm/__init__.py b/addons/crm/__init__.py index 4e9b019bd7a..3398a4b470d 100644 --- a/addons/crm/__init__.py +++ b/addons/crm/__init__.py @@ -5,3 +5,11 @@ from . import controllers from . import models from . import report from . import wizard + +from odoo import api, SUPERUSER_ID + + +def uninstall_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + teams = env['crm.team'].search([('dashboard_graph_model', '=', 'crm.opportunity.report')]) + teams.update({'dashboard_graph_model': None}) diff --git a/addons/crm/__manifest__.py b/addons/crm/__manifest__.py index e224a6d8101..b09e6c9c70d 100644 --- a/addons/crm/__manifest__.py +++ b/addons/crm/__manifest__.py @@ -54,4 +54,5 @@ 'installable': True, 'application': True, 'auto_install': False, + 'uninstall_hook': 'uninstall_hook', } diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 3ec21c7eb1e..5945470f51c 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -450,7 +450,8 @@ class Lead(models.Model): 'res_id': self.id, 'views': [(form_view.id, 'form'),], 'type': 'ir.actions.act_window', - 'target': 'inline' + 'target': 'inline', + 'context': {'default_type': 'opportunity'} } # ---------------------------------------- diff --git a/addons/crm/wizard/crm_lead_to_opportunity_views.xml b/addons/crm/wizard/crm_lead_to_opportunity_views.xml index 201f2957636..5b29d25b934 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity_views.xml +++ b/addons/crm/wizard/crm_lead_to_opportunity_views.xml @@ -56,8 +56,7 @@ - - +