mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
Merge branch '11.0' of https://github.com/hootel/hootel into 11.0
This commit is contained in:
@@ -52,6 +52,7 @@ class BusHotelCalendar(models.TransientModel):
|
||||
'price_room_services_set': vals['price_room_services_set'],
|
||||
'amount_total': vals['pending_amount'] + vals['invoices_paid'],
|
||||
'real_dates': vals['real_dates'],
|
||||
'channel_type': vals['channel_type'],
|
||||
},
|
||||
'tooltip': {
|
||||
'folio_name': vals['folio_name'],
|
||||
|
||||
@@ -94,7 +94,9 @@ class HotelReservation(models.Model):
|
||||
'state': reserv['state'],
|
||||
'price_room_services_set': reserv['price_room_services_set'],
|
||||
'amount_total': reserv['amount_total'],
|
||||
'real_dates': [reserv['real_checkin'], reserv['real_checkout']]})
|
||||
'real_dates': [reserv['real_checkin'], reserv['real_checkout']],
|
||||
'channel_type': reserv['channel_type'],
|
||||
})
|
||||
json_reservation_tooltips.update({
|
||||
reserv['id']: {
|
||||
'folio_name': reserv['folio_name'],
|
||||
|
||||
@@ -376,6 +376,7 @@ var PMSCalendarController = AbstractController.extend({
|
||||
_assign_multi_calendar_events: function() {
|
||||
var self = this;
|
||||
this._multi_calendar.on_calendar('hcalOnSavePricelist', function(ev){
|
||||
document.getElementById("btn_save_changes").disabled = true;
|
||||
self.savePricelist(ev.detail.calendar_obj, ev.detail.pricelist_id, ev.detail.pricelist);
|
||||
});
|
||||
|
||||
|
||||
@@ -84,7 +84,9 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
|
||||
save_changes: function() {
|
||||
var oparams = this.get_values_to_save();
|
||||
this.trigger_up('onSaveChanges', oparams);
|
||||
if (oparams) {
|
||||
this.trigger_up('onSaveChanges', oparams);
|
||||
}
|
||||
},
|
||||
|
||||
resetSaveState: function() {
|
||||
@@ -138,6 +140,9 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
|
||||
// Sticky Header Days
|
||||
$('.o_content').scroll(this._on_scroll.bind(this));
|
||||
|
||||
// Initialize Save Button state to disable
|
||||
document.getElementById("btn_save_changes").disabled = true;
|
||||
},
|
||||
|
||||
setCalendarData: function (prices, restrictions, availability, count_reservations) {
|
||||
@@ -149,23 +154,19 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
var self = this;
|
||||
this._hcalendar.addEventListener('hcOnChangeDate', function(ev){
|
||||
var date_begin = moment(ev.detail.newDate);
|
||||
var days = self._hcalendar.getOptions('days')-1;
|
||||
var date_end = date_begin.clone().add(days, 'd');
|
||||
|
||||
var $dateTimePickerBegin = self.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = self.$el.find('#mpms-search #date_end');
|
||||
$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
|
||||
self.reload_hcalendar_management();
|
||||
});
|
||||
this._hcalendar.addEventListener('hcmOnInputChanged', function(ev){
|
||||
var btn_save = self.$el.find('#btn_save_changes');
|
||||
if (self._hcalendar.hasChangesToSave()) {
|
||||
btn_save.addClass('need-save');
|
||||
document.getElementById("btn_save_changes").disabled = false;
|
||||
} else {
|
||||
btn_save.removeClass('need-save');
|
||||
document.getElementById("btn_save_changes").disabled = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -250,94 +251,82 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
format : HotelConstants.L10N_DATE_MOMENT_FORMAT,
|
||||
//disabledHours: [0, 1, 2, 3, 4, 5, 6, 7, 8, 18, 19, 20, 21, 22, 23]
|
||||
};
|
||||
|
||||
var $dateTimePickerBegin = this.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = this.$el.find('#mpms-search #date_end');
|
||||
$dateTimePickerBegin.datetimepicker(DTPickerOptions);
|
||||
$dateTimePickerEnd.datetimepicker($.extend({}, DTPickerOptions, { 'useCurrent': false }));
|
||||
$dateTimePickerBegin.on("dp.change", function (e) {
|
||||
$dateTimePickerEnd.data("DateTimePicker").minDate(e.date.clone().add(3,'d'));
|
||||
$dateTimePickerEnd.data("DateTimePicker").maxDate(e.date.clone().add(2,'M'));
|
||||
$dateTimePickerBegin.data("DateTimePicker").hide(); // TODO: Odoo uses old datetimepicker version
|
||||
self.on_change_filter_date(e, true);
|
||||
});
|
||||
$dateTimePickerEnd.on("dp.change", function (e) {
|
||||
$dateTimePickerEnd.data("DateTimePicker").hide(); // TODO: Odoo uses old datetimepicker version
|
||||
self.on_change_filter_date(e, false);
|
||||
|
||||
var $dateEndDays = this.$el.find('#mpms-search #date_end_days');
|
||||
$dateEndDays.select2({
|
||||
data: [
|
||||
{id:7, text: '1w'},
|
||||
{id:12, text: '2w'},
|
||||
{id:21, text: '3w'},
|
||||
{id:'month', text: '1m'},
|
||||
{id:60, text: '2m'},
|
||||
{id:90, text: '3m'},
|
||||
],
|
||||
allowClear: true,
|
||||
minimumResultsForSearch: -1
|
||||
});
|
||||
|
||||
// var date_begin = moment().startOf('day');
|
||||
// var date_end = date_begin.clone().add(this._view_options['days'], 'd').endOf('day');
|
||||
// $dateTimePickerBegin.data("ignore_onchange", true);
|
||||
// $dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
// $dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
// this._last_dates = this.generate_params()['dates'];
|
||||
$dateEndDays.on("change", function (e) {
|
||||
self.on_change_filter_date();
|
||||
});
|
||||
|
||||
// View Events
|
||||
this.$el.find("#mpms-search #cal-pag-prev-plus").on('click', function(ev){
|
||||
// FIXME: Ugly repeated code. Change place.
|
||||
var $dateTimePickerBegin = self.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = self.$el.find('#mpms-search #date_end');
|
||||
//var days = moment($dateTimePickerBegin.data("DateTimePicker").date()).clone().local().daysInMonth();
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().subtract(14, 'd');
|
||||
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().subtract(14, 'd');
|
||||
$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
|
||||
self.on_change_filter_date(ev, true);
|
||||
ev.preventDefault();
|
||||
});
|
||||
this.$el.find("#mpms-search #cal-pag-prev").on('click', function(ev){
|
||||
// FIXME: Ugly repeated code. Change place.
|
||||
var $dateTimePickerBegin = self.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = self.$el.find('#mpms-search #date_end');
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().subtract(7, 'd');
|
||||
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().subtract(7, 'd');
|
||||
$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
|
||||
self.on_change_filter_date(ev, true);
|
||||
ev.preventDefault();
|
||||
});
|
||||
this.$el.find("#mpms-search #cal-pag-next-plus").on('click', function(ev){
|
||||
// FIXME: Ugly repeated code. Change place.
|
||||
var $dateTimePickerBegin = self.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = self.$el.find('#mpms-search #date_end');
|
||||
//var days = moment($dateTimePickerBegin.data("DateTimePicker").date()).clone().local().daysInMonth();
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().add(14, 'd');
|
||||
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().add(14, 'd');
|
||||
$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
|
||||
self.on_change_filter_date(ev, true);
|
||||
ev.preventDefault();
|
||||
});
|
||||
this.$el.find("#mpms-search #cal-pag-next").on('click', function(ev){
|
||||
// FIXME: Ugly repeated code. Change place.
|
||||
var $dateTimePickerBegin = self.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = self.$el.find('#mpms-search #date_end');
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().add(7, 'd');
|
||||
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().add(7, 'd');
|
||||
$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
|
||||
self.on_change_filter_date(ev, true);
|
||||
ev.preventDefault();
|
||||
});
|
||||
this.$el.find("#mpms-search #cal-pag-selector").on('click', function(ev){
|
||||
// FIXME: Ugly repeated code. Change place.
|
||||
var $dateTimePickerBegin = self.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = self.$el.find('#mpms-search #date_end');
|
||||
var date_begin = moment().startOf('day');
|
||||
var date_end = date_begin.clone().add(self._view_options['days'], 'd').endOf('day');
|
||||
$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
|
||||
self.on_change_filter_date(ev, true);
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
// Save Button
|
||||
this.$el.find("#btn_save_changes").on('click', function(ev){
|
||||
this.$el.find("#btn_save_changes").on('click', function(ev) {
|
||||
document.getElementById(this.id).disabled = true;
|
||||
self.save_changes();
|
||||
});
|
||||
|
||||
@@ -358,15 +347,15 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
} else {
|
||||
this._view_options['days'] = (this._view_options['days'] !== 'month')?parseInt(this._view_options['days']):date_begin.daysInMonth();
|
||||
}
|
||||
var date_end = date_begin.clone().add(this._view_options['days'], 'd').endOf('day');
|
||||
var $dateTimePickerBegin = this.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = this.$el.find('#mpms-search #date_end');
|
||||
//$dateTimePickerBegin.data("ignore_onchange", true);
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
//$dateTimePickerEnd.data("ignore_onchange", true);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
|
||||
this._last_dates = this.generate_params()['dates'];
|
||||
|
||||
var $dateTimePickerBegin = this.$el.find('#mpms-search #date_begin');
|
||||
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
|
||||
|
||||
var $dateEndDays = this.$el.find('#mpms-search #date_end_days');
|
||||
$dateEndDays.val('month');
|
||||
$dateEndDays.trigger('change');
|
||||
|
||||
this._last_dates = this.generate_params()['dates'];
|
||||
this.trigger_up('onLoadCalendar');
|
||||
},
|
||||
|
||||
@@ -374,25 +363,23 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
var self = this;
|
||||
isStartDate = isStartDate || false;
|
||||
var $dateTimePickerBegin = this.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = this.$el.find('#mpms-search #date_end');
|
||||
var $dateEndDays = this.$el.find('#mpms-search #date_end_days');
|
||||
|
||||
// FIXME: Hackish onchange ignore (Used when change dates from code)
|
||||
if ($dateTimePickerBegin.data("ignore_onchange") || $dateTimePickerEnd.data("ignore_onchange")) {
|
||||
if ($dateTimePickerBegin.data("ignore_onchange") || $dateEndDays.data("ignore_onchange")) {
|
||||
$dateTimePickerBegin.data("ignore_onchange", false);
|
||||
$dateTimePickerEnd.data("ignore_onchange", false)
|
||||
$dateEndDays.data("ignore_onchange", false);
|
||||
return true;
|
||||
}
|
||||
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().set({'hour': 0, 'minute': 0, 'second': 0}).clone();
|
||||
|
||||
if (this._hcalendar && date_begin) {
|
||||
if (isStartDate) {
|
||||
var ndate_end = date_begin.clone().add(this._view_options['days'], 'd');
|
||||
$dateTimePickerEnd.data("ignore_onchange", true);
|
||||
$dateTimePickerEnd.data("DateTimePicker").date(ndate_end.local());
|
||||
var days = $dateEndDays.val();
|
||||
if (days === 'month') {
|
||||
days = date_begin.daysInMonth();
|
||||
}
|
||||
|
||||
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().set({'hour': 23, 'minute': 59, 'second': 59}).clone();
|
||||
var date_end = date_begin.set({'hour': 23, 'minute': 59, 'second': 59}).clone().add(days, 'd');
|
||||
|
||||
this._check_unsaved_changes(function(){
|
||||
self._hcalendar.setStartDate(date_begin, self._hcalendar.getDateDiffDays(date_begin, date_end));
|
||||
@@ -411,11 +398,15 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
var restrictions = this.$el.find('#mpms-search #restriction_list').val();
|
||||
|
||||
var $dateTimePickerBegin = this.$el.find('#mpms-search #date_begin');
|
||||
var $dateTimePickerEnd = this.$el.find('#mpms-search #date_end');
|
||||
var $dateEndDays = this.$el.find('#mpms-search #date_end_days');
|
||||
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().set({'hour': 0, 'minute': 0, 'second': 0}).clone().utc().format(HotelConstants.ODOO_DATE_MOMENT_FORMAT);
|
||||
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().set({'hour': 23, 'minute': 59, 'second': 59}).clone().utc().format(HotelConstants.ODOO_DATE_MOMENT_FORMAT);
|
||||
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().set({'hour': 0, 'minute': 0, 'second': 0}).clone();
|
||||
|
||||
var days = $dateEndDays.val();
|
||||
if (days === 'month') {
|
||||
days = date_begin.daysInMonth();
|
||||
}
|
||||
var date_end = date_begin.set({'hour': 23, 'minute': 59, 'second': 59}).clone().add(days, 'd');
|
||||
return {
|
||||
'dates': [date_begin, date_end],
|
||||
'prices': prices,
|
||||
@@ -428,6 +419,7 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
var btn_save = this.$el.find("#btn_save_changes");
|
||||
if (!btn_save.hasClass('need-save')) {
|
||||
btn_save.removeClass('need-save');
|
||||
document.getElementById("btn_save_changes").disabled = true;
|
||||
fnCallback();
|
||||
return;
|
||||
}
|
||||
@@ -440,6 +432,7 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
classes: 'btn-primary',
|
||||
close: true,
|
||||
click: function() {
|
||||
document.getElementById("btn_save_changes").disabled = true;
|
||||
self.save_changes();
|
||||
fnCallback();
|
||||
}
|
||||
@@ -449,6 +442,7 @@ var HotelCalendarManagementView = AbstractRenderer.extend({
|
||||
close: true,
|
||||
click: function() {
|
||||
btn_save.removeClass('need-save');
|
||||
document.getElementById("btn_save_changes").disabled = true;
|
||||
fnCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1240,6 +1240,8 @@ HotelCalendar.prototype = {
|
||||
});
|
||||
}
|
||||
});
|
||||
// Initialize Save Button state to disable
|
||||
this.btnSaveChanges.disabled = true;
|
||||
cell.appendChild(this.btnSaveChanges);
|
||||
}
|
||||
//cell.setAttribute('class', 'col-xs-1 col-lg-1');
|
||||
@@ -2451,8 +2453,10 @@ HotelCalendar.prototype = {
|
||||
if (this.edivc.querySelector('.hcal-input-changed') !== null)
|
||||
{
|
||||
this.btnSaveChanges.classList.add('need-save');
|
||||
this.btnSaveChanges.disabled = false;
|
||||
} else {
|
||||
this.btnSaveChanges.classList.remove('need-save');
|
||||
this.btnSaveChanges.disabled = true;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -22,22 +22,27 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="filter-title">FROM</span><br/>
|
||||
<span class="filter-title">FROM</span>
|
||||
<div class="input-group date" id="date_begin">
|
||||
<input type="text" class="o_datepicker_input form-control" name="date_begin" required="required" />
|
||||
<span class="input-group-addon">
|
||||
<span class="fa fa-calendar"></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<span class="filter-title">TO</span><br/>
|
||||
<div class="input-group date" id="date_end">
|
||||
<input type="text" class="o_datepicker_input form-control" name="date_end" required="required" />
|
||||
<span class="input-group-addon">
|
||||
<span class="fa fa-calendar"></span>
|
||||
</span>
|
||||
</div>
|
||||
<span class="filter-title">RANGE</span>
|
||||
<div class="input-group date">
|
||||
<input id="date_end_days" required="required" class="form-control" />
|
||||
</div>
|
||||
<!-- <span class="filter-title">TO</span><br/>-->
|
||||
<!-- <div class="input-group date" id="date_end">-->
|
||||
<!-- <input type="text" class="o_datepicker_input form-control" name="date_end" required="required" />-->
|
||||
<!-- <span class="input-group-addon">-->
|
||||
<!-- <span class="fa fa-calendar"></span>-->
|
||||
<!-- </span>-->
|
||||
<!-- </div>-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -76,7 +76,7 @@ var PMSHotelCalendarController = PMSCalendarController.include({
|
||||
}
|
||||
else if (notif[1]['type'] === 'reservation') {
|
||||
var reserv = notif[1]['reservation'];
|
||||
if (reserv['external_id']) {
|
||||
if (reserv['channel_type'] == 'web') {
|
||||
if (notif[1]['action'] === 'create') {
|
||||
this._play_sound(this.SOUNDS.BOOK_NEW);
|
||||
} else if (notif[1]['action'] !== 'unlink' && reserv['state'] === 'cancelled') {
|
||||
|
||||
@@ -267,11 +267,11 @@ class ChannelBackend(models.Model):
|
||||
_logger.warning(msg)
|
||||
|
||||
email_values.update({'body_html': email_values['body_html'] + msg + '<br/>'})
|
||||
|
||||
if len(email_values['body_html']) > 0:
|
||||
template = self.env.ref('hotel_channel_connector.mail_template_hotel_availability_watchdog')
|
||||
email_values.update({'email_to': self._context['email_to']})
|
||||
template.send_mail(self.id, email_values=email_values)
|
||||
if 'email_to' in self._context:
|
||||
template = self.env.ref('hotel_channel_connector.mail_template_hotel_availability_watchdog')
|
||||
email_values.update({'email_to': self._context['email_to']})
|
||||
template.send_mail(self.id, email_values=email_values)
|
||||
# push availability on demand
|
||||
self.with_context({'show_notify': False}).push_availability()
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models, fields, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.addons import decimal_precision as dp
|
||||
from odoo.addons.queue_job.job import job
|
||||
@@ -26,7 +25,6 @@ class ChannelHotelRoomType(models.Model):
|
||||
def _default_availability(self):
|
||||
return max(min(self.default_quota, self.default_max_avail), 0)
|
||||
|
||||
|
||||
odoo_id = fields.Many2one(comodel_name='hotel.room.type',
|
||||
string='Room Type',
|
||||
required=True,
|
||||
@@ -139,6 +137,14 @@ class HotelRoomType(models.Model):
|
||||
for record in self:
|
||||
record.capacity = record.get_capacity()
|
||||
|
||||
@api.constrains('active')
|
||||
def _check_active(self):
|
||||
for record in self:
|
||||
if not record.active and record.total_rooms_count > 0:
|
||||
raise ValidationError(
|
||||
_("You can not archive a room type with active rooms.") + " " +
|
||||
_("Please, change the %s room(s) to other room type.") % str(record.total_rooms_count))
|
||||
|
||||
@api.multi
|
||||
def get_restrictions(self, date, restriction_plan_id):
|
||||
self.ensure_one()
|
||||
@@ -172,10 +178,14 @@ class HotelRoomType(models.Model):
|
||||
|
||||
@api.multi
|
||||
def disconnect_channel_bind_ids(self):
|
||||
channel_bind_ids = self.mapped('channel_bind_ids')
|
||||
msg = _("This function is not yet implemented.")
|
||||
msg += _(" The room type [%s] should be delete from the channel manager.") % channel_bind_ids.get_external_id
|
||||
raise UserError(msg)
|
||||
# TODO: multichannel rooms is not implemented
|
||||
self.channel_bind_ids.with_context({'connector_no_export': True}).unlink()
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'active' in vals and vals.get('active') is False:
|
||||
self.channel_bind_ids.unlink()
|
||||
return super().write(vals)
|
||||
|
||||
|
||||
class BindingHotelRoomTypeListener(Component):
|
||||
|
||||
@@ -53,6 +53,7 @@ class ChannelHotelRoomTypeRestriction(models.Model):
|
||||
importer = work.component(usage='hotel.room.type.restriction.importer')
|
||||
return importer.import_restriction_plans()
|
||||
|
||||
|
||||
class HotelRoomTypeRestriction(models.Model):
|
||||
_inherit = 'hotel.room.type.restriction'
|
||||
|
||||
@@ -99,10 +100,15 @@ class HotelRoomTypeRestriction(models.Model):
|
||||
|
||||
@api.multi
|
||||
def disconnect_channel_bind_ids(self):
|
||||
channel_bind_ids = self.mapped('channel_bind_ids')
|
||||
msg = _("This function is not yet implemented.")
|
||||
msg += _(" The restriction plan [%s] should be delete from the channel manager.") % channel_bind_ids.get_external_id
|
||||
raise UserError(msg)
|
||||
# TODO: multichannel rooms is not implemented
|
||||
self.channel_bind_ids.with_context({'connector_no_export': True}).unlink()
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'active' in vals and vals.get('active') is False:
|
||||
self.channel_bind_ids.unlink()
|
||||
return super().write(vals)
|
||||
|
||||
|
||||
class BindingHotelRoomTypeListener(Component):
|
||||
_name = 'binding.hotel.room.type.restriction.listener'
|
||||
@@ -115,6 +121,7 @@ class BindingHotelRoomTypeListener(Component):
|
||||
for binding in record.channel_bind_ids:
|
||||
binding.update_plan_name()
|
||||
|
||||
|
||||
class ChannelBindingHotelRoomTypeRestrictionListener(Component):
|
||||
_name = 'channel.binding.hotel.room.type.restriction.listener'
|
||||
_inherit = 'base.connector.listener'
|
||||
|
||||
@@ -61,7 +61,7 @@ class HotelRoom(models.Model):
|
||||
|
||||
channel_availability = self.env['channel.hotel.room.type.availability'].search([
|
||||
('room_type_id', '=', item['old_room_type_id']),
|
||||
('channel_avail', '>=', old_room_type_total_rooms_count),
|
||||
('channel_avail', '>', old_room_type_total_rooms_count),
|
||||
('date', '>=', _today)
|
||||
], order='date asc') or False
|
||||
if channel_availability:
|
||||
@@ -119,6 +119,11 @@ class HotelRoom(models.Model):
|
||||
checkout=dto,
|
||||
backend_id=new_channel_room_type.backend_id.id,
|
||||
room_type_id=item['new_room_type_id'], )
|
||||
# TODO: channel_backend MUST be the same for both room types
|
||||
channel_backend = self.env['channel.hotel.room.type'].search([
|
||||
('odoo_id', '=', vals.get('room_type_id'))
|
||||
]).backend_id
|
||||
channel_backend.channel_availability_watchdog()
|
||||
else:
|
||||
res = super().write(vals)
|
||||
return res
|
||||
|
||||
@@ -82,7 +82,6 @@ class ProductPricelist(models.Model):
|
||||
inverse_name='odoo_id',
|
||||
string='Hotel Channel Connector Bindings')
|
||||
|
||||
|
||||
pricelist_type = fields.Selection(selection_add=[
|
||||
('virtual', 'Virtual Plan'),
|
||||
])
|
||||
@@ -104,7 +103,6 @@ class ProductPricelist(models.Model):
|
||||
for item in record.item_ids):
|
||||
record.is_virtual_plan = False
|
||||
|
||||
|
||||
@api.multi
|
||||
@api.depends('name')
|
||||
def name_get(self):
|
||||
@@ -144,10 +142,14 @@ class ProductPricelist(models.Model):
|
||||
|
||||
@api.multi
|
||||
def disconnect_channel_bind_ids(self):
|
||||
channel_bind_ids = self.mapped('channel_bind_ids')
|
||||
msg = _("This function is not yet implemented.")
|
||||
msg += _(" The pricelist [%s] should be delete from the channel manager.") % channel_bind_ids.get_external_id
|
||||
raise UserError(msg)
|
||||
# TODO: multichannel rooms is not implemented
|
||||
self.channel_bind_ids.with_context({'connector_no_export': True}).unlink()
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'active' in vals and vals.get('active') is False:
|
||||
self.channel_bind_ids.unlink()
|
||||
return super().write(vals)
|
||||
|
||||
|
||||
class BindingProductPricelistListener(Component):
|
||||
|
||||
@@ -5,20 +5,39 @@
|
||||
<field name="model">hotel.room.type.restriction</field>
|
||||
<field name="inherit_id" ref="hotel.room_type_restriction_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//form/sheet" position="inside">
|
||||
<field name="channel_bind_ids" invisible="1" />
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[@name='toggle_active']" position="replace">
|
||||
<!-- custom message for warning when archiving a channel restriction plan with binding -->
|
||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"
|
||||
confirm="Archive a restriction plan will automatically delete the restriction plan in the Channel.
|
||||
Do you want to proceed?"
|
||||
attrs="{'invisible': [('channel_bind_ids', '=', [])]}">
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
<!-- default message for archiving a channel restriction plan without binding -->
|
||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"
|
||||
attrs="{'invisible': [('channel_bind_ids','!=', [])]}">
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[@name='toggle_active']" position="before">
|
||||
<field name="channel_bind_ids" invisible="1" />
|
||||
<button name="open_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-toggle-off" string="Connect to Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','!=', [])]}"
|
||||
attrs="{'invisible': ['|', ('channel_bind_ids','!=', []), ('active','=', False) ]}"
|
||||
/>
|
||||
<button name="open_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-cloud-upload" string="Synchronize to Channel"
|
||||
class="oe_stat_button" icon="fa fa-gears" string="Configure Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','=', [])]}"
|
||||
/>
|
||||
<button name="disconnect_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-toggle-on" string="Disconnect from Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','=', [])]}"
|
||||
confirm="Disconnecting will automatically delete the restriction plan in the Channel. Do you want to proceed?"
|
||||
confirm="Disconnecting will unbind the restriction plan from the Channel but it will not be deleted.
|
||||
Do you want to proceed?"
|
||||
/>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
@@ -5,20 +5,43 @@
|
||||
<field name="model">hotel.room.type</field>
|
||||
<field name="inherit_id" ref="hotel.hotel_room_type_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//form/sheet/notebook" position="inside">
|
||||
<page string="Channel Bindings" invisible="1">
|
||||
<field name="channel_bind_ids" />
|
||||
</page>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[@name='toggle_active']" position="replace">
|
||||
<!-- custom message for warning when archiving a channel room type with binding -->
|
||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"
|
||||
confirm="Archive a room type will automatically delete the room type in the Channel.
|
||||
Ensure yourself no reservations are binded to this room type from today and hereafter.
|
||||
Do you want to proceed?"
|
||||
attrs="{'invisible': [('channel_bind_ids', '=', [])]}">
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
<!-- default message for archiving a channel room type without binding -->
|
||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"
|
||||
attrs="{'invisible': [('channel_bind_ids','!=', [])]}">
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[@name='toggle_active']" position="before">
|
||||
<field name="channel_bind_ids" invisible="1" />
|
||||
<button name="open_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-toggle-off" string="Connect to Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','!=', [])]}"
|
||||
attrs="{'invisible': ['|', ('channel_bind_ids','!=', []), ('active','=', False) ]}"
|
||||
/>
|
||||
<button name="open_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-cloud-upload" string="Synchronize to Channel"
|
||||
class="oe_stat_button" icon="fa fa-gears" string="Configure Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','=', [])]}"
|
||||
/>
|
||||
<button name="disconnect_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-toggle-on" string="Disconnect from Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','=', [])]}"
|
||||
confirm="Disconnecting will automatically delete the room type in the Channel. Do you want to proceed?"
|
||||
confirm="Disconnecting will unbind the room type from the Channel but it will not be deleted.
|
||||
Ensure yourself no reservations are binded to this room type from today and hereafter.
|
||||
Do you want to proceed?"
|
||||
/>
|
||||
</xpath>
|
||||
|
||||
|
||||
@@ -5,20 +5,39 @@
|
||||
<field name="model">product.pricelist</field>
|
||||
<field name="inherit_id" ref="product.product_pricelist_view" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//form/sheet" position="inside">
|
||||
<field name="channel_bind_ids" invisible="1" />
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[@name='toggle_active']" position="replace">
|
||||
<!-- custom message for warning when archiving a channel pricelist plan with binding -->
|
||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"
|
||||
confirm="Archive a pricelist plan will automatically delete the pricelist plan in the Channel.
|
||||
Do you want to proceed?"
|
||||
attrs="{'invisible': [('channel_bind_ids', '=', [])]}">
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
<!-- default message for archiving a channel pricelist plan without binding -->
|
||||
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"
|
||||
attrs="{'invisible': [('channel_bind_ids','!=', [])]}">
|
||||
<field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[@name='toggle_active']" position="before">
|
||||
<field name="channel_bind_ids" invisible="1" />
|
||||
<button name="open_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-toggle-off" string="Connect to Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','!=', [])]}"
|
||||
attrs="{'invisible': ['|', ('channel_bind_ids','!=', []), ('active','=', False) ]}"
|
||||
/>
|
||||
<button name="open_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-cloud-upload" string="Synchronize to Channel"
|
||||
class="oe_stat_button" icon="fa fa-gears" string="Configure Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','=', [])]}"
|
||||
/>
|
||||
<button name="disconnect_channel_bind_ids" type="object"
|
||||
class="oe_stat_button" icon="fa-toggle-on" string="Disconnect from Channel"
|
||||
attrs="{'invisible': [('channel_bind_ids','=', [])]}"
|
||||
confirm="Disconnecting will automatically delete the pricelist in the Channel. Do you want to proceed?"
|
||||
confirm="Disconnecting will unbind the pricelist plan from the Channel but it will not be deleted.
|
||||
Do you want to proceed?"
|
||||
/>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.core import ChannelConnectorError
|
||||
from odoo import api
|
||||
from odoo import api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class HotelRoomTypeDeleter(Component):
|
||||
@@ -18,3 +19,4 @@ class HotelRoomTypeDeleter(Component):
|
||||
section='room',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']) + ". " + _(str(err)))
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.core import ChannelConnectorError
|
||||
from odoo import api, fields
|
||||
from odoo import api, fields, _
|
||||
from odoo.exceptions import AccessError, UserError, ValidationError
|
||||
|
||||
|
||||
class HotelRoomTypeExporter(Component):
|
||||
@@ -44,6 +45,7 @@ class HotelRoomTypeExporter(Component):
|
||||
section='room',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
|
||||
@api.model
|
||||
def create_room(self, binding):
|
||||
@@ -78,6 +80,7 @@ class HotelRoomTypeExporter(Component):
|
||||
section='room',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
else:
|
||||
binding.with_context({
|
||||
'connector_no_export': True,
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.core import ChannelConnectorError
|
||||
from odoo import api
|
||||
from odoo import api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class HotelRoomTypeRestrictionDeleter(Component):
|
||||
@@ -18,3 +19,4 @@ class HotelRoomTypeRestrictionDeleter(Component):
|
||||
section='restriction',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']) + ". " + _(str(err)))
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.core import ChannelConnectorError
|
||||
from odoo import api, fields
|
||||
from odoo import api, fields, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class HotelRoomTypeRestrictionExporter(Component):
|
||||
@@ -23,6 +24,7 @@ class HotelRoomTypeRestrictionExporter(Component):
|
||||
section='restriction',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
|
||||
@api.model
|
||||
def create_rplan(self, binding):
|
||||
@@ -33,5 +35,6 @@ class HotelRoomTypeRestrictionExporter(Component):
|
||||
section='restriction',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
else:
|
||||
self.binder.bind(external_id, binding)
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.core import ChannelConnectorError
|
||||
from odoo import api
|
||||
from odoo import api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ProductPricelistDeleter(Component):
|
||||
@@ -18,3 +19,4 @@ class ProductPricelistDeleter(Component):
|
||||
section='pricelist',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']) + ". " + _(str(err)))
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.core import ChannelConnectorError
|
||||
from odoo import api, _, fields
|
||||
from odoo import api, fields, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ProductPricelistExporter(Component):
|
||||
@@ -23,6 +24,7 @@ class ProductPricelistExporter(Component):
|
||||
section='pricelist',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
|
||||
@api.model
|
||||
def create_plan(self, binding):
|
||||
@@ -33,6 +35,7 @@ class ProductPricelistExporter(Component):
|
||||
section='pricelist',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
else:
|
||||
binding.external_id = external_id
|
||||
self.binder.bind(external_id, binding)
|
||||
@@ -67,6 +70,7 @@ class ProductPricelistExporter(Component):
|
||||
section='pricelist',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
else:
|
||||
binding.external_id = external_id
|
||||
self.binder.bind(external_id, binding)
|
||||
@@ -102,3 +106,4 @@ class ProductPricelistExporter(Component):
|
||||
section='pricelist',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
raise ValidationError(_(err.data['message']))
|
||||
|
||||
@@ -564,6 +564,7 @@ class Data_Bi(models.Model):
|
||||
precio_comision = inv_percent(
|
||||
precio_neto, expedia_rate[1]) - precio_neto
|
||||
precio_calculo = precio_neto + precio_comision
|
||||
precio_neto -= precio_comision
|
||||
# iva "interno" de expedia.....
|
||||
precio_iva2 = (precio_calculo*1.1) - precio_calculo
|
||||
precio_calculo += precio_iva2
|
||||
|
||||
@@ -20,12 +20,11 @@ class HotelFolio(models.Model):
|
||||
if not stay.get('ReservationCode'):
|
||||
reservation_obj = self.env['hotel.reservation']
|
||||
vals = {
|
||||
'checkin': datetime.strptime(
|
||||
stay["Arrival"], DEFAULT_ROOMMATIK_DATE_FORMAT).date(),
|
||||
'checkout': datetime.strptime(
|
||||
stay["Departure"], DEFAULT_ROOMMATIK_DATE_FORMAT).date(),
|
||||
'checkin': stay["Arrival"],
|
||||
'checkout': stay["Departure"],
|
||||
'adults': stay['Adults'],
|
||||
'room_type_id': stay['RoomType'],
|
||||
'arrival_hour': stay['Arrival_hour'],
|
||||
'room_type_id': stay['RoomType']['Id'],
|
||||
'partner_id': stay["Customers"][0]["Id"]
|
||||
}
|
||||
reservation_rm = reservation_obj.create(vals)
|
||||
@@ -42,11 +41,9 @@ class HotelFolio(models.Model):
|
||||
checkin_partner_val = {
|
||||
'folio_id': reservation_rm.folio_id.id,
|
||||
'reservation_id': reservation_rm.id,
|
||||
'enter_date': datetime.strptime(
|
||||
stay["Arrival"], DEFAULT_ROOMMATIK_DATE_FORMAT).date(),
|
||||
'exit_date': datetime.strptime(
|
||||
stay["Departure"], DEFAULT_ROOMMATIK_DATE_FORMAT).date(),
|
||||
'partner_id': room_partner["Customer"]["Id"],
|
||||
'partner_id': room_partner["Id"],
|
||||
'enter_date': stay["Arrival"],
|
||||
'exit_date': stay["Departure"],
|
||||
}
|
||||
try:
|
||||
record = self.env['hotel.checkin.partner'].create(
|
||||
|
||||
Reference in New Issue
Block a user