diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 9947816b8b1..97d24fb7048 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -3446,8 +3446,10 @@ class AccountMove(models.Model): default_email_layout_xmlid="mail.mail_notification_layout_with_responsible_signature", model_description=self.with_context(lang=lang).type_name, force_email=True, + active_ids=self.ids, ) - return { + + report_action = { 'name': _('Send Invoice'), 'type': 'ir.actions.act_window', 'view_type': 'form', @@ -3459,6 +3461,11 @@ class AccountMove(models.Model): 'context': ctx, } + if self.env.is_admin() and not self.env.company.external_report_layout_id and not self.env.context.get('discard_logo_check'): + return self.env['ir.actions.report']._action_configure_external_report_layout(report_action) + + return report_action + def preview_invoice(self): self.ensure_one() return { diff --git a/addons/web/models/base_document_layout.py b/addons/web/models/base_document_layout.py index ff685b32073..47df92452da 100644 --- a/addons/web/models/base_document_layout.py +++ b/addons/web/models/base_document_layout.py @@ -40,12 +40,20 @@ class BaseDocumentLayout(models.TransientModel): def _default_company_details(self): company = self.env.company address_format, company_data = company.partner_id._prepare_display_address() + address_format = self._clean_address_format(address_format, company_data) # company_name may *still* be missing from prepared address in case commercial_company_name is falsy if 'company_name' not in address_format: address_format = '%(company_name)s\n' + address_format company_data['company_name'] = company_data['company_name'] or company.name return Markup(nl2br(address_format)) % company_data + def _clean_address_format(self, address_format, company_data): + missing_company_data = [k for k, v in company_data.items() if not v] + for key in missing_company_data: + if key in address_format: + address_format = address_format.replace(f'%({key})s\n', '') + return address_format + company_id = fields.Many2one( 'res.company', default=lambda self: self.env.company, required=True) diff --git a/addons/web/tests/test_base_document_layout.py b/addons/web/tests/test_base_document_layout.py index fb658fff5fa..14afbc0acdb 100644 --- a/addons/web/tests/test_base_document_layout.py +++ b/addons/web/tests/test_base_document_layout.py @@ -223,3 +223,16 @@ class TestBaseDocumentLayout(TestBaseDocumentLayoutHelpers): # self.assertColors(doc_layout, default_colors) # doc_layout.report_layout_id = self.report_layout2 # self.assertColors(doc_layout, self.report_layout2) + + def test_company_details_blank_lines(self): + """Test that the company address is generated dynamically using only the fields that are defined, + without leaving any blank lines.""" + # Make sure there is no blank line in the company details. + doc_layout_1 = self.env['base.document.layout'].create({'company_id': self.company.id}) + self.assertFalse('\n
\n' in doc_layout_1.company_details) + + # Make sure that 'street2' (an optional field, initially blank), + # appears in the company details when it is defined. + self.company.write({'street2': 'street_2_detail'}) + doc_layout_2 = self.env['base.document.layout'].create({'company_id': self.company.id}) + self.assertTrue('street_2_detail' in doc_layout_2.company_details) diff --git a/odoo/addons/base/models/ir_actions_report.py b/odoo/addons/base/models/ir_actions_report.py index bf9b13e3971..187bb7266fb 100644 --- a/odoo/addons/base/models/ir_actions_report.py +++ b/odoo/addons/base/models/ir_actions_report.py @@ -926,12 +926,14 @@ class IrActionsReport(models.Model): discard_logo_check = self.env.context.get('discard_logo_check') if self.env.is_admin() and not self.env.company.external_report_layout_id and config and not discard_logo_check: - action = self.env["ir.actions.actions"]._for_xml_id("web.action_base_document_layout_configurator") - ctx = action.get('context') - py_ctx = json.loads(ctx) if ctx else {} - report_action['close_on_report_download'] = True - py_ctx['report_action'] = report_action - action['context'] = py_ctx - return action + return self._action_configure_external_report_layout(report_action) return report_action + + def _action_configure_external_report_layout(self, report_action): + action = self.env["ir.actions.actions"]._for_xml_id("web.action_base_document_layout_configurator") + py_ctx = json.loads(action.get('context', {})) + report_action['close_on_report_download'] = True + py_ctx['report_action'] = report_action + action['context'] = py_ctx + return action