[ADD] Cron no_show and no_checkout

This commit is contained in:
Darío Lodeiros
2020-11-26 12:19:35 +01:00
parent 95d2f9fc8f
commit c19b56a912
7 changed files with 170 additions and 123 deletions

View File

@@ -1,6 +1,38 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="0">
<!-- Set reservation like No Show if the client does not show up -->
<record model="ir.cron" id="noshow_reservations">
<field name="name">Automatic No Show Reservation</field>
<field name="interval_number">1</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False" />
<field name="state">code</field>
<field name="model_id" ref="model_pms_reservation" />
<field
name="nextcall"
eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 06:00:00')"
/>
<field name="code">model.auto_no_show()</field>
</record>
<!-- Set reservation like No Checout if checkout is not confirmed-->
<record model="ir.cron" id="nocheckout_reservations">
<field name="name">Automatic No Checkout Reservations</field>
<field name="interval_number">1</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False" />
<field name="state">code</field>
<field name="model_id" ref="model_pms_reservation" />
<field
name="nextcall"
eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 12:00:00')"
/>
<field name="code">model.auto_no_checkout()</field>
</record>
<!-- Scheduler For To Inform Guest About Reservation Before 24 Hours -->
<record model="ir.cron" id="autocheckout_reservations">
<field name="name">Automatic Checkout on past reservations</field>

View File

@@ -82,7 +82,7 @@ class PmsCheckinPartner(models.Model):
for record in self.filtered("reservation_id"):
record.folio_id = record.reservation_id.folio_id
@api.depends(lambda self: self._checkin_mandatory_fields(), "reservation_id.state")
@api.depends(lambda self: self._checkin_mandatory_fields(depends=True))
def _compute_state(self):
for record in self:
if not record.state:
@@ -98,7 +98,11 @@ class PmsCheckinPartner(models.Model):
else:
record.state = "precheckin"
def _checkin_mandatory_fields(self):
@api.model
def _checkin_mandatory_fields(self, depends=False):
# api.depends need "reservation_id.state" in de lambda function
if depends:
return ["reservation_id.state", "name"]
return ["name"]
# Constraints and onchanges
@@ -156,6 +160,22 @@ class PmsCheckinPartner(models.Model):
record.update(vals)
if record.reservation_id.state == "confirm":
record.reservation_id.state = "onboard"
if self._context.get("popup"):
self.ensure_one()
kanban_id = self.env.ref("pms.pms_checkin_partner_kanban_view").id
return {
"name": _("Register Checkins"),
"views": [[kanban_id, "tree"]],
"res_model": "pms.checkin.partner",
"type": "ir.actions.act_window",
"context": {
"create": False,
"edit": True,
"popup": True,
},
"domain": [("reservation_id", "=", self.reservation_id.id)],
"target": "new",
}
def action_done(self):
for record in self:

View File

