Merge PR #52 into 14.0

Signed-off-by DarioLodeiros
This commit is contained in:
OCA-git-bot
2021-08-13 07:33:35 +00:00
9 changed files with 751 additions and 80 deletions

View File

@@ -604,16 +604,20 @@ class PmsFolio(models.Model):
)
def _compute_sale_line_ids(self):
for folio in self:
for reservation in folio.reservation_ids:
# RESERVATION LINES
# res = self.env['pms.reservation'].browse(reservation.id)
self.generate_reservation_lines_sale_lines(folio, reservation)
if folio.reservation_type == "normal":
for reservation in folio.reservation_ids:
# RESERVATION LINES
# res = self.env['pms.reservation'].browse(reservation.id)
self.generate_reservation_lines_sale_lines(folio, reservation)
# RESERVATION SERVICES
self.generate_reservation_services_sale_lines(folio, reservation)
# RESERVATION SERVICES
self.generate_reservation_services_sale_lines(folio, reservation)
# FOLIO SERVICES
self.generate_folio_services_sale_lines(folio)
# FOLIO SERVICES
self.generate_folio_services_sale_lines(folio)
else:
for reservation in folio.reservation_ids:
reservation.sale_line_ids = False
@api.depends("pms_property_id")
def _compute_company_id(self):
@@ -765,7 +769,7 @@ class PmsFolio(models.Model):
else:
order.invoice_status = "no"
@api.depends("partner_id", "partner_id.name", "agency_id")
@api.depends("partner_id", "partner_id.name", "agency_id", "reservation_type")
def _compute_partner_name(self):
for record in self:
self._apply_partner_name(record)
@@ -841,22 +845,24 @@ class PmsFolio(models.Model):
@api.depends("checkin_partner_ids", "checkin_partner_ids.state")
def _compute_pending_checkin_data(self):
for folio in self:
folio.pending_checkin_data = len(
folio.checkin_partner_ids.filtered(lambda c: c.state == "draft")
)
if folio.reservation_type != "out":
folio.pending_checkin_data = len(
folio.checkin_partner_ids.filtered(lambda c: c.state == "draft")
)
@api.depends("pending_checkin_data")
def _compute_ratio_checkin_data(self):
self.ratio_checkin_data = 0
for folio in self.filtered("reservation_ids"):
folio.ratio_checkin_data = (
(
sum(folio.reservation_ids.mapped("adults"))
- folio.pending_checkin_data
if folio.reservation_type != "out":
folio.ratio_checkin_data = (
(
sum(folio.reservation_ids.mapped("adults"))
- folio.pending_checkin_data
)
* 100
/ sum(folio.reservation_ids.mapped("adults"))
)
* 100
/ sum(folio.reservation_ids.mapped("adults"))
)
# TODO: Add return_ids to depends
@api.depends(
@@ -871,7 +877,9 @@ class PmsFolio(models.Model):
def _compute_amount(self):
for record in self:
if record.reservation_type in ("staff", "out"):
record.amount_total = 0
vals = {
"payment_state": False,
"pending_amount": 0,
"invoices_paid": 0,
}

View File

@@ -342,9 +342,10 @@ class PmsReservation(models.Model):
reservation_type = fields.Selection(
string="Reservation Type",
help="Type of reservations. It can be 'normal', 'staff' or 'out of service",
related="folio_id.reservation_type",
store=True,
readonly=False,
compute="_compute_reservation_type",
selection=[("normal", "Normal"), ("staff", "Staff"), ("out", "Out of Service")],
)
splitted = fields.Boolean(
string="Splitted",
@@ -867,7 +868,7 @@ class PmsReservation(models.Model):
for reservation in self:
if reservation.reservation_type in ("out", "staff"):
reservation.pricelist_id = False
if reservation.agency_id and reservation.agency_id.apply_pricelist:
elif reservation.agency_id and reservation.agency_id.apply_pricelist:
reservation.pricelist_id = (
reservation.agency_id.property_product_pricelist
)
@@ -986,7 +987,8 @@ class PmsReservation(models.Model):
record.allowed_checkin = (
True
if (
record.state in ["draft", "confirm", "arrival_delayed"]
record.reservation_type != "out"
and record.state in ["draft", "confirm", "arrival_delayed"]
and record.checkin <= fields.Date.today()
)
else False
@@ -1133,13 +1135,13 @@ class PmsReservation(models.Model):
reservation.commission_amount = 0
# REVIEW: Dont run with set room_type_id -> room_id(compute)-> No set adults¿?
@api.depends("preferred_room_id")
@api.depends("preferred_room_id", "reservation_type")
def _compute_adults(self):
for reservation in self:
if reservation.preferred_room_id:
if reservation.preferred_room_id and reservation.reservation_type != "out":
if reservation.adults == 0:
reservation.adults = reservation.preferred_room_id.capacity
elif not reservation.adults:
elif not reservation.adults or reservation.reservation_type == "out":
reservation.adults = 0
@api.depends("reservation_line_ids", "reservation_line_ids.room_id")
@@ -1177,6 +1179,8 @@ class PmsReservation(models.Model):
line.invoice_status = "no"
else:
line.invoice_status = "no"
if line.reservation_type != "normal":
line.invoice_status = "no"
@api.depends("reservation_line_ids")
def _compute_nights(self):
@@ -1262,10 +1266,19 @@ class PmsReservation(models.Model):
else:
record.shared_folio = False
@api.depends("partner_id", "partner_id.name", "agency_id")
@api.depends(
"partner_id",
"partner_id.name",
"agency_id",
"reservation_type",
"out_service_description",
)
def _compute_partner_name(self):
for record in self:
self.env["pms.folio"]._apply_partner_name(record)
if record.reservation_type != "out":
self.env["pms.folio"]._apply_partner_name(record)
else:
record.partner_name = record.out_service_description
@api.depends("partner_id", "partner_id.email", "agency_id")
def _compute_email(self):
@@ -1340,6 +1353,14 @@ class PmsReservation(models.Model):
else:
reservation.rooms = reservation.preferred_room_id.name
@api.depends("folio_id", "folio_id.reservation_type")
def _compute_reservation_type(self):
for record in self:
if record.folio_id:
record.reservation_type = record.folio_id.reservation_type
else:
record.reservation_type = "normal"
def _search_allowed_checkin(self, operator, value):
if operator not in ("=",):
raise UserError(
@@ -1451,6 +1472,7 @@ class PmsReservation(models.Model):
if (
not record.checkin_partner_ids.filtered(lambda c: c.state == "onboard")
and record.state == "onboard"
and record.reservation_type != "out"
):
raise ValidationError(
_("No person from reserve %s has arrived", record.name)
@@ -1496,6 +1518,19 @@ class PmsReservation(models.Model):
record, record.service_ids.service_line_ids
)
@api.constrains("reservation_type")
def _check_same_reservation_type(self):
for record in self:
if len(record.folio_id.reservation_ids) > 1:
for reservation in record.folio_id.reservation_ids:
if reservation.reservation_type != record.reservation_type:
raise ValidationError(
_(
"The reservation type must be the "
"same for all reservations in folio"
)
)
# Action methods
def open_partner(self):
""" Utility method used to add an "View Customer" button in reservation views """
@@ -1618,6 +1653,8 @@ class PmsReservation(models.Model):
raise ValidationError(_("Partner contact name is required"))
# Create the folio in case of need
# (To allow to create reservations direct)
if vals.get("reservation_type"):
folio_vals["reservation_type"] = vals.get("reservation_type")
folio = self.env["pms.folio"].create(folio_vals)
vals.update(
{

View File

@@ -353,6 +353,7 @@ class PmsReservationLine(models.Model):
not reservation.room_type_id
or not reservation.pricelist_id
or not reservation.pms_property_id
or reservation.reservation_type != "normal"
):
line.price = 0
elif not line.price or self._context.get("force_recompute"):

View File

@@ -547,35 +547,38 @@ class PmsService(models.Model):
def _get_price_unit_line(self, date=False):
self.ensure_one()
folio = self.folio_id
reservation = self.reservation_id
origin = reservation if reservation else folio
if origin:
partner = origin.partner_id
pricelist = origin.pricelist_id
board_room_type = False
product_context = dict(
self.env.context,
lang=partner.lang,
partner=partner.id,
quantity=self.product_qty,
date=folio.date_order if folio else fields.Date.today(),
pricelist=pricelist.id,
board_service=board_room_type.id if board_room_type else False,
uom=self.product_id.uom_id.id,
fiscal_position=False,
property=self.reservation_id.pms_property_id.id,
)
if date:
product_context["consumption_date"] = date
if reservation and self.is_board_service:
product_context["board_service"] = reservation.board_service_room_id.id
product = self.product_id.with_context(product_context)
return self.env["account.tax"]._fix_tax_included_price_company(
self._get_display_price(product),
product.taxes_id,
self.tax_ids,
origin.company_id,
)
else:
return 0
if self.reservation_id.reservation_type == "normal":
folio = self.folio_id
reservation = self.reservation_id
origin = reservation if reservation else folio
if origin:
partner = origin.partner_id
pricelist = origin.pricelist_id
board_room_type = False
product_context = dict(
self.env.context,
lang=partner.lang,
partner=partner.id,
quantity=self.product_qty,
date=folio.date_order if folio else fields.Date.today(),
pricelist=pricelist.id,
board_service=board_room_type.id if board_room_type else False,
uom=self.product_id.uom_id.id,
fiscal_position=False,
property=self.reservation_id.pms_property_id.id,
)
if date:
product_context["consumption_date"] = date
if reservation and self.is_board_service:
product_context[
"board_service"
] = reservation.board_service_room_id.id
product = self.product_id.with_context(product_context)
return self.env["account.tax"]._fix_tax_included_price_company(
self._get_display_price(product),
product.taxes_id,
self.tax_ids,
origin.company_id,
)
else:
return 0

View File

@@ -3,6 +3,7 @@ import datetime
from freezegun import freeze_time
from odoo import fields
from odoo.exceptions import ValidationError
from .common import TestPms
@@ -333,3 +334,227 @@ class TestPmsFolio(TestPms):
"The pending amount on a partially paid folio it \
does not correspond to the amount that it should",
)
def test_reservation_type_folio(self):
"""
Check that the reservation_type of a folio with
a reservation with the default reservation_type is equal
to 'normal'.
---------------
A folio is created. A reservation is created to which the
value of the folio_id is the id of the previously created
folio. Then it is verified that the value of the reservation_type
field of the folio is 'normal'.
"""
# ARRANGE AND ACT
self.partner1 = self.env["res.partner"].create({"name": "Ana"})
folio1 = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner1.id,
}
)
self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"checkin": fields.date.today(),
"checkout": fields.date.today() + datetime.timedelta(days=1),
"folio_id": folio1.id,
}
)
# ASSERT
self.assertEqual(
folio1.reservation_type,
"normal",
"The default reservation type of the folio should be 'normal'",
)
def test_invoice_status_staff_reservation(self):
"""
Check that the value of the invoice_status field is 'no'
on a page with reservation_type equal to 'staff'.
------------
A reservation is created with the reservation_type field
equal to 'staff'. Then it is verified that the value of
the invoice_status field of the folio created with the
reservation is equal to 'no'.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
self.partner1 = self.env["res.partner"].create({"name": "Pedro"})
# ACT
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "staff",
}
)
# ASSERT
self.assertEqual(
reservation.folio_id.invoice_status,
"no",
"The invoice status of the folio in a staff reservation should be 'no' ",
)
def test_invoice_status_out_reservation(self):
"""
Check that the value of the invoice_status field is 'no'
on a page with reservation_type equal to 'out'.
------------
A reservation is created with the reservation_type field
equal to 'out'. Then it is verified that the value of
the invoice_status field of the folio created with the
reservation is equal to 'no'.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
self.partner1 = self.env["res.partner"].create({"name": "Pedro"})
# ACT
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "out",
}
)
# ASSERT
self.assertEqual(
reservation.folio_id.invoice_status,
"no",
"The invoice status of the folio in a out reservation should be 'no' ",
)
def test_amount_total_staff_reservation(self):
"""
Check that the amount_total field of the folio whose
reservation has the reservation_type field as staff
is not calculated.
-------------------------
A folio is created. A reservation is created to which the
value of the folio_id is the id of the previously created
folio and the field reservation_type equal to 'staff'. Then
it is verified that the value of the amount_total field of
the folio is 0.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
self.partner1 = self.env["res.partner"].create({"name": "Pedro"})
# ACT
folio1 = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner1.id,
}
)
self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"checkin": checkin,
"checkout": checkout,
"folio_id": folio1.id,
"reservation_type": "staff",
}
)
# ASSERT
self.assertEqual(
folio1.amount_total,
0.0,
"The amount total of the folio in a staff reservation should be 0",
)
def test_amount_total_out_reservation(self):
"""
Check that the amount_total field of the folio whose
reservation has the reservation_type field as out
is not calculated.
-------------------------
A folio is created. A reservation is created to which the
value of the folio_id is the id of the previously created
folio and the field reservation_type equal to 'out'. Then
it is verified that the value of the amount_total field of
the folio is 0.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
self.partner1 = self.env["res.partner"].create({"name": "Pedro"})
# ACT
folio1 = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner1.id,
}
)
self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"checkin": checkin,
"checkout": checkout,
"folio_id": folio1.id,
"reservation_type": "out",
}
)
# ASSERT
self.assertEqual(
folio1.amount_total,
0.0,
"The amount total of the folio in a out of service reservation should be 0",
)
def test_reservation_type_incongruence(self):
"""
Check that a reservation cannot be created
with the reservation_type field different from the
reservation_type of its folio.
-------------
A folio is created. A reservation is created to which the
value of the folio_id is the id of the previously created
folio and the field reservation_type by default('normal').
Then it is tried to create another reservation with its
reservation_type equal to 'staff'. But it should throw an
error because the value of the reservation_type of the
folio is equal to 'normal'.
"""
self.partner1 = self.env["res.partner"].create({"name": "Ana"})
folio1 = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner1.id,
}
)
self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"checkin": fields.date.today(),
"checkout": fields.date.today() + datetime.timedelta(days=3),
"folio_id": folio1.id,
}
)
with self.assertRaises(
ValidationError,
msg="You cannot create reservations with different reservation_type for a folio",
):
self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"checkin": fields.date.today(),
"checkout": fields.date.today() + datetime.timedelta(days=3),
"folio_id": folio1.id,
"reservation_type": "staff",
}
)

