diff --git a/pms/demo/pms_folio.xml b/pms/demo/pms_folio.xml
index be9214c38..a5b48079e 100644
--- a/pms/demo/pms_folio.xml
+++ b/pms/demo/pms_folio.xml
@@ -34,7 +34,7 @@
/>
-
+
-
+
normal
@@ -381,7 +381,7 @@
/>
-
+
normal
diff --git a/pms/i18n/es.po b/pms/i18n/es.po
index 0eca6fec0..7b22c075c 100644
--- a/pms/i18n/es.po
+++ b/pms/i18n/es.po
@@ -5700,12 +5700,12 @@ msgid "End Date"
msgstr "Fecha de finalización"
#. module: hotel
-#: model:ir.model.fields,field_description:hotel.field_hotel_checkin_partner_enter_date
+#: model:ir.model.fields,field_description:hotel.field_hotel_checkin_partner_arrival
msgid "Enter Date"
msgstr "Fecha de entrada"
#. module: hotel
-#: model:ir.model.fields,field_description:hotel.field_hotel_checkin_partner_exit_date
+#: model:ir.model.fields,field_description:hotel.field_hotel_checkin_partner_departure
msgid "Exit Date"
msgstr "Fecha salida"
@@ -6671,7 +6671,7 @@ msgstr "Mail"
#: model:ir.model.fields,help:hotel.field_hotel_room_type_property_valuation
msgid ""
"Manual: The accounting entries to value the inventory are not posted automatically.\n"
-" Automated: An accounting entry is automatically created to value the inventory when a product enters or leaves the company."
+" Automated: An accounting arrival is automatically created to value the inventory when a product enters or leaves the company."
msgstr ""
"Manual: Los registros contables de valoración del inventario no se publican automáticamente.\n"
" Automatizado: Se crea automáticamente un registro contable para evaluar el inventario cuando un producto entra o sale de la empresa."
@@ -7215,7 +7215,7 @@ msgstr "Pagos"
#. module: hotel
#: selection:hotel.checkin.partner,state:0 selection:hotel.reservation,state:0
-msgid "Pending Entry"
+msgid "Pending arrival"
msgstr "Por entrar"
#. module: hotel
diff --git a/pms/models/pms_checkin_partner.py b/pms/models/pms_checkin_partner.py
index 4acc25465..728319274 100644
--- a/pms/models/pms_checkin_partner.py
+++ b/pms/models/pms_checkin_partner.py
@@ -1,103 +1,44 @@
# Copyright 2017 Dario Lodeiros
# Copyright 2018 Alexandre Diaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-import datetime
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
-from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
class PmsCheckinPartner(models.Model):
_name = "pms.checkin.partner"
_description = "Partner Checkins"
- # Default Methods ang Gets
- def _default_reservation_id(self):
- if "reservation_id" in self.env.context:
- reservation = self.env["pms.reservation"].browse(
- [self.env.context["reservation_id"]]
- )
- return reservation
- return False
-
- def _default_partner_id(self):
- if "reservation_id" in self.env.context:
- reservation = self.env["pms.reservation"].browse(
- [self.env.context["reservation_id"]]
- )
- partner_ids = []
- if reservation.folio_id:
- for room in reservation.folio_id.reservation_ids:
- partner_ids.append(room.mapped("checkin_partner_ids.partner_id.id"))
- if "checkin_partner_ids" in self.env.context:
- for checkin in self.env.context["checkin_partner_ids"]:
- if checkin[0] == 0:
- partner_ids.append(checkin[2].get("partner_id"))
- if (
- self._context.get("include_customer")
- and reservation.partner_id.id not in partner_ids
- and not reservation.partner_id.is_company
- ):
- return reservation.partner_id
- return False
-
- def _default_folio_id(self):
- if "folio_id" in self.env.context:
- folio = self.env["pms.folio"].browse([self.env.context["folio_id"]])
- return folio
- if "reservation_id" in self.env.context:
- folio = (
- self.env["pms.reservation"]
- .browse([self.env.context["reservation_id"]])
- .folio_id
- )
- return folio
- return False
-
- def _default_enter_date(self):
- if "reservation_id" in self.env.context:
- reservation = self.env["pms.reservation"].browse(
- [self.env.context["reservation_id"]]
- )
- return reservation.checkin
- return False
-
- def _default_exit_date(self):
- if "reservation_id" in self.env.context:
- reservation = self.env["pms.reservation"].browse(
- [self.env.context["reservation_id"]]
- )
- return reservation.checkout
- return False
-
@api.model
def _get_default_pms_property(self):
+ # TODO: Change by property env variable (like company)
return self.env.user.pms_property_id
# Fields declaration
partner_id = fields.Many2one(
- "res.partner", default=_default_partner_id, required=True
+ "res.partner",
+ required=True,
+ domain="[('is_company', '=', False)]",
)
- reservation_id = fields.Many2one("pms.reservation", default=_default_reservation_id)
+ reservation_id = fields.Many2one("pms.reservation")
folio_id = fields.Many2one(
- "pms.folio", default=_default_folio_id, readonly=True, required=True
+ "pms.folio",
+ compute="_compute_folio_id",
+ store=True,
+ readonly=False,
)
pms_property_id = fields.Many2one(
"pms.property", default=_get_default_pms_property, required=True
)
email = fields.Char("E-mail", related="partner_id.email")
mobile = fields.Char("Mobile", related="partner_id.mobile")
- enter_date = fields.Date(default=_default_enter_date, required=True)
- exit_date = fields.Date(default=_default_exit_date, required=True)
- arrival_hour = fields.Char("Arrival Hour", help="Default Arrival Hour (HH:MM)")
- departure_hour = fields.Char(
- "Departure Hour", help="Default Departure Hour (HH:MM)"
- )
+ arrival = fields.Datetime("Enter")
+ departure = fields.Datetime("Exit")
auto_booking = fields.Boolean("Get in Now", default=False)
state = fields.Selection(
selection=[
- ("draft", "Pending Entry"),
+ ("draft", "Pending arrival"),
("onboard", "On Board"),
("done", "Out"),
("cancelled", "Cancelled"),
@@ -105,50 +46,36 @@ class PmsCheckinPartner(models.Model):
string="State",
readonly=True,
default=lambda *a: "draft",
- tracking=True,
)
+ # Compute
+
+ @api.depends("reservation_id", "reservation_id.folio_id")
+ def _compute_folio_id(self):
+ for record in self:
+ record.folio_id = record.reservation_id.folio_id
+
# Constraints and onchanges
- @api.constrains("exit_date", "enter_date")
- def _check_exit_date(self):
+ @api.constrains("departure", "arrival")
+ def _check_departure(self):
for record in self:
- date_in = fields.Date.from_string(record.enter_date)
- date_out = fields.Date.from_string(record.exit_date)
- if date_out < date_in:
- raise models.ValidationError(
+ if record.departure and record.arrival < record.departure:
+ raise ValidationError(
_("Departure date (%s) is prior to arrival on %s")
- % (date_out, date_in)
+ % (record.departure, record.arrival)
)
- @api.onchange("enter_date", "exit_date")
- def _onchange_enter_date(self):
- date_in = fields.Date.from_string(self.enter_date)
- date_out = fields.Date.from_string(self.exit_date)
- if date_out <= date_in:
- date_out = date_in + datetime.timedelta(days=1)
- self.update({"exit_date": date_out})
- raise ValidationError(
- _("Departure date, is prior to arrival. Check it now. %s") % date_out
- )
-
- @api.onchange("partner_id")
+ @api.constrains("partner_id")
def _check_partner_id(self):
for record in self:
if record.partner_id:
- if record.partner_id.is_company:
- raise models.ValidationError(
- _(
- "A Checkin Guest is configured like a company, \
- modify it in contact form if its a mistake"
- )
- )
indoor_partner_ids = record.reservation_id.checkin_partner_ids.filtered(
lambda r: r.id != record.id
).mapped("partner_id.id")
if indoor_partner_ids.count(record.partner_id.id) > 1:
record.partner_id = None
- raise models.ValidationError(
+ raise ValidationError(
_("This guest is already registered in the room")
)
@@ -157,18 +84,16 @@ class PmsCheckinPartner(models.Model):
def action_on_board(self):
for record in self:
if record.reservation_id.checkin > fields.Date.today():
- raise models.ValidationError(_("It is not yet checkin day!"))
- hour = record._get_arrival_hour()
+ raise ValidationError(_("It is not yet checkin day!"))
+ if record.reservation_id.checkout <= fields.Date.today():
+ raise ValidationError(_("Its too late to checkin"))
vals = {
"state": "onboard",
- "arrival_hour": hour,
+ "arrival": fields.Datetime.now(),
}
record.update(vals)
if record.reservation_id.state == "confirm":
record.reservation_id.state = "onboard"
- return {
- "type": "ir.actions.do_nothing",
- }
def action_done(self):
for record in self:
@@ -188,42 +113,3 @@ class PmsCheckinPartner(models.Model):
if vals.get("auto_booking", False):
record.action_on_board()
return record
-
- # Business methods
- def _get_arrival_hour(self):
- self.ensure_one()
- tz_property = self.env.user.pms_property_id.tz
- today = fields.Datetime.context_timestamp(
- self.with_context(tz=tz_property),
- datetime.datetime.strptime(fields.Date.today(), DEFAULT_SERVER_DATE_FORMAT),
- )
- default_arrival_hour = self.env.user.pms_property_id.default_arrival_hour
- if self.reservation_id.checkin < today.strftime(DEFAULT_SERVER_DATE_FORMAT):
- return default_arrival_hour
- now = fields.Datetime.context_timestamp(
- self.with_context(tz=tz_property),
- datetime.datetime.strptime(
- fields.Datetime.now(), DEFAULT_SERVER_DATETIME_FORMAT
- ),
- )
- arrival_hour = now.strftime("%H:%M")
- return arrival_hour
-
- def _get_departure_hour(self):
- self.ensure_one()
- tz_property = self.env.user.pms_property_id.tz
- today = fields.Datetime.context_timestamp(
- self.with_context(tz=tz_property),
- datetime.datetime.strptime(fields.Date.today(), DEFAULT_SERVER_DATE_FORMAT),
- )
- default_departure_hour = self.env.user.pms_property_id.default_departure_hour
- if self.reservation_id.checkout < today.strftime(DEFAULT_SERVER_DATE_FORMAT):
- return default_departure_hour
- now = fields.Datetime.context_timestamp(
- self.with_context(tz=tz_property),
- datetime.datetime.strptime(
- fields.Datetime.now(), DEFAULT_SERVER_DATETIME_FORMAT
- ),
- )
- departure_hour = now.strftime("%H:%M")
- return departure_hour
diff --git a/pms/models/pms_reservation.py b/pms/models/pms_reservation.py
index cedccf2bd..25c872f72 100644
--- a/pms/models/pms_reservation.py
+++ b/pms/models/pms_reservation.py
@@ -239,7 +239,7 @@ class PmsReservation(models.Model):
state = fields.Selection(
[
("draft", "Pre-reservation"),
- ("confirm", "Pending Entry"),
+ ("confirm", "Pending arrival"),
("onboard", "On Board"),
("done", "Out"),
("cancelled", "Cancelled"),
diff --git a/pms/tests/test_pms_checkin_partner.py b/pms/tests/test_pms_checkin_partner.py
index 68abc79a7..9049cd3ac 100644
--- a/pms/tests/test_pms_checkin_partner.py
+++ b/pms/tests/test_pms_checkin_partner.py
@@ -1,18 +1,21 @@
+import logging
+
from freezegun import freeze_time
+from odoo import fields
+from odoo.exceptions import ValidationError
+
from .common import TestHotel
+_logger = logging.getLogger(__name__)
+
@freeze_time("2012-01-14")
class TestPmsCheckinPartner(TestHotel):
@classmethod
- def setUpClass(cls):
- super(TestHotel, cls).setUpClass()
-
- def test_create_checkin_partner(self):
-
- # ARRANGE
- host1 = self.env["res.partner"].create(
+ def arrange_single_checkin(cls):
+ # Arrange for one checkin on one reservation
+ cls.host1 = cls.env["res.partner"].create(
{
"name": "Miguel",
"phone": "654667733",
@@ -22,27 +25,124 @@ class TestPmsCheckinPartner(TestHotel):
reservation_vals = {
"checkin": "2012-01-14",
"checkout": "2012-01-17",
- "room_type_id": self.env.ref("pms.pms_room_type_3").id,
- "partner_id": host1.id,
- "pms_property_id": self.env.ref("pms.main_pms_property").id,
+ "room_type_id": cls.env.ref("pms.pms_room_type_3").id,
+ "partner_id": cls.host1.id,
+ "pms_property_id": cls.env.ref("pms.main_pms_property").id,
}
- demo_user = self.env.ref("base.user_demo")
-
- # ACT
- reservation_1 = (
- self.env["pms.reservation"].with_user(demo_user).create(reservation_vals)
+ demo_user = cls.env.ref("base.user_demo")
+ cls.reservation_1 = (
+ cls.env["pms.reservation"].with_user(demo_user).create(reservation_vals)
)
- checkin1 = self.env["pms.checkin.partner"].create(
+ cls.checkin1 = cls.env["pms.checkin.partner"].create(
{
- "partner_id": host1.id,
- "reservation_id": reservation_1.id,
+ "partner_id": cls.host1.id,
+ "reservation_id": cls.reservation_1.id,
}
)
- checkin1.onboard()
+
+ def test_onboard_checkin(self):
+
+ # ARRANGE
+ self.arrange_single_checkin()
+
+ # ACT
+ self.checkin1.action_on_board()
# ASSERT
self.assertEqual(
- checkin1.state,
+ self.checkin1.state,
"onboard",
- "the checkin was not successful",
+ "the partner checkin was not successful",
)
+
+ def test_onboard_reservation(self):
+
+ # ARRANGE
+ self.arrange_single_checkin()
+
+ # ACT
+ self.checkin1.action_on_board()
+
+ # ASSERT
+ self.assertEqual(
+ self.reservation_1.state,
+ "onboard",
+ "the reservation checkin was not successful",
+ )
+
+ def test_premature_checkin(self):
+ # ARRANGE
+ self.arrange_single_checkin()
+ self.reservation_1.write(
+ {
+ "checkin": "2012-01-15",
+ }
+ )
+
+ # ACT & ASSERT
+ with self.assertRaises(ValidationError), self.cr.savepoint():
+ self.checkin1.action_on_board()
+
+ def test_late_checkin(self):
+ # ARRANGE
+ self.arrange_single_checkin()
+ self.reservation_1.write(
+ {
+ "checkin": "2012-01-13",
+ }
+ )
+
+ # ACT
+ self.checkin1.action_on_board()
+
+ # ASSERT
+ self.assertEqual(
+ self.checkin1.arrival,
+ fields.datetime.now(),
+ "the late checkin has problems",
+ )
+
+ def test_too_many_people_checkin(self):
+ # ARRANGE
+ self.arrange_single_checkin()
+ host2 = self.env["res.partner"].create(
+ {
+ "name": "Carlos",
+ "phone": "654667733",
+ "email": "carlos@example.com",
+ }
+ )
+ host3 = self.env["res.partner"].create(
+ {
+ "name": "Enmanuel",
+ "phone": "654667733",
+ "email": "enmanuel@example.com",
+ }
+ )
+ host4 = self.env["res.partner"].create(
+ {
+ "name": "Enrique",
+ "phone": "654667733",
+ "email": "enrique@example.com",
+ }
+ )
+ self.env["pms.checkin.partner"].create(
+ {
+ "partner_id": host2.id,
+ "reservation_id": self.reservation_1.id,
+ }
+ )
+ self.env["pms.checkin.partner"].create(
+ {
+ "partner_id": host3.id,
+ "reservation_id": self.reservation_1.id,
+ }
+ )
+ # ACT & ASSERT
+ with self.assertRaises(ValidationError), self.cr.savepoint():
+ self.env["pms.checkin.partner"].create(
+ {
+ "partner_id": host4.id,
+ "reservation_id": self.reservation_1.id,
+ }
+ )
diff --git a/pms/views/pms_checkin_partner_views.xml b/pms/views/pms_checkin_partner_views.xml
index f17d2deed..0f2392df3 100644
--- a/pms/views/pms_checkin_partner_views.xml
+++ b/pms/views/pms_checkin_partner_views.xml
@@ -27,10 +27,8 @@
domain="[('is_company','=', False)]"
/>
-
-
-
-
+
+
@@ -56,7 +54,7 @@
-
-
+
+
@@ -99,8 +97,8 @@
/>
-
-
+
+
@@ -129,21 +127,21 @@
@@ -167,33 +165,33 @@