mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[ADD] Test basic case
This commit is contained in:
@@ -72,6 +72,6 @@
|
|||||||
"views/webclient_templates.xml",
|
"views/webclient_templates.xml",
|
||||||
"wizard/folio_make_invoice_advance_views.xml",
|
"wizard/folio_make_invoice_advance_views.xml",
|
||||||
],
|
],
|
||||||
"demo": ["demo/pms_demo.xml"],
|
"demo": ["demo/pms_master_data.xml", "demo/pms_reservation.xml"],
|
||||||
"qweb": ["static/src/xml/pms_base_templates.xml",],
|
"qweb": ["static/src/xml/pms_base_templates.xml",],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -529,7 +529,7 @@
|
|||||||
<div class="h2" style="font-family: sans-serif; font-size: 18px; font-weight: bold; color: #45C2B1; padding: 0 0 0 0; text-transform: uppercase; letter-spacing: 0.5px;">Información de la
|
<div class="h2" style="font-family: sans-serif; font-size: 18px; font-weight: bold; color: #45C2B1; padding: 0 0 0 0; text-transform: uppercase; letter-spacing: 0.5px;">Información de la
|
||||||
habitación</div>
|
habitación</div>
|
||||||
% set room_type_ids = object.reservation_ids.filtered('to_send').mapped('room_type_id.id')
|
% set room_type_ids = object.reservation_ids.filtered('to_send').mapped('room_type_id.id')
|
||||||
% set room_types = user.env['hotel.room.type'].browse(room_type_ids)
|
% set room_types = user.env['pms.room.type'].browse(room_type_ids)
|
||||||
% for room_type in room_types:
|
% for room_type in room_types:
|
||||||
|
|
||||||
% if room_type.product_id.name:
|
% if room_type.product_id.name:
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<!-- users -->
|
<!-- users -->
|
||||||
<record id="base.user_demo" model="res.users">
|
<record id="base.user_demo" model="res.users">
|
||||||
<field name="groups_id" eval="[(4,ref('pms.group_pms_user'))]" />
|
<field name="groups_id" eval="[(4,ref('pms.group_pms_user'))]" />
|
||||||
|
<field name="company_id" ref="base.main_company" />
|
||||||
|
<field name="company_ids" eval="[(4, ref('base.main_company'))]" />
|
||||||
|
<field name="pms_property_id" ref="main_pms_property" />
|
||||||
|
<field name="pms_property_ids" eval="[(4, ref('main_pms_property'))]" />
|
||||||
</record>
|
</record>
|
||||||
<!-- pms.floor -->
|
<!-- pms.floor -->
|
||||||
<record id="pms_floor_0" model="pms.floor">
|
<record id="pms_floor_0" model="pms.floor">
|
||||||
@@ -292,105 +296,6 @@
|
|||||||
name="description"
|
name="description"
|
||||||
>Used for closing of rooms for extra privacy.</field>
|
>Used for closing of rooms for extra privacy.</field>
|
||||||
</record>
|
</record>
|
||||||
<!-- pms.folio -->
|
|
||||||
<!-- reservation of 1 economic room for 1 person -->
|
|
||||||
<record id="pms_folio_0" model="pms.folio">
|
|
||||||
<field name="partner_id" ref="base.res_partner_address_27" />
|
|
||||||
<field
|
|
||||||
name="reservation_ids"
|
|
||||||
eval="[(5, 0), (0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_0'),
|
|
||||||
'checkin': DateTime.today().strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 2,
|
|
||||||
'state': 'confirm',
|
|
||||||
'board_service_room_id': ref('pms_board_service_room_1'),
|
|
||||||
})]"
|
|
||||||
/>
|
|
||||||
</record>
|
|
||||||
<!-- reservation of 1 triple room for 3 people on behalf on the company -->
|
|
||||||
<record id="pms_folio_1" model="pms.folio">
|
|
||||||
<field name="partner_id" ref="base.res_partner_12" />
|
|
||||||
<field
|
|
||||||
name="reservation_ids"
|
|
||||||
eval="[(5, 0), (0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_3'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 3,
|
|
||||||
'board_service_room_id': ref('pms_board_service_room_3'),
|
|
||||||
})]"
|
|
||||||
/>
|
|
||||||
</record>
|
|
||||||
<!-- reservation of 3 single rooms for 3 people with 1 cancelled -->
|
|
||||||
<!-- TODO: The third reservation is marked from State: Cancelled to Pending Entry at Folio creation -->
|
|
||||||
<record id="pms_folio_2" model="pms.folio">
|
|
||||||
<field name="partner_id" ref="base.res_partner_address_10" />
|
|
||||||
<field
|
|
||||||
name="reservation_ids"
|
|
||||||
eval="[(5, 0),
|
|
||||||
(0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_1'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 1,
|
|
||||||
'state': 'confirm',
|
|
||||||
}),
|
|
||||||
(0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_1'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 1,
|
|
||||||
'state': 'confirm',
|
|
||||||
}),
|
|
||||||
(0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_1'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 1,
|
|
||||||
'state': 'cancelled',
|
|
||||||
})]"
|
|
||||||
/>
|
|
||||||
</record>
|
|
||||||
<!-- reservation of the conference room for 1 day on behalf of a company -->
|
|
||||||
<record id="pms_folio_3" model="pms.folio">
|
|
||||||
<field name="partner_id" ref="base.res_partner_12" />
|
|
||||||
<field
|
|
||||||
name="reservation_ids"
|
|
||||||
eval="[(5, 0), (0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_4'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=3)).strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 1,
|
|
||||||
'state': 'confirm',
|
|
||||||
})]"
|
|
||||||
/>
|
|
||||||
</record>
|
|
||||||
<!-- out of service room -->
|
|
||||||
<record id="pms_folio_4" model="pms.folio">
|
|
||||||
<field name="partner_id" ref="main_pms_property" />
|
|
||||||
<field name="reservation_type">out</field>
|
|
||||||
<field
|
|
||||||
name="reservation_ids"
|
|
||||||
eval="[(5, 0), (0, 0, {
|
|
||||||
'pricelist_id': 1,
|
|
||||||
'room_type_id': ref('pms_room_type_1'),
|
|
||||||
'checkin': (DateTime.today() + timedelta(days=5)).strftime('%Y-%m-%d'),
|
|
||||||
'checkout': (DateTime.today() + timedelta(days=7)).strftime('%Y-%m-%d'),
|
|
||||||
'adults': 1,
|
|
||||||
'state': 'confirm',
|
|
||||||
'reservation_type': 'out',
|
|
||||||
'closure_reason_id': ref('pms_room_closure_reason_0'),
|
|
||||||
'out_service_description': 'Change of lighting',
|
|
||||||
})]"
|
|
||||||
/>
|
|
||||||
</record>
|
|
||||||
<!-- Multi pms Demo -->
|
<!-- Multi pms Demo -->
|
||||||
<record id="demo_pms_room_type_restriction" model="pms.room.type.restriction">
|
<record id="demo_pms_room_type_restriction" model="pms.room.type.restriction">
|
||||||
<field name="name">Restriction Plan Demo</field>
|
<field name="name">Restriction Plan Demo</field>
|
||||||
104
pms/demo/pms_reservation.xml
Normal file
104
pms/demo/pms_reservation.xml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
<!-- pms.folio -->
|
||||||
|
<!-- reservation of 1 economic room for 1 person -->
|
||||||
|
<record id="pms_folio_0" model="pms.folio">
|
||||||
|
<field name="partner_id" ref="base.res_partner_address_27" />
|
||||||
|
<field
|
||||||
|
name="reservation_ids"
|
||||||
|
eval="[(5, 0), (0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_0'),
|
||||||
|
'checkin': DateTime.today(),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=2)),
|
||||||
|
'adults': 2,
|
||||||
|
'state': 'confirm',
|
||||||
|
'board_service_room_id': ref('pms_board_service_room_1'),
|
||||||
|
})]"
|
||||||
|
/>
|
||||||
|
</record>
|
||||||
|
<!-- reservation of 1 triple room for 3 people on behalf on the company -->
|
||||||
|
<record id="pms_folio_1" model="pms.folio">
|
||||||
|
<field name="partner_id" ref="base.res_partner_12" />
|
||||||
|
<field
|
||||||
|
name="reservation_ids"
|
||||||
|
eval="[(5, 0), (0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_3'),
|
||||||
|
'checkin': (DateTime.today() + timedelta(days=2)),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=4)),
|
||||||
|
'adults': 3,
|
||||||
|
'board_service_room_id': ref('pms_board_service_room_3'),
|
||||||
|
})]"
|
||||||
|
/>
|
||||||
|
</record>
|
||||||
|
<!-- reservation of 3 single rooms for 3 people with 1 cancelled -->
|
||||||
|
<!-- TODO: The third reservation is marked from State: Cancelled to Pending Entry at Folio creation -->
|
||||||
|
<record id="pms_folio_2" model="pms.folio">
|
||||||
|
<field name="partner_id" ref="base.res_partner_address_10" />
|
||||||
|
<field
|
||||||
|
name="reservation_ids"
|
||||||
|
eval="[(5, 0),
|
||||||
|
(0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_1'),
|
||||||
|
'checkin': (DateTime.today() + timedelta(days=2)),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=4)),
|
||||||
|
'adults': 1,
|
||||||
|
'state': 'confirm',
|
||||||
|
}),
|
||||||
|
(0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_1'),
|
||||||
|
'checkin': (DateTime.today() + timedelta(days=2)),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=4)),
|
||||||
|
'adults': 1,
|
||||||
|
'state': 'confirm',
|
||||||
|
}),
|
||||||
|
(0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_1'),
|
||||||
|
'checkin': (DateTime.today() + timedelta(days=2)),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=4)),
|
||||||
|
'adults': 1,
|
||||||
|
'state': 'cancelled',
|
||||||
|
})]"
|
||||||
|
/>
|
||||||
|
</record>
|
||||||
|
<!-- reservation of the conference room for 1 day on behalf of a company -->
|
||||||
|
<record id="pms_folio_3" model="pms.folio">
|
||||||
|
<field name="partner_id" ref="base.res_partner_12" />
|
||||||
|
<field
|
||||||
|
name="reservation_ids"
|
||||||
|
eval="[(5, 0), (0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_4'),
|
||||||
|
'checkin': (DateTime.today() + timedelta(days=3)),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=4)),
|
||||||
|
'adults': 1,
|
||||||
|
'state': 'confirm',
|
||||||
|
})]"
|
||||||
|
/>
|
||||||
|
</record>
|
||||||
|
<!-- out of service room -->
|
||||||
|
<record id="pms_folio_4" model="pms.folio">
|
||||||
|
<field name="partner_id" ref="main_pms_property" />
|
||||||
|
<field name="reservation_type">out</field>
|
||||||
|
<field
|
||||||
|
name="reservation_ids"
|
||||||
|
eval="[(5, 0), (0, 0, {
|
||||||
|
'pricelist_id': 1,
|
||||||
|
'room_type_id': ref('pms_room_type_1'),
|
||||||
|
'checkin': (DateTime.today() + timedelta(days=5)),
|
||||||
|
'checkout': (DateTime.today() + timedelta(days=7)),
|
||||||
|
'adults': 1,
|
||||||
|
'state': 'confirm',
|
||||||
|
'reservation_type': 'out',
|
||||||
|
'closure_reason_id': ref('pms_room_closure_reason_0'),
|
||||||
|
'out_service_description': 'Change of lighting',
|
||||||
|
})]"
|
||||||
|
/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
@@ -2,10 +2,13 @@
|
|||||||
# 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).
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from odoo import _, api, fields, models
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PmsFolio(models.Model):
|
class PmsFolio(models.Model):
|
||||||
_name = "pms.folio"
|
_name = "pms.folio"
|
||||||
_description = "PMS Folio"
|
_description = "PMS Folio"
|
||||||
@@ -47,9 +50,7 @@ class PmsFolio(models.Model):
|
|||||||
help="Room reservation detail.",
|
help="Room reservation detail.",
|
||||||
)
|
)
|
||||||
number_of_rooms = fields.Integer(
|
number_of_rooms = fields.Integer(
|
||||||
"Number of Rooms",
|
"Number of Rooms", compute="_compute_number_of_rooms", store="True",
|
||||||
compute="_compute_number_of_rooms",
|
|
||||||
store="True",
|
|
||||||
)
|
)
|
||||||
service_ids = fields.One2many(
|
service_ids = fields.One2many(
|
||||||
"pms.service",
|
"pms.service",
|
||||||
@@ -60,10 +61,7 @@ class PmsFolio(models.Model):
|
|||||||
"include in main Invoice.",
|
"include in main Invoice.",
|
||||||
)
|
)
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
"res.company",
|
"res.company", "Company", required=True, default=lambda self: self.env.company,
|
||||||
"Company",
|
|
||||||
required=True,
|
|
||||||
default=lambda self: self.env.company,
|
|
||||||
)
|
)
|
||||||
analytic_account_id = fields.Many2one(
|
analytic_account_id = fields.Many2one(
|
||||||
"account.analytic.account",
|
"account.analytic.account",
|
||||||
@@ -101,10 +99,7 @@ class PmsFolio(models.Model):
|
|||||||
readonly=False,
|
readonly=False,
|
||||||
)
|
)
|
||||||
agency_id = fields.Many2one(
|
agency_id = fields.Many2one(
|
||||||
"res.partner",
|
"res.partner", "Agency", ondelete="restrict", domain=[("is_agency", "=", True)],
|
||||||
"Agency",
|
|
||||||
ondelete="restrict",
|
|
||||||
domain=[("is_agency", "=", True)],
|
|
||||||
)
|
)
|
||||||
payment_ids = fields.One2many("account.payment", "folio_id", readonly=True)
|
payment_ids = fields.One2many("account.payment", "folio_id", readonly=True)
|
||||||
return_ids = fields.One2many("payment.return", "folio_id", readonly=True)
|
return_ids = fields.One2many("payment.return", "folio_id", readonly=True)
|
||||||
@@ -115,7 +110,8 @@ class PmsFolio(models.Model):
|
|||||||
compute="_compute_payment_term_id",
|
compute="_compute_payment_term_id",
|
||||||
store=True,
|
store=True,
|
||||||
readonly=False,
|
readonly=False,
|
||||||
help="Pricelist for current folio.",)
|
help="Pricelist for current folio.",
|
||||||
|
)
|
||||||
checkin_partner_ids = fields.One2many("pms.checkin.partner", "folio_id")
|
checkin_partner_ids = fields.One2many("pms.checkin.partner", "folio_id")
|
||||||
move_ids = fields.Many2many(
|
move_ids = fields.Many2many(
|
||||||
"account.move",
|
"account.move",
|
||||||
@@ -159,10 +155,7 @@ class PmsFolio(models.Model):
|
|||||||
default=lambda *a: "normal",
|
default=lambda *a: "normal",
|
||||||
)
|
)
|
||||||
channel_type = fields.Selection(
|
channel_type = fields.Selection(
|
||||||
[
|
[("direct", "Direct"), ("agency", "Agency"),],
|
||||||
("direct", "Direct"),
|
|
||||||
("agency", "Agency"),
|
|
||||||
],
|
|
||||||
"Sales Channel",
|
"Sales Channel",
|
||||||
default="direct",
|
default="direct",
|
||||||
)
|
)
|
||||||
@@ -297,9 +290,9 @@ class PmsFolio(models.Model):
|
|||||||
@api.depends("reservation_ids", "reservation_ids.state")
|
@api.depends("reservation_ids", "reservation_ids.state")
|
||||||
def _compute_number_of_rooms(self):
|
def _compute_number_of_rooms(self):
|
||||||
for folio in self:
|
for folio in self:
|
||||||
folio.number_of_rooms = len(folio.reservation_ids.filtered(
|
folio.number_of_rooms = len(
|
||||||
lambda a: a.state != "cancelled"
|
folio.reservation_ids.filtered(lambda a: a.state != "cancelled")
|
||||||
))
|
)
|
||||||
|
|
||||||
@api.depends("partner_id")
|
@api.depends("partner_id")
|
||||||
def _compute_pricelist_id(self):
|
def _compute_pricelist_id(self):
|
||||||
@@ -316,7 +309,7 @@ class PmsFolio(models.Model):
|
|||||||
@api.depends("partner_id")
|
@api.depends("partner_id")
|
||||||
def _compute_user_id(self):
|
def _compute_user_id(self):
|
||||||
for folio in self:
|
for folio in self:
|
||||||
folio.user_id = folio.partner_id.user_id.id or self.env.uid,
|
folio.user_id = (folio.partner_id.user_id.id or self.env.uid,)
|
||||||
|
|
||||||
@api.depends("partner_id")
|
@api.depends("partner_id")
|
||||||
def _compute_partner_invoice_id(self):
|
def _compute_partner_invoice_id(self):
|
||||||
@@ -329,14 +322,19 @@ class PmsFolio(models.Model):
|
|||||||
def _compute_payment_term_id(self):
|
def _compute_payment_term_id(self):
|
||||||
self.payment_term_id = False
|
self.payment_term_id = False
|
||||||
for folio in self:
|
for folio in self:
|
||||||
folio.payment_term_id = self.partner_id.property_payment_term_id \
|
folio.payment_term_id = (
|
||||||
and self.partner_id.property_payment_term_id.id or False
|
self.partner_id.property_payment_term_id
|
||||||
|
and self.partner_id.property_payment_term_id.id
|
||||||
|
or False
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends("partner_id")
|
@api.depends("partner_id")
|
||||||
def _compute_team_id(self):
|
def _compute_team_id(self):
|
||||||
for folio in self:
|
for folio in self:
|
||||||
folio.team_id = self.partner_id.team_id.id or \
|
folio.team_id = (
|
||||||
self.env["crm.team"]._get_default_team_id()
|
self.partner_id.team_id.id
|
||||||
|
or self.env["crm.team"]._get_default_team_id()
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
"state", "reservation_ids.invoice_status", "service_ids.invoice_status"
|
"state", "reservation_ids.invoice_status", "service_ids.invoice_status"
|
||||||
|
|||||||
@@ -5,13 +5,8 @@ import logging
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.tools import (
|
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, float_compare, float_is_zero
|
||||||
DEFAULT_SERVER_DATE_FORMAT,
|
|
||||||
DEFAULT_SERVER_DATETIME_FORMAT,
|
|
||||||
float_compare,
|
|
||||||
float_is_zero,
|
|
||||||
)
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -290,19 +285,18 @@ class PmsReservation(models.Model):
|
|||||||
reselling = fields.Boolean("Is Reselling", default=False)
|
reselling = fields.Boolean("Is Reselling", default=False)
|
||||||
nights = fields.Integer("Nights", compute="_computed_nights", store=True)
|
nights = fields.Integer("Nights", compute="_computed_nights", store=True)
|
||||||
channel_type = fields.Selection(
|
channel_type = fields.Selection(
|
||||||
[("direct", "Direct"), ("agency", "Agency"),],
|
selection=[("direct", "Direct"), ("agency", "Agency"),],
|
||||||
string="Sales Channel",
|
string="Sales Channel",
|
||||||
default="direct",
|
default="direct",
|
||||||
)
|
)
|
||||||
subchannel_direct = fields.Selection([
|
subchannel_direct = fields.Selection(
|
||||||
("door", "Door"),
|
selection=[("door", "Door"), ("mail", "Mail"), ("phone", "Phone"),],
|
||||||
("mail", "Mail"),
|
|
||||||
("phone", "Phone"),
|
|
||||||
],
|
|
||||||
string="Direct Channel",
|
string="Direct Channel",
|
||||||
)
|
)
|
||||||
origin = fields.Char("Origin", compute="_compute_origin", store=True)
|
origin = fields.Char("Origin", compute="_compute_origin", store=True)
|
||||||
detail_origin = fields.Char("Detail Origin", compute="_compute_detail_origin", store=True)
|
detail_origin = fields.Char(
|
||||||
|
"Detail Origin", compute="_compute_detail_origin", store=True
|
||||||
|
)
|
||||||
# TODO: Review functionality of last_update_res
|
# TODO: Review functionality of last_update_res
|
||||||
last_updated_res = fields.Datetime(
|
last_updated_res = fields.Datetime(
|
||||||
"Last Updated", compute="_compute_last_updated_res", store=True, readonly=False,
|
"Last Updated", compute="_compute_last_updated_res", store=True, readonly=False,
|
||||||
@@ -424,7 +418,7 @@ class PmsReservation(models.Model):
|
|||||||
|
|
||||||
@api.depends("checkin")
|
@api.depends("checkin")
|
||||||
def _compute_priority(self):
|
def _compute_priority(self):
|
||||||
#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("reservation_line_ids", "reservation_line_ids.room_id")
|
||||||
@@ -1079,7 +1073,7 @@ class PmsReservation(models.Model):
|
|||||||
@api.depends("origin")
|
@api.depends("origin")
|
||||||
def _compute_detail_origin(self):
|
def _compute_detail_origin(self):
|
||||||
for reservation in self:
|
for reservation in self:
|
||||||
if reservation.channel_type in ["direct","agency"]:
|
if reservation.channel_type in ["direct", "agency"]:
|
||||||
reservation.detail_origin = reservation.sudo().create_uid.name
|
reservation.detail_origin = reservation.sudo().create_uid.name
|
||||||
|
|
||||||
# https://www.odoo.com/es_ES/forum/ayuda-1/question/calculated-fields-in-search-filter-possible-118501
|
# https://www.odoo.com/es_ES/forum/ayuda-1/question/calculated-fields-in-search-filter-possible-118501
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
# Copyright 2017-2018 Alexandre Díaz
|
# Copyright 2017-2018 Alexandre Díaz
|
||||||
# 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).
|
||||||
from odoo import _, api, fields, models
|
import logging
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import logging
|
from odoo import _, api, fields, models
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -74,28 +75,31 @@ class PmsReservationLine(models.Model):
|
|||||||
)
|
)
|
||||||
discount = fields.Float(string="Discount (%)", digits=("Discount"), default=0.0)
|
discount = fields.Float(string="Discount (%)", digits=("Discount"), default=0.0)
|
||||||
occupies_availability = fields.Boolean(
|
occupies_availability = fields.Boolean(
|
||||||
string = "Occupies",
|
string="Occupies",
|
||||||
compute="_compute_occupies_availability",
|
compute="_compute_occupies_availability",
|
||||||
store=True,
|
store=True,
|
||||||
help="This record is taken into account to calculate availability")
|
help="This record is taken into account to calculate availability",
|
||||||
|
)
|
||||||
|
|
||||||
_sql_constraints = [
|
_sql_constraints = [
|
||||||
(
|
(
|
||||||
"rule_availability",
|
"rule_availability",
|
||||||
"EXCLUDE (room_id WITH =, date WITH =) WHERE (occupies_availability = True)",
|
"EXCLUDE (room_id WITH =, date WITH =) WHERE (occupies_availability = True)",
|
||||||
"Room Occupied"
|
"Room Occupied",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Compute and Search methods
|
# Compute and Search methods
|
||||||
@api.depends(
|
@api.depends(
|
||||||
"reservation_id.adults",
|
"reservation_id.adults", "reservation_id.room_type_id",
|
||||||
"reservation_id.room_type_id",)
|
)
|
||||||
def _compute_room_id(self):
|
def _compute_room_id(self):
|
||||||
for line in self:
|
for line in self:
|
||||||
if line.reservation_id.room_type_id:
|
if line.reservation_id.room_type_id:
|
||||||
preferred_room = line.reservation_id.room_id
|
preferred_room = line.reservation_id.room_id
|
||||||
rooms_available = self.env["pms.room.type.availability"].rooms_available(
|
rooms_available = self.env[
|
||||||
|
"pms.room.type.availability"
|
||||||
|
].rooms_available(
|
||||||
checkin=line.date,
|
checkin=line.date,
|
||||||
checkout=line.date + timedelta(1),
|
checkout=line.date + timedelta(1),
|
||||||
room_type_id=self.reservation_id.room_type_id.id or False,
|
room_type_id=self.reservation_id.room_type_id.id or False,
|
||||||
@@ -110,8 +114,9 @@ class PmsReservationLine(models.Model):
|
|||||||
else:
|
else:
|
||||||
line.room_id = False
|
line.room_id = False
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_("%s: No rooms available") % (self.reservation_id.room_type_id.name)
|
_("%s: No rooms available")
|
||||||
)
|
% (self.reservation_id.room_type_id.name)
|
||||||
|
)
|
||||||
line._check_adults()
|
line._check_adults()
|
||||||
else:
|
else:
|
||||||
line.room_id = False
|
line.room_id = False
|
||||||
@@ -153,25 +158,28 @@ class PmsReservationLine(models.Model):
|
|||||||
@api.depends("reservation_id.state", "reservation_id.overbooking")
|
@api.depends("reservation_id.state", "reservation_id.overbooking")
|
||||||
def _compute_occupies_availability(self):
|
def _compute_occupies_availability(self):
|
||||||
for line in self:
|
for line in self:
|
||||||
if line.reservation_id.state == "cancelled" or \
|
if (
|
||||||
line.reservation_id.overbooking == True:
|
line.reservation_id.state == "cancelled"
|
||||||
|
or line.reservation_id.overbooking == True
|
||||||
|
):
|
||||||
line.occupies_availability = False
|
line.occupies_availability = False
|
||||||
else:
|
else:
|
||||||
line.occupies_availability = True
|
line.occupies_availability = True
|
||||||
|
|
||||||
def _recompute_price(self):
|
def _recompute_price(self):
|
||||||
#REVIEW: Conditional to avoid overriding already calculated prices,
|
# REVIEW: Conditional to avoid overriding already calculated prices,
|
||||||
# I'm not sure it's the best way
|
# I'm not sure it's the best way
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
origin = self._origin.reservation_id
|
origin = self._origin.reservation_id
|
||||||
new = self.reservation_id
|
new = self.reservation_id
|
||||||
price_fields = ["pricelist_id", "room_type_id", "reservation_type"]
|
price_fields = ["pricelist_id", "room_type_id", "reservation_type"]
|
||||||
if any(origin[field] != new[field] for field in price_fields) or \
|
if (
|
||||||
self._origin.price == 0:
|
any(origin[field] != new[field] for field in price_fields)
|
||||||
|
or self._origin.price == 0
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# TODO: Refact method and allowed cancelled single days
|
# TODO: Refact method and allowed cancelled single days
|
||||||
@api.depends("reservation_id.cancelled_reason")
|
@api.depends("reservation_id.cancelled_reason")
|
||||||
def _compute_cancel_discount(self):
|
def _compute_cancel_discount(self):
|
||||||
@@ -289,7 +297,9 @@ class PmsReservationLine(models.Model):
|
|||||||
extra_bed = record.reservation_id.service_ids.filtered(
|
extra_bed = record.reservation_id.service_ids.filtered(
|
||||||
lambda r: r.product_id.is_extra_bed is True
|
lambda r: r.product_id.is_extra_bed is True
|
||||||
)
|
)
|
||||||
if record.reservation_id.adults > record.room_id.get_capacity(len(extra_bed)):
|
if record.reservation_id.adults > record.room_id.get_capacity(
|
||||||
|
len(extra_bed)
|
||||||
|
):
|
||||||
raise ValidationError(_("Persons can't be higher than room capacity"))
|
raise ValidationError(_("Persons can't be higher than room capacity"))
|
||||||
#if record.reservation_id.adults == 0:
|
# if record.reservation_id.adults == 0:
|
||||||
# raise ValidationError(_("Reservation has no adults"))
|
# raise ValidationError(_("Reservation has no adults"))
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
# Copyright 2017 Alexandre Díaz
|
# Copyright 2017 Alexandre Díaz
|
||||||
# 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).
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
|
|
||||||
class PmsRoomType(models.Model):
|
class PmsRoomType(models.Model):
|
||||||
@@ -57,14 +58,19 @@ class PmsRoomType(models.Model):
|
|||||||
total_rooms_count = fields.Integer(compute="_compute_total_rooms", store=True)
|
total_rooms_count = fields.Integer(compute="_compute_total_rooms", store=True)
|
||||||
active = fields.Boolean("Active", default=True)
|
active = fields.Boolean("Active", default=True)
|
||||||
sequence = fields.Integer("Sequence", default=0)
|
sequence = fields.Integer("Sequence", default=0)
|
||||||
default_max_avail = fields.Integer("Max. Availability", default=-1,
|
default_max_avail = fields.Integer(
|
||||||
help="Maximum simultaneous availability on own Booking Engine "
|
"Max. Availability",
|
||||||
"given no availability rules. "
|
default=-1,
|
||||||
"Use `-1` for using maximum simultaneous availability.")
|
help="Maximum simultaneous availability on own Booking Engine "
|
||||||
default_quota = fields.Integer("Default Quota", default=-1,
|
"given no availability rules. "
|
||||||
help="Quota assigned to the own Booking Engine given no availability rules. "
|
"Use `-1` for using maximum simultaneous availability.",
|
||||||
"Use `-1` for managing no quota.")
|
)
|
||||||
|
default_quota = fields.Integer(
|
||||||
|
"Default Quota",
|
||||||
|
default=-1,
|
||||||
|
help="Quota assigned to the own Booking Engine given no availability rules. "
|
||||||
|
"Use `-1` for managing no quota.",
|
||||||
|
)
|
||||||
|
|
||||||
_sql_constraints = [
|
_sql_constraints = [
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -91,10 +91,7 @@ class PmsService(models.Model):
|
|||||||
state = fields.Selection(related="folio_id.state")
|
state = fields.Selection(related="folio_id.state")
|
||||||
per_day = fields.Boolean(related="product_id.per_day", related_sudo=True)
|
per_day = fields.Boolean(related="product_id.per_day", related_sudo=True)
|
||||||
product_qty = fields.Integer(
|
product_qty = fields.Integer(
|
||||||
"Quantity",
|
"Quantity", compute="_compute_product_qty", store=True, readonly=False,
|
||||||
compute="_compute_product_qty",
|
|
||||||
store=True,
|
|
||||||
readonly=False,
|
|
||||||
)
|
)
|
||||||
is_board_service = fields.Boolean()
|
is_board_service = fields.Boolean()
|
||||||
to_print = fields.Boolean("Print", help="Print in Folio Report")
|
to_print = fields.Boolean("Print", help="Print in Folio Report")
|
||||||
@@ -204,15 +201,14 @@ class PmsService(models.Model):
|
|||||||
i += 1
|
i += 1
|
||||||
idate = reservation.checkin + timedelta(days=i)
|
idate = reservation.checkin + timedelta(days=i)
|
||||||
old_line = service._search_old_lines(idate)
|
old_line = service._search_old_lines(idate)
|
||||||
if idate in [line.date for line in service.service_line_ids]:
|
if idate in [
|
||||||
#REVIEW: If the date is already cached (otherwise double the date)
|
line.date for line in service.service_line_ids
|
||||||
|
]:
|
||||||
|
# REVIEW: If the date is already cached (otherwise double the date)
|
||||||
pass
|
pass
|
||||||
elif not old_line:
|
elif not old_line:
|
||||||
lines.append(
|
lines.append(
|
||||||
(0, False, {
|
(0, False, {"date": idate, "day_qty": day_qty,})
|
||||||
"date": idate,
|
|
||||||
"day_qty": day_qty,
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
lines.append((4, old_line.id))
|
lines.append((4, old_line.id))
|
||||||
@@ -222,8 +218,16 @@ class PmsService(models.Model):
|
|||||||
service.service_line_ids -= service.service_line_ids.filtered_domain(
|
service.service_line_ids -= service.service_line_ids.filtered_domain(
|
||||||
[
|
[
|
||||||
"|",
|
"|",
|
||||||
("date", "<", reservation.checkin + timedelta(move_day)),
|
(
|
||||||
("date", ">=", reservation.checkout + timedelta(move_day)),
|
"date",
|
||||||
|
"<",
|
||||||
|
reservation.checkin + timedelta(move_day),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"date",
|
||||||
|
">=",
|
||||||
|
reservation.checkout + timedelta(move_day),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
_logger.info(service)
|
_logger.info(service)
|
||||||
@@ -232,40 +236,35 @@ class PmsService(models.Model):
|
|||||||
else:
|
else:
|
||||||
# TODO: Review (business logic refact) no per_day logic service
|
# TODO: Review (business logic refact) no per_day logic service
|
||||||
if not service.service_line_ids:
|
if not service.service_line_ids:
|
||||||
service.service_line_ids = [(
|
service.service_line_ids = [
|
||||||
0,
|
(
|
||||||
False,
|
0,
|
||||||
{
|
False,
|
||||||
"date": fields.Date.today(),
|
{"date": fields.Date.today(), "day_qty": day_qty,},
|
||||||
"day_qty": day_qty,
|
)
|
||||||
},
|
]
|
||||||
)]
|
|
||||||
else:
|
else:
|
||||||
# TODO: Service without reservation(room) but with folio¿?
|
# TODO: Service without reservation(room) but with folio¿?
|
||||||
# example: tourist tour in group
|
# example: tourist tour in group
|
||||||
if not service.service_line_ids:
|
if not service.service_line_ids:
|
||||||
service.service_line_ids = [(
|
service.service_line_ids = [
|
||||||
|
(
|
||||||
0,
|
0,
|
||||||
False,
|
False,
|
||||||
{
|
{"date": fields.Date.today(), "day_qty": day_qty,},
|
||||||
"date": fields.Date.today(),
|
)
|
||||||
"day_qty": day_qty,
|
]
|
||||||
},
|
|
||||||
)]
|
|
||||||
else:
|
else:
|
||||||
service.service_line_ids = False
|
service.service_line_ids = False
|
||||||
|
|
||||||
def _search_old_lines(self, date):
|
def _search_old_lines(self, date):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
old_lines = self.env['pms.service.line']
|
old_lines = self.env["pms.service.line"]
|
||||||
if isinstance(self._origin.id, int):
|
if isinstance(self._origin.id, int):
|
||||||
old_line = self._origin.service_line_ids.filtered(
|
old_line = self._origin.service_line_ids.filtered(lambda r: r.date == date)
|
||||||
lambda r: r.date == date
|
|
||||||
)
|
|
||||||
return old_line
|
return old_line
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@api.depends("product_id")
|
@api.depends("product_id")
|
||||||
def _compute_tax_ids(self):
|
def _compute_tax_ids(self):
|
||||||
for service in self:
|
for service in self:
|
||||||
@@ -348,20 +347,22 @@ class PmsService(models.Model):
|
|||||||
service.price_unit = 0
|
service.price_unit = 0
|
||||||
|
|
||||||
def _recompute_price(self):
|
def _recompute_price(self):
|
||||||
#REVIEW: Conditional to avoid overriding already calculated prices,
|
# REVIEW: Conditional to avoid overriding already calculated prices,
|
||||||
# I'm not sure it's the best way
|
# I'm not sure it's the best way
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
#folio/reservation origin service
|
# folio/reservation origin service
|
||||||
folio_origin = self._origin.folio_id
|
folio_origin = self._origin.folio_id
|
||||||
reservation_origin = self._origin.reservation_id
|
reservation_origin = self._origin.reservation_id
|
||||||
origin = reservation_origin if reservation_origin else folio_origin
|
origin = reservation_origin if reservation_origin else folio_origin
|
||||||
#folio/reservation new service
|
# folio/reservation new service
|
||||||
folio_new = self.folio_id
|
folio_new = self.folio_id
|
||||||
reservation_new = self.reservation_id
|
reservation_new = self.reservation_id
|
||||||
new = reservation_new if reservation_new else folio_new
|
new = reservation_new if reservation_new else folio_new
|
||||||
price_fields = ["pricelist_id", "reservation_type"]
|
price_fields = ["pricelist_id", "reservation_type"]
|
||||||
if any(origin[field] != new[field] for field in price_fields) or \
|
if (
|
||||||
self._origin.price_unit == 0:
|
any(origin[field] != new[field] for field in price_fields)
|
||||||
|
or self._origin.price_unit == 0
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
name="domain_force"
|
name="domain_force"
|
||||||
>['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
>['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Property Rules -->
|
<!-- Property Rules -->
|
||||||
<!--<record id="pms_folio_property_rule" model="ir.rule">
|
<!--<record id="pms_folio_property_rule" model="ir.rule">
|
||||||
<field name="name">PMS Folio Company Rule</field>
|
<field name="name">PMS Folio Company Rule</field>
|
||||||
|
|||||||
@@ -19,11 +19,4 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# from . import test_reservation
|
from . import test_pms_reservation
|
||||||
# from . import test_folio
|
|
||||||
from . import test_inherited_ir_http
|
|
||||||
from . import test_inherited_product_pricelist
|
|
||||||
from . import test_hotel_property
|
|
||||||
from . import test_hotel_room_type
|
|
||||||
from . import test_hotel_room
|
|
||||||
from . import test_massive_changes
|
|
||||||
|
|||||||
@@ -34,47 +34,6 @@ class TestHotel(common.SavepointCase):
|
|||||||
def _init_mock_hotel(cls):
|
def _init_mock_hotel(cls):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create_folio(self, creator, partner):
|
|
||||||
# Create Folio
|
|
||||||
folio = (
|
|
||||||
self.env["hotel.folio"].sudo(creator).create({"partner_id": partner.id,})
|
|
||||||
)
|
|
||||||
self.assertTrue(folio, "Can't create folio")
|
|
||||||
return folio
|
|
||||||
|
|
||||||
def create_reservation(
|
|
||||||
self, creator, folio, checkin, checkout, room, resname, adults=1, children=0
|
|
||||||
):
|
|
||||||
# Create Reservation (Special Room)
|
|
||||||
reservation = (
|
|
||||||
self.env["hotel.reservation"]
|
|
||||||
.sudo(creator)
|
|
||||||
.create(
|
|
||||||
{
|
|
||||||
"name": resname,
|
|
||||||
"adults": adults,
|
|
||||||
"children": children,
|
|
||||||
"checkin": checkin.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
|
||||||
"checkout": checkout.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
|
||||||
"folio_id": folio.id,
|
|
||||||
"room_type_id": room.price_room_type.id,
|
|
||||||
"product_id": room.product_id.id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.assertTrue(reservation, "Hotel Calendar can't create a new reservation!")
|
|
||||||
|
|
||||||
# Create Reservation Lines + Update Reservation Price
|
|
||||||
# days_diff = date_utils.date_diff(checkin, checkout, hours=False)
|
|
||||||
# res = reservation.sudo(creator).prepare_reservation_lines(
|
|
||||||
# checkin.strftime(DEFAULT_SERVER_DATETIME_FORMAT), days_diff)
|
|
||||||
# reservation.sudo(creator).write({
|
|
||||||
# 'reservation_lines': res['commands'],
|
|
||||||
# 'price_unit': res['total_price'],
|
|
||||||
# })
|
|
||||||
|
|
||||||
return reservation
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(TestHotel, cls).setUpClass()
|
super(TestHotel, cls).setUpClass()
|
||||||
@@ -82,24 +41,24 @@ class TestHotel(common.SavepointCase):
|
|||||||
cls._init_mock_hotel()
|
cls._init_mock_hotel()
|
||||||
|
|
||||||
# Create Tests Records
|
# Create Tests Records
|
||||||
cls.main_hotel_property = cls.env.ref("hotel.main_hotel_property")
|
cls.main_hotel_property = cls.env.ref("pms.main_pms_property")
|
||||||
cls.demo_hotel_property = cls.env.ref("hotel.demo_hotel_property")
|
cls.demo_hotel_property = cls.env.ref("pms.demo_pms_property")
|
||||||
|
|
||||||
cls.room_type_0 = cls.env.ref("hotel.hotel_room_type_0")
|
cls.room_type_0 = cls.env.ref("pms.pms_room_type_0")
|
||||||
cls.room_type_1 = cls.env.ref("hotel.hotel_room_type_1")
|
cls.room_type_1 = cls.env.ref("pms.pms_room_type_1")
|
||||||
cls.room_type_2 = cls.env.ref("hotel.hotel_room_type_2")
|
cls.room_type_2 = cls.env.ref("pms.pms_room_type_2")
|
||||||
cls.room_type_3 = cls.env.ref("hotel.hotel_room_type_3")
|
cls.room_type_3 = cls.env.ref("pms.pms_room_type_3")
|
||||||
|
|
||||||
cls.demo_room_type_0 = cls.env.ref("hotel.demo_hotel_room_type_0")
|
cls.demo_room_type_0 = cls.env.ref("pms.demo_pms_room_type_0")
|
||||||
cls.demo_room_type_1 = cls.env.ref("hotel.demo_hotel_room_type_1")
|
cls.demo_room_type_1 = cls.env.ref("pms.demo_pms_room_type_1")
|
||||||
|
|
||||||
cls.room_0 = cls.env.ref("hotel.hotel_room_0")
|
cls.room_0 = cls.env.ref("pms.pms_room_0")
|
||||||
cls.room_1 = cls.env.ref("hotel.hotel_room_1")
|
cls.room_1 = cls.env.ref("pms.pms_room_1")
|
||||||
cls.room_2 = cls.env.ref("hotel.hotel_room_2")
|
cls.room_2 = cls.env.ref("pms.pms_room_2")
|
||||||
cls.room_3 = cls.env.ref("hotel.hotel_room_3")
|
cls.room_3 = cls.env.ref("pms.pms_room_3")
|
||||||
cls.room_4 = cls.env.ref("hotel.hotel_room_4")
|
cls.room_4 = cls.env.ref("pms.pms_room_4")
|
||||||
cls.room_5 = cls.env.ref("hotel.hotel_room_5")
|
cls.room_5 = cls.env.ref("pms.pms_room_5")
|
||||||
cls.room_6 = cls.env.ref("hotel.hotel_room_6")
|
cls.room_6 = cls.env.ref("pms.pms_room_6")
|
||||||
|
|
||||||
cls.list0 = cls.env.ref("product.list0")
|
cls.list0 = cls.env.ref("product.list0")
|
||||||
cls.list1 = cls.env["product.pricelist"].create(
|
cls.list1 = cls.env["product.pricelist"].create(
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
|
|
||||||
# Alexandre Díaz <dev@redneboa.es>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
from odoo.addons.hotel import date_utils
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestHotelReservations(TestHotel):
|
|
||||||
def test_cancel_folio(self):
|
|
||||||
now_utc_dt = date_utils.now()
|
|
||||||
|
|
||||||
org_reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
org_reserv_end_utc_dt = org_reserv_start_utc_dt + timedelta(days=6)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation_a = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
org_reserv_start_utc_dt,
|
|
||||||
org_reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Reservation Test #1",
|
|
||||||
)
|
|
||||||
reservation_b = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
org_reserv_start_utc_dt,
|
|
||||||
org_reserv_end_utc_dt,
|
|
||||||
self.hotel_room_simple_100,
|
|
||||||
"Reservation Test #2",
|
|
||||||
)
|
|
||||||
self.assertEqual(len(folio.reservation_ids), 2, "Invalid room lines count")
|
|
||||||
folio.action_cancel()
|
|
||||||
self.assertEqual(folio.state, "cancel", "Invalid folio state")
|
|
||||||
for rline in folio.reservation_ids:
|
|
||||||
self.assertEqual(rline.state, "cancelled", "Invalid reservation state")
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
from odoo import fields
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestHotelProperty(TestHotel):
|
|
||||||
|
|
||||||
# be aware using self.env.user.hotel_id because it is the value configure for the user running the tests
|
|
||||||
|
|
||||||
def test_default_pricelist(self):
|
|
||||||
# A default pricelist must be related with one and only one hotel
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.demo_hotel_property.default_pricelist_id = self.list0
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
|
|
||||||
# Alexandre Díaz <dev@redneboa.es>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestHotelRoom(TestHotel):
|
|
||||||
def test_rooms_by_hotel(self):
|
|
||||||
# A room cannot be created in a room type of another hotel
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
record = (
|
|
||||||
self.env["hotel.room"]
|
|
||||||
.sudo()
|
|
||||||
.create(
|
|
||||||
{
|
|
||||||
"name": "Test Room",
|
|
||||||
"hotel_id": self.demo_hotel_property.id,
|
|
||||||
"room_type_id": self.room_type_0.id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# A room cannot be changed to another hotel
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.room_0.sudo().write({"hotel_id": self.demo_room_type_0.hotel_id.id})
|
|
||||||
|
|
||||||
def test_rooms_by_room_type(self):
|
|
||||||
# A room cannot be changed to a room type of another hotel
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.room_0.sudo().write({"room_type_id": self.demo_room_type_1.id})
|
|
||||||
|
|
||||||
def test_check_capacity(self):
|
|
||||||
# The capacity of the room must be greater than 0
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.room_0.sudo().write({"capacity": 0})
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
|
|
||||||
# Alexandre Díaz <dev@redneboa.es>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
from psycopg2 import IntegrityError
|
|
||||||
|
|
||||||
from odoo.tools import mute_logger
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestHotelRoomType(TestHotel):
|
|
||||||
|
|
||||||
# TODO: use users with different access rules
|
|
||||||
|
|
||||||
# code type must be unique by hotel
|
|
||||||
def test_code_type_unique_by_hotel(self):
|
|
||||||
with self.assertRaises(IntegrityError), mute_logger("odoo.sql_db"):
|
|
||||||
self.room_type_0.sudo().write({"code_type": self.room_type_1.code_type})
|
|
||||||
|
|
||||||
# code type can be used in other hotel
|
|
||||||
def test_code_type_shared_by_hotel(self):
|
|
||||||
test_result = self.demo_room_type_0.sudo().write(
|
|
||||||
{"code_type": self.room_type_0.code_type}
|
|
||||||
)
|
|
||||||
self.assertEqual(test_result, True)
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestInheritedIrHttp(TestHotel):
|
|
||||||
def test_user_hotel_company(self):
|
|
||||||
admin_user = self.env.ref("base.user_root")
|
|
||||||
self.assertTrue(
|
|
||||||
admin_user.hotel_id.company_id in admin_user.company_ids,
|
|
||||||
"Wrong hotel and company access settings for %s" % admin_user.name,
|
|
||||||
)
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
from odoo import fields
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestInheritedProductPricelist(TestHotel):
|
|
||||||
|
|
||||||
# be aware using self.env.user.hotel_id because it is the value configure for the user running the tests
|
|
||||||
|
|
||||||
def test_daily_pricelist(self):
|
|
||||||
# A daily pricelist must be related with one and only one hotel #1
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.list0.hotel_ids += self.demo_hotel_property
|
|
||||||
|
|
||||||
# A daily pricelist must be related with one and only one hotel #2
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.list0.hotel_ids = False
|
|
||||||
|
|
||||||
# create a valid record using a daily pricelist
|
|
||||||
test_result = self.env["product.pricelist"].create(
|
|
||||||
{
|
|
||||||
"name": "Test Daily Pricelist",
|
|
||||||
"hotel_ids": [(4, self.demo_hotel_property.id)],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.assertEqual(test_result.pricelist_type, "daily")
|
|
||||||
self.assertEqual(test_result.hotel_ids, self.demo_hotel_property)
|
|
||||||
|
|
||||||
def test_pricelist_by_hotel(self):
|
|
||||||
# Relationship mismatch when the pricelist is already used as default in a different hotel
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
self.list0.hotel_ids = self.demo_hotel_property
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
from odoo import fields
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
|
|
||||||
class TestMassiveChanges(TestHotel):
|
|
||||||
|
|
||||||
# be aware using self.env.user.hotel_id because it is the value configure for the user running the tests
|
|
||||||
|
|
||||||
# base massive change record
|
|
||||||
def base_massive_change_vals(self, hotel_id=None):
|
|
||||||
return {
|
|
||||||
"hotel_id": hotel_id and hotel_id.id or self.main_hotel_property.id,
|
|
||||||
"date_start": fields.Date.today(),
|
|
||||||
"date_end": fields.Date.today(),
|
|
||||||
}
|
|
||||||
|
|
||||||
def pricelist_massive_change_vals(self, pricelist_id=None):
|
|
||||||
return {
|
|
||||||
"pricelist_id": pricelist_id and pricelist_id.id or self.list0.id,
|
|
||||||
"price": 50.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_daily_pricelist(self):
|
|
||||||
# Only daily pricelist can be manage by a massive change
|
|
||||||
self.list0.pricelist_type = ""
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
vals = self.base_massive_change_vals()
|
|
||||||
vals.update(self.pricelist_massive_change_vals())
|
|
||||||
self.env["hotel.wizard.massive.changes"].create(vals)
|
|
||||||
|
|
||||||
# create a valid record using a daily pricelist
|
|
||||||
self.list0.pricelist_type = "daily"
|
|
||||||
test_result = self.env["hotel.wizard.massive.changes"].create(vals)
|
|
||||||
self.assertEqual(test_result.pricelist_id, self.list0)
|
|
||||||
|
|
||||||
def test_pricelist_by_hotel(self):
|
|
||||||
# Ensure the pricelist plan belongs to the current hotel #1
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
vals = self.base_massive_change_vals(self.demo_hotel_property)
|
|
||||||
vals.update(self.pricelist_massive_change_vals())
|
|
||||||
self.env["hotel.wizard.massive.changes"].create(vals)
|
|
||||||
|
|
||||||
# Ensure the pricelist plan belongs to the current hotel #2
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
vals = self.base_massive_change_vals()
|
|
||||||
vals.update(self.pricelist_massive_change_vals(self.list1))
|
|
||||||
self.list1.hotel_ids = self.demo_hotel_property
|
|
||||||
self.list1.pricelist_type = "daily"
|
|
||||||
self.env["hotel.wizard.massive.changes"].create(vals)
|
|
||||||
|
|
||||||
# create a valid record using the current hotel
|
|
||||||
vals = self.base_massive_change_vals()
|
|
||||||
vals.update(self.pricelist_massive_change_vals(self.list1))
|
|
||||||
self.list1.hotel_ids = self.main_hotel_property
|
|
||||||
self.list1.pricelist_type = "daily"
|
|
||||||
test_result = self.env["hotel.wizard.massive.changes"].create(vals)
|
|
||||||
self.assertEqual(test_result.pricelist_id.hotel_ids, self.main_hotel_property)
|
|
||||||
|
|
||||||
def test_do_massive_change(self):
|
|
||||||
# check the result of a massive change
|
|
||||||
pass
|
|
||||||
35
pms/tests/test_pms_reservation.py
Normal file
35
pms/tests/test_pms_reservation.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from odoo import fields
|
||||||
|
|
||||||
|
from .common import TestHotel
|
||||||
|
|
||||||
|
|
||||||
|
class TestPmsReservations(TestHotel):
|
||||||
|
def test_create_reservation(self):
|
||||||
|
today = fields.date.today()
|
||||||
|
checkin = today + timedelta(days=8)
|
||||||
|
checkout = checkin + timedelta(days=11)
|
||||||
|
demo_user = self.env.ref("base.user_demo")
|
||||||
|
customer = self.env.ref("base.res_partner_12")
|
||||||
|
reservation_vals = {
|
||||||
|
"checkin": checkin,
|
||||||
|
"checkout": checkout,
|
||||||
|
"room_type_id": self.room_type_3.id,
|
||||||
|
"partner_id": customer.id,
|
||||||
|
"pms_property_id": self.main_hotel_property.id,
|
||||||
|
}
|
||||||
|
reservation = (
|
||||||
|
self.env["pms.reservation"].with_user(demo_user).create(reservation_vals)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
reservation.reservation_line_ids[0].date,
|
||||||
|
checkin,
|
||||||
|
"Reservation lines don't start in the correct date",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
reservation.reservation_line_ids[-1].date,
|
||||||
|
checkout - timedelta(1),
|
||||||
|
"Reservation lines don't end in the correct date",
|
||||||
|
)
|
||||||
@@ -1,294 +0,0 @@
|
|||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
|
|
||||||
# Alexandre Díaz <dev@redneboa.es>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
import datetime
|
|
||||||
import logging
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import pytz
|
|
||||||
from openerp.exceptions import ValidationError
|
|
||||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
|
|
||||||
|
|
||||||
from odoo import fields
|
|
||||||
|
|
||||||
from odoo.addons.hotel import date_utils
|
|
||||||
|
|
||||||
from .common import TestHotel
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class TestHotelReservations(TestHotel):
|
|
||||||
def test_create_reservation(self):
|
|
||||||
now_utc_dt = date_utils.now()
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Reservation Test #1",
|
|
||||||
)
|
|
||||||
|
|
||||||
reserv_start_dt = date_utils.dt_as_timezone(reserv_start_utc_dt, self.tz_hotel)
|
|
||||||
reserv_end_dt = date_utils.dt_as_timezone(
|
|
||||||
reserv_end_utc_dt - timedelta(days=1), self.tz_hotel
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
reservation.reservation_lines[0].date,
|
|
||||||
reserv_start_dt.strftime(DEFAULT_SERVER_DATE_FORMAT),
|
|
||||||
"Reservation lines don't start in the correct date",
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
reservation.reservation_lines[-1].date,
|
|
||||||
reserv_end_dt.strftime(DEFAULT_SERVER_DATE_FORMAT),
|
|
||||||
"Reservation lines don't end in the correct date",
|
|
||||||
)
|
|
||||||
|
|
||||||
total_price = 0.0
|
|
||||||
for rline in reservation.reservation_lines:
|
|
||||||
total_price += rline.price
|
|
||||||
self.assertEqual(
|
|
||||||
folio.amount_untaxed,
|
|
||||||
total_price,
|
|
||||||
"Folio amount doesn't match with reservation lines",
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_create_reservations(self):
|
|
||||||
now_utc_dt = date_utils.now()
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Reservation Test #1",
|
|
||||||
)
|
|
||||||
|
|
||||||
reserv_start_utc_dt = reserv_end_utc_dt
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Reservation Test #2",
|
|
||||||
)
|
|
||||||
|
|
||||||
reserv_end_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
reserv_start_utc_dt = reserv_end_utc_dt - timedelta(days=1)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Reservation Test #3",
|
|
||||||
)
|
|
||||||
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_simple_100,
|
|
||||||
"Reservation Test #4",
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_create_invalid_reservations(self):
|
|
||||||
now_utc_dt = date_utils.now()
|
|
||||||
|
|
||||||
org_reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
org_reserv_end_utc_dt = org_reserv_start_utc_dt + timedelta(days=6)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
org_reserv_start_utc_dt,
|
|
||||||
org_reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Original Reservation Test #1",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Same Dates
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=6)
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #1",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Inside Org Reservation (Start Same Date)
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=3)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #2",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Inside Org Reservation (Start after)
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=4)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #3",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Intersect Org Reservation (Start before)
|
|
||||||
reserv_start_utc_dt = now_utc_dt + timedelta(days=2)
|
|
||||||
reserv_end_utc_dt = reserv_start_utc_dt + timedelta(days=3)
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #4",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Intersect Org Reservation (End Same)
|
|
||||||
reserv_start_utc_dt = org_reserv_end_utc_dt - timedelta(days=2)
|
|
||||||
reserv_end_utc_dt = org_reserv_end_utc_dt
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #5",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Intersect Org Reservation (End after)
|
|
||||||
reserv_start_utc_dt = org_reserv_end_utc_dt - timedelta(days=2)
|
|
||||||
reserv_end_utc_dt = org_reserv_end_utc_dt + timedelta(days=3)
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #6",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Overlays Org Reservation
|
|
||||||
reserv_start_utc_dt = org_reserv_start_utc_dt - timedelta(days=2)
|
|
||||||
reserv_end_utc_dt = org_reserv_end_utc_dt + timedelta(days=2)
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
reserv_start_utc_dt,
|
|
||||||
reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Invalid Reservation Test #7",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Checkin > Checkout
|
|
||||||
with self.assertRaises(ValidationError):
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
org_reserv_end_utc_dt,
|
|
||||||
org_reserv_start_utc_dt,
|
|
||||||
self.hotel_room_simple_100,
|
|
||||||
"Invalid Reservation Test #8",
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_modify_reservation(self):
|
|
||||||
now_utc_dt = date_utils.now()
|
|
||||||
|
|
||||||
# 5.0, 15.0, 15.0, 35.0, 35.0, 10.0, 10.0
|
|
||||||
|
|
||||||
room_type_prices = self.prices_tmp[
|
|
||||||
self.hotel_room_double_200.price_room_type.id
|
|
||||||
]
|
|
||||||
org_reserv_start_utc_dt = now_utc_dt + timedelta(days=1)
|
|
||||||
org_reserv_end_utc_dt = org_reserv_start_utc_dt + timedelta(days=2)
|
|
||||||
folio = self.create_folio(self.user_hotel_manager, self.partner_2)
|
|
||||||
reservation = self.create_reservation(
|
|
||||||
self.user_hotel_manager,
|
|
||||||
folio,
|
|
||||||
org_reserv_start_utc_dt,
|
|
||||||
org_reserv_end_utc_dt,
|
|
||||||
self.hotel_room_double_200,
|
|
||||||
"Original Reservation Test #1",
|
|
||||||
)
|
|
||||||
ndate = org_reserv_start_utc_dt
|
|
||||||
for r_k, r_v in enumerate(reservation.reservation_lines):
|
|
||||||
self.assertEqual(r_v.date, ndate.strftime(DEFAULT_SERVER_DATE_FORMAT))
|
|
||||||
self.assertEqual(r_v.price, room_type_prices[r_k + 1])
|
|
||||||
ndate = ndate + timedelta(days=1)
|
|
||||||
self.assertEqual(reservation.amount_room, 30.0)
|
|
||||||
ndate = org_reserv_start_utc_dt + timedelta(days=1)
|
|
||||||
line = reservation.reservation_lines.filtered(
|
|
||||||
lambda r: r.date == ndate.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
|
||||||
)
|
|
||||||
reservation.reservation_lines = [(1, line.id, {"price": 100.0})]
|
|
||||||
self.assertEqual(reservation.amount_room, 115.0)
|
|
||||||
reservation.sudo(self.user_hotel_manager).write(
|
|
||||||
{
|
|
||||||
"checkin": (org_reserv_start_utc_dt + timedelta(days=1)).strftime(
|
|
||||||
DEFAULT_SERVER_DATE_FORMAT
|
|
||||||
),
|
|
||||||
"checkout": (org_reserv_end_utc_dt + timedelta(days=1)).strftime(
|
|
||||||
DEFAULT_SERVER_DATE_FORMAT
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.assertEqual(reservation.amount_room, 135.0)
|
|
||||||
@@ -495,10 +495,7 @@
|
|||||||
<!-- <field name="product_uom" string="Rent(UOM)" invisible="1" /> -->
|
<!-- <field name="product_uom" string="Rent(UOM)" invisible="1" /> -->
|
||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page
|
<page name="detail" string="Detail">
|
||||||
name="detail"
|
|
||||||
string="Detail"
|
|
||||||
>
|
|
||||||
<button
|
<button
|
||||||
name="%(action_pms_massive_price_change_reservation_days)d"
|
name="%(action_pms_massive_price_change_reservation_days)d"
|
||||||
string="Massive Day Prices"
|
string="Massive Day Prices"
|
||||||
@@ -518,15 +515,12 @@
|
|||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<button
|
<button
|
||||||
name="%(action_service_on_day)d"
|
name="%(action_service_on_day)d"
|
||||||
string="Service on Day"
|
string="Service on Day"
|
||||||
type="action"
|
type="action"
|
||||||
icon="fa-coffee"
|
icon="fa-coffee"
|
||||||
/>
|
/>
|
||||||
<group
|
<group string="Services" name="reservation_services">
|
||||||
string="Services"
|
|
||||||
name="reservation_services"
|
|
||||||
>
|
|
||||||
<field
|
<field
|
||||||
name="service_ids"
|
name="service_ids"
|
||||||
context="{'default_reservation_id': active_id, 'default_folio_id': folio_id, 'form_view_ref':'pms.pms_service_view_form'}"
|
context="{'default_reservation_id': active_id, 'default_folio_id': folio_id, 'form_view_ref':'pms.pms_service_view_form'}"
|
||||||
@@ -863,6 +857,7 @@
|
|||||||
<field name="create_date" />
|
<field name="create_date" />
|
||||||
<field name="overbooking" invisible="1" />
|
<field name="overbooking" invisible="1" />
|
||||||
<field name="last_updated_res" string="Updated on" />
|
<field name="last_updated_res" string="Updated on" />
|
||||||
|
<field name="origin" />
|
||||||
<field name="checkin_partner_ids" invisible="1" />
|
<field name="checkin_partner_ids" invisible="1" />
|
||||||
<field name="to_assign" invisible="1" />
|
<field name="to_assign" invisible="1" />
|
||||||
<field name="checkin_partner_pending_count" invisible="1" />
|
<field name="checkin_partner_pending_count" invisible="1" />
|
||||||
|
|||||||
Reference in New Issue
Block a user