mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[WIP] Checkin status indicators
This commit is contained in:
@@ -31,10 +31,12 @@ class PmsCheckinPartner(models.Model):
|
|||||||
pms_property_id = fields.Many2one(
|
pms_property_id = fields.Many2one(
|
||||||
"pms.property", default=_get_default_pms_property, required=True
|
"pms.property", default=_get_default_pms_property, required=True
|
||||||
)
|
)
|
||||||
|
name = fields.Char("E-mail", related="partner_id.name")
|
||||||
email = fields.Char("E-mail", related="partner_id.email")
|
email = fields.Char("E-mail", related="partner_id.email")
|
||||||
mobile = fields.Char("Mobile", related="partner_id.mobile")
|
mobile = fields.Char("Mobile", related="partner_id.mobile")
|
||||||
arrival = fields.Datetime("Enter")
|
arrival = fields.Datetime("Enter")
|
||||||
departure = fields.Datetime("Exit")
|
departure = fields.Datetime("Exit")
|
||||||
|
completed_data = fields.Boolean(compute="_compute_completed_data", store=True)
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
selection=[
|
selection=[
|
||||||
("draft", "Pending arrival"),
|
("draft", "Pending arrival"),
|
||||||
@@ -54,6 +56,20 @@ class PmsCheckinPartner(models.Model):
|
|||||||
for record in self:
|
for record in self:
|
||||||
record.folio_id = record.reservation_id.folio_id
|
record.folio_id = record.reservation_id.folio_id
|
||||||
|
|
||||||
|
@api.depends(lambda self: self._checkin_mandatory_fields(), "state")
|
||||||
|
def _compute_completed_data(self):
|
||||||
|
self.completed_data = False
|
||||||
|
for record in self:
|
||||||
|
if any(
|
||||||
|
not getattr(self, field) for field in record._checkin_mandatory_fields()
|
||||||
|
):
|
||||||
|
record.completed_data = False
|
||||||
|
break
|
||||||
|
record.completed_data = True
|
||||||
|
|
||||||
|
def _checkin_mandatory_fields(self):
|
||||||
|
return ["name"]
|
||||||
|
|
||||||
# Constraints and onchanges
|
# Constraints and onchanges
|
||||||
|
|
||||||
@api.constrains("departure", "arrival")
|
@api.constrains("departure", "arrival")
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import logging
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, float_compare, float_is_zero
|
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, float_compare, float_is_zero
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
@@ -188,7 +188,7 @@ class PmsReservation(models.Model):
|
|||||||
# TODO: Warning Mens to update pricelist
|
# TODO: Warning Mens to update pricelist
|
||||||
checkin_partner_ids = fields.One2many("pms.checkin.partner", "reservation_id")
|
checkin_partner_ids = fields.One2many("pms.checkin.partner", "reservation_id")
|
||||||
count_pending_arrival = fields.Integer(
|
count_pending_arrival = fields.Integer(
|
||||||
"Reservation Description",
|
"Pending Arrival",
|
||||||
compute="_compute_count_pending_arrival",
|
compute="_compute_count_pending_arrival",
|
||||||
store=True,
|
store=True,
|
||||||
)
|
)
|
||||||
@@ -196,6 +196,21 @@ class PmsReservation(models.Model):
|
|||||||
string="Pending Arrival Ratio",
|
string="Pending Arrival Ratio",
|
||||||
compute="_compute_checkins_ratio",
|
compute="_compute_checkins_ratio",
|
||||||
)
|
)
|
||||||
|
pending_checkin_data = fields.Integer(
|
||||||
|
"Pending Checkin Data",
|
||||||
|
compute="_compute_pending_checkin_data",
|
||||||
|
store=True,
|
||||||
|
)
|
||||||
|
arrival_today = fields.Boolean(
|
||||||
|
compute="_compute_arrival_today", search="_search_arrival_today"
|
||||||
|
)
|
||||||
|
departure_today = fields.Boolean(
|
||||||
|
compute="_compute_departure_today", search="_search_departure_today"
|
||||||
|
)
|
||||||
|
ratio_checkin_data = fields.Integer(
|
||||||
|
string="Pending Checkin Data Ratio",
|
||||||
|
compute="_compute_ratio_checkin_data",
|
||||||
|
)
|
||||||
segmentation_ids = fields.Many2many(
|
segmentation_ids = fields.Many2many(
|
||||||
"res.partner.category",
|
"res.partner.category",
|
||||||
string="Segmentation",
|
string="Segmentation",
|
||||||
@@ -562,6 +577,66 @@ class PmsReservation(models.Model):
|
|||||||
/ reservation.adults
|
/ reservation.adults
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@api.depends("checkin_partner_ids", "checkin_partner_ids.completed_data")
|
||||||
|
def _compute_pending_checkin_data(self):
|
||||||
|
for reservation in self:
|
||||||
|
reservation.pending_checkin_data = reservation.adults - len(
|
||||||
|
reservation.checkin_partner_ids.filtered(
|
||||||
|
lambda c: c.state != "cancelled" and c.completed_data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends("pending_checkin_data")
|
||||||
|
def _compute_ratio_checkin_data(self):
|
||||||
|
self.ratio_checkin_data = 0
|
||||||
|
for reservation in self.filtered(lambda r: r.adults > 0):
|
||||||
|
reservation.ratio_checkin_data = (
|
||||||
|
(reservation.adults - reservation.pending_checkin_data)
|
||||||
|
* 100
|
||||||
|
/ reservation.adults
|
||||||
|
)
|
||||||
|
|
||||||
|
def _compute_arrival_today(self):
|
||||||
|
for record in self:
|
||||||
|
record.arrival_today = (
|
||||||
|
True if record.checkin == fields.Date.today() else False
|
||||||
|
)
|
||||||
|
# REVIEW: Late checkin?? (next day)
|
||||||
|
|
||||||
|
def _search_arrival_today(self, operator, value):
|
||||||
|
if operator not in ("=", "!="):
|
||||||
|
raise UserError(_("Invalid domain operator %s", operator))
|
||||||
|
|
||||||
|
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)]
|
||||||
|
|
||||||
|
def _compute_departure_today(self):
|
||||||
|
for record in self:
|
||||||
|
record.departure_today = (
|
||||||
|
True if record.checkout == fields.Date.today() else False
|
||||||
|
)
|
||||||
|
|
||||||
|
def _search_departure_today(self, operator, value):
|
||||||
|
if operator not in ("=", "!="):
|
||||||
|
raise UserError(_("Invalid domain operator %s", operator))
|
||||||
|
|
||||||
|
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 [("checkout", searching_for_true, today)]
|
||||||
|
|
||||||
# REVIEW: Dont run with set room_type_id -> room_id(compute)-> No set adults¿?
|
# REVIEW: Dont run with set room_type_id -> room_id(compute)-> No set adults¿?
|
||||||
@api.depends("preferred_room_id")
|
@api.depends("preferred_room_id")
|
||||||
def _compute_adults(self):
|
def _compute_adults(self):
|
||||||
|
|||||||
@@ -267,3 +267,36 @@ class TestPmsCheckinPartner(TestHotel):
|
|||||||
int(2 * 100 / 3),
|
int(2 * 100 / 3),
|
||||||
"Fail the checkins ratio on reservation",
|
"Fail the checkins ratio on reservation",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_complete_checkin_data(self):
|
||||||
|
|
||||||
|
# ARRANGE
|
||||||
|
self.arrange_folio_reservations()
|
||||||
|
|
||||||
|
# ACT
|
||||||
|
self.checkin1 = self.env["pms.checkin.partner"].create(
|
||||||
|
{
|
||||||
|
"partner_id": self.host1.id,
|
||||||
|
"reservation_id": self.reservation_1.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.checkin2 = self.env["pms.checkin.partner"].create(
|
||||||
|
{
|
||||||
|
"partner_id": self.host2.id,
|
||||||
|
"reservation_id": self.reservation_1.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
pending_checkin_data = self.reservation_1.pending_checkin_data
|
||||||
|
ratio_checkin_data = self.reservation_1.ratio_checkin_data
|
||||||
|
|
||||||
|
# ASSERT
|
||||||
|
self.assertEqual(
|
||||||
|
pending_checkin_data,
|
||||||
|
1,
|
||||||
|
"Fail the count pending checkin data on reservation",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ratio_checkin_data,
|
||||||
|
int(2 * 100 / 3),
|
||||||
|
"Fail the checkins data ratio on reservation",
|
||||||
|
)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<field name="splitted" invisible="True" />
|
<field name="splitted" invisible="True" />
|
||||||
<field name="tax_ids" invisible="1" />
|
<field name="tax_ids" invisible="1" />
|
||||||
|
<field name="arrival_today" invisible="1" />
|
||||||
<field name="checkin_partner_count" invisible="1" />
|
<field name="checkin_partner_count" invisible="1" />
|
||||||
<button
|
<button
|
||||||
name="confirm"
|
name="confirm"
|
||||||
@@ -96,18 +97,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
type="action"
|
|
||||||
class="oe_stat_button"
|
|
||||||
icon="fa-list-ul"
|
|
||||||
attrs="{'invisible': ['|', ('partner_id','=',False), ('reservation_type','in',('out'))]}"
|
|
||||||
name="%(open_pms_reservation_form_tree_all)d"
|
|
||||||
context="{'search_default_partner_id': partner_id}"
|
|
||||||
>
|
|
||||||
<div class="o_field_widget o_stat_info">
|
|
||||||
<span class="o_stat_text">Books</span>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="object"
|
type="object"
|
||||||
class="oe_stat_button"
|
class="oe_stat_button"
|
||||||
@@ -132,11 +121,33 @@
|
|||||||
type="object"
|
type="object"
|
||||||
class="oe_stat_button"
|
class="oe_stat_button"
|
||||||
name="action_checks"
|
name="action_checks"
|
||||||
attrs="{'invisible': [('state', 'in', ('cancelled','done'))]}"
|
attrs="{'invisible': [
|
||||||
|
('state', '!=', ('onboard')),
|
||||||
|
('arrival_today', '=', False),
|
||||||
|
'|',
|
||||||
|
('state', 'in', ('cancelled','done')),
|
||||||
|
]}"
|
||||||
>
|
>
|
||||||
<field
|
<field
|
||||||
name="checkins_ratio"
|
name="checkins_ratio"
|
||||||
string="Checkins"
|
string="On Board"
|
||||||
|
widget="percentpie"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="object"
|
||||||
|
class="oe_stat_button"
|
||||||
|
name="action_checks"
|
||||||
|
attrs="{'invisible': [
|
||||||
|
('state', 'not in', ('onboard','confirm')),
|
||||||
|
('arrival_today', '=', False),
|
||||||
|
'|',
|
||||||
|
('state', 'in', ('cancelled','done')),
|
||||||
|
]}"
|
||||||
|
>
|
||||||
|
<field
|
||||||
|
name="ratio_checkin_data"
|
||||||
|
string="Checkin Data"
|
||||||
widget="percentpie"
|
widget="percentpie"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user