View File

@@ -31,6 +31,14 @@ class TestPmsFolioSaleLine(TestPms):
"capacity": 2,
}
)
self.room2 = self.env["pms.room"].create(
{
"pms_property_id": self.pms_property1.id,
"name": "Double 102",
"room_type_id": self.room_type_double.id,
"capacity": 2,
}
)
self.product_test1 = self.env["product.product"].create(
{
@@ -1179,3 +1187,67 @@ class TestPmsFolioSaleLine(TestPms):
expected_folio_service_sale_lines
),
)
def test_no_sale_lines_staff_reservation(self):
"""
Check that the sale_line_ids of a folio whose reservation
is of type 'staff' are not created.
-----
A reservation is created with the reservation_type field
with value 'staff'. Then it is verified that the
sale_line_ids of the folio created with the creation of
the reservation are equal to False.
"""
# ARRANGE
self.partner1 = self.env["res.partner"].create({"name": "Alberto"})
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "staff",
}
)
# ASSERT
self.assertFalse(
reservation.folio_id.sale_line_ids,
"Folio sale lines should not be generated for a staff type reservation ",
)
def test_no_sale_lines_out_reservation(self):
"""
Check that the sale_line_ids of a folio whose reservation
is of type 'out' are not created.
-----
A reservation is created with the reservation_type field
with value 'out'. Then it is verified that the
sale_line_ids of the folio created with the creation of
the reservation are equal to False.
"""
# ARRANGE
self.partner1 = self.env["res.partner"].create({"name": "Alberto"})
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "out",
}
)
# ASSERT
self.assertFalse(
reservation.folio_id.sale_line_ids,
"Folio sale lines should not be generated for a out of service type reservation ",
)

