From ccf4245aebc6f625b802635b9791e6d3fe1bf566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Lodeiros?= Date: Wed, 4 Nov 2020 08:57:09 +0100 Subject: [PATCH] [WIP]pms: change checkin name field arriva-departure --- pms/demo/pms_folio.xml | 6 +- pms/i18n/es.po | 8 +- pms/models/pms_checkin_partner.py | 174 ++++-------------------- pms/models/pms_reservation.py | 2 +- pms/tests/test_pms_checkin_partner.py | 142 ++++++++++++++++--- pms/views/pms_checkin_partner_views.xml | 34 +++-- 6 files changed, 175 insertions(+), 191 deletions(-) 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 @@