@@ -245,7 +245,9 @@ class PmsFolio(models.Model):
)
# Checkin Fields-----------------------------------------------------
reservation_pending_arrival_ids = fields.One2many(
string="Pending Arrival Rooms", compute="_compute_reservations_pending_arrival"
comodel_name="pms.checkin.partner",
string="Pending Arrival Rooms",
compute="_compute_reservations_pending_arrival",
)
reservations_pending_count = fields.Integer(
compute="_compute_reservations_pending_arrival"

View File

@@ -2,7 +2,7 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from datetime import timedelta
from datetime import datetime, time, timedelta
from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
@@ -274,6 +274,8 @@ class PmsReservation(models.Model):
("onboard", "On Board"),
("done", "Out"),
("cancelled", "Cancelled"),
("no_show", "No Show"),
("no_checkout", "No Checkout"),
],
string="Status",
default=lambda *a: "draft",
@@ -653,12 +655,9 @@ class PmsReservation(models.Model):
if value not in (False, True):
raise UserError(_("Invalid domain right operand %s", value))
searching_for_true = (operator == "=" and value) or (
operator == "!=" and not value
)
today = fields.Date.context_today(self)
return [("checkin", searching_for_true, today)]
return [("checkin", operator, today)]
def _compute_departure_today(self):
for record in self:
@@ -1224,13 +1223,60 @@ class PmsReservation(models.Model):
def action_checks(self):
self.ensure_one()
action = self.env.ref("pms.open_pms_reservation_form_tree_all").read()[0]
action["views"] = [
(self.env.ref("pms.pms_reservation_checkin_view_form").id, "form")
]
action["res_id"] = self.id
action["target"] = "new"
return action
tree_id = self.env.ref("pms.pms_checkin_partner_reservation_view_tree").id
return {
"name": _("Register Partners"),
"views": [[tree_id, "tree"]],
"res_model": "pms.checkin.partner",
"type": "ir.actions.act_window",
"context": {
"create": False,
"edit": True,
"popup": True,
},
"domain": [("reservation_id", "=", self.id), ("state", "=", "draft")],
"target": "new",
}
def action_onboard(self):
self.ensure_one()
kanban_id = self.env.ref("pms.pms_checkin_partner_kanban_view").id
return {
"name": _("Register Checkins"),
"views": [[kanban_id, "kanban"]],
"res_model": "pms.checkin.partner",
"type": "ir.actions.act_window",
"context": {
"create": False,
"edit": True,
"popup": True,
},
"domain": [("reservation_id", "=", self.id), ("state", "=", "precheckin")],
"target": "new",
}
@api.model
def auto_no_show(self):
no_show_reservations = self.env["pms.reservation"].search(
[
("state", "in", ("draft", "confirm")),
("checkin", "<", fields.Date.today()),
]
)
no_show_reservations.state = "no_show"
@api.model
def auto_no_checkout(self):
reservations = self.env["pms.reservation"].search(
[("state", "in", ("onboard",))]
)
for reservation in reservations:
checkout_hour = int(reservation.departure_hour[0:2])
checkout_minut = int(reservation.departure_hour[3:5])
checkout_time = time(checkout_hour, checkout_minut, 00)
checkout_datetime = datetime.combine(reservation.checkout, checkout_time)
if checkout_datetime <= fields.Datetime.now():
reservation.state = "no_checkout"
def unify(self):
# TODO

View File

@@ -338,3 +338,48 @@ class TestPmsCheckinPartner(TestHotel):
int(2 * 100 / 3),
"Fail the checkins data ratio on reservation",
)
def test_auto_no_show(self):
# ARRANGE
self.arrange_folio_reservations()
PmsReservation = self.env["pms.reservation"]
# ACTION
freezer = freeze_time("2012-01-15 10:00:00")
freezer.start()
PmsReservation.auto_no_show()
no_show_reservations = PmsReservation.search([("state", "=", "no_show")])
# ASSERT
self.assertEqual(
len(no_show_reservations),
3,
"Reservations not set like No Show",
)
freezer.stop()
def test_auto_no_checkout(self):
# ARRANGE
self.arrange_single_checkin()
PmsReservation = self.env["pms.reservation"]
self.checkin1.action_on_board()
# ACTION
freezer = freeze_time("2012-01-17 12:00:00")
freezer.start()
PmsReservation.auto_no_checkout()
no_checkout_reservations = PmsReservation.search(
[("state", "=", "no_checkout")]
)
freezer.stop()
# ASSERT
self.assertEqual(
len(no_checkout_reservations),
1,
"Reservations not set like No checkout",
)

View File