View File

@@ -46,6 +46,7 @@ class TestPmsReservations(TestPms):
"name": "Double 102",
"room_type_id": self.room_type_double.id,
"capacity": 2,
"extra_beds_allowed": 1,
}
)
@@ -55,6 +56,7 @@ class TestPmsReservations(TestPms):
"name": "Double 103",
"room_type_id": self.room_type_double.id,
"capacity": 2,
"extra_beds_allowed": 1,
}
)
self.partner1 = self.env["res.partner"].create(
@@ -2902,3 +2904,258 @@ class TestPmsReservations(TestPms):
reservation.discount,
"Room discount isn't the expected",
)
def test_default_normal_reservation_type(self):
"""
Check that the default reservation type is "normal".
-----------
A reservation is created without defining the reservation_type
field and it is checked that it is 'normal'
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
self.partner1 = self.env["res.partner"].create({"name": "Ana"})
folio1 = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner1.id,
}
)
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"folio_id": folio1.id,
}
)
# ASSERT
self.assertEqual(
reservation.reservation_type,
"normal",
"The default reservation type should be 'normal'",
)
def test_price_normal_reservation(self):
"""
Check the price of a normal type reservation.
-----------
A reservation is created for a room with price 30.
Then it is verified that the total price of the
reservation is equal to the price of the room multiplied
by the number of days of the reservation.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
}
)
diff_days = (checkout - checkin).days
expected_price = self.room_type_double.list_price * diff_days
# ASSERT
self.assertEqual(
reservation.price_total,
expected_price,
"The expected price of the reservation is not correct",
)
def test_price_staff_reservation(self):
"""
Check that the price of a staff type reservation
is not calculated.
-------------
A reservation is created with the reservation_type field as 'staff'.
Then it is verified that the price of the reservation is equal to 0.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "staff",
}
)
# ASSERT
self.assertEqual(
reservation.price_total,
0.0,
"The expected price of the reservation is not correct",
)
def test_price_out_of_service_reservation(self):
"""
Check that the price of a out type reservation
is not calculated.
-------------
A reservation is created with the reservation_type field as 'out'.
Then it is verified that the price of the reservation is equal to 0.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "out",
}
)
# ASSERT
self.assertEqual(
reservation.price_total,
0.0,
"The expected price of the reservation is not correct",
)
def test_no_pricelist_staff_reservation(self):
"""
Check that in a staff type reservation the pricelist is False.
-------------
A reservation is created with the reservation_type field as 'staff'.
Then it is verified that the pricelist of the reservation is False.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"reservation_type": "staff",
}
)
self.assertFalse(
reservation.pricelist_id,
"The pricelist of a staff reservation should be False",
)
def test_no_pricelist_out_reservation(self):
"""
Check that in a out type reservation the pricelist is False.
-------------
A reservation is created with the reservation_type field as 'out'.
Then it is verified that the pricelist of the reservation is False.
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"reservation_type": "out",
}
)
self.assertFalse(
reservation.pricelist_id,
"The pricelist of a out of service reservation should be False",
)
def test_reservation_type_by_folio(self):
"""
Check that the reservation type field in a reservation is the
same as the reservation type on the folio that contains
that reservation.
--------------------------
A folio is created with the field reservation_type as 'staff'.
A reservation is created to which the
value of the folio_id is the id of the previously created
folio. Then it is verified that the value of the reservation_type
field of the reservation is the same that reservation_type in the folio:
'staff'.
"""
# ARRANGE AND ACT
self.partner1 = self.env["res.partner"].create({"name": "Ana"})
folio1 = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner1.id,
"reservation_type": "staff",
}
)
reservation1 = self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"checkin": fields.date.today(),
"checkout": fields.date.today() + datetime.timedelta(days=1),
"folio_id": folio1.id,
}
)
# ASSERT
self.assertEqual(
reservation1.reservation_type,
"staff",
"The reservation type of the folio should be 'staff'",
)
def test_no_partner_id_out_reservation(self):
"""
Check that a reservation of type out of service does not
have a partner_id.
------------------
A reservation is created without a partner_id and with the
value of the field reservation_type as '' out. Then it is
checked that the partner_id field of the reservation is False
"""
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
# ACT
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"pms_property_id": self.pms_property1.id,
"reservation_type": "out",
"partner_name": "Install furniture",
}
)
self.assertFalse(
reservation.partner_id,
"The partner of an out of service reservation should be False",
)

View File

@@ -123,6 +123,7 @@
type="object"
class="oe_stat_button"
name="action_checks"
attrs="{'invisible': [('reservation_type', 'in', 'out')]}"
>
<field
name="ratio_checkin_data"
@@ -148,6 +149,7 @@
type="object"
class="oe_stat_button"
icon="fa-magic"
attrs="{'invisible': [('reservation_type', 'not in', 'normal')]}"
>
<span class="o_stat_text">Change in Group</span>
</button>
@@ -165,6 +167,7 @@
type="object"
class="oe_stat_button"
icon="fa-globe icon"
attrs="{'invisible': [('reservation_type', '!=', 'normal')]}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Customer</span>
@@ -183,6 +186,19 @@
bg_color="bg-warning"
attrs="{'invisible': [('payment_state', '!=', 'partial')]}"
/>
<widget
name="web_ribbon"
title="Staff"
bg_color="bg-info"
attrs="{'invisible': [('reservation_type', 'not in', 'staff')]}"
/>
<widget
name="web_ribbon"
title="Out of Service"
bg_color="bg-dark"
attrs="{'invisible': [('reservation_type', 'not in', 'out')]}"
/>
<h2>
<field name="name" />
</h2>
@@ -239,7 +255,10 @@
name="sale_details"
>
<field name="pms_property_id" invisible="0" />
<field name="pricelist_id" />
<field
name="pricelist_id"
attrs="{'invisible': [('reservation_type', 'not in', 'normal')]}"
/>
<field
name="company_id"
options="{'no_create': True}"
@@ -249,10 +268,13 @@
name="reservation_type"
attrs="{'readonly':[('state','not in',('draft'))]}"
/>
<field name="agency_id" />
<field
name="agency_id"
attrs="{'invisible': [('reservation_type', 'not in', 'normal')]}"
/>
<field
name="channel_type_id"
attrs="{'readonly':[('agency_id','!=', False)]}"
attrs="{'readonly':[('agency_id','!=', False)], 'invisible':[('reservation_type', 'not in', 'normal')]}"
/>
<field name="internal_comment" />
</group>
@@ -260,6 +282,7 @@
class="oe_subtotal_footer oe_right"
colspan="2"
name="folio_total"
attrs="{'invisible':[('reservation_type', '!=', 'normal')]}"
>
<field
name="amount_untaxed"
@@ -302,7 +325,10 @@
<field name="invoices_paid" invisible="1" />
</group>
<notebook colspan="4" col="1">
<page string="Sale Lines">
<page
string="Sale Lines"
attrs="{'invisible':[('reservation_type', '!=', 'normal')]}"
>
<field
name="sale_line_ids"
widget="section_and_note_one2many"
@@ -465,7 +491,11 @@
}"
/>
</page>
<page name="invoicing" string="Invoicing">
<page
name="invoicing"
string="Invoicing"
attrs="{'invisible':[('reservation_type', '!=', 'normal')]}"
>
<div
class="alert alert-info"
role="alert"
@@ -525,12 +555,17 @@
decoration-muted="state == 'cancel'"
default_order="create_date desc"
>
<field name="name" />
<field
name="name"
decoration-info="reservation_type == 'staff'"
decoration-bf="reservation_type == 'out'"
/>
<field name="partner_id" invisible="1" />
<field name="partner_name" select="1" />
<field name="date_order" select="1" />
<field name="user_id" widget="many2one_avatar_user" optional="show" />
<field name="reservation_ids" widget="many2many_tags" optional="show" />
<field name="reservation_type" invisible="1" />
<field
name="amount_total"
sum="Total amount"

View File

@@ -130,8 +130,9 @@
string="Print All Checkins"
type="object"
icon="fa-print"
attrs="{'invisible':[
('checkin_partner_ids','=', [])
attrs="{'invisible':['|',
('checkin_partner_ids','=', []),
('reservation_type', 'in', ('out'))
]}"
/>
<button
@@ -139,6 +140,7 @@
type="object"
class="oe_stat_button"
icon="fa-globe icon"
attrs="{'invisible':[('reservation_type','not in',('normal'))]}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Customer</span>
@@ -200,8 +202,8 @@
type="object"
class="oe_stat_button"
name="action_checkin_partner_view"
attrs="{'invisible': [
('allowed_checkin', '!=', True),
attrs="{'invisible': ['|',
('allowed_checkin', '!=', True), ('reservation_type','in',('out'))
]}"
>
<field
@@ -221,6 +223,19 @@
title="Partial"
bg_color="bg-warning"
attrs="{'invisible': [('folio_payment_state', '!=', 'partial')]}"
/>
<widget
name="web_ribbon"
title="Staff"
bg_color="bg-info"
attrs="{'invisible': [('reservation_type', 'not in', 'staff')]}"
/>
<widget
name="web_ribbon"
title="Out of Service"
bg_color="bg-dark"
attrs="{'invisible': [('reservation_type', 'not in', 'out')]}"
/>
<div
class="card bg-danger mb8"
@@ -286,11 +301,6 @@
attrs="{'invisible': [('splitted','=',True)]}"
/>
</h3>
<field
name="out_service_description"
placeholder="Out service description"
attrs="{'invisible':[('reservation_type','not in',('out'))]}"
/>
<group col="8">
<group
colspan="2"
@@ -298,12 +308,20 @@
string="General Info"
name="contact_details"
>
<field name="partner_id" invisible="0" />
<field
name="partner_id"
attrs="{'invisible':[('reservation_type','in',('out'))]}"
/>
<field
name="partner_name"
placeholder="Guest"
attrs="{'invisible':[('reservation_type','in',('out'))]}"
/>
<field
name="out_service_description"
placeholder="Out service description"
attrs="{'invisible':[('reservation_type','not in',('out'))]}"
/>
<field
name="email"
placeholder="email"
@@ -340,6 +358,7 @@
<field
name="pricelist_id"
options="{'no_open':True,'no_create': True}"
attrs="{'invisible': [('reservation_type', '!=', 'normal')]}"
/>
<!--<field
name="agency_id"
@@ -376,10 +395,13 @@
nolabel="1"
placeholder="Reservation Notes"
/>
<field name="agency_id" />
<field
name="agency_id"
attrs="{'invisible': [('reservation_type', '!=', 'normal')]}"
/>
<field
name="channel_type_id"
attrs="{'readonly':[('agency_id','!=', False)]}"
attrs="{'readonly':[('agency_id','!=', False)], 'invisible': [('reservation_type', '!=', 'normal')]}"
/>
</group>
<group
@@ -387,6 +409,7 @@
class="oe_subtotal_footer oe_right"
name="reservation_total"
string="Amounts"
attrs="{'invisible':[('reservation_type', '!=', 'normal')]}"
>
<field
name="price_services"
@@ -483,7 +506,11 @@
<field name="pms_property_id" invisible="1" />
</tree>
</field>
<group string="Services" name="reservation_services">
<group
string="Services"
name="reservation_services"
attrs="{'invisible':[('reservation_type', 'in', ('out'))]}"
>
<field
name="service_ids"
context="{'default_reservation_id': active_id, 'default_folio_id': folio_id, 'form_view_ref':'pms.pms_service_view_form'}"
@@ -596,7 +623,7 @@
<page
name="invoicing"
string="Invoicing"
attrs="{'invisible': [('reservation_type','in',('out'))]}"
attrs="{'invisible': [('reservation_type','in',('out','staff'))]}"
>
</page>
<page name="others" string="Others">
@@ -667,8 +694,14 @@
decoration-bf="splitted"
js_class="pms_booking_engine_request_tree"
>
<field name="reservation_type" invisible="1" />
<field name="folio_id" optional="show" decoration-bf="1" />
<field name="name" optional="show" />
<field
name="name"
optional="show"
decoration-info="reservation_type == 'staff'"
decoration-bf="reservation_type == 'out'"
/>
<field name="splitted" invisible="1" />
<field name="pricelist_id" invisible="1" />
<field name="rooms" />