Merge branch '14.0' into 14.0-pms_checkin_flow

This commit is contained in:
Darío Lodeiros
2021-06-19 08:19:19 +02:00
committed by GitHub
30 changed files with 2202 additions and 1301 deletions

View File

@@ -4,7 +4,7 @@
{
"name": "PMS (Property Management System)",
"summary": "A property management system",
"version": "14.0.1.0.8",
"version": "14.0.1.0.10",
"development_status": "Alpha",
"category": "Generic Modules/Property Management System",
"website": "https://github.com/OCA/pms",

View File

@@ -72,8 +72,8 @@ msgstr "%s no encontrado en los checkins (%s)"
#. module: pms
#: code:addons/pms/models/pms_reservation_line.py:0
#, python-format
msgid "%s: No room available."
msgstr "%s: Habitación no disponible."
msgid "%s: No room available in %s <-> %s."
msgstr ""
#. module: pms
#: code:addons/pms/models/pms_reservation_line.py:0
@@ -6457,6 +6457,12 @@ msgstr "Línea de la Reserva"
msgid "Reservation availability plan"
msgstr "Plan de Disponibilidad de la Reserva"
#. module: pms
#: code:addons/pms/models/pms_reservation.py:0
#, python-format
msgid "Reservation dates should be consecutives"
msgstr ""
#. module: pms
#: model:ir.model.fields,help:pms.field_pms_service__reservation_id
msgid "Reservation in which the service is included"
@@ -7800,6 +7806,12 @@ msgstr "La capacidad de la habitación debe ser mayor que 0."
msgid "The checkin partners on a folio"
msgstr ""
#. module: pms
#: code:addons/pms/models/pms_reservation.py:0
#, python-format
msgid "The checkout date must be greater than the checkin date"
msgstr ""
#. module: pms
#: code:addons/pms/models/res_users.py:0
#, python-format
@@ -9042,6 +9054,9 @@ msgid ""
"you cannot have more than one room with the same name in the same property"
msgstr ""
#~ msgid "%s: No room available."
#~ msgstr "%s: Habitación no disponible."
#, fuzzy
#~ msgid "Technical field"
#~ msgstr "Computación técnica"

View File

@@ -60,7 +60,7 @@ msgstr ""
#. module: pms
#: code:addons/pms/models/pms_reservation_line.py:0
#, python-format
msgid "%s: No room available."
msgid "%s: No room available in %s <-> %s."
msgstr ""
#. module: pms
@@ -6129,6 +6129,12 @@ msgstr ""
msgid "Reservation availability plan"
msgstr ""
#. module: pms
#: code:addons/pms/models/pms_reservation.py:0
#, python-format
msgid "Reservation dates should be consecutives"
msgstr ""
#. module: pms
#: model:ir.model.fields,help:pms.field_pms_service__reservation_id
msgid "Reservation in which the service is included"
@@ -7419,6 +7425,12 @@ msgstr ""
msgid "The checkin partners on a folio"
msgstr ""
#. module: pms
#: code:addons/pms/models/pms_reservation.py:0
#, python-format
msgid "The checkout date must be greater than the checkin date"
msgstr ""
#. module: pms
#: code:addons/pms/models/res_users.py:0
#, python-format

View File

@@ -140,7 +140,6 @@ class PmsFolio(models.Model):
commission = fields.Float(
string="Commission",
readonly=True,
default=0,
store=True,
compute="_compute_commission",
)
@@ -642,7 +641,7 @@ class PmsFolio(models.Model):
or False
)
@api.depends("reservation_ids")
@api.depends("reservation_ids", "reservation_ids.commission_amount")
def _compute_commission(self):
for folio in self:
for reservation in folio.reservation_ids:

View File

