diff --git a/pms_api_rest/services/pms_availability_plan_service.py b/pms_api_rest/services/pms_availability_plan_service.py index 98f117d16..a6acb6851 100644 --- a/pms_api_rest/services/pms_availability_plan_service.py +++ b/pms_api_rest/services/pms_availability_plan_service.py @@ -80,15 +80,21 @@ class PmsAvailabilityPlanService(Component): def get_availability_plan_rules( self, availability_plan_id, availability_plan_rule_search_param ): - result = [] + date_from = datetime.strptime( + availability_plan_rule_search_param.dateFrom, "%Y-%m-%d" + ).date() + date_to = datetime.strptime( + availability_plan_rule_search_param.dateTo, "%Y-%m-%d" + ).date() + count_nights = (date_to - date_from).days + 1 + target_dates = [date_from + timedelta(days=x) for x in range(count_nights)] + pms_property_id = availability_plan_rule_search_param.pmsPropertyId record_availability_plan_id = self.env["pms.availability.plan"].browse( availability_plan_id ) if not record_availability_plan_id: raise MissingError - PmsAvailabilityPlanRuleInfo = self.env.datamodels[ - "pms.availability.plan.rule.info" - ] + rooms = self.env["pms.room"].search( [ ( @@ -98,50 +104,78 @@ class PmsAvailabilityPlanService(Component): ) ] ) - date_from = datetime.strptime( - availability_plan_rule_search_param.dateFrom, "%Y-%m-%d" - ).date() - date_to = datetime.strptime( - availability_plan_rule_search_param.dateTo, "%Y-%m-%d" - ).date() + room_type_ids = rooms.mapped("room_type_id").ids + selected_fields = [ + "id", + "date", + "room_type_id", + "min_stay", + "min_stay_arrival", + "max_stay", + "max_stay_arrival", + "closed", + "closed_departure", + "closed_arrival", + "quota", + "max_avail", + ] + sql_select = "SELECT %s" % ", ".join(selected_fields) + self.env.cr.execute( + f""" + {sql_select} + FROM pms_availability_plan_rule rule + WHERE (pms_property_id = %s) + AND (date in %s) + AND (availability_plan_id = %s) + AND (room_type_id in %s) + """, + ( + pms_property_id, + tuple(target_dates), + record_availability_plan_id.id, + tuple(room_type_ids), + ), + ) + result_sql = self.env.cr.fetchall() + rules = [] + for res in result_sql: + rules.append( + {field: res[selected_fields.index(field)] for field in selected_fields} + ) - for date in ( - date_from + timedelta(d) for d in range((date_to - date_from).days + 1) - ): - for room_type in self.env["pms.room.type"].search( - [("id", "in", rooms.mapped("room_type_id").ids)] - ): - rule = self.env["pms.availability.plan.rule"].search( - [ - ("date", "=", date), - ( - "availability_plan_id", - "=", - record_availability_plan_id.id, - ), - ("room_type_id", "=", room_type.id), - ( - "pms_property_id", - "=", - availability_plan_rule_search_param.pmsPropertyId, - ), - ] + result = [] + PmsAvailabilityPlanRuleInfo = self.env.datamodels[ + "pms.availability.plan.rule.info" + ] + + for date in target_dates: + for room_type_id in room_type_ids: + rule = next( + ( + rule + for rule in rules + if rule["room_type_id"] == room_type_id and rule["date"] == date + ), + False, ) + if rule: availability_plan_rule_info = PmsAvailabilityPlanRuleInfo( - roomTypeId=room_type.id, + roomTypeId=rule["room_type_id"], date=datetime.combine(date, datetime.min.time()).isoformat(), - availabilityRuleId=rule.id, - minStay=rule.min_stay, - minStayArrival=rule.min_stay_arrival, - maxStay=rule.max_stay, - maxStayArrival=rule.max_stay_arrival, - closed=rule.closed, - closedDeparture=rule.closed_departure, - closedArrival=rule.closed_arrival, - quota=rule.quota if rule.quota != -1 else 0, - maxAvailability=rule.max_avail, - availabilityPlanId=rule.availability_plan_id, + availabilityRuleId=rule["id"], + minStay=rule["min_stay"], + minStayArrival=rule["min_stay_arrival"], + maxStay=rule["max_stay"], + maxStayArrival=rule["max_stay_arrival"], + closed=rule["closed"], + closedDeparture=rule["closed_departure"], + closedArrival=rule["closed_arrival"], + quota=rule["quota"] if rule["quota"] != -1 else 0, + maxAvailability=rule["max_avail"] + if rule["max_avail"] != -1 + else 0, + availabilityPlanId=availability_plan_id, ) result.append(availability_plan_rule_info) diff --git a/pms_api_rest/services/pms_calendar_service.py b/pms_api_rest/services/pms_calendar_service.py index 486dc6a66..0542c26aa 100644 --- a/pms_api_rest/services/pms_calendar_service.py +++ b/pms_api_rest/services/pms_calendar_service.py @@ -30,14 +30,33 @@ class PmsCalendarService(Component): count_nights = (date_to - date_from).days + 1 target_dates = [date_from + timedelta(days=x) for x in range(count_nights)] pms_property_id = calendar_search_param.pmsPropertyId + + selected_fields_mapper = { + "id": "night.id", + "state": "night.state", + "date": "DATE(night.date)", + "room_id": "night.room_id", + "room_type_name": "pms_room_type.default_code", + "to_assign": "reservation.to_assign", + "splitted": "reservation.splitted", + "partner_id": "reservation.partner_id", + "partner_name": "reservation.partner_name", + "folio_id": "folio.id", + "reservation_id": "reservation.id", + "reservation_name": "reservation.name", + "reservation_type": "reservation.reservation_type", + "checkin": "reservation.checkin", + "checkout": "reservation.checkout", + "price_total": "reservation.price_total", + "folio_pending_amount": "folio.pending_amount", + "adults": "reservation.adults", + } + selected_fields_sql = list(selected_fields_mapper.values()) + selected_fields = list(selected_fields_mapper.keys()) + sql_select = "SELECT %s" % ", ".join(selected_fields_sql) self.env.cr.execute( - """ - SELECT night.id as id, night.state, DATE(night.date), night.room_id, - pms_room_type.default_code, reservation.to_assign, reservation.splitted, - reservation.partner_id, reservation.partner_name, folio.id, reservation.id, - reservation.name, reservation.reservation_type, reservation.checkin, - reservation.checkout, reservation.price_total, folio.pending_amount, - reservation.adults + f""" + {sql_select} FROM pms_reservation_line night LEFT JOIN pms_reservation reservation ON reservation.id = night.reservation_id @@ -54,30 +73,12 @@ class PmsCalendarService(Component): tuple(target_dates), ), ) - SQL_FIELDS = [ - "id", - "state", - "date", - "room_id", - "room_type_name", - "to_assign", - "splitted", - "partner_id", - "partner_name", - "folio_id", - "reservation_id", - "reservation_name", - "reservation_type", - "checkin", - "checkout", - "price_total", - "folio_pending_amount", - "adults", - ] result_sql = self.env.cr.fetchall() lines = [] for res in result_sql: - lines.append({field: res[SQL_FIELDS.index(field)] for field in SQL_FIELDS}) + lines.append( + {field: res[selected_fields.index(field)] for field in selected_fields} + ) PmsCalendarInfo = self.env.datamodels["pms.calendar.info"] result_lines = [] @@ -290,59 +291,64 @@ class PmsCalendarService(Component): auth="jwt_api_pms", ) def get_free_rooms(self, pms_calendar_search_param): - date_from = datetime.strptime( pms_calendar_search_param.dateFrom, "%Y-%m-%d" ).date() date_to = datetime.strptime(pms_calendar_search_param.dateTo, "%Y-%m-%d").date() - result = [] + count_nights = (date_to - date_from).days + 1 + target_dates = [date_from + timedelta(days=x) for x in range(count_nights)] + pms_property_id = pms_calendar_search_param.pmsPropertyId + + self.env.cr.execute( + """ + SELECT night.date AS date, room.room_type_id AS room_type, COUNT(night.id) AS count + FROM pms_reservation_line night + LEFT JOIN pms_room room + ON night.room_id = room.id + WHERE (night.pms_property_id = %s) + AND (night.date in %s) + AND (night.occupies_availability = True) + GROUP BY night.date, room.room_type_id + """, + ( + pms_property_id, + tuple(target_dates), + ), + ) + result_sql = self.env.cr.fetchall() + rooms = self.env["pms.room"].search([("pms_property_id", "=", pms_property_id)]) + room_types = rooms.mapped("room_type_id") + total_rooms_by_room_type = [ + { + "room_type_id": room_type.id, + "rooms_total": len( + self.env["pms.room"].search([("room_type_id", "=", room_type.id)]) + ), + } + for room_type in room_types + ] PmsCalendarFreeDailyRoomsByType = self.env.datamodels[ "pms.calendar.free.daily.rooms.by.type" ] - for date in ( - date_from + timedelta(d) for d in range((date_to - date_from).days + 1) - ): - rooms = self.env["pms.room"].search( - [("pms_property_id", "=", pms_calendar_search_param.pmsPropertyId)] - ) - for room_type_iterator in self.env["pms.room.type"].search( - [("id", "in", rooms.mapped("room_type_id").ids)] - ): - reservation_lines_room_type = self.env["pms.reservation.line"].search( - [ - ("date", "=", date), - ("occupies_availability", "=", True), - ("room_id.room_type_id", "=", room_type_iterator.id), - ( - "pms_property_id", - "=", - pms_calendar_search_param.pmsPropertyId, - ), - ] + result = [] + for day in target_dates: + for total_room_type in total_rooms_by_room_type: + count_occupied_night_by_room_type = next( + ( + item[2] + for item in result_sql + if item[0] == day and item[1] == total_room_type["room_type_id"] + ), + 0, ) - num_rooms_room_type = self.env["pms.room"].search_count( - [ - ( - "pms_property_id", - "=", - pms_calendar_search_param.pmsPropertyId, - ), - ("room_type_id", "=", room_type_iterator.id), - ] - ) - if not reservation_lines_room_type: - free_rooms_room_type = num_rooms_room_type - else: - free_rooms_room_type = num_rooms_room_type - len( - reservation_lines_room_type - ) result.append( PmsCalendarFreeDailyRoomsByType( date=str( - datetime.combine(date, datetime.min.time()).isoformat() + datetime.combine(day, datetime.min.time()).isoformat() ), - roomTypeId=room_type_iterator.id, - freeRooms=free_rooms_room_type, + roomTypeId=total_room_type["room_type_id"], + freeRooms=total_room_type["rooms_total"] + - count_occupied_night_by_room_type, ) ) return result @@ -361,26 +367,37 @@ class PmsCalendarService(Component): auth="jwt_api_pms", ) def get_alerts_per_day(self, pms_calendar_search_param): - PmsCalendarAlertsPerDay = self.env.datamodels["pms.calendar.alerts.per.day"] date_from = datetime.strptime( pms_calendar_search_param.dateFrom, "%Y-%m-%d" ).date() date_to = datetime.strptime(pms_calendar_search_param.dateTo, "%Y-%m-%d").date() + count_nights = (date_to - date_from).days + 1 + target_dates = [date_from + timedelta(days=x) for x in range(count_nights)] + pms_property_id = pms_calendar_search_param.pmsPropertyId + + self.env.cr.execute( + """ + SELECT night.date AS date, COUNT(night.id) AS count + FROM pms_reservation_line night + WHERE (night.pms_property_id = %s) + AND (night.date in %s) + AND (night.overbooking = True) + GROUP BY night.date + """, + ( + pms_property_id, + tuple(target_dates), + ), + ) + result_sql = self.env.cr.fetchall() + PmsCalendarAlertsPerDay = self.env.datamodels["pms.calendar.alerts.per.day"] result = [] - for day in ( - date_from + timedelta(d) for d in range((date_to - date_from).days + 1) - ): - lines = self.env["pms.reservation.line"].search_count( - [ - ("date", "=", day), - ("pms_property_id", "=", pms_calendar_search_param.pmsPropertyId), - ("overbooking", "=", True), - ] - ) + for day in target_dates: + overbooking_lines = next((item for item in result_sql if item[0] == day), 0) result.append( PmsCalendarAlertsPerDay( date=str(datetime.combine(day, datetime.min.time()).isoformat()), - overbooking=True if lines > 0 else False, + overbooking=True if overbooking_lines > 0 else False, ) ) return result diff --git a/pms_api_rest/services/pms_pricelist_service.py b/pms_api_rest/services/pms_pricelist_service.py index 4ef9b5cc1..21061cdd1 100644 --- a/pms_api_rest/services/pms_pricelist_service.py +++ b/pms_api_rest/services/pms_pricelist_service.py @@ -89,15 +89,8 @@ class PmsPricelistService(Component): auth="jwt_api_pms", ) def get_pricelists_items(self, pricelist_id, pricelist_item_search_param): - result = [] - record_pricelist_id = self.env["product.pricelist"].search( - [("id", "=", pricelist_id)] - ) - if not record_pricelist_id: - raise MissingError - PmsPricelistItemInfo = self.env.datamodels["pms.pricelist.item.info"] - rooms = self.env["pms.room"].search( - [("pms_property_id", "=", pricelist_item_search_param.pmsPropertyId)] + pms_property = self.env["pms.property"].browse( + pricelist_item_search_param.pmsPropertyId ) date_from = datetime.strptime( pricelist_item_search_param.dateFrom, "%Y-%m-%d" @@ -105,44 +98,39 @@ class PmsPricelistService(Component): date_to = datetime.strptime( pricelist_item_search_param.dateTo, "%Y-%m-%d" ).date() - - for date in ( - date_from + timedelta(d) for d in range((date_to - date_from).days + 1) - ): - for room_type in self.env["pms.room.type"].search( - [("id", "in", rooms.mapped("room_type_id").ids)] - ): - item = self.env["product.pricelist.item"].search( - [ - ("pricelist_id", "=", pricelist_id), - ("applied_on", "=", "0_product_variant"), - ("product_id", "=", room_type.product_id.id), - ( - "date_start_consumption", - ">=", - date, - ), - ( - "date_end_consumption", - "<=", - date, - ), - ] + count_nights = (date_to - date_from).days + 1 + target_dates = [date_from + timedelta(days=x) for x in range(count_nights)] + record_pricelist = self.env["product.pricelist"].search( + [("id", "=", pricelist_id)] + ) + if not record_pricelist: + raise MissingError + rooms = self.env["pms.room"].search( + [("pms_property_id", "=", pricelist_item_search_param.pmsPropertyId)] + ) + room_types = rooms.mapped("room_type_id") + result = [] + PmsPricelistItemInfo = self.env.datamodels["pms.pricelist.item.info"] + for date in target_dates: + products = [(product, 1, False) for product in room_types.product_id] + date_prices = record_pricelist.with_context( + quantity=1, + consumption_date=date, + property=pms_property.id, + )._compute_price_rule(products, datetime.today()) + for product_id, v in date_prices.items(): + room_type_id = ( + self.env["product.product"].browse(product_id).room_type_id.id ) - - if item: - pricelist_info = PmsPricelistItemInfo( - roomTypeId=room_type.id, - date=str( - datetime.combine(date, datetime.min.time()).isoformat() - ), - ) - - pricelist_info.pricelistItemId = item[0].id - pricelist_info.price = item[0].fixed_price - - result.append(pricelist_info) - + if not v[1]: + continue + pricelist_info = PmsPricelistItemInfo( + roomTypeId=room_type_id, + date=str(datetime.combine(date, datetime.min.time()).isoformat()), + pricelistItemId=v[1], + price=v[0], + ) + result.append(pricelist_info) return result @restapi.method(