diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 6cee000e51c..d8828794475 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -570,7 +570,7 @@ class AccountInvoice(models.Model): # lots of duplicate calls to action_invoice_paid, so we remove those already paid to_pay_invoices = self.filtered(lambda inv: inv.state != 'paid') if to_pay_invoices.filtered(lambda inv: inv.state != 'open'): - raise UserError(_('Invoice must be validated in order to set it to register payemnt.')) + raise UserError(_('Invoice must be validated in order to set it to register payment.')) if to_pay_invoices.filtered(lambda inv: not inv.reconciled): raise UserError(_('You cannot pay an invoice which is partially paid. You need to reconcile payment entries first.')) return to_pay_invoices.write({'state': 'paid'}) @@ -578,13 +578,13 @@ class AccountInvoice(models.Model): @api.multi def action_invoice_re_open(self): if self.filtered(lambda inv: inv.state != 'paid'): - raise UserError(_('Invoice must be paid in order to set it to register payemnt.')) + raise UserError(_('Invoice must be paid in order to set it to register payment.')) return self.write({'state': 'open'}) @api.multi def action_invoice_cancel(self): if self.filtered(lambda inv: inv.state not in ['proforma2', 'draft', 'open']): - raise UserError(_("Invoice must be in draft,Pro-forma or open state in order to be cancelled.")) + raise UserError(_("Invoice must be in draft, Pro-forma or open state in order to be cancelled.")) return self.action_cancel() @api.multi @@ -1151,7 +1151,8 @@ class AccountInvoiceLine(models.Model): @api.one @api.depends('price_unit', 'discount', 'invoice_line_tax_ids', 'quantity', - 'product_id', 'invoice_id.partner_id', 'invoice_id.currency_id', 'invoice_id.company_id') + 'product_id', 'invoice_id.partner_id', 'invoice_id.currency_id', 'invoice_id.company_id', + 'invoice_id.date_invoice') def _compute_price(self): currency = self.invoice_id and self.invoice_id.currency_id or None price = self.price_unit * (1 - (self.discount or 0.0) / 100.0) @@ -1160,7 +1161,7 @@ class AccountInvoiceLine(models.Model): taxes = self.invoice_line_tax_ids.compute_all(price, currency, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id) self.price_subtotal = price_subtotal_signed = taxes['total_excluded'] if taxes else self.quantity * price if self.invoice_id.currency_id and self.invoice_id.company_id and self.invoice_id.currency_id != self.invoice_id.company_id.currency_id: - price_subtotal_signed = self.invoice_id.currency_id.compute(price_subtotal_signed, self.invoice_id.company_id.currency_id) + price_subtotal_signed = self.invoice_id.currency_id.with_context(date=self.invoice_id.date_invoice).compute(price_subtotal_signed, self.invoice_id.company_id.currency_id) sign = self.invoice_id.type in ['in_refund', 'out_refund'] and -1 or 1 self.price_subtotal_signed = price_subtotal_signed * sign diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 683dff63037..1af8d118375 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -394,7 +394,7 @@ class AccountMoveLine(models.Model): statement_id = fields.Many2one('account.bank.statement', related='statement_line_id.statement_id', string='Statement', store=True, help="The bank statement used for bank reconciliation", index=True, copy=False) reconciled = fields.Boolean(compute='_amount_residual', store=True) - full_reconcile_id = fields.Many2one('account.full.reconcile', string="Matching Number") + full_reconcile_id = fields.Many2one('account.full.reconcile', string="Matching Number", copy=False) matched_debit_ids = fields.One2many('account.partial.reconcile', 'credit_move_id', String='Matched Debits', help='Debit journal items that are matched with this journal item.') matched_credit_ids = fields.One2many('account.partial.reconcile', 'debit_move_id', String='Matched Credits', @@ -1020,7 +1020,7 @@ class AccountMoveLine(models.Model): rec_move_ids = self.env['account.partial.reconcile'] for account_move_line in self: for invoice in account_move_line.payment_id.invoice_ids: - if account_move_line in invoice.payment_move_line_ids: + if invoice.id == self.env.context.get('invoice_id') and account_move_line in invoice.payment_move_line_ids: account_move_line.payment_id.write({'invoice_ids': [(3, invoice.id, None)]}) rec_move_ids += account_move_line.matched_debit_ids rec_move_ids += account_move_line.matched_credit_ids @@ -1388,7 +1388,7 @@ class AccountPartialReconcile(models.Model): company_currency_id = fields.Many2one('res.currency', related='company_id.currency_id', readonly=True, help='Utility field to express amount currency') company_id = fields.Many2one('res.company', related='debit_move_id.company_id', store=True, string='Currency') - full_reconcile_id = fields.Many2one('account.full.reconcile', string="Full Reconcile") + full_reconcile_id = fields.Many2one('account.full.reconcile', string="Full Reconcile", copy=False) def create_exchange_rate_entry(self, aml_to_fix, amount_diff, diff_in_currency, currency, move_date): """ Automatically create a journal entry to book the exchange rate difference. diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py index 36164be72f7..dbdd7c16335 100644 --- a/addons/account/models/account_payment.py +++ b/addons/account/models/account_payment.py @@ -400,9 +400,12 @@ class account_payment(models.Model): # the writeoff debit and credit must be computed from the invoice residual in company currency # minus the payment amount in company currency, and not from the payment difference in the payment currency # to avoid loss of precision during the currency rate computations. See revision 20935462a0cabeb45480ce70114ff2f4e91eaf79 for a detailed example. - total_residual_company_signed = sum(invoice.residual_company_signed for invoice in self.invoice_ids) + total_residual_company_signed = self._compute_total_invoices_amount() total_payment_company_signed = self.currency_id.with_context(date=self.payment_date).compute(self.amount, self.company_id.currency_id) - amount_wo = total_residual_company_signed - total_payment_company_signed + if self.invoice_ids[0].type in ['in_invoice', 'out_refund']: + amount_wo = total_payment_company_signed - total_residual_company_signed + else: + amount_wo = total_residual_company_signed - total_payment_company_signed debit_wo = amount_wo > 0 and amount_wo or 0.0 credit_wo = amount_wo < 0 and -amount_wo or 0.0 writeoff_line['name'] = _('Counterpart') diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index 37bcefb2675..65f33c4d748 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -226,7 +226,7 @@ class AccountChartTemplate(models.Model): account = getattr(self, record[0]) value = account and 'account.account,' + str(acc_template_ref[account.id]) or False if value: - field = self.env['ir.model.fields'].sudo().search([('name', '=', record[0]), ('model', '=', record[1]), ('relation', '=', record[2])]) + field = self.env['ir.model.fields'].search([('name', '=', record[0]), ('model', '=', record[1]), ('relation', '=', record[2])], limit=1) vals = { 'name': record[0], 'company_id': company.id, @@ -394,22 +394,11 @@ class AccountChartTemplate(models.Model): acc_template_ref[account_template.id] = new_account return acc_template_ref - @api.multi - def generate_account_reconcile_model(self, tax_template_ref, acc_template_ref, company): - """ This method for generating accounts from templates. - - :param tax_template_ref: Taxes templates reference for write taxes_id in account_account. - :param acc_template_ref: dictionary with the mappping between the account templates and the real accounts. - :param company_id: company_id selected from wizard.multi.charts.accounts. - :returns: return new_account_reconcile_model for reference purpose. - :rtype: dict + def _prepare_reconcile_model_vals(self, company, account_reconcile_model, acc_template_ref, tax_template_ref): + """ This method generates a dictionnary of all the values for the account.reconcile.model that will be created. """ self.ensure_one() - account_reconcile_models = self.env['account.reconcile.model.template'].search([ - ('account_id.chart_template_id', '=', self.id) - ]) - for account_reconcile_model in account_reconcile_models: - vals = { + return { 'name': account_reconcile_model.name, 'sequence': account_reconcile_model.sequence, 'has_second_line': account_reconcile_model.has_second_line, @@ -425,6 +414,23 @@ class AccountChartTemplate(models.Model): 'second_amount': account_reconcile_model.second_amount, 'second_tax_id': account_reconcile_model.second_tax_id and tax_template_ref[account_reconcile_model.second_tax_id.id] or False, } + + @api.multi + def generate_account_reconcile_model(self, tax_template_ref, acc_template_ref, company): + """ This method for generating accounts from templates. + + :param tax_template_ref: Taxes templates reference for write taxes_id in account_account. + :param acc_template_ref: dictionary with the mappping between the account templates and the real accounts. + :param company_id: company_id selected from wizard.multi.charts.accounts. + :returns: return new_account_reconcile_model for reference purpose. + :rtype: dict + """ + self.ensure_one() + account_reconcile_models = self.env['account.reconcile.model.template'].search([ + ('account_id.chart_template_id', '=', self.id) + ]) + for account_reconcile_model in account_reconcile_models: + vals = self._prepare_reconcile_model_vals(company, account_reconcile_model, acc_template_ref, tax_template_ref) self.create_record_with_xmlid(company, account_reconcile_model, 'account.reconcile.model', vals) return True @@ -511,9 +517,14 @@ class AccountTaxTemplate(models.Model): res.append((record.id, name)) return res - def _get_tax_vals(self, company): + def _get_tax_vals(self, company, tax_template_to_tax): """ This method generates a dictionnary of all the values for the tax that will be created. """ + # Compute children tax ids + children_ids = [] + for child_tax in self.children_tax_ids: + if tax_template_to_tax.get(child_tax.id): + children_ids.append(tax_template_to_tax[child_tax.id]) self.ensure_one() val = { 'name': self.name, @@ -528,6 +539,7 @@ class AccountTaxTemplate(models.Model): 'include_base_amount': self.include_base_amount, 'analytic': self.analytic, 'tag_ids': [(6, 0, [t.id for t in self.tag_ids])], + 'children_tax_ids': [(6, 0, children_ids)], 'tax_adjustment': self.tax_adjustment, 'use_cash_basis': self.use_cash_basis, 'cash_basis_account': self.cash_basis_account, @@ -549,13 +561,7 @@ class AccountTaxTemplate(models.Model): todo_dict = {} tax_template_to_tax = {} for tax in self: - # Compute children tax ids - children_ids = [] - for child_tax in tax.children_tax_ids: - if tax_template_to_tax.get(child_tax.id): - children_ids.append(tax_template_to_tax[child_tax.id]) - vals_tax = tax._get_tax_vals(company) - vals_tax['children_tax_ids'] = children_ids and [(6, 0, children_ids)] or [] + vals_tax = tax._get_tax_vals(company, tax_template_to_tax) new_tax = self.env['account.chart.template'].create_record_with_xmlid(company, tax, 'account.tax', vals_tax) tax_template_to_tax[tax.id] = new_tax # Since the accounts have not been created yet, we have to wait before filling these fields diff --git a/addons/account/security/account_security.xml b/addons/account/security/account_security.xml index fdfcb1caaa5..846a86724b2 100644 --- a/addons/account/security/account_security.xml +++ b/addons/account/security/account_security.xml @@ -5,10 +5,14 @@ Billing - + + + + + Accountant diff --git a/addons/account/static/src/js/account_payment_widget.js b/addons/account/static/src/js/account_payment_widget.js index 932de22eef5..a7f2b64c413 100644 --- a/addons/account/static/src/js/account_payment_widget.js +++ b/addons/account/static/src/js/account_payment_widget.js @@ -59,7 +59,7 @@ var ShowPaymentLineWidget = form_common.AbstractField.extend({ var payment_id = parseInt($(this).attr('payment-id')) if (payment_id !== undefined && payment_id !== NaN){ new Model("account.move.line") - .call("remove_move_reconcile", [payment_id]) + .call("remove_move_reconcile", [payment_id, {'invoice_id': self.view.datarecord.id}]) .then(function (result) { self.view.reload(); }); diff --git a/addons/account/views/account_invoice_view.xml b/addons/account/views/account_invoice_view.xml index bcd1434e454..7154cb65c66 100644 --- a/addons/account/views/account_invoice_view.xml +++ b/addons/account/views/account_invoice_view.xml @@ -46,7 +46,7 @@ - + @@ -68,7 +68,7 @@ - + @@ -272,7 +272,7 @@ - + @@ -411,7 +411,7 @@ - + diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml index 25bb8089b78..74011168e11 100644 --- a/addons/account/views/report_invoice.xml +++ b/addons/account/views/report_invoice.xml @@ -61,7 +61,7 @@ Source Document Quantity Unit Price - Disc.(%) + Disc.(%) Taxes Subtotal @@ -77,7 +77,7 @@ - + diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py index c2b57cd7d2c..6f1251ccaca 100644 --- a/addons/account_asset/models/account_asset.py +++ b/addons/account_asset/models/account_asset.py @@ -42,7 +42,10 @@ class AccountAssetCategory(models.Model): @api.onchange('account_asset_id') def onchange_account_asset(self): - self.account_depreciation_id = self.account_asset_id + if self.type == "purchase": + self.account_depreciation_id = self.account_asset_id + elif self.type == "sale": + self.account_depreciation_expense_id = self.account_asset_id @api.onchange('type') def onchange_type(self): diff --git a/addons/account_asset/models/account_invoice.py b/addons/account_asset/models/account_invoice.py index 3e45b722976..d6fb00358c9 100644 --- a/addons/account_asset/models/account_invoice.py +++ b/addons/account_asset/models/account_invoice.py @@ -12,14 +12,16 @@ import odoo.addons.decimal_precision as dp class AccountInvoice(models.Model): _inherit = 'account.invoice' + @api.multi + def action_cancel(self): + res = super(AccountInvoice, self).action_cancel() + self.env['account.asset.asset'].sudo().search([('invoice_id', 'in', self.ids)]).write({'active': False}) + return res + @api.multi def action_move_create(self): result = super(AccountInvoice, self).action_move_create() for inv in self: - if inv.number: - asset_ids = self.env['account.asset.asset'].sudo().search([('invoice_id', '=', inv.id), ('company_id', '=', inv.company_id.id)]) - if asset_ids: - asset_ids.write({'active': False}) context = dict(self.env.context) # Within the context of an invoice, # this default value is for the type of the invoice, not the type of the asset. @@ -83,7 +85,7 @@ class AccountInvoiceLine(models.Model): if self.invoice_id.type == 'out_invoice' and self.asset_category_id: self.account_id = self.asset_category_id.account_asset_id.id elif self.invoice_id.type == 'in_invoice' and self.asset_category_id: - self.account_id = self.asset_category_id.account_depreciation_id.id + self.account_id = self.asset_category_id.account_asset_id.id @api.onchange('uom_id') def _onchange_uom_id(self): diff --git a/addons/account_check_printing/models/account_payment.py b/addons/account_check_printing/models/account_payment.py index fc3e200840e..8ee9a40a11f 100644 --- a/addons/account_check_printing/models/account_payment.py +++ b/addons/account_check_printing/models/account_payment.py @@ -88,7 +88,7 @@ class AccountPayment(models.Model): and vals.get('check_manual_sequencing'): sequence = self.env['account.journal'].browse(vals['journal_id']).check_sequence_id vals.update({'check_number': sequence.next_by_id()}) - return super(AccountPayment, self.sudo()).create(vals) + return super(AccountPayment, self).create(vals) @api.multi def print_checks(self): diff --git a/addons/account_tax_python/models/account_tax.py b/addons/account_tax_python/models/account_tax.py index 01f8576ec8e..7ab0c2bbe1f 100644 --- a/addons/account_tax_python/models/account_tax.py +++ b/addons/account_tax_python/models/account_tax.py @@ -66,11 +66,11 @@ class AccountTaxTemplatePython(models.Model): ":param product: product.product recordset singleton or None\n" ":param partner: res.partner recordset singleton or None") - def _get_tax_vals(self, company): + def _get_tax_vals(self, company, tax_template_to_tax): """ This method generates a dictionnary of all the values for the tax that will be created. """ self.ensure_one() - res = super(AccountTaxTemplatePython, self)._get_tax_vals(company) + res = super(AccountTaxTemplatePython, self)._get_tax_vals(company, tax_template_to_tax) res['python_compute'] = self.python_compute res['python_applicable'] = self.python_applicable return res diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 233cd839e6b..aa3f4e69b5c 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -111,8 +111,6 @@ class OAuthLogin(Home): @http.route() def web_auth_signup(self, *args, **kw): providers = self.list_providers() - if len(providers) == 1: - werkzeug.exceptions.abort(werkzeug.utils.redirect(providers[0]['auth_link'], 303)) response = super(OAuthLogin, self).web_auth_signup(*args, **kw) response.qcontext.update(providers=providers) return response diff --git a/addons/base_address_city/models/res_partner.py b/addons/base_address_city/models/res_partner.py index ab1f0518864..afa5cd759e8 100644 --- a/addons/base_address_city/models/res_partner.py +++ b/addons/base_address_city/models/res_partner.py @@ -26,8 +26,8 @@ class Partner(models.Model): replacement_xml = """
- - + +
""" city_id_node = etree.fromstring(replacement_xml) diff --git a/addons/base_address_extended/views/base_address_extended.xml b/addons/base_address_extended/views/base_address_extended.xml index 9f6ab4be442..dcd22b68f25 100644 --- a/addons/base_address_extended/views/base_address_extended.xml +++ b/addons/base_address_extended/views/base_address_extended.xml @@ -6,8 +6,9 @@ res.country - + +
Change how the system computes the full street field based on the different street subfields
@@ -19,14 +20,13 @@ - +
-
@@ -39,13 +39,13 @@ - +
diff --git a/addons/base_automation/views/base_automation_view.xml b/addons/base_automation/views/base_automation_view.xml index 838b1a62ccb..1fe302d286c 100644 --- a/addons/base_automation/views/base_automation_view.xml +++ b/addons/base_automation/views/base_automation_view.xml @@ -9,10 +9,6 @@ -