@@ -49,7 +49,6 @@
<field name="arch" type="xml">
<tree
editable="bottom"
create="1"
decoration-danger="state == 'draft'"
decoration-info="state == 'done'"
decoration-muted="state == 'cancelled'"
@@ -61,7 +60,7 @@
icon="fa-2x fa-check-circle"
name="action_on_board"
help="Get in"
attrs="{'invisible': [('state','!=','preconfirm')]}"
attrs="{'invisible': [('state','!=','precheckin')]}"
/>
<field name="identifier" />
<field name="partner_id" required="True" />
@@ -71,7 +70,7 @@
<field name="departure" />
<field name="reservation_id" invisible="1" />
<field name="folio_id" force_save="1" invisible="1" />
<field name="state" invisible="1" />
<field name="state" invisible="0" />
</tree>
</field>
</record>
@@ -114,7 +113,12 @@
<field name="name">pms.checkin.partner.kanban</field>
<field name="model">pms.checkin.partner</field>
<field name="arch" type="xml">
<kanban default_group_by="state" class="o_res_partner_kanban" sample="1">
<kanban
default_group_by="state"
class="o_res_partner_kanban"
sample="1"
create="false"
>
<field name="id" />
<field name="identifier" />
<field name="partner_id" />

View File

@@ -120,7 +120,7 @@
<button
type="object"
class="oe_stat_button"
name="action_checks"
name="action_onboard"
attrs="{'invisible': [
('state', '!=', ('onboard')),
('arrival_today', '=', False),
@@ -556,108 +556,6 @@
</calendar>
</field>
</record>
<!-- Form view Checkin Partners from reservation -->
<record model="ir.ui.view" id="pms_reservation_checkin_view_form">
<field name="name">pms.reservation.checkin.form</field>
<field name="model">pms.reservation</field>
<field name="priority">100</field>
<field name="arch" type="xml">
<form string="Reservation">
<field name="reservation_type" invisible="1" />
<field name="splitted" invisible="1" />
<field name="state" invisible="1" />
<field name="overbooking" invisible="1" />
<field name="folio_id" invisible="1" />
<field name="adults" invisible="1" />
<field name="children" invisible="1" />
<div
class="alert alert-info"
role="alert"
style="margin-bottom:0px;"
attrs="{'invisible': ['|',('shared_folio','=',False),('splitted', '=', True)]}"
>
This reservation has other reservantions and/or services in the
folio, you can check it in the
<bold>
<button
class="alert-link"
type="object"
name="open_folio"
string="Folio Form"
/>
</bold>
</div>
<field name="shared_folio" invisible="1" />
<field name="allowed_room_ids" invisible="1" />
<sheet>
<span
class="label label-danger"
attrs="{'invisible': [('state', 'not in', ('cancelled'))]}"
>
Cancelled Reservation!
</span>
<span
class="label label-warning"
attrs="{'invisible': [('overbooking', '=', False)]}"
>
OverBooking!
</span>
<h2>
<field
name="preferred_room_id"
readonly="1"
nolabel="1"
options="{'no_create': True,'no_open': True}"
style="margin-right: 30px;"
/>
<!-- <field
name="partner_id"
readonly="1"
options="{'no_open': True}"
/>
<span
class="fa-user"
style="margin-left:20px;"
attrs="{'invisible': [('reservation_type','not in',('normal'))]}"
/>
<span
class="fa-black-tie"
style="margin-left:20px; color: #C67;"
attrs="{'invisible': [('reservation_type','not in',('staff'))]}"
/> -->
<h3>
From
<span class="fa-sign-in" style="margin: 5px;" />
<field
name="checkin"
style="margin-right: 10px;"
readonly="1"
/>
to
<span class="fa-sign-out" style="margin-right: 5px;" />
<field name="checkout" readonly="1" />
</h3>
</h2>
<group>
<field
name="segmentation_ids"
widget="many2many_tags"
placeholder="Segmentation..."
options="{'no_create': True,'no_open': True}"
/>
</group>
<field
name="checkin_partner_ids"
context="{
'default_reservation_id': id,
'reservation_id': id,
'tree_view_ref':'pms.pms_checkin_partner_reservation_view_tree',
}"
/>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="pms_reservation_view_tree">
<field name="name">pms.reservation.tree</field>
<field name="model">pms.reservation</field>
@@ -799,7 +697,7 @@
<filter
string="To enter"
name="to_enter"
domain="[('state', '=', 'confirm')]"
domain="[('arrival_today', '=', True),('state', 'in', ('draft','confirm'))]"
/>
<filter
string="Overbookings"