diff --git a/pms/__manifest__.py b/pms/__manifest__.py index 6eca94f81..61b490dd6 100644 --- a/pms/__manifest__.py +++ b/pms/__manifest__.py @@ -4,7 +4,7 @@ { "name": "PMS (Property Management System)", "summary": "A property management system", - "version": "14.0.2.35.1", + "version": "14.0.2.36.1", "development_status": "Beta", "category": "Generic Modules/Property Management System", "website": "https://github.com/OCA/pms", diff --git a/pms/demo/pms_folio.xml b/pms/demo/pms_folio.xml index f4630eebd..9846195a4 100644 --- a/pms/demo/pms_folio.xml +++ b/pms/demo/pms_folio.xml @@ -22,13 +22,17 @@ })]" /> - + + - + + + + Each guest pays his bill - + - + + out - + - + + Do not allow guests to pay anything. The company pays for everything. @@ -269,6 +300,7 @@ 'checkout': (DateTime.today() + timedelta(days=18)), 'adults': 1, 'state': 'confirm', + 'sale_channel_origin_id': ref('pms.main_pms_sale_channel_door') }), (0, 0, { 'pricelist_id': ref('product.list0'), @@ -285,6 +317,7 @@ 'checkout': (DateTime.today() + timedelta(days=18)), 'adults': 1, 'state': 'confirm', + 'sale_channel_origin_id': ref('pms.main_pms_sale_channel_mail') }), (0, 0, { 'pricelist_id': ref('product.list0'), @@ -309,6 +342,7 @@ 'checkout': (DateTime.today() + timedelta(days=18)), 'adults': 3, 'state': 'confirm', + 'sale_channel_origin_id': ref('pms.main_pms_sale_channel_mail') }), (0, 0, { 'pricelist_id': ref('product.list0'), @@ -325,6 +359,11 @@ + + out - + - + Each guest pays his bill - + Each guest pays his bill @@ -427,7 +474,7 @@ - + normal - + normal - + normal + cancel - - - - normal - - - - + + + + + + + + + + + + + + + + + + + + + + + + Each guest pays his bill @@ -571,7 +629,7 @@ - + Each guest pays his bill @@ -611,7 +670,7 @@ - + Each guest pays his bill + Each guest pays his bill - + - + - + - + + - + - + - + + Extra privacy for school field trip. + @@ -26,6 +27,7 @@ Carpet replacement. + @@ -37,6 +39,7 @@ Carpet replacement. + @@ -49,6 +52,7 @@ Wall painting. + @@ -65,7 +69,7 @@ ref="pms_board_service_room_eco_full_board" /> - + done - + done @@ -124,7 +128,7 @@ ref="pms_board_service_room_eco_full_board" /> - + done Breakfast at 5:00 am. @@ -158,7 +162,7 @@ ref="pms_board_service_room_eco_full_board" /> - + done @@ -185,7 +189,7 @@ ref="pms_board_service_room_eco_full_board" /> - + done @@ -212,7 +216,7 @@ ref="pms_board_service_room_eco_full_board" /> - + done Need lunchs to take away. @@ -255,6 +259,10 @@ /> + @@ -265,6 +273,10 @@ + Need 1 extra towel. @@ -275,7 +287,7 @@ - + @@ -285,7 +297,10 @@ - + Need 2 extra towel. @@ -297,6 +312,10 @@ + @@ -307,7 +326,7 @@ - + Need 2 extra towels. Friend of manager @@ -325,7 +344,7 @@ - + @@ -338,6 +357,10 @@ + Preferably street view. @@ -350,7 +373,10 @@ - + @@ -367,7 +393,7 @@ ref="pms_board_service_room_single_full_board" /> - + done Late for dinner. Cold dinner needed. @@ -395,7 +421,7 @@ ref="pms_board_service_room_single_full_board" /> - + done @@ -422,8 +448,8 @@ ref="pms_board_service_room_single_full_board" /> - done + @@ -458,7 +484,7 @@ ref="pms_board_service_room_single_full_board" /> - + breakfast at 5:00 am @@ -484,6 +510,10 @@ /> + @@ -499,7 +529,7 @@ ref="pms_board_service_room_single_full_board" /> - + Breakfast to take away. @@ -517,6 +547,10 @@ /> + @@ -529,6 +563,10 @@ + preferably street view @@ -541,7 +579,10 @@ - + @@ -555,6 +596,10 @@ + Preferably street view. @@ -567,7 +612,10 @@ - + @@ -581,7 +629,7 @@ - + - + 1 bottle of champagne upon check-in @@ -620,7 +668,7 @@ - + @@ -637,6 +685,10 @@ /> + 3 extra towels @@ -649,7 +701,10 @@ - + @@ -666,6 +721,10 @@ /> + Vegan breakfast @@ -686,6 +745,10 @@ + @@ -701,7 +764,7 @@ ref="pms_board_service_room_double_half_board" /> - + Help needed with the luggage. @@ -719,7 +782,7 @@ ref="pms_board_service_room_double_breakfast" /> - + @@ -732,7 +795,10 @@ - + Need 1 extra set of bedclothes @@ -744,6 +810,10 @@ 2 + - + welcome cocktail @@ -785,7 +855,7 @@ ref="pms_board_service_room_triple_full_board" /> - + done @@ -828,6 +898,10 @@ /> + Vegetarian food for all guests. @@ -839,6 +913,10 @@ + @@ -858,7 +936,7 @@ - + 3 set of keys needed. @@ -879,7 +957,10 @@ - + @@ -902,7 +983,7 @@ ref="pms_board_service_room_triple_breakfast" /> - + Celiac breakfast @@ -919,7 +1000,7 @@ ref="pms_board_service_room_triple_full_board" /> - + @@ -930,6 +1011,10 @@ + room with low noise 24x7 @@ -941,7 +1026,7 @@ - + done @@ -963,6 +1048,10 @@ + done - + done @@ -1008,6 +1100,10 @@ + Allergic to chemicals done @@ -1030,6 +1126,10 @@ + @@ -1039,8 +1139,25 @@ - + Hard mattress needed. + @@ -1050,7 +1167,7 @@ - + @@ -1065,7 +1182,7 @@ 0 paid - + done 2 bottles of water each 2 hours. @@ -1089,6 +1206,10 @@ + @@ -1099,8 +1220,21 @@ - + Projector needed + @@ -1111,7 +1245,10 @@ - + @@ -1122,7 +1259,10 @@ - + done @@ -1143,7 +1283,7 @@ - + Need 1 extra shampoo done @@ -1165,7 +1305,7 @@ - + done @@ -1186,7 +1326,10 @@ - + Welcome cocktail. @@ -1197,7 +1340,7 @@ - + @@ -1207,7 +1350,7 @@ - + Basket fruit at bedroom @@ -1219,7 +1362,10 @@ - + done @@ -1240,7 +1386,7 @@ - + allergic to chemicals done @@ -1262,7 +1408,7 @@ - + done @@ -1283,7 +1429,10 @@ - + Smoking room. @@ -1294,7 +1443,7 @@ - + @@ -1304,7 +1453,7 @@ - + two bottles of moët diff --git a/pms/migrations/14.0.2.35.1/post-migration.py b/pms/migrations/14.0.2.35.1/post-migration.py index d103f214c..16bff610c 100644 --- a/pms/migrations/14.0.2.35.1/post-migration.py +++ b/pms/migrations/14.0.2.35.1/post-migration.py @@ -7,7 +7,7 @@ def migrate(env, version): env.cr, """ UPDATE pms_reservation - SET to_send_confirmation_mail = to_send_mail, + SET to_send_confirmation_mail = False, to_send_cancelation_mail = False, to_send_exit_mail = False, to_send_modification_mail = False; diff --git a/pms/migrations/14.0.2.36.1/post-migration.py b/pms/migrations/14.0.2.36.1/post-migration.py new file mode 100644 index 000000000..355a36033 --- /dev/null +++ b/pms/migrations/14.0.2.36.1/post-migration.py @@ -0,0 +1,32 @@ +import logging + +from openupgradelib import openupgrade + +_logger = logging.getLogger(__name__) + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.logged_query( + env.cr, + """ + UPDATE pms_reservation_line rl + SET sale_channel_id = r.sale_channel_origin_id + FROM pms_reservation r + WHERE r.id = rl.reservation_id + """, + ) + openupgrade.logged_query( + env.cr, + """ + UPDATE pms_service ser + SET sale_channel_origin_id = fol.sale_channel_origin_id + FROM pms_folio fol + WHERE fol.id = ser.folio_id + """, + ) + + _logger.info("Recompute reservations sale channel ids...") + env["pms.reservation"].search( + [("reservation_type", "!=", "out")] + )._compute_sale_channel_ids() diff --git a/pms/migrations/14.0.2.36.1/pre-migration.py b/pms/migrations/14.0.2.36.1/pre-migration.py new file mode 100644 index 000000000..cc81dc010 --- /dev/null +++ b/pms/migrations/14.0.2.36.1/pre-migration.py @@ -0,0 +1,11 @@ +from openupgradelib import openupgrade + +_field_renames = [ + ("pms.folio", "pms_folio", "channel_type_id", "sale_channel_origin_id"), + ("pms.reservation", "pms_reservation", "channel_type_id", "sale_channel_origin_id"), +] + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.rename_fields(env, _field_renames) diff --git a/pms/models/folio_sale_line.py b/pms/models/folio_sale_line.py index 90ac27f13..921b9920d 100644 --- a/pms/models/folio_sale_line.py +++ b/pms/models/folio_sale_line.py @@ -1,9 +1,11 @@ # Copyright 2020 Dario Lodeiros # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from datetime import timedelta from math import ceil import babel.dates +from dateutil import relativedelta from odoo import _, api, fields, models from odoo.osv import expression @@ -44,6 +46,15 @@ class FolioSaleLine(models.Model): comodel_name="pms.service", ondelete="cascade", ) + pms_property_id = fields.Many2one( + string="Property", + help="Property with access to the element;", + readonly=True, + store=True, + comodel_name="pms.property", + related="folio_id.pms_property_id", + check_pms_properties=True, + ) is_board_service = fields.Boolean( string="Board Service", help="Indicates if the service included in " @@ -51,7 +62,6 @@ class FolioSaleLine(models.Model): store=True, related="service_id.is_board_service", ) - name = fields.Text( string="Description", help="Description of folio sale line", @@ -259,13 +269,6 @@ class FolioSaleLine(models.Model): index=True, related="folio_id.company_id", ) - folio_partner_id = fields.Many2one( - string="Customer", - help="Related customer with Folio Sale Line", - readonly=False, - store=True, - related="folio_id.partner_id", - ) origin_agency_id = fields.Many2one( string="Origin Agency", help="The agency where the folio sale line originates", @@ -330,14 +333,38 @@ class FolioSaleLine(models.Model): store=True, compute="_compute_date_order", ) + default_invoice_to = fields.Many2one( + string="Invoice to", + help="""Indicates the contact to which this line will be + billed by default, if it is not established, + a guest or the generic contact will be used instead""", + comodel_name="res.partner", + ondelete="restrict", + ) + autoinvoice_date = fields.Date( + string="Autoinvoice Date", + compute="_compute_autoinvoice_date", + store=True, + ) @api.depends( + "folio_id.agency_id", "reservation_line_ids", - "reservation_id.agency_id", + "service_line_ids", ) def _compute_origin_agency_id(self): + """ + Set the origin agency if the origin lines channel + match with the agency's channel + """ for rec in self: - rec.origin_agency_id = rec.folio_id.agency_id + # TODO: ServiceLines agency + if rec.folio_id.agency_id and list( + set(rec.reservation_line_ids.mapped("sale_channel_id.id")) + ) == rec.folio_id.agency_id.mapped("sale_channel_id.id"): + rec.origin_agency_id = rec.folio_id.agency_id + else: + rec.origin_agency_id = False @api.depends("qty_to_invoice") def _compute_service_order(self): @@ -370,6 +397,54 @@ class FolioSaleLine(models.Model): else: record.date_order = 0 + @api.depends( + "default_invoice_to", + "invoice_status", + "folio_id.last_checkout", + "reservation_id.checkout", + "service_id.reservation_id.checkout", + ) + def _compute_autoinvoice_date(self): + self.autoinvoice_date = False + for record in self.filtered(lambda r: r.invoice_status == "to_invoice"): + record.autoinvoice_date = record._get_to_invoice_date() + + def _get_to_invoice_date(self): + self.ensure_one() + partner = self.default_invoice_to + if self.reservation_id: + last_checkout = self.reservation_id.checkout + elif self.service_id and self.service_id.reservation_id: + last_checkout = self.service_id.reservation_id.checkout + else: + last_checkout = self.folio_id.last_checkout + invoicing_policy = ( + self.pms_property_id.default_invoicing_policy + if not partner or partner.invoicing_policy == "property" + else partner.invoicing_policy + ) + if invoicing_policy == "manual": + return False + if invoicing_policy == "checkout": + margin_days = ( + self.pms_property_id.margin_days_autoinvoice + if not partner or partner.invoicing_policy == "property" + else partner.margin_days_autoinvoice + ) + return last_checkout + timedelta(days=margin_days) + if invoicing_policy == "month_day": + month_day = ( + self.pms_property_id.invoicing_month_day + if not partner or partner.invoicing_policy == "property" + else partner.invoicing_month_day + ) + if last_checkout.day <= month_day: + self.autoinvoice_date = last_checkout.replace(day=month_day) + else: + self.autoinvoice_date = ( + last_checkout + relativedelta.relativedelta(months=1) + ).replace(day=month_day) + @api.depends("date_order") def _compute_reservation_order(self): for record in self: diff --git a/pms/models/pms_checkin_partner.py b/pms/models/pms_checkin_partner.py index c05df60c7..9b6886662 100644 --- a/pms/models/pms_checkin_partner.py +++ b/pms/models/pms_checkin_partner.py @@ -952,7 +952,7 @@ class PmsCheckinPartner(models.Model): )[self.id] self.reservation_id.message_post(body=body) - if self.reservation_id.to_send_mail: + if self.reservation_id.to_send_exit_mail: emails = self.reservation_id.checkin_partner_ids.mapped("email") if ( self.reservation_id.partner_id @@ -972,4 +972,4 @@ class PmsCheckinPartner(models.Model): "body_html", [6, 0, self.id], compute_lang=True, post_process=True )[self.id] self.reservation_id.message_post(body=body) - self.reservation_id.to_send_mail = False + self.reservation_id.to_send_exit_mail = False diff --git a/pms/models/pms_folio.py b/pms/models/pms_folio.py index 5ec54f9c0..469b0ae19 100644 --- a/pms/models/pms_folio.py +++ b/pms/models/pms_folio.py @@ -4,11 +4,8 @@ import datetime import logging -from datetime import timedelta from itertools import groupby -from dateutil import relativedelta - from odoo import _, api, fields, models from odoo.exceptions import AccessError, UserError, ValidationError from odoo.tools import float_compare, float_is_zero @@ -204,17 +201,19 @@ class PmsFolio(models.Model): ondelete="restrict", check_pms_properties=True, ) - channel_type_id = fields.Many2one( - string="Direct Sale Channel", - help="Only allowed if the field of sale channel channel_type is 'direct'", - readonly=False, + sale_channel_ids = fields.Many2many( + string="Sale Channels", + help="Sale Channels through which reservations were managed", store=True, + compute="_compute_sale_channel_ids", comodel_name="pms.sale.channel", - domain=[("channel_type", "=", "direct")], - ondelete="restrict", - compute="_compute_channel_type_id", - check_pms_properties=True, ) + sale_channel_origin_id = fields.Many2one( + string="Sale Channel Origin", + help="Sale Channel through which folio was created, the original", + comodel_name="pms.sale.channel", + ) + transaction_ids = fields.Many2many( string="Transactions", help="Payments made through payment acquirer", @@ -623,13 +622,11 @@ class PmsFolio(models.Model): folio_lines_to_invoice = folio.sale_line_ids.filtered( lambda l: l.id in list(lines_to_invoice.keys()) ) - folio_partner_invoice_id = partner_invoice_id - if not folio_partner_invoice_id: - folio_partner_invoice_id = folio._get_default_partner_invoice_id() - + folio._set_default_partner_invoice_id( + folio_lines_to_invoice, partner_invoice_id + ) groups_invoice_lines = folio._get_groups_invoice_lines( lines_to_invoice=folio_lines_to_invoice, - partner_invoice_id=folio_partner_invoice_id, ) for group in groups_invoice_lines: folio = folio.with_company(folio.company_id) @@ -696,60 +693,49 @@ class PmsFolio(models.Model): invoice_vals_list.append(invoice_vals) return invoice_vals_list - def _get_groups_invoice_lines(self, lines_to_invoice, partner_invoice_id): + def _get_groups_invoice_lines(self, lines_to_invoice): self.ensure_one() - target_lines = lines_to_invoice - if self._context.get("lines_auto_add") and partner_invoice_id: - folio_partner_invoice = self.env["res.partner"].browse(partner_invoice_id) - if folio_partner_invoice.default_invoice_lines == "overnights": - target_lines = target_lines.filtered( - lambda r: r.is_board_service - or (r.reservation_line_ids and r.reservation_id.overnight_room) - ) - elif folio_partner_invoice.default_invoice_lines == "reservations": - target_lines = target_lines.filtered( - lambda r: r.is_board_service or r.reservation_line_ids - ) - elif folio_partner_invoice.default_invoice_lines == "services": - target_lines = target_lines.filtered( - lambda r: not r.is_board_service or r.service_line_ids - ) - groups_invoice_lines = [ - { - "partner_id": partner_invoice_id, - "lines": target_lines, - } - ] - if ( - self.autoinvoice_date - and self.autoinvoice_date <= fields.Date.today() - and len(target_lines) < len(lines_to_invoice) - ): - other_partner_to_invoice = self.partner_invoice_ids.filtered( - lambda p: p.id != partner_invoice_id - ) - if not other_partner_to_invoice: - other_partner_to_invoice = self.env.ref("pms.various_pms_partner") + groups_invoice_lines = [] + partners = lines_to_invoice.mapped("default_invoice_to") + for partner in partners: groups_invoice_lines.append( { - "partner_id": other_partner_to_invoice.id, - "lines": lines_to_invoice - target_lines, + "partner_id": partner.id, + "lines": lines_to_invoice.filtered( + lambda l: l.default_invoice_to == partner + ), } ) return groups_invoice_lines - def _get_default_partner_invoice_id(self): + def _set_default_partner_invoice_id( + self, lines_to_invoice, folio_partner_invoice_id=False + ): + # By priotiy: + # 1º- Partner set in parameter, + # 2º- Partner in default_invoice_to in line + # 3º- Partner in folio, + # 4º- Partner in checkins, + # 5º- Generic various partner self.ensure_one() - folio_partner_invoice_id = False - if self.partner_id and self.partner_id.vat: - folio_partner_invoice_id = self.partner_id.id - if not folio_partner_invoice_id: - folio_partner_invoice_id = ( - self.partner_invoice_ids[0].id if self.partner_invoice_ids else False + for line in lines_to_invoice: + if not folio_partner_invoice_id and line.default_invoice_to: + folio_partner_invoice_id = line.default_invoice_to + if ( + not folio_partner_invoice_id + and self.partner_id + and self.partner_id._check_enought_invoice_data() + and not self.partner_id.is_agency + ): + folio_partner_invoice_id = self.partner_id.id + checkin_invoice_partner = self.checkin_partner_ids.filtered( + lambda c: c.partner_id and c.partner_id._check_enought_invoice_data() ) - if not folio_partner_invoice_id: - folio_partner_invoice_id = self.env.ref("pms.various_pms_partner").id - return folio_partner_invoice_id + if not folio_partner_invoice_id and checkin_invoice_partner: + folio_partner_invoice_id = checkin_invoice_partner[0].partner_id + if not folio_partner_invoice_id: + folio_partner_invoice_id = self.env.ref("pms.various_pms_partner").id + line.default_invoice_to = folio_partner_invoice_id def _get_tax_amount_by_group(self): self.ensure_one() @@ -787,42 +773,6 @@ class PmsFolio(models.Model): else: return False - @api.depends("partner_id", "invoice_status", "last_checkout", "partner_invoice_ids") - def _compute_autoinvoice_date(self): - self.autoinvoice_date = False - for record in self.filtered(lambda r: r.invoice_status == "to_invoice"): - record.autoinvoice_date = record._get_to_invoice_date() - - def _get_to_invoice_date(self): - self.ensure_one() - partner = self.partner_id - invoicing_policy = ( - self.pms_property_id.default_invoicing_policy - if not partner or partner.invoicing_policy == "property" - else partner.invoicing_policy - ) - if invoicing_policy == "manual": - return False - if invoicing_policy == "checkout": - margin_days = ( - self.pms_property_id.margin_days_autoinvoice - if not partner or partner.invoicing_policy == "property" - else partner.margin_days_autoinvoice - ) - return self.last_checkout + timedelta(days=margin_days) - if invoicing_policy == "month_day": - month_day = ( - self.pms_property_id.invoicing_month_day - if not partner or partner.invoicing_policy == "property" - else partner.invoicing_month_day - ) - if self.last_checkout.day <= month_day: - self.autoinvoice_date = self.last_checkout.replace(day=month_day) - else: - self.autoinvoice_date = ( - self.last_checkout + relativedelta.relativedelta(months=1) - ).replace(day=month_day) - @api.depends("reservation_ids", "reservation_ids.state") def _compute_number_of_rooms(self): for folio in self: @@ -846,6 +796,7 @@ class PmsFolio(models.Model): "reservation_ids", "service_ids", "service_ids.reservation_id", + "service_ids.default_invoice_to", "service_ids.service_line_ids.price_day_total", "service_ids.service_line_ids.discount", "service_ids.service_line_ids.cancel_discount", @@ -855,6 +806,7 @@ class PmsFolio(models.Model): "reservation_ids.reservation_line_ids.price", "reservation_ids.reservation_line_ids.discount", "reservation_ids.reservation_line_ids.cancel_discount", + "reservation_ids.reservation_line_ids.default_invoice_to", "reservation_ids.tax_ids", ) def _compute_sale_line_ids(self): @@ -1048,11 +1000,23 @@ class PmsFolio(models.Model): if reservation.commission_amount != 0: folio.commission = folio.commission + reservation.commission_amount - @api.depends("agency_id") - def _compute_channel_type_id(self): - for folio in self: - if folio.agency_id: - folio.channel_type_id = folio.agency_id.sale_channel_id.id + @api.depends( + "reservation_ids", + "reservation_ids.sale_channel_ids", + "service_ids", + "service_ids.sale_channel_origin_id", + ) + def _compute_sale_channel_ids(self): + for record in self: + sale_channel_ids = [] + if record.reservation_ids: + for sale in record.reservation_ids.mapped("sale_channel_ids.id"): + sale_channel_ids.append(sale) + if record.service_ids: + for sale in record.service_ids.mapped("sale_channel_origin_id.id"): + sale_channel_ids.append(sale) + sale_channel_ids = list(set(sale_channel_ids)) + record.sale_channel_ids = [(6, 0, sale_channel_ids)] @api.depends("sale_line_ids.invoice_lines") def _compute_get_invoiced(self): @@ -1427,7 +1391,7 @@ class PmsFolio(models.Model): record.days_to_checkin = (record.first_checkin - fields.Date.today()).days def _search_days_to_checkin(self, operator, value): - target_date = fields.Date.today() + timedelta(days=value) + target_date = fields.Date.today() + datetime.timedelta(days=value) if operator in ("=", ">=", ">", "<=", "<"): return [("first_checkin", operator, target_date)] raise UserError( @@ -1446,7 +1410,7 @@ class PmsFolio(models.Model): record.days_to_checkout = (record.last_checkout - fields.Date.today()).days def _search_days_to_checkout(self, operator, value): - target_date = fields.Date.today() + timedelta(days=value) + target_date = fields.Date.today() + datetime.timedelta(days=value) if operator in ("=", ">=", ">", "<=", "<"): return [("last_checkout", operator, target_date)] raise UserError( @@ -1491,18 +1455,6 @@ class PmsFolio(models.Model): ("sale_line_ids.invoice_lines.move_id", operator, value), ] - @api.constrains("agency_id", "channel_type_id") - def _check_only_one_channel(self): - for record in self: - if ( - record.agency_id - and record.channel_type_id.channel_type - != record.agency_id.sale_channel_id.channel_type - ): - raise models.ValidationError( - _("The Sale Channel does not correspond to the agency's") - ) - @api.constrains("name") def _check_required_partner_name(self): for record in self: @@ -1523,6 +1475,52 @@ class PmsFolio(models.Model): result.access_token = result._portal_ensure_token() return result + def write(self, vals): + reservations_to_update = self.env["pms.reservation"] + services_to_update = self.env["pms.service"] + if "sale_channel_origin_id" in vals: + reservations_to_update = self.get_reservations_to_update_channel(vals) + services_to_update = self.get_services_to_update_channel(vals) + + res = super(PmsFolio, self).write(vals) + if reservations_to_update: + reservations_to_update.sale_channel_origin_id = vals[ + "sale_channel_origin_id" + ] + + if services_to_update: + services_to_update.sale_channel_origin_id = vals["sale_channel_origin_id"] + + return res + + def get_reservations_to_update_channel(self, vals): + reservations_to_update = self.env["pms.reservation"] + for record in self: + for reservation in record.reservation_ids: + if ( + reservation.sale_channel_origin_id == self.sale_channel_origin_id + ) and ( + vals["sale_channel_origin_id"] + != reservation.sale_channel_origin_id.id + ): + reservations_to_update += reservation + return reservations_to_update + + def get_services_to_update_channel(self, vals): + services_to_update = self.env["pms.service"] + for record in self: + for service in record.service_ids: + if ( + not service.reservation_id + and (service.sale_channel_origin_id == self.sale_channel_origin_id) + and ( + vals["sale_channel_origin_id"] + != service.sale_channel_origin_id.id + ) + ): + services_to_update += service + return services_to_update + def action_pay(self): self.ensure_one() self.ensure_one() @@ -1860,9 +1858,17 @@ class PmsFolio(models.Model): self = self.with_context(lines_auto_add=True) lines_to_invoice = dict() for line in self.sale_line_ids: - lines_to_invoice[line.id] = ( - 0 if line.display_type else line.qty_to_invoice - ) + if not self._context.get("autoinvoice"): + lines_to_invoice[line.id] = ( + 0 if line.display_type else line.qty_to_invoice + ) + elif ( + line.autoinvoice_date + and line.autoinvoice_date <= fields.Date.today() + ): + lines_to_invoice[line.id] = ( + 0 if line.display_type else line.qty_to_invoice + ) invoice_vals_list = self.get_invoice_vals_list( final=final, lines_to_invoice=lines_to_invoice, @@ -2325,8 +2331,8 @@ class PmsFolio(models.Model): ("reservation_id", "=", reservation.id), ("cancel_discount", "<", 100), ], - ["price", "discount", "cancel_discount"], - ["price", "discount", "cancel_discount"], + ["price", "discount", "cancel_discount", "default_invoice_to"], + ["price", "discount", "cancel_discount", "default_invoice_to"], lazy=False, ) current_sale_line_ids = reservation.sale_line_ids.filtered( @@ -2341,13 +2347,17 @@ class PmsFolio(models.Model): final_discount = self.concat_discounts( item["discount"], item["cancel_discount"] ) - + partner_invoice = lines_to.mapped("default_invoice_to") if current_sale_line_ids and index <= (len(current_sale_line_ids) - 1): + current = { "price_unit": item["price"], "discount": final_discount, "reservation_line_ids": [(6, 0, lines_to.ids)], "sequence": sequence, + "default_invoice_to": partner_invoice[0].id + if partner_invoice + else current_sale_line_ids[index].default_invoice_to, } sale_reservation_vals.append( (1, current_sale_line_ids[index].id, current) @@ -2362,6 +2372,9 @@ class PmsFolio(models.Model): "tax_ids": [(6, 0, reservation.tax_ids.ids)], "reservation_line_ids": [(6, 0, lines_to.ids)], "sequence": sequence, + "default_invoice_to": partner_invoice[0].id + if partner_invoice + else False, } sale_reservation_vals.append((0, 0, new)) folio_sale_lines_to_remove = [] @@ -2384,8 +2397,8 @@ class PmsFolio(models.Model): ("service_id", "=", service.id), ("cancel_discount", "<", 100), ], - ["price_unit", "discount", "cancel_discount"], - ["price_unit", "discount", "cancel_discount"], + ["price_unit", "discount", "cancel_discount", "default_invoice_to"], + ["price_unit", "discount", "cancel_discount", "default_invoice_to"], lazy=False, ) current_sale_service_ids = reservation.sale_line_ids.filtered( @@ -2399,7 +2412,7 @@ class PmsFolio(models.Model): final_discount = self.concat_discounts( item["discount"], item["cancel_discount"] ) - + partner_invoice = lines_to.mapped("default_invoice_to") if current_sale_service_ids and index <= ( len(current_sale_service_ids) - 1 ): @@ -2408,6 +2421,9 @@ class PmsFolio(models.Model): "discount": final_discount, "service_line_ids": [(6, 0, lines_to.ids)], "sequence": sequence, + "default_invoice_to": partner_invoice[0].id + if partner_invoice + else current_sale_service_ids[index].default_invoice_to, } sale_service_vals.append( (1, current_sale_service_ids[index].id, current) @@ -2423,6 +2439,9 @@ class PmsFolio(models.Model): "product_id": service.product_id.id, "tax_ids": [(6, 0, service.tax_ids.ids)], "sequence": sequence, + "default_invoice_to": partner_invoice[0].id + if partner_invoice + else False, } sale_service_vals.append((0, 0, new)) sequence = sequence + 1 diff --git a/pms/models/pms_property.py b/pms/models/pms_property.py index 288677dac..13948ef83 100644 --- a/pms/models/pms_property.py +++ b/pms/models/pms_property.py @@ -607,7 +607,7 @@ class PmsProperty(models.Model): """ folios = self.env["pms.folio"].search( [ - ("autoinvoice_date", "=", fields.date.today()), + ("sale_line_ids.autoinvoice_date", "=", fields.date.today()), ("invoice_status", "=", "to_invoice"), ] ) diff --git a/pms/models/pms_reservation.py b/pms/models/pms_reservation.py index 94ee17dd0..1b4f10ca8 100644 --- a/pms/models/pms_reservation.py +++ b/pms/models/pms_reservation.py @@ -124,13 +124,33 @@ class PmsReservation(models.Model): depends=["folio_id.agency_id"], tracking=True, ) - channel_type_id = fields.Many2one( - string="Channel Type", - help="Sales Channel through which the reservation was managed", - readonly=False, + sale_channel_ids = fields.Many2many( + string="Sale Channels", + help="Sale Channels through which reservation lines were managed", store=True, - related="folio_id.channel_type_id", - tracking=True, + compute="_compute_sale_channel_ids", + comodel_name="pms.sale.channel", + ) + sale_channel_origin_id = fields.Many2one( + string="Sale Channel Origin", + help="Sale Channel through which reservation was created, the original", + default=lambda self: self._get_default_sale_channel_origin(), + comodel_name="pms.sale.channel", + ) + force_update_origin = fields.Boolean( + string="Update Sale Channel Origin", + help="This field is for force update in sale channel " + "origin of folio and another reservations", + store=True, + readonly=False, + compute="_compute_force_update_origin", + ) + is_origin_channel_check_visible = fields.Boolean( + string="Check force update origin visible", + help="Technical field to make visible update " "origin channel check", + store=True, + readonly=False, + compute="_compute_is_origin_channel_check_visible", ) closure_reason_id = fields.Many2one( string="Closure Reason", @@ -1314,7 +1334,13 @@ class PmsReservation(models.Model): reservation.preferred_room_id = False else: reservation.splitted = False - if room_ids: + # Set automatically preferred_room_id if, and only if, + # all nights has the same room + if ( + len(room_ids) == 1 + and len(reservation.reservation_line_ids) + == (reservation.checkout - reservation.checkin).days + ): reservation.preferred_room_id = room_ids[0] @api.depends( @@ -1608,6 +1634,50 @@ class PmsReservation(models.Model): else: record.lang = self.env["res.lang"].get_installed() + @api.depends( + "reservation_line_ids", + "reservation_line_ids.sale_channel_id", + "service_ids", + "service_ids.sale_channel_origin_id", + ) + def _compute_sale_channel_ids(self): + for record in self: + sale_channel_ids = [] + if record.reservation_line_ids: + for sale in record.reservation_line_ids.mapped("sale_channel_id.id"): + sale_channel_ids.append(sale) + if record.service_ids: + for sale in record.service_ids.mapped("sale_channel_origin_id.id"): + sale_channel_ids.append(sale) + sale_channel_ids = list(set(sale_channel_ids)) + record.sale_channel_ids = [(6, 0, sale_channel_ids)] + + @api.depends("agency_id") + def _compute_sale_channel_origin_id(self): + for record in self: + # if record.folio_id.sale_channel_origin_id and not record.sale_channel_origin_id: + # record.sale_channel_origin_id = record.folio_id.sale_channel_origin_id + if record.agency_id: + record.sale_channel_origin_id = record.agency_id.sale_channel_id + + @api.depends("sale_channel_origin_id") + def _compute_is_origin_channel_check_visible(self): + for record in self: + if ( + record.sale_channel_origin_id != record.folio_id.sale_channel_origin_id + and record.folio_id + # and isinstance(self.id, int) + and record._origin.sale_channel_origin_id.id + ): + record.is_origin_channel_check_visible = True + else: + record.is_origin_channel_check_visible = False + + @api.depends("sale_channel_origin_id") + def _compute_force_update_origin(self): + for record in self: + record.force_update_origin = True + def _search_allowed_checkin(self, operator, value): if operator not in ("=",): raise UserError( @@ -1674,6 +1744,17 @@ class PmsReservation(models.Model): segmentation_ids = folio.segmentation_ids return segmentation_ids + def _get_default_sale_channel_origin(self): + folio = False + sale_channel_origin_id = False + if "default_folio_id" in self._context: + folio = self.env["pms.folio"].search( + [("id", "=", self._context["default_folio_id"])] + ) + if folio and folio.sale_channel_origin_id: + sale_channel_origin_id = folio.sale_channel_origin_id + return sale_channel_origin_id + def check_in_out_dates(self): """ 1.-When date_order is less then checkin date or @@ -1812,6 +1893,19 @@ class PmsReservation(models.Model): ) ) + @api.constrains("sale_channel_ids") + def _check_lines_with_sale_channel_id(self): + for record in self.filtered("sale_channel_origin_id"): + if record.reservation_line_ids: + if record.sale_channel_origin_id not in record.sale_channel_ids: + raise ValidationError( + _( + "Reservation must have one reservation line " + "with sale channel equal to sale channel origin of reservation." + "Change sale_channel_origin of reservation before" + ) + ) + # Action methods def open_partner(self): """Utility method used to add an "View Customer" button in reservation views""" @@ -1942,36 +2036,23 @@ class PmsReservation(models.Model): default_vals["email"] = folio.email elif vals.get("reservation_type") != "out": raise ValidationError(_("Partner contact name is required")) + if folio.sale_channel_origin_id and "sale_channel_origin_id" not in vals: + default_vals["sale_channel_origin_id"] = folio.sale_channel_origin_id.id vals.update(default_vals) - elif "pms_property_id" in vals and ( - "partner_name" in vals or "partner_id" in vals or "agency_id" in vals + elif ( + "pms_property_id" in vals + and "sale_channel_origin_id" in vals + and ("partner_name" in vals or "partner_id" in vals or "agency_id" in vals) ): - folio_vals = { - "pms_property_id": vals["pms_property_id"], - } - if vals.get("partner_id"): - folio_vals["partner_id"] = vals.get("partner_id") - elif vals.get("agency_id"): - folio_vals["agency_id"] = vals.get("agency_id") - elif vals.get("partner_name"): - folio_vals["partner_name"] = vals.get("partner_name") - folio_vals["mobile"] = vals.get("mobile") - folio_vals["email"] = vals.get("email") - elif vals.get("reservation_type") != "out": - raise ValidationError(_("Partner contact name is required")) + folio_vals = self._get_folio_vals(vals) + + self._check_clousure_reason( + reservation_type=vals.get("reservation_type"), + closure_reason_id=vals.get("closure_reason_id"), + ) + # Create the folio in case of need # (To allow to create reservations direct) - if vals.get("reservation_type"): - folio_vals["reservation_type"] = vals.get("reservation_type") - if vals.get("reservation_type") == "out" and not vals.get( - "closure_reason_id" - ): - raise ValidationError( - _( - "A closure reason is mandatory when reservation" - " type is 'out of service'" - ) - ) folio = self.env["pms.folio"].create(folio_vals) vals.update( { @@ -1981,7 +2062,11 @@ class PmsReservation(models.Model): ) else: - raise ValidationError(_("The Property are mandatory in the reservation")) + raise ValidationError( + _( + "The Property and Sale Channel Origin are mandatory in the reservation" + ) + ) if vals.get("name", _("New")) == _("New") or "name" not in vals: folio_sequence = ( max(folio.mapped("reservation_ids.folio_sequence")) + 1 @@ -2004,13 +2089,62 @@ class PmsReservation(models.Model): return record def write(self, vals): - asset = super(PmsReservation, self).write(vals) + folios_to_update_channel = self.env["pms.folio"] + lines_to_update_channel = self.env["pms.reservation.line"] + services_to_update_channel = self.env["pms.service"] + if "sale_channel_origin_id" in vals: + folios_to_update_channel = self.get_folios_to_update_channel(vals) + lines_to_update_channel = self.get_lines_to_update_channel(vals) + services_to_update_channel = self.get_services_to_update_channel(vals) + res = super(PmsReservation, self).write(vals) + if folios_to_update_channel: + folios_to_update_channel.sale_channel_origin_id = vals[ + "sale_channel_origin_id" + ] + if lines_to_update_channel: + lines_to_update_channel.sale_channel_id = vals["sale_channel_origin_id"] + if services_to_update_channel: + services_to_update_channel.sale_channel_origin_id = vals[ + "sale_channel_origin_id" + ] + self._check_services(vals) # Only check if adult to avoid to check capacity in intermediate states (p.e. flush) # that not take access to possible extra beds service in vals if "adults" in vals: self._check_capacity() - return asset + return res + + def _get_folio_vals(self, reservation_vals): + folio_vals = { + "pms_property_id": reservation_vals["pms_property_id"], + } + if reservation_vals.get("sale_channel_origin_id"): + folio_vals["sale_channel_origin_id"] = reservation_vals.get( + "sale_channel_origin_id" + ) + if reservation_vals.get("partner_id"): + folio_vals["partner_id"] = reservation_vals.get("partner_id") + elif reservation_vals.get("agency_id"): + folio_vals["agency_id"] = reservation_vals.get("agency_id") + elif reservation_vals.get("partner_name"): + folio_vals["partner_name"] = reservation_vals.get("partner_name") + folio_vals["mobile"] = reservation_vals.get("mobile") + folio_vals["email"] = reservation_vals.get("email") + elif reservation_vals.get("reservation_type") != "out": + raise ValidationError(_("Partner contact name is required")) + if reservation_vals.get("reservation_type"): + folio_vals["reservation_type"] = reservation_vals.get("reservation_type") + return folio_vals + + def _check_clousure_reason(self, reservation_type, closure_reason_id): + if reservation_type == "out" and not closure_reason_id: + raise ValidationError( + _( + "A closure reason is mandatory when reservation" + " type is 'out of service'" + ) + ) def _check_services(self, vals): # If we create a reservation with board service and other service at the same time, @@ -2019,6 +2153,47 @@ class PmsReservation(models.Model): if "board_service_room_id" in vals and "service_ids" in vals: self._compute_service_ids() + def get_folios_to_update_channel(self, vals): + folios_to_update_channel = self.env["pms.folio"] + for folio in self.mapped("folio_id"): + if ( + any( + res.sale_channel_origin_id == folio.sale_channel_origin_id + for res in self.filtered(lambda r: r.folio_id == folio) + ) + and vals["sale_channel_origin_id"] != folio.sale_channel_origin_id.id + and ( + ("force_update_origin" in vals and vals.get("force_update_origin")) + or len(folio.reservation_ids) == 1 + ) + ): + folios_to_update_channel += folio + return folios_to_update_channel + + def get_lines_to_update_channel(self, vals): + lines_to_update_channel = self.env["pms.reservation.line"] + for record in self: + for line in record.reservation_line_ids: + if line.sale_channel_id == record.sale_channel_origin_id and ( + vals["sale_channel_origin_id"] != line.sale_channel_id.id + ): + lines_to_update_channel += line + return lines_to_update_channel + + def get_services_to_update_channel(self, vals): + services_to_update_channel = self.env["pms.service"] + for record in self: + for service in record.service_ids: + if ( + service.sale_channel_origin_id == record.sale_channel_origin_id + and ( + vals["sale_channel_origin_id"] + != service.sale_channel_origin_id.id + ) + ): + services_to_update_channel += service + return services_to_update_channel + def update_prices(self): self.ensure_one() for line in self.reservation_line_ids: diff --git a/pms/models/pms_reservation_line.py b/pms/models/pms_reservation_line.py index aa64e0d1b..19a7d1fcc 100644 --- a/pms/models/pms_reservation_line.py +++ b/pms/models/pms_reservation_line.py @@ -45,8 +45,7 @@ class PmsReservationLine(models.Model): ) pms_property_id = fields.Many2one( string="Property", - help="Property with access to the element;" - " if not set, all properties can access", + help="Property with access to the element", readonly=True, store=True, comodel_name="pms.property", @@ -113,6 +112,24 @@ class PmsReservationLine(models.Model): readonly=False, compute="_compute_overbooking", ) + sale_channel_id = fields.Many2one( + string="Sale Channel", + help="Sale Channel through which reservation line was created", + comodel_name="pms.sale.channel", + check_pms_properties=True, + ) + default_invoice_to = fields.Many2one( + string="Invoice to", + help="""Indicates the contact to which this line will be + billed by default, if it is not established, + a guest or the generic contact will be used instead""", + readonly=False, + store=True, + compute="_compute_default_invoice_to", + comodel_name="res.partner", + ondelete="restrict", + ) + _sql_constraints = [ ( "rule_availability", @@ -480,9 +497,19 @@ class PmsReservationLine(models.Model): @api.model_create_multi def create(self, vals_list): + for vals in vals_list: + if vals.get("reservation_id") and not vals.get("sale_channel_id"): + reservation = self.env["pms.reservation"].browse( + vals.get("reservation_id") + ) + vals["sale_channel_id"] = reservation.sale_channel_origin_id.id records = super().create(vals_list) for line in records: reservation = line.reservation_id + # Set default channel + if not line.sale_channel_id: + line.sale_channel_id = reservation.sale_channel_origin_id.id + # Update quota self.env["pms.availability.plan"].update_quota( pricelist_id=reservation.pricelist_id.id, room_type_id=reservation.room_type_id.id, @@ -491,6 +518,19 @@ class PmsReservationLine(models.Model): ) return records + @api.depends("sale_channel_id", "reservation_id.agency_id") + def _compute_default_invoice_to(self): + for record in self: + agency = record.reservation_id.agency_id + if ( + agency + and agency.invoice_to_agency == "always" + and agency.sale_channel_id == record.sale_channel_id + ): + record.default_invoice_to = agency + elif not record.default_invoice_to: + record.default_invoice_to = False + # Constraints and onchanges @api.constrains("date") def constrains_duplicated_date(self): diff --git a/pms/models/pms_service.py b/pms/models/pms_service.py index 36111a3e0..b80a5251d 100644 --- a/pms/models/pms_service.py +++ b/pms/models/pms_service.py @@ -146,17 +146,11 @@ class PmsService(models.Model): ("no", "Nothing to Invoice"), ], ) - channel_type = fields.Selection( - string="Sales Channel", - help="sales channel through which the service was sold." - "It can be 'door', 'mail', 'phone', 'call' or 'web'", - selection=[ - ("door", "Door"), - ("mail", "Mail"), - ("phone", "Phone"), - ("call", "Call Center"), - ("web", "Web"), - ], + sale_channel_origin_id = fields.Many2one( + string="Sale Channel Origin", + help="Sale Channel through which service was created, the original", + comodel_name="pms.sale.channel", + check_pms_properties=True, ) price_subtotal = fields.Monetary( string="Subtotal", @@ -197,6 +191,17 @@ class PmsService(models.Model): """, default=False, ) + default_invoice_to = fields.Many2one( + string="Invoice to", + help="""Indicates the contact to which this line will be + billed by default, if it is not established, + a guest or the generic contact will be used instead""", + readonly=False, + store=True, + compute="_compute_default_invoice_to", + comodel_name="res.partner", + ondelete="restrict", + ) # Compute and Search methods @api.depends("product_id") @@ -425,6 +430,19 @@ class PmsService(models.Model): line.discount = record.discount line.cancel_discount = 0 + @api.depends("sale_channel_origin_id", "folio_id.agency_id") + def _compute_default_invoice_to(self): + for record in self: + agency = record.folio_id.agency_id + if ( + agency + and agency.invoice_to_agency == "always" + and agency.sale_channel_id == record.sale_channel_origin_id + ): + record.default_invoice_to = agency + elif not record.default_invoice_to: + record.default_invoice_to = False + def name_get(self): result = [] for rec in self: @@ -534,3 +552,49 @@ class PmsService(models.Model): ) else: return 0 + + @api.model + def create(self, vals): + if vals.get("reservation_id") and not vals.get("sale_channel_origin_id"): + reservation = self.env["pms.reservation"].browse(vals["reservation_id"]) + if reservation.sale_channel_origin_id: + vals["sale_channel_origin_id"] = reservation.sale_channel_origin_id.id + elif ( + vals.get("folio_id") + and not vals.get("reservation_id") + and not vals.get("sale_channel_origin_id") + ): + folio = self.env["pms.folio"].browse(vals["folio_id"]) + if folio.sale_channel_origin_id: + vals["sale_channel_origin_id"] = folio.sale_channel_origin_id.id + record = super(PmsService, self).create(vals) + return record + + def write(self, vals): + folios_to_update_channel = self.env["pms.folio"] + lines_to_update_channel = self.env["pms.service.line"] + if "sale_channel_origin_id" in vals: + folios_to_update_channel = self.get_folios_to_update_channel(vals) + res = super(PmsService, self).write(vals) + if folios_to_update_channel: + folios_to_update_channel.sale_channel_origin_id = vals[ + "sale_channel_origin_id" + ] + if lines_to_update_channel: + lines_to_update_channel.sale_channel_id = vals["sale_channel_origin_id"] + return res + + def get_folios_to_update_channel(self, vals): + folios_to_update_channel = self.env["pms.folio"] + for folio in self.mapped("folio_id"): + if ( + any( + service.sale_channel_origin_id == folio.sale_channel_origin_id + for service in self.filtered(lambda r: r.folio_id == folio) + ) + and vals["sale_channel_origin_id"] != folio.sale_channel_origin_id.id + and (len(folio.reservation_ids) == 0) + and (len(folio.service_ids) == 1) + ): + folios_to_update_channel += folio + return folios_to_update_channel diff --git a/pms/models/pms_service_line.py b/pms/models/pms_service_line.py index 11933b16d..f8e15648d 100644 --- a/pms/models/pms_service_line.py +++ b/pms/models/pms_service_line.py @@ -133,6 +133,16 @@ class PmsServiceLine(models.Model): readonly=False, store=True, ) + default_invoice_to = fields.Many2one( + string="Invoice to", + help="""Indicates the contact to which this line will be + billed by default, if it is not established, + a guest or the generic contact will be used instead""", + comodel_name="res.partner", + store=True, + related="service_id.default_invoice_to", + ondelete="restrict", + ) @api.depends("day_qty", "discount", "price_unit", "tax_ids") def _compute_day_amount_service(self): diff --git a/pms/models/res_company.py b/pms/models/res_company.py index a04be518d..f44d9effa 100644 --- a/pms/models/res_company.py +++ b/pms/models/res_company.py @@ -25,5 +25,5 @@ class ResCompany(models.Model): string="Check minimum partner data for invoices", help="""Check minimum partner data for invoices: - VAT, name, street, city, country""", - default=True, + default=False, ) diff --git a/pms/models/res_partner.py b/pms/models/res_partner.py index df0de86e9..1f1ba3d97 100644 --- a/pms/models/res_partner.py +++ b/pms/models/res_partner.py @@ -192,22 +192,6 @@ class ResPartner(models.Model): string="Days from Checkout", help="Days from Checkout to generate the invoice", ) - default_invoice_lines = fields.Selection( - string="Invoice...", - help="""Use to preconfigure the sale lines to autoinvoice - for this partner. All (invoice reservations and services), - Only overnights to invoice only the reservations - with overnight and board services(exclude parkings, salon, etc...), - All reservations to include all reservations, - and Services only include services not boards""", - selection=[ - ("all", "All"), - ("overnights", "Only Overnights"), - ("reservations", "All reservations"), - ("services", "Services"), - ], - default="all", - ) vat_document_type = fields.Selection( string="Document Type", help="""The vat document type of the partner, diff --git a/pms/tests/__init__.py b/pms/tests/__init__.py index b7730751d..4d084fc6c 100644 --- a/pms/tests/__init__.py +++ b/pms/tests/__init__.py @@ -40,3 +40,4 @@ from . import test_pms_multiproperty from . import test_shared_room # from . import test_automated_mails +from . import test_pms_service diff --git a/pms/tests/test_pms_availability_plan_rules.py b/pms/tests/test_pms_availability_plan_rules.py index 3bb5c2c62..58fc94ab6 100644 --- a/pms/tests/test_pms_availability_plan_rules.py +++ b/pms/tests/test_pms_availability_plan_rules.py @@ -25,7 +25,13 @@ class TestPmsRoomTypeAvailabilityRules(TestPms): ], } ) - + # pms.sale.channel + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) # pms.availability.plan self.test_room_type_availability1 = self.env["pms.availability.plan"].create( { @@ -164,6 +170,7 @@ class TestPmsRoomTypeAvailabilityRules(TestPms): "checkout": checkout, "partner_id": self.partner1.id, "room_type_id": room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) result = self.test_room_type_availability_rule1.plan_avail @@ -209,6 +216,7 @@ class TestPmsRoomTypeAvailabilityRules(TestPms): "checkout": checkout, "partner_id": self.partner1.id, "room_type_id": room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) self.env["pms.reservation"].create( @@ -218,6 +226,7 @@ class TestPmsRoomTypeAvailabilityRules(TestPms): "checkout": checkout, "partner_id": self.partner1.id, "room_type_id": room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) result = self.test_room_type_availability_rule1.plan_avail @@ -258,6 +267,7 @@ class TestPmsRoomTypeAvailabilityRules(TestPms): "checkin": checkin, "checkout": checkout, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -586,6 +596,7 @@ class TestPmsRoomTypeAvailabilityRules(TestPms): "room_type_id": self.test_room_type_double.id, "pricelist_id": self.pricelist2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() diff --git a/pms/tests/test_pms_checkin_partner.py b/pms/tests/test_pms_checkin_partner.py index 1db2b4ac1..9476ad1fb 100644 --- a/pms/tests/test_pms_checkin_partner.py +++ b/pms/tests/test_pms_checkin_partner.py @@ -57,9 +57,13 @@ class TestPmsCheckinPartner(TestPms): "gender": "male", } ) - self.id_category = self.env["res.partner.id_category"].create( - {"name": "DNI", "code": "D"} + self.id_category = self.env["res.partner.id_category"].search( + [("code", "=", "D")] ) + if not self.id_category: + self.id_category = self.env["res.partner.id_category"].create( + {"name": "DNI", "code": "D"} + ) self.env["res.partner.id_number"].create( { "category_id": self.id_category.id, @@ -68,6 +72,12 @@ class TestPmsCheckinPartner(TestPms): "partner_id": self.host1.id, } ) + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) reservation_vals = { "checkin": datetime.date.today(), "checkout": datetime.date.today() + datetime.timedelta(days=3), @@ -75,6 +85,7 @@ class TestPmsCheckinPartner(TestPms): "partner_id": self.host1.id, "adults": 3, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } self.reservation_1 = self.env["pms.reservation"].create(reservation_vals) self.checkin1 = self.env["pms.checkin.partner"].create( @@ -1091,6 +1102,7 @@ class TestPmsCheckinPartner(TestPms): "pms_property_id": self.pms_property1.id, "partner_name": partner.name, "email": partner.email, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ACT @@ -1133,6 +1145,7 @@ class TestPmsCheckinPartner(TestPms): "room_type_id": self.room_type1.id, "pms_property_id": self.pms_property1.id, "partner_name": partner.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ACT @@ -1178,6 +1191,7 @@ class TestPmsCheckinPartner(TestPms): "room_type_id": self.room_type1.id, "pms_property_id": self.pms_property1.id, "partner_name": partner.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) checkin = self.env["pms.checkin.partner"].create( @@ -1239,6 +1253,7 @@ class TestPmsCheckinPartner(TestPms): "room_type_id": self.room_type1.id, "pms_property_id": self.pms_property1.id, "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -1286,6 +1301,7 @@ class TestPmsCheckinPartner(TestPms): "room_type_id": self.room_type1.id, "pms_property_id": self.pms_property1.id, "partner_name": "Rosa Costa", + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) checkin = self.env["pms.checkin.partner"].create( @@ -1539,6 +1555,7 @@ class TestPmsCheckinPartner(TestPms): "partner_id": self.host1.id, "adults": 1, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) checkin_partner_id = self.reservation.checkin_partner_ids[0] @@ -1596,6 +1613,7 @@ class TestPmsCheckinPartner(TestPms): "partner_id": self.host1.id, "adults": 1, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) checkin_partner_id = self.reservation.checkin_partner_ids[0] diff --git a/pms/tests/test_pms_folio.py b/pms/tests/test_pms_folio.py index 52704bfc8..3d94959ac 100644 --- a/pms/tests/test_pms_folio.py +++ b/pms/tests/test_pms_folio.py @@ -55,6 +55,14 @@ class TestPmsFolio(TestPms): ) journals.allowed_pms_payments = True + # create sale channel direct + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) + def create_sale_channel_scenario(self): """ Method to simplified scenario on sale channel tests: @@ -410,6 +418,7 @@ class TestPmsFolio(TestPms): "adults": 2, "partner_id": self.env.ref("base.res_partner_12").id, "room_type_id": self.demo_room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -456,6 +465,7 @@ class TestPmsFolio(TestPms): "adults": 2, "partner_id": self.env.ref("base.res_partner_12").id, "room_type_id": self.demo_room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -542,6 +552,7 @@ class TestPmsFolio(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "reservation_type": "staff", + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -582,6 +593,7 @@ class TestPmsFolio(TestPms): "pricelist_id": self.pricelist1.id, "reservation_type": "out", "closure_reason_id": closure_reason.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -1108,3 +1120,419 @@ class TestPmsFolio(TestPms): folio1.partner_invoice_ids.ids, "A checkin partner was not added as a billing contact", ) + + @freeze_time("2001-10-10") + def test_folio_sale_channel_origin_in_reservation(self): + """ + Check that the reservation has sale_channel_origin_id + as the folio sale_channel_origin_id in + which reservation was created + + When a reservation is created on a folio + that already has a sale_channel_origin + that reservation will have the same sale_channel_origin + + """ + # ARRANGE + partner1 = self.env["res.partner"].create({"name": "partner1"}) + folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, + } + ) + # ACT + reservation1 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + # ASSERT + self.assertEqual( + reservation1.sale_channel_origin_id.id, + folio1.sale_channel_origin_id.id, + "Sale channel of reservation must be the same that it folio", + ) + + @freeze_time("2001-10-19") + def test_folio_sale_channel_ids(self): + """ + Check if sale_channel_ids of folio correspond to + sale_channel_origin_id of its reservations at the + time of creating a new reservation in the folio + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + partner1 = self.env["res.partner"].create({"name": "partner1"}) + folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, + } + ) + + self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + "sale_channel_origin_id": sale_channel_phone.id, + } + ) + # ACT + expected_sale_channels = [] + for reservation in folio1.reservation_ids: + expected_sale_channels.append(reservation.sale_channel_origin_id.id) + + # ASSERT + self.assertItemsEqual( + folio1.sale_channel_ids.ids, + list(set(expected_sale_channels)), + "Sale_channel_ids of folio must be the same as " + "sale_channel_origin of its reservation ", + ) + + @freeze_time("2001-10-22") + def test_folio_sale_channel_ids_reservations_several_origin(self): + """ + Check that sale_channel_ids of folio correspond to sale_channel_origin_id + of its reservations + + In this case, folio1 has two reservations(reservation1, reservation2) + with the same sale_channel_origin. + + sale_channel_origin_id sale_channel_ids + ------------------------- + Folio1 --------> sale_channel_direct1 || sale_channel_direct1 + reservation1 --> sale_channel_direct1 + reservation2 --> sale_channel_direct1 + + Then, reservation2 update sale_channel_origin_id for a diferent one. So the folio + has several reservations with different sale_channel_origin_id. + It should be noted that the check would force having to update + the folio sale_channel_origin_id (force_update_origin) isn't marked. + + Expected result: + + sale_channel_origin_id sale_channel_ids + ---------------------- + Folio1 --------> sale_channel_direct1 | (sale_channel_direct1, sale_channel_phone) + reservation1 --> sale_channel_direct1 + reservation2 --> sale_channel_phone + + In this test case, sale_channel_ids will be checked + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + partner1 = self.env["res.partner"].create({"name": "partner1"}) + folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, + } + ) + + self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + reservation2 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + # ACT + reservation_vals = { + "sale_channel_origin_id": sale_channel_phone.id, + "force_update_origin": False, + } + + reservation2.write(reservation_vals) + expected_sale_channels = [] + for reservation in folio1.reservation_ids: + expected_sale_channels.append(reservation.sale_channel_origin_id.id) + + # ASSERT + self.assertItemsEqual( + folio1.sale_channel_ids.ids, + list(set(expected_sale_channels)), + "Sale_channel_ids of folio must be the same as " + "sale_channel_origin of its reservation ", + ) + + @freeze_time("2001-10-22") + def test_sale_channel_origin_id_reservation_not_update_origin(self): + """ + Check that sale_channel_origin_id of folio doesn't change + when sale_channel_origin_id of one of its reservations is updated + but the check isn't checked + + In this case, folio1 has two reservations(reservation1, reservation2) + with the same sale_channel_origin. + + sale_channel_origin_id + ------------------------- + Folio1 --------> sale_channel_direct1 + reservation1 --> sale_channel_direct1 + reservation2 --> sale_channel_direct1 + + Then, reservation2 update sale_channel_origin_id for a diferent one. So the folio + has several reservations with different sale_channel_origin_id. + And the check would force having to update + the folio sale_channel_origin_id (force_update_origin) isn't marked. + So sale_channel_origin_id of folio shouldn't change. + + Expected result: + + sale_channel_origin_id + ------------------------- + Folio1 --------> sale_channel_direct1 + reservation1 --> sale_channel_direct1 + reservation2 --> sale_channel_phone + + In this test case, sale_channel_origin_id of folio will be checked + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + partner1 = self.env["res.partner"].create({"name": "partner1"}) + folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, + } + ) + + self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + reservation2 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + # ACT + reservation_vals = { + "sale_channel_origin_id": sale_channel_phone.id, + "force_update_origin": False, + } + reservation2.write(reservation_vals) + + # ASSERT + self.assertNotEqual( + folio1.sale_channel_origin_id, + reservation2.sale_channel_origin_id, + "Sale_channel_origin_id of folio shouldn't be the same as " + "sale_channel_origin of reservation2", + ) + + @freeze_time("2001-10-25") + def test_sale_channel_origin_id_reservation_update_origin(self): + """ + Check that sale_channel_origin_id of the folio changes when + you change sale_channel_origin_id of one of its reservations + and check that forces the update of sale_channel_origin_id of folio + + + sale_channel_origin_id + ------------------------- + Folio1 --------> sale_channel_direct1 + reservation1 --> sale_channel_direct1 + reservation2 --> sale_channel_direct1 + + Then, reservation2 update sale_channel_origin_id for a diferent one. So the folio + has several reservations with different sale_channel_origin_id. + And the check would force having to update + the folio sale_channel_origin_id (force_update_origin) is marked. + So sale_channel_origin_id of folio must change. + + Expected result: + + sale_channel_origin_id + ------------------------- + Folio1 --------> sale_channel_phone + reservation1 --> sale_channel_phone + reservation2 --> sale_channel_phone + + In this test case, sale_channel_origin_id of folio1 will be checked + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + partner1 = self.env["res.partner"].create({"name": "partner1"}) + folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, + } + ) + + self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + reservation2 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + # ACT + reservation_vals = { + "sale_channel_origin_id": sale_channel_phone.id, + "force_update_origin": True, + } + reservation2.write(reservation_vals) + # ASSERT + self.assertEqual( + folio1.sale_channel_origin_id, + reservation2.sale_channel_origin_id, + "Sale_channel_origin_id of folio should be updated", + ) + + @freeze_time("2001-10-25") + def test_sale_channel_origin_id_reservation_update_reservations(self): + """ + Check that sale_channel_origin_id of a reservation changes when + another reservation of the same folio changes sale_channel_origin_id + and marks the check. + By changing sale_channel_origin_ id of a reservation and marking the check + that forces the update, changes both sale_channel_origin of folio and + sale_channel_origin of reservations that had the same + + + sale_channel_origin_id + ------------------------- + Folio1 --------> sale_channel_direct1 + reservation1 --> sale_channel_direct1 + reservation2 --> sale_channel_direct1 + + Then, reservation2 update sale_channel_origin_id for a diferent one. + And the check would force having to update + the folio sale_channel_origin_id (force_update_origin) is marked. + So sale_channel_origin_id of folio and other reservations with the same + sale_channel_origin must change. + + Expected result: + + sale_channel_origin_id + ------------------------- + Folio1 --------> sale_channel_phone + reservation1 --> sale_channel_phone + reservation2 --> sale_channel_phone + + In this test case, sale_channel_origin_id of reservation1 will be checked + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + partner1 = self.env["res.partner"].create({"name": "partner1"}) + folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": partner1.name, + "sale_channel_origin_id": self.sale_channel_direct1.id, + } + ) + + reservation1 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + reservation2 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "folio_id": folio1.id, + } + ) + # ACT + reservation_vals = { + "sale_channel_origin_id": sale_channel_phone.id, + "force_update_origin": True, + } + reservation2.write(reservation_vals) + + # ASSERT + self.assertEqual( + reservation1.sale_channel_origin_id, + reservation2.sale_channel_origin_id, + "sale_channel_origin_id of reservations that coincided " + "with sale_channel_origin_id of folio de should be updated", + ) diff --git a/pms/tests/test_pms_folio_invoice.py b/pms/tests/test_pms_folio_invoice.py index c5d509a7e..bed69c713 100644 --- a/pms/tests/test_pms_folio_invoice.py +++ b/pms/tests/test_pms_folio_invoice.py @@ -84,6 +84,14 @@ class TestPmsFolioInvoice(TestPms): } ) + # create a sale channel + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) + def create_configuration_accounting_scenario(self): """ Method to simplified scenario to payments and accounting: @@ -153,6 +161,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) state_expected = "invoiced" @@ -183,6 +192,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) dict_lines = dict() @@ -208,6 +218,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) dict_lines = dict() @@ -228,7 +239,6 @@ class TestPmsFolioInvoice(TestPms): r1.folio_id.invoice_status, "The status after a partial invoicing is not correct", ) - # qty to 2 to 1st folio sale line dict_lines[ r1.folio_id.sale_line_ids.filtered(lambda l: not l.display_type)[0].id @@ -260,6 +270,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) tcs = [-1, 0, 3] @@ -294,6 +305,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -321,6 +333,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) qty_to_invoice_expected = sum( @@ -348,6 +361,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.folio_id._create_invoices() @@ -376,6 +390,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -418,6 +433,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -461,6 +477,7 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -523,6 +540,7 @@ class TestPmsFolioInvoice(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) dict_lines = dict() @@ -578,6 +596,7 @@ class TestPmsFolioInvoice(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) dict_lines = dict() @@ -634,6 +653,7 @@ class TestPmsFolioInvoice(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) dict_lines = dict() @@ -673,13 +693,14 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT - self.assertEqual( + self.assertIn( datetime.date.today() + datetime.timedelta(days=3), - self.reservation1.folio_id.autoinvoice_date, + self.reservation1.folio_id.mapped("sale_line_ids.autoinvoice_date"), "The autoinvoice date in folio with property checkout policy is wrong", ) @@ -704,20 +725,24 @@ class TestPmsFolioInvoice(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) + self.reservation1.reservation_line_ids.default_invoice_to = self.partner_id # ASSERT self.assertEqual( datetime.date.today() + datetime.timedelta(days=5), - self.reservation1.folio_id.autoinvoice_date, + self.reservation1.folio_id.sale_line_ids.filtered( + lambda l: l.invoice_status == "to_invoice" + )[0].autoinvoice_date, "The autoinvoice date in folio with property checkout policy is wrong", ) def test_autoinvoice_paid_folio_overnights_partner_policy(self): """ Test create and invoice the cron by partner preconfig automation - with only overnights reservations (included board services) + with partner setted as default invoiced to in reservation lines -------------------------------------- Set partner invoicing_policy to checkout, create a reservation with room, board service and normal service, run autoinvoicing @@ -727,9 +752,18 @@ class TestPmsFolioInvoice(TestPms): """ # ARRANGE self.create_configuration_accounting_scenario() + self.partner_id2 = self.env["res.partner"].create( + { + "name": "Sara", + "vat": "ES123456787", + "country_id": self.env.ref("base.es").id, + "city": "Madrid", + "zip": "28013", + "street": "Street 321", + } + ) self.partner_id.invoicing_policy = "checkout" self.partner_id.margin_days_autoinvoice = 0 - self.partner_id.default_invoice_lines = "overnights" self.product1 = self.env["product.product"].create( { "name": "Test Product 1", @@ -773,8 +807,9 @@ class TestPmsFolioInvoice(TestPms): "checkout": datetime.date.today(), "adults": 2, "room_type_id": self.demo_room_type_double.id, - "partner_id": self.partner_id.id, + "partner_id": self.partner_id2.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) self.service = self.env["pms.service"].create( @@ -786,6 +821,11 @@ class TestPmsFolioInvoice(TestPms): ) folio = self.reservation1.folio_id reservation1 = self.reservation1 + reservation1.reservation_line_ids.default_invoice_to = self.partner_id + reservation1.service_ids.filtered( + "is_board_service" + ).default_invoice_to = self.partner_id + folio.do_payment( journal=self.env["account.journal"].browse( reservation1.folio_id.pms_property_id._get_payment_methods().ids[0] @@ -826,7 +866,6 @@ class TestPmsFolioInvoice(TestPms): # ARRANGE self.partner_id.invoicing_policy = "checkout" self.partner_id.margin_days_autoinvoice = 0 - self.partner_id.default_invoice_lines = "overnights" self.product1 = self.env["product.product"].create( { "name": "Test Product 1", @@ -872,6 +911,7 @@ class TestPmsFolioInvoice(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner_id.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) self.service = self.env["pms.service"].create( diff --git a/pms/tests/test_pms_folio_sale_line.py b/pms/tests/test_pms_folio_sale_line.py index b329d93f1..140e1c159 100644 --- a/pms/tests/test_pms_folio_sale_line.py +++ b/pms/tests/test_pms_folio_sale_line.py @@ -81,6 +81,13 @@ class TestPmsFolioSaleLine(TestPms): } ) + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) + # RESERVATION LINES def test_comp_fsl_rooms_all_same_group(self): """ @@ -129,6 +136,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -160,6 +168,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -196,6 +205,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -234,6 +244,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -268,6 +279,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -304,6 +316,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.flush() @@ -342,6 +355,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.flush() @@ -383,6 +397,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.flush() @@ -426,6 +441,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -464,6 +480,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids[0].service_line_ids[0].price_unit = 1.0 @@ -503,6 +520,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -545,6 +563,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -586,6 +605,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -628,6 +648,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) previous_folio_board_service_sale_line = r_test.folio_id.sale_line_ids.filtered( @@ -670,6 +691,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -713,6 +735,7 @@ class TestPmsFolioSaleLine(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, "board_service_room_id": self.board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -756,6 +779,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ACT @@ -797,6 +821,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -841,6 +866,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -886,6 +912,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -929,6 +956,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -973,6 +1001,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -1016,6 +1045,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -1066,6 +1096,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.service_ids = [(4, self.extra_service.id)] @@ -1114,6 +1145,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -1160,6 +1192,7 @@ class TestPmsFolioSaleLine(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.env.ref("base.res_partner_12").id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -1212,6 +1245,7 @@ class TestPmsFolioSaleLine(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "reservation_type": "staff", + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -1251,6 +1285,7 @@ class TestPmsFolioSaleLine(TestPms): "pricelist_id": self.pricelist1.id, "reservation_type": "out", "closure_reason_id": closure_reason.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT diff --git a/pms/tests/test_pms_multiproperty.py b/pms/tests/test_pms_multiproperty.py index e040491a6..6f74d82f7 100644 --- a/pms/tests/test_pms_multiproperty.py +++ b/pms/tests/test_pms_multiproperty.py @@ -828,12 +828,19 @@ class TestPmsMultiproperty(TestPms): "email": "miguel@example.com", } ) + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) self.reservation1 = self.env["pms.reservation"].create( { "checkin": fields.date.today(), "checkout": fields.date.today() + datetime.timedelta(days=1), "pms_property_id": self.pms_property1.id, "partner_id": host1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) diff --git a/pms/tests/test_pms_pricelist.py b/pms/tests/test_pms_pricelist.py index 9a034ccf4..bebfd4ed4 100644 --- a/pms/tests/test_pms_pricelist.py +++ b/pms/tests/test_pms_pricelist.py @@ -83,6 +83,14 @@ class TestPmsPricelist(TestPms): self.partner1 = self.env["res.partner"].create({"name": "Carles"}) + # create a sale channel + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) + @freeze_time("2000-01-01") def test_board_service_pricelist_item_apply_sale_dates(self): """ @@ -120,6 +128,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -167,6 +176,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -211,6 +221,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -259,6 +270,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -305,6 +317,7 @@ class TestPmsPricelist(TestPms): "preferred_room_id": self.room1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -351,6 +364,7 @@ class TestPmsPricelist(TestPms): "preferred_room_id": self.room1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -393,6 +407,7 @@ class TestPmsPricelist(TestPms): "preferred_room_id": self.room1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -439,6 +454,7 @@ class TestPmsPricelist(TestPms): "preferred_room_id": self.room1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -485,6 +501,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "service_ids": [(0, 0, {"product_id": self.product1.id})], + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -531,6 +548,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "service_ids": [(0, 0, {"product_id": self.product1.id})], + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -573,6 +591,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "service_ids": [(0, 0, {"product_id": self.product1.id})], + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -619,6 +638,7 @@ class TestPmsPricelist(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist2.id, "service_ids": [(0, 0, {"product_id": self.product1.id})], + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -782,6 +802,7 @@ class TestPmsPricelist(TestPms): "preferred_room_id": self.room.id, "pms_property_id": self.pms_property1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ACT @@ -1230,6 +1251,7 @@ class TestPmsPricelist(TestPms): "preferred_room_id": self.room.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) reservation_price = reservation.price_subtotal diff --git a/pms/tests/test_pms_reservation.py b/pms/tests/test_pms_reservation.py index f7c6e0f10..4d736e28c 100644 --- a/pms/tests/test_pms_reservation.py +++ b/pms/tests/test_pms_reservation.py @@ -90,6 +90,9 @@ class TestPmsReservations(TestPms): self.id_category = self.env["res.partner.id_category"].create( {"name": "DNI", "code": "D"} ) + self.sale_channel_direct = self.env["pms.sale.channel"].create( + {"name": "sale channel direct", "channel_type": "direct"} + ) self.sale_channel1 = self.env["pms.sale.channel"].create( {"name": "saleChannel1", "channel_type": "indirect"} ) @@ -155,6 +158,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, "reservation_line_ids": [ (0, False, {"date": today}), (0, False, {"date": tomorrow}), @@ -197,6 +201,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } # ACT @@ -226,6 +231,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } # ACT @@ -262,6 +268,7 @@ class TestPmsReservations(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r_test.flush() @@ -300,6 +307,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r_test.flush() @@ -331,6 +339,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r1.reservation_line_ids[0].room_id = self.room2.id @@ -344,6 +353,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r2.reservation_line_ids[0].room_id = self.room3.id @@ -357,6 +367,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r3.reservation_line_ids[0].room_id = self.room1.id @@ -370,6 +381,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r4.reservation_line_ids[0].room_id = self.room3.id @@ -385,6 +397,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r_test.flush() @@ -419,6 +432,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r1.reservation_line_ids[0].room_id = self.room2.id @@ -432,6 +446,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r2.reservation_line_ids[0].room_id = self.room3.id @@ -445,6 +460,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r3.reservation_line_ids[0].room_id = self.room1.id @@ -458,6 +474,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r4.reservation_line_ids[0].room_id = self.room3.id @@ -471,6 +488,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r5.reservation_line_ids[0].room_id = self.room2.id @@ -485,6 +503,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r_test.flush() @@ -524,6 +543,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r1.reservation_line_ids[0].room_id = self.room1 @@ -566,6 +586,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r1.reservation_line_ids[0].room_id = self.room1 @@ -608,6 +629,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r1.reservation_line_ids[0].room_id = self.room1 @@ -623,6 +645,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r2.reservation_line_ids[0].room_id = self.room2 @@ -638,6 +661,7 @@ class TestPmsReservations(TestPms): "adults": 2, "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r3.reservation_line_ids[0].room_id = self.room3 @@ -722,6 +746,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) computed_priority = res.priority @@ -758,6 +783,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -860,6 +886,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -902,6 +929,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -971,6 +999,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -1032,6 +1061,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) computed_priority = res.priority @@ -1069,6 +1099,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -1134,6 +1165,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -1209,6 +1241,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) computed_priority = res.priority @@ -1247,6 +1280,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) computed_priority = res.priority @@ -1288,6 +1322,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -1366,6 +1401,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -1444,6 +1480,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) host1 = self.env["res.partner"].create( @@ -1514,6 +1551,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ACT @@ -1539,6 +1577,7 @@ class TestPmsReservations(TestPms): "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -1568,6 +1607,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -1596,6 +1636,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ACT @@ -1618,6 +1659,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ACT @@ -1660,6 +1702,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": host.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r1.flush() @@ -1729,6 +1772,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=305), "partner_id": self.partner1.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) r = reservation.checkin @@ -1766,6 +1810,7 @@ class TestPmsReservations(TestPms): "partner_id": self.partner1.id, "room_type_id": self.room_type_double.id, "pricelist_id": self.pricelist1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.assertEqual( @@ -1804,6 +1849,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=152), "agency_id": agency.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -1849,6 +1895,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=152), "agency_id": agency.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.assertEqual( @@ -1871,6 +1918,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=152), "partner_id": self.partner1.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -1931,6 +1979,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "adults": 3, "room_type_id": self.room_type_triple.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.checkin1 = self.env["pms.checkin.partner"].create( @@ -2112,6 +2161,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=65), "pms_property_id": self.pms_property1.id, "partner_id": self.host1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.reservation2 = self.env["pms.reservation"].create( @@ -2121,6 +2171,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "partner_id": self.host1.id, "folio_id": self.reservation.folio_id.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.assertTrue( @@ -2145,6 +2196,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=65), "pms_property_id": self.pms_property1.id, "partner_id": self.host1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.assertFalse( @@ -2175,6 +2227,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "partner_id": self.host1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2223,6 +2276,7 @@ class TestPmsReservations(TestPms): "partner_id": self.host1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2276,6 +2330,7 @@ class TestPmsReservations(TestPms): "partner_id": self.host1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2327,6 +2382,7 @@ class TestPmsReservations(TestPms): "partner_id": self.host1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) reservation.action_cancel() @@ -2365,6 +2421,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "adults": 3, "room_type_id": self.room_type_triple.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.checkin1 = self.env["pms.checkin.partner"].create( @@ -2425,6 +2482,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "room_type_id": self.room_type_triple.id, "adults": 3, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) self.checkin1 = self.env["pms.checkin.partner"].create( @@ -2479,6 +2537,7 @@ class TestPmsReservations(TestPms): "allowed_checkout": True, "pms_property_id": self.pms_property1.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2512,6 +2571,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "folio_id": self.folio1.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ACT AND ASSERT @@ -2551,6 +2611,7 @@ class TestPmsReservations(TestPms): "checkout": fields.date.today() + datetime.timedelta(days=152), "agency_id": agency.id, "room_type_id": self.room_type_double.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2605,6 +2666,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "service_ids": [self.board_service.id], + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ACTION @@ -2649,6 +2711,7 @@ class TestPmsReservations(TestPms): "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2705,6 +2768,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "service_ids": [self.service.id], + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2766,6 +2830,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "service_ids": [self.board_service.id], + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2842,6 +2907,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "service_ids": [self.service.id, self.board_service.id], + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2916,6 +2982,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "service_ids": [self.service.id, self.board_service.id], + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -2965,6 +3032,7 @@ class TestPmsReservations(TestPms): "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3045,6 +3113,7 @@ class TestPmsReservations(TestPms): "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) diff_days = (checkout - checkin).days @@ -3079,6 +3148,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "pricelist_id": self.pricelist1.id, "reservation_type": "staff", + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3118,6 +3188,7 @@ class TestPmsReservations(TestPms): "pricelist_id": self.pricelist1.id, "reservation_type": "out", "closure_reason_id": closure_reason.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3147,6 +3218,7 @@ class TestPmsReservations(TestPms): "partner_id": self.partner1.id, "pms_property_id": self.pms_property1.id, "reservation_type": "staff", + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3183,6 +3255,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "reservation_type": "out", "closure_reason_id": closure_reason.id, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3260,6 +3333,7 @@ class TestPmsReservations(TestPms): "reservation_type": "out", "closure_reason_id": closure_reason.id, "partner_name": "Install furniture", + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3296,6 +3370,7 @@ class TestPmsReservations(TestPms): "mobile": "61568547", "document_type": self.id_category.id, "document_number": "31640132K", + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3347,6 +3422,7 @@ class TestPmsReservations(TestPms): "partner_name": partner.name, "document_type": self.document_id.category_id.id, "document_number": self.document_id.name, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3402,6 +3478,7 @@ class TestPmsReservations(TestPms): "partner_name": partner.name, "document_type": self.document_id.category_id.id, "document_number": self.document_id.name, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3440,6 +3517,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "partner_name": partner.name, "email": partner.email, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3477,6 +3555,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "partner_name": partner.name, "mobile": partner.mobile, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3517,6 +3596,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "partner_name": partner.name, "email": partner.email, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3535,81 +3615,6 @@ class TestPmsReservations(TestPms): "The partner was not added to the reservation ", ) - # def test_is_modified_reservation(self): - # """ - # Checked that the is_modified_reservation field is correctly set - # to True when the checkin or checkout fields are modified in a - # reservation. - # ---------------------- - # A reservation is created. The checkin and checkout fields of - # the reservation are modified. The state of the boolean - # to_send_mail is changed to False so that the compute of - # the is_modified_reservation field is activated correctly - # and it is verified that the state of this field is True. - # """ - # # ARRANGE - # checkin = fields.date.today() - # checkout = fields.date.today() + datetime.timedelta(days=2) - # reservation_vals = { - # "checkin": checkin, - # "checkout": checkout, - # "room_type_id": self.room_type_double.id, - # "partner_id": self.partner1.id, - # "pms_property_id": self.pms_property1.id, - # } - # - # reservation = self.env["pms.reservation"].create(reservation_vals) - # - # # ACT - # writed_checkin = fields.date.today() + datetime.timedelta(days=4) - # writed_checkout = fields.date.today() + datetime.timedelta(days=6) - # reservation.to_send_mail = False - # reservation.update( - # { - # "checkin": writed_checkin, - # "checkout": writed_checkout, - # } - # ) - # - # # ASSERT - # self.assertTrue( - # reservation.is_modified_reservation, - # "is_modified_reservation field should be True ", - # ) - - # @freeze_time("2012-01-14") - # def test_is_not_modified_reservation(self): - # """ - # Checked that the is_modified_reservation field is correctly set - # to False when the reservation is modified but not the checkin - # or checkout fields. - # ---------------------- - # A reservation is created. The adults, arrival_hour and departure_hours - # fields of the reservation are modified.The it is verified that the state - # of this field is False. - # """ - # # ARRANGE - # checkin = fields.date.today() - # checkout = fields.date.today() + datetime.timedelta(days=2) - # reservation_vals = { - # "checkin": checkin, - # "checkout": checkout, - # "room_type_id": self.room_type_double.id, - # "partner_id": self.partner1.id, - # "pms_property_id": self.pms_property1.id, - # } - - # reservation = self.env["pms.reservation"].create(reservation_vals) - # reservation.update( - # {"adults": 1, "arrival_hour": "18:00", "departure_hour": "08:00"} - # ) - - # # ASSERT - # self.assertFalse( - # reservation.is_modified_reservation, - # "is_modified_reservation field should be False ", - # ) - @freeze_time("2012-01-14") def test_not_add_several_possibles_customers(self): """ @@ -3648,6 +3653,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "partner_name": partner1.name, "email": partner1.email, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3688,6 +3694,7 @@ class TestPmsReservations(TestPms): "room_type_id": self.room_type_double.id, "pms_property_id": self.pms_property1.id, "partner_name": "Rosa Costa", + "sale_channel_origin_id": self.sale_channel_direct.id, } ) @@ -3772,6 +3779,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "agency_id": self.agency1.id, "service_ids": [self.service.id], + "sale_channel_origin_id": self.sale_channel_direct.id, } # ACT reservation = self.env["pms.reservation"].create(reservation_vals) @@ -3791,6 +3799,7 @@ class TestPmsReservations(TestPms): self.commission + service.price_total * self.agency1.default_commission / 100 ) + # ASSERT self.assertEqual( self.commission, reservation.commission_amount, @@ -3854,6 +3863,7 @@ class TestPmsReservations(TestPms): "pms_property_id": self.pms_property1.id, "reservation_type": "out", "closure_reason_id": closure_reason, + "sale_channel_origin_id": self.sale_channel_direct.id, } ) # ASSERT @@ -3862,3 +3872,378 @@ class TestPmsReservations(TestPms): "The out of service reservation should be created properly with " "a closure reason.", ) + + # tests for several sale channels in reservation + @freeze_time("2000-11-10") + def test_reservation_sale_channel_origin_in_reservation_lines(self): + """ + Check that reservation_lines have sale_channel_id + corresponding to sale_channel_origin_id of their reservation + + When a reservation was created with a sale channel, it corresponds + to the sale_channel_origin. + Reservation lines will have as sale_channel_id the sale_channel_origin_id + of reservation when creating them + + """ + # ARRANGE + checkin = fields.date.today() + checkout = checkin + datetime.timedelta(days=3) + reservation_vals = { + "checkin": checkin, + "checkout": checkout, + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + + # ACT + reservation = self.env["pms.reservation"].create(reservation_vals) + + # ASSERT + self.assertEqual( + reservation.sale_channel_origin_id, + reservation.reservation_line_ids.mapped("sale_channel_id"), + "Sale channel of reservation lines must be the same that their reservation", + ) + + @freeze_time("2000-10-10") + def test_reservation_sale_channel_origin_in_folio(self): + """ + Check that folio have sale_channel_origin_id + corresponding to sale_channel_origin_id of the reservation + that was created before the folio + + When a reservation was created with a sale channel, it corresponds + to the sale_channel_origin. + If reservation didn't have folio previously, the folio to be created + will have the same sale_channel_origin as the reservation + + """ + # ARRANGE + checkin = fields.date.today() + checkout = checkin + datetime.timedelta(days=3) + reservation_vals = { + "checkin": checkin, + "checkout": checkout, + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + + # ACT + reservation = self.env["pms.reservation"].create(reservation_vals) + + # ASSERT + self.assertEqual( + reservation.sale_channel_origin_id, + reservation.folio_id.sale_channel_origin_id, + "Sale channel of folio must be the same that it reservation", + ) + + @freeze_time("2001-10-15") + def test_reservation_sale_channel_origin_of_folio(self): + """ + Check that the reservation has sale_channel_origin_id + as the folio sale_channel_origin_id in + which reservation was created when a folio has already + another reservations. + + Testing whether it works when the folio sale_channel_origin_id + is given by a previously created reservation + + When a reservation is created on a folio + that already has a sale_channel_origin + that reservation will have the same sale_channel_origin + + """ + # ARRANGE + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + reservation1 = self.env["pms.reservation"].create(reservation_vals) + # ACT + reservation2 = self.env["pms.reservation"].create( + { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "adults": 2, + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "folio_id": reservation1.folio_id.id, + } + ) + # ASSERT + self.assertEqual( + reservation1.sale_channel_origin_id.id, + reservation2.sale_channel_origin_id.id, + "Sale channel of reservations must be the same", + ) + + @freeze_time("2000-10-19") + def test_reservation_lines_same_sale_channel(self): + """ + Check if sale_channel_ids of reservation correspond to + sale_channel_id of its reservation. + + In this case, the reservation has several reservation_lines + with the same sale_channel_id. Reservation lines are created + with sale_channel_origin_id of the reservation and haven't been + modified. + + """ + # ARRANGE + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=4), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + # ACT + reservation1 = self.env["pms.reservation"].create(reservation_vals) + + # ASSERT + self.assertEqual( + reservation1.sale_channel_ids, + reservation1.reservation_line_ids.mapped("sale_channel_id"), + "Sale_channel_ids of reservation must be the same as " + "sale channels of its reservation lines", + ) + + @freeze_time("2000-10-24") + def test_reservation_sale_channel_origin_change_check_lines(self): + """ + Check that sale_channel_id of reservation_lines changes when + sale_channel_origin_id of its reservation has changed + """ + # ARRANGE + sale_channel_direct2 = self.env["pms.sale.channel"].create( + { + "name": "sale channel 2", + "channel_type": "direct", + } + ) + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=4), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + reservation1 = self.env["pms.reservation"].create(reservation_vals) + + # ACT + reservation1.sale_channel_origin_id = sale_channel_direct2.id + + # ASSERT + self.assertEqual( + reservation1.sale_channel_origin_id, + reservation1.reservation_line_ids.mapped("sale_channel_id"), + "Sale_channel_id of reservation lines must also be changed", + ) + + @freeze_time("2000-10-29") + def test_reservation_lines_not_change_sale_channel(self): + """ + Check that when changing sale_channel_origin_id of a reservation, + reservation lines that didn't have the same sale_channel_id didn't + change it + + Reservation1: + --> sale_channel_origin_id : sale_channel1.id + --> reservation_lines: + --> 1: sale_channel_id: sale_channel1.id + --> 2: sale_channel_id: sale_channel1.id + --> 3: sale_channel_id: sale_channel1.id + --> 4: sale_channel_id: sale_channel_phone.id + + Change reservation1.sale_channel_origin_id = sale_channel_mail.id + + Expected result: + Reservation1: + --> sale_channel_origin_id : sale_channel_mail.id + --> reservation_lines: + --> 1: sale_channel_id: sale_channel_mail.id + --> 2: sale_channel_id: sale_channel_mail.id + --> 3: sale_channel_id: sale_channel_mail.id + --> 4: sale_channel_id: sale_channel_phone.id + + In short, sale channel of those reservations lines of the reservation + that didn't coincide with sale chanel origin that has been modified, + shouldn't be changed. That is, the last reservation_line must have + sale_channel_id = sale_channel_phone + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + sale_channel_mail = self.env["pms.sale.channel"].create( + { + "name": "mail", + "channel_type": "direct", + } + ) + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=4), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + reservation1 = self.env["pms.reservation"].create(reservation_vals) + + # ACT + reservation_lines = reservation1.reservation_line_ids + reservation_lines[ + len(reservation_lines) - 1 + ].sale_channel_id = sale_channel_phone.id + + reservation1.sale_channel_origin_id = sale_channel_mail + + # ASSERT + self.assertNotEqual( + reservation1.sale_channel_origin_id, + reservation_lines[len(reservation_lines) - 1].sale_channel_id, + "Sale_channel_id of that reservation line shouldn't have changed", + ) + + @freeze_time("2000-11-29") + def test_several_sale_channel_in_lines(self): + """ + Check that when a reservation has more than one sale_channel_id + in its reservation_lines, sale_channel_ids of reservation is well + calculated + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=4), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + reservation1 = self.env["pms.reservation"].create(reservation_vals) + + # ACT + reservation_lines = reservation1.reservation_line_ids + reservation_lines[0].sale_channel_id = sale_channel_phone.id + + expected_sale_channels = [] + for line in reservation_lines: + expected_sale_channels.append(line.sale_channel_id.id) + + # ASSERT + self.assertItemsEqual( + reservation1.sale_channel_ids.ids, + list(set(expected_sale_channels)), + "Sale_channel_ids of that reservation must match those of its lines", + ) + + @freeze_time("2000-12-01") + def test_reservation_no_sale_channel_origin(self): + """ + Check that you can't create a reservation without sale_channel_origin + """ + # ACT & ASSERT + with self.assertRaises( + ValidationError, + msg="Error, it has been allowed to create a reservation without sale channel", + ): + self.env["pms.reservation"].create( + { + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=4), + } + ) + + @freeze_time("2000-12-01") + def test_one_reservation_change_sale_channel_origin(self): + """ + Check that when changing the sale_channel_origin of a reservation, + sale_channel_origin of its folio changes if folio only has one reservation + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=4), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + reservation1 = self.env["pms.reservation"].create(reservation_vals) + + # ACT + reservation1.sale_channel_origin_id = sale_channel_phone.id + + # ASSERT + self.assertEqual( + reservation1.folio_id.sale_channel_origin_id, + reservation1.sale_channel_origin_id, + "Sale_channel_origin_id of folio must be the same as " + "sale_channel_origin of rservation", + ) + + @freeze_time("2000-12-10") + def test_check_sale_channel_origin_in_reservation_lines(self): + """ + Check that a reservation has at least one reservation_line woth the + same sale_channel_id as its sale_channel_origin_id + """ + # ARRANGE + sale_channel_phone = self.env["pms.sale.channel"].create( + { + "name": "phone", + "channel_type": "direct", + } + ) + reservation_vals = { + "checkin": datetime.datetime.now(), + "checkout": datetime.datetime.now() + datetime.timedelta(days=1), + "room_type_id": self.room_type_double.id, + "partner_id": self.partner1.id, + "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct.id, + } + reservation1 = self.env["pms.reservation"].create(reservation_vals) + + # ACT & ASSERT + with self.assertRaises( + ValidationError, + msg="Error, there cannot be a reservation in which at least one of its reservation" + "lines doesn't have as sale_channel_id the sale_channel_origin_id of reservation", + ): + reservation1.reservation_line_ids.write( + {"sale_channel_id": sale_channel_phone} + ) + reservation1.flush() diff --git a/pms/tests/test_pms_sale_channel.py b/pms/tests/test_pms_sale_channel.py index 70702b53a..fc13ff813 100644 --- a/pms/tests/test_pms_sale_channel.py +++ b/pms/tests/test_pms_sale_channel.py @@ -56,6 +56,7 @@ class TestPmsSaleChannel(TestPms): "checkout": datetime.datetime.now() + datetime.timedelta(days=3), "agency_id": agency1.id, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": sale_channel1.id, } ) @@ -66,66 +67,6 @@ class TestPmsSaleChannel(TestPms): "Reservation with a valid agency should be created.", ) - def test_reservation_with_partner_direct(self): - """ - Reservation create with partner (no agency) and sale channel - 'direct' must be set reservation sale channel to 'direct'. - A reservation with partner and sale channel as 'direct' - should be created. - """ - # ARRANGE - PmsReservation = self.env["pms.reservation"] - PmsSaleChannel = self.env["pms.sale.channel"] - # ACT - sale_channel1 = PmsSaleChannel.create({"channel_type": "direct"}) - partner1 = self.env["res.partner"].create({"name": "partner1"}) - reservation1 = PmsReservation.create( - { - "checkin": datetime.datetime.now(), - "checkout": datetime.datetime.now() + datetime.timedelta(days=3), - "channel_type_id": sale_channel1.id, - "partner_id": partner1.id, - "pms_property_id": self.pms_property1.id, - } - ) - # ASSERT - self.assertEqual( - reservation1.channel_type_id.channel_type, - "direct", - "A reservation with partner and sale channel as 'direct'" - "should be created a 'direct' reservation.", - ) - - def test_reservation_with_partner_indirect(self): - """ - Reservation create with partner (no agency) and sale channel - 'indirect' must be set reservation sale channel to 'direct'. - A reservation with partner and sale channel as 'direct' - should be created. - """ - # ARRANGE - PmsReservation = self.env["pms.reservation"] - PmsSaleChannel = self.env["pms.sale.channel"] - # ACT - sale_channel1 = PmsSaleChannel.create({"channel_type": "indirect"}) - partner1 = self.env["res.partner"].create({"name": "partner1"}) - reservation1 = PmsReservation.create( - { - "checkin": datetime.datetime.now(), - "checkout": datetime.datetime.now() + datetime.timedelta(days=3), - "channel_type_id": sale_channel1.id, - "partner_id": partner1.id, - "pms_property_id": self.pms_property1.id, - } - ) - # ASSERT - self.assertEqual( - reservation1.channel_type_id.channel_type, - "indirect", - "A reservation with partner and sale channel as 'direct'" - "should be created a 'indirect' reservation.", - ) - def test_create_agency_with_sale_channel_indirect(self): """ Agency should be created as partner setted as 'agency' diff --git a/pms/tests/test_pms_service.py b/pms/tests/test_pms_service.py new file mode 100644 index 000000000..7e2fdd5a4 --- /dev/null +++ b/pms/tests/test_pms_service.py @@ -0,0 +1,1042 @@ +import datetime + +from freezegun import freeze_time + +from odoo import fields + +from .common import TestPms + + +class TestPmsService(TestPms): + def setUp(self): + super().setUp() + # create room type + self.room_type_double = self.env["pms.room.type"].create( + { + "pms_property_ids": [self.pms_property1.id], + "name": "Double Test", + "default_code": "DBL_Test", + "class_id": self.room_type_class1.id, + } + ) + # create rooms + self.room1 = self.env["pms.room"].create( + { + "pms_property_id": self.pms_property1.id, + "name": "Double 101", + "room_type_id": self.room_type_double.id, + "capacity": 2, + "extra_beds_allowed": 1, + } + ) + + self.room2 = self.env["pms.room"].create( + { + "pms_property_id": self.pms_property1.id, + "name": "Double 102", + "room_type_id": self.room_type_double.id, + "capacity": 2, + "extra_beds_allowed": 1, + } + ) + self.partner1 = self.env["res.partner"].create( + { + "firstname": "María", + "lastname": "", + "email": "jaime@example.com", + "birthdate_date": "1983-03-01", + "gender": "male", + } + ) + self.sale_channel_door = self.env["pms.sale.channel"].create( + {"name": "Door", "channel_type": "direct"} + ) + self.sale_channel_phone = self.env["pms.sale.channel"].create( + {"name": "Phone", "channel_type": "direct"} + ) + self.sale_channel_mail = self.env["pms.sale.channel"].create( + {"name": "Mail", "channel_type": "direct"} + ) + + @freeze_time("2002-01-01") + def test_reservation_sale_origin_in_board_service(self): + """ + When a reservation is created with board_service, the sale_channel_origin_id + is indicated in reservation. Therefore, the board_service takes + the sale_channel_origin of its reservation + + Reservation --> sale_channel_origin_id = Door + | + --> service.sale_channel_origin_id? It must be Door + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + } + ) + + self.board_service1 = self.env["pms.board.service"].create( + { + "name": "Test Board Service 1", + "default_code": "CB1", + } + ) + self.board_service_line1 = self.env["pms.board.service.line"].create( + { + "product_id": self.product1.id, + "pms_board_service_id": self.board_service1.id, + "amount": 10, + } + ) + + self.board_service_room_type1 = self.env["pms.board.service.room.type"].create( + { + "pms_room_type_id": self.room_type_double.id, + "pms_board_service_id": self.board_service1.id, + } + ) + # ACT + self.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, + "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ASSERT + self.assertEqual( + self.reservation.sale_channel_origin_id, + self.reservation.service_ids.sale_channel_origin_id, + "sale_channel_origin of board_Service must be the same as its reservation", + ) + + @freeze_time("2002-01-11") + def test_change_origin_board_service_not_change_reservation_origin(self): + """ + When you change the sale_channel_origin_id of a board_service in a reservation + that matched the origin of its reservation, if that reservation has reservation_lines + with that sale_channel_id, it doesn't change the origin of reservation + + Reservation --> sale_channel_origin = Door sale_channel_ids = Door + | + --> board_services.sale_channel_origin = Door + + Change board_service origin to Mail + Reservation --> sale_channel_origin = Door sale_channel_ids = {Door, Mail} + | + --> board_services.sale_channel_origin = Mail + + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + } + ) + + self.board_service1 = self.env["pms.board.service"].create( + { + "name": "Test Board Service 1", + "default_code": "CB1", + } + ) + self.board_service_line1 = self.env["pms.board.service.line"].create( + { + "product_id": self.product1.id, + "pms_board_service_id": self.board_service1.id, + "amount": 10, + } + ) + + self.board_service_room_type1 = self.env["pms.board.service.room.type"].create( + { + "pms_room_type_id": self.room_type_double.id, + "pms_board_service_id": self.board_service1.id, + } + ) + + self.reservation = self.env["pms.reservation"].create( + { + "checkin": fields.date.today(), + "checkout": fields.date.today() + datetime.timedelta(days=3), + "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, + "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.reservation.service_ids.sale_channel_origin_id = self.sale_channel_mail.id + # ASSERT + self.assertNotEqual( + self.reservation.sale_channel_origin_id, + self.reservation.service_ids.sale_channel_origin_id, + """sale_channel_origin_id mustn't match + with sale_channel_origin_id of its reservation""", + ) + + @freeze_time("2002-01-17") + def test_change_origin_board_service_in_sale_channels(self): + """ + When sale_channel_origin_id of board_service is changed, the sale_channel_ids + of its reservation and folio are recalculated. Check that these calculations are correct + + Reservation --> sale_channel_origin = Door sale_channel_ids = Door + | + ---> board_service.sale_channel_origin = Door + + Change origin of board services to Phone and + check sale_channel_ids of reservation and folio: + Reservation --> sale_channel_origin = Door sale_channel_ids = {Door, Phone} + | + ---> board_service.sale_channel_origin = Phone + + Reservation.folio_id.sale_channel_ids = {Door, Phone} + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + } + ) + + self.board_service1 = self.env["pms.board.service"].create( + { + "name": "Test Board Service 1", + "default_code": "CB1", + } + ) + self.board_service_line1 = self.env["pms.board.service.line"].create( + { + "product_id": self.product1.id, + "pms_board_service_id": self.board_service1.id, + "amount": 10, + } + ) + + self.board_service_room_type1 = self.env["pms.board.service.room.type"].create( + { + "pms_room_type_id": self.room_type_double.id, + "pms_board_service_id": self.board_service1.id, + } + ) + self.reservation = self.env["pms.reservation"].create( + { + "checkin": fields.date.today(), + "checkout": fields.date.today() + datetime.timedelta(days=3), + "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, + "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.reservation.service_ids.sale_channel_origin_id = self.sale_channel_phone + + sale_channel_ids = [ + self.reservation.folio_id.sale_channel_ids.ids, + self.reservation.sale_channel_ids.ids, + ] + + expected_sale_channel_ids = [ + self.sale_channel_door.id, + self.sale_channel_phone.id, + ] + # ASSERT + for sale_channel in sale_channel_ids: + with self.subTest(k=sale_channel): + self.assertItemsEqual( + sale_channel, + expected_sale_channel_ids, + "sale_channel_ids must contain sale_channel_origin_id of all board_service", + ) + + @freeze_time("2002-01-19") + def test_change_origin_reservation_change_origin_services(self): + """ + When sale_channel_origin_id of reservation is changed, + sale_channel_origin_id of its services having the same origin + must also be changed + + Reservation ---> sale_channel_origin = Door + | + --> service.sale_channel_origin = Door + + Change sale_channel_origin to Mail, expected results: + Reservation ---> sale_channel_origin = Mail + | + --> service.sale_channel_origin = Mail ----CHECKING THIS--- + + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + } + ) + + self.board_service1 = self.env["pms.board.service"].create( + { + "name": "Test Board Service 1", + "default_code": "CB1", + } + ) + self.board_service_line1 = self.env["pms.board.service.line"].create( + { + "product_id": self.product1.id, + "pms_board_service_id": self.board_service1.id, + "amount": 10, + } + ) + + self.board_service_room_type1 = self.env["pms.board.service.room.type"].create( + { + "pms_room_type_id": self.room_type_double.id, + "pms_board_service_id": self.board_service1.id, + } + ) + + self.reservation = self.env["pms.reservation"].create( + { + "checkin": fields.date.today(), + "checkout": fields.date.today() + datetime.timedelta(days=3), + "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, + "board_service_room_id": self.board_service_room_type1.id, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.reservation.sale_channel_origin_id = self.sale_channel_mail + + # ASSERT + self.assertIn( + self.reservation.sale_channel_origin_id, + self.reservation.service_ids.sale_channel_origin_id, + "sale_channel_origin_id of service must be the same that its reservation ", + ) + + @freeze_time("2002-02-01") + def test_reservation_sale_origin_in_service(self): + """ + When a reservation is created with service, the sale_channel_origin_id + is indicated in reservation. Therefore, the service takes + the sale_channel_origin of its reservation + + Reservation --> sale_channel_origin_id = Door + | + --> service.sale_channel_origin_id? It must be Door + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + + self.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, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.service1 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + } + ) + # ASSERT + self.assertEqual( + self.reservation.sale_channel_origin_id, + self.service1.sale_channel_origin_id, + "sale_channel_origin of service must be the same as its reservation", + ) + + @freeze_time("2002-02-03") + def test_origin_different_in_services_check_sale_channel_ids(self): + """ + Check that sale_channel_ids is calculated well (in folio and + reservation) when a reservation has services from different sale_channels + + Reservation --> sale_channel_origin = Door sale_channel_ids = Door + | + --> service.sale_channel_origin = Door + + Add in reservation another service with sale_channel_origin = Phone, expected results: + + Reservation --> sale_channel_origin = Door sale_channel_ids = Door, Phone + | + --> service[0].sale_channel_origin = Door + | + --> service[1].sale_channel_origin = Phone + + Reservation.folio_id.sale_channels = {Door, Phone} + + Check sale_channel_ids of reservation and its folio + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + + self.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, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.service1 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + } + ) + self.service2 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + "sale_channel_origin_id": self.sale_channel_phone.id, + } + ) + + sale_channel_ids = [ + self.reservation.folio_id.sale_channel_ids, + self.reservation.sale_channel_ids, + ] + + expected_sale_channel_ids = self.reservation.service_ids.mapped( + "sale_channel_origin_id" + ) + + # ASSERT + for sale_channel in sale_channel_ids: + with self.subTest(k=sale_channel): + self.assertItemsEqual( + sale_channel, + expected_sale_channel_ids, + "sale_channel_ids must contain sale_channel_id of all board_service_lines", + ) + + @freeze_time("2002-02-16") + def test_change_origin_service_not_change_reservation_origin(self): + """ + When you change the sale_channel_origin_id of a service in a reservation + that matched the origin of its reservation, if that reservation has reservation_lines + with that sale_channel_id, it doesn't change the origin of reservation + + Reservation --> sale_channel_origin = Door + | + --> service.sale_channel_origin = Door + + Change sale_channel_origin of service to Phone, expected results: + + Reservation --> sale_channel_origin = Door ----CHECKING THIS--- + | + --> service.sale_channel_origin = Phone + + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + + self.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, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + } + ) + # ACT + self.reservation.service_ids.sale_channel_origin_id = self.sale_channel_phone.id + # ASSERT + self.assertNotEqual( + self.reservation.sale_channel_origin_id, + self.reservation.service_ids.sale_channel_origin_id, + """sale_channel_origin_id mustn't match + with sale_channel_origin_id of its reservation""", + ) + + @freeze_time("2002-02-23") + def test_change_origin_in_services_check_sale_channel_ids(self): + """ + Check that sale_channel_ids is calculated well (in folio and + reservation) when a service of a reservation change its sale_channel_origin + + Reservation --> sale_channel_origin = Door sale_channel_ids = Door + | + --> service.sale_channel_origin = Door + + Change sale_channel_origin of service to Mail, expected results: + + Reservation --> sale_channel_origin = Door + --> sale_channel_ids = Door, Mail -----CHECKING THIS---- + | + --> service.sale_channel_origin = Mail + + Reservation.folio_id.sale_channels = {Door, Mail} -----CHECKING THIS---- + + Check sale_channel_ids of reservation and its folio + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + + self.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, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + } + ) + + # ACT + self.service1.sale_channel_origin_id = self.sale_channel_mail + + sale_channel_ids = [ + self.reservation.folio_id.sale_channel_ids.ids, + self.reservation.sale_channel_ids.ids, + ] + + expected_sale_channel_ids = [ + self.sale_channel_door.id, + self.sale_channel_mail.id, + ] + + # ASSERT + for sale_channel in sale_channel_ids: + with self.subTest(k=sale_channel): + self.assertItemsEqual( + sale_channel, + expected_sale_channel_ids, + "sale_channel_ids must contain sale_channel_origin_id of all services", + ) + + @freeze_time("2002-02-25") + def test_change_origin_in_reservation_change_origin_service(self): + """ + Check that when change sale_channel_origin of a reservation, sale_channel_origin + of services that match with the origin changed, change too + + Service --> sale_channel_origin_id = Door sale_channel_ids = {Door, Phone} + | + --> service[0].sale_channel_id = Door + | + --> service[1].sale_channel_id = Phone + + Change service origin to mail, expected results: + Reservation --> sale_channel_origin_id = Mail sale_channel_ids = {Mail, Phone} + | + --> service[0].sale_channel_id = Mail -----------CHECKING THIS--- + | + --> service[1].sale_channel_id = Phone + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + + self.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, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + } + ) + self.service2 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + "sale_channel_origin_id": self.sale_channel_phone.id, + } + ) + + # ACT + self.reservation.sale_channel_origin_id = self.sale_channel_mail + + # ASSERT + self.assertIn( + self.reservation.sale_channel_origin_id, + self.reservation.service_ids.mapped("sale_channel_origin_id"), + "sale_channel_origin_id of that service should be changed", + ) + + @freeze_time("2002-03-29") + def test_change_origin_in_reservation_no_change_origin_service(self): + """ + Check that when change sale_channel_origin of a reservation, sale_channel_origin + of services that don't match with the origin changed don't change + + Service --> sale_channel_origin_id = Door sale_channel_ids = {Door, Phone} + | + --> service[0].sale_channel_id = Door + | + --> service[1].sale_channel_id = Phone + + Change service origin to mail, expected results: + Reservation --> sale_channel_origin_id = Mail sale_channel_ids = {Mail, Phone} + | + --> service[0].sale_channel_id = Mail + | + --> service[1].sale_channel_id = Phone -----------CHECKING THIS--- + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + + self.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, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + } + ) + self.service2 = self.env["pms.service"].create( + { + "reservation_id": self.reservation.id, + "product_id": self.product1.id, + "is_board_service": False, + "sale_channel_origin_id": self.sale_channel_phone.id, + } + ) + + # ACT + self.reservation.sale_channel_origin_id = self.sale_channel_mail + + # ASSERT + self.assertIn( + self.sale_channel_phone, + self.reservation.service_ids.mapped("sale_channel_origin_id"), + "sale_channel_origin_id of that service shouldn't be changed", + ) + + @freeze_time("2002-03-01") + def test_new_service_in_folio_sale_channel_origin(self): + """ + Check that when a service is created within a folio already created, + this service will use the sale_channel_origin_id of the folio as + its sale_channel_origin_id + + Folio ----> sale_channel_origin_id = Door + | + ----> service.sale_channel_origin_id? It must be Door + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + self.folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": self.partner1.name, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.service1 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + } + ) + # ASSERT + self.assertEqual( + self.folio1.sale_channel_origin_id, + self.service1.sale_channel_origin_id, + "Service that is just created must have its folio sale_channel_origin", + ) + + @freeze_time("2002-03-03") + def test_change_origin_folio_change_origin_one_service(self): + """ + Check that when a folio has a service, changing the sale_channel_origin + of folio changes sale_channel_origin of it service + + Folio ----> sale_channel_origin_id = Door + | + ----> service.sale_channel_origin_id = Door + + Change sale_channel_origin of folio to Mail + Folio ----> sale_channel_origin_id = Mail + | + ----> service.sale_channel_origin_id = Mail ---CHECKING THIS--- + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + self.folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": self.partner1.name, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + } + ) + # ACT + self.folio1.sale_channel_origin_id = self.sale_channel_mail.id + + # ASSERT + self.assertEqual( + self.folio1.sale_channel_origin_id, + self.service1.sale_channel_origin_id, + "Service must have equal sale_channel_origin than folio", + ) + + @freeze_time("2002-03-05") + def test_change_origin_service_change_origin_folio(self): + """ + When a folio has only one service, when changing the service sale_channel_origin + folio.sale_channel_origin will also change + + Folio ----> sale_channel_origin_id = Door + | + ----> service.sale_channel_origin_id = Door + + Change sale_channel_origin of service to Mail + Folio ----> sale_channel_origin_id = Mail ---CHECKING THIS--- + | + ----> service.sale_channel_origin_id = Mail + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + self.folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": self.partner1.name, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + } + ) + # ACT + self.service1.sale_channel_origin_id = self.sale_channel_mail.id + + # ASSERT + self.assertEqual( + self.folio1.sale_channel_origin_id, + self.service1.sale_channel_origin_id, + "Service must have equal sale_channel_origin than folio", + ) + + @freeze_time("2002-03-07") + def test_folio_sale_channels_with_service_different_origins(self): + """ + Check that on a folio with services with differents sale_channel_origin + the sale_channel_ids of folio are calculated well. + In this case sale_channel_ids must be formed by sale_channel_origin of its + services + + Folio ----> sale_channel_origin_id = Door + ----> sale_cahnnel_ids = {Door, Mail} ---CHECKING THIS---- + | + ----> service.sale_channel_origin_id = Door + | + ----> service.sale_channel_origin_id = Mail + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + self.folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": self.partner1.name, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + # ACT + self.service1 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + } + ) + self.service2 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + "sale_channel_origin_id": self.sale_channel_mail.id, + } + ) + + expected_sale_channels = self.folio1.service_ids.mapped( + "sale_channel_origin_id" + ) + + # ASSERT + self.assertEqual( + self.folio1.sale_channel_ids, + expected_sale_channels, + "sale_channel_ids must be the set of sale_channel_origin of its services", + ) + + @freeze_time("2002-03-10") + def test_change_origin_folio_change_origin_service(self): + """ + Check that when a folio has several services with different sale_channel_origin_id + and change sale_channel_origin_id of folio, only changes origin of those services that + match with the sale_channel_origin changed + + Folio ----> sale_channel_origin_id = Door + | + ----> service[0].sale_channel_origin_id = Door + | + ----> service[1].sale_channel_origin_id = Mail + + Change origin of folio to Phone, expected results: + Folio ----> sale_channel_origin_id = Phone + | + ----> service[0].sale_channel_origin_id = Phone ---CHECKIN THIS--- + | + ----> service[1].sale_channel_origin_id = Mail + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + self.folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": self.partner1.name, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + } + ) + self.service2 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + "sale_channel_origin_id": self.sale_channel_mail.id, + } + ) + # ACT + self.folio1.sale_channel_origin_id = self.sale_channel_phone.id + + # ASSERT + self.assertIn( + self.sale_channel_phone, + self.folio1.service_ids.mapped("sale_channel_origin_id"), + "sale_channel_origin_id of that service must be changed", + ) + + @freeze_time("2002-03-13") + def test_change_origin_folio_no_change_origin_service(self): + """ + Check that when a folio has several services with different sale_channel_origin_id + and change sale_channel_origin_id of folio, only changes origin of those services that + match with the sale_channel_origin changed. Then services that didn't initially + match with sale_channel_origin of folio shouldn't have changed + + Folio ----> sale_channel_origin_id = Door + | + ----> service[0].sale_channel_origin_id = Door + | + ----> service[1].sale_channel_origin_id = Mail + + Change origin of folio to Phone, expected results: + Folio ----> sale_channel_origin_id = Phone + | + ----> service[0].sale_channel_origin_id = Phone + | + ----> service[1].sale_channel_origin_id = Mail ---CHECKIN THIS--- + """ + # ARRANGE + self.product1 = self.env["product.product"].create( + { + "name": "Test Product 1", + "per_day": True, + "consumed_on": "after", + "is_extra_bed": True, + } + ) + self.folio1 = self.env["pms.folio"].create( + { + "pms_property_id": self.pms_property1.id, + "partner_name": self.partner1.name, + "sale_channel_origin_id": self.sale_channel_door.id, + } + ) + + self.service1 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + } + ) + self.service2 = self.env["pms.service"].create( + { + "product_id": self.product1.id, + "is_board_service": False, + "folio_id": self.folio1.id, + "sale_channel_origin_id": self.sale_channel_mail.id, + } + ) + # ACT + self.folio1.sale_channel_origin_id = self.sale_channel_phone.id + + # ASSERT + self.assertIn( + self.sale_channel_mail, + self.folio1.service_ids.mapped("sale_channel_origin_id"), + "sale_channel_origin_id of that service mustn't be changed", + ) diff --git a/pms/tests/test_pms_wizard_split_join_swap_reservation.py b/pms/tests/test_pms_wizard_split_join_swap_reservation.py index c1f6853ef..e91538492 100644 --- a/pms/tests/test_pms_wizard_split_join_swap_reservation.py +++ b/pms/tests/test_pms_wizard_split_join_swap_reservation.py @@ -56,6 +56,14 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): self.partner1 = self.env["res.partner"].create({"name": "Antón"}) + # create a sale channel + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) + # UNIFY TESTS # review def test_unify_reservation_avail_should(self): """ @@ -83,6 +91,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -119,6 +128,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -129,6 +139,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1 = self.env["pms.reservation"].create( @@ -139,6 +150,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "room_type_id": self.test_room_type_double.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2.flush() @@ -164,6 +176,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -174,6 +187,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2.flush() @@ -215,6 +229,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -225,6 +240,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -274,6 +290,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -284,6 +301,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -332,6 +350,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -342,6 +361,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -394,6 +414,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -404,6 +425,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -456,6 +478,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -466,6 +489,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -515,6 +539,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -561,6 +586,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -572,6 +598,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -582,6 +609,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -633,6 +661,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -644,6 +673,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r2 = self.env["pms.reservation"].create( @@ -654,6 +684,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -699,6 +730,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -736,6 +768,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -773,6 +806,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -819,6 +853,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -861,6 +896,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -900,6 +936,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -930,6 +967,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() @@ -959,6 +997,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room2.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1 = self.env["pms.reservation"].create( @@ -969,6 +1008,7 @@ class TestPmsWizardSplitJoinSwapReservation(TestPms): "adults": 2, "preferred_room_id": self.room1.id, "partner_id": self.partner1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.flush() diff --git a/pms/tests/test_product_template.py b/pms/tests/test_product_template.py index 730d77e5f..eb61f894f 100644 --- a/pms/tests/test_product_template.py +++ b/pms/tests/test_product_template.py @@ -31,6 +31,13 @@ class TestProductTemplate(TestPms): "default_code": "BST", } ) + # create a sale channel + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) def test_bs_consumed_on_after(self): """ @@ -69,6 +76,7 @@ class TestProductTemplate(TestPms): "pms_property_id": self.pms_property1.id, "partner_id": self.partner.id, "board_service_room_id": board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -115,6 +123,7 @@ class TestProductTemplate(TestPms): "pms_property_id": self.pms_property1.id, "partner_id": self.partner.id, "board_service_room_id": board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) # ASSERT @@ -162,6 +171,7 @@ class TestProductTemplate(TestPms): "pms_property_id": self.pms_property1.id, "partner_id": self.partner.id, "board_service_room_id": board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) reservation.flush() @@ -211,6 +221,7 @@ class TestProductTemplate(TestPms): "pms_property_id": self.pms_property1.id, "partner_id": self.partner.id, "board_service_room_id": board_service_room_type.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) reservation.flush() @@ -267,6 +278,7 @@ class TestProductTemplate(TestPms): "partner_id": self.partner.id, "board_service_room_id": board_service_room_type.id, "adults": 2, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -298,6 +310,7 @@ class TestProductTemplate(TestPms): "pms_property_id": self.pms_property1.id, "partner_id": self.partner.id, "service_ids": [extra_bed_service.id], + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) reservation._check_adults() diff --git a/pms/tests/test_shared_room.py b/pms/tests/test_shared_room.py index 2408805c4..3bcb98b86 100644 --- a/pms/tests/test_shared_room.py +++ b/pms/tests/test_shared_room.py @@ -85,6 +85,14 @@ class TestPmsSharedRoom(TestPms): } ) + # create a sale channel + self.sale_channel_direct1 = self.env["pms.sale.channel"].create( + { + "name": "Door", + "channel_type": "direct", + } + ) + def test_count_avail_beds_with_room_occupied(self): """ Check that not allow to create a bed reservation with a room occupied @@ -104,6 +112,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -137,6 +146,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -182,6 +192,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -217,6 +228,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) res1.flush() @@ -250,6 +262,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -285,6 +298,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -321,6 +335,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -355,6 +370,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -370,6 +386,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.flush() @@ -394,6 +411,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) @@ -410,6 +428,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r_test.flush() @@ -435,6 +454,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.action_cancel() @@ -471,6 +491,7 @@ class TestPmsSharedRoom(TestPms): "checkin": today, "checkout": tomorrow, "pms_property_id": self.pms_property1.id, + "sale_channel_origin_id": self.sale_channel_direct1.id, } ) r1.action_cancel() diff --git a/pms/views/pms_folio_views.xml b/pms/views/pms_folio_views.xml index c835bdda5..9c0d68505 100644 --- a/pms/views/pms_folio_views.xml +++ b/pms/views/pms_folio_views.xml @@ -348,13 +348,15 @@ name="agency_id" attrs="{'invisible': [('reservation_type', 'not in', 'normal')]}" /> +
@@ -786,12 +788,12 @@ name="group_customer" context="{'group_by':'partner_id'}" /> - + + + + + + - diff --git a/pms/views/pms_reservation_views.xml b/pms/views/pms_reservation_views.xml index b77a394fa..a273e7d42 100644 --- a/pms/views/pms_reservation_views.xml +++ b/pms/views/pms_reservation_views.xml @@ -441,17 +441,28 @@ options="{'no_create': True,'no_open': True}" attrs="{'invisible': [('reservation_type','in',('out'))]}" /> - + + + + @@ -491,6 +502,8 @@ name="cancel_discount" attrs="{'column_invisible': [('parent.state','!=','cancel')]}" /> + + @@ -554,6 +567,11 @@ attrs="{'readonly': [('per_day','=',True)]}" force_save="1" /> + +