[IMP] Calendar Performance

This commit is contained in:
Alexandre Díaz
2019-01-13 02:10:33 +01:00
parent 03457f2228
commit 279675e2ae
10 changed files with 181 additions and 178 deletions

View File

@@ -97,7 +97,7 @@ class HotelFolio(models.Model):
readonly=True, copy=False, readonly=True, copy=False,
index=True, track_visibility='onchange', index=True, track_visibility='onchange',
default='draft') default='draft')
# Partner fields for being used directly in the Folio views--------- # Partner fields for being used directly in the Folio views---------
email = fields.Char('E-mail', related='partner_id.email') email = fields.Char('E-mail', related='partner_id.email')
@@ -165,7 +165,7 @@ class HotelFolio(models.Model):
has_checkout_to_send = fields.Boolean( has_checkout_to_send = fields.Boolean(
compute='_compute_has_checkout_to_send') compute='_compute_has_checkout_to_send')
#Generic Fields----------------------------------------------------- #Generic Fields-----------------------------------------------------
internal_comment = fields.Text(string='Internal Folio Notes') internal_comment = fields.Text(string='Internal Folio Notes')
cancelled_reason = fields.Text('Cause of cancelled') cancelled_reason = fields.Text('Cause of cancelled')
closure_reason_id = fields.Many2one('room.closure.reason') closure_reason_id = fields.Many2one('room.closure.reason')
@@ -349,7 +349,7 @@ class HotelFolio(models.Model):
).next_by_code('hotel.folio') or _('New') ).next_by_code('hotel.folio') or _('New')
else: else:
vals['name'] = self.env['ir.sequence'].next_by_code('hotel.folio') or _('New') vals['name'] = self.env['ir.sequence'].next_by_code('hotel.folio') or _('New')
# Makes sure partner_invoice_id' and 'pricelist_id' are defined # Makes sure partner_invoice_id' and 'pricelist_id' are defined
lfields = ('partner_invoice_id', 'partner_shipping_id', 'pricelist_id') lfields = ('partner_invoice_id', 'partner_shipping_id', 'pricelist_id')
@@ -402,7 +402,7 @@ class HotelFolio(models.Model):
self.pricelist_id.is_staff, self.pricelist_id.is_staff,
self.reservation_type)} self.reservation_type)}
self.update(values) self.update(values)
@api.model @api.model
def calcule_reservation_type(self, is_staff, current_type): def calcule_reservation_type(self, is_staff, current_type):
@@ -753,13 +753,13 @@ class HotelFolio(models.Model):
info_grouped = [] info_grouped = []
for rline in self.room_lines: for rline in self.room_lines:
if (import_all or rline.to_send) and \ if (import_all or rline.to_send) and \
not rline.parent_reservation and rline.state == state: not rline.parent_reservation and rline.state == state:
dates = rline.get_real_checkin_checkout() dates = (rline.real_checkin, rline.real_checkout)
vals = { vals = {
'num': len( 'num': len(
self.room_lines.filtered( self.room_lines.filtered(
lambda r: r.get_real_checkin_checkout()[0] == dates[0] and \ lambda r: r.real_checkin == dates[0] and \
r.get_real_checkin_checkout()[1] == dates[1] and \ r.real_checkout == dates[1] and \
r.room_type_id.id == rline.room_type_id.id and \ r.room_type_id.id == rline.room_type_id.id and \
(r.to_send or import_all) and not r.parent_reservation and \ (r.to_send or import_all) and not r.parent_reservation and \
r.state == rline.state) r.state == rline.state)

View File

@@ -151,6 +151,10 @@ class HotelReservation(models.Model):
checkout = fields.Date('Check Out', required=True, checkout = fields.Date('Check Out', required=True,
default=_get_default_checkout, default=_get_default_checkout,
track_visibility='onchange') track_visibility='onchange')
real_checkin = fields.Date('Real Check In', required=True,
track_visibility='onchange')
real_checkout = fields.Date('Real Check Out', required=True,
track_visibility='onchange')
arrival_hour = fields.Char('Arrival Hour', arrival_hour = fields.Char('Arrival Hour',
default=_get_default_arrival_hour, default=_get_default_arrival_hour,
help="Default Arrival Hour (HH:MM)") help="Default Arrival Hour (HH:MM)")
@@ -309,7 +313,11 @@ class HotelReservation(models.Model):
vals.update(self.prepare_reservation_lines( vals.update(self.prepare_reservation_lines(
vals['checkin'], vals['checkin'],
days_diff, days_diff,
vals=vals)) #REVISAR el unlink vals=vals)) # REVISAR el unlink
if 'checkin' in vals and 'checkout' in vals \
and 'real_checkin' not in vals and 'real_checkout' not in vals:
vals['real_checkin'] = vals['checkin']
vals['real_checkout'] = vals['checkout']
record = super(HotelReservation, self).create(vals) record = super(HotelReservation, self).create(vals)
#~ if (record.state == 'draft' and record.folio_id.state == 'sale') or \ #~ if (record.state == 'draft' and record.folio_id.state == 'sale') or \
#~ record.preconfirm: #~ record.preconfirm:
@@ -325,6 +333,13 @@ class HotelReservation(models.Model):
for record in self: for record in self:
checkin = vals['checkin'] if 'checkin' in vals else record.checkin checkin = vals['checkin'] if 'checkin' in vals else record.checkin
checkout = vals['checkout'] if 'checkout' in vals else record.checkout checkout = vals['checkout'] if 'checkout' in vals else record.checkout
if not record.splitted and not vals.get('splitted', False):
if 'checkin' in vals:
vals['real_checkin'] = vals['checkin']
if 'checkout' in vals:
vals['real_checkout'] = vals['checkout']
days_diff = ( days_diff = (
fields.Date.from_string(checkout) - \ fields.Date.from_string(checkout) - \
fields.Date.from_string(checkin) fields.Date.from_string(checkin)
@@ -485,6 +500,8 @@ class HotelReservation(models.Model):
'splitted': self.splitted, 'splitted': self.splitted,
'room_type_id': self.room_type_id.id, 'room_type_id': self.room_type_id.id,
'room_id': self.room_id.id, 'room_id': self.room_id.id,
'real_checkin': self.real_checkin,
'real_checkout': self.real_checkout,
} }
@api.constrains('adults') @api.constrains('adults')
@@ -952,31 +969,6 @@ class HotelReservation(models.Model):
RESERVATION SPLITTED ----------------------------------------------- RESERVATION SPLITTED -----------------------------------------------
""" """
@api.multi
def get_real_checkin_checkout(self):
self.ensure_one()
if not self.splitted:
return (self.checkin, self.checkout)
master_reservation = self.parent_reservation or self
splitted_reservs = self.env['hotel.reservation'].search([
'|',
('splitted', '=', True),
('id', '=', master_reservation.id), # This here because can create a splitted reserv before set as splitted the parent reservation (master)
('folio_id', '=', self.folio_id.id),
'|',
('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id)
])
last_checkout = splitted_reservs[0].checkout
first_checkin = splitted_reservs[0].checkin
for reserv in splitted_reservs:
if last_checkout < reserv.checkout:
last_checkout = reserv.checkout
if first_checkin > reserv.checkin:
first_checkin = reserv.checkin
return (first_checkin, last_checkout)
@api.multi @api.multi
def split(self, nights): def split(self, nights):
for record in self: for record in self:
@@ -1088,16 +1080,19 @@ class HotelReservation(models.Model):
})) }))
tprice += rline.price tprice += rline.price
# Real Dates
rdate_begin, rdate_end = master_reservation.get_real_checkin_checkout()
# Unify # Unify
osplitted_reservs = splitted_reservs - master_reservation osplitted_reservs = splitted_reservs - master_reservation
osplitted_reservs.sudo().unlink() osplitted_reservs.sudo().unlink()
_logger.info("========== UNIFY")
_logger.info(master_reservation.real_checkin)
_logger.info(first_checkin)
_logger.info(master_reservation.real_checkout)
_logger.info(last_checkout)
master_reservation.write({ master_reservation.write({
'checkout': last_checkout, 'checkout': last_checkout,
'splitted': rdate_begin != first_checkin or rdate_end != last_checkout, 'splitted': master_reservation.real_checkin != first_checkin or master_reservation.real_checkout != last_checkout,
'reservation_line_ids': rlines, 'reservation_line_ids': rlines,
'price_total': tprice, 'price_total': tprice,
}) })

View File

@@ -1,12 +1,11 @@
# Copyright 2018 Alexandre Díaz <dev@redneboa.es> # Copyright 2018 Alexandre Díaz <dev@redneboa.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging import logging
from datetime import datetime, timedelta import time
from datetime import timedelta
from odoo import models, fields, api, _ from odoo import models, fields, api, _
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.tools import ( from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
DEFAULT_SERVER_DATE_FORMAT,
DEFAULT_SERVER_DATETIME_FORMAT)
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -18,10 +17,6 @@ class HotelReservation(models.Model):
reserve_color_text = fields.Char(compute='_compute_color', string='Color', reserve_color_text = fields.Char(compute='_compute_color', string='Color',
store=True) store=True)
"""
COMPUTE RESERVE COLOR ----------------------------------------------
"""
@api.multi @api.multi
def _generate_color(self): def _generate_color(self):
self.ensure_one() self.ensure_one()
@@ -81,8 +76,10 @@ class HotelReservation(models.Model):
json_reservations.append({ json_reservations.append({
'room_id': reserv.room_id.id, 'room_id': reserv.room_id.id,
'id': reserv.id, 'id': reserv.id,
'name': reserv.folio_id.closure_reason_id.name or _('Out of service') if reserv.folio_id.reservation_type == 'out' 'name': reserv.folio_id.closure_reason_id.name
else reserv.folio_id.partner_id.name, or _('Out of service')
if reserv.folio_id.reservation_type == 'out'
else reserv.folio_id.partner_id.name,
'adults': reserv.adults, 'adults': reserv.adults,
'childrens': reserv.children, 'childrens': reserv.children,
'checkin': reserv.checkin, 'checkin': reserv.checkin,
@@ -91,27 +88,22 @@ class HotelReservation(models.Model):
'bgcolor': reserv.reserve_color, 'bgcolor': reserv.reserve_color,
'color': reserv.reserve_color_text, 'color': reserv.reserve_color_text,
'splitted': reserv.splitted, 'splitted': reserv.splitted,
'parent_reservation': reserv.parent_reservation and reserv.parent_reservation.id or False, 'parent_reservation': reserv.parent_reservation
and reserv.parent_reservation.id or False,
'read_only': False, # Read-Only 'read_only': False, # Read-Only
'fix_days': reserv.splitted, # Fix Days 'fix_days': reserv.splitted, # Fix Days
'fix_room': False, # Fix Rooms 'fix_room': False, # Fix Rooms
'overbooking': reserv.overbooking, 'overbooking': reserv.overbooking,
'state': reserv.state, 'state': reserv.state,
'real_dates': reserv.get_real_checkin_checkout()}) 'real_dates': [reserv.real_checkin, reserv.real_checkout]})
num_split = 0
if reserv.splitted:
master_reserv = reserv.parent_reservation or reserv
num_split = self.search_count([
('folio_id', '=', reserv.folio_id.id),
'|', ('parent_reservation', '=', master_reserv.id),
('id', '=', master_reserv.id),
('splitted', '=', True),
])
json_reservation_tooltips.update({ json_reservation_tooltips.update({
reserv.id: { reserv.id: {
'folio_name': reserv.folio_id.name, 'folio_name': reserv.folio_id.name,
'name': _('Out of service') if reserv.folio_id.reservation_type == 'out' else reserv.folio_id.partner_id.name, 'name': _('Out of service')
'phone': reserv.mobile or reserv.phone or _('Phone not provided'), if reserv.folio_id.reservation_type == 'out'
else reserv.folio_id.partner_id.name,
'phone': reserv.mobile or reserv.phone
or _('Phone not provided'),
'email': reserv.email or _('Email not provided'), 'email': reserv.email or _('Email not provided'),
'room_type_name': reserv.room_type_id.name, 'room_type_name': reserv.room_type_id.name,
'adults': reserv.adults, 'adults': reserv.adults,
@@ -120,13 +112,12 @@ class HotelReservation(models.Model):
'checkout': reserv.checkout, 'checkout': reserv.checkout,
'arrival_hour': reserv.arrival_hour, 'arrival_hour': reserv.arrival_hour,
'departure_hour': reserv.departure_hour, 'departure_hour': reserv.departure_hour,
'num_split': num_split,
'amount_total': reserv.folio_id.amount_total, 'amount_total': reserv.folio_id.amount_total,
'pending_amount': reserv.folio_id.pending_amount, 'pending_amount': reserv.folio_id.pending_amount,
'amount_paid': reserv.folio_id.amount_total - reserv.folio_id.pending_amount, 'amount_paid': reserv.folio_id.amount_total - reserv.folio_id.pending_amount,
'type': reserv.reservation_type or 'normal', 'type': reserv.reservation_type or 'normal',
'out_service_description': reserv.out_service_description or 'out_service_description': reserv.out_service_description
_('No reason given'), or _('No reason given'),
# TODO: Add Board Services and Extra Service as Cradle, Bed, ... # TODO: Add Board Services and Extra Service as Cradle, Bed, ...
} }
}) })
@@ -138,9 +129,8 @@ class HotelReservation(models.Model):
'res.config.settings', 'default_pricelist_id') 'res.config.settings', 'default_pricelist_id')
if pricelist_id: if pricelist_id:
pricelist_id = int(pricelist_id) pricelist_id = int(pricelist_id)
json_rooms = [] json_rooms = [
for room in rooms: {
json_rooms.append({
'id': room.id, 'id': room.id,
'name': room.name, 'name': room.name,
'capacity': room.capacity, 'capacity': room.capacity,
@@ -148,57 +138,57 @@ class HotelReservation(models.Model):
'class_id': room.room_type_id.class_id.id, 'class_id': room.room_type_id.class_id.id,
'shared': room.shared_room, 'shared': room.shared_room,
'price': room.room_type_id 'price': room.room_type_id
and ['pricelist', room.room_type_id.id, pricelist_id, and ['pricelist', room.room_type_id.id, pricelist_id,
room.room_type_id.name] or 0, room.room_type_id.name] or 0,
'room_type_name': room.room_type_id.name, 'room_type_name': room.room_type_id.name,
'room_type_id': room.room_type_id.id, 'room_type_id': room.room_type_id.id,
'floor_id': room.floor_id.id, 'floor_id': room.floor_id.id,
'amentity_ids': room.room_type_id.room_amenity_ids.ids, 'amentity_ids': room.room_type_id.room_amenity_ids.ids,
}) } for room in rooms]
return json_rooms return json_rooms
@api.model @api.model
def _hcalendar_calendar_data(self, calendars): def _hcalendar_calendar_data(self, calendars):
json_calendars = [] return [
for calendar in calendars: {
json_calendars.append({
'id': calendar.id, 'id': calendar.id,
'name': calendar.name, 'name': calendar.name,
'segmentation_ids': calendar.segmentation_ids.ids, 'segmentation_ids': calendar.segmentation_ids.ids,
'location_ids': calendar.location_ids.ids, 'location_ids': calendar.location_ids.ids,
'amenity_ids': calendar.amenity_ids.ids, 'amenity_ids': calendar.amenity_ids.ids,
'room_type_ids': calendar.room_type_ids.ids, 'room_type_ids': calendar.room_type_ids.ids,
}) } for calendar in calendars]
return json_calendars
@api.model @api.model
def _hcalendar_event_data(self, events): def _hcalendar_event_data(self, events):
json_events = [] json_events = [
for event in events: {
json_events.append({
'id': event.id, 'id': event.id,
'name': event.name, 'name': event.name,
'date': event.start, 'date': event.start,
'location': event.location, 'location': event.location,
}) } for event in events]
return json_events return json_events
@api.model
def get_hcalendar_calendar_data(self):
calendars = self.env['hotel.calendar'].search([])
res = self._hcalendar_calendar_data(calendars)
return res
@api.model @api.model
def get_hcalendar_reservations_data(self, dfrom_dt, dto_dt, rooms): def get_hcalendar_reservations_data(self, dfrom_dt, dto_dt, rooms):
rdfrom_dt = dfrom_dt + timedelta(days=1) # Ignore checkout rdfrom_dt = dfrom_dt + timedelta(days=1) # Ignore checkout
reservations_raw = self.env['hotel.reservation'].search( reservations_raw = self.env['hotel.reservation'].search([
[('room_id', 'in', rooms.ids)], ('room_id', 'in', rooms.ids),
order="checkin DESC, checkout ASC, adults DESC, children DESC") '|', '&',
reservations_ll = self.env['hotel.reservation'].search([
('checkin', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)), ('checkin', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('checkout', '>=', rdfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)) ('checkout', '>=', rdfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
]) '&',
reservations_lr = self.env['hotel.reservation'].search([
('checkin', '>=', dfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)), ('checkin', '>=', dfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('checkout', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)) ('checkout', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT))
]) ], order="checkin DESC, checkout ASC, adults DESC, children DESC")
reservations = (reservations_ll | reservations_lr) & reservations_raw return self._hcalendar_reservation_data(reservations_raw)
return self._hcalendar_reservation_data(reservations)
@api.model @api.model
def get_hcalendar_pricelist_data(self, dfrom_dt, dto_dt): def get_hcalendar_pricelist_data(self, dfrom_dt, dto_dt):
@@ -206,6 +196,7 @@ class HotelReservation(models.Model):
'res.config.settings', 'default_pricelist_id') 'res.config.settings', 'default_pricelist_id')
if pricelist_id: if pricelist_id:
pricelist_id = int(pricelist_id) pricelist_id = int(pricelist_id)
date_diff = abs((dfrom_dt - dto_dt).days) + 1 date_diff = abs((dfrom_dt - dto_dt).days) + 1
# Get Prices # Get Prices
json_rooms_prices = {pricelist_id: []} json_rooms_prices = {pricelist_id: []}
@@ -214,22 +205,30 @@ class HotelReservation(models.Model):
order='hcal_sequence ASC') order='hcal_sequence ASC')
room_pr_cached_obj = self.env['room.pricelist.cached'] room_pr_cached_obj = self.env['room.pricelist.cached']
prod_price_ids = room_pr_cached_obj.search([
('room_id', 'in', room_typed_ids.ids),
('date', '>=', dfrom_dt),
('date', '<=', dto_dt)
], order='date ASC')
for room_type_id in room_typed_ids: for room_type_id in room_typed_ids:
days = {} days = {}
for i in range(0, date_diff): prod_price_room_ids = prod_price_ids.filtered(
ndate = dfrom_dt + timedelta(days=i) lambda x: x.room_id == room_type_id)
ndate_str = ndate.strftime(DEFAULT_SERVER_DATE_FORMAT) prod_price_ids = prod_price_ids - prod_price_room_ids
prod_price_id = room_pr_cached_obj.search([ for offsetDay in range(0, date_diff):
('room_id', '=', room_type_id.id), ndate = dfrom_dt+timedelta(days=offsetDay)
('date', '=', ndate_str) strndate = ndate.strftime(DEFAULT_SERVER_DATE_FORMAT)
], limit=1) prod_price_id = prod_price_room_ids.filtered(
lambda x: x.date == strndate)
prod_price_room_ids = prod_price_room_ids - prod_price_id
days.update({ days.update({
ndate.strftime("%d/%m/%Y"): prod_price_id and ndate.strftime("%d/%m/%Y"): prod_price_id
prod_price_id.price or and prod_price_id.price
room_type_id.product_id.with_context( or room_type_id.product_id.with_context(
quantity=1, quantity=1,
date=ndate_str, date=prod_price_id.date,
pricelist=pricelist_id).price pricelist=pricelist_id).price
}) })
json_rooms_prices[pricelist_id].append({ json_rooms_prices[pricelist_id].append({
'room': room_type_id.id, 'room': room_type_id.id,
@@ -244,60 +243,56 @@ class HotelReservation(models.Model):
'res.config.settings', 'default_restriction_id') 'res.config.settings', 'default_restriction_id')
if restriction_id: if restriction_id:
restriction_id = int(restriction_id) restriction_id = int(restriction_id)
date_diff = abs((dto_dt - dfrom_dt).days) + 1
# Get Prices # Get Restrictions
json_rooms_rests = {} json_rooms_rests = {}
room_types = self.env['hotel.room.type'].search( room_typed_ids = self.env['hotel.room.type'].search(
[], [],
order='hcal_sequence ASC') order='hcal_sequence ASC')
room_type_rest_obj = self.env['hotel.room.type.restriction.item'] room_type_rest_obj = self.env['hotel.room.type.restriction.item']
for room_type in room_types: rtype_rest_ids = room_type_rest_obj.search([
('room_type_id', 'in', room_typed_ids.ids),
('date', '>=', dfrom_dt),
('date', '<=', dto_dt),
('restriction_id', '=', restriction_id)
])
for room_type in room_typed_ids:
days = {} days = {}
for i in range(0, date_diff): rest_ids = rtype_rest_ids.filtered(
ndate = dfrom_dt + timedelta(days=i) lambda x: x.room_type_id == room_type)
ndate_str = ndate.strftime(DEFAULT_SERVER_DATE_FORMAT) for rest_id in rest_ids:
rest_id = room_type_rest_obj.search([ days.update({
('room_type_id', '=', room_type.id), fields.Date.from_string(rest_id.date).strftime("%d/%m/%Y"): (
('date', '=', ndate_str), rest_id.min_stay,
('restriction_id', '=', restriction_id) rest_id.min_stay_arrival,
], limit=1) rest_id.max_stay,
if rest_id and (rest_id.min_stay or rest_id.min_stay_arrival or rest_id.max_stay_arrival,
rest_id.max_stay or rest_id.max_stay_arrival or rest_id.closed,
rest_id.closed or rest_id.closed_arrival or rest_id.closed_arrival,
rest_id.closed_departure): rest_id.closed_departure)
days.update({ })
ndate.strftime("%d/%m/%Y"): (
rest_id.min_stay,
rest_id.min_stay_arrival,
rest_id.max_stay,
rest_id.max_stay_arrival,
rest_id.closed,
rest_id.closed_arrival,
rest_id.closed_departure)
})
json_rooms_rests.update({room_type.id: days}) json_rooms_rests.update({room_type.id: days})
return json_rooms_rests return json_rooms_rests
@api.model @api.model
def get_hcalendar_events_data(self, dfrom_dt, dto_dt): def get_hcalendar_events_data(self, dfrom_dt, dto_dt):
user_id = self.env['res.users'].browse(self.env.uid) user_id = self.env['res.users'].browse(self.env.uid)
domain = [] domain = [
'|', '&',
('start', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('stop', '>=', dfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
'&',
('start', '>=', dfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('stop', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT))
]
if user_id.pms_allowed_events_tags: if user_id.pms_allowed_events_tags:
domain.append(('categ_ids', 'in', user_id.pms_allowed_events_tags)) domain.append(('categ_ids', 'in', user_id.pms_allowed_events_tags))
if user_id.pms_denied_events_tags: if user_id.pms_denied_events_tags:
domain.append( domain.append(
('categ_ids', 'not in', user_id.pms_denied_events_tags)) ('categ_ids', 'not in', user_id.pms_denied_events_tags))
events_raw = self.env['calendar.event'].search(domain) events_raw = self.env['calendar.event'].search(domain)
events_ll = self.env['calendar.event'].search([ return self._hcalendar_event_data(events_raw)
('start', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('stop', '>=', dfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT))
])
events_lr = self.env['calendar.event'].search([
('start', '>=', dfrom_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('stop', '<=', dto_dt.strftime(DEFAULT_SERVER_DATE_FORMAT))
])
events = (events_ll | events_lr) & events_raw
return self._hcalendar_event_data(events)
@api.model @api.model
def get_hcalendar_settings(self): def get_hcalendar_settings(self):
@@ -327,9 +322,8 @@ class HotelReservation(models.Model):
dfrom_dt = fields.Date.from_string(dfrom) dfrom_dt = fields.Date.from_string(dfrom)
dto_dt = fields.Date.from_string(dto) dto_dt = fields.Date.from_string(dto)
rooms = self.env['hotel.room'].search([], order='hcal_sequence ASC') rooms = self.env['hotel.room'].search([], order='hcal_sequence ASC')
calendars = self.env['hotel.calendar'].search([])
json_res, json_res_tooltips = self.get_hcalendar_reservations_data( json_res, json_res_tooltips = self.get_hcalendar_reservations_data(
dfrom_dt, dto_dt, rooms) dfrom_dt, dto_dt, rooms)
@@ -341,7 +335,8 @@ class HotelReservation(models.Model):
'restrictions': self.get_hcalendar_restrictions_data(dfrom_dt, 'restrictions': self.get_hcalendar_restrictions_data(dfrom_dt,
dto_dt), dto_dt),
'events': self.get_hcalendar_events_data(dfrom_dt, dto_dt), 'events': self.get_hcalendar_events_data(dfrom_dt, dto_dt),
'calendars': self._hcalendar_calendar_data(calendars) 'calendars': withRooms and self.get_hcalendar_calendar_data()
or []
} }
return vals return vals
@@ -356,7 +351,7 @@ class HotelReservation(models.Model):
'room_id': self.room_id.id, 'room_id': self.room_id.id,
'reserv_id': self.id, 'reserv_id': self.id,
'partner_name': (self.closure_reason_id.name or _('Out of service')) 'partner_name': (self.closure_reason_id.name or _('Out of service'))
if self.reservation_type == 'out' else self.partner_id.name, if self.reservation_type == 'out' else self.partner_id.name,
'adults': self.adults, 'adults': self.adults,
'children': self.children, 'children': self.children,
'checkin': self.checkin, 'checkin': self.checkin,
@@ -367,12 +362,12 @@ class HotelReservation(models.Model):
'reserve_color': self.reserve_color, 'reserve_color': self.reserve_color,
'reserve_color_text': self.reserve_color_text, 'reserve_color_text': self.reserve_color_text,
'splitted': self.splitted, 'splitted': self.splitted,
'parent_reservation': self.parent_reservation and 'parent_reservation': self.parent_reservation
self.parent_reservation.id or 0, and self.parent_reservation.id or 0,
'room_name': self.room_id.name, 'room_name': self.room_id.name,
'room_type_name': self.room_type_id.name, 'room_type_name': self.room_type_id.name,
'partner_phone': self.partner_id.mobile 'partner_phone': self.partner_id.mobile
or self.partner_id.phone or _('Undefined'), or self.partner_id.phone or _('Undefined'),
'partner_email': self.partner_id.email or _('Undefined'), 'partner_email': self.partner_id.email or _('Undefined'),
'state': self.state, 'state': self.state,
'fix_days': self.splitted, 'fix_days': self.splitted,
@@ -382,8 +377,9 @@ class HotelReservation(models.Model):
'amount_paid': self.folio_id.amount_total - self.folio_id.pending_amount, 'amount_paid': self.folio_id.amount_total - self.folio_id.pending_amount,
'reservation_type': self.reservation_type or 'normal', 'reservation_type': self.reservation_type or 'normal',
'closure_reason_id': self.closure_reason_id, 'closure_reason_id': self.closure_reason_id,
'out_service_description': self.out_service_description or _('No reason given'), 'out_service_description': self.out_service_description
'real_dates': self.get_real_checkin_checkout(), or _('No reason given'),
'real_dates': [self.real_checkin, self.real_checkout],
} }
@api.multi @api.multi
@@ -438,24 +434,24 @@ class HotelReservation(models.Model):
@api.multi @api.multi
def write(self, vals): def write(self, vals):
ret = super(HotelReservation, self).write(vals)
_logger.info("RESERV WRITE") _logger.info("RESERV WRITE")
ret = super(HotelReservation, self).write(vals)
if 'partner_id' in vals or 'checkin' in vals or \ if 'partner_id' in vals or 'checkin' in vals or \
'checkout' in vals or 'product_id' in vals or \ 'checkout' in vals or 'product_id' in vals or \
'adults' in vals or 'children' in vals or \ 'adults' in vals or 'children' in vals or \
'state' in vals or 'splitted' in vals or \ 'state' in vals or 'splitted' in vals or \
'closure_reason_id' in vals or 'out_service_description' in vals or \ 'closure_reason_id' in vals or 'out_service_description' in vals or \
'reservation_type' in vals or \ 'reservation_type' in vals or \
'reserve_color' in vals or \ 'price_total' in vals or \
'reserve_color_text' in vals or 'price_total' in vals or \
'parent_reservation' in vals or 'overbooking' in vals or \ 'parent_reservation' in vals or 'overbooking' in vals or \
'room_type_id' in vals: 'room_type_id' in vals:
for record in self: for record in self:
record.send_bus_notification( record.send_bus_notification(
'write', 'write',
(record.state == 'cancelled') and 'warn' or 'notify', (record.state == 'cancelled') and 'warn' or 'notify',
(record.state == 'cancelled') and (record.state == 'cancelled')
_("Reservation Cancelled") or _("Reservation Changed") and _("Reservation Cancelled") or _("Reservation Changed")
) )
elif not any(vals) or 'to_read' in vals or 'to_assign' in vals: elif not any(vals) or 'to_read' in vals or 'to_assign' in vals:
self.send_bus_notification('write', 'noshow') self.send_bus_notification('write', 'noshow')

View File

@@ -104,7 +104,7 @@ var PMSCalendarController = AbstractController.extend({
/** DO MAGIC **/ /** DO MAGIC **/
var hcal_dates = this.renderer.get_view_filter_dates(); var hcal_dates = this.renderer.get_view_filter_dates();
var oparams = [ var oparams = [
hcal_dates[0].format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT), hcal_dates[0].subtract(1, 'd').format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
hcal_dates[1].format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT) hcal_dates[1].format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT)
]; ];
@@ -192,7 +192,7 @@ var PMSCalendarController = AbstractController.extend({
self._view_options['days'] = 7; self._view_options['days'] = 7;
} }
var date_begin = moment().startOf('day'); var date_begin = moment().local().startOf('day');
var days = self._view_options['days']; var days = self._view_options['days'];
if (self._view_options['days'] === 'month') { if (self._view_options['days'] === 'month') {
days = date_begin.daysInMonth(); days = date_begin.daysInMonth();
@@ -206,7 +206,6 @@ var PMSCalendarController = AbstractController.extend({
$dateTimePickerBegin.data("DateTimePicker").date(date_begin); $dateTimePickerBegin.data("DateTimePicker").date(date_begin);
$dateEndDays.val(self._view_options['days']); $dateEndDays.val(self._view_options['days']);
//self.renderer.init_calendar_view();
self._load_calendars(); self._load_calendars();
self._assign_view_events(); self._assign_view_events();
}); });
@@ -214,23 +213,24 @@ var PMSCalendarController = AbstractController.extend({
_reload_active_calendar: function() { _reload_active_calendar: function() {
var self = this; var self = this;
var filterDates = this.renderer.get_view_filter_dates();
var active_calendar = this._multi_calendar.get_active_calendar(); var active_calendar = this._multi_calendar.get_active_calendar();
var filterDates = active_calendar.getDates();
// Clip dates // Clip dates
var dfrom = filterDates[0].clone(), var dfrom = filterDates[0].clone(),
dto = filterDates[1].clone(); dto = filterDates[1].clone();
if (filterDates[0].isBetween(this._last_dates[0], this._last_dates[1], 'days') && filterDates[1].isAfter(this._last_dates[1], 'day')) { if (filterDates[0].isBetween(this._last_dates[0], this._last_dates[1], 'days') && filterDates[1].isAfter(this._last_dates[1], 'day')) {
dfrom = this._last_dates[1].clone().local().startOf('day').utc(); dfrom = this._last_dates[1].clone();
} else if (this._last_dates[0].isBetween(filterDates[0], filterDates[1], 'days') && this._last_dates[1].isAfter(filterDates[0], 'day')) { } else if (this._last_dates[0].isBetween(filterDates[0], filterDates[1], 'days') && this._last_dates[1].isAfter(filterDates[0], 'day')) {
dto = this._last_dates[0].clone().local().endOf('day').utc(); dto = this._last_dates[0].clone();
} }
var oparams = [ var oparams = [
dfrom.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT), dfrom.subtract(1, 'd').format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
dto.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT), dto.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
false false
]; ];
this.model.get_calendar_data(oparams).then(function(results){ this.model.get_calendar_data(oparams).then(function(results){
var reservs = []; var reservs = [];
for (var r of results['reservations']) { for (var r of results['reservations']) {
@@ -750,7 +750,6 @@ var PMSCalendarController = AbstractController.extend({
'checkout_day_of_week': HotelCalendar.toMomentUTC(tp['checkout'], '').format("dddd"), 'checkout_day_of_week': HotelCalendar.toMomentUTC(tp['checkout'], '').format("dddd"),
'arrival_hour': tp['arrival_hour'], 'arrival_hour': tp['arrival_hour'],
'departure_hour': tp['departure_hour'], 'departure_hour': tp['departure_hour'],
'num_split': tp['num_split'],
'amount_total': Number(tp['amount_total']).toLocaleString(), 'amount_total': Number(tp['amount_total']).toLocaleString(),
'pending_amount': Number(tp['pending_amount']).toLocaleString(), 'pending_amount': Number(tp['pending_amount']).toLocaleString(),
'amount_paid': Number(tp['amount_paid']).toLocaleString(), 'amount_paid': Number(tp['amount_paid']).toLocaleString(),

View File

@@ -31,7 +31,7 @@ return AbstractModel.extend({
get_calendar_data: function(oparams) { get_calendar_data: function(oparams) {
var dialog = bootbox.dialog({ var dialog = bootbox.dialog({
message: '<div class="text-center"><i class="fa fa-spin fa-spinner"></i> Downloading Calendar Data...</div>', message: '<div class="text-center"><i class="fa fa-spin fa-spinner"></i> Getting Calendar Data From Server...</div>',
onEscape: false, onEscape: false,
closeButton: false, closeButton: false,
size: 'small', size: 'small',
@@ -43,6 +43,16 @@ return AbstractModel.extend({
args: oparams, args: oparams,
context: Session.user_context, context: Session.user_context,
}, { }, {
xhr: function () {
var xhr = new window.XMLHttpRequest();
//Download progress
xhr.addEventListener("readystatechange", function() {
if (this.readyState == this.DONE) {
console.log(`[HotelCalendar] Downloaded ${(parseInt(xhr.getResponseHeader("Content-Length"), 10)/1024).toFixed(3)}KiB of data`);
}
}, false);
return xhr;
},
success: function() { success: function() {
dialog.modal('hide'); dialog.modal('hide');
}, },

View File

@@ -48,13 +48,12 @@ var HotelCalendarView = AbstractRenderer.extend({
get_view_filter_dates: function () { get_view_filter_dates: function () {
var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin'); var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin');
var $dateEndDays = this.$el.find('#pms-menu #date_end_days'); var $dateEndDays = this.$el.find('#pms-menu #date_end_days');
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().set({'hour': 0, 'minute': 0, 'second': 0}).clone().utc(); var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().clone();
var days = $dateEndDays.val(); var days = $dateEndDays.val();
if (days === 'month') { if (days === 'month') {
days = date_begin.daysInMonth(); days = date_begin.daysInMonth();
} }
var date_end = date_begin.clone().add(days+1, 'd').set({'hour': 23, 'minute': 59, 'second': 59}).clone().utc(); var date_end = date_begin.clone().add(days+1, 'd');
return [date_begin, date_end]; return [date_begin, date_end];
}, },
@@ -113,6 +112,10 @@ var HotelCalendarView = AbstractRenderer.extend({
//language : moment.locale(), //language : moment.locale(),
locale : moment.locale(), locale : moment.locale(),
format : HotelConstants.L10N_DATE_MOMENT_FORMAT, format : HotelConstants.L10N_DATE_MOMENT_FORMAT,
widgetPositioning:{
horizontal: 'auto',
vertical: 'bottom'
}
}; };
var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin'); var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin');
var $dateEndDays = this.$el.find('#pms-menu #date_end_days'); var $dateEndDays = this.$el.find('#pms-menu #date_end_days');

View File

@@ -21,12 +21,12 @@ return AbstractModel.extend({
}, },
save_changes: function (params) { save_changes: function (params) {
params.splice(0, 0, false); // FIXME: ID=False because first parameter its an integer //params.splice(0, 0, false); // FIXME: ID=False because first parameter its an integer
return this._rpc({ return this._rpc({
model: this.modelName, model: this.modelName,
method: 'save_changes', method: 'save_changes',
args: params, args: params,
context: Session.user_context, //context: Session.user_context,
}); });
}, },

View File

@@ -97,12 +97,8 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
var active_calendar = this.get_active_calendar(); var active_calendar = this.get_active_calendar();
if (active_calendar) { if (active_calendar) {
setTimeout(function(calendar){ setTimeout(function(calendar){
for (var reserv of calendar._reservations) { calendar._updateOffsets();
var style = window.getComputedStyle(reserv._html, null); calendar._updateReservations(false);
if (parseInt(style.width, 10) < 15 || parseInt(style.height, 10) < 15 || parseInt(style.top, 10) === 0) {
this.get_active_calendar()._updateReservation(reserv);
}
}
}.bind(this, active_calendar), 200); }.bind(this, active_calendar), 200);
} }
}, },

View File

@@ -82,7 +82,7 @@ function HotelCalendar(/*String*/querySelector, /*Dictionary*/options, /*List*/p
this._reservationsMap = {}; // Store Reservations Mapped by Room for Search Purposes this._reservationsMap = {}; // Store Reservations Mapped by Room for Search Purposes
this._modeSwap = HotelCalendar.MODE.NONE; // Store Swap Mode this._modeSwap = HotelCalendar.MODE.NONE; // Store Swap Mode
this._selectionMode = HotelCalendar.MODE.NONE; this._selectionMode = HotelCalendar.MODE.NONE;
this._endDate = this.options.startDate.clone().add(this.options.days, 'd'); // Store End Calendar Day this._endDate = this.options.startDate.clone().add(this.options.days+1, 'd'); // Store End Calendar Day
this._tableCreated = false; // Store Flag to Know Calendar Creation this._tableCreated = false; // Store Flag to Know Calendar Creation
this._cellSelection = {start:false, end:false, current:false}; // Store Info About Selected Cells this._cellSelection = {start:false, end:false, current:false}; // Store Info About Selected Cells
this._lazyModeReservationsSelection = false; // Store Info About Timer for Selection Action this._lazyModeReservationsSelection = false; // Store Info About Timer for Selection Action
@@ -152,7 +152,7 @@ HotelCalendar.prototype = {
this.options.orig_days = days; this.options.orig_days = days;
this.options.days = this.parseDays(days) + 1; this.options.days = this.parseDays(days) + 1;
} }
this._endDate = this.options.startDate.clone().add(this.options.days, 'd'); this._endDate = this.options.startDate.clone().add(this.options.days+1, 'd');
/*this.e.dispatchEvent(new CustomEvent( /*this.e.dispatchEvent(new CustomEvent(
'hcOnChangeDate', 'hcOnChangeDate',
@@ -865,7 +865,7 @@ HotelCalendar.prototype = {
if (!day) { return false; } if (!day) { return false; }
var num_rooms = this._roomCapacityTotal; var num_rooms = this._roomCapacityTotal;
num_rooms -= _.reduce(this.getReservationsByDay(day, true), function(memo, r){ return memo + (r.room && r.room.shared)?r.getTotalPersons(false):1; }, 0); num_rooms -= _.reduce(this.getReservationsByDay(day, true), function(memo, r){ return memo + ((r.room && r.room.shared)?r.getTotalPersons(false):1); }, 0);
return num_rooms; return num_rooms;
}, },
@@ -2382,6 +2382,10 @@ HotelCalendar.prototype = {
return true; return true;
}, },
getDates: function() {
return [this.options.startDate.clone(), this._endDate.clone()];
},
//==== EVENT FUNCTIONS //==== EVENT FUNCTIONS
_onInputChange: function(/*EventObject*/ev, /*HTMLObject*/elm) { _onInputChange: function(/*EventObject*/ev, /*HTMLObject*/elm) {
//var parentCell = this.edtable.querySelector(`#${elm.dataset.hcalParentCell}`); //var parentCell = this.edtable.querySelector(`#${elm.dataset.hcalParentCell}`);

View File

@@ -43,10 +43,10 @@ class HotelFolio(models.Model):
info_grouped = [] info_grouped = []
for rline in self.room_lines: for rline in self.room_lines:
if (import_all or rline.to_send) and not rline.parent_reservation and rline.state == state and ((rline.state == 'cancelled' and not rline.channel_modified) or rline.state != 'cancelled'): if (import_all or rline.to_send) and not rline.parent_reservation and rline.state == state and ((rline.state == 'cancelled' and not rline.channel_modified) or rline.state != 'cancelled'):
dates = rline.get_real_checkin_checkout() dates = (rline.real_checkin, rline.real_checkout)
vals = { vals = {
'num': len( 'num': len(
self.room_lines.filtered(lambda r: r.get_real_checkin_checkout()[0] == dates[0] and r.get_real_checkin_checkout()[1] == dates[1] and r.room_type_id.id == rline.room_type_id.id and (r.to_send or import_all) and not r.parent_reservation and r.state == rline.state and ((r.state == 'cancelled' and not r.channel_modified) or r.state != 'cancelled')) self.room_lines.filtered(lambda r: r.real_checkin == dates[0] and r.real_checkout == dates[1] and r.room_type_id.id == rline.room_type_id.id and (r.to_send or import_all) and not r.parent_reservation and r.state == rline.state and ((r.state == 'cancelled' and not r.channel_modified) or r.state != 'cancelled'))
), ),
'room_type': { 'room_type': {
'id': rline.room_type_id.id, 'id': rline.room_type_id.id,