From 7fcc8ab0481704240921f4670da59dcfa9acbdbf Mon Sep 17 00:00:00 2001 From: Parthiv Patel Date: Sun, 19 Jun 2022 08:34:29 +0000 Subject: [PATCH] [PATCH] Upstream patch - 19062022 --- addons/account/models/account_move.py | 4 +- addons/account/models/partner.py | 13 +- .../account_edi/models/account_edi_format.py | 161 ++++++++++-------- addons/account_edi/models/account_journal.py | 6 +- addons/account_edi/models/account_move.py | 56 ++++++ addons/account_edi_facturx/__init__.py | 10 ++ addons/account_edi_facturx/__manifest__.py | 1 + .../models/account_edi_format.py | 14 +- .../account_edi_facturx/tests/test_facturx.py | 6 + addons/l10n_be_edi/__init__.py | 7 + addons/l10n_be_edi/__manifest__.py | 1 + .../l10n_be_edi/models/account_edi_format.py | 15 +- addons/l10n_be_edi/tests/test_efff_export.py | 6 + addons/l10n_be_edi/tests/test_ubl.py | 6 + .../l10n_it_edi/data/invoice_it_template.xml | 4 +- .../l10n_it_edi/models/account_edi_format.py | 4 +- addons/l10n_it_edi/models/account_invoice.py | 6 +- addons/pos_adyen/controllers/main.py | 1 + addons/pos_adyen/models/pos_payment_method.py | 1 + addons/web_unsplash/models/res_users.py | 8 +- addons/website/models/mixins.py | 4 +- addons/website/models/res_users.py | 8 +- 22 files changed, 233 insertions(+), 109 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 902c7ef9d3..94608c8872 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -184,9 +184,9 @@ class AccountMove(models.Model): partner_id = fields.Many2one('res.partner', readonly=True, tracking=True, states={'draft': [('readonly', False)]}, check_company=True, - string='Partner', change_default=True) + string='Partner', change_default=True, ondelete='restrict') commercial_partner_id = fields.Many2one('res.partner', string='Commercial Entity', store=True, readonly=True, - compute='_compute_commercial_partner_id') + compute='_compute_commercial_partner_id', ondelete='restrict') country_code = fields.Char(related='company_id.country_id.code', readonly=True) user_id = fields.Many2one(string='User', related='invoice_user_id', help='Technical field used to fit the generic behavior in mail templates.') diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py index 1dd3e8f21e..0877469842 100644 --- a/addons/account/models/partner.py +++ b/addons/account/models/partner.py @@ -8,7 +8,7 @@ from psycopg2 import sql, DatabaseError from flectra import api, fields, models, _ from flectra.tools import DEFAULT_SERVER_DATETIME_FORMAT -from flectra.exceptions import ValidationError +from flectra.exceptions import ValidationError, UserError from flectra.addons.base.models.res_partner import WARNING_MESSAGE, WARNING_HELP _logger = logging.getLogger(__name__) @@ -499,6 +499,17 @@ class ResPartner(models.Model): vals['supplier_rank'] = 1 return super().create(vals_list) + def unlink(self): + """ + Prevent the deletion of a partner "Individual", child of a company if: + - partner in 'account.move' + - state: all states (draft and posted) + """ + moves = self.sudo().env['account.move'].search_count([('partner_id', 'in', self.ids), ('state', 'in', ['draft', 'posted'])]) + if moves: + raise UserError(_("Record cannot be deleted. Partner used in Accounting")) + return super(ResPartner, self).unlink() + def _increase_rank(self, field, n=1): if self.ids and field in ['customer_rank', 'supplier_rank']: try: diff --git a/addons/account_edi/models/account_edi_format.py b/addons/account_edi/models/account_edi_format.py index 88810e5d8f..c0e68f25ed 100644 --- a/addons/account_edi/models/account_edi_format.py +++ b/addons/account_edi/models/account_edi_format.py @@ -218,11 +218,12 @@ class AccountEdiFormat(models.Model): # Import methods to override based on EDI Format #################################################### - def _create_invoice_from_xml_tree(self, filename, tree): + def _create_invoice_from_xml_tree(self, filename, tree, journal=None): """ Create a new invoice with the data inside the xml. :param filename: The name of the xml. :param tree: The tree of the xml to import. + :param journal: The journal on which importing the invoice. :returns: The created invoice. """ # TO OVERRIDE @@ -504,96 +505,107 @@ class AccountEdiFormat(models.Model): element = xml_element.xpath(xpath, namespaces=namespaces) return element[0].text if element else None - def _retrieve_partner(self, name=None, phone=None, mail=None, vat=None): - '''Search all partners and find one that matches one of the parameters. + @api.model + def _retrieve_partner_with_vat(self, vat, extra_domain): + if not vat: + return None + # Sometimes, the vat is specified with some whitespaces. + normalized_vat = vat.replace(' ', '') + country_prefix = re.match('^[a-zA-Z]{2}|^', vat).group() + + partner = self.env['res.partner'].search(extra_domain + [('vat', 'in', (normalized_vat, vat))], limit=1) + + # Try to remove the country code prefix from the vat. + if not partner and country_prefix: + partner = self.env['res.partner'].search(extra_domain + [ + ('vat', 'in', (normalized_vat[2:], vat[2:])), + ('country_id.code', '=', country_prefix.upper()), + ], limit=1) + + # The country could be not specified on the partner. + if not partner: + partner = self.env['res.partner'].search(extra_domain + [ + ('vat', 'in', (normalized_vat[2:], vat[2:])), + ('country_id', '=', False), + ], limit=1) + + # The vat could be a string of alphanumeric values without country code but with missing zeros at the + # beginning. + if not partner: + try: + vat_only_numeric = str(int(re.sub(r'^\D{2}', '', normalized_vat) or 0)) + except ValueError: + vat_only_numeric = None + + if vat_only_numeric: + query = self.env['res.partner']._where_calc(extra_domain + [('active', '=', True)]) + tables, where_clause, where_params = query.get_sql() + + if country_prefix: + vat_prefix_regex = f'({country_prefix})?' + else: + vat_prefix_regex = '([A-z]{2})?' + + self._cr.execute(f''' + SELECT res_partner.id + FROM {tables} + WHERE {where_clause} + AND res_partner.vat ~ %s + LIMIT 1 + ''', where_params + ['^%s0*%s$' % (vat_prefix_regex, vat_only_numeric)]) + partner_row = self._cr.fetchone() + if partner_row: + partner = self.env['res.partner'].browse(partner_row[0]) + + return partner + + @api.model + def _retrieve_partner_with_phone_mail(self, phone, mail, extra_domain): + domains = [] + if phone: + domains.append([('phone', '=', phone)]) + domains.append([('mobile', '=', phone)]) + if mail: + domains.append([('email', '=', mail)]) + + if not domains: + return None + + domain = expression.OR(domains) + if extra_domain: + domain = expression.AND([domain, extra_domain]) + return self.env['res.partner'].search(domain, limit=1) + + @api.model + def _retrieve_partner_with_name(self, name, extra_domain): + if not name: + return None + return self.env['res.partner'].search([('name', 'ilike', name)] + extra_domain, limit=1) + + def _retrieve_partner(self, name=None, phone=None, mail=None, vat=None, domain=None): + '''Search all partners and find one that matches one of the parameters. :param name: The name of the partner. :param phone: The phone or mobile of the partner. :param mail: The mail of the partner. :param vat: The vat number of the partner. :returns: A partner or an empty recordset if not found. ''' + def search_with_vat(extra_domain): - if not vat: - return None - - # Sometimes, the vat is specified with some whitespaces. - normalized_vat = vat.replace(' ', '') - country_prefix = re.match('^[a-zA-Z]{2}|^', vat).group() - - partner = self.env['res.partner'].search(extra_domain + [('vat', 'in', (normalized_vat, vat))], limit=1) - - # Try to remove the country code prefix from the vat. - if not partner and country_prefix: - partner = self.env['res.partner'].search(extra_domain + [ - ('vat', 'in', (normalized_vat[2:], vat[2:])), - ('country_id.code', '=', country_prefix.upper()), - ], limit=1) - - # The country could be not specified on the partner. - if not partner: - partner = self.env['res.partner'].search(extra_domain + [ - ('vat', 'in', (normalized_vat[2:], vat[2:])), - ('country_id', '=', False), - ], limit=1) - - # The vat could be a string of alphanumeric values without country code but with missing zeros at the - # beginning. - if not partner: - try: - vat_only_numeric = str(int(re.sub('^\D{2}', '', normalized_vat) or 0)) - except ValueError: - vat_only_numeric = None - - if vat_only_numeric: - query = self.env['res.partner']._where_calc(extra_domain + [('active', '=', True)]) - tables, where_clause, where_params = query.get_sql() - - if country_prefix: - vat_prefix_regex = f'({country_prefix})?' - else: - vat_prefix_regex = '([A-z]{2})?' - - self._cr.execute(f''' - SELECT res_partner.id - FROM {tables} - WHERE {where_clause} - AND res_partner.vat ~ %s - LIMIT 1 - ''', where_params + ['^%s0*%s$' % (vat_prefix_regex, vat_only_numeric)]) - partner_row = self._cr.fetchone() - if partner_row: - partner = self.env['res.partner'].browse(partner_row[0]) - - return partner + return self._retrieve_partner_with_vat(vat, extra_domain) def search_with_phone_mail(extra_domain): - domains = [] - if phone: - domains.append([('phone', '=', phone)]) - domains.append([('mobile', '=', phone)]) - if mail: - domains.append([('email', '=', mail)]) - - if not domains: - return None - - domain = expression.OR(domains) - if extra_domain: - domain = expression.AND([domain, extra_domain]) - return self.env['res.partner'].search(domain, limit=1) + return self._retrieve_partner_with_phone_mail(phone, mail, extra_domain) def search_with_name(extra_domain): - if not name: - return None - return self.env['res.partner'].search([('name', 'ilike', name)] + extra_domain, limit=1) + return self._retrieve_partner_with_name(name, extra_domain) for search_method in (search_with_vat, search_with_phone_mail, search_with_name): for extra_domain in ([('company_id', '=', self.env.company.id)], []): partner = search_method(extra_domain) if partner: return partner - return self.env['res.partner'] def _retrieve_product(self, name=None, default_code=None, barcode=None): @@ -648,3 +660,6 @@ class AccountEdiFormat(models.Model): def _format_error_message(self, error_title, errors): bullet_list_msg = ''.join('
  • %s
  • ' % html_escape(msg) for msg in errors) return '%s' % (error_title, bullet_list_msg) + + def _is_account_edi_ubl_cii_available(self): + return hasattr(self, '_infer_xml_builder_from_tree') diff --git a/addons/account_edi/models/account_journal.py b/addons/account_edi/models/account_journal.py index b939b8cf6e..93373246e3 100644 --- a/addons/account_edi/models/account_journal.py +++ b/addons/account_edi/models/account_journal.py @@ -31,8 +31,12 @@ class AccountJournal(models.Model): ('edi_format_id', 'in', diff_edi_format_ids.ids), ('state', 'in', ('to_cancel', 'to_send')), ]) - if documents: + # If the formats we are unchecking do not need a webservice, we don't need them to be correctly sent + if documents.filtered(lambda d: d.edi_format_id._needs_web_services()): raise UserError(_('Cannot deactivate (%s) on this journal because not all documents are synchronized', ', '.join(documents.edi_format_id.mapped('display_name')))) + # remove these documents which: do not need a web service & are linked to the edi formats we are unchecking + if documents: + documents.unlink() return res else: return super().write(vals) diff --git a/addons/account_edi/models/account_move.py b/addons/account_edi/models/account_move.py index 4ec4567663..894e60992d 100644 --- a/addons/account_edi/models/account_move.py +++ b/addons/account_edi/models/account_move.py @@ -264,6 +264,34 @@ class AccountMove(models.Model): return invoice_global_tax_details + def _prepare_edi_vals_to_export(self): + ''' The purpose of this helper is to prepare values in order to export an invoice through the EDI system. + This includes the computation of the tax details for each invoice line that could be very difficult to + handle regarding the computation of the base amount. + :return: A python dict containing default pre-processed values. + ''' + self.ensure_one() + + res = { + 'record': self, + 'balance_multiplicator': -1 if self.is_inbound() else 1, + 'invoice_line_vals_list': [], + } + + # Invoice lines details. + for index, line in enumerate(self.invoice_line_ids.filtered(lambda line: not line.display_type), start=1): + line_vals = line._prepare_edi_vals_to_export() + line_vals['index'] = index + res['invoice_line_vals_list'].append(line_vals) + + # Totals. + res.update({ + 'total_price_subtotal_before_discount': sum(x['price_subtotal_before_discount'] for x in res['invoice_line_vals_list']), + 'total_price_discount': sum(x['price_discount'] for x in res['invoice_line_vals_list']), + }) + + return res + def _update_payments_edi_documents(self): ''' Update the edi documents linked to the current journal entries. These journal entries must be linked to an account.payment of an account.bank.statement.line. This additional method is needed because the payment flow is @@ -416,6 +444,34 @@ class AccountMoveLine(models.Model): # Export Electronic Document #################################################### + def _prepare_edi_vals_to_export(self): + ''' The purpose of this helper is the same as '_prepare_edi_vals_to_export' but for a single invoice line. + This includes the computation of the tax details for each invoice line or the management of the discount. + Indeed, in some EDI, we need to provide extra values depending the discount such as: + - the discount as an amount instead of a percentage. + - the price_unit but after subtraction of the discount. + :return: A python dict containing default pre-processed values. + ''' + self.ensure_one() + + if self.discount == 100.0: + gross_price_subtotal = self.currency_id.round(self.price_unit * self.quantity) + else: + gross_price_subtotal = self.currency_id.round(self.price_subtotal / (1 - self.discount / 100.0)) + + res = { + 'line': self, + 'price_unit_after_discount': self.currency_id.round(self.price_unit * (1 - (self.discount / 100.0))), + 'price_subtotal_before_discount': gross_price_subtotal, + 'price_subtotal_unit': self.currency_id.round(self.price_subtotal / self.quantity) if self.quantity else 0.0, + 'price_total_unit': self.currency_id.round(self.price_total / self.quantity) if self.quantity else 0.0, + 'price_discount': gross_price_subtotal - self.price_subtotal, + 'price_discount_unit': (gross_price_subtotal - self.price_subtotal) / self.quantity if self.quantity else 0.0, + 'gross_price_total_unit': self.currency_id.round(gross_price_subtotal / self.quantity) if self.quantity else 0.0, + 'unece_uom_code': self.product_id.product_tmpl_id.uom_id._get_unece_code(), + } + return res + def reconcile(self): # OVERRIDE # In some countries, the payments must be sent to the government under some condition. One of them could be diff --git a/addons/account_edi_facturx/__init__.py b/addons/account_edi_facturx/__init__.py index 0650744f6b..ca252bd677 100644 --- a/addons/account_edi_facturx/__init__.py +++ b/addons/account_edi_facturx/__init__.py @@ -1 +1,11 @@ +# -*- coding: utf-8 -*- +# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details. + from . import models +from flectra import api, SUPERUSER_ID + + +def _post_init_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + modules = env['ir.module.module'].search([('name', '=', 'account_edi_ubl_cii'), ('state', '=', 'uninstalled')]) + modules.sudo().button_install() diff --git a/addons/account_edi_facturx/__manifest__.py b/addons/account_edi_facturx/__manifest__.py index 5fea31829f..8c05cdb06e 100644 --- a/addons/account_edi_facturx/__manifest__.py +++ b/addons/account_edi_facturx/__manifest__.py @@ -9,6 +9,7 @@ 'data/facturx_templates.xml', ], 'installable': True, + 'post_init_hook': '_post_init_hook', 'application': False, 'auto_install': True, 'license': 'LGPL-3', diff --git a/addons/account_edi_facturx/models/account_edi_format.py b/addons/account_edi_facturx/models/account_edi_format.py index fb95e60710..dce594e40e 100644 --- a/addons/account_edi_facturx/models/account_edi_format.py +++ b/addons/account_edi_facturx/models/account_edi_format.py @@ -26,13 +26,13 @@ class AccountEdiFormat(models.Model): def _is_compatible_with_journal(self, journal): self.ensure_one() res = super()._is_compatible_with_journal(journal) - if self.code != 'facturx_1_0_05': + if self.code != 'facturx_1_0_05' or self._is_account_edi_ubl_cii_available(): return res return journal.type == 'sale' def _post_invoice_edi(self, invoices, test_mode=False): self.ensure_one() - if self.code != 'facturx_1_0_05': + if self.code != 'facturx_1_0_05' or self._is_account_edi_ubl_cii_available(): return super()._post_invoice_edi(invoices, test_mode=test_mode) res = {} for invoice in invoices: @@ -53,7 +53,7 @@ class AccountEdiFormat(models.Model): def _prepare_invoice_report(self, pdf_writer, edi_document): self.ensure_one() - if self.code != 'facturx_1_0_05': + if self.code != 'facturx_1_0_05' or self._is_account_edi_ubl_cii_available(): return super()._prepare_invoice_report(pdf_writer, edi_document) if not edi_document.attachment_id: return @@ -175,15 +175,15 @@ class AccountEdiFormat(models.Model): def _is_facturx(self, filename, tree): return self.code == 'facturx_1_0_05' and tree.tag == '{urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100}CrossIndustryInvoice' - def _create_invoice_from_xml_tree(self, filename, tree): + def _create_invoice_from_xml_tree(self, filename, tree, journal=None): self.ensure_one() - if self._is_facturx(filename, tree): + if self._is_facturx(filename, tree) and not self._is_account_edi_ubl_cii_available(): return self._import_facturx(tree, self.env['account.move']) - return super()._create_invoice_from_xml_tree(filename, tree) + return super()._create_invoice_from_xml_tree(filename, tree, journal=journal) def _update_invoice_from_xml_tree(self, filename, tree, invoice): self.ensure_one() - if self._is_facturx(filename, tree): + if self._is_facturx(filename, tree) and not self._is_account_edi_ubl_cii_available(): return self._import_facturx(tree, invoice) return super()._update_invoice_from_xml_tree(filename, tree, invoice) diff --git a/addons/account_edi_facturx/tests/test_facturx.py b/addons/account_edi_facturx/tests/test_facturx.py index 1c889220a0..bfc0b80e1e 100644 --- a/addons/account_edi_facturx/tests/test_facturx.py +++ b/addons/account_edi_facturx/tests/test_facturx.py @@ -11,6 +11,12 @@ class TestAccountEdiFacturx(AccountEdiTestCommon): def setUpClass(cls, chart_template_ref=None, edi_format_ref='account_edi_facturx.edi_facturx_1_0_05'): super().setUpClass(chart_template_ref=chart_template_ref, edi_format_ref=edi_format_ref) + if cls.env['ir.module.module'].search( + [('name', '=', 'account_edi_ubl_cii'), ('state', '=', 'installed')], + limit=1, + ): + cls.skipTest(cls, "Factur-X Tests skipped because account_edi_ubl_cii is installed.") + # ==== Init ==== cls.tax_10_include = cls.env['account.tax'].create({ diff --git a/addons/l10n_be_edi/__init__.py b/addons/l10n_be_edi/__init__.py index 013872cc0d..ca252bd677 100644 --- a/addons/l10n_be_edi/__init__.py +++ b/addons/l10n_be_edi/__init__.py @@ -2,3 +2,10 @@ # Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details. from . import models +from flectra import api, SUPERUSER_ID + + +def _post_init_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + modules = env['ir.module.module'].search([('name', '=', 'account_edi_ubl_cii'), ('state', '=', 'uninstalled')]) + modules.sudo().button_install() diff --git a/addons/l10n_be_edi/__manifest__.py b/addons/l10n_be_edi/__manifest__.py index 7bd802a131..bdb7b4bb26 100644 --- a/addons/l10n_be_edi/__manifest__.py +++ b/addons/l10n_be_edi/__manifest__.py @@ -17,5 +17,6 @@ Belgian e-invoicing uses the UBL 2.0 using the e-fff protocol. ], 'installable': True, 'auto_install': True, + 'post_init_hook': '_post_init_hook', 'license': 'LGPL-3', } diff --git a/addons/l10n_be_edi/models/account_edi_format.py b/addons/l10n_be_edi/models/account_edi_format.py index 97bd434a1a..9d3b1cd00d 100644 --- a/addons/l10n_be_edi/models/account_edi_format.py +++ b/addons/l10n_be_edi/models/account_edi_format.py @@ -11,28 +11,27 @@ class AccountEdiFormat(models.Model): def _is_efff(self, filename, tree): return self.code == 'efff_1' and tree.tag == '{urn:oasis:names:specification:ubl:schema:xsd:Invoice-2}Invoice' - def _create_invoice_from_xml_tree(self, filename, tree): + def _create_invoice_from_xml_tree(self, filename, tree, journal=None): self.ensure_one() - if self._is_efff(filename, tree): + if self._is_efff(filename, tree) and not self._is_account_edi_ubl_cii_available(): return self._create_invoice_from_ubl(tree) - return super()._create_invoice_from_xml_tree(filename, tree) + return super()._create_invoice_from_xml_tree(filename, tree, journal=journal) def _update_invoice_from_xml_tree(self, filename, tree, invoice): self.ensure_one() - if self._is_efff(filename, tree): + if self._is_efff(filename, tree) and not self._is_account_edi_ubl_cii_available(): return self._update_invoice_from_ubl(tree, invoice) return super()._update_invoice_from_xml_tree(filename, tree, invoice) def _is_compatible_with_journal(self, journal): self.ensure_one() - res = super()._is_compatible_with_journal(journal) - if self.code != 'efff_1': - return res + if self.code != 'efff_1' or self._is_account_edi_ubl_cii_available(): + return super()._is_compatible_with_journal(journal) return journal.type == 'sale' and journal.country_code == 'BE' def _post_invoice_edi(self, invoices, test_mode=False): self.ensure_one() - if self.code != 'efff_1': + if self.code != 'efff_1' or self._is_account_edi_ubl_cii_available(): return super()._post_invoice_edi(invoices, test_mode=test_mode) res = {} for invoice in invoices: diff --git a/addons/l10n_be_edi/tests/test_efff_export.py b/addons/l10n_be_edi/tests/test_efff_export.py index a826c0ab2c..073dc55a96 100644 --- a/addons/l10n_be_edi/tests/test_efff_export.py +++ b/addons/l10n_be_edi/tests/test_efff_export.py @@ -14,6 +14,12 @@ class TestUBLBE(AccountEdiTestCommon): def setUpClass(cls, chart_template_ref='l10n_be.l10nbe_chart_template', edi_format_ref='l10n_be_edi.edi_efff_1'): super().setUpClass(chart_template_ref=chart_template_ref, edi_format_ref=edi_format_ref) + if cls.env['ir.module.module'].search( + [('name', '=', 'account_edi_ubl_cii'), ('state', '=', 'installed')], + limit=1, + ): + cls.skipTest(cls, "L10n_be_edi Tests skipped because account_edi_ubl_cii is installed.") + cls.partner_a.write({ 'street': "Chaussée de Namur 40", 'zip': "1367", diff --git a/addons/l10n_be_edi/tests/test_ubl.py b/addons/l10n_be_edi/tests/test_ubl.py index 64e0eea005..5d347d7c7a 100644 --- a/addons/l10n_be_edi/tests/test_ubl.py +++ b/addons/l10n_be_edi/tests/test_ubl.py @@ -9,6 +9,12 @@ class TestUBL(AccountEdiTestCommon): def setUpClass(cls, chart_template_ref='l10n_be.l10nbe_chart_template', edi_format_ref='l10n_be_edi.edi_efff_1'): super().setUpClass(chart_template_ref=chart_template_ref, edi_format_ref=edi_format_ref) + if cls.env['ir.module.module'].search( + [('name', '=', 'account_edi_ubl_cii'), ('state', '=', 'installed')], + limit=1, + ): + cls.skipTest(cls, "L10n_be_edi Tests skipped because account_edi_ubl_cii is installed.") + cls.partner_a.vat = 'BE0477472701' def test_invoice_edi_xml_update(self): diff --git a/addons/l10n_it_edi/data/invoice_it_template.xml b/addons/l10n_it_edi/data/invoice_it_template.xml index bc1ac5fcd8..28cf793afc 100644 --- a/addons/l10n_it_edi/data/invoice_it_template.xml +++ b/addons/l10n_it_edi/data/invoice_it_template.xml @@ -169,8 +169,8 @@ - - + + diff --git a/addons/l10n_it_edi/models/account_edi_format.py b/addons/l10n_it_edi/models/account_edi_format.py index 089e7d2e46..691670940b 100644 --- a/addons/l10n_it_edi/models/account_edi_format.py +++ b/addons/l10n_it_edi/models/account_edi_format.py @@ -233,11 +233,11 @@ class AccountEdiFormat(models.Model): def _is_fattura_pa(self, filename, tree): return self.code == 'fattura_pa' and self._check_filename_is_fattura_pa(filename) - def _create_invoice_from_xml_tree(self, filename, tree): + def _create_invoice_from_xml_tree(self, filename, tree, journal=None): self.ensure_one() if self._is_fattura_pa(filename, tree): return self._import_fattura_pa(tree, self.env['account.move']) - return super()._create_invoice_from_xml_tree(filename, tree) + return super()._create_invoice_from_xml_tree(filename, tree, journal=journal) def _update_invoice_from_xml_tree(self, filename, tree, invoice): self.ensure_one() diff --git a/addons/l10n_it_edi/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py index 197908462f..9ad08887a7 100644 --- a/addons/l10n_it_edi/models/account_invoice.py +++ b/addons/l10n_it_edi/models/account_invoice.py @@ -167,14 +167,14 @@ class AccountMove(models.Model): # taxable base = sum(taxable base for each unit) + Arrotondamento tax_details = self._prepare_edi_tax_details() for _tax_name, tax_dict in tax_details['tax_details'].items(): - base_amount = tax_dict['base_amount'] - tax_amount = tax_dict['tax_amount'] + base_amount = tax_dict['base_amount_currency'] + tax_amount = tax_dict['tax_amount_currency'] tax_rate = tax_dict['tax'].amount if tax_dict['tax'].price_include and tax_dict['tax'].amount_type == 'percent': expected_base_amount = tax_amount * 100 / tax_rate if tax_rate else False if expected_base_amount and float_compare(base_amount, expected_base_amount, 2): tax_dict['rounding'] = base_amount - (tax_amount * 100 / tax_rate) - tax_dict['base_amount'] = base_amount - tax_dict['rounding'] + tax_dict['base_amount_currency'] = base_amount - tax_dict['rounding'] # Create file content. template_values = { diff --git a/addons/pos_adyen/controllers/main.py b/addons/pos_adyen/controllers/main.py index fc7bdaee78..e41763c8cf 100644 --- a/addons/pos_adyen/controllers/main.py +++ b/addons/pos_adyen/controllers/main.py @@ -28,5 +28,6 @@ class PosAdyenController(http.Controller): payment_method.adyen_latest_diagnosis = data['SaleToPOIResponse']['MessageHeader']['ServiceID'] else: payment_method.adyen_latest_response = json.dumps(data) + _logger.info('notification writed from adyen\n%s', data) else: _logger.error('received a message for a terminal not registered in Flectra: %s', terminal_identifier) diff --git a/addons/pos_adyen/models/pos_payment_method.py b/addons/pos_adyen/models/pos_payment_method.py index 5d69126297..7a62e6d965 100644 --- a/addons/pos_adyen/models/pos_payment_method.py +++ b/addons/pos_adyen/models/pos_payment_method.py @@ -79,6 +79,7 @@ class PosPaymentMethod(models.Model): } def get_latest_adyen_status(self, pos_config_name): + _logger.info('get_latest_adyen_status\n%s', pos_config_name) self.ensure_one() # Poll the status of the terminal if there's no new diff --git a/addons/web_unsplash/models/res_users.py b/addons/web_unsplash/models/res_users.py index cac441fbeb..fa004e905f 100644 --- a/addons/web_unsplash/models/res_users.py +++ b/addons/web_unsplash/models/res_users.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details. -from flectra import api, models +from flectra import models class ResUsers(models.Model): @@ -8,4 +8,8 @@ class ResUsers(models.Model): def _has_unsplash_key_rights(self): self.ensure_one() - return self.has_group('base.group_erp_manager') + # Website has no dependency to web_unsplash, we cannot warranty the order of the execution + # of the overwrite done in 5ef8300. + # So to avoid to create a new module bridge, with a lot of code, we prefer to make a check + # here for website's user. + return self.has_group('base.group_erp_manager') or self.has_group('website.group_website_designer') diff --git a/addons/website/models/mixins.py b/addons/website/models/mixins.py index a9662db28e..70afd25c0f 100644 --- a/addons/website/models/mixins.py +++ b/addons/website/models/mixins.py @@ -3,8 +3,10 @@ import logging +from werkzeug.urls import url_join from flectra import api, fields, models, _ +from flectra.addons.http_routing.models.ir_http import url_for from flectra.http import request from flectra.osv import expression from flectra.exceptions import AccessError @@ -50,7 +52,7 @@ class SeoMetadata(models.AbstractModel): 'og:type': 'website', 'og:title': title, 'og:site_name': company.name, - 'og:url': request.httprequest.url, + 'og:url': url_join(request.httprequest.url_root, url_for(request.httprequest.path)), 'og:image': img, } # Default meta for Twitter diff --git a/addons/website/models/res_users.py b/addons/website/models/res_users.py index 23a4b97a3b..20ac0d0ed1 100644 --- a/addons/website/models/res_users.py +++ b/addons/website/models/res_users.py @@ -2,7 +2,7 @@ # Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details. import logging -from flectra import api, fields, models, tools, _ +from flectra import api, fields, models, _ from flectra.exceptions import ValidationError from flectra.http import request @@ -19,12 +19,6 @@ class ResUsers(models.Model): ('login_key', 'unique (login, website_id)', 'You can not have two users with the same login!'), ] - def _has_unsplash_key_rights(self): - self.ensure_one() - if self.has_group('website.group_website_designer'): - return True - return super(ResUsers, self)._has_unsplash_key_rights() - @api.constrains('login', 'website_id') def _check_login(self): """ Do not allow two users with the same login without website """