mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
Merge pull request #14 from commitsun/14.0-pms-minimize-split-rooms
Compute rooms on splitted reservations
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
from . import wizards
|
||||||
from .init_hook import post_init_hook
|
from .init_hook import post_init_hook
|
||||||
|
|
||||||
# from . import wizard
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
"views/product_template_views.xml",
|
"views/product_template_views.xml",
|
||||||
"views/webclient_templates.xml",
|
"views/webclient_templates.xml",
|
||||||
"views/ir_sequence_views.xml",
|
"views/ir_sequence_views.xml",
|
||||||
|
"wizards/wizard_reservation.xml",
|
||||||
],
|
],
|
||||||
"demo": [
|
"demo": [
|
||||||
"demo/pms_master_data.xml",
|
"demo/pms_master_data.xml",
|
||||||
|
|||||||
@@ -213,7 +213,7 @@
|
|||||||
name="reservation_ids"
|
name="reservation_ids"
|
||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_1'),
|
'preferred_room_id': ref('pms_room_1'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=19)),
|
'checkin': (DateTime.today() + timedelta(days=19)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=20)),
|
'checkout': (DateTime.today() + timedelta(days=20)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -233,7 +233,6 @@
|
|||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_type_id': ref('pms_room_type_2'),
|
'room_type_id': ref('pms_room_type_2'),
|
||||||
'room_id': ref('pms_room_4'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=19)),
|
'checkin': (DateTime.today() + timedelta(days=19)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=20)),
|
'checkout': (DateTime.today() + timedelta(days=20)),
|
||||||
'adults': 2,
|
'adults': 2,
|
||||||
@@ -303,7 +302,7 @@
|
|||||||
name="reservation_ids"
|
name="reservation_ids"
|
||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_0'),
|
'preferred_room_id': ref('pms_room_0'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=19)),
|
'checkin': (DateTime.today() + timedelta(days=19)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=20)),
|
'checkout': (DateTime.today() + timedelta(days=20)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -319,7 +318,7 @@
|
|||||||
name="reservation_ids"
|
name="reservation_ids"
|
||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_7'),
|
'preferred_room_id': ref('pms_room_7'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=21)),
|
'checkin': (DateTime.today() + timedelta(days=21)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=22)),
|
'checkout': (DateTime.today() + timedelta(days=22)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -370,7 +369,6 @@
|
|||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_type_id': ref('pms_room_type_2'),
|
'room_type_id': ref('pms_room_type_2'),
|
||||||
'room_id': ref('pms_room_4'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=21)),
|
'checkin': (DateTime.today() + timedelta(days=21)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=22)),
|
'checkout': (DateTime.today() + timedelta(days=22)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -391,7 +389,7 @@
|
|||||||
name="reservation_ids"
|
name="reservation_ids"
|
||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_6'),
|
'preferred_room_id': ref('pms_room_6'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=20)),
|
'checkin': (DateTime.today() + timedelta(days=20)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=21)),
|
'checkout': (DateTime.today() + timedelta(days=21)),
|
||||||
'adults': 3,
|
'adults': 3,
|
||||||
@@ -408,7 +406,6 @@
|
|||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_type_id': ref('pms_room_type_2'),
|
'room_type_id': ref('pms_room_type_2'),
|
||||||
'room_id': ref('pms_room_4'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=23)),
|
'checkin': (DateTime.today() + timedelta(days=23)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=24)),
|
'checkout': (DateTime.today() + timedelta(days=24)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -526,7 +523,6 @@
|
|||||||
}),
|
}),
|
||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_5'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=24)),
|
'checkin': (DateTime.today() + timedelta(days=24)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=25)),
|
'checkout': (DateTime.today() + timedelta(days=25)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -544,7 +540,7 @@
|
|||||||
eval="[(5, 0),
|
eval="[(5, 0),
|
||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_7'),
|
'preferred_room_id': ref('pms_room_7'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=24)),
|
'checkin': (DateTime.today() + timedelta(days=24)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=25)),
|
'checkout': (DateTime.today() + timedelta(days=25)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -563,7 +559,7 @@
|
|||||||
eval="[(5, 0),
|
eval="[(5, 0),
|
||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_0'),
|
'preferred_room_id': ref('pms_room_0'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=25)),
|
'checkin': (DateTime.today() + timedelta(days=25)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=32)),
|
'checkout': (DateTime.today() + timedelta(days=32)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -580,7 +576,7 @@
|
|||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_type_id': ref('pms_room_type_1'),
|
'room_type_id': ref('pms_room_type_1'),
|
||||||
'room_id': ref('pms_room_1'),
|
'preferred_room_id': ref('pms_room_1'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=25)),
|
'checkin': (DateTime.today() + timedelta(days=25)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=32)),
|
'checkout': (DateTime.today() + timedelta(days=32)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -596,7 +592,7 @@
|
|||||||
eval="[(5, 0),
|
eval="[(5, 0),
|
||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_2'),
|
'preferred_room_id': ref('pms_room_2'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=25)),
|
'checkin': (DateTime.today() + timedelta(days=25)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=32)),
|
'checkout': (DateTime.today() + timedelta(days=32)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -614,7 +610,6 @@
|
|||||||
(0, 0, {
|
(0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_type_id': ref('pms_room_type_2'),
|
'room_type_id': ref('pms_room_type_2'),
|
||||||
'room_id': ref('pms_room_5'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=25)),
|
'checkin': (DateTime.today() + timedelta(days=25)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=31)),
|
'checkout': (DateTime.today() + timedelta(days=31)),
|
||||||
'adults': 2,
|
'adults': 2,
|
||||||
@@ -637,7 +632,7 @@
|
|||||||
name="reservation_ids"
|
name="reservation_ids"
|
||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_id': ref('pms_room_7'),
|
'preferred_room_id': ref('pms_room_7'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=25)),
|
'checkin': (DateTime.today() + timedelta(days=25)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=26)),
|
'checkout': (DateTime.today() + timedelta(days=26)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
@@ -689,7 +684,7 @@
|
|||||||
eval="[(5, 0), (0, 0, {
|
eval="[(5, 0), (0, 0, {
|
||||||
'pricelist_id': ref('product.list0'),
|
'pricelist_id': ref('product.list0'),
|
||||||
'room_type_id': ref('pms_room_type_3'),
|
'room_type_id': ref('pms_room_type_3'),
|
||||||
'room_id': ref('pms_room_6'),
|
'preferred_room_id': ref('pms_room_6'),
|
||||||
'checkin': (DateTime.today() + timedelta(days=29)),
|
'checkin': (DateTime.today() + timedelta(days=29)),
|
||||||
'checkout': (DateTime.today() + timedelta(days=30)),
|
'checkout': (DateTime.today() + timedelta(days=30)),
|
||||||
'adults': 1,
|
'adults': 1,
|
||||||
|
|||||||
@@ -106,15 +106,12 @@ class PmsReservation(models.Model):
|
|||||||
# required=True,
|
# required=True,
|
||||||
)
|
)
|
||||||
priority = fields.Integer(compute="_compute_priority", store="True", index=True)
|
priority = fields.Integer(compute="_compute_priority", store="True", index=True)
|
||||||
room_id = fields.Many2one(
|
|
||||||
|
preferred_room_id = fields.Many2one(
|
||||||
"pms.room",
|
"pms.room",
|
||||||
string="Room",
|
string="Room",
|
||||||
tracking=True,
|
tracking=True,
|
||||||
ondelete="restrict",
|
ondelete="restrict",
|
||||||
compute="_compute_room_id",
|
|
||||||
store=True,
|
|
||||||
readonly=False,
|
|
||||||
# required=True,
|
|
||||||
domain="[('id', 'in', allowed_room_ids)]",
|
domain="[('id', 'in', allowed_room_ids)]",
|
||||||
)
|
)
|
||||||
allowed_room_ids = fields.Many2many(
|
allowed_room_ids = fields.Many2many(
|
||||||
@@ -262,6 +259,13 @@ class PmsReservation(models.Model):
|
|||||||
store=True,
|
store=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rooms = fields.Char(
|
||||||
|
string="Room/s",
|
||||||
|
compute="_compute_rooms",
|
||||||
|
store=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
credit_card_details = fields.Text(related="folio_id.credit_card_details")
|
credit_card_details = fields.Text(related="folio_id.credit_card_details")
|
||||||
cancelled_reason = fields.Selection(
|
cancelled_reason = fields.Selection(
|
||||||
[("late", "Late"), ("intime", "In time"), ("noshow", "No Show")],
|
[("late", "Late"), ("intime", "In time"), ("noshow", "No Show")],
|
||||||
@@ -419,22 +423,15 @@ class PmsReservation(models.Model):
|
|||||||
# TODO: Logic priority (100 by example)
|
# TODO: Logic priority (100 by example)
|
||||||
self.priority = 100
|
self.priority = 100
|
||||||
|
|
||||||
@api.depends("reservation_line_ids", "reservation_line_ids.room_id")
|
@api.depends("preferred_room_id")
|
||||||
def _compute_room_id(self):
|
|
||||||
for reservation in self.filtered(
|
|
||||||
lambda r: r.reservation_line_ids and not r.room_id
|
|
||||||
):
|
|
||||||
reservation.room_id = reservation.reservation_line_ids[0].room_id
|
|
||||||
|
|
||||||
@api.depends("room_id")
|
|
||||||
def _compute_room_type_id(self):
|
def _compute_room_type_id(self):
|
||||||
for reservation in self:
|
for reservation in self:
|
||||||
if reservation.room_id and not reservation.room_type_id:
|
if reservation.preferred_room_id and not reservation.room_type_id:
|
||||||
reservation.room_type_id = reservation.room_id.room_type_id.id
|
reservation.room_type_id = reservation.preferred_room_id.room_type_id.id
|
||||||
elif not reservation.room_type_id:
|
elif not reservation.room_type_id:
|
||||||
reservation.room_type_id = False
|
reservation.room_type_id = False
|
||||||
|
|
||||||
@api.depends("reservation_line_ids.date", "overbooking", "state", "room_id")
|
@api.depends("reservation_line_ids.date", "overbooking", "state", "preferred_room_id")
|
||||||
def _compute_allowed_room_ids(self):
|
def _compute_allowed_room_ids(self):
|
||||||
for reservation in self:
|
for reservation in self:
|
||||||
if reservation.checkin and reservation.checkout:
|
if reservation.checkin and reservation.checkout:
|
||||||
@@ -541,12 +538,12 @@ class PmsReservation(models.Model):
|
|||||||
reservation.pricelist_id = pricelist_id
|
reservation.pricelist_id = pricelist_id
|
||||||
|
|
||||||
# REVIEW: Dont run with set room_type_id -> room_id(compute)-> No set adults¿?
|
# REVIEW: Dont run with set room_type_id -> room_id(compute)-> No set adults¿?
|
||||||
@api.depends("room_id")
|
@api.depends("preferred_room_id")
|
||||||
def _compute_adults(self):
|
def _compute_adults(self):
|
||||||
for reservation in self:
|
for reservation in self:
|
||||||
if reservation.room_id:
|
if reservation.preferred_room_id:
|
||||||
if reservation.adults == 0:
|
if reservation.adults == 0:
|
||||||
reservation.adults = reservation.room_id.capacity
|
reservation.adults = reservation.preferred_room_id.capacity
|
||||||
elif not reservation.adults:
|
elif not reservation.adults:
|
||||||
reservation.adults = 0
|
reservation.adults = 0
|
||||||
|
|
||||||
@@ -557,6 +554,8 @@ class PmsReservation(models.Model):
|
|||||||
reservation.splitted = True
|
reservation.splitted = True
|
||||||
else:
|
else:
|
||||||
reservation.splitted = False
|
reservation.splitted = False
|
||||||
|
reservation.preferred_room_id = reservation.reservation_line_ids[0].room_id
|
||||||
|
|
||||||
|
|
||||||
@api.depends("state", "qty_to_invoice", "qty_invoiced")
|
@api.depends("state", "qty_to_invoice", "qty_invoiced")
|
||||||
def _compute_invoice_status(self):
|
def _compute_invoice_status(self):
|
||||||
@@ -691,7 +690,7 @@ class PmsReservation(models.Model):
|
|||||||
|
|
||||||
# TODO: Use default values on checkin /checkout is empty
|
# TODO: Use default values on checkin /checkout is empty
|
||||||
@api.constrains(
|
@api.constrains(
|
||||||
"checkin", "checkout", "state", "room_id", "overbooking", "reselling"
|
"checkin", "checkout", "state", "preferred_room_id", "overbooking", "reselling"
|
||||||
)
|
)
|
||||||
def check_dates(self):
|
def check_dates(self):
|
||||||
"""
|
"""
|
||||||
@@ -791,6 +790,24 @@ class PmsReservation(models.Model):
|
|||||||
"target": "new",
|
"target": "new",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def open_reservation_wizard(self):
|
||||||
|
rooms_available = self.env["pms.room.type.availability"].rooms_available(
|
||||||
|
checkin=self.checkin,
|
||||||
|
checkout=self.checkout,
|
||||||
|
current_lines=self.reservation_line_ids.ids,
|
||||||
|
)
|
||||||
|
# REVIEW: check capacity room
|
||||||
|
return {
|
||||||
|
'view_type': 'form',
|
||||||
|
'view_mode': 'form',
|
||||||
|
'name': 'Unify the reservation',
|
||||||
|
'res_model': 'pms.reservation.wizard',
|
||||||
|
'target': 'new',
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
'context': {'rooms_available': rooms_available.ids,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# ORM Overrides
|
# ORM Overrides
|
||||||
@api.model
|
@api.model
|
||||||
def name_search(self, name="", args=None, operator="ilike", limit=100):
|
def name_search(self, name="", args=None, operator="ilike", limit=100):
|
||||||
@@ -800,7 +817,7 @@ class PmsReservation(models.Model):
|
|||||||
args += [
|
args += [
|
||||||
"|",
|
"|",
|
||||||
("folio_id.name", operator, name),
|
("folio_id.name", operator, name),
|
||||||
("room_id.name", operator, name),
|
("preferred_room_id.name", operator, name),
|
||||||
]
|
]
|
||||||
return super(PmsReservation, self).name_search(
|
return super(PmsReservation, self).name_search(
|
||||||
name="", args=args, operator="ilike", limit=limit
|
name="", args=args, operator="ilike", limit=limit
|
||||||
@@ -809,7 +826,7 @@ class PmsReservation(models.Model):
|
|||||||
def name_get(self):
|
def name_get(self):
|
||||||
result = []
|
result = []
|
||||||
for res in self:
|
for res in self:
|
||||||
name = u"{} ({})".format(res.folio_id.name, res.room_id.name)
|
name = u"{} ({})".format(res.folio_id.name, res.rooms if res.rooms else 'No room')
|
||||||
result.append((res.id, name))
|
result.append((res.id, name))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -911,7 +928,7 @@ class PmsReservation(models.Model):
|
|||||||
"price_subtotal": self.price_subtotal,
|
"price_subtotal": self.price_subtotal,
|
||||||
"splitted": self.splitted,
|
"splitted": self.splitted,
|
||||||
"room_type_id": self.room_type_id.id,
|
"room_type_id": self.room_type_id.id,
|
||||||
"room_id": self.room_id.id,
|
"preferred_room_id": self.preferred_room_id.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
def confirm(self):
|
def confirm(self):
|
||||||
@@ -1000,8 +1017,8 @@ class PmsReservation(models.Model):
|
|||||||
if record.reservation_type != "out":
|
if record.reservation_type != "out":
|
||||||
record.checkin_partner_count = len(record.checkin_partner_ids)
|
record.checkin_partner_count = len(record.checkin_partner_ids)
|
||||||
record.checkin_partner_pending_count = (
|
record.checkin_partner_pending_count = (
|
||||||
record.adults + record.children
|
record.adults + record.children
|
||||||
) - len(record.checkin_partner_ids)
|
) - len(record.checkin_partner_ids)
|
||||||
else:
|
else:
|
||||||
record.checkin_partner_count = 0
|
record.checkin_partner_count = 0
|
||||||
record.checkin_partner_pending_count = 0
|
record.checkin_partner_pending_count = 0
|
||||||
@@ -1058,3 +1075,14 @@ class PmsReservation(models.Model):
|
|||||||
record.tax_ids = product.taxes_id.filtered(
|
record.tax_ids = product.taxes_id.filtered(
|
||||||
lambda r: not record.company_id or r.company_id == folio.company_id
|
lambda r: not record.company_id or r.company_id == folio.company_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@api.depends("reservation_line_ids", "reservation_line_ids.room_id")
|
||||||
|
def _compute_rooms(self):
|
||||||
|
self.rooms = False
|
||||||
|
|
||||||
|
for reservation in self:
|
||||||
|
if reservation.splitted:
|
||||||
|
reservation.rooms = ", ".join([r for r in reservation.reservation_line_ids.mapped('room_id.name')])
|
||||||
|
reservation.preferred_room_id = False
|
||||||
|
else:
|
||||||
|
reservation.rooms = reservation.preferred_room_id.name
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
# Copyright 2017 Dario Lodeiros
|
# Copyright 2017 Dario Lodeiros
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
import datetime
|
||||||
|
import operator
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PmsReservationLine(models.Model):
|
class PmsReservationLine(models.Model):
|
||||||
_name = "pms.reservation.line"
|
_name = "pms.reservation.line"
|
||||||
_description = "Reservations by day"
|
_description = "Reservations by day"
|
||||||
@@ -91,37 +91,96 @@ class PmsReservationLine(models.Model):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Compute and Search methods
|
# Compute and Search methods
|
||||||
@api.depends(
|
@api.depends("reservation_id.room_type_id")
|
||||||
"reservation_id.adults",
|
|
||||||
"reservation_id.room_type_id",
|
|
||||||
)
|
|
||||||
def _compute_room_id(self):
|
def _compute_room_id(self):
|
||||||
for line in self:
|
for line in self.sorted(key=lambda r: (r.reservation_id, r.date)):
|
||||||
if line.reservation_id.room_type_id:
|
|
||||||
preferred_room = line.reservation_id.room_id
|
# if the reservation has a room type and no room id
|
||||||
rooms_available = self.env[
|
if line.reservation_id.room_type_id and not line.room_id:
|
||||||
"pms.room.type.availability"
|
|
||||||
].rooms_available(
|
# we get the rooms available for the entire stay
|
||||||
checkin=line.date,
|
rooms_available = self.env[ "pms.room.type.availability"].rooms_available(
|
||||||
checkout=line.date + timedelta(1),
|
checkin=line.reservation_id.checkin,
|
||||||
room_type_id=line.reservation_id.room_type_id.id or False,
|
checkout=line.reservation_id.checkout,
|
||||||
current_lines=line._origin.id,
|
room_type_id=line.reservation_id.room_type_id.id,
|
||||||
|
current_lines=line._origin.reservation_id.reservation_line_ids.ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# if there is availability for the entire stay
|
||||||
if rooms_available:
|
if rooms_available:
|
||||||
if preferred_room.id in rooms_available.ids:
|
|
||||||
room_chosen = preferred_room
|
# if the reservation has a preferred room
|
||||||
|
if line.reservation_id.preferred_room_id:
|
||||||
|
|
||||||
|
# if the preferred room is available
|
||||||
|
if line.reservation_id.preferred_room_id in rooms_available:
|
||||||
|
line.room_id = line.reservation_id.preferred_room_id
|
||||||
|
|
||||||
|
# if the preferred room is NOT available
|
||||||
|
else:
|
||||||
|
raise ValidationError(_("%s: No room available.")% (line.reservation_id.preferred_room_id.name))
|
||||||
|
|
||||||
|
# otherwise we assign the first of those available for the entire stay
|
||||||
else:
|
else:
|
||||||
room_chosen = rooms_available[0]
|
line.room_id = rooms_available[0]
|
||||||
line.room_id = room_chosen
|
|
||||||
|
# if there is no availability for the entire stay without changing rooms (we assume a split reservation)
|
||||||
else:
|
else:
|
||||||
line.room_id = False
|
rooms_ranking = dict()
|
||||||
raise ValidationError(
|
|
||||||
_("%s: No rooms available")
|
# we go through the rooms of the type
|
||||||
% (line.reservation_id.room_type_id.name)
|
for room in self.env['pms.room'].search([('room_type_id', '=', line.reservation_id.room_type_id.id)]):
|
||||||
)
|
|
||||||
line._check_adults()
|
# we iterate the dates from the date of the line to the checkout
|
||||||
else:
|
for date_iterator in \
|
||||||
line.room_id = False
|
[line.date + datetime.timedelta(days=x) for x in range(0, (line.reservation_id.checkout - line.date).days)]:
|
||||||
|
|
||||||
|
# if the room is already assigned for a date we go to the next room
|
||||||
|
if self.env['pms.reservation.line'].search_count([
|
||||||
|
('date', '=', date_iterator),
|
||||||
|
('room_id', '=', room.id),
|
||||||
|
('id', 'not in', line.reservation_id.reservation_line_ids.ids),
|
||||||
|
("occupies_availability", "=", True),
|
||||||
|
]) > 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
# if the room is not assigned for a date we add it to the ranking / update its ranking
|
||||||
|
else:
|
||||||
|
rooms_ranking[room.id] = 1 if room.id not in rooms_ranking else rooms_ranking[room.id] + 1
|
||||||
|
if len(rooms_ranking) == 0:
|
||||||
|
raise ValidationError(_("%s: No room type available") % (line.reservation_id.room_type_id.name))
|
||||||
|
else:
|
||||||
|
# we get the best score in the ranking
|
||||||
|
best = max(rooms_ranking.values())
|
||||||
|
|
||||||
|
# we keep the rooms with the best ranking
|
||||||
|
bests = {key: value for (key, value) in rooms_ranking.items() if value == best}
|
||||||
|
|
||||||
|
# if there is a tie in the rankings
|
||||||
|
if len(bests) > 1:
|
||||||
|
|
||||||
|
# we get the line from last night
|
||||||
|
date_last_night = line.date + datetime.timedelta(days=-1)
|
||||||
|
line_past_night = self.env['pms.reservation.line'].search([
|
||||||
|
('date', '=', date_last_night),
|
||||||
|
('reservation_id', '=', line.reservation_id.id)
|
||||||
|
])
|
||||||
|
|
||||||
|
# if there is the night before and if the room from the night before is in the ranking
|
||||||
|
if line_past_night and line_past_night.room_id.id in bests:
|
||||||
|
line.room_id = line_past_night.room_id.id
|
||||||
|
|
||||||
|
# if the room from the night before is not in the ranking or there is no night before
|
||||||
|
else:
|
||||||
|
# At this point we set the room with the best ranking, no matter what it is
|
||||||
|
line.room_id = list(bests.keys())[0]
|
||||||
|
|
||||||
|
# if there is no tie in the rankings
|
||||||
|
else:
|
||||||
|
# At this point we set the room with the best ranking, no matter what it is
|
||||||
|
line.room_id = list(bests.keys())[0]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
"reservation_id",
|
"reservation_id",
|
||||||
@@ -158,7 +217,7 @@ class PmsReservationLine(models.Model):
|
|||||||
line.reservation_id.tax_ids,
|
line.reservation_id.tax_ids,
|
||||||
line.reservation_id.company_id,
|
line.reservation_id.company_id,
|
||||||
)
|
)
|
||||||
_logger.info(line.price)
|
# _logger.info(line.price)
|
||||||
# TODO: Out of service 0 amount
|
# TODO: Out of service 0 amount
|
||||||
else:
|
else:
|
||||||
line.price = line._origin.price
|
line.price = line._origin.price
|
||||||
|
|||||||
@@ -47,3 +47,4 @@ manager_access_pms_board_service_line,manager_access_pms_board_service_line,mode
|
|||||||
manager_access_property,manager_access_property,model_pms_property,pms.group_pms_manager,1,1,1,1
|
manager_access_property,manager_access_property,model_pms_property,pms.group_pms_manager,1,1,1,1
|
||||||
manager_access_pms_cancelation_rule,manager_access_pms_cancelation_rule,model_pms_cancelation_rule,pms.group_pms_manager,1,1,1,1
|
manager_access_pms_cancelation_rule,manager_access_pms_cancelation_rule,model_pms_cancelation_rule,pms.group_pms_manager,1,1,1,1
|
||||||
manager_access_availability,manager_access_availability,model_pms_room_type_availability,pms.group_pms_manager,1,1,1,1
|
manager_access_availability,manager_access_availability,model_pms_room_type_availability,pms.group_pms_manager,1,1,1,1
|
||||||
|
user_access_pms_reservation_wizard,user_access_pms_reservation_wizard,model_pms_reservation_wizard,pms.group_pms_user,1,1,1,1
|
||||||
|
|||||||
|
@@ -1,20 +1,80 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from _pytest.skipping import Skip
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from odoo import fields
|
from odoo import fields
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from .common import TestHotel
|
from .common import TestHotel
|
||||||
|
|
||||||
|
|
||||||
@freeze_time("2012-01-14")
|
@freeze_time("2012-01-14")
|
||||||
class TestPmsReservations(TestHotel):
|
class TestPmsReservations(TestHotel):
|
||||||
|
|
||||||
|
def create_common_scenario(self):
|
||||||
|
# create a room type restriction
|
||||||
|
self.room_type_restriction = self.env['pms.room.type.restriction'].create(
|
||||||
|
{
|
||||||
|
'name': 'Restriction plan for TEST'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# create a property
|
||||||
|
self.property = self.env['pms.property'].create(
|
||||||
|
{
|
||||||
|
'name': 'MY PMS TEST',
|
||||||
|
'company_id': self.env.ref('base.main_company').id,
|
||||||
|
'default_pricelist_id': self.env.ref('product.list0').id,
|
||||||
|
'default_restriction_id': self.room_type_restriction.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
# create room type class
|
||||||
|
self.room_type_class = self.env['pms.room.type.class'].create(
|
||||||
|
{
|
||||||
|
'name': 'Room'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# create room type
|
||||||
|
self.room_type_double = self.env['pms.room.type'].create(
|
||||||
|
{
|
||||||
|
'pms_property_ids': [self.property.id],
|
||||||
|
'name': 'Double Test',
|
||||||
|
'code_type': 'DBL_Test',
|
||||||
|
'class_id': self.room_type_class.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# create rooms
|
||||||
|
self.room1 = self.env['pms.room'].create(
|
||||||
|
{
|
||||||
|
'pms_property_id': self.property.id,
|
||||||
|
'name': 'Double 101',
|
||||||
|
'room_type_id': self.room_type_double.id,
|
||||||
|
'capacity': 2
|
||||||
|
})
|
||||||
|
|
||||||
|
self.room2 = self.env['pms.room'].create(
|
||||||
|
{
|
||||||
|
'pms_property_id': self.property.id,
|
||||||
|
'name': 'Double 102',
|
||||||
|
'room_type_id': self.room_type_double.id,
|
||||||
|
'capacity': 2
|
||||||
|
})
|
||||||
|
|
||||||
|
self.room3 = self.env['pms.room'].create(
|
||||||
|
{
|
||||||
|
'pms_property_id': self.property.id,
|
||||||
|
'name': 'Double 103',
|
||||||
|
'room_type_id': self.room_type_double.id,
|
||||||
|
'capacity': 2
|
||||||
|
})
|
||||||
|
self.demo_user = self.env.ref("base.user_admin")
|
||||||
|
|
||||||
|
|
||||||
def test_create_reservation(self):
|
def test_create_reservation(self):
|
||||||
today = fields.date.today()
|
today = fields.date.today()
|
||||||
checkin = today + datetime.timedelta(days=8)
|
checkin = today + datetime.timedelta(days=8)
|
||||||
checkout = checkin + datetime.timedelta(days=11)
|
checkout = checkin + datetime.timedelta(days=11)
|
||||||
demo_user = self.env.ref("base.user_demo")
|
|
||||||
customer = self.env.ref("base.res_partner_12")
|
customer = self.env.ref("base.res_partner_12")
|
||||||
reservation_vals = {
|
reservation_vals = {
|
||||||
"checkin": checkin,
|
"checkin": checkin,
|
||||||
@@ -24,7 +84,7 @@ class TestPmsReservations(TestHotel):
|
|||||||
"pms_property_id": self.main_hotel_property.id,
|
"pms_property_id": self.main_hotel_property.id,
|
||||||
}
|
}
|
||||||
reservation = (
|
reservation = (
|
||||||
self.env["pms.reservation"].with_user(demo_user).create(reservation_vals)
|
self.env["pms.reservation"].create(reservation_vals)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@@ -36,7 +96,401 @@ class TestPmsReservations(TestHotel):
|
|||||||
reservation.reservation_line_ids[-1].date,
|
reservation.reservation_line_ids[-1].date,
|
||||||
checkout - datetime.timedelta(1),
|
checkout - datetime.timedelta(1),
|
||||||
"Reservation lines don't end in the correct date",
|
"Reservation lines don't end in the correct date",
|
||||||
|
)
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation01(self):
|
||||||
|
"""
|
||||||
|
The reservation shouldn't be splitted
|
||||||
|
preferred_room_id with availability provided
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| Double 101 | test | test | test | | | |
|
||||||
|
| Double 102 | | | | | | |
|
||||||
|
| Double 103 | | | | | | |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||||
|
"adults": 2,
|
||||||
|
"preferred_room_id": self.room1.id
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
r_test.flush()
|
||||||
|
obtained = all(elem.room_id.id == r_test.reservation_line_ids[0].room_id.id for elem in r_test.reservation_line_ids)
|
||||||
|
self.assertTrue(obtained, "The entire reservation should be allocated in the preferred room")
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation02(self):
|
||||||
|
"""
|
||||||
|
The reservation shouldn't be splitted
|
||||||
|
room_type_id with availability provided
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| Double 101 | test | test | test | | | |
|
||||||
|
| Double 102 | | | | | | |
|
||||||
|
| Double 103 | | | | | | |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
"""
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r_test.flush()
|
||||||
|
self.assertFalse(r_test.splitted, "The reservation shouldn't be splitted")
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation03(self):
|
||||||
|
"""
|
||||||
|
The reservation should be splitted in 2 rooms
|
||||||
|
(there is only one better option on day 02 and a draw the next day.
|
||||||
|
The night before should be prioritized)
|
||||||
|
+------------+------+------+------+------+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+------+----+----+
|
||||||
|
| Double 101 | test | r3 | | | | |
|
||||||
|
| Double 102 | r1 | test | test | test | | |
|
||||||
|
| Double 103 | r2 | r4 | | | | |
|
||||||
|
+------------+------+------+------+------+----+----+
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r1 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r1.reservation_line_ids[0].room_id = self.room2.id
|
||||||
|
r1.flush()
|
||||||
|
|
||||||
|
r2 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r2.reservation_line_ids[0].room_id = self.room3.id
|
||||||
|
r2.flush()
|
||||||
|
|
||||||
|
r3 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r3.reservation_line_ids[0].room_id = self.room1.id
|
||||||
|
r3.flush()
|
||||||
|
|
||||||
|
r4 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r4.reservation_line_ids[0].room_id = self.room3.id
|
||||||
|
r4.flush()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=4),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r_test.flush()
|
||||||
|
changes = 0
|
||||||
|
last_room = None
|
||||||
|
|
||||||
|
for line in r_test.reservation_line_ids:
|
||||||
|
if last_room != line.room_id.id:
|
||||||
|
last_room = line.room_id.id
|
||||||
|
changes +=1
|
||||||
|
|
||||||
|
self.assertEqual(2, changes, "The reservation shouldn't have more than 2 changes")
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation04(self):
|
||||||
|
"""
|
||||||
|
The reservation should be splitted in 3 rooms
|
||||||
|
(there are 2 best options on day 03 and room of last night is not available)
|
||||||
|
+------------+------+------+------+------+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+------+----+----+
|
||||||
|
| Double 101 | test | r3 | test | test | | |
|
||||||
|
| Double 102 | r1 | test | r5 | | | |
|
||||||
|
| Double 103 | r2 | r4 | | | | |
|
||||||
|
+------------+------+------+------+------+----+----+
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r1 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r1.reservation_line_ids[0].room_id = self.room2.id
|
||||||
|
r1.flush()
|
||||||
|
|
||||||
|
r2 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r2.reservation_line_ids[0].room_id = self.room3.id
|
||||||
|
r2.flush()
|
||||||
|
|
||||||
|
r3 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r3.reservation_line_ids[0].room_id = self.room1.id
|
||||||
|
r3.flush()
|
||||||
|
|
||||||
|
r4 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r4.reservation_line_ids[0].room_id = self.room3.id
|
||||||
|
r4.flush()
|
||||||
|
|
||||||
|
r5 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r5.reservation_line_ids[0].room_id = self.room2.id
|
||||||
|
r5.flush()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=4),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r_test.flush()
|
||||||
|
|
||||||
|
changes = 0
|
||||||
|
last_room = None
|
||||||
|
for line in r_test.reservation_line_ids:
|
||||||
|
if line.room_id != last_room:
|
||||||
|
last_room = line.room_id
|
||||||
|
changes += 1
|
||||||
|
|
||||||
|
self.assertEqual(3, changes, "The reservation shouldn't be splitted in more than 3 roomss")
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation05(self):
|
||||||
|
"""
|
||||||
|
The preferred room_id is not available
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| Double 101 |r1/tst| | | | | |
|
||||||
|
| Double 102 | | | | | | |
|
||||||
|
| Double 103 | | | | | | |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r1 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r1.reservation_line_ids[0].room_id = self.room1
|
||||||
|
r1.flush()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"preferred_room_id": self.room1.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
r_test.flush()
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation06(self):
|
||||||
|
"""
|
||||||
|
There's no availability in the preferred_room_id provided
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| Double 101 | r1 |r1/tst| tst | | | |
|
||||||
|
| Double 102 | | | | | | |
|
||||||
|
| Double 103 | | | | | | |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r1 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r1.reservation_line_ids[0].room_id = self.room1
|
||||||
|
r1.reservation_line_ids[1].room_id = self.room1
|
||||||
|
r1.flush()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||||
|
"adults": 2,
|
||||||
|
"preferred_room_id": self.room1.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
r_test.flush()
|
||||||
|
|
||||||
|
@freeze_time("1980-11-01")
|
||||||
|
def test_split_reservation07(self):
|
||||||
|
"""
|
||||||
|
There's no availability
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| room/date | 01 | 02 | 03 | 04 | 05 | 06 |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
| Double 101 | r1 | r1 | r1 | | | |
|
||||||
|
| Double 102 | r2 | r2 | r2 | | | |
|
||||||
|
| Double 103 | r3 | r3 | r3 | | | |
|
||||||
|
+------------+------+------+------+----+----+----+
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.create_common_scenario()
|
||||||
|
|
||||||
|
r1 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r1.reservation_line_ids[0].room_id = self.room1
|
||||||
|
r1.reservation_line_ids[1].room_id = self.room1
|
||||||
|
r1.reservation_line_ids[2].room_id = self.room1
|
||||||
|
r1.flush()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r2 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r2.reservation_line_ids[0].room_id = self.room2
|
||||||
|
r2.reservation_line_ids[1].room_id = self.room2
|
||||||
|
r2.reservation_line_ids[2].room_id = self.room2
|
||||||
|
r2.flush()
|
||||||
|
|
||||||
|
r3 = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
r3.reservation_line_ids[0].room_id = self.room3
|
||||||
|
r3.reservation_line_ids[1].room_id = self.room3
|
||||||
|
r3.reservation_line_ids[2].room_id = self.room3
|
||||||
|
r3.flush()
|
||||||
|
|
||||||
|
r_test = self.env["pms.reservation"].create(
|
||||||
|
{
|
||||||
|
"pms_property_id": self.property.id,
|
||||||
|
"checkin": datetime.datetime.now(),
|
||||||
|
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
|
||||||
|
"adults": 2,
|
||||||
|
"room_type_id": self.room_type_double.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
r_test.flush()
|
||||||
|
|
||||||
|
|
||||||
def test_manage_children_raise(self):
|
def test_manage_children_raise(self):
|
||||||
|
|
||||||
|
|||||||
@@ -66,14 +66,13 @@
|
|||||||
style="margin-bottom:0px;"
|
style="margin-bottom:0px;"
|
||||||
attrs="{'invisible': [('splitted','=',False)]}"
|
attrs="{'invisible': [('splitted','=',False)]}"
|
||||||
>
|
>
|
||||||
This reservation is part of splitted reservation!, you can check it
|
This reservation is part of splitted reservation, you can try to unify the reservation here
|
||||||
in the
|
|
||||||
<bold>
|
<bold>
|
||||||
<button
|
<button
|
||||||
class="alert-link"
|
class="alert-link"
|
||||||
type="object"
|
type="object"
|
||||||
name="open_folio"
|
name="open_reservation_wizard"
|
||||||
string="Folio Form"
|
string="Unify the reservation"
|
||||||
/>
|
/>
|
||||||
</bold>
|
</bold>
|
||||||
</div>
|
</div>
|
||||||
@@ -161,14 +160,16 @@
|
|||||||
</span>
|
</span>
|
||||||
<h1>
|
<h1>
|
||||||
<field
|
<field
|
||||||
name="room_id"
|
name="preferred_room_id"
|
||||||
select="1"
|
select="1"
|
||||||
nolabel="1"
|
nolabel="1"
|
||||||
options="{'no_create': True,'no_open': True}"
|
options="{'no_create': True,'no_open': True}"
|
||||||
placeholder="Room"
|
placeholder="Room"
|
||||||
style="margin-right: 30px;"
|
style="margin-right: 30px;"
|
||||||
required='1'
|
attrs="{'invisible': [('splitted','=',True)]}"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<field
|
<field
|
||||||
name="partner_id"
|
name="partner_id"
|
||||||
default_focus="1"
|
default_focus="1"
|
||||||
@@ -548,10 +549,11 @@
|
|||||||
>
|
>
|
||||||
<field name="partner_id" avatar_field="image_128" />
|
<field name="partner_id" avatar_field="image_128" />
|
||||||
<field name="room_type_id" />
|
<field name="room_type_id" />
|
||||||
<field name="room_id" />
|
<field name="rooms" />
|
||||||
</calendar>
|
</calendar>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Form view Checkin Partners from reservation -->
|
<!-- Form view Checkin Partners from reservation -->
|
||||||
<record model="ir.ui.view" id="pms_reservation_checkin_view_form">
|
<record model="ir.ui.view" id="pms_reservation_checkin_view_form">
|
||||||
<field name="name">pms.reservation.checkin.form</field>
|
<field name="name">pms.reservation.checkin.form</field>
|
||||||
@@ -600,7 +602,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<h2>
|
<h2>
|
||||||
<field
|
<field
|
||||||
name="room_id"
|
name="preferred_room_id"
|
||||||
readonly="1"
|
readonly="1"
|
||||||
nolabel="1"
|
nolabel="1"
|
||||||
options="{'no_create': True,'no_open': True}"
|
options="{'no_create': True,'no_open': True}"
|
||||||
@@ -658,10 +660,12 @@
|
|||||||
<field name="name">pms.reservation.tree</field>
|
<field name="name">pms.reservation.tree</field>
|
||||||
<field name="model">pms.reservation</field>
|
<field name="model">pms.reservation</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Reservation" multi_edit="1" sample="1" class="o_sale_order">
|
<tree string="Reservation" multi_edit="1" sample="1" class="o_sale_order"
|
||||||
|
decoration-warning="splitted"
|
||||||
|
decoration-bf="splitted">
|
||||||
<field name="splitted" invisible="1" />
|
<field name="splitted" invisible="1" />
|
||||||
<field name="pricelist_id" invisible="1" />
|
<field name="pricelist_id" invisible="1" />
|
||||||
<field name="room_id" options="{'no_create': True,'no_open': True}" />
|
<field name="rooms" />
|
||||||
<field
|
<field
|
||||||
name="checkin"
|
name="checkin"
|
||||||
widget="daterange"
|
widget="daterange"
|
||||||
|
|||||||
1
pms/wizards/__init__.py
Normal file
1
pms/wizards/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import wizard_reservation
|
||||||
18
pms/wizards/wizard_reservation.py
Normal file
18
pms/wizards/wizard_reservation.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
from odoo import models, fields
|
||||||
|
|
||||||
|
class ReservationWizard(models.TransientModel):
|
||||||
|
_name = 'pms.reservation.wizard'
|
||||||
|
allowed_rooms = fields.One2many('pms.room', compute="_compute_allowed_rooms")
|
||||||
|
options = fields.Many2one('pms.room', string='Room')
|
||||||
|
|
||||||
|
def _compute_allowed_rooms(self):
|
||||||
|
for record in self:
|
||||||
|
record.allowed_rooms = self._context.get('rooms_available')
|
||||||
|
|
||||||
|
def unify(self):
|
||||||
|
if self.options:
|
||||||
|
for record in self:
|
||||||
|
for line in self.env['pms.reservation'].search([('id', '=', self._context.get('active_id'))]).reservation_line_ids:
|
||||||
|
line.room_id = self.options
|
||||||
|
|
||||||
24
pms/wizards/wizard_reservation.xml
Normal file
24
pms/wizards/wizard_reservation.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="reservation_wizard" model="ir.ui.view">
|
||||||
|
<field name="name">Reservation Wizard</field>
|
||||||
|
<field name="model">pms.reservation.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Choose The Details">
|
||||||
|
<group>
|
||||||
|
<field name="options"
|
||||||
|
string="Suggested rooms to unify the reservation:"
|
||||||
|
options="{'no_create': True,'no_open': True}"
|
||||||
|
required="1"
|
||||||
|
domain="[('id', 'in', allowed_rooms)]"/>
|
||||||
|
<field name="allowed_rooms" invisible="1"/>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button name="unify" string="Unify" type="object" class="oe_highlight" />
|
||||||
|
or
|
||||||
|
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user