mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[IMP] pms-api-rest: add planning calendar headers service
This commit is contained in:
committed by
Darío Lodeiros
parent
8eb92c0635
commit
16b172592d
@@ -30,6 +30,14 @@ class PmsCalendarSearchParam(Datamodel):
|
||||
pricelistId = fields.Integer(required=False, allow_none=True)
|
||||
|
||||
|
||||
class PmsCalendarHeaderSearchParam(Datamodel):
|
||||
_name = "pms.calendar.header.search.param"
|
||||
dateFrom = fields.String(required=False, allow_none=True)
|
||||
dateTo = fields.String(required=False, allow_none=True)
|
||||
pmsPropertyId = fields.Integer(required=True, allow_none=False)
|
||||
roomIds = fields.List(fields.Integer(), required=False)
|
||||
|
||||
|
||||
class PmsCalendarFreeDailyRoomsByType(Datamodel):
|
||||
_name = "pms.calendar.free.daily.rooms.by.type"
|
||||
date = fields.String(required=True, allow_none=False)
|
||||
@@ -43,6 +51,14 @@ class PmsCalendarDailyInvoicing(Datamodel):
|
||||
invoicingTotal = fields.Float(required=True, allow_none=False)
|
||||
|
||||
|
||||
class PmsCalendarHeaderInfo(Datamodel):
|
||||
_name = "pms.calendar.header.info"
|
||||
date = fields.String(required=True, allow_none=False)
|
||||
dailyBilling = fields.Float(required=True, allow_none=False)
|
||||
freeRooms = fields.Integer(required=True, allow_none=False)
|
||||
occupancyRate = fields.Float(required=True, allow_none=False)
|
||||
overbooking = fields.Boolean(required=False, allow_none=True)
|
||||
|
||||
class PmsCalendarInfo(Datamodel):
|
||||
_name = "pms.calendar.info"
|
||||
id = fields.Integer(required=False, allow_none=True)
|
||||
|
||||
@@ -5,6 +5,54 @@ from odoo.addons.base_rest_datamodel.restapi import Datamodel
|
||||
from odoo.addons.component.core import Component
|
||||
|
||||
|
||||
def build_reservation_line_info( calendar_item, previous_item=False, next_item=False):
|
||||
next_itemSplitted = (
|
||||
calendar_item["splitted"]
|
||||
and next_item
|
||||
and calendar_item["date"] < calendar_item["checkout"] - timedelta(days=1)
|
||||
and (
|
||||
next_item["room_id"] != calendar_item["room_id"]
|
||||
or next_item["reservation_id"] != calendar_item["reservation_id"]
|
||||
)
|
||||
)
|
||||
previous_itemSplitted = (
|
||||
calendar_item["splitted"]
|
||||
and previous_item
|
||||
and calendar_item["date"] > calendar_item["checkin"]
|
||||
and (
|
||||
previous_item["room_id"] != calendar_item["room_id"]
|
||||
or previous_item["reservation_id"] != calendar_item["reservation_id"]
|
||||
)
|
||||
)
|
||||
return {
|
||||
"date": datetime.combine(calendar_item['date'], datetime.min.time()).isoformat(),
|
||||
"roomId": calendar_item['room_id'],
|
||||
"roomTypeId": calendar_item['room_type_id'],
|
||||
"id": calendar_item['id'],
|
||||
"state": calendar_item['state'],
|
||||
"priceDayTotal": calendar_item['price_day_total'],
|
||||
"toAssign": calendar_item['to_assign'],
|
||||
"splitted": calendar_item['splitted'],
|
||||
"partnerId": calendar_item['partner_id'],
|
||||
"partnerName": calendar_item['partner_name'],
|
||||
"folioId": calendar_item['folio_id'],
|
||||
"reservationId": calendar_item['reservation_id'],
|
||||
"reservationName": calendar_item['reservation_name'],
|
||||
"reservationType": calendar_item['reservation_type'],
|
||||
"checkin": datetime.combine(calendar_item['checkin'], datetime.min.time()).isoformat(),
|
||||
"checkout": datetime.combine(calendar_item['checkout'], datetime.min.time()).isoformat(),
|
||||
"priceTotal": calendar_item['price_total'],
|
||||
"adults": calendar_item['adults'],
|
||||
"pendingPayment": calendar_item['folio_pending_amount'],
|
||||
"closureReasonId": calendar_item['closure_reason_id'],
|
||||
"isFirstNight": calendar_item['date'] == calendar_item['checkin'] if calendar_item['checkin'] else None,
|
||||
"isLastNight": calendar_item['date'] == calendar_item['checkout'] + timedelta(days=-1)
|
||||
if calendar_item['checkout'] else None,
|
||||
"nextLineSplitted": next_itemSplitted,
|
||||
"previousLineSplitted": previous_itemSplitted,
|
||||
}
|
||||
|
||||
|
||||
class PmsCalendarService(Component):
|
||||
_inherit = "base.rest.service"
|
||||
_name = "pms.private.service"
|
||||
@@ -153,7 +201,7 @@ class PmsCalendarService(Component):
|
||||
[
|
||||
(
|
||||
[
|
||||
"/temp-calendar",
|
||||
"/",
|
||||
],
|
||||
"GET",
|
||||
)
|
||||
@@ -213,7 +261,7 @@ class PmsCalendarService(Component):
|
||||
LEFT OUTER JOIN ( SELECT id, state, price_day_total, room_id, date, reservation_id
|
||||
FROM pms_reservation_line
|
||||
WHERE pms_property_id = %s AND state != 'cancel'
|
||||
AND occupies_availability = true AND date < %s
|
||||
AND occupies_availability = true AND date <= %s
|
||||
) l ON l.room_id = dr.room_id AND l.date = dr.date
|
||||
LEFT OUTER JOIN pms_reservation r ON l.reservation_id = r.id
|
||||
LEFT OUTER JOIN pms_folio f ON r.folio_id = f.id
|
||||
@@ -259,7 +307,7 @@ class PmsCalendarService(Component):
|
||||
)
|
||||
if item['reservation_id'] is not None and item['reservation_id'] != last_reservation_id:
|
||||
response[-1].dates[-1]['reservationLines'].append(
|
||||
self.build_reservation_line_info(
|
||||
build_reservation_line_info(
|
||||
item,
|
||||
previous_item=False
|
||||
if (not item["splitted"] or item["date"] == date_from)
|
||||
@@ -273,7 +321,7 @@ class PmsCalendarService(Component):
|
||||
index_date_last_reservation = len(response[-1].dates) - 1
|
||||
elif item['reservation_id'] is not None and item['reservation_id'] == last_reservation_id:
|
||||
response[-1].dates[index_date_last_reservation]['reservationLines'].append(
|
||||
self.build_reservation_line_info(
|
||||
build_reservation_line_info(
|
||||
item,
|
||||
previous_item=False
|
||||
if (not item["splitted"] or item["date"] == date_from)
|
||||
@@ -288,52 +336,100 @@ class PmsCalendarService(Component):
|
||||
last_reservation_id = False
|
||||
return response
|
||||
|
||||
def build_reservation_line_info(self, calendar_item, previous_item=False, next_item=False):
|
||||
next_itemSplitted = (
|
||||
calendar_item["splitted"]
|
||||
and next_item
|
||||
and calendar_item["date"] < calendar_item["checkout"] - timedelta(days=1)
|
||||
and (
|
||||
next_item["room_id"] != calendar_item["room_id"]
|
||||
or next_item["reservation_id"] != calendar_item["reservation_id"]
|
||||
|
||||
@restapi.method(
|
||||
[
|
||||
(
|
||||
[
|
||||
"/calendar-headers",
|
||||
],
|
||||
"GET",
|
||||
)
|
||||
],
|
||||
input_param=Datamodel("pms.calendar.header.search.param"),
|
||||
output_param=Datamodel("pms.calendar.header.info", is_list=True),
|
||||
auth="jwt_api_pms",
|
||||
)
|
||||
def get_calendar_headers(self, calendar_search_param):
|
||||
response = []
|
||||
date_from = datetime.strptime(calendar_search_param.dateFrom, "%Y-%m-%d").date()
|
||||
date_to = datetime.strptime(calendar_search_param.dateTo, "%Y-%m-%d").date()
|
||||
|
||||
room_ids = tuple(calendar_search_param.roomIds)
|
||||
|
||||
self.env.cr.execute(
|
||||
f"""
|
||||
SELECT d.date,
|
||||
bool_or(l.overbooking) overbooking,
|
||||
SUM(l.price_day_total) daily_billing,
|
||||
tr.num_total_rooms
|
||||
-
|
||||
(
|
||||
SELECT COUNT(1)
|
||||
FROM pms_reservation_line
|
||||
WHERE date = d.date
|
||||
AND pms_property_id = %s
|
||||
AND state != 'cancel'
|
||||
AND occupies_availability = true
|
||||
AND room_id IN %s
|
||||
) free_rooms,
|
||||
ceil((
|
||||
SELECT COUNT(1)
|
||||
FROM pms_reservation_line l
|
||||
INNER JOIN pms_reservation r ON r.id = l.reservation_id
|
||||
WHERE r.reservation_type NOT IN ('out', 'staff')
|
||||
AND r.pms_property_id = %s
|
||||
AND l.occupies_availability = true
|
||||
AND l.state != 'cancel'
|
||||
AND l.room_id IN %s
|
||||
AND l.date = d.date
|
||||
) * 100.00 / tr.num_total_rooms) occupancy_rate
|
||||
FROM (
|
||||
SELECT (CURRENT_DATE + date) date
|
||||
FROM generate_series(date %s- CURRENT_DATE, date %s - CURRENT_DATE
|
||||
) date) d
|
||||
LEFT OUTER JOIN ( SELECT date, price_day_total, overbooking
|
||||
FROM pms_reservation_line
|
||||
WHERE pms_property_id = %s
|
||||
AND room_id IN %s
|
||||
) l ON l.date = d.date,
|
||||
( SELECT COUNT(1) num_total_rooms
|
||||
FROM pms_room
|
||||
WHERE pms_property_id = %s
|
||||
AND id IN %s
|
||||
) tr
|
||||
GROUP BY d.date, tr.num_total_rooms
|
||||
ORDER BY d.date;
|
||||
""",
|
||||
(
|
||||
calendar_search_param.pmsPropertyId,
|
||||
room_ids,
|
||||
calendar_search_param.pmsPropertyId,
|
||||
room_ids,
|
||||
date_from,
|
||||
date_to,
|
||||
calendar_search_param.pmsPropertyId,
|
||||
room_ids,
|
||||
calendar_search_param.pmsPropertyId,
|
||||
room_ids,
|
||||
),
|
||||
)
|
||||
previous_itemSplitted = (
|
||||
calendar_item["splitted"]
|
||||
and previous_item
|
||||
and calendar_item["date"] > calendar_item["checkin"]
|
||||
and (
|
||||
previous_item["room_id"] != calendar_item["room_id"]
|
||||
or previous_item["reservation_id"] != calendar_item["reservation_id"]
|
||||
|
||||
result = self.env.cr.dictfetchall()
|
||||
CalendarHeaderInfo = self.env.datamodels["pms.calendar.header.info"]
|
||||
|
||||
for item in result:
|
||||
response.append(
|
||||
CalendarHeaderInfo(
|
||||
date=datetime.combine(item['date'], datetime.min.time()).isoformat(),
|
||||
dailyBilling=item["daily_billing"] if item["daily_billing"] else 0,
|
||||
freeRooms=item["free_rooms"] if item["free_rooms"] else 0,
|
||||
occupancyRate=item["occupancy_rate"] if item["occupancy_rate"] else 0,
|
||||
overbooking=item["overbooking"] if item["overbooking"] else False,
|
||||
)
|
||||
)
|
||||
)
|
||||
return {
|
||||
"date": datetime.combine(calendar_item['date'], datetime.min.time()).isoformat(),
|
||||
"roomId": calendar_item['room_id'],
|
||||
"roomTypeId": calendar_item['room_type_id'],
|
||||
"id": calendar_item['id'],
|
||||
"state": calendar_item['state'],
|
||||
"priceDayTotal": calendar_item['price_day_total'],
|
||||
"toAssign": calendar_item['to_assign'],
|
||||
"splitted": calendar_item['splitted'],
|
||||
"partnerId": calendar_item['partner_id'],
|
||||
"partnerName": calendar_item['partner_name'],
|
||||
"folioId": calendar_item['folio_id'],
|
||||
"reservationId": calendar_item['reservation_id'],
|
||||
"reservationName": calendar_item['reservation_name'],
|
||||
"reservationType": calendar_item['reservation_type'],
|
||||
"checkin": datetime.combine(calendar_item['checkin'], datetime.min.time()).isoformat(),
|
||||
"checkout": datetime.combine(calendar_item['checkout'], datetime.min.time()).isoformat(),
|
||||
"priceTotal": calendar_item['price_total'],
|
||||
"adults": calendar_item['adults'],
|
||||
"pendingPayment": calendar_item['folio_pending_amount'],
|
||||
"closureReasonId": calendar_item['closure_reason_id'],
|
||||
"isFirstNight": calendar_item['date'] == calendar_item['checkin'] if calendar_item['checkin'] else None,
|
||||
"isLastNight": calendar_item['date'] == calendar_item['checkout'] + timedelta(days=-1)
|
||||
if calendar_item['checkout'] else None,
|
||||
"nextLineSplitted": next_itemSplitted,
|
||||
"previousLineSplitted": previous_itemSplitted,
|
||||
}
|
||||
|
||||
return response
|
||||
|
||||
@restapi.method(
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user