diff --git a/hotel_calendar/__manifest__.py b/hotel_calendar/__manifest__.py
index 5a0b0ec24..e8577a3db 100644
--- a/hotel_calendar/__manifest__.py
+++ b/hotel_calendar/__manifest__.py
@@ -28,6 +28,7 @@
'views/room_pricelist_cached_views.xml',
'views/hotel_reservation_views.xml',
'views/hotel_calendar_management_views.xml',
+ 'views/hotel_calendar_views.xml',
'data/menus.xml',
'security/ir.model.access.csv',
],
diff --git a/hotel_calendar/data/menus.xml b/hotel_calendar/data/menus.xml
index 1c440156d..6ef1e3d96 100644
--- a/hotel_calendar/data/menus.xml
+++ b/hotel_calendar/data/menus.xml
@@ -25,4 +25,9 @@
+
+
diff --git a/hotel_calendar/models/__init__.py b/hotel_calendar/models/__init__.py
index ab6021fe4..7aa6dfff6 100644
--- a/hotel_calendar/models/__init__.py
+++ b/hotel_calendar/models/__init__.py
@@ -1,5 +1,6 @@
# Copyright 2018 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from . import hotel_calendar
from . import bus_hotel_calendar
from . import room_pricelist_cached
from . import hotel_calendar_management
diff --git a/hotel_calendar/models/hotel_calendar.py b/hotel_calendar/models/hotel_calendar.py
new file mode 100644
index 000000000..6adfdea37
--- /dev/null
+++ b/hotel_calendar/models/hotel_calendar.py
@@ -0,0 +1,15 @@
+# Copyright 2018 Alexandre Díaz
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import models, api, _, fields
+from odoo.exceptions import ValidationError
+
+
+class HotelCalendar(models.Model):
+ _name = 'hotel.calendar'
+
+ name = fields.Char('Name', required=True)
+ segmentation_ids = fields.Many2many('hotel.room.type.class', string='Segmentation')
+ location_ids = fields.Many2many('hotel.floor', string='Location')
+ amenity_ids = fields.Many2many('hotel.amenity', string='Amenity')
+ room_type_ids = fields.Many2many('hotel.room.type', string='Room Type')
diff --git a/hotel_calendar/models/hotel_calendar_management.py b/hotel_calendar/models/hotel_calendar_management.py
index 2ee906533..cfbf50f47 100644
--- a/hotel_calendar/models/hotel_calendar_management.py
+++ b/hotel_calendar/models/hotel_calendar_management.py
@@ -122,13 +122,13 @@ class HotelCalendarManagement(models.TransientModel):
def _hcalendar_room_json_data(self, rooms):
json_data = []
for room in rooms:
- json_data.append((
- room.id,
- room.name,
- room.get_capacity(),
- room.list_price,
- room.total_rooms_count,
- ))
+ json_data.append({
+ 'id': room.id,
+ 'name': room.name,
+ 'capacity': room.get_capacity(),
+ 'price': room.list_price,
+ 'total_rooms': room.total_rooms_count,
+ })
return json_data
@api.model
diff --git a/hotel_calendar/models/inherited_hotel_reservation.py b/hotel_calendar/models/inherited_hotel_reservation.py
index cb2baecc9..b7d2c2e85 100644
--- a/hotel_calendar/models/inherited_hotel_reservation.py
+++ b/hotel_calendar/models/inherited_hotel_reservation.py
@@ -64,19 +64,20 @@ class HotelReservation(models.Model):
pricelist_id = int(pricelist_id)
json_rooms = []
for room in rooms:
- json_rooms.append((
- room.id,
- room.name,
- room.capacity,
- '', # Reserved for type code
- room.shared_room,
- room.room_type_id
- and ['pricelist', room.room_type_id.id, pricelist_id,
- room.room_type_id.name]
- or 0,
- room.room_type_id.name,
- room.room_type_id.id,
- room.floor_id.id))
+ json_rooms.append({
+ 'id': room.id,
+ 'name': room.name,
+ 'capacity': room.capacity,
+ 'class_id': room.room_type_id.class_id.id,
+ 'shared': room.shared_room,
+ 'price': room.room_type_id
+ and ['pricelist', room.room_type_id.id, pricelist_id,
+ room.room_type_id.name] or 0,
+ 'room_type_name': room.room_type_id.name,
+ 'room_type_id': room.room_type_id.id,
+ 'floor_id': room.floor_id.id,
+ 'amentity_ids': room.room_type_id.room_amenity_ids.ids,
+ })
return json_rooms
@api.model
diff --git a/hotel_calendar/models/inherited_hotel_room_type_restriction_item.py b/hotel_calendar/models/inherited_hotel_room_type_restriction_item.py
index 8e9f6b85e..cfcde6493 100644
--- a/hotel_calendar/models/inherited_hotel_room_type_restriction_item.py
+++ b/hotel_calendar/models/inherited_hotel_room_type_restriction_item.py
@@ -33,17 +33,9 @@ class HotelRoomTypeResrtrictionItem(models.Model):
@api.multi
def write(self, vals):
- restrictions_default_id = self.env['ir.default'].sudo().get(
- 'res.config.settings', 'default_restriction_id')
- if restrictions_default_id:
- restrictions_default_id = int(restrictions_default_id)
ret_vals = super(HotelRoomTypeResrtrictionItem, self).write(vals)
-
bus_hotel_calendar_obj = self.env['bus.hotel.calendar']
for record in self:
- if record.restriction_id.id != restrictions_default_id or \
- record.applied_on != '0_room_type':
- continue
bus_hotel_calendar_obj.send_restriction_notification({
'restriction_id': record.restriction_id.id,
'date': record.date,
diff --git a/hotel_calendar/security/ir.model.access.csv b/hotel_calendar/security/ir.model.access.csv
index 95627661a..66ba9fac2 100644
--- a/hotel_calendar/security/ir.model.access.csv
+++ b/hotel_calendar/security/ir.model.access.csv
@@ -3,3 +3,4 @@ access_room_price_cache_user,hotel_calendar.model_room_pricelist_cached_user,hot
access_room_price_cache_call,hotel_calendar.model_room_pricelist_cached_call,hotel_calendar.model_room_pricelist_cached,hotel.group_hotel_call,1,1,1,1
access_hotel_product_pricelist_item_call,hotel_calendar.pricelist_item_call,hotel_calendar.model_product_pricelist_item,hotel.group_hotel_call,1,1,1,1
access_hotel_product_pricelist_item_user,hotel_calendar.pricelist_item_use,hotel_calendar.model_product_pricelist_item,hotel.group_hotel_user,1,1,1,1
+access_hotel_calendar,access_hotel_calendar,model_hotel_calendar,base.group_user,1,0,0,0
diff --git a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js
index dcb1e8266..4dd69b277 100644
--- a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js
+++ b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js
@@ -110,18 +110,19 @@ var PMSCalendarController = AbstractController.extend({
var rooms = [];
for (var r of results['rooms']) {
var nroom = new HRoom(
- r[0], // Id
- r[1], // Name
- r[2], // Capacity
- r[3], // Category
- r[4], // Shared Room
- r[5] // Price
+ r['id'],
+ r['name'],
+ r['capacity'],
+ r['class_id'],
+ r['shared'],
+ r['price']
);
nroom.addUserData({
- 'room_type_name': r[6],
- 'room_type_id': r[7],
- 'floor_id': r[8],
- 'amenities': r[9]
+ 'room_type_name': r['room_type_name'],
+ 'room_type_id': r['room_type_id'],
+ 'floor_id': r['floor_id'],
+ 'amenities': r['amenity_ids'],
+ 'class_id': r['class_id']
});
rooms.push(nroom);
}
@@ -236,10 +237,10 @@ var PMSCalendarController = AbstractController.extend({
_onLoadViewFilters: function (ev) {
var self = this;
$.when(
- this.model.get_room_types(),
+ this.model.get_room_type_class(),
this.model.get_floors(),
this.model.get_amenities(),
- this.model.get_rooms()
+ this.model.get_room_types()
).then(function(a1, a2, a3, a4){
self.renderer.loadViewFilters(a1, a2, a3, a4);
});
diff --git a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js
index 9b59fb25f..095d4daf3 100644
--- a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js
+++ b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js
@@ -79,9 +79,9 @@ return AbstractModel.extend({
context: Session.user_context,
});
},
- get_rooms: function() {
+ get_room_type_class: function() {
return this._rpc({
- model: 'hotel.room.type',
+ model: 'hotel.room.type.class',
method: 'search_read',
args: [false, ['id','name']],
context: Session.user_context,
diff --git a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js
index 5675f894d..b9b96b69b 100644
--- a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js
+++ b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js
@@ -30,6 +30,7 @@ var HotelCalendarView = AbstractRenderer.extend({
_reserv_tooltips: {},
_days_tooltips: [],
_last_dates: [false, false],
+ _hcalendars: [],
/** VIEW METHODS **/
@@ -771,7 +772,7 @@ var HotelCalendarView = AbstractRenderer.extend({
var virtual = _.map(this.$el.find('#pms-search #virtual_list').val(), function(item){ return +item; });
var domain = [];
if (category && category.length > 0) {
- domain.push(['categ_id', 'in', category]);
+ domain.push(['class_id', 'in', category]);
}
if (floor && floor.length > 0) {
domain.push(['floor_id', 'in', floor]);
diff --git a/hotel_calendar/static/src/js/views/calendar_management/hotel_calendar_management_controller.js b/hotel_calendar/static/src/js/views/calendar_management/hotel_calendar_management_controller.js
index 17b33d88c..dab9aec38 100644
--- a/hotel_calendar/static/src/js/views/calendar_management/hotel_calendar_management_controller.js
+++ b/hotel_calendar/static/src/js/views/calendar_management/hotel_calendar_management_controller.js
@@ -89,10 +89,10 @@ var MPMSCalendarController = AbstractController.extend({
var rooms = [];
for (var r of results['rooms']) {
var nroom = new HRoomType(
- r[0], // Id
- r[1], // Name
- r[2], // Capacity
- r[3], // Price
+ r['id'],
+ r['name'],
+ r['capacity'],
+ r['price'],
);
rooms.push(nroom);
}
diff --git a/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js b/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js
index c7c260b72..ccad0a273 100644
--- a/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js
+++ b/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js
@@ -41,23 +41,23 @@ function HotelCalendar(/*String*/querySelector, /*Dictionary*/options, /*List*/p
};
/** Options **/
- options = options || {};
- this.options = {
- startDate: ((options.startDate && HotelCalendar.toMomentUTC(options.startDate)) || moment(new Date()).utc()).subtract('1', 'd'),
- days: (options.days || ((options.startDate && HotelCalendar.toMomentUTC(options.startDate)) || moment(new Date())).clone().local().daysInMonth()),
- rooms: options.rooms || [],
- allowInvalidActions: options.allowInvalidActions || false,
- assistedMovement: options.assistedMovement || false,
- endOfWeek: options.endOfWeek || 6,
- endOfWeekOffset: options.endOfWeekOffset || 0,
- divideRoomsByCapacity: options.divideRoomsByCapacity || false,
- currencySymbol: options.currencySymbol || '€',
- showPricelist: options.showPricelist || false,
- showAvailability: options.showAvailability || false,
- showNumRooms: options.showNumRooms || 0,
- paginatorStepsMin: options.paginatorAdv || 1,
- paginatorStepsMax: options.paginatorAdv || 15,
- };
+ this.options = _.extend({
+ startDate: moment(new Date()).utc(),
+ days: moment(new Date()).local().daysInMonth(),
+ rooms: [],
+ allowInvalidActions: false,
+ assistedMovement: false,
+ endOfWeek: 6,
+ endOfWeekOffset: 0,
+ divideRoomsByCapacity: false,
+ currencySymbol: '€',
+ showPricelist: false,
+ showAvailability: false,
+ showNumRooms: 0,
+ paginatorStepsMin: 1,
+ paginatorStepsMax: 15,
+ }, options);
+ this.options.startDate.subtract('1', 'd');
// Check correct values
if (this.options.rooms.length > 0 && !(this.options.rooms[0] instanceof HRoom)) {
@@ -104,14 +104,15 @@ HotelCalendar.prototype = {
//==== CALENDAR
setStartDate: function(/*String,MomentObject*/date, /*Int?*/days, /*Bool*/fullUpdate, /*Functions*/callback) {
if (moment.isMoment(date)) {
- this.options.startDate = date.subtract('1','d');
+ this.options.startDate = date;
} else if (typeof date === 'string'){
- this.options.startDate = HotelCalendar.toMomentUTC(date).subtract('1','d');
+ this.options.startDate = HotelCalendar.toMomentUTC(date);
} else {
console.warn("[Hotel Calendar][setStartDate] Invalid date format!");
return;
}
+ this.options.startDate.subtract('1','d');
if (typeof days !== 'undefined') {
this.options.days = days;
}
diff --git a/hotel_calendar/views/actions.xml b/hotel_calendar/views/actions.xml
index a60864446..2dd031c3b 100644
--- a/hotel_calendar/views/actions.xml
+++ b/hotel_calendar/views/actions.xml
@@ -24,4 +24,11 @@
tree,form
+
+ Hotel Calendar
+ hotel.calendar
+ form
+ tree,form
+
+
diff --git a/hotel_calendar/views/hotel_calendar_views.xml b/hotel_calendar/views/hotel_calendar_views.xml
new file mode 100644
index 000000000..113ae062a
--- /dev/null
+++ b/hotel_calendar/views/hotel_calendar_views.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ hotel.calendar.form
+ hotel.calendar
+
+
+
+
+
+
+
+ hotel.calendar.tree
+ hotel.calendar
+
+
+
+
+
+
+
+
diff --git a/hotel_calendar_channel_connector/views/hotel_reservation.xml b/hotel_calendar_channel_connector/views/hotel_reservation.xml
index 13cf82c6b..99aa93d4a 100644
--- a/hotel_calendar_channel_connector/views/hotel_reservation.xml
+++ b/hotel_calendar_channel_connector/views/hotel_reservation.xml
@@ -73,8 +73,7 @@
+ attrs="{'invisible':[('to_read','=', False)]}" />
diff --git a/hotel_channel_connector/models/hotel_reservation/common.py b/hotel_channel_connector/models/hotel_reservation/common.py
index ea3072fd5..b02e04cf8 100644
--- a/hotel_channel_connector/models/hotel_reservation/common.py
+++ b/hotel_channel_connector/models/hotel_reservation/common.py
@@ -113,8 +113,7 @@ class ChannelHotelReservation(models.Model):
def unlink(self):
vals = []
for record in self:
- if any(record.channel_bind_ids) and record.channel_bind_ids[0].external_id \
- and not record.parent_reservation:
+ if record.is_from_ota and self._context.get('ota_limits', True):
raise UserError(_("You can't delete OTA's reservations"))
vals.append({
'checkin': record.checkin,
@@ -140,26 +139,28 @@ class HotelReservation(models.Model):
user = self.env['res.users'].browse(self.env.uid)
record.able_to_modify_channel = user.has_group('base.group_system')
- @api.depends('channel_type', 'channel_bind_ids.ota_id')
- def _get_origin_sale(self):
- for record in self:
- if not record.channel_type:
- record.channel_type = 'door'
-
- if record.channel_type == 'web' and any(record.channel_bind_ids) and \
- record.channel_bind_ids[0].ota_id:
- record.origin_sale = record.channel_bind_ids[0].ota_id.name
- else:
- record.origin_sale = dict(
- self.fields_get(allfields=['channel_type'])['channel_type']['selection']
- )[record.channel_type]
+ # TODO: Dario v2
+ # @api.depends('channel_type', 'channel_bind_ids.ota_id')
+ # def _get_origin_sale(self):
+ # for record in self:
+ # if not record.channel_type:
+ # record.channel_type = 'door'
+ #
+ # if record.channel_type == 'web' and any(record.channel_bind_ids) and \
+ # record.channel_bind_ids[0].ota_id:
+ # record.origin_sale = record.channel_bind_ids[0].ota_id.name
+ # else:
+ # record.origin_sale = dict(
+ # self.fields_get(allfields=['channel_type'])['channel_type']['selection']
+ # )[record.channel_type]
channel_bind_ids = fields.One2many(
comodel_name='channel.hotel.reservation',
inverse_name='odoo_id',
string='Hotel Channel Connector Bindings')
- origin_sale = fields.Char('Origin', compute=_get_origin_sale,
- store=True)
+ # TODO: Dario v2
+ # origin_sale = fields.Char('Origin', compute=_get_origin_sale,
+ # store=True)
is_from_ota = fields.Boolean('Is From OTA',
readonly=True,
old_name='wis_from_channel')
diff --git a/hotel_channel_connector/models/hotel_room_type/common.py b/hotel_channel_connector/models/hotel_room_type/common.py
index 5f3a13134..84252479c 100644
--- a/hotel_channel_connector/models/hotel_room_type/common.py
+++ b/hotel_channel_connector/models/hotel_room_type/common.py
@@ -113,10 +113,9 @@ class BindingHotelRoomTypeListener(Component):
@skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
def on_record_write(self, record, fields=None):
- if any(record.channel_bind_ids) and 'name' in fields or 'list_price' in fields or \
- 'room_ids' in fields:
- # FIXME: Supossed that only exists one channel connector per record
- record.channel_bind_ids[0].modify_room()
+ if 'name' in fields or 'list_price' in fields or 'room_ids' in fields:
+ for binding in record.channel_bind_ids:
+ binding.modify_room()
# @skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
# def on_record_create(self, record, fields=None):
diff --git a/hotel_channel_connector/models/hotel_room_type_restriction/common.py b/hotel_channel_connector/models/hotel_room_type_restriction/common.py
index c400bbfe6..64fc0fbed 100644
--- a/hotel_channel_connector/models/hotel_room_type_restriction/common.py
+++ b/hotel_channel_connector/models/hotel_room_type_restriction/common.py
@@ -68,13 +68,12 @@ class HotelRoomTypeRestriction(models.Model):
names = []
for name in org_names:
restriction_id = room_type_restriction_obj.browse(name[0])
- if any(restriction_id.channel_bind_ids) and \
- restriction_id.channel_bind_ids[0].external_id:
- names.append((
- name[0],
- '%s (%s Backend)' % (name[1],
- restriction_id.channel_bind_ids[0].backend_id.name),
- ))
+ new_name = name[1]
+ if any(restriction_id.channel_bind_ids):
+ for restriction_bind in restriction_id.channel_bind_ids:
+ if restriction_bind.external_id:
+ new_name += ' (%s Backend)' % restriction_bind.backend_id.name
+ names.append((name[0], new_name))
else:
names.append((name[0], name[1]))
return names
@@ -86,8 +85,9 @@ class BindingHotelRoomTypeListener(Component):
@skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
def on_record_write(self, record, fields=None):
- if any(record.channel_bind_ids) and 'name' in fields:
- record.channel_bind_ids[0].update_plan_name()
+ if 'name' in fields:
+ for binding in record.channel_bind_ids:
+ binding.update_plan_name()
class ChannelBindingHotelRoomTypeRestrictionListener(Component):
_name = 'channel.binding.hotel.room.type.restriction.listener'
diff --git a/hotel_channel_connector/models/hotel_room_type_restriction_item/common.py b/hotel_channel_connector/models/hotel_room_type_restriction_item/common.py
index cd7e8e82d..27f7f9d74 100644
--- a/hotel_channel_connector/models/hotel_room_type_restriction_item/common.py
+++ b/hotel_channel_connector/models/hotel_room_type_restriction_item/common.py
@@ -37,6 +37,7 @@ class ChannelHotelRoomTypeRestrictionItem(models.Model):
exporter = work.component(usage='hotel.room.type.restriction.item.exporter')
return exporter.push_restriction()
+
class HotelRoomTypeRestrictionItem(models.Model):
_inherit = 'hotel.room.type.restriction.item'
@@ -45,6 +46,7 @@ class HotelRoomTypeRestrictionItem(models.Model):
inverse_name='odoo_id',
string='Hotel Channel Connector Bindings')
+
class BindingHotelRoomTypeRestrictionItemListener(Component):
_name = 'binding.hotel.room.type.restriction.item.listener'
_inherit = 'base.connector.listener'
@@ -59,6 +61,24 @@ class BindingHotelRoomTypeRestrictionItemListener(Component):
if any(fields_checked):
record.channel_bind_ids.write({'channel_pushed': False})
+ @skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
+ def on_record_create(self, record, fields=None):
+ if not any(record.channel_bind_ids):
+ channel_hotel_room_type_rest_item_obj = self.env[
+ 'channel.hotel.room.type.restriction.item']
+ for restriction_bind in record.restriction_id.channel_bind_ids:
+ restriction_item_bind = channel_hotel_room_type_rest_item_obj.search([
+ ('odoo_id', '=', record.id),
+ ('backend_id', '=', restriction_bind.backend_id.id),
+ ])
+ if not restriction_item_bind:
+ channel_hotel_room_type_rest_item_obj.create({
+ 'odoo_id': record.id,
+ 'channel_pushed': False,
+ 'backend_id': restriction_bind.backend_id.id,
+ })
+
+
class ChannelBindingHotelRoomTypeRestrictionItemListener(Component):
_name = 'channel.binding.hotel.room.type.restriction.item.listener'
_inherit = 'base.connector.listener'
diff --git a/hotel_channel_connector/models/inherited_hotel_room_type_class.py b/hotel_channel_connector/models/inherited_hotel_room_type_class.py
new file mode 100644
index 000000000..fb04c4f7c
--- /dev/null
+++ b/hotel_channel_connector/models/inherited_hotel_room_type_class.py
@@ -0,0 +1,25 @@
+# Copyright 2018 Alexandre Díaz
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from openerp import models, fields, api, _
+from openerp.exceptions import ValidationError
+
+
+class HotelRoomTypeClass(models.Model):
+ _inherit = 'hotel.room.type.class'
+
+ _locked_codes = []
+
+ @api.multi
+ def write(self, vals):
+ for record in self:
+ if record.code_class in self._locked_codes:
+ raise ValidationError(_("Can't modify channel room type class"))
+ return super(HotelRoomTypeClass, self).write(vals)
+
+ @api.multi
+ def unlink(self):
+ for record in self:
+ if record.code_class in self._locked_codes:
+ raise ValidationError(_("Can't delete channel room type class"))
+ return super(HotelRoomTypeClass, self).unlink()
diff --git a/hotel_channel_connector/models/product_pricelist/common.py b/hotel_channel_connector/models/product_pricelist/common.py
index 7eb29085a..0b0e28224 100644
--- a/hotel_channel_connector/models/product_pricelist/common.py
+++ b/hotel_channel_connector/models/product_pricelist/common.py
@@ -68,14 +68,13 @@ class ProductPricelist(models.Model):
org_names = super(ProductPricelist, self).name_get()
names = []
for name in org_names:
- priclist_id = pricelist_obj.browse(name[0])
- if any(priclist_id.channel_bind_ids) and \
- priclist_id.channel_bind_ids[0].external_id:
- names.append((name[0], '%s (%s Backend)' % (
- name[1],
- priclist_id.channel_bind_ids[0].backend_id.name)))
- else:
- names.append((name[0], name[1]))
+ pricelist_id = pricelist_obj.browse(name[0])
+ new_name = name[1]
+ if any(pricelist_id.channel_bind_ids):
+ for pricelist_bind in pricelist_id.channel_bind_ids:
+ if pricelist_bind.external_id:
+ new_name += ' (%s Backend)' % pricelist_bind.backend_id.name
+ names.append((name[0], new_name))
return names
class BindingProductPricelistListener(Component):
@@ -85,8 +84,9 @@ class BindingProductPricelistListener(Component):
@skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
def on_record_write(self, record, fields=None):
- if any(record.channel_bind_ids) and 'name' in fields:
- record.channel_bind_ids[0].update_plan_name()
+ if 'name' in fields:
+ for binding in record.channel_bind_ids:
+ binding.update_plan_name()
class ChannelBindingProductPricelistListener(Component):
_name = 'channel.binding.product.pricelist.listener'
diff --git a/hotel_channel_connector/models/product_pricelist_item/common.py b/hotel_channel_connector/models/product_pricelist_item/common.py
index 9614cb7c5..6e25e546e 100644
--- a/hotel_channel_connector/models/product_pricelist_item/common.py
+++ b/hotel_channel_connector/models/product_pricelist_item/common.py
@@ -61,6 +61,23 @@ class BindingProductPricelistItemListener(Component):
if any(fields_checked):
record.channel_bind_ids.write({'channel_pushed': False})
+ @skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
+ def on_record_create(self, record, fields=None):
+ if not any(record.channel_bind_ids):
+ channel_product_pricelist_item_obj = self.env[
+ 'channel.product.pricelist.item']
+ for pricelist_bind in record.restriction_id.channel_bind_ids:
+ pricelist_item_bind = channel_product_pricelist_item_obj.search([
+ ('odoo_id', '=', record.id),
+ ('backend_id', '=', pricelist_bind.backend_id.id),
+ ])
+ if not pricelist_item_bind:
+ channel_product_pricelist_item_obj.create({
+ 'odoo_id': record.id,
+ 'channel_pushed': False,
+ 'backend_id': pricelist_bind.backend_id.id,
+ })
+
class ChannelBindingProductPricelistItemListener(Component):
_name = 'channel.binding.product.pricelist.item.listener'
_inherit = 'base.connector.listener'
diff --git a/hotel_channel_connector/views/inherited_hotel_folio_views.xml b/hotel_channel_connector/views/inherited_hotel_folio_views.xml
index 3821538be..328d8b46c 100644
--- a/hotel_channel_connector/views/inherited_hotel_folio_views.xml
+++ b/hotel_channel_connector/views/inherited_hotel_folio_views.xml
@@ -10,7 +10,7 @@
-
+
@@ -20,7 +20,7 @@
{'readonly': [('is_from_ota', '!=', False)]}
-
+
diff --git a/hotel_channel_connector/views/inherited_hotel_reservation_views.xml b/hotel_channel_connector/views/inherited_hotel_reservation_views.xml
index 497cf2114..87ef10340 100644
--- a/hotel_channel_connector/views/inherited_hotel_reservation_views.xml
+++ b/hotel_channel_connector/views/inherited_hotel_reservation_views.xml
@@ -64,7 +64,7 @@
-
+
@@ -78,8 +78,8 @@
-
+
@@ -90,7 +90,7 @@
hotel.reservation
-
+
@@ -103,7 +103,7 @@
-
+
diff --git a/hotel_channel_connector_wubook/__manifest__.py b/hotel_channel_connector_wubook/__manifest__.py
index 4347f952f..7db1e2dc9 100644
--- a/hotel_channel_connector_wubook/__manifest__.py
+++ b/hotel_channel_connector_wubook/__manifest__.py
@@ -18,6 +18,7 @@
'data': [
'data/cron_jobs.xml',
'data/sequences.xml',
+ 'data/records.xml',
'views/inherited_channel_connector_backend_views.xml',
'views/inherited_channel_ota_info_views.xml',
#'security/wubook_security.xml',
diff --git a/hotel_channel_connector_wubook/components/backend_adapter.py b/hotel_channel_connector_wubook/components/backend_adapter.py
index ecc8abd2e..14a05666d 100644
--- a/hotel_channel_connector_wubook/components/backend_adapter.py
+++ b/hotel_channel_connector_wubook/components/backend_adapter.py
@@ -102,8 +102,7 @@ class WuBookAdapter(AbstractComponent):
rcode_a, results_a = self._server.push_activation(
self._session_info[0],
self._session_info[1],
- urljoin(base_url,
- "/wubook/push/reservations/%s" % security_token),
+ urljoin(base_url, "wubook/push/reservations/%s" % security_token),
1)
if rcode_a != 0:
raise ChannelConnectorError(_("Can't activate push reservations"), {
@@ -113,7 +112,7 @@ class WuBookAdapter(AbstractComponent):
rcode_b, results_b = self._server.push_update_activation(
self._session_info[0],
self._session_info[1],
- urljoin(base_url, "/wubook/push/rooms/%s" % security_token))
+ urljoin(base_url, "wubook/push/rooms/%s" % security_token))
if rcode_b != 0:
raise ChannelConnectorError(_("Can't activate push rooms"), {
'message': results_b,
@@ -122,7 +121,7 @@ class WuBookAdapter(AbstractComponent):
return rcode_a == 0 and results_b == 0
# === ROOMS
- def create_room(self, shortcode, name, capacity, price, availability):
+ def create_room(self, shortcode, name, capacity, price, availability, defboard, rtype):
rcode, results = self._server.new_room(
self._session_info[0],
self._session_info[1],
@@ -132,8 +131,8 @@ class WuBookAdapter(AbstractComponent):
price,
availability,
shortcode[:4],
- 'nb' # TODO: Complete this part
- # rtype=('name' in vals and vals['name'] and 3) or 1
+ defboard,
+ rtype=rtype
)
if rcode != 0:
raise ChannelConnectorError(_("Can't create room in WuBook"), {
@@ -141,7 +140,7 @@ class WuBookAdapter(AbstractComponent):
})
return results
- def modify_room(self, channel_room_id, name, capacity, price, availability, scode):
+ def modify_room(self, channel_room_id, name, capacity, price, availability, scode, defboard, rtype):
rcode, results = self._server.mod_room(
self._session_info[0],
self._session_info[1],
@@ -151,8 +150,8 @@ class WuBookAdapter(AbstractComponent):
price,
availability,
scode,
- 'nb'
- # rtype=('name' in vals and vals['name'] and 3) or 1
+ defboard,
+ rtype=rtype
)
if rcode != 0:
raise ChannelConnectorError(_("Can't modify room in WuBook"), {
@@ -405,6 +404,7 @@ class WuBookAdapter(AbstractComponent):
rcode, results = self._server.wired_rplan_get_rplan_values(
self._session_info[0],
self._session_info[1],
+ '1.1',
fields.Date.from_string(date_from).strftime(DEFAULT_WUBOOK_DATE_FORMAT),
fields.Date.from_string(date_to).strftime(DEFAULT_WUBOOK_DATE_FORMAT),
int(channel_restriction_plan_id))
diff --git a/hotel_channel_connector_wubook/data/records.xml b/hotel_channel_connector_wubook/data/records.xml
new file mode 100644
index 000000000..4e67dba44
--- /dev/null
+++ b/hotel_channel_connector_wubook/data/records.xml
@@ -0,0 +1,44 @@
+
+
+
+
+ Room
+ 1
+
+
+
+ Apartment
+ 2
+
+
+
+ Beds Number
+ 3
+
+
+
+ Beds
+ 4
+
+
+
+ Bungalow
+ 5
+
+
+
+ Tent
+ 6
+
+
+
+ Villa
+ 7
+
+
+
+ Chalet
+ 8
+
+
+
diff --git a/hotel_channel_connector_wubook/models/__init__.py b/hotel_channel_connector_wubook/models/__init__.py
index f85e8b583..0cd2b3cea 100644
--- a/hotel_channel_connector_wubook/models/__init__.py
+++ b/hotel_channel_connector_wubook/models/__init__.py
@@ -10,4 +10,5 @@ from . import hotel_room_type_restriction_item
from . import hotel_room_type_availability
from . import hotel_reservation
from . import inherited_hotel_folio
+from . import inherited_hotel_room_type_class
from . import channel_ota_info
diff --git a/hotel_channel_connector_wubook/models/channel_backend/common.py b/hotel_channel_connector_wubook/models/channel_backend/common.py
index b9d0da3fe..3c3197d30 100644
--- a/hotel_channel_connector_wubook/models/channel_backend/common.py
+++ b/hotel_channel_connector_wubook/models/channel_backend/common.py
@@ -17,7 +17,7 @@ class ChannelBackend(models.Model):
to redefine the ``version`` field in the ``_inherit`` model.
"""
super(ChannelBackend, self).select_versions()
- return [('1.2', '1.2+')]
+ return [('1.1', '1.1')]
def _get_default_server(self):
return 'https://wired.wubook.net/xrws/'
diff --git a/hotel_channel_connector_wubook/models/hotel_reservation/common.py b/hotel_channel_connector_wubook/models/hotel_reservation/common.py
index eb659f2a1..1ef3e3708 100644
--- a/hotel_channel_connector_wubook/models/hotel_reservation/common.py
+++ b/hotel_channel_connector_wubook/models/hotel_reservation/common.py
@@ -11,7 +11,8 @@ from odoo.addons.hotel_channel_connector_wubook.components.backend_adapter impor
WUBOOK_STATUS_ACCEPTED,
WUBOOK_STATUS_CANCELLED,
WUBOOK_STATUS_CANCELLED_PENALTY,
- WUBOOK_STATUS_BAD)
+ WUBOOK_STATUS_BAD,
+ WUBOOK_STATUS_GOOD)
class ChannelHotelReservation(models.Model):
@@ -32,37 +33,31 @@ class HotelReservation(models.Model):
@api.multi
def action_cancel(self):
- no_export = self._context.get('connector_no_export', True)
- if no_export:
- for record in self:
- # Can't cancel in Odoo
- if record.is_from_ota:
- raise ValidationError(_("Can't cancel reservations from OTA's"))
+ for record in self:
+ # Can't cancel in Odoo
+ if record.is_from_ota and self._context.get('ota_limits', True):
+ raise ValidationError(_("Can't cancel reservations from OTA's"))
user = self.env['res.users'].browse(self.env.uid)
if user.has_group('hotel.group_hotel_call'):
self.write({'to_read': True, 'to_assign': True})
res = super(HotelReservation, self).action_cancel()
- if no_export:
- for record in self:
- # Only can cancel reservations created directly in wubook
- if any(record.channel_bind_ids) and \
- record.channel_bind_ids[0].external_id and \
- not record.channel_bind_ids[0].ota_id and \
- record.channel_bind_ids[0].channel_status in ['1', '2', '4']:
- self._event('on_record_cancel').notify(record)
+ for record in self:
+ # Only can cancel reservations created directly in wubook
+ for binding in record.channel_bind_ids:
+ if binding.external_id and not binding.ota_id and \
+ binding.channel_status in WUBOOK_STATUS_GOOD:
+ self._event('on_record_cancel').notify(binding)
return res
@api.multi
def confirm(self):
- can_confirm = True
for record in self:
- if record.is_from_ota and any(record.channel_bind_ids) and \
- int(record.channel_bind_ids[0].channel_status) in WUBOOK_STATUS_BAD:
- can_confirm = False
- break
- if not can_confirm:
- raise ValidationError(_("Can't confirm OTA's cancelled reservations"))
+ if record.is_from_ota:
+ for binding in record.channel_bind_ids:
+ if int(binding.channel_status) in WUBOOK_STATUS_BAD \
+ and self._context.get('ota_limits', True):
+ raise ValidationError(_("Can't confirm OTA's cancelled reservations"))
return super(HotelReservation, self).confirm()
diff --git a/hotel_channel_connector_wubook/models/hotel_room_type/exporter.py b/hotel_channel_connector_wubook/models/hotel_room_type/exporter.py
index 2faf77a92..c763d51cb 100644
--- a/hotel_channel_connector_wubook/models/hotel_room_type/exporter.py
+++ b/hotel_channel_connector_wubook/models/hotel_room_type/exporter.py
@@ -3,7 +3,7 @@
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, fields
class HotelRoomTypeExporter(Component):
@@ -12,13 +12,16 @@ class HotelRoomTypeExporter(Component):
@api.model
def modify_room(self, binding):
try:
+ binding.sync_date = fields.Datetime.now()
return self.backend_adapter.modify_room(
binding.external_id,
binding.name,
binding.ota_capacity,
binding.list_price,
binding.total_rooms_count,
- binding.channel_short_code)
+ binding.channel_short_code,
+ 'nb',
+ binding.class_id and binding.class_id.class_code or False)
except ChannelConnectorError as err:
self.create_issue(
section='room',
@@ -35,8 +38,9 @@ class HotelRoomTypeExporter(Component):
binding.name,
binding.ota_capacity,
binding.list_price,
- binding.total_rooms_count
- )
+ binding.total_rooms_count,
+ 'nb',
+ binding.class_id and binding.class_id.class_code or False)
except ChannelConnectorError as err:
self.create_issue(
section='room',
diff --git a/hotel_channel_connector_wubook/models/hotel_room_type/importer.py b/hotel_channel_connector_wubook/models/hotel_room_type/importer.py
index addec8065..09f29f769 100644
--- a/hotel_channel_connector_wubook/models/hotel_room_type/importer.py
+++ b/hotel_channel_connector_wubook/models/hotel_room_type/importer.py
@@ -22,9 +22,16 @@ class HotelRoomTypeImporter(Component):
channel_message=err.data['message'])
else:
channel_room_type_obj = self.env['channel.hotel.room.type']
+ hotel_room_type_class_obj = self.env['hotel.room.type.class']
room_mapper = self.component(usage='import.mapper',
model_name='channel.hotel.room.type')
for room in results:
+ room_type_class = hotel_room_type_class_obj.search([
+ ('code_class', '=', str(room['rtype'])),
+ ])
+ room.update({
+ 'class_id': room_type_class and room_type_class.id or False,
+ })
map_record = room_mapper.map_record(room)
room_bind = channel_room_type_obj.search([
('backend_id', '=', self.backend_record.id),
@@ -57,3 +64,7 @@ class HotelRoomTypeImportMapper(Component):
@mapping
def backend_id(self, record):
return {'backend_id': self.backend_record.id}
+
+ @mapping
+ def class_id(self, record):
+ return {'class_id': record['class_id']}
diff --git a/hotel_channel_connector_wubook/models/hotel_room_type_availability/exporter.py b/hotel_channel_connector_wubook/models/hotel_room_type_availability/exporter.py
index 242fbe044..3698419a5 100644
--- a/hotel_channel_connector_wubook/models/hotel_room_type_availability/exporter.py
+++ b/hotel_channel_connector_wubook/models/hotel_room_type_availability/exporter.py
@@ -14,6 +14,7 @@ class HotelRoomTypeAvailabilityExporter(Component):
_inherit = 'channel.hotel.room.type.availability.exporter'
def push_availability(self):
+ channel_hotel_room_type_obj = self.env['channel.hotel.room.type']
channel_room_type_avail_ids = self.env['channel.hotel.room.type.availability'].search([
('backend_id', '=', self.backend_record.id),
('channel_pushed', '=', False),
@@ -38,7 +39,11 @@ class HotelRoomTypeAvailabilityExporter(Component):
'no_ota': channel_room_type_avail.no_ota and 1 or 0,
# 'booked': room_type_avail.booked and 1 or 0,
})
- avails.append({'id': room_type.channel_bind_ids[0].channel_room_id, 'days': days})
+ room_type_bind = channel_hotel_room_type_obj.search([
+ ('odoo_id', '=', room_type.id),
+ ('backend_id', '=', self.backend_record.id),
+ ], limit=1)
+ avails.append({'id': room_type_bind.external_id, 'days': days})
_logger.info("==[ODOO->CHANNEL]==== AVAILABILITY ==")
_logger.info(avails)
if any(avails):
diff --git a/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/exporter.py b/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/exporter.py
index e6e82afa2..2f5c39bc4 100644
--- a/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/exporter.py
+++ b/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/exporter.py
@@ -13,6 +13,7 @@ class HotelRoomTypeRestrictionItemExporter(Component):
@api.model
def push_restriction(self):
+ channel_hotel_room_type_obj = self.env['channel.hotel.room.type']
channel_room_type_rest_obj = self.env['channel.hotel.room.type.restriction']
channel_rest_item_obj = self.env['channel.hotel.room.type.restriction.item']
unpushed = channel_rest_item_obj.search([
@@ -38,8 +39,11 @@ class HotelRoomTypeRestrictionItemExporter(Component):
room_type_ids = unpushed_rp.mapped('room_type_id')
for room_type in room_type_ids:
if any(room_type.channel_bind_ids):
- # FIXME: Supossed that only exists one channel connector per record
- room_type_external_id = room_type.channel_bind_ids[0].external_id
+ room_type_bind = channel_hotel_room_type_obj.search([
+ ('odoo_id', '=', room_type.id),
+ ('backend_id', '=', self.backend_record.id),
+ ], limit=1)
+ room_type_external_id = room_type_bind.external_id
restrictions[rp.external_id].update({
room_type_external_id: [],
})
diff --git a/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/importer.py b/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/importer.py
index 5ad3e05a0..842a34d1b 100644
--- a/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/importer.py
+++ b/hotel_channel_connector_wubook/models/hotel_room_type_restriction_item/importer.py
@@ -27,6 +27,7 @@ class HotelRoomTypeRestrictionImporter(Component):
model_name='channel.hotel.room.type.restriction.item')
_logger.info("==[CHANNEL->ODOO]==== RESTRICTIONS ==")
_logger.info(plan_restrictions)
+ count = 0
for k_rpid, v_rpid in plan_restrictions.items():
channel_restriction_id = channel_reserv_restriction_obj.search([
('backend_id', '=', self.backend_record.id),
@@ -40,6 +41,7 @@ class HotelRoomTypeRestrictionImporter(Component):
], limit=1)
if channel_room_type:
for item in v_rid:
+ _logger.info(item)
map_record = restriction_item_mapper.map_record(item)
date_dt = datetime.strptime(item['date'], DEFAULT_WUBOOK_DATE_FORMAT)
date_str = date_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)
@@ -47,7 +49,6 @@ class HotelRoomTypeRestrictionImporter(Component):
('backend_id', '=', self.backend_record.id),
('restriction_id', '=', channel_restriction_id.odoo_id.id),
('date', '=', date_str),
- ('applied_on', '=', '0_room_type'),
('room_type_id', '=', channel_room_type.odoo_id.id)
], limit=1)
item.update({
@@ -64,6 +65,8 @@ class HotelRoomTypeRestrictionImporter(Component):
'connector_no_export': True
}).create(map_record.values(for_create=True))
channel_restriction_item.channel_pushed = True
+ count += 1
+ return count
@api.model
def import_restriction_values(self, date_from, date_to, channel_restr_id=False):
@@ -82,7 +85,8 @@ class HotelRoomTypeRestrictionImporter(Component):
dfrom=date_from, dto=date_to)
else:
if any(results):
- self._generate_restriction_items(results)
+ return self._generate_restriction_items(results)
+ return 0
class HotelRoomTypeRestrictionItemImportMapper(Component):
@@ -96,7 +100,7 @@ class HotelRoomTypeRestrictionItemImportMapper(Component):
('max_stay', 'max_stay'),
('max_stay_arrival', 'max_stay_arrival'),
('closed', 'closed'),
- ('closed_departure', 'closed_departure'),
+ #('closed_departure', 'closed_departure'),
('closed_arrival', 'closed_arrival'),
('date', 'date'),
]
@@ -121,3 +125,7 @@ class HotelRoomTypeRestrictionItemImportMapper(Component):
@mapping
def sync_date(self, record):
return {'sync_date': fields.Datetime.now()}
+
+ @mapping
+ def closed_departure(self, record):
+ return {'closed_departure': int(record['closed_departure'])}
diff --git a/hotel_channel_connector_wubook/models/inherited_hotel_room_type_class.py b/hotel_channel_connector_wubook/models/inherited_hotel_room_type_class.py
new file mode 100644
index 000000000..ede1ffe97
--- /dev/null
+++ b/hotel_channel_connector_wubook/models/inherited_hotel_room_type_class.py
@@ -0,0 +1,25 @@
+# Copyright 2018 Alexandre Díaz
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from openerp import models, fields, api, _
+from openerp.exceptions import ValidationError
+
+
+class HotelRoomTypeClass(models.Model):
+ _inherit = 'hotel.room.type.class'
+
+ _locked_codes = ('1', '2', '3', '4', '5', '6', '7', '8')
+
+ @api.multi
+ def write(self, vals):
+ for record in self:
+ if record.code_class in self._locked_codes:
+ raise ValidationError(_("Can't modify channel room type class"))
+ return super(HotelRoomTypeClass, self).write(vals)
+
+ @api.multi
+ def unlink(self):
+ for record in self:
+ if record.code_class in self._locked_codes:
+ raise ValidationError(_("Can't delete channel room type class"))
+ return super(HotelRoomTypeClass, self).unlink()