@@ -109,6 +109,7 @@ class PmsReservation(models.Model):
readonly=False,
store=True,
related="folio_id.agency_id",
depends=["folio_id.agency_id"],
tracking=True,
)
channel_type_id = fields.Many2one(
@@ -376,16 +377,18 @@ class PmsReservation(models.Model):
checkin = fields.Date(
string="Check In",
help="It is the checkin date of the reservation, ",
required=True,
default=lambda self: self._get_default_checkin(),
compute="_compute_checkin",
readonly=False,
store=True,
copy=False,
tracking=True,
)
checkout = fields.Date(
string="Check Out",
help="It is the checkout date of the reservation, ",
required=True,
default=lambda self: self._get_default_checkout(),
compute="_compute_checkout",
readonly=False,
store=True,
copy=False,
tracking=True,
)
@@ -924,6 +927,53 @@ class PmsReservation(models.Model):
for reservation in self:
reservation.access_url = "/my/reservations/%s" % (reservation.id)
@api.depends("reservation_line_ids")
def _compute_checkin(self):
"""
Allows to calculate the checkin by default or when the create
specifically indicates the lines of the reservation
"""
for record in self:
if record.reservation_line_ids:
checkin_line_date = min(record.reservation_line_ids.mapped("date"))
# check if the checkin was created directly as reservation_line_id:
if checkin_line_date != record.checkin:
record.checkin = checkin_line_date
elif not record.checkin:
# default checkout other folio reservations or today
if len(record.folio_id.reservation_ids) > 1:
record.checkin = record.folio_id.reservation_ids[0].checkin
else:
record.checkin = fields.date.today()
@api.depends("reservation_line_ids", "checkin")
def _compute_checkout(self):
"""
Allows to calculate the checkout by default or when the create
specifically indicates the lines of the reservation
"""
for record in self:
if record.reservation_line_ids:
checkout_line_date = max(
record.reservation_line_ids.mapped("date")
) + datetime.timedelta(days=1)
# check if the checkout was created directly as reservation_line_id:
if checkout_line_date != record.checkout:
record.checkout = checkout_line_date
# default checkout if checkin is set
elif record.checkin and not record.checkout:
if len(record.folio_id.reservation_ids) > 1:
record.checkin = record.folio_id.reservation_ids[0].checkout
else:
record.checkout = record.checkin + datetime.timedelta(days=1)
elif not record.checkout:
record.checkout = False
# date checking
if record.checkin and record.checkout and record.checkin >= record.checkout:
raise UserError(
_("The checkout date must be greater than the checkin date")
)
@api.depends("pms_property_id", "folio_id")
def _compute_arrival_hour(self):
for record in self:
@@ -975,7 +1025,7 @@ class PmsReservation(models.Model):
for reservation in self:
if reservation.commission_percent > 0:
reservation.commission_amount = (
reservation.price_total * reservation.commission_percent
reservation.price_total * reservation.commission_percent / 100
)
else:
reservation.commission_amount = 0
@@ -1184,28 +1234,6 @@ class PmsReservation(models.Model):
recs = self.search([]).filtered(lambda x: x.checkin_partner_pending_count > 0)
return [("id", "in", [x.id for x in recs])] if recs else []
def _get_default_checkin(self):
folio = False
if "folio_id" in self._context:
folio = self.env["pms.folio"].search(
[("id", "=", self._context["folio_id"])]
)
if folio and folio.reservation_ids:
return folio.reservation_ids[0].checkin
else:
return fields.Date.today()
def _get_default_checkout(self):
folio = False
if "folio_id" in self._context:
folio = self.env["pms.folio"].search(
[("id", "=", self._context["folio_id"])]
)
if folio and folio.reservation_ids:
return folio.reservation_ids[0].checkout
else:
return fields.Date.today() + datetime.timedelta(1)
def _get_default_segmentation(self):
folio = False
segmentation_ids = False
@@ -1234,6 +1262,20 @@ class PmsReservation(models.Model):
)
)
@api.constrains("reservation_line_ids")
def check_consecutive_dates(self):
"""
simply convert date objects to integers using the .toordinal() method
of datetime objects. The difference between the maximum and minimum value
of the set of ordinal dates is one more than the length of the set
"""
for record in self:
if record.reservation_line_ids and len(record.reservation_line_ids) > 1:
dates = record.reservation_line_ids.mapped("date")
date_ints = {d.toordinal() for d in dates}
if not (max(date_ints) - min(date_ints) == len(date_ints) - 1):
raise ValidationError(_("Reservation dates should be consecutives"))
# @api.constrains("checkin_partner_ids", "adults")
# def _max_checkin_partner_ids(self):
# for record in self:

View File

@@ -210,8 +210,12 @@ class PmsReservationLine(models.Model):
# if the preferred room is NOT available
else:
raise ValidationError(
_("%s: No room available.")
% (reservation.preferred_room_id.name)
_("%s: No room available in %s <-> %s.")
% (
reservation.preferred_room_id.name,
line.reservation_id.checkin,
line.reservation_id.checkout,
)
)
# otherwise we assign the first of those

View File

@@ -21,7 +21,6 @@
##############################################################################
from . import test_pms_reservation
from . import test_pms_pricelist
from . import test_pms_pricelist_priority
from . import test_pms_checkin_partner
from . import test_pms_sale_channel
from . import test_pms_folio

View File

@@ -4,73 +4,34 @@ from freezegun import freeze_time
from odoo import fields
from odoo.exceptions import UserError
from odoo.tests import common
freeze_time("2000-02-02")
from .common import TestPms
class TestPmsFolio(common.SavepointCase):
def create_common_scenario(self):
# create a room type availability
self.room_type_availability = self.env["pms.availability.plan"].create(
{"name": "Availability plan for TEST"}
)
# sequences
self.folio_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Folio",
"code": "pms.folio",
"padding": 4,
"company_id": self.env.ref("base.main_company").id,
}
)
self.reservation_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Reservation",
"code": "pms.reservation",
"padding": 4,
"company_id": self.env.ref("base.main_company").id,
}
)
self.checkin_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Checkin",
"code": "pms.checkin.partner",
"padding": 4,
"company_id": self.env.ref("base.main_company").id,
}
)
# create a property
self.property = self.env["pms.property"].create(
{
"name": "MY PMS TEST",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"folio_sequence_id": self.folio_sequence.id,
"reservation_sequence_id": self.reservation_sequence.id,
"checkin_sequence_id": self.checkin_sequence.id,
}
)
class TestPmsFolio(TestPms):
# create room type class
self.room_type_class = self.env["pms.room.type.class"].create(
{"name": "Room", "default_code": "ROOM"}
)
# SetUp and Common Scenarios methods
def setUp(self):
"""
- common + room_type_double with 2 rooms (double1 and double2) in pms_property1
"""
super().setUp()
# create room type
self.room_type_double = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.property.id],
"pms_property_ids": [self.pms_property1.id],
"name": "Double Test",
"default_code": "DBL_Test",
"class_id": self.room_type_class.id,
"class_id": self.room_type_class1.id,
"price": 25,
}
)
# create room
self.room1 = self.env["pms.room"].create(
self.double1 = self.env["pms.room"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"name": "Double 101",
"room_type_id": self.room_type_double.id,
"capacity": 2,
@@ -78,9 +39,9 @@ class TestPmsFolio(common.SavepointCase):
)
# create room
self.room2 = self.env["pms.room"].create(
self.double2 = self.env["pms.room"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"name": "Double 102",
"room_type_id": self.room_type_double.id,
"capacity": 2,
@@ -88,233 +49,344 @@ class TestPmsFolio(common.SavepointCase):
)
def create_multiproperty_scenario(self):
self.create_common_scenario()
self.property1 = self.env["pms.property"].create(
{
"name": "Property_1",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"folio_sequence_id": self.folio_sequence.id,
"reservation_sequence_id": self.reservation_sequence.id,
"checkin_sequence_id": self.checkin_sequence.id,
}
)
self.property2 = self.env["pms.property"].create(
"""
Just 2 properties to majors
"""
self.pms_property2 = self.env["pms.property"].create(
{
"name": "Property_2",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"folio_sequence_id": self.folio_sequence.id,
"reservation_sequence_id": self.reservation_sequence.id,
"checkin_sequence_id": self.checkin_sequence.id,
}
)
self.property3 = self.env["pms.property"].create(
self.pms_property3 = self.env["pms.property"].create(
{
"name": "Property_3",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"folio_sequence_id": self.folio_sequence.id,
"reservation_sequence_id": self.reservation_sequence.id,
"checkin_sequence_id": self.checkin_sequence.id,
}
)
def test_commission_and_partner_correct(self):
# ARRANGE
self.create_common_scenario()
PmsFolio = self.env["pms.folio"]
PmsReservation = self.env["pms.reservation"]
def create_sale_channel_scenario(self):
"""
Method to simplified scenario on sale channel tests:
- create a sale_channel1 like indirect
- create a agency1 like sale_channel1 agency
"""
PmsPartner = self.env["res.partner"]
PmsSaleChannel = self.env["pms.sale.channel"]
# ACT
saleChannel = PmsSaleChannel.create(
self.sale_channel1 = PmsSaleChannel.create(
{"name": "saleChannel1", "channel_type": "indirect"}
)
agency = PmsPartner.create(
self.agency1 = PmsPartner.create(
{
"name": "partner1",
"is_agency": True,
"invoice_to_agency": True,
"default_commission": 15,
"sale_channel_id": saleChannel.id,
"sale_channel_id": self.sale_channel1.id,
}
)
folio = PmsFolio.create(
def create_configuration_accounting_scenario(self):
"""
Method to simplified scenario to payments and accounting:
# REVIEW:
- Use new property with odoo demo data company to avoid account configuration
- Emule SetUp with new property:
- create demo_room_type_double
- Create 2 rooms room_type_double
"""
self.pms_property_demo = self.env["pms.property"].create(
{
"agency_id": agency.id,
"pms_property_id": self.property.id,
"name": "Property Based on Comapany Demo",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
reservation = PmsReservation.create(
# create room type
self.demo_room_type_double = self.env["pms.room.type"].create(
{
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"agency_id": agency.id,
"folio_id": folio.id,
"pms_property_ids": [self.pms_property_demo.id],
"name": "Double Test",
"default_code": "Demo_DBL_Test",
"class_id": self.room_type_class1.id,
"price": 25,
}
)
commission = 0
for reservation in folio.reservation_ids:
commission += reservation.commission_amount
# ASSERT
self.assertEqual(
folio.commission,
commission,
"Folio commission don't math with his reservation commission",
)
if folio.agency_id:
self.assertEqual(
folio.agency_id, folio.partner_id, "Agency has to be the partner"
)
def test_compute_folio_priority(self):
self.create_common_scenario()
r1 = self.env["pms.reservation"].create(
# create rooms
self.double1 = self.env["pms.room"].create(
{
"checkin": fields.date.today(),
"checkout": fields.date.today() + datetime.timedelta(days=1),
"room_type_id": self.room_type_double.id,
"partner_id": self.env.ref("base.res_partner_12").id,
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property_demo.id,
"name": "Double 101",
"room_type_id": self.demo_room_type_double.id,
"capacity": 2,
}
)
self.double2 = self.env["pms.room"].create(
{
"pms_property_id": self.pms_property_demo.id,
"name": "Double 102",
"room_type_id": self.demo_room_type_double.id,
"capacity": 2,
}
)
# TestCases: Sale Channels
def test_default_agency_commission(self):
"""
Check the total commission of a folio with agency based on the
reservation night price and the preconfigured commission in the agency.
-------
Agency with 15% default commision, folio with one reservation
and 3 nights at 20$ by night (60$ total)
"""
# ARRANGE
self.create_sale_channel_scenario()
commission = (20 + 20 + 20) * 0.15
# ACT
folio1 = self.env["pms.folio"].create(
{
"agency_id": self.agency1.id,
"pms_property_id": self.pms_property1.id,
}
)
r1.allowed_checkin = False
self.env["pms.reservation"].create(
{
"folio_id": r1.folio_id.id,
"folio_id": folio1.id,
"room_type_id": self.room_type_double.id,
"reservation_line_ids": [
(
0,
False,
{
"date": fields.date.today(),
"price": 20,
},
),
(
0,
False,
{
"date": fields.date.today() + datetime.timedelta(days=1),
"price": 20,
},
),
(
0,
False,
{
"date": fields.date.today() + datetime.timedelta(days=2),
"price": 20,
},
),
],
}
)
# ASSERT
self.assertEqual(
commission, folio1.commission, "The folio compute commission is wrong"
)
def test_reservation_agency_without_partner(self):
"""
Check that a reservation / folio created with an agency
and without a partner will automatically take the partner.
-------
Create the folio1 and the reservation1, only set agency_id,
and the partner_id should be the agency itself.
"""
# ARRANGE
self.create_sale_channel_scenario()
# ACT
folio1 = self.env["pms.folio"].create(
{
"agency_id": self.agency1.id,
"pms_property_id": self.pms_property1.id,
}
)
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),
"room_type_id": self.room_type_double.id,
"partner_id": self.env.ref("base.res_partner_12").id,
"pms_property_id": self.property.id,
"folio_id": folio1.id,
}
)
# ASSERT
self.assertEqual(
r1.priority,
r1.folio_id.max_reservation_prior,
"The max. reservation priority on the whole folio is incorrect",
reservation1.agency_id, folio1.partner_id, "Agency has to be the partner"
)
# TestCases: Priority
def test_compute_folio_priority(self):
"""
Check the priority of a folio based on its reservations
#TODO: Commented test waiting to redefine the priority calculation
"""
# reservation1 = self.env["pms.reservation"].create(
# {
# "checkin": fields.date.today(),
# "checkout": fields.date.today() + datetime.timedelta(days=1),
# "room_type_id": self.room_type_double.id,
# "partner_id": self.env.ref("base.res_partner_12").id,
# "pms_property_id": self.property.id,
# }
# )
# reservation1.allowed_checkin = False
# self.env["pms.reservation"].create(
# {
# "folio_id": reservation1.folio_id.id,
# "checkin": fields.date.today(),
# "checkout": fields.date.today() + datetime.timedelta(days=1),
# "room_type_id": self.room_type_double.id,
# "partner_id": self.env.ref("base.res_partner_12").id,
# "pms_property_id": self.property.id,
# }
# )
# self.assertEqual(
# reservation1.priority,
# reservation1.folio_id.max_reservation_prior,
# "The max. reservation priority on the whole folio is incorrect",
# )
# TestCases: Payments
@freeze_time("2000-02-02")
def test_full_pay_folio(self):
# TEST CASE
# Folio is paid after execute
#
"""
After making the payment of a folio for the entire amount,
check that there is nothing pending.
-----
We create a reservation (autocalculates the amounts) and
then make the payment using the do_payment method of the folio,
directly indicating the pending amount on the folio of the newly
created reservation
"""
# ARRANGE
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
self.create_configuration_accounting_scenario()
reservation1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property_demo.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"adults": 2,
"partner_id": self.env.ref("base.res_partner_12").id,
"room_type_id": self.room_type_double.id,
"room_type_id": self.demo_room_type_double.id,
}
)
# ACTION
self.env["pms.folio"].do_payment(
self.env["account.journal"].browse(
r_test.folio_id.pms_property_id._get_payment_methods().ids[0]
journal=self.env["account.journal"].browse(
reservation1.folio_id.pms_property_id._get_payment_methods().ids[0]
),
self.env["account.journal"]
.browse(r_test.folio_id.pms_property_id._get_payment_methods().ids[0])
receivable_account=self.env["account.journal"]
.browse(reservation1.folio_id.pms_property_id._get_payment_methods().ids[0])
.suspense_account_id,
self.env.user,
r_test.folio_id.pending_amount,
r_test.folio_id,
partner=r_test.partner_id,
user=self.env.user,
amount=reservation1.folio_id.pending_amount,
folio=reservation1.folio_id,
partner=reservation1.partner_id,
date=fields.date.today(),
)
self.assertFalse(r_test.folio_id.pending_amount)
# ASSERT
self.assertFalse(
reservation1.folio_id.pending_amount,
"The pending amount of a folio paid in full has not been zero",
)
@freeze_time("2000-02-02")
def test_partial_pay_folio(self):
# TEST CASE
# Folio is partially paid after execute
#
"""
After making the payment of a folio for the partial amount,
We check that the pending amount is the one that corresponds to it.
-----
We create a reservation (autocalculates the amounts) and
then make the payment using the do_payment method of the folio,
directly indicating the pending amount on the folio MINUS 1$
of the newly created reservation
"""
# ARRANGE
self.create_configuration_accounting_scenario()
left_to_pay = 1
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
reservation1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property_demo.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"adults": 2,
"partner_id": self.env.ref("base.res_partner_12").id,
"room_type_id": self.room_type_double.id,
"room_type_id": self.demo_room_type_double.id,
}
)
# ACTION
self.env["pms.folio"].do_payment(
self.env["account.journal"].browse(
r_test.folio_id.pms_property_id._get_payment_methods().ids[0]
journal=self.env["account.journal"].browse(
reservation1.folio_id.pms_property_id._get_payment_methods().ids[0]
),
self.env["account.journal"]
.browse(r_test.folio_id.pms_property_id._get_payment_methods().ids[0])
receivable_account=self.env["account.journal"]
.browse(reservation1.folio_id.pms_property_id._get_payment_methods().ids[0])
.suspense_account_id,
self.env.user,
r_test.folio_id.pending_amount - left_to_pay,
r_test.folio_id,
partner=r_test.partner_id,
user=self.env.user,
amount=reservation1.folio_id.pending_amount - left_to_pay,
folio=reservation1.folio_id,
partner=reservation1.partner_id,
date=fields.date.today(),
)
self.assertEqual(r_test.folio_id.pending_amount, left_to_pay)
def test_closure_reason_property(self):
# ASSERT
self.assertEqual(
reservation1.folio_id.pending_amount,
left_to_pay,
"The pending amount on a partially paid folio it \
does not correspond to the amount that it should",
)
# TestCases: Property Consistencies
def test_folio_closure_reason_consistency_properties(self):
"""
Check the multioproperty consistencia between
clousure reasons and folios
-------
create multiproperty scenario (3 properties in total) and
a new clousure reason in pms_property1 and pms_property2, then, create
a new folio in property3 and try to set the clousure_reason
waiting a error property consistency.
"""
# ARRANGE
self.create_multiproperty_scenario()
cl_reason = self.env["room.closure.reason"].create(
{
"name": "closure_reason_test",
"pms_property_ids": [
(4, self.property1.id),
(4, self.property2.id),
(4, self.pms_property1.id),
(4, self.pms_property2.id),
],
}
)
with self.assertRaises(UserError):
# ACTION & ASSERT
with self.assertRaises(
UserError,
msg="Folio created with clousure_reason_id with properties inconsistence",
):
self.env["pms.folio"].create(
{
"pms_property_id": self.property3.id,
"pms_property_id": self.pms_property3.id,
"closure_reason_id": cl_reason.id,
}
)
def _test_compute_currency(self):
self.create_common_scenario()
self.currency1 = self.env["res.currency"].create(
{
"name": "currency1",
"symbol": "C",
}
)
self.pricelist = self.env["product.pricelist"].create(
{
"name": "pricelist 1",
"pms_property_ids": [
(4, self.property.id),
],
"currency_id": self.currency1.id,
}
)
self.reservation1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"partner_id": self.env.ref("base.res_partner_12").id,
"pricelist_id": self.pricelist.id,
}
)
self.assertEqual(
self.currency1.id,
self.reservation1.folio_id.currency_id.id,
"Currency must match",
)

View File

@@ -6,10 +6,7 @@ from odoo.tests import common
class TestPmsFolioInvoice(common.SavepointCase):
def setUp(self):
super(TestPmsFolioInvoice, self).setUp()
def create_common_scenario(self):
# create a room type availability
# sequences
# create a room type availability and sequences
self.folio_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Folio",
@@ -95,7 +92,6 @@ class TestPmsFolioInvoice(common.SavepointCase):
def test_invoice_full_folio(self):
# ARRANGE
self.create_common_scenario()
r1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
@@ -121,7 +117,6 @@ class TestPmsFolioInvoice(common.SavepointCase):
def test_invoice_partial_folio_by_steps(self):
# ARRANGE
self.create_common_scenario()
r1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
@@ -162,7 +157,6 @@ class TestPmsFolioInvoice(common.SavepointCase):
def test_invoice_partial_folio_diferent_partners(self):
# ARRANGE
self.create_common_scenario()
r1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
@@ -208,7 +202,6 @@ class TestPmsFolioInvoice(common.SavepointCase):
def test_invoice_partial_folio_wrong_qtys(self):
# ARRANGE
self.create_common_scenario()
r1 = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,

View File

@@ -1,43 +1,31 @@
import datetime
from odoo import fields
from .common import TestPms
class TestPmsFolioSaleLine(TestPms):
def create_common_scenario(self):
# create a room type availability
self.room_type_availability = self.env["pms.availability.plan"].create(
{"name": "Availability plan for TEST"}
)
# create a property
self.property = self.env["pms.property"].create(
{
"name": "MY PMS TEST",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
# create room type class
self.room_type_class = self.env["pms.room.type.class"].create(
{"name": "Room", "default_code": "ROOM"}
)
def setUp(self):
"""
- common + room_type_avalability_plan
"""
super().setUp()
# create room type
self.room_type_double = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.property.id],
"pms_property_ids": [self.pms_property1.id],
"name": "Double Test",
"default_code": "DBL_Test",
"class_id": self.room_type_class.id,
"class_id": self.room_type_class1.id,
"price": 25,
}
)
# create room
self.room1 = self.env["pms.room"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"name": "Double 101",
"room_type_id": self.room_type_double.id,
"capacity": 2,
@@ -46,21 +34,49 @@ class TestPmsFolioSaleLine(TestPms):
# RESERVATION LINES
def test_comp_fsl_rooms_all_same_group(self):
# TEST CASE
# 2-night reservation and same price, discount & cancel_discount for
# all nights
# should generate just 1 reservation sale line
"""
check the grouping of the reservation lines on the sale line folio
when the price, discount match-
------------
reservation with 3 nights with the same price,
should generate just 1 reservation sale line
"""
# ARRANGE
expected_sale_lines = 1
self.create_common_scenario()
# ACT
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"pms_property_id": self.pms_property1.id,
"reservation_line_ids": [
(
0,
False,
{
"date": fields.date.today(),
"price": 20,
"discount": 10,
},
),
(
0,
False,
{
"date": fields.date.today() + datetime.timedelta(days=1),
"price": 20,
"discount": 10,
},
),
(
0,
False,
{
"date": fields.date.today() + datetime.timedelta(days=2),
"price": 20,
"discount": 10,
},
),
],
"adults": 2,
"room_type_id": self.room_type_double.id,
"partner_id": self.env.ref("base.res_partner_12").id,
@@ -81,10 +97,9 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_sale_lines = 2
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -112,10 +127,9 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_sale_lines = 2
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -143,10 +157,9 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_sale_lines = 2
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -175,10 +188,9 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_sale_lines = 1
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -207,10 +219,9 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same reservation sales line record.
# ARRANGE
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -242,10 +253,9 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same reservation sales line record.
# ARRANGE
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -278,10 +288,9 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same reservation sales line record.
# ARRANGE
self.create_common_scenario()
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -315,7 +324,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_board_service_sale_lines = 1
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -345,7 +353,7 @@ class TestPmsFolioSaleLine(TestPms):
# ACT
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -375,7 +383,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_board_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -404,7 +411,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -435,7 +442,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_board_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -464,7 +470,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -498,7 +504,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_board_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -527,7 +532,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -561,7 +566,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_board_service_sale_lines = 1
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -590,7 +594,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -623,7 +627,6 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same board service sales line record.
# ARRANGE
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -651,7 +654,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -684,7 +687,6 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same board service sales line record.
# ARRANGE
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -716,7 +718,7 @@ class TestPmsFolioSaleLine(TestPms):
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -751,7 +753,6 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same board service sales line record.
# ARRANGE
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -783,7 +784,7 @@ class TestPmsFolioSaleLine(TestPms):
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -821,7 +822,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_extra_service_sale_lines = 1
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -832,7 +832,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -871,7 +871,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_extra_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -882,7 +881,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -923,7 +922,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_extra_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -934,7 +932,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -976,7 +974,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_extra_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -987,7 +984,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -1030,7 +1027,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_extra_service_sale_lines = 1
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -1041,7 +1037,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -1082,7 +1078,6 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same reservation service sales line record.
# ARRANGE
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -1093,7 +1088,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -1134,7 +1129,6 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same reservation service sales line record.
# ARRANGE
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -1145,7 +1139,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -1187,7 +1181,6 @@ class TestPmsFolioSaleLine(TestPms):
# Should keep the same reservation service sales line record.
# ARRANGE
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -1198,7 +1191,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -1220,7 +1213,7 @@ class TestPmsFolioSaleLine(TestPms):
# ACT
r_test.service_ids.filtered(
lambda x: x.id == extra_service
lambda x: x.id == extra_service.id
).service_line_ids.price_unit = 50
r_test.service_ids.service_line_ids.flush()
@@ -1242,7 +1235,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_folio_service_sale_lines = 1
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -1250,7 +1242,7 @@ class TestPmsFolioSaleLine(TestPms):
)
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,
@@ -1289,7 +1281,6 @@ class TestPmsFolioSaleLine(TestPms):
# ARRANGE
expected_folio_service_sale_lines = 2
self.create_common_scenario()
product_test1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -1303,7 +1294,7 @@ class TestPmsFolioSaleLine(TestPms):
r_test = self.env["pms.reservation"].create(
{
"pms_property_id": self.property.id,
"pms_property_id": self.pms_property1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
"adults": 2,

File diff suppressed because it is too large Load Diff

View File

@@ -1,541 +0,0 @@
import datetime
from freezegun import freeze_time
from odoo.tests import common
class TestPmsPricelistRules(common.SavepointCase):
def create_common_scenario(self):
self.product_template = self.env["product.template"].create(
{"name": "Template1"}
)
self.product_category = self.env["product.category"].create(
{"name": "Category1"}
)
self.availability_plan1 = self.env["pms.availability.plan"].create(
{"name": "Availability 1"}
)
self.availability_plan2 = self.env["pms.availability.plan"].create(
{"name": "Availability"}
)
# sequences
self.folio_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Folio",
"code": "pms.folio",
"padding": 4,
"company_id": self.env.ref("base.main_company").id,
}
)
self.reservation_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Reservation",
"code": "pms.reservation",
"padding": 4,
"company_id": self.env.ref("base.main_company").id,
}
)
self.checkin_sequence = self.env["ir.sequence"].create(
{
"name": "PMS Checkin",
"code": "pms.checkin.partner",
"padding": 4,
"company_id": self.env.ref("base.main_company").id,
}
)
self.property1 = self.env["pms.property"].create(
{
"name": "Property_1",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"folio_sequence_id": self.folio_sequence.id,
"reservation_sequence_id": self.reservation_sequence.id,
"checkin_sequence_id": self.checkin_sequence.id,
}
)
self.property2 = self.env["pms.property"].create(
{
"name": "Property_2",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"folio_sequence_id": self.folio_sequence.id,
"reservation_sequence_id": self.reservation_sequence.id,
"checkin_sequence_id": self.checkin_sequence.id,
}
)
self.room_type_class = self.env["pms.room.type.class"].create(
{"name": "Room Class", "default_code": "ROOM"}
)
self.room_type = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.property1.id, self.property2.id],
"name": "Single",
"default_code": "SIN",
"class_id": self.room_type_class.id,
"list_price": 30,
}
)
self.room = self.env["pms.room"].create(
{
"pms_property_id": self.property1.id,
"name": "Single 101",
"room_type_id": self.room_type.id,
}
)
self.room2 = self.env["pms.room"].create(
{
"pms_property_id": self.property2.id,
"name": "Single 102",
"room_type_id": self.room_type.id,
}
)
self.pricelist = self.env["product.pricelist"].create(
{
"name": "pricelist_1",
}
)
self.partner1 = self.env["res.partner"].create({"name": "Carles"})
@freeze_time("2000-01-01")
def test_simple_price_without_items(self):
# TEST CASE : no items applied
# ARRANGE
self.create_common_scenario()
reservation = self.env["pms.reservation"].create(
{
"checkin": datetime.datetime.today(),
"checkout": datetime.datetime.today() + datetime.timedelta(days=3),
"preferred_room_id": self.room.id,
"pms_property_id": self.property1.id,
"partner_id": self.partner1.id,
}
)
# ACT
n_days = (reservation.checkout - reservation.checkin).days
expected_price = self.room.room_type_id.list_price * n_days
# ASSERT
self.assertEqual(
expected_price, reservation.price_subtotal, "The price is not as expected"
)
@freeze_time("2022-01-01")
def test_items_sort(self):
# ARRANGE
self.create_common_scenario()
# - test cases to verify the order for each field considered individually
# - test cases to prioritize fields over other fields:
# 1. applied_on
# 2. date
# 3. date consumption
# 4. num. properties
# 5. id
# - tie
# - no [date_start|date_end|date_start_consumption|date_end_consumption]
properties = self.room_type.product_id.pms_property_ids.ids
test_cases = [
{
"name": "sorting applied_on",
"expected_price": 50 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "2_product_category",
"categ_id": self.product_category.id,
"fixed_price": 60.0,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": 50.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "1_product",
"product_id": self.room_type.product_id.id,
"product_tmpl_id": self.product_template.id,
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "sorting SALE date min range",
"expected_price": 50.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=2),
"fixed_price": 60.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=1),
"fixed_price": 50.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=3),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "sorting CONSUMPTION date min range",
"expected_price": 40.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=6),
"fixed_price": 60.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=10),
"fixed_price": 50.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "sorting num. properties",
"expected_price": 50.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": 60.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"pms_property_ids": [self.property1.id],
"fixed_price": 50.0,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"pms_property_ids": [self.property1.id, self.property2.id],
"fixed_price": 40.0,
},
],
},
{
"name": "sorting by item id",
"expected_price": 40.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": 60.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": 50.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "prioritize applied_on over SALE date",
"expected_price": 60.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=2),
"fixed_price": 60.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"product_id": self.room_type.product_id.id,
"product_tmpl_id": self.product_template.id,
"applied_on": "1_product",
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=1),
"fixed_price": 50.0,
"pms_property_ids": properties,
},
],
},
{
"name": "prioritize SALE date over CONSUMPTION date",
"expected_price": 120.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=10),
"fixed_price": 120.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"fixed_price": 50.0,
"pms_property_ids": properties,
},
],
},
{
"name": "prioritize CONSUMPTION date over min. num. properties",
"expected_price": 50.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"fixed_price": 120.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"pms_property_ids": [self.property1.id, self.property2.id],
"fixed_price": 50.0,
},
],
},
{
"name": "prioritize min. num. properties over item id",
"expected_price": 50.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"fixed_price": 120.0,
"pms_property_ids": properties,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"pms_property_ids": [self.property1.id, self.property2.id],
"fixed_price": 50.0,
},
],
},
{
"name": "tie => order by item id",
"expected_price": 50.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=3),
"pms_property_ids": [self.property1.id, self.property2.id],
"fixed_price": 120.0,
},
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now()
+ datetime.timedelta(days=3),
"date_start": datetime.datetime.now(),
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=3),
"pms_property_ids": [self.property1.id, self.property2.id],
"fixed_price": 50.0,
},
],
},
{
"name": "no SALE DATE START",
"expected_price": 40.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_end": datetime.datetime.now()
+ datetime.timedelta(days=1),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "no SALE DATE END",
"expected_price": 40.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.now(),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "no consumption DATE START",
"expected_price": 40.0 + self.room_type.list_price * 2,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_end_consumption": datetime.datetime.now(),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "no consumption DATE END",
"expected_price": 40.0 * 3,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
{
"name": "only applied consumption in one night",
"expected_price": 40.0 + self.room_type.list_price * 2,
"items": [
{
"pricelist_id": self.pricelist.id,
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start_consumption": datetime.datetime.now(),
"date_end_consumption": datetime.datetime.now(),
"fixed_price": 40.0,
"pms_property_ids": properties,
},
],
},
]
for tc in test_cases:
with self.subTest(k=tc):
# ARRANGE
items = []
for item in tc["items"]:
item = self.env["product.pricelist.item"].create(item)
items.append(item.id)
# ACT
reservation = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now()
+ datetime.timedelta(days=3),
"preferred_room_id": self.room.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
}
)
reservation_price = reservation.price_subtotal
self.env["pms.reservation"].browse(reservation.id).unlink()
self.env["product.pricelist.item"].browse(items).unlink()
# ASSERT
self.assertEqual(tc["expected_price"], reservation_price, tc["name"])

View File

@@ -0,0 +1,55 @@
from odoo.exceptions import ValidationError
from .common import TestPms
class TestPmsPricelistSettings(TestPms):
def test_advanced_pricelist_exists(self):
"""
Check if value of Pricelist parameter in sales settings is Advanced Price Rules.
Find the value of Pricelist parameter
with the key product.product_pricelist_setting and check if is equal to "advanced".
"""
# ARRANGE
key = "product.product_pricelist_setting"
value = "advanced"
# ACT
found_value = self.env["ir.config_parameter"].sudo().get_param(key)
# ASSERT
self.assertEqual(
found_value, value, "Parameter of Pricelist in setting is not 'advanced'"
)
def test_product_pricelist_setting_not_modified(self):
"""
Check that Pricelist parameter 'advanced' cannot be modified.
Set the value of product.product_pricelist_setting to 'basic'
but is not possible because this only can be 'advanced'.
"""
# ARRANGE
key = "product.product_pricelist_setting"
value = "basic"
# ACT & ASSERT
with self.assertRaises(
ValidationError, msg="The Pricelist parameter 'advanced' was modified."
):
self.env["ir.config_parameter"].set_param(key, value)
def test_product_pricelist_setting_not_unlink(self):
"""
Check that Pricelist parameter 'advanced' cannot be unlink.
Try to unlink the parameter product_pricelist with value 'advanced'
but this should be impossible.
"""
# ARRANGE
key = "product.product_pricelist_setting"
value = "advanced"
# ACT & ASSERT
with self.assertRaises(ValidationError), self.cr.savepoint():
self.env["ir.config_parameter"].search(
[("key", "=", key), ("value", "=", value)]
).unlink()

View File

@@ -153,6 +153,84 @@ class TestPmsReservations(common.SavepointCase):
}
)
@freeze_time("1980-11-01")
def test_reservation_dates_not_consecutive(self):
"""
Check the constrain if not consecutive dates
----------------
Create correct reservation set 3 reservation lines consecutives (nights)
"""
# ARRANGE
self.create_common_scenario()
customer = self.env.ref("base.res_partner_12")
today = fields.date.today()
tomorrow = fields.date.today() + datetime.timedelta(days=1)
three_days_later = fields.date.today() + datetime.timedelta(days=3)
# ACT & ASSERT
with self.assertRaises(
ValidationError,
msg="Error, it has been allowed to create a reservation with non-consecutive days",
):
self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"partner_id": customer.id,
"pms_property_id": self.property.id,
"reservation_line_ids": [
(0, False, {"date": today}),
(0, False, {"date": tomorrow}),
(0, False, {"date": three_days_later}),
],
}
)
@freeze_time("1980-11-01")
def test_reservation_dates_compute_checkin_out(self):
"""
Check the reservation creation with specific reservation lines
anc compute checkin checkout
----------------
Create reservation with correct reservation lines and check
the checkin and checkout fields. Take into account that the
checkout of the reservation must be the day after the last night
(view checkout assertEqual)
"""
# ARRANGE
self.create_common_scenario()
customer = self.env.ref("base.res_partner_12")
today = fields.date.today()
tomorrow = fields.date.today() + datetime.timedelta(days=1)
two_days_later = fields.date.today() + datetime.timedelta(days=2)
# ACT
reservation = self.env["pms.reservation"].create(
{
"room_type_id": self.room_type_double.id,
"partner_id": customer.id,
"pms_property_id": self.property.id,
"reservation_line_ids": [
(0, False, {"date": today}),
(0, False, {"date": tomorrow}),
(0, False, {"date": two_days_later}),
],
}
)
# ASSERT
self.assertEqual(
reservation.checkin,
today,
"The calculated checkin of the reservation does \
not correspond to the first day indicated in the dates",
)
self.assertEqual(
reservation.checkout,
two_days_later + datetime.timedelta(days=1),
"The calculated checkout of the reservation does \
not correspond to the last day indicated in the dates",
)
@freeze_time("1980-11-01")
def test_create_reservation_start_date(self):
# TEST CASE

View File

@@ -1,12 +0,0 @@
from odoo.tests.common import SavepointCase
class TestPmsFolioInvoice(SavepointCase):
def setUp(self):
super(TestPmsFolioInvoice, self).setUp()
def test_price_reservation(self):
"""Test create a reservation, and check price and discounts"""
def test_general_discount_reservation(self):
"""Test a discount in reservation head, and check lines"""