mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[IMP] Refactor & Export pricelist values (#63)
This commit is contained in:
@@ -1,127 +1,10 @@
|
||||
# Copyright 2018 Alexandre Díaz <dev@redneboa.es>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
import psycopg2
|
||||
from contextlib import contextmanager
|
||||
from odoo.addons.connector.exception import (IDMissingInBackend,
|
||||
RetryableJobError)
|
||||
from odoo.addons.component.core import AbstractComponent
|
||||
from odoo.tools import (
|
||||
DEFAULT_SERVER_DATE_FORMAT,
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
from .backend_adapter import DEFAULT_WUBOOK_DATE_FORMAT
|
||||
from odoo import api, fields
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HotelChannelConnectorExporter(AbstractComponent):
|
||||
_name = 'hotel.channel.exporter'
|
||||
_inherit = ['base.exporter', 'base.hotel.channel.connector']
|
||||
_usage = 'channel.exporter'
|
||||
|
||||
@api.model
|
||||
def push_changes(self):
|
||||
return self.push_availability() and self.push_priceplans() and \
|
||||
self.push_restrictions()
|
||||
|
||||
@api.model
|
||||
def push_priceplans(self):
|
||||
unpushed = self.env['product.pricelist.item'].search([
|
||||
('wpushed', '=', False),
|
||||
('date_start', '>=', fields.Datetime.now().strftime(
|
||||
DEFAULT_SERVER_DATE_FORMAT))
|
||||
], order="date_start ASC")
|
||||
if any(unpushed):
|
||||
date_start = fields.Date.from_string(unpushed[0].date_start)
|
||||
date_end = fields.Date.from_string(unpushed[-1].date_start)
|
||||
days_diff = (date_start - date_end).days + 1
|
||||
|
||||
prices = {}
|
||||
pricelist_ids = self.env['product.pricelist'].search([
|
||||
('wpid', '!=', False),
|
||||
('active', '=', True)
|
||||
])
|
||||
for pr in pricelist_ids:
|
||||
prices.update({pr.wpid: {}})
|
||||
unpushed_pl = self.env['product.pricelist.item'].search(
|
||||
[('wpushed', '=', False), ('pricelist_id', '=', pr.id)])
|
||||
product_tmpl_ids = unpushed_pl.mapped('product_tmpl_id')
|
||||
for pt_id in product_tmpl_ids:
|
||||
room_type = self.env['hotel.room.type'].search([
|
||||
('product_id.product_tmpl_id', '=', pt_id.id)
|
||||
], limit=1)
|
||||
if room_type:
|
||||
prices[pr.wpid].update({room_type.wrid: []})
|
||||
for i in range(0, days_diff):
|
||||
prod = room_type.product_id.with_context({
|
||||
'quantity': 1,
|
||||
'pricelist': pr.id,
|
||||
'date': (date_start + timedelta(days=i)).
|
||||
strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
})
|
||||
prices[pr.wpid][room_type.wrid].append(prod.price)
|
||||
_logger.info("UPDATING PRICES IN WUBOOK...")
|
||||
_logger.info(prices)
|
||||
for k_pk, v_pk in prices.iteritems():
|
||||
if any(v_pk):
|
||||
self.backend_adapter.update_plan_prices(k_pk, date_start.strftime(
|
||||
DEFAULT_SERVER_DATE_FORMAT), v_pk)
|
||||
|
||||
unpushed.with_context({
|
||||
'wubook_action': False}).write({'wpushed': True})
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def push_restrictions(self):
|
||||
room_type_rest_obj = self.env['hotel.room.type.restriction']
|
||||
rest_item_obj = self.env['hotel.room.type.restriction.item']
|
||||
unpushed = rest_item_obj.search([
|
||||
('wpushed', '=', False),
|
||||
('date_start', '>=', fields.Datetime.now().strftime(
|
||||
DEFAULT_SERVER_DATE_FORMAT))
|
||||
], order="date_start ASC")
|
||||
if any(unpushed):
|
||||
date_start = fields.Date.from_string(unpushed[0].date_start)
|
||||
date_end = fields.Date.from_string(unpushed[-1].date_start)
|
||||
days_diff = (date_start - date_end) + 1
|
||||
restrictions = {}
|
||||
restriction_plan_ids = room_type_rest_obj.search([
|
||||
('wpid', '!=', False),
|
||||
('active', '=', True)
|
||||
])
|
||||
for rp in restriction_plan_ids:
|
||||
restrictions.update({rp.wpid: {}})
|
||||
unpushed_rp = rest_item_obj.search([
|
||||
('wpushed', '=', False),
|
||||
('restriction_id', '=', rp.id)
|
||||
])
|
||||
room_type_ids = unpushed_rp.mapped('room_type_id')
|
||||
for room_type in room_type_ids:
|
||||
restrictions[rp.wpid].update({room_type.wrid: []})
|
||||
for i in range(0, days_diff):
|
||||
ndate_dt = date_start + timedelta(days=i)
|
||||
restr = room_type.get_restrictions(
|
||||
ndate_dt.strftime(DEFAULT_SERVER_DATE_FORMAT))
|
||||
if restr:
|
||||
restrictions[rp.wpid][room_type.wrid].append({
|
||||
'min_stay': restr.min_stay or 0,
|
||||
'min_stay_arrival': restr.min_stay_arrival or 0,
|
||||
'max_stay': restr.max_stay or 0,
|
||||
'max_stay_arrival': restr.max_stay_arrival or 0,
|
||||
'closed': restr.closed and 1 or 0,
|
||||
'closed_arrival': restr.closed_arrival and 1 or 0,
|
||||
'closed_departure': restr.closed_departure and 1 or 0,
|
||||
})
|
||||
else:
|
||||
restrictions[rp.wpid][room_type.wrid].append({})
|
||||
_logger.info("UPDATING RESTRICTIONS IN WUBOOK...")
|
||||
_logger.info(restrictions)
|
||||
for k_res, v_res in restrictions.iteritems():
|
||||
if any(v_res):
|
||||
self.backend_adapter.update_rplan_values(
|
||||
int(k_res),
|
||||
date_start.strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
v_res)
|
||||
unpushed.with_context({
|
||||
'wubook_action': False}).write({'wpushed': True})
|
||||
return True
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from openerp import http, _
|
||||
from openerp.http import request
|
||||
from openerp.exceptions import ValidationError
|
||||
from odoo.addons.hotel_channel_connector.components.backend_adapter import (
|
||||
DEFAULT_WUBOOK_DATE_FORMAT)
|
||||
from odoo.tools import (
|
||||
DEFAULT_SERVER_DATE_FORMAT,
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -14,14 +20,6 @@ class website_wubook(http.Controller):
|
||||
type='http', cors="*", auth="public", methods=['POST'],
|
||||
website=True, csrf=False)
|
||||
def wubook_push_reservations(self, security_token, **kwargs):
|
||||
# Check Security Token
|
||||
hotel_security_token = request.env['ir.default'].sudo().get(
|
||||
'wubook.config.settings', 'wubook_push_security_token')
|
||||
if security_token != hotel_security_token:
|
||||
# _logger.info("Invalid Tokens: '%s' != '%s'" %
|
||||
# (security_token, hotel_security_token))
|
||||
raise ValidationError(_('Invalid Security Token!'))
|
||||
|
||||
rcode = kwargs.get('rcode')
|
||||
lcode = kwargs.get('lcode')
|
||||
|
||||
@@ -31,35 +29,27 @@ class website_wubook(http.Controller):
|
||||
|
||||
# WuBook Check
|
||||
if rcode == '2000' and lcode == '1000':
|
||||
return request.make_response(
|
||||
'200 OK', [('Content-Type', 'text/plain')])
|
||||
return request.make_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
|
||||
# Poor Security Check
|
||||
wlcode = request.env['ir.default'].sudo().get(
|
||||
'wubook.config.settings', 'wubook_lcode')
|
||||
if lcode != wlcode:
|
||||
raise ValidationError(_("Error! lcode doesn't match!"))
|
||||
# Get Backend
|
||||
backend = request.env['channel.backend'].search([
|
||||
('security_token', '=', security_token),
|
||||
('lcode', '=', lcode),
|
||||
])
|
||||
if not backend:
|
||||
raise ValidationError(_("Can't found a backend!"))
|
||||
|
||||
_logger.info(_("[WUBOOK->ODOO] Importing Booking..."))
|
||||
# Create Reservation
|
||||
request.env['wubook'].sudo().fetch_booking(lcode, rcode)
|
||||
|
||||
return request.make_response('200 OK',
|
||||
[('Content-Type', 'text/plain')])
|
||||
return request.make_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
|
||||
# Called when modify room values (Delay: ~5mins)
|
||||
@http.route(['/wubook/push/rooms/<string:security_token>'], type='http',
|
||||
cors="*", auth="public", methods=['POST'], website=True,
|
||||
csrf=False)
|
||||
def wubook_push_rooms(self, security_token, **kwargs):
|
||||
# Check Security Token
|
||||
hotel_security_token = request.env['ir.default'].sudo().get(
|
||||
'wubook.config.settings', 'wubook_push_security_token')
|
||||
if security_token != hotel_security_token:
|
||||
# _logger.info("Invalid Tokens: '%s' != '%s'" %
|
||||
# (security_token, hotel_security_token))
|
||||
raise ValidationError(_('Invalid Security Token!'))
|
||||
|
||||
lcode = kwargs.get('lcode')
|
||||
dfrom = kwargs.get('dfrom')
|
||||
dto = kwargs.get('dto')
|
||||
@@ -68,36 +58,32 @@ class website_wubook(http.Controller):
|
||||
if not lcode or not dfrom or not dto:
|
||||
raise ValidationError(_('Invalid Input Parameters!'))
|
||||
|
||||
# Poor Security Check
|
||||
wlcode = request.env['ir.default'].sudo().get(
|
||||
'wubook.config.settings', 'wubook_lcode')
|
||||
if lcode != wlcode:
|
||||
raise ValidationError(_("Error! lcode doesn't match!"))
|
||||
# Get Backend
|
||||
backend = request.env['channel.backend'].search([
|
||||
('security_token', '=', security_token),
|
||||
('lcode', '=', lcode),
|
||||
])
|
||||
if not backend:
|
||||
raise ValidationError(_("Can't found a backend!"))
|
||||
|
||||
_logger.info(_("[WUBOOK->ODOO] Updating values..."))
|
||||
wubook_obj = request.env['wubook'].sudo().with_context({
|
||||
'init_connection': False
|
||||
odoo_dfrom = datetime.strptime(
|
||||
dfrom,
|
||||
DEFAULT_WUBOOK_DATE_FORMAT).strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
odoo_dto = datetime.strptime(
|
||||
dto,
|
||||
DEFAULT_WUBOOK_DATE_FORMAT).strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
backend.write({
|
||||
'avail_from': odoo_dfrom,
|
||||
'avail_to': odoo_dto,
|
||||
'restriction_id': False,
|
||||
'restriction_from': odoo_dfrom,
|
||||
'restriction_to': odoo_dto,
|
||||
'pricelist_id': False,
|
||||
'pricelist_from': odoo_dfrom,
|
||||
'pricelist_to': odoo_dto,
|
||||
})
|
||||
if wubook_obj.init_connection():
|
||||
wubook_obj.fetch_rooms_values(dfrom, dto)
|
||||
backend.import_availability()
|
||||
backend.import_restriction()
|
||||
backend.import_pricelist()
|
||||
|
||||
default_restr_id = request.env['ir.default'].sudo().get(
|
||||
'res.config.settings', 'default_restriction_id')
|
||||
if default_restr_id:
|
||||
room_type_restr_obj = request.env['hotel.room.type.restriction']
|
||||
restr_id = room_type_restr_obj.sudo().browse(int(default_restr_id))
|
||||
if restr_id and restr_id.wpid and restr_id.wpid != '0':
|
||||
wubook_obj.fetch_rplan_restrictions(dfrom, dto,
|
||||
rpid=restr_id.wpid)
|
||||
|
||||
default_pricelist_id = request.env['ir.default'].sudo().get(
|
||||
'res.config.settings', 'default_pricelist_id')
|
||||
if default_pricelist_id:
|
||||
pricelist_id = request.env['product.pricelist'].sudo().browse(
|
||||
int(default_pricelist_id))
|
||||
if pricelist_id and pricelist_id.wpid:
|
||||
wubook_obj.fetch_plan_prices(pricelist_id.wpid, dfrom, dto)
|
||||
wubook_obj.close_connection()
|
||||
|
||||
return request.make_response('200 OK',
|
||||
[('Content-Type', 'text/plain')])
|
||||
return request.make_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
|
||||
@@ -126,6 +126,19 @@ class ChannelBackend(models.Model):
|
||||
channel_product_pricelist_item_obj.import_pricelist_values(backend)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def push_pricelist(self):
|
||||
channel_product_pricelist_item_obj = self.env['channel.product.pricelist.item']
|
||||
for backend in self:
|
||||
channel_product_pricelist_item_obj.push_pricelist(backend)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def push_changes(self):
|
||||
self.push_availability()
|
||||
self.push_restriction()
|
||||
self.push_pricelist()
|
||||
|
||||
@contextmanager
|
||||
@api.multi
|
||||
def work_on(self, model_name, **kwargs):
|
||||
|
||||
@@ -26,7 +26,7 @@ class ChannelOtaInfo(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='room',
|
||||
internal_message=_("Can't import ota info from WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class HotelRoomTypeAdapter(Component):
|
||||
|
||||
@@ -35,9 +35,13 @@ class ChannelOtaInfoImporter(Component):
|
||||
('ota_id', '=', ota_id)
|
||||
], limit=1)
|
||||
if ota_info_bind:
|
||||
ota_info_bind.write(map_record.values())
|
||||
ota_info_bind.with_context({
|
||||
'connector_no_export': True,
|
||||
}).write(map_record.values())
|
||||
else:
|
||||
ota_info_bind.create(map_record.values(for_create=True))
|
||||
ota_info_bind.with_context({
|
||||
'connector_no_export': True,
|
||||
}).create(map_record.values(for_create=True))
|
||||
count = count + 1
|
||||
return count
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class ChannelHotelRoomType(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='room',
|
||||
internal_message=_("Can't create room in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -90,7 +90,7 @@ class ChannelHotelRoomType(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='room',
|
||||
internal_message=_("Can't modify rooms in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -107,7 +107,7 @@ class ChannelHotelRoomType(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='room',
|
||||
internal_message=_("Can't delete room in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class HotelRoomType(models.Model):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.connector.components.mapper import mapping
|
||||
@@ -34,9 +34,9 @@ class HotelRoomTypeImporter(Component):
|
||||
('external_id', '=', room['id'])
|
||||
], limit=1)
|
||||
if room_bind:
|
||||
room_bind.with_context({'wubook_action': False}).write(map_record.values())
|
||||
room_bind.with_context({'connector_no_export':True}).write(map_record.values())
|
||||
else:
|
||||
room_bind = channel_room_type_obj.with_context({'wubook_action': False}).create(
|
||||
room_bind = channel_room_type_obj.with_context({'connector_no_export':True}).create(
|
||||
map_record.values(for_create=True))
|
||||
return count
|
||||
|
||||
@@ -44,7 +44,7 @@ class HotelRoomTypeImporter(Component):
|
||||
def fetch_rooms_values(self, dfrom, dto, rooms=False,
|
||||
set_max_avail=False):
|
||||
# Sanitize Dates
|
||||
now_dt = fields.Datetime.now()
|
||||
now_dt = datetime.now()
|
||||
dfrom_dt = fields.Date.from_string(dfrom)
|
||||
dto_dt = fields.Date.from_string(dto)
|
||||
if dto_dt < now_dt:
|
||||
@@ -77,11 +77,11 @@ class HotelRoomTypeImporter(Component):
|
||||
], limit=1)
|
||||
if channel_room_type_avail:
|
||||
channel_room_type_avail.with_context({
|
||||
'wubook_action': False,
|
||||
'connector_no_export': True,
|
||||
}).write(map_record.values())
|
||||
else:
|
||||
channel_room_type_avail_obj.with_context({
|
||||
'wubook_action': False,
|
||||
'connector_no_export': True,
|
||||
'mail_create_nosubscribe': True,
|
||||
}).create(map_record.values(for_create=True))
|
||||
|
||||
@@ -102,11 +102,11 @@ class HotelRoomTypeImporter(Component):
|
||||
])
|
||||
if room_type_restr:
|
||||
room_type_restr.with_context({
|
||||
'wubook_action': False,
|
||||
'connector_no_export': True,
|
||||
}).write(map_record.values())
|
||||
else:
|
||||
channel_room_type_restr_item_obj.with_context({
|
||||
'wubook_action': False,
|
||||
'connector_no_export': True,
|
||||
}).create(map_record.values(for_create=True))
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -54,7 +54,7 @@ class ChannelHotelRoomTypeAvailability(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='avail',
|
||||
internal_message=_("Can't update availability in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -63,12 +63,13 @@ class ChannelHotelRoomTypeAvailability(models.Model):
|
||||
with backend.work_on(self._name) as work:
|
||||
importer = work.component(usage='hotel.room.type.availability.importer')
|
||||
try:
|
||||
return importer.get_availability(backend.avail_from, backend.avail_to)
|
||||
return importer.import_availability_values(backend.avail_from,
|
||||
backend.avail_to)
|
||||
except ChannelConnectorError as err:
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='avail',
|
||||
internal_message=_("Can't import availability from WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -82,7 +83,7 @@ class ChannelHotelRoomTypeAvailability(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='avail',
|
||||
internal_message=_("Can't update availability in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class HotelRoomTypeAvailability(models.Model):
|
||||
|
||||
@@ -15,21 +15,6 @@ class HotelRoomTypeAvailabilityExporter(Component):
|
||||
_apply_on = ['channel.hotel.room.type.availability']
|
||||
_usage = 'hotel.room.type.availability.exporter'
|
||||
|
||||
@api.model
|
||||
def update_availability(self, binding):
|
||||
if any(binding.room_type_id.channel_bind_ids):
|
||||
sday_dt = fields.Date.from_string(binding.date)
|
||||
# FIXME: Supossed that only exists one channel connector per record
|
||||
binding.channel_pushed = True
|
||||
return self.backend_adapter.update_availability({
|
||||
'id': binding.room_type_id.channel_bind_ids[0].channel_room_id,
|
||||
'days': [{
|
||||
'date': sday_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT),
|
||||
'avail': binding.avail,
|
||||
'no_ota': binding.no_ota,
|
||||
}],
|
||||
})
|
||||
|
||||
def push_availability(self):
|
||||
channel_room_type_avail_ids = self.env['channel.hotel.room.type.availability'].search([
|
||||
('channel_pushed', '=', False),
|
||||
@@ -56,7 +41,7 @@ class HotelRoomTypeAvailabilityExporter(Component):
|
||||
# 'booked': room_type_avail.booked and 1 or 0,
|
||||
})
|
||||
avails.append({'id': room_type.channel_bind_ids[0].channel_room_id, 'days': days})
|
||||
_logger.info("UPDATING AVAILABILITY IN WUBOOK...")
|
||||
_logger.info("==[ODOO->CHANNEL]==== AVAILABILITY ==")
|
||||
_logger.info(avails)
|
||||
if any(avails):
|
||||
self.backend_adapter.update_availability(avails)
|
||||
|
||||
@@ -18,7 +18,7 @@ class HotelRoomTypeAvailabilityImporter(Component):
|
||||
_usage = 'hotel.room.type.availability.importer'
|
||||
|
||||
@api.model
|
||||
def get_availability(self, date_from, date_to):
|
||||
def import_availability_values(self, date_from, date_to):
|
||||
now_dt = date.today()
|
||||
dfrom_dt = fields.Date.from_string(date_from)
|
||||
dto_dt = fields.Date.from_string(date_to)
|
||||
@@ -30,6 +30,9 @@ class HotelRoomTypeAvailabilityImporter(Component):
|
||||
return True
|
||||
|
||||
results = self.backend_adapter.fetch_rooms_values(date_from, date_to)
|
||||
_logger.info("==[CHANNEL->ODOO]==== AVAILABILITY (%s - %s) ==",
|
||||
date_from, date_to)
|
||||
_logger.info(results)
|
||||
|
||||
channel_room_type_avail_obj = self.env['channel.hotel.room.type.availability']
|
||||
channel_room_type_obj = self.env['channel.hotel.room.type']
|
||||
@@ -55,11 +58,11 @@ class HotelRoomTypeAvailabilityImporter(Component):
|
||||
], limit=1)
|
||||
if room_type_avail_bind:
|
||||
room_type_avail_bind.with_context({
|
||||
'wubook_action': False
|
||||
'connector_no_export': True,
|
||||
}).write(map_record.values())
|
||||
else:
|
||||
room_type_avail_bind = channel_room_type_avail_obj.with_context({
|
||||
'wubook_action': False
|
||||
'connector_no_export': True,
|
||||
}).create(map_record.values(for_create=True))
|
||||
iter_day += timedelta(days=1)
|
||||
return count
|
||||
|
||||
@@ -35,7 +35,7 @@ class ChannelHotelRoomTypeRestriction(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't create restriction plan in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -52,7 +52,7 @@ class ChannelHotelRoomTypeRestriction(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't modify restriction plan in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -69,7 +69,7 @@ class ChannelHotelRoomTypeRestriction(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't delete restriction plan in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -83,7 +83,7 @@ class ChannelHotelRoomTypeRestriction(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't fetch restriction plans from wubook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class HotelRoomTypeRestriction(models.Model):
|
||||
|
||||
@@ -29,11 +29,11 @@ class HotelRoomTypeRestrictionImporter(Component):
|
||||
], limit=1)
|
||||
if not plan_bind:
|
||||
channel_restriction_obj.with_context({
|
||||
'wubook_action': False,
|
||||
'connector_no_export': True,
|
||||
'rules': plan.get('rules'),
|
||||
}).create(plan_record.values(for_create=True))
|
||||
else:
|
||||
plan_bind.with_context({'wubook_action': False}).write(
|
||||
plan_bind.with_context({'connector_no_export':True}).write(
|
||||
plan_record.values())
|
||||
count = count + 1
|
||||
return count
|
||||
|
||||
@@ -35,7 +35,7 @@ class ChannelHotelRoomTypeRestrictionItem(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't fetch plan restrictions from wubook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'],
|
||||
channel_object_id=backend.restriction_id,
|
||||
dfrom=backend.restriction_from, dto=backend.restriction_to)
|
||||
@@ -51,7 +51,7 @@ class ChannelHotelRoomTypeRestrictionItem(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't update restrictions in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class HotelRoomTypeRestrictionItem(models.Model):
|
||||
|
||||
@@ -17,24 +17,6 @@ class HotelRoomTypeRestrictionItemExporter(Component):
|
||||
_apply_on = ['channel.hotel.room.type.restriction.item']
|
||||
_usage = 'hotel.room.type.restriction.item.exporter'
|
||||
|
||||
@api.model
|
||||
def update_restriction(self, binding):
|
||||
if any(binding.restriction_id.channel_bind_ids):
|
||||
# FIXME: Supossed that only exists one channel connector per record
|
||||
binding.channel_pushed = True
|
||||
return self.backend_adapter.update_rplan_values(
|
||||
binding.restriction_id.channel_bind_ids[0].external_id,
|
||||
binding.date,
|
||||
{
|
||||
'min_stay': binding.min_stay or 0,
|
||||
'min_stay_arrival': binding.min_stay_arrival or 0,
|
||||
'max_stay': binding.max_stay or 0,
|
||||
'max_stay_arrival': binding.max_stay_arrival or 0,
|
||||
'closed': binding.closed and 1 or 0,
|
||||
'closed_arrival': binding.closed_arrival and 1 or 0,
|
||||
'closed_departure': binding.closed_departure and 1 or 0,
|
||||
})
|
||||
|
||||
@api.model
|
||||
def push_restriction(self):
|
||||
channel_room_type_rest_obj = self.env['channel.hotel.room.type.restriction']
|
||||
@@ -80,7 +62,7 @@ class HotelRoomTypeRestrictionItemExporter(Component):
|
||||
})
|
||||
else:
|
||||
restrictions[rp.external_id][room_type_external_id].append({})
|
||||
_logger.info("==[ODOO->CHANNEL]==== UPDATING RESTRICTIONS ==")
|
||||
_logger.info("==[ODOO->CHANNEL]==== RESTRICTIONS ==")
|
||||
_logger.info(restrictions)
|
||||
for k_res, v_res in restrictions.items():
|
||||
if any(v_res):
|
||||
|
||||
@@ -57,10 +57,11 @@ class HotelRoomTypeRestrictionImporter(Component):
|
||||
})
|
||||
if channel_restriction_item:
|
||||
channel_restriction_item.with_context({
|
||||
'wubook_action': False}).write(map_record.values())
|
||||
'connector_no_export': True
|
||||
}).write(map_record.values())
|
||||
else:
|
||||
channel_restriction_item_obj.with_context({
|
||||
'wubook_action': False
|
||||
'connector_no_export': True
|
||||
}).create(map_record.values(for_create=True))
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -34,7 +34,7 @@ class ChannelProductPricelist(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't create pricelist plan in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -51,7 +51,7 @@ class ChannelProductPricelist(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't modify pricelist plan in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -68,7 +68,7 @@ class ChannelProductPricelist(models.Model):
|
||||
self.create_issue(
|
||||
backend=self.backend_id.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't delete pricelist plan in WuBook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@job(default_channel='root.channel')
|
||||
@@ -82,7 +82,7 @@ class ChannelProductPricelist(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='pricelist',
|
||||
internal_message=_("Can't get pricing plans from wubook"),
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class ProductPricelist(models.Model):
|
||||
|
||||
@@ -34,9 +34,12 @@ class ProductPricelistImporter(Component):
|
||||
], limit=1)
|
||||
if not plan_bind:
|
||||
channel_product_listprice_obj.with_context({
|
||||
'wubook_action': False}).create(plan_record.values(for_create=True))
|
||||
'connector_no_export': True,
|
||||
}).create(plan_record.values(for_create=True))
|
||||
else:
|
||||
channel_product_listprice_obj.write(plan_record.values())
|
||||
channel_product_listprice_obj.with_context({
|
||||
'connector_no_export': True,
|
||||
}).write(plan_record.values())
|
||||
count = count + 1
|
||||
return count
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class ChannelProductPricelistItem(models.Model):
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='pricelist',
|
||||
internal_message="Can't fetch plan prices from wubook!",
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'],
|
||||
channel_object_id=backend.pricelist_id.external_id,
|
||||
dfrom=backend.pricelist_from,
|
||||
@@ -51,7 +51,14 @@ class ChannelProductPricelistItem(models.Model):
|
||||
def push_pricelist(self, backend):
|
||||
with backend.work_on(self._name) as work:
|
||||
exporter = work.component(usage='product.pricelist.item.exporter')
|
||||
return exporter.push_pricelist()
|
||||
try:
|
||||
return exporter.push_pricelist()
|
||||
except ChannelConnectorError as err:
|
||||
self.create_issue(
|
||||
backend=backend.id,
|
||||
section='pricelist',
|
||||
internal_message=str(err),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
class ProductPricelistItem(models.Model):
|
||||
_inherit = 'product.pricelist.item'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from odoo.addons.component.core import Component
|
||||
from odoo.addons.hotel_channel_connector.components.backend_adapter import (
|
||||
DEFAULT_WUBOOK_DATE_FORMAT)
|
||||
@@ -17,90 +17,50 @@ class ProductPricelistItemExporter(Component):
|
||||
_usage = 'product.pricelist.item.exporter'
|
||||
|
||||
@api.model
|
||||
def update_restriction(self, binding):
|
||||
if any(binding.restriction_id.channel_bind_ids):
|
||||
try:
|
||||
# FIXME: Supossed that only exists one channel connector per record
|
||||
binding.channel_pushed = True
|
||||
return self.backend_adapter.update_rplan_values(
|
||||
binding.restriction_id.channel_bind_ids[0].external_id,
|
||||
binding.date,
|
||||
{
|
||||
'min_stay': binding.min_stay or 0,
|
||||
'min_stay_arrival': binding.min_stay_arrival or 0,
|
||||
'max_stay': binding.max_stay or 0,
|
||||
'max_stay_arrival': binding.max_stay_arrival or 0,
|
||||
'closed': binding.closed and 1 or 0,
|
||||
'closed_arrival': binding.closed_arrival and 1 or 0,
|
||||
'closed_departure': binding.closed_departure and 1 or 0,
|
||||
})
|
||||
except ChannelConnectorError as err:
|
||||
self.create_issue(
|
||||
backend=self.backend_adapter.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't update restriction in WuBook"),
|
||||
channel_message=err.data['message'])
|
||||
|
||||
@api.model
|
||||
def push_restriction(self):
|
||||
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([
|
||||
def push_pricelist(self):
|
||||
channel_product_pricelist_item_obj = self.env['channel.product.pricelist.item']
|
||||
channel_product_pricelist_obj = self.env['channel.product.pricelist']
|
||||
channel_room_type_obj = self.env['channel.hotel.room.type']
|
||||
channel_unpushed = channel_product_pricelist_item_obj.search([
|
||||
('channel_pushed', '=', False),
|
||||
('date', '>=', fields.Date.today())
|
||||
], order="date ASC")
|
||||
if any(unpushed):
|
||||
date_start = fields.Date.from_string(unpushed[0].date)
|
||||
date_end = fields.Date.from_string(unpushed[-1].date)
|
||||
days_diff = (date_end-date_start).days + 1
|
||||
restrictions = {}
|
||||
channel_restr_plan_ids = channel_room_type_rest_obj.search([])
|
||||
for rp in channel_restr_plan_ids:
|
||||
restrictions.update({rp.external_id: {}})
|
||||
unpushed_rp = channel_rest_item_obj.search([
|
||||
('channel_pushed', '=', False),
|
||||
('restriction_id', '=', rp.odoo_id.id)
|
||||
])
|
||||
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
|
||||
restrictions[rp.external_id].update({
|
||||
room_type_external_id: [],
|
||||
})
|
||||
('date_start', '>=', datetime.now().strftime(
|
||||
DEFAULT_SERVER_DATE_FORMAT))
|
||||
], order="date_start ASC")
|
||||
if any(channel_unpushed):
|
||||
date_start = fields.Date.from_string(channel_unpushed[0].date_start)
|
||||
date_end = fields.Date.from_string(channel_unpushed[-1].date_start)
|
||||
days_diff = (date_start - date_end).days + 1
|
||||
|
||||
prices = {}
|
||||
pricelist_ids = channel_product_pricelist_obj.search([
|
||||
('external_id', '!=', False),
|
||||
('active', '=', True)
|
||||
])
|
||||
for pr in pricelist_ids:
|
||||
prices.update({pr.external_id: {}})
|
||||
unpushed_pl = channel_product_pricelist_item_obj.search(
|
||||
[('channel_pushed', '=', False), ('pricelist_id', '=', pr.id)])
|
||||
product_tmpl_ids = unpushed_pl.mapped('product_tmpl_id')
|
||||
for pt_id in product_tmpl_ids:
|
||||
channel_room_type = channel_room_type_obj.search([
|
||||
('product_id.product_tmpl_id', '=', pt_id.id)
|
||||
], limit=1)
|
||||
if channel_room_type:
|
||||
prices[pr.external_id].update({channel_room_type.external_id: []})
|
||||
for i in range(0, days_diff):
|
||||
ndate_dt = date_start + timedelta(days=i)
|
||||
restr = room_type.get_restrictions(
|
||||
ndate_dt.strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
rp.odoo_id.id)
|
||||
if restr:
|
||||
restrictions[rp.external_id][room_type_external_id].append({
|
||||
'min_stay': restr.min_stay or 0,
|
||||
'min_stay_arrival': restr.min_stay_arrival or 0,
|
||||
'max_stay': restr.max_stay or 0,
|
||||
'max_stay_arrival': restr.max_stay_arrival or 0,
|
||||
'closed': restr.closed and 1 or 0,
|
||||
'closed_arrival': restr.closed_arrival and 1 or 0,
|
||||
'closed_departure': restr.closed_departure and 1 or 0,
|
||||
prod = channel_room_type.product_id.with_context({
|
||||
'quantity': 1,
|
||||
'pricelist': pr.id,
|
||||
'date': (date_start + timedelta(days=i)).
|
||||
strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
})
|
||||
else:
|
||||
restrictions[rp.external_id][room_type_external_id].append({})
|
||||
_logger.info("==[ODOO->CHANNEL]==== UPDATING RESTRICTIONS ==")
|
||||
_logger.info(restrictions)
|
||||
for k_res, v_res in restrictions.items():
|
||||
if any(v_res):
|
||||
try:
|
||||
self.backend_adapter.update_rplan_values(
|
||||
int(k_res),
|
||||
date_start.strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
v_res)
|
||||
except ChannelConnectorError as err:
|
||||
self.create_issue(
|
||||
backend=self.backend_adapter.id,
|
||||
section='restriction',
|
||||
internal_message=_("Can't update restrictions in WuBook"),
|
||||
channel_message=err.data['message'])
|
||||
unpushed.with_context({
|
||||
'wubook_action': False}).write({'channel_pushed': True})
|
||||
prices[pr.external_id][channel_room_type.external_id].append(prod.price)
|
||||
_logger.info("==[ODOO->CHANNEL]==== PRICELISTS ==")
|
||||
_logger.info(prices)
|
||||
for k_pk, v_pk in prices.items():
|
||||
if any(v_pk):
|
||||
self.backend_adapter.update_plan_prices(k_pk, date_start.strftime(
|
||||
DEFAULT_SERVER_DATE_FORMAT), v_pk)
|
||||
|
||||
channel_unpushed.write({'channel_pushed': True})
|
||||
return True
|
||||
|
||||
@@ -20,6 +20,9 @@ class ProductPricelistItemImporter(Component):
|
||||
|
||||
@api.model
|
||||
def _generate_pricelist_items(self, channel_plan_id, date_from, date_to, plan_prices):
|
||||
_logger.info("==[CHANNEL->ODOO]==== PRICELISTS [%d] (%s - %s) ==",
|
||||
int(channel_plan_id), date_from, date_to)
|
||||
_logger.info(plan_prices)
|
||||
channel_hotel_room_type_obj = self.env['channel.hotel.room.type']
|
||||
pricelist_bind = self.env['channel.product.pricelist'].search([
|
||||
('external_id', '=', channel_plan_id)
|
||||
@@ -58,10 +61,12 @@ class ProductPricelistItemImporter(Component):
|
||||
], limit=1)
|
||||
if pricelist_item:
|
||||
pricelist_item.with_context({
|
||||
'wubook_action': False}).write(map_record.values())
|
||||
'connector_no_export': True,
|
||||
}).write(map_record.values())
|
||||
else:
|
||||
channel_pricelist_item_obj.with_context({
|
||||
'wubook_action': False}).create(map_record.values(for_create=True))
|
||||
'connector_no_export': True,
|
||||
}).create(map_record.values(for_create=True))
|
||||
return True
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -41,24 +41,6 @@
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="import" string="Imports">
|
||||
<p class="oe_grey oe_inline">
|
||||
By clicking on the buttons,
|
||||
you will initiate the synchronizations
|
||||
with Channel.
|
||||
Note that the import or exports
|
||||
won't be done directly,
|
||||
they will create 'Jobs'
|
||||
executed as soon as possible.
|
||||
</p>
|
||||
<p class="oe_grey oe_inline">
|
||||
Once imported,
|
||||
some types of records,
|
||||
like the reservations,
|
||||
need a manual review.
|
||||
You will find the list
|
||||
of the new records to review
|
||||
in the menu 'Connectors > Checkpoint'.
|
||||
</p>
|
||||
<group>
|
||||
<label string="Import Reservations" class="oe_inline"/>
|
||||
<div>
|
||||
@@ -147,7 +129,7 @@
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<label string="Push Restriction" class="oe_inline"/>
|
||||
<label string="Push Restrictions" class="oe_inline"/>
|
||||
<div>
|
||||
<button name="push_restriction"
|
||||
type="object"
|
||||
@@ -155,6 +137,15 @@
|
||||
string="Export in background"/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<label string="Push Pricelists" class="oe_inline"/>
|
||||
<div>
|
||||
<button name="push_pricelist"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
string="Export in background"/>
|
||||
</div>
|
||||
</group>
|
||||
</page>
|
||||
<page name="otas" string="OTA's">
|
||||
<field name="ota_ids" nolabel="1">
|
||||
|
||||
Reference in New Issue
Block a user