From a8b4814a222b0358afb2e5ce6da05e1f3ed4fb21 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Tue, 6 Oct 2026 10:50:45 +0200 Subject: [PATCH] [IMP] pms: agencies only pay the stay by default Agencies invoiced always also became the payer of the extra services. By default they are now invoiced the nights and the board services and the extras are left to the guest; a new agency option keeps invoicing the extras to the agency. --- pms/i18n/es.po | 20 ++++++ pms/i18n/pms.pot | 17 +++++ pms/models/pms_service.py | 1 + pms/models/res_partner.py | 6 ++ pms/tests/test_pms_service.py | 108 ++++++++++++++++++++++++++++++++ pms/views/res_partner_views.xml | 4 ++ 6 files changed, 156 insertions(+) diff --git a/pms/i18n/es.po b/pms/i18n/es.po index e9e5f6710e..94f07db640 100644 --- a/pms/i18n/es.po +++ b/pms/i18n/es.po @@ -5912,6 +5912,13 @@ msgstr "Facturar a la agencia" msgid "Invoice Count" msgstr "Recuento de facturas" +#. module: pms +#: model:ir.model.fields,field_description:pms.field_pms_property__invoice_extras_to_agency +#: model:ir.model.fields,field_description:pms.field_res_partner__invoice_extras_to_agency +#: model:ir.model.fields,field_description:pms.field_res_users__invoice_extras_to_agency +msgid "Invoice Extras to Agency" +msgstr "Facturar extras a la agencia" + #. module: pms #: model_terms:ir.ui.view,arch_db:pms.view_folio_advance_payment_inv msgid "Invoice Folio Order" @@ -7465,6 +7472,19 @@ msgstr "Solo servicios" msgid "Only allowed if the field of partner is_agency is True" msgstr "Solo se permite si el campo del partner is_agency es True" +#. module: pms +#: model:ir.model.fields,help:pms.field_pms_property__invoice_extras_to_agency +#: model:ir.model.fields,help:pms.field_res_partner__invoice_extras_to_agency +#: model:ir.model.fields,help:pms.field_res_users__invoice_extras_to_agency +msgid "" +"Only for agencies invoiced always. Unchecked: the agency is invoiced the " +"nights and the board services, and the guest the extra services. Checked: " +"the agency is also invoiced the extra services." +msgstr "" +"Solo para agencias con «Facturar a la agencia: Siempre». Desmarcado: a la " +"agencia se le facturan las noches y el régimen, y al huésped los servicios " +"extra. Marcado: a la agencia se le facturan también los servicios extra." + #. module: pms #: model:ir.model.constraint,message:pms.constraint_pms_availability_room_type_registry_unique msgid "" diff --git a/pms/i18n/pms.pot b/pms/i18n/pms.pot index 0e74171113..bf950b4e4f 100644 --- a/pms/i18n/pms.pot +++ b/pms/i18n/pms.pot @@ -5477,6 +5477,13 @@ msgstr "" msgid "Invoice Count" msgstr "" +#. module: pms +#: model:ir.model.fields,field_description:pms.field_pms_property__invoice_extras_to_agency +#: model:ir.model.fields,field_description:pms.field_res_partner__invoice_extras_to_agency +#: model:ir.model.fields,field_description:pms.field_res_users__invoice_extras_to_agency +msgid "Invoice Extras to Agency" +msgstr "" + #. module: pms #: model_terms:ir.ui.view,arch_db:pms.view_folio_advance_payment_inv msgid "Invoice Folio Order" @@ -6993,6 +7000,16 @@ msgstr "" msgid "Only allowed if the field of partner is_agency is True" msgstr "" +#. module: pms +#: model:ir.model.fields,help:pms.field_pms_property__invoice_extras_to_agency +#: model:ir.model.fields,help:pms.field_res_partner__invoice_extras_to_agency +#: model:ir.model.fields,help:pms.field_res_users__invoice_extras_to_agency +msgid "" +"Only for agencies invoiced always. Unchecked: the agency is invoiced the " +"nights and the board services, and the guest the extra services. Checked: " +"the agency is also invoiced the extra services." +msgstr "" + #. module: pms #: model:ir.model.constraint,message:pms.constraint_pms_availability_room_type_registry_unique msgid "" diff --git a/pms/models/pms_service.py b/pms/models/pms_service.py index 6aeb84d908..7f26e4df8e 100644 --- a/pms/models/pms_service.py +++ b/pms/models/pms_service.py @@ -507,6 +507,7 @@ def _compute_default_invoice_to(self): agency and agency.invoice_to_agency == "always" and agency.sale_channel_id == record.sale_channel_origin_id + and (record.is_board_service or agency.invoice_extras_to_agency) ): record.default_invoice_to = agency elif not record.default_invoice_to: diff --git a/pms/models/res_partner.py b/pms/models/res_partner.py index 1cb7744d3c..ed59504ed0 100644 --- a/pms/models/res_partner.py +++ b/pms/models/res_partner.py @@ -56,6 +56,12 @@ class ResPartner(models.Model): default="never", required=True, ) + invoice_extras_to_agency = fields.Boolean( + string="Invoice Extras to Agency", + help="Only for agencies invoiced always. Unchecked: the agency is invoiced " + "the nights and the board services, and the guest the extra services. " + "Checked: the agency is also invoiced the extra services.", + ) pms_property_ids = fields.Many2many( string="Properties", help="Properties with access to the element" diff --git a/pms/tests/test_pms_service.py b/pms/tests/test_pms_service.py index 193ee099c3..e4835db834 100644 --- a/pms/tests/test_pms_service.py +++ b/pms/tests/test_pms_service.py @@ -1067,3 +1067,111 @@ def test_change_origin_folio_no_change_origin_service(self): self.folio1.service_ids.mapped("sale_channel_origin_id"), "sale_channel_origin_id of that service mustn't be changed", ) + + def _create_agency_reservation(self, **agency_vals): + """Half board reservation of an agency that is always invoiced""" + sale_channel = self.env["pms.sale.channel"].create( + {"name": "Tour Operator", "channel_type": "indirect"} + ) + agency = self.env["res.partner"].create( + { + "name": "Agency", + "is_agency": True, + "sale_channel_id": sale_channel.id, + "invoice_to_agency": "always", + **agency_vals, + } + ) + board_service = self.env["pms.board.service"].create( + { + "name": "Half Board", + "default_code": "HB", + "pms_property_ids": [self.pms_property1.id], + } + ) + self.env["pms.board.service.line"].create( + { + "product_id": self.env["product.product"].create({"name": "Dinner"}).id, + "pms_board_service_id": board_service.id, + "amount": 20, + "adults": True, + } + ) + board_service_room_type = self.env["pms.board.service.room.type"].create( + { + "pms_room_type_id": self.room_type_double.id, + "pms_board_service_id": board_service.id, + "pms_property_id": self.pms_property1.id, + } + ) + reservation = self.env["pms.reservation"].create( + { + "checkin": fields.date.today(), + "checkout": fields.date.today() + datetime.timedelta(days=2), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "pricelist_id": self.pricelist1.id, + "agency_id": agency.id, + "sale_channel_origin_id": sale_channel.id, + "board_service_room_id": board_service_room_type.id, + "adults": 2, + } + ) + return agency, reservation + + def _create_extra_service(self, reservation): + return self.env["pms.service"].create( + { + "reservation_id": reservation.id, + "product_id": self.env["product.product"].create({"name": "Bar"}).id, + "is_board_service": False, + } + ) + + @freeze_time("2002-03-01") + def test_agency_invoiced_extras(self): + """ + An agency that is always invoiced and also the extras is invoiced the + extra services added to the reservation. + """ + # ARRANGE + agency, reservation = self._create_agency_reservation( + invoice_extras_to_agency=True + ) + # ACT + extra = self._create_extra_service(reservation) + # ASSERT + self.assertEqual( + extra.default_invoice_to, + agency, + "The extra service must be invoiced to the agency", + ) + + @freeze_time("2002-03-01") + def test_agency_only_invoiced_the_stay_by_default(self): + """ + An agency that is always invoiced is invoiced by default the nights + and the board services, while the extras added to the reservation + are left to the guest, also in the folio sale lines. + """ + # ARRANGE + agency, reservation = self._create_agency_reservation() + # ACT + extra = self._create_extra_service(reservation) + # ASSERT + sale_lines = reservation.folio_id.sale_line_ids.filtered( + lambda line: not line.display_type + ) + extra_lines = sale_lines.filtered(lambda line: line.service_id == extra) + self.assertTrue(extra_lines) + self.assertTrue(sale_lines.filtered("is_board_service")) + self.assertFalse( + extra_lines.default_invoice_to, + "The extra service must be invoiced to the guest", + ) + self.assertEqual( + (sale_lines - extra_lines).default_invoice_to, + agency, + "The nights and the board services must be invoiced to the agency", + ) diff --git a/pms/views/res_partner_views.xml b/pms/views/res_partner_views.xml index 95c67d2614..4ec17b041f 100644 --- a/pms/views/res_partner_views.xml +++ b/pms/views/res_partner_views.xml @@ -97,6 +97,10 @@ --> +