[WIP][MIG][11.0] Hotel module review

This commit is contained in:
QS5ELkMu
2018-09-03 21:08:06 +02:00
parent d2363b7736
commit 0c7b3edd77
79 changed files with 675 additions and 962 deletions

View File

@@ -1,7 +1,7 @@
<odoo>
<data noupdate="1">
<record model="hotel.virtual.room.restriction">
<record model="hotel.room.type.restriction">
<field name="name">Default Restrictions</field>
</record>

View File

@@ -4356,7 +4356,7 @@ msgid "Gives the sequence order when displaying a product list"
msgstr "Proporciona el orden de secuencia al mostrar una lista de productos"
#. module: hotel
#: selection:hotel.virtual.room.restriction.item,applied_on:0
#: selection:hotel.room.type.restriction.item,applied_on:0
#: selection:hotel.wizard.massive.changes,applied_on:0
msgid "Global"
msgstr "Global"
@@ -7285,7 +7285,7 @@ msgstr "Proveedores"
#. module: hotel
#: selection:hotel.room,sale_price_type:0
#: selection:hotel.virtual.room.restriction.item,applied_on:0
#: selection:hotel.room.type.restriction.item,applied_on:0
#: selection:hotel.wizard.massive.changes,applied_on:0
#: model:ir.model.fields,field_description:hotel.field_hotel_virtual_room_availability_virtual_room_id
#: model:ir.model.fields,field_description:hotel.field_hotel_virtual_room_restriction_item_virtual_room_id
@@ -7585,8 +7585,8 @@ msgstr "hotel.virtual.room"
#. module: hotel
#: model:ir.model,name:hotel.model_hotel_virtual_room_availability
msgid "hotel.virtual.room.availability"
msgstr "hotel.virtual.room.availability"
msgid "hotel.room.type.availability"
msgstr "hotel.room.type.availability"
#. module: hotel
#: model:ir.model,name:hotel.model_hotel_virtual_room_availabity
@@ -7595,13 +7595,13 @@ msgstr "hotel.virtual.room.availabity"
#. module: hotel
#: model:ir.model,name:hotel.model_hotel_virtual_room_restriction
msgid "hotel.virtual.room.restriction"
msgstr "hotel.virtual.room.restriction"
msgid "hotel.room.type.restriction"
msgstr "hotel.room.type.restriction"
#. module: hotel
#: model:ir.model,name:hotel.model_hotel_virtual_room_restriction_item
msgid "hotel.virtual.room.restriction.item"
msgstr "hotel.virtual.room.restriction.item"
msgid "hotel.room.type.restriction.item"
msgstr "hotel.room.type.restriction.item"
#. module: hotel
#: model:ir.model,name:hotel.model_hotel_wizard_duplicate_reservation

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Alexandre Díaz
# Copyright 2018 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import currency_exchange
@@ -21,11 +21,11 @@ from . import inherit_product_product
from . import inherit_res_company
# from . import virtual_room
from . import inherit_account_payment
from . import hotel_virtual_room_restriction
from . import hotel_virtual_room_restriction_item
from . import hotel_room_type_restriction
from . import hotel_room_type_restriction_item
from . import hotel_reservation_line
from . import cardex
from . import hotel_virtual_room_availability
from . import hotel_room_type_availability
from . import inherit_product_pricelist
from . import res_config
from . import inherit_res_partner

View File

@@ -1,25 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Dario Lodeiros <>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Dario Lodeiros
# Copyright 2018 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import datetime
from openerp import models, fields, api, _
from openerp.exceptions import except_orm, ValidationError

View File

@@ -1,10 +1,12 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Dario Lodeiros
# Copyright 2018 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from decimal import Decimal
import time
# For Python 3.0 and later
from urllib.request import urlopen
from openerp import models, fields, api, _
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class CurrencyExchangeRate(models.Model):

View File

@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Alexandre Díaz
# Copyright 2018 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import json
from datetime import datetime, timedelta
@@ -11,17 +10,19 @@ from odoo.tools.misc import formatLang
class HotelDashboard(models.Model):
_name = "hotel.dashboard"
# FIXME
def _get_count(self):
resevations_count = self.env['hotel.reservation'].search(
resevations_count = self.env['hotel.reservation'].search_count(
[('sate', '=', 'confirm')])
folios_count = self.env['hotel.folio'].search(
folios_count = self.env['hotel.folio'].search_count(
[('sate', '=', 'sales_order')])
next_arrivals_count = self.env['hotel.reservation'].search(
next_arrivals_count = self.env['hotel.reservation'].search_count(
[('is_checkin', '=', True)])
self.orders_count = len(orders_count)
self.quotations_count = len(quotations_count)
self.orders_done_count = len(orders_done_count)
@api.one
def _kanban_dashboard(self):
if self.graph_type == 'bar':
@@ -40,25 +41,33 @@ class HotelDashboard(models.Model):
color = fields.Integer(string='Color Index')
name = fields.Char(string="Name")
type = fields.Char(default="sale")
graph_type = fields.Selection([('line','Line'),('bar','Bar'),('none','None')])
reservations_count = fields.Integer(compute = '_get_count')
folios_count = fields.Integer(compute= '_get_count')
next_arrivals_count = fields.Integer(compute= '_get_count')
graph_type = fields.Selection([
('line', 'Line'),
('bar', 'Bar'),
('none', 'None')])
reservations_count = fields.Integer(compute='_get_count')
folios_count = fields.Integer(compute='_get_count')
next_arrivals_count = fields.Integer(compute='_get_count')
kanban_dashboard = fields.Text(compute='_kanban_dashboard')
kanban_dashboard_graph = fields.Text(compute='_kanban_dashboard_graph')
show_on_dashboard = fields.Boolean(string='Show journal on dashboard', help="Whether this journal should be displayed on the dashboard or not", default=True)
show_on_dashboard = fields.Boolean(
string='Show journal on dashboard',
help="Whether this journal should be displayed on the dashboard or not",
default=True)
@api.multi
def get_bar_graph_datas(self):
data = []
today = datetime.strptime(fields.Date.context_today(self), DF)
day_of_week = int(format_datetime(today, 'e', locale=self._context.get('lang') or 'en_US'))
for i in range(0,15):
if i==0:
for i in range(0, 15):
if i == 0:
label = _('Today')
else:
label = format_date(today + timedelta(days=i) , 'd', locale=self._context.get('lang') or 'en_US')
data.append({'label':label,'value':0.0, 'type': 'past' if i<0 else 'future'})
label = format_date(today + timedelta(days=i),
'd',
locale=self._context.get('lang') or 'en_US')
data.append({'label':label, 'value':0.0, 'type': 'past' if i < 0 else 'future'})
# Build SQL query to find amount aggregated by week
select_sql_clause = """SELECT count(id) as total from hotel_reservation where state != 'cancelled'"""
query = "("+select_sql_clause+" and date(checkin) = '"+today.strftime(DF)+"')"
@@ -68,8 +77,8 @@ class HotelDashboard(models.Model):
self.env.cr.execute(query)
query_results = self.env.cr.dictfetchall()
for index in range(0, len(query_results)):
data[index]['value'] = query_results[index].get('total')
for index_k, index_v in enumerate(query_results):
data[index_k]['value'] = index_v.get('total')
return [{'values': data}]
@api.multi

View File

@@ -1,30 +1,9 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Dario Lodeiros <>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
class HotelFloor(models.Model):
_name = "hotel.floor"
_description = "Ubication"

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017-2018 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import datetime
from datetime import datetime
import time
import pytz
import logging
@@ -78,9 +77,9 @@ class HotelFolio(models.Model):
help="Hotel room reservation detail.",)
service_line_ids = fields.One2many('hotel.service', 'folio_id',
readonly=False,
states={'done': [('readonly', True)]},
help="Hotel services detail provide to "
readonly=False,
states={'done': [('readonly', True)]},
help="Hotel services detail provide to "
"customer and it will include in "
"main Invoice.")
hotel_invoice_id = fields.Many2one('account.invoice', 'Invoice')
@@ -98,23 +97,21 @@ class HotelFolio(models.Model):
'sent': [('readonly', False)]},
help="Pricelist for current folio.")
pending_amount = fields.Monetary(compute='compute_amount',
store=True,
string="Pending in Folio")
store=True,
string="Pending in Folio")
refund_amount = fields.Monetary(compute='compute_amount',
store=True,
string="Payment Returns")
invoices_paid = fields.Monetary(compute='compute_amount',
store=True, track_visibility='onchange',
string="Payments")
store=True, track_visibility='onchange',
string="Payments")
booking_pending = fields.Integer('Booking pending',
compute='_compute_cardex_count')
cardex_count = fields.Integer('Cardex counter',
compute='_compute_cardex_count')
cardex_pending = fields.Boolean('Cardex Pending',
compute='_compute_cardex_count')
cardex_pending_num = fields.Integer('Cardex Pending',
compute='_compute_cardex_count')
cardex_pending_count = fields.Integer('Cardex Pending',
compute='_compute_cardex_count')
checkins_reservations = fields.Integer('checkins reservations')
checkouts_reservations = fields.Integer('checkouts reservations')
partner_internal_comment = fields.Text(string='Internal Partner Notes',
@@ -173,12 +170,11 @@ class HotelFolio(models.Model):
sequence = fields.Integer(string='Sequence', default=10)
# sale.order
amount_total = fields.Float(string='Total', store=True, readonly=True,
track_visibility='always')
track_visibility='always')
def _computed_rooms_char(self):
for record in self:
rooms = ', '.join(record.mapped('room_lines.room_id.name'))
record.rooms_char = rooms
record.rooms_char = ', '.join(record.mapped('room_lines.room_id.name'))
@api.multi
def _compute_num_invoices(self):
@@ -219,9 +215,8 @@ class HotelFolio(models.Model):
def action_payments(self):
self.ensure_one()
payments_obj = self.env['account.payment']
payments = payments_obj.search([('folio_id','=',self.id)])
payment_ids = payments.mapped('id')
invoices = self.mapped('invoice_ids.id')
payments = payments_obj.search([('folio_id', '=', self.id)])
#invoices = self.mapped('invoice_ids.id')
return{
'name': _('Payments'),
'view_type': 'form',
@@ -229,7 +224,7 @@ class HotelFolio(models.Model):
'res_model': 'account.payment',
'target': 'new',
'type': 'ir.actions.act_window',
'domain': [('id', 'in', payment_ids)],
'domain': [('id', 'in', payments.ids)],
}
@api.multi
@@ -251,16 +246,16 @@ class HotelFolio(models.Model):
return_move_ids = []
acc_pay_obj = self.env['account.payment']
payments = acc_pay_obj.search([
'|',
('invoice_ids', 'in', self.invoice_ids.ids),
('folio_id', '=', self.id)
])
'|',
('invoice_ids', 'in', self.invoice_ids.ids),
('folio_id', '=', self.id)
])
return_move_ids += self.invoice_ids.filtered(
lambda invoice: invoice.type == 'out_refund').mapped(
'payment_move_line_ids.move_id.id')
return_lines = self.env['payment.return.line'].search([(
'move_line_ids','in',payments.mapped(
'move_line_ids.id'))])
'payment_move_line_ids.move_id.id')
return_lines = self.env['payment.return.line'].search([
('move_line_ids', 'in', payments.mapped('move_line_ids.id')),
])
return_move_ids += return_lines.mapped('return_id.move_id.id')
return{
@@ -323,19 +318,24 @@ class HotelFolio(models.Model):
# }
@api.model
def create(self, vals, check=True):
def create(self, vals):
if vals.get('name', _('New')) == _('New'):
if 'company_id' in vals:
vals['name'] = self.env['ir.sequence'].with_context(force_company=vals['company_id']).next_by_code('sale.order') or _('New')
vals['name'] = self.env['ir.sequence'].with_context(
force_company=vals['company_id']
).next_by_code('sale.order') or _('New')
else:
vals['name'] = self.env['ir.sequence'].next_by_code('hotel.folio') or _('New')
# Makes sure partner_invoice_id' and 'pricelist_id' are defined
if any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']):
lfields = ('partner_invoice_id', 'partner_shipping_id', 'pricelist_id')
if any(f not in vals for f in lfields):
partner = self.env['res.partner'].browse(vals.get('partner_id'))
addr = partner.address_get(['delivery', 'invoice'])
vals['partner_invoice_id'] = vals.setdefault('partner_invoice_id', addr['invoice'])
vals['pricelist_id'] = vals.setdefault('pricelist_id', partner.property_product_pricelist and partner.property_product_pricelist.id)
vals['pricelist_id'] = vals.setdefault(
'pricelist_id',
partner.property_product_pricelist and partner.property_product_pricelist.id)
result = super(HotelFolio, self).create(vals)
return result
@@ -358,12 +358,15 @@ class HotelFolio(models.Model):
addr = self.partner_id.address_get(['invoice'])
values = {
'pricelist_id': self.partner_id.property_product_pricelist and self.partner_id.property_product_pricelist.id or False,
'pricelist_id': self.partner_id.property_product_pricelist and \
self.partner_id.property_product_pricelist.id or False,
'partner_invoice_id': addr['invoice'],
'user_id': self.partner_id.user_id.id or self.env.uid
}
if self.env['ir.config_parameter'].sudo().get_param('sale.use_sale_note') and self.env.user.company_id.sale_note:
values['note'] = self.with_context(lang=self.partner_id.lang).env.user.company_id.sale_note
if self.env['ir.config_parameter'].sudo().get_param('sale.use_sale_note') and \
self.env.user.company_id.sale_note:
values['note'] = self.with_context(
lang=self.partner_id.lang).env.user.company_id.sale_note
if self.partner_id.team_id:
values['team_id'] = self.partner_id.team_id.id
@@ -409,10 +412,11 @@ class HotelFolio(models.Model):
@api.multi
def action_done(self):
for line in self.room_lines:
room_lines = self.mapped('room_lines')
for line in room_lines:
if line.state == "booking":
line.action_reservation_checkout()
@api.multi
def action_cancel(self):
'''
@@ -457,7 +461,7 @@ class HotelFolio(models.Model):
'domain': [('reservation_id', 'in', rooms)],
'target': 'new',
}
@api.model
def daily_plan(self):
_logger.info('daily_plan')
@@ -486,26 +490,19 @@ class HotelFolio(models.Model):
@api.multi
def _compute_cardex_count(self):
_logger.info('_compute_cardex_amount')
for fol in self:
num_cardex = 0
pending = False
if fol.reservation_type == 'normal':
for reser in fol.room_lines:
if reser.state != 'cancelled' and \
not reser.parent_reservation:
num_cardex += len(reser.cardex_ids)
fol.cardex_count = num_cardex
pending = 0
for reser in fol.room_lines:
if reser.state != 'cancelled' and \
not reser.parent_reservation:
pending += (reser.adults + reser.children) \
- len(reser.cardex_ids)
if pending <= 0:
fol.cardex_pending = False
else:
fol.cardex_pending = True
fol.cardex_pending_num = pending
for record in self:
if record.reservation_type == 'normal':
write_vals = {}
filtered_reservs = record.filtered(
lambda x: x.room_lines.state != 'cancelled' and \
not x.room_lines.parent_reservation)
mapped_cardex = filtered_reservs.mapped('cardex_ids.id')
write_vals.update({'cardex_count': len(mapped_cardex)})
mapped_cardex_count = filtered_reservs.mapped(
lambda x: (x.adults + x.children) - len(x.cardex_ids))
write_vals.update({'cardex_pending_count': sum(mapped_cardex_count)})
record.write(write_vals)
"""
MAILING PROCESS
@@ -586,15 +583,15 @@ class HotelFolio(models.Model):
self.ensure_one()
ir_model_data = self.env['ir.model.data']
try:
template_id = (ir_model_data.get_object_reference
('hotel',
'mail_template_hotel_reservation')[1])
template_id = ir_model_data.get_object_reference(
'hotel',
'mail_template_hotel_reservation')[1]
except ValueError:
template_id = False
try:
compose_form_id = (ir_model_data.get_object_reference
('mail',
'email_compose_message_wizard_form')[1])
compose_form_id = ir_model_data.get_object_reference(
'mail',
'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
ctx = dict()
@@ -632,15 +629,15 @@ class HotelFolio(models.Model):
self.ensure_one()
ir_model_data = self.env['ir.model.data']
try:
template_id = (ir_model_data.get_object_reference
('hotel',
'mail_template_hotel_exit')[1])
template_id = ir_model_data.get_object_reference(
'hotel',
'mail_template_hotel_exit')[1]
except ValueError:
template_id = False
try:
compose_form_id = (ir_model_data.get_object_reference
('mail',
'email_compose_message_wizard_form')[1])
compose_form_id = ir_model_data.get_object_reference(
'mail',
'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
ctx = dict()
@@ -679,15 +676,15 @@ class HotelFolio(models.Model):
self.ensure_one()
ir_model_data = self.env['ir.model.data']
try:
template_id = (ir_model_data.get_object_reference
('hotel',
'mail_template_hotel_cancel')[1])
template_id = ir_model_data.get_object_reference(
'hotel',
'mail_template_hotel_cancel')[1]
except ValueError:
template_id = False
try:
compose_form_id = (ir_model_data.get_object_reference
('mail',
'email_compose_message_wizard_form')[1])
compose_form_id = ir_model_data.get_object_reference(
'mail',
'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
ctx = dict()
@@ -722,15 +719,14 @@ class HotelFolio(models.Model):
@param self: The object pointer
@return: send a mail
"""
now_str = time.strftime(dt)
now_date = datetime.strptime(now_str, dt)
now_date = fields.Datetime.now()
ir_model_data = self.env['ir.model.data']
template_id = (ir_model_data.get_object_reference
('hotel_reservation',
'mail_template_reservation_reminder_24hrs')[1])
template_id = ir_model_data.get_object_reference(
'hotel_reservation',
'mail_template_reservation_reminder_24hrs')[1]
template_rec = self.env['mail.template'].browse(template_id)
for reserv_rec in self.search([]):
checkin_date = (datetime.strptime(reserv_rec.checkin, dt))
checkin_date = datetime.strptime(reserv_rec.checkin, dt)
difference = relativedelta(now_date, checkin_date)
if(difference.days == -1 and reserv_rec.partner_id.email and
reserv_rec.state == 'confirm'):
@@ -742,11 +738,17 @@ class HotelFolio(models.Model):
self.ensure_one()
info_grouped = []
for rline in self.room_lines:
if (import_all or rline.to_send) and not rline.parent_reservation and rline.state == state:
if (import_all or rline.to_send) and \
not rline.parent_reservation and rline.state == state:
dates = rline.get_real_checkin_checkout()
vals = {
'num': len(
self.room_lines.filtered(lambda r: r.get_real_checkin_checkout()[0] == dates[0] and r.get_real_checkin_checkout()[1] == dates[1] and r.room_type_id.id == rline.room_type_id.id and (r.to_send or import_all) and not r.parent_reservation and r.state == rline.state)
self.room_lines.filtered(
lambda r: r.get_real_checkin_checkout()[0] == dates[0] and \
r.get_real_checkin_checkout()[1] == dates[1] and \
r.room_type_id.id == rline.room_type_id.id and \
(r.to_send or import_all) and not r.parent_reservation and \
r.state == rline.state)
),
'room_type': {
'id': rline.room_type_id.id,
@@ -760,10 +762,13 @@ class HotelFolio(models.Model):
}
founded = False
for srline in info_grouped:
if srline['num'] == vals['num'] and srline['room_type']['id'] == vals['room_type']['id'] and srline['checkin'] == vals['checkin'] and srline['checkout'] == vals['checkout']:
if srline['num'] == vals['num'] and \
srline['room_type']['id'] == vals['room_type']['id'] and \
srline['checkin'] == vals['checkin'] and \
srline['checkout'] == vals['checkout']:
founded = True
break
if not founded:
info_grouped.append(vals)
return sorted(sorted(info_grouped, key=lambda k: k['num'], reverse=True), key=lambda k: k['room_type']['id'])
return sorted(sorted(info_grouped,key=lambda k: k['num'], reverse=True),
key=lambda k: k['room_type']['id'])

View File

@@ -1,24 +1,19 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017-2018 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.exceptions import except_orm, UserError, ValidationError
import logging
import time
from datetime import timedelta
from odoo.exceptions import UserError, ValidationError
from odoo.tools import (
misc,
DEFAULT_SERVER_DATE_FORMAT,
DEFAULT_SERVER_DATETIME_FORMAT)
from odoo import models, fields, api, _
from decimal import Decimal
from dateutil.relativedelta import relativedelta
from dateutil import tz
from datetime import datetime, timedelta, date
from odoo.addons import decimal_precision as dp
from odoo.addons.hotel import date_utils
import pytz
import time
import logging
_logger = logging.getLogger(__name__)
from odoo.addons import decimal_precision as dp
class HotelReservation(models.Model):
@@ -48,7 +43,8 @@ class HotelReservation(models.Model):
tz_hotel = self.env['ir.default'].sudo().get(
'res.config.settings', 'tz_hotel')
today = fields.Date.context_today(self.with_context(tz=tz_hotel))
return (fields.Date.from_string(today) + timedelta(days=1)).strftime(DEFAULT_SERVER_DATE_FORMAT)
return (fields.Date.from_string(today) + timedelta(days=1)).strftime(
DEFAULT_SERVER_DATE_FORMAT)
def _get_default_arrival_hour(self):
folio = False
@@ -102,18 +98,17 @@ class HotelReservation(models.Model):
# Has this reservation more charges associates in folio?, Yes?, then, this is share folio ;)
for record in self:
if record.folio_id:
if len(record.folio_id.room_lines) > 1 or \
record.folio_id.service_line_ids.filtered(lambda x: (
x.ser_room_line != record.id)):
record.shared_folio = True
else:
record.shared_folio = False
record.shared_folio = len(record.folio_id.room_lines) > 1 or \
any(record.folio_id.service_line_ids.filtered(
lambda x: x.ser_room_line != record.id))
@api.depends('checkin', 'checkout')
def _computed_nights(self):
for res in self:
if res.checkin and res.checkout:
res.nights = (fields.Date.from_string(res.checkout) - fields.Date.from_string(res.checkin)).days
res.nights = (
fields.Date.from_string(res.checkout) - fields.Date.from_string(res.checkin)
).days
_name = 'hotel.reservation'
_description = 'Hotel Reservation'
@@ -191,11 +186,9 @@ class HotelReservation(models.Model):
# The value is a method name returning a Domains
cardex_count = fields.Integer('Cardex counter',
compute='_compute_cardex_count')
cardex_pending = fields.Boolean('Cardex Pending',
compute='_compute_cardex_count',
search='_search_cardex_pending')
cardex_pending_num = fields.Integer('Cardex Pending Num',
compute='_compute_cardex_count')
cardex_pending_count = fields.Integer('Cardex Pending Num',
compute='_compute_cardex_count',
search='_search_cardex_pending')
# check_rooms = fields.Boolean('Check Rooms')
is_checkin = fields.Boolean()
is_checkout = fields.Boolean()
@@ -226,29 +219,31 @@ class HotelReservation(models.Model):
preconfirm = fields.Boolean('Auto confirm to Save', default=True)
to_send = fields.Boolean('To Send', default=True)
has_confirmed_reservations_to_send = fields.Boolean(
related='folio_id.has_confirmed_reservations_to_send',
readonly=True)
related='folio_id.has_confirmed_reservations_to_send',
readonly=True)
has_cancelled_reservations_to_send = fields.Boolean(
related='folio_id.has_cancelled_reservations_to_send',
readonly=True)
related='folio_id.has_cancelled_reservations_to_send',
readonly=True)
has_checkout_to_send = fields.Boolean(
related='folio_id.has_checkout_to_send',
readonly=True)
related='folio_id.has_checkout_to_send',
readonly=True)
# order_line = fields.One2many('sale.order.line', 'order_id', string='Order Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True, auto_join=True)
# product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product')
# product_uom = fields.Many2one('product.uom', string='Unit of Measure', required=True)
# product_uom_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product Unit of Measure'), required=True, default=1.0)
currency_id = fields.Many2one('res.currency',
related='pricelist_id.currency_id',
string='Currency', readonly=True, required=True)
related='pricelist_id.currency_id',
string='Currency', readonly=True, required=True)
# invoice_status = fields.Selection([
# ('upselling', 'Upselling Opportunity'),
# ('invoiced', 'Fully Invoiced'),
# ('to invoice', 'To Invoice'),
# ('no', 'Nothing to Invoice')
# ], string='Invoice Status', compute='_compute_invoice_status', store=True, readonly=True, default='no')
tax_id = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)])
tax_id = fields.Many2many('account.tax',
string='Taxes',
domain=['|', ('active', '=', False), ('active', '=', True)])
# qty_to_invoice = fields.Float(
# string='To Invoice', store=True, readonly=True,
# digits=dp.get_precision('Product Unit of Measure'))
@@ -257,9 +252,18 @@ class HotelReservation(models.Model):
# digits=dp.get_precision('Product Unit of Measure'))
# qty_delivered = fields.Float(string='Delivered', copy=False, digits=dp.get_precision('Product Unit of Measure'), default=0.0)
# qty_delivered_updateable = fields.Boolean(compute='_compute_qty_delivered_updateable', string='Can Edit Delivered', readonly=True, default=True)
price_subtotal = fields.Monetary(string='Subtotal', readonly=True, store=True, compute='_compute_amount_reservation')
price_total = fields.Monetary(string='Total', readonly=True, store=True, compute='_compute_amount_reservation')
price_tax = fields.Float(string='Taxes', readonly=True, store=True, compute='_compute_amount_reservation')
price_subtotal = fields.Monetary(string='Subtotal',
readonly=True,
store=True,
compute='_compute_amount_reservation')
price_total = fields.Monetary(string='Total',
readonly=True,
store=True,
compute='_compute_amount_reservation')
price_tax = fields.Float(string='Taxes',
readonly=True,
store=True,
compute='_compute_amount_reservation')
# FIXME discount per night
discount = fields.Float(string='Discount (%)', digits=dp.get_precision('Discount'), default=0.0)
@@ -286,11 +290,13 @@ class HotelReservation(models.Model):
#~ 'reserve_color_text': colors[1],
})
if self.compute_price_out_vals(vals):
days_diff = (fields.Date.from_string(vals['checkout']) - fields.Date.from_string(vals['checkin'])).days
vals.update(record.prepare_reservation_lines(
days_diff = (
fields.Date.from_string(vals['checkout']) - fields.Date.from_string(vals['checkin'])
).days
vals.update(self.prepare_reservation_lines(
vals['checkin'],
days_diff,
vals = vals)) #REVISAR el unlink
vals=vals)) #REVISAR el unlink
record = super(HotelReservation, self).create(vals)
#~ if (record.state == 'draft' and record.folio_id.state == 'sale') or \
#~ record.preconfirm:
@@ -301,18 +307,22 @@ class HotelReservation(models.Model):
def write(self, vals):
if self.notify_update(vals):
vals.update({
'last_updated_res': date_utils.now(hours=True).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
'last_updated_res': date_utils.now(hours=True).strftime(
DEFAULT_SERVER_DATETIME_FORMAT)
})
for record in self:
if record.compute_price_out_vals(vals):
days_diff = (fields.Date.from_string(record.checkout) - fields.Date.from_string(record.checkin)).days
days_diff = (
fields.Date.from_string(record.checkout) - \
fields.Date.from_string(record.checkin)
).days
record.update(record.prepare_reservation_lines(
vals['checkin'],
days_diff,
vals = vals)) #REVISAR el unlink
vals=vals)) #REVISAR el unlink
if ('checkin' in vals and record.checkin != vals['checkin']) or \
('checkout' in vals and record.checkout != vals['checkout']) or \
('state' in vals and record.state != vals['state']) :
('state' in vals and record.state != vals['state']):
vals.update({'to_send': True})
res = super(HotelReservation, self).write(vals)
return res
@@ -321,9 +331,9 @@ class HotelReservation(models.Model):
def _prepare_add_missing_fields(self, values):
""" Deduce missing required fields from the onchange """
res = {}
onchange_fields = ['room_id', 'pricelist_id',
'reservation_type', 'currency_id']
if values.get('partner_id') and values.get('room_type_id') and any(f not in values for f in onchange_fields):
onchange_fields = ['room_id', 'pricelist_id', 'reservation_type', 'currency_id']
if values.get('partner_id') and values.get('room_type_id') and \
any(f not in values for f in onchange_fields):
line = self.new(values)
line.onchange_room_id()
for field in onchange_fields:
@@ -345,7 +355,7 @@ class HotelReservation(models.Model):
@api.multi
def overbooking_button(self):
self.ensure_one()
return self.write({'overbooking': not self.overbooking})
self.overbooking = not self.overbooking
@api.multi
def open_folio(self):
@@ -388,8 +398,8 @@ class HotelReservation(models.Model):
def _check_adults(self):
for record in self:
if record.adults > record.room_id.capacity:
raise ValidationError(
_("Reservation persons can't be higher than room capacity"))
raise ValidationError(
_("Reservation persons can't be higher than room capacity"))
if record.adults == 0:
raise ValidationError(_("Reservation has no adults"))
@@ -399,22 +409,24 @@ class HotelReservation(models.Model):
@api.onchange('adults', 'room_id')
def onchange_room_id(self):
# TODO: Usar vals y write
if self.room_id:
write_vals = {}
if self.room_id.capacity < self.adults:
self.adults = self.room_id.capacity
raise UserError(
_('%s people do not fit in this room! ;)') % (persons))
_('%s people do not fit in this room! ;)') % (self.adults))
if self.adults == 0:
self.adults = self.room_id.capacity
if not self.room_type_id: #Si el registro no existe, modificar room_type aunque ya esté establecido
self.room_type_id = self.room_id.room_type_id
write_vals.update({'adults': self.room_id.capacity})
#Si el registro no existe, modificar room_type aunque ya esté establecido
if not self.room_type_id:
write_vals.update({'room_type_id': self.room_id.room_type_id.id})
self.write(write_vals)
@api.onchange('partner_id')
def onchange_partner_id(self):
#TODO: Change parity pricelist by default pricelist
values = {
'pricelist_id': self.partner_id.property_product_pricelist and self.partner_id.property_product_pricelist.id or \
'pricelist_id': self.partner_id.property_product_pricelist and \
self.partner_id.property_product_pricelist.id or \
self.env['ir.default'].sudo().get('res.config.settings', 'parity_pricelist_id'),
}
self.update(values)
@@ -423,11 +435,13 @@ class HotelReservation(models.Model):
@api.onchange('room_type_id', 'pricelist_id', 'reservation_type')
def onchange_overwrite_price_by_day(self):
if self.room_type_id and self.checkin and self.checkout:
days_diff = (fields.Date.from_string(self.checkout) - fields.Date.from_string(self.checkin)).days
days_diff = (
fields.Date.from_string(self.checkout) - fields.Date.from_string(self.checkin)
).days
self.update(self.prepare_reservation_lines(
self.checkin,
days_diff,
update_old_prices = True))
update_old_prices=True))
# When we need to update prices respecting those that were already established
@api.onchange('checkin', 'checkout')
@@ -439,15 +453,16 @@ class HotelReservation(models.Model):
checkin_dt = fields.Date.from_string(self.checkin)
checkout_dt = fields.Date.from_string(self.checkout)
if checkin_dt >= checkout_dt:
self.checkout = (fields.Date.from_string(self.checkin) + timedelta(days=1)).strftime(DEFAULT_SERVER_DATE_FORMAT)
self.checkout = (fields.Date.from_string(self.checkin) + timedelta(days=1)).strftime(
DEFAULT_SERVER_DATE_FORMAT)
if self.room_type_id:
days_diff = (fields.Date.from_string(self.checkout) - fields.Date.from_string(self.checkin)).days
days_diff = (
fields.Date.from_string(self.checkout) - fields.Date.from_string(self.checkin)
).days
self.update(self.prepare_reservation_lines(
self.checkin,
days_diff,
update_old_prices = False))
update_old_prices=False))
@api.onchange('checkin', 'checkout', 'room_type_id')
def onchange_compute_reservation_description(self):
@@ -468,8 +483,9 @@ class HotelReservation(models.Model):
return
occupied = self.env['hotel.reservation'].get_reservations(
self.checkin,
fields.Date.from_string(self.checkout).strftime(DEFAULT_SERVER_DATE_FORMAT)).filtered(
lambda r: r.id != self._origin.id)
fields.Date.from_string(self.checkout).strftime(
DEFAULT_SERVER_DATE_FORMAT)).filtered(
lambda r: r.id != self._origin.id)
rooms_occupied = occupied.mapped('room_id.id')
if self.room_id and self.room_id.id in rooms_occupied:
warning_msg = _('You tried to change \
@@ -488,7 +504,7 @@ class HotelReservation(models.Model):
@api.multi
def _generate_color(self):
self.ensure_one()
now_utc_dt = date_utils.now()
now_utc_dt = fields.Datetime.now()
# unused variables
# diff_checkin_now = date_utils.date_diff(now_utc_dt, self.checkin,
# hours=False)
@@ -502,26 +518,22 @@ class HotelReservation(models.Model):
return ('#4E9DC4', '#000000')
if self.reservation_type == 'staff':
reserv_color = ir_values_obj.get('res.config.settings',
'color_staff')
reserv_color = ir_values_obj.get('res.config.settings', 'color_staff')
reserv_color_text = ir_values_obj.get(
'res.config.settings',
'color_letter_staff')
elif self.reservation_type == 'out':
reserv_color = ir_values_obj.get('res.config.settings',
'color_dontsell')
reserv_color = ir_values_obj.get('res.config.settings', 'color_dontsell')
reserv_color_text = ir_values_obj.get(
'res.config.settings',
'color_letter_dontsell')
elif self.to_assign:
reserv_color = ir_values_obj.get('res.config.settings',
'color_to_assign')
reserv_color = ir_values_obj.get('res.config.settings', 'color_to_assign')
reserv_color_text = ir_values_obj.get(
'res.config.settings',
'color_letter_to_assign')
elif self.state == 'draft':
reserv_color = ir_values_obj.get('res.config.settings',
'color_pre_reservation')
reserv_color = ir_values_obj.get('res.config.settings', 'color_pre_reservation')
reserv_color_text = ir_values_obj.get(
'res.config.settings',
'color_letter_pre_reservation')
@@ -563,13 +575,13 @@ class HotelReservation(models.Model):
@api.depends('state', 'reservation_type', 'folio_id.pending_amount', 'to_assign')
def _compute_color(self):
_logger.info('_compute_color')
for rec in self:
colors = rec._generate_color()
rec.update({
for record in self:
colors = record._generate_color()
record.update({
'reserve_color': colors[0],
'reserve_color_text': colors[1],
})
rec.folio_id.color = colors[0]
record.folio_id.color = colors[0]
# hotel_reserv_obj = self.env['hotel.reservation']
# if rec.splitted:
@@ -595,27 +607,28 @@ class HotelReservation(models.Model):
_logger.info('confirm')
hotel_folio_obj = self.env['hotel.folio']
hotel_reserv_obj = self.env['hotel.reservation']
for r in self:
for record in self:
vals = {}
if r.cardex_ids:
if record.cardex_ids:
vals.update({'state': 'booking'})
else:
vals.update({'state': 'confirm'})
if r.checkin_is_today():
if record.checkin_is_today():
vals.update({'is_checkin': True})
folio = hotel_folio_obj.browse(r.folio_id.id)
folio = hotel_folio_obj.browse(record.folio_id.id)
folio.checkins_reservations = folio.room_lines.search_count([
('folio_id', '=', folio.id), ('is_checkin', '=', True)])
r.write(vals)
record.write(vals)
if r.splitted:
master_reservation = r.parent_reservation or r
if record.splitted:
master_reservation = record.parent_reservation or record
splitted_reservs = hotel_reserv_obj.search([
('splitted', '=', True),
'|', ('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id),
('folio_id', '=', r.folio_id.id),
('id', '!=', r.id),
'|',
('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id),
('folio_id', '=', record.folio_id.id),
('id', '!=', record.id),
('state', '!=', 'confirm')
])
splitted_reservs.confirm()
@@ -626,8 +639,8 @@ class HotelReservation(models.Model):
'''
@param self: object pointer
'''
for res in self:
res.action_reservation_checkout()
for record in self:
record.action_reservation_checkout()
return True
@api.multi
@@ -649,8 +662,9 @@ class HotelReservation(models.Model):
master_reservation = record.parent_reservation or record
splitted_reservs = self.env['hotel.reservation'].search([
('splitted', '=', True),
'|', ('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id),
'|',
('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id),
('folio_id', '=', record.folio_id.id),
('id', '!=', record.id),
('state', '!=', 'cancelled')
@@ -661,14 +675,14 @@ class HotelReservation(models.Model):
@api.multi
def draft(self):
for record in self:
record.write({'state': 'draft'})
record.state = 'draft'
if record.splitted:
master_reservation = record.parent_reservation or record
splitted_reservs = self.env['hotel.reservation'].search([
('splitted', '=', True),
'|', ('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id),
'|',
('parent_reservation', '=', master_reservation.id),
('id', '=', master_reservation.id),
('folio_id', '=', record.folio_id.id),
('id', '!=', record.id),
('state', '!=', 'draft')
@@ -696,21 +710,19 @@ class HotelReservation(models.Model):
"""
Compute the amounts of the reservation.
"""
for line in self:
amount_room = 0
for day in line.reservation_line_ids:
amount_room += day.price
for record in self:
amount_room = sum(record.reservation_line_ids.mapped('price'))
if amount_room > 0:
product = line.room_type_id.product_id
price = amount_room * (1 - (line.discount or 0.0) / 100.0)
taxes = line.tax_id.compute_all(price, line.currency_id, 1, product=product)
line.update({
product = record.room_type_id.product_id
price = amount_room * (1 - (record.discount or 0.0) * 0.01)
taxes = record.tax_id.compute_all(price, record.currency_id, 1, product=product)
record.update({
'price_tax': sum(t.get('amount', 0.0) for t in taxes.get('taxes', [])),
'price_total': taxes['total_included'],
'price_subtotal': taxes['total_excluded'],
})
@api.multi
@api.model
def prepare_reservation_lines(self, dfrom, days, vals=False, update_old_prices=False):
total_price = 0.0
cmds = [(5, 0, 0)]
@@ -719,23 +731,24 @@ class HotelReservation(models.Model):
pricelist_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_pricelist_id')
#~ pricelist_id = vals.get('pricelist_id') or self.pricelist_id.id
product = self.env['hotel.room.type'].browse(vals.get('room_type_id') or self.room_type_id.id).product_id
room_type_id = vals.get('room_type_id') or self.room_type_id.id
product = self.env['hotel.room.type'].browse(room_type_id).product_id
old_lines_days = self.mapped('reservation_line_ids.date')
partner = self.env['res.partner'].browse(vals.get('partner_id') or self.partner_id.id)
total_price = 0
for i in range(0, days):
idate = (fields.Date.from_string(dfrom) + timedelta(days=i)).strftime(DEFAULT_SERVER_DATE_FORMAT)
idate = (fields.Date.from_string(dfrom) + timedelta(days=i)).strftime(
DEFAULT_SERVER_DATE_FORMAT)
old_line = self.reservation_line_ids.filtered(lambda r: r.date == idate)
if update_old_prices or (idate not in old_lines_days):
_logger.info("PASA 3")
product = product.with_context(
lang=partner.lang,
partner=partner.id,
quantity=1,
date=idate,
pricelist=pricelist_id,
uom=product.uom_id.id)
line_price = self.env['account.tax']._fix_tax_included_price_company(product.price, product.taxes_id, self.tax_id, self.company_id)
lang=partner.lang,
partner=partner.id,
quantity=1,
date=idate,
pricelist=pricelist_id,
uom=product.uom_id.id)
line_price = self.env['account.tax']._fix_tax_included_price_company(
product.price, product.taxes_id, self.tax_id, self.company_id)
if old_line:
cmds.append((1, old_line.id, {
'price': line_price
@@ -748,7 +761,6 @@ class HotelReservation(models.Model):
else:
line_price = old_line.price
cmds.append((4, old_line.id))
total_price += line_price
return {'reservation_line_ids': cmds}
@api.multi
@@ -798,7 +810,6 @@ class HotelReservation(models.Model):
('reservation_line_ids.date', '<', dto),
('state', '!=', 'cancelled'),
('overbooking', '=', False)]
reservations = self.env['hotel.reservation'].search(domain)
return self.env['hotel.reservation'].search(domain)
@api.model
@@ -860,21 +871,19 @@ class HotelReservation(models.Model):
@api.multi
def _compute_cardex_count(self):
_logger.info('_compute_cardex_count')
for res in self:
res.cardex_count = len(res.cardex_ids)
res.cardex_pending_num = (res.adults + res.children) \
- len(res.cardex_ids)
if (res.adults + res.children - len(res.cardex_ids)) <= 0:
res.cardex_pending = False
else:
res.cardex_pending = True
for record in self:
record.write({
'cardex_count': len(record.cardex_ids),
'cardex_pending_count': (record.adults + record.children) \
- len(record.cardex_ids)
})
# https://www.odoo.com/es_ES/forum/ayuda-1/question/calculated-fields-in-search-filter-possible-118501
@api.multi
def _search_cardex_pending(self, operator, value):
recs = self.search([]).filtered(lambda x: x.cardex_pending is True)
if recs:
return [('id', 'in', [x.id for x in recs])]
self.ensure_one()
recs = self.search([]).filtered(lambda x: x.cardex_pending_count > 0)
return [('id', 'in', [x.id for x in recs])] if recs else []
@api.multi
def action_reservation_checkout(self):
@@ -908,8 +917,7 @@ class HotelReservation(models.Model):
res.action_reservation_checkout()
reservations = self.env['hotel.reservation'].search([
('reservation_line_ids.date', 'in', [today_str,
yesterday_str]),
('reservation_line_ids.date', 'in', [today_str, yesterday_str]),
('state', 'in', ['confirm', 'booking'])
])
self._cr.execute("update hotel_reservation set is_checkin = False, \
@@ -932,8 +940,7 @@ class HotelReservation(models.Model):
@api.model
def checkin_is_today(self):
self.ensure_one()
tz_hotel = self.env['ir.default'].sudo().get(
'res.config.settings', 'tz_hotel')
tz_hotel = self.env['ir.default'].sudo().get('res.config.settings', 'tz_hotel')
today = fields.Date.context_today(self.with_context(tz=tz_hotel))
return self.checkin == today

View File

@@ -1,26 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import models, fields, api, _
# Copyright 2017-2018 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
from odoo.addons import decimal_precision as dp
from odoo.exceptions import except_orm, UserError, ValidationError
class HotelReservationLine(models.Model):
_name = "hotel.reservation.line"

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -12,7 +11,7 @@ class HotelRoom(models.Model):
_name = 'hotel.room'
_description = 'Hotel Room'
_order = "sequence, room_type_id, name"
name = fields.Char('Room Name', required=True)
active = fields.Boolean('Active', default=True)
sequence = fields.Integer('Sequence', default=0)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -6,7 +5,6 @@ from odoo import models, fields, api, _
class HotelRoomAmenities(models.Model):
_name = 'hotel.room.amenities'
_description = 'Room amenities'
# The record's name

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -6,7 +5,6 @@ from odoo import models, fields, api, _
class HotelRoomAmenitiesType(models.Model):
_name = 'hotel.room.amenities.type'
_description = 'Amenities Type'
# The record's name

View File

@@ -1,20 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from decimal import Decimal
from datetime import datetime, timedelta
import dateutil.parser
# For Python 3.0 and later
from urllib.request import urlopen
import time
from odoo.exceptions import except_orm, UserError, ValidationError
from odoo.tools import (
misc,
DEFAULT_SERVER_DATE_FORMAT,
DEFAULT_SERVER_DATETIME_FORMAT)
from odoo import models, fields, api, _
from odoo.addons.hotel import date_utils
from odoo import models, fields, api
class HotelRoomType(models.Model):
""" Before creating a 'room type', you need to consider the following:
@@ -68,7 +55,7 @@ class HotelRoomType(models.Model):
"""
self.ensure_one()
capacities = self.room_ids.mapped('capacity')
return any(capacities) and min(capacities) or 0
return min(capacities) if any(capacities) else 0
@api.model
# TODO Rename to check_availability_room_type
@@ -93,7 +80,7 @@ class HotelRoomType(models.Model):
room_type_id = self.env['hotel.room.type'].search([
('id', '=', room_type_id)
])
# QUESTION What linked represent? Rooms in this type ?
# QUESTION What linked represent? Rooms in this type ?
rooms_linked = self.room_ids
free_rooms = free_rooms & rooms_linked
return free_rooms.sorted(key=lambda r: r.sequence)
@@ -106,9 +93,11 @@ class HotelRoomType(models.Model):
@param vals: dictionary of fields value.
@return: new record set for hotel room type.
"""
vals.update({'is_room_type': True})
vals.update({'purchase_ok': False})
vals.update({'type': 'service'})
vals.update({
'is_room_type': True,
'purchase_ok': False,
'type': 'service',
})
return super().create(vals)
@api.multi

View File

@@ -1,33 +1,14 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <alex@aloxa.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
class HotelVirtualRoomAvailability(models.Model):
class HotelRoomTypeAvailability(models.Model):
_inherit = 'mail.thread'
_name = 'hotel.virtual.room.availability'
_name = 'hotel.room.type.availability'
# virtual_room_id = fields.Many2one('hotel.virtual.room', 'Virtual Room',
# required=True, track_visibility='always',
@@ -41,16 +22,19 @@ class HotelVirtualRoomAvailability(models.Model):
track_visibility='always')
date = fields.Date('Date', required=True, track_visibility='always')
_sql_constraints = [('vroom_registry_unique', 'unique(room_type_id, date)',
'Only can exists one availability in the same day for the same room type!')]
_sql_constraints = [
('room_type_registry_unique',
'unique(room_type_id, date)',
'Only can exists one availability in the same day for the same room type!')
]
@api.constrains('avail')
def _check_avail(self):
if self.avail < 0:
self.avail = 0
vroom_obj = self.env['hotel.room.type']
cavail = len(vroom_obj.check_availability_virtual_room(
room_type_obj = self.env['hotel.room.type']
cavail = len(room_type_obj.check_availability_virtual_room(
self.date,
self.date,
room_type_id=self.room_type_id.id))

View File

@@ -0,0 +1,31 @@
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
class HotelRoomTypeRestriction(models.Model):
_name = 'hotel.room.type.restriction'
name = fields.Char('Restriction Plan Name', required=True)
item_ids = fields.One2many('hotel.room.type.restriction.item',
'restriction_id', string='Restriction Items',
copy=True)
active = fields.Boolean('Active',
help='If unchecked, it will allow you to hide the \
restriction plan without removing it.',
default=True)
@api.multi
@api.depends('name')
def name_get(self):
restriction_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id')
if restriction_id:
restriction_id = int(restriction_id)
names = []
for record in self:
if record.id == restriction_id:
names.append((record.id, '%s (Parity)' % record.name))
else:
names.append((record.id, record.name))
return names

View File

@@ -1,24 +1,5 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <alex@aloxa.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import datetime
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
@@ -26,10 +7,10 @@ from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from odoo.addons.hotel import date_utils
class HotelVirtualRoomRestrictionItem(models.Model):
_name = 'hotel.virtual.room.restriction.item'
class HotelRoomTypeRestrictionItem(models.Model):
_name = 'hotel.room.type.restriction.item'
restriction_id = fields.Many2one('hotel.virtual.room.restriction',
restriction_id = fields.Many2one('hotel.room.type.restriction',
'Restriction Plan', ondelete='cascade',
index=True)
# virtual_room_id = fields.Many2one('hotel.virtual.room', 'Virtual Room',
@@ -54,7 +35,7 @@ class HotelVirtualRoomRestrictionItem(models.Model):
closed_departure = fields.Boolean('Closed Departure')
closed_arrival = fields.Boolean('Closed Arrival')
_sql_constraints = [('vroom_registry_unique',
_sql_constraints = [('room_type_registry_unique',
'unique(restriction_id, room_type_id, date_start, date_end)',
'Only can exists one restriction in the same day for the same room type!')]

View File

@@ -1,14 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import time
import datetime
import logging
from odoo import models, fields, api, _
from odoo.tools import misc, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.addons.hotel import date_utils
from odoo.addons import decimal_precision as dp
from odoo import models, fields, api
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
_logger = logging.getLogger(__name__)
class HotelService(models.Model):
@@ -29,8 +25,9 @@ class HotelService(models.Model):
def _default_ser_room_line(self):
if 'room_lines' in self.env.context and self.env.context['room_lines']:
ids = [item[1] for item in self.env.context['room_lines']]
return self.env['hotel.reservation'].search([('id', 'in', ids)],
limit=1)
return self.env['hotel.reservation'].search([
('id', 'in', ids),
], limit=1)
return False
_name = 'hotel.service'
@@ -56,9 +53,9 @@ class HotelService(models.Model):
('web', 'Web')], 'Sales Channel')
ser_checkin = fields.Datetime('From Date', required=True,
default=_service_checkin)
default=_service_checkin)
ser_checkout = fields.Datetime('To Date', required=True,
default=_service_checkout)
default=_service_checkout)
# TODO Hierarchical relationship for parent-child tree

View File

@@ -1,12 +1,11 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import time
import datetime
import logging
from odoo import models, fields, api, _
from odoo.tools import misc, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.exceptions import UserError
from odoo.addons.hotel import date_utils
_logger = logging.getLogger(__name__)
@@ -14,6 +13,8 @@ from odoo.addons import decimal_precision as dp
class HotelServiceLine(models.Model):
_name = 'hotel.service.line'
_description = 'hotel Service line'
@api.one
def copy(self, default=None):
@@ -32,10 +33,11 @@ class HotelServiceLine(models.Model):
@param field_name: Names of fields.
@param arg: User defined arguments
'''
for folio in self:
line = folio.service_line_id
x = line._amount_line(field_name, arg)
return x
total_amount = 0
for record in self:
line = record.service_line_id
total_amount += line._amount_line(field_name, arg)
return total_amount
@api.multi
def _number_packages(self, field_name, arg):
@@ -44,10 +46,11 @@ class HotelServiceLine(models.Model):
@param field_name: Names of fields.
@param arg: User defined arguments
'''
for folio in self:
line = folio.service_line_id
x = line._number_packages(field_name, arg)
return x
total_packages = 0
for record in self:
line = record.service_line_id
total_packages = line._number_packages(field_name, arg)
return total_packages
@api.model
def _service_checkin(self):
@@ -69,8 +72,6 @@ class HotelServiceLine(models.Model):
limit=1)
return False
_name = 'hotel.service.line'
_description = 'hotel Service line'
# The record's name
name = fields.Char('Service line', required=True)
# services in the hotel are products
@@ -93,13 +94,14 @@ class HotelServiceLine(models.Model):
('web','Web')], 'Sales Channel')
ser_checkin = fields.Datetime('From Date', required=True,
default=_service_checkin)
default=_service_checkin)
ser_checkout = fields.Datetime('To Date', required=True,
default=_service_checkout)
ser_room_line = fields.Many2one('hotel.reservation','Room', default=_default_ser_room_line)
default=_service_checkout)
ser_room_line = fields.Many2one('hotel.reservation', 'Room',
default=_default_ser_room_line)
@api.model
def create(self, vals, check=True):
def create(self, vals):
"""
Overrides orm create method.
@param self: The object pointer
@@ -134,14 +136,17 @@ class HotelServiceLine(models.Model):
@param self: object pointer
'''
if self.product_id:
write_vals = {}
if not (self.folio_id and self.folio_id.partner_id) and \
self.ser_room_line:
self.folio_id = self.ser_room_line.folio_id
self.name = self.product_id.name
self.price_unit = self.product_id.lst_price
self.product_uom = self.product_id.uom_id
self.price_unit = self.product_id.price
write_vals.update({'folio_id': self.ser_room_line.folio_id.id})
write_vals.update({
'name': self.product_id.name,
'price_unit': self.product_id.lst_price,
'product_uom': self.product_id.uom_id,
'price_unit': self.product_id.price,
})
self.write(write_vals)
#~ self.price_unit = tax_obj._fix_tax_included_price(prod.price,
#~ prod.taxes_id,
@@ -208,26 +213,23 @@ class HotelServiceLine(models.Model):
if self.ser_checkin and self.ser_checkout:
diffDate = date_utils.date_diff(self.ser_checkin,
self.ser_checkout, hours=False) + 1
# FIXME: Finalize method!
@api.multi
def button_confirm(self):
'''
@param self: object pointer
'''
for folio in self:
line = folio.service_line_id
x = line.button_confirm()
return x
self.ensure_one()
self.service_line_id.button_confirm()
@api.multi
def button_done(self):
'''
@param self: object pointer
'''
for folio in self:
line = folio.service_line_id
x = line.button_done()
return x
self.ensure_one()
self.service_line_id.button_done()
@api.one
def copy_data(self, default=None):
@@ -235,8 +237,7 @@ class HotelServiceLine(models.Model):
@param self: object pointer
@param default: dict of default values to be set
'''
sale_line_obj = self.env['sale.order.line'
].browse(self.service_line_id.id)
sale_line_obj = self.env['sale.order.line'].browse(self.service_line_id.id)
return sale_line_obj.copy_data(default=default)
@api.multi

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -6,10 +5,9 @@ from odoo import models, fields, api, _
class HotelServiceType(models.Model):
_name = "hotel.service.type"
_description = "Service Type"
# The record's name
name = fields.Char('Service Type', required=True)
# Used for activate records
active = fields.Boolean('Active?', default=True)
@@ -19,7 +17,7 @@ class HotelServiceType(models.Model):
service_ids = fields.One2many('hotel.services', 'service_type_id',
'Services in this category')
@api.multi
def unlink(self):
# self.ser_id.unlink()
return super(HotelServiceType, self).unlink()
# @api.multi
# def unlink(self):
# # self.ser_id.unlink()
# return super(HotelServiceType, self).unlink()

View File

@@ -1,50 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <alex@aloxa.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import models, fields, api
class VirtualRoomRestriction(models.Model):
_name = 'hotel.virtual.room.restriction'
name = fields.Char('Restriction Plan Name', required=True)
item_ids = fields.One2many('hotel.virtual.room.restriction.item',
'restriction_id', string='Restriction Items',
copy=True)
active = fields.Boolean('Active',
help='If unchecked, it will allow you to hide the \
restriction plan without removing it.',
default=True)
@api.multi
@api.depends('name')
def name_get(self):
restriction_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id')
if restriction_id:
restriction_id = int(restriction_id)
names = []
for record in self:
if record.id == restriction_id:
names.append((record.id, '%s (Parity)' % record.name))
else:
names.append((record.id, record.name))
return names

View File

@@ -1,16 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import logging
from openerp import models, fields, api, _
from openerp.exceptions import UserError, ValidationError
import logging
_logger = logging.getLogger(__name__)
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
@api.model
@@ -64,7 +61,8 @@ class AccountInvoice(models.Model):
@api.multi
def action_invoice_open(self):
to_open_invoices_without_vat = self.filtered(lambda inv: inv.state != 'open' and inv.partner_id.vat == False)
to_open_invoices_without_vat = self.filtered(
lambda inv: inv.state != 'open' and inv.partner_id.vat == False)
if to_open_invoices_without_vat:
vat_error = _("We need the VAT of the following companies")
for invoice in to_open_invoices_without_vat:

View File

@@ -1,15 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from decimal import Decimal
import datetime
# For Python 3.0 and later
from urllib.request import urlopen
import time
import logging
from openerp.exceptions import except_orm, UserError, ValidationError
from openerp.tools import misc, DEFAULT_SERVER_DATETIME_FORMAT
from openerp.exceptions import except_orm
from openerp import models, fields, api, _
_logger = logging.getLogger(__name__)
@@ -40,7 +32,7 @@ class AccountPayment(models.Model):
}
return_vals = {
'journal_id': journal.id,
'line_ids': [(0,0,return_line_vals)],
'line_ids': [(0, 0, return_line_vals)],
}
return_pay = self.env['payment.return'].create(return_vals)
return {
@@ -73,6 +65,7 @@ class AccountPayment(models.Model):
@api.multi
@api.depends('state')
def _compute_folio_amount(self):
# FIXME: Finalize method
res = []
fol = ()
for payment in self:
@@ -84,7 +77,7 @@ class AccountPayment(models.Model):
])
else:
return
if len(fol) == 0:
if not any(fol):
return
elif len(fol) > 1:
raise except_orm(_('Warning'), _('This pay is related with \

View File

@@ -1,28 +1,9 @@
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2018-Darío Lodeiros Vázquez
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
# ---------------------------------------------------------------------------
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
class PaymentReturn(models.Model):
_inherit = 'payment.return'
folio_id = fields.Many2one('hotel.folio', string='Folio')
@@ -33,7 +14,9 @@ class PaymentReturn(models.Model):
if pay:
folio_ids = []
for line in self.line_ids:
payments = self.env['account.payment'].search([('move_line_ids','in',line.move_line_ids.ids)])
folio_ids += payments.mapped('folio_id.id')
payments = self.env['account.payment'].search([
('move_line_ids', 'in', line.move_line_ids.ids)
])
folio_ids += payments.mapped('folio_id.id')
folios = self.env['hotel.folio'].browse(folio_ids)
folios.compute_amount()

View File

@@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
class ProductCategory(models.Model):
_inherit = "product.category"
# isroomtype = fields.Boolean('Is Room Type')

View File

@@ -1,23 +1,5 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, api

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -6,7 +5,6 @@ from openerp import models, fields, api, _
class ProductProduct(models.Model):
_inherit = "product.product"
is_room_type = fields.Boolean('Is a Room Type', default=False)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -6,7 +5,6 @@ from openerp import models, fields, api, _
class ResCompany(models.Model):
_inherit = 'res.company'
additional_hours = fields.Integer('Additional Hours',

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -6,23 +5,22 @@ from openerp import models, fields, api, _
class ResPartner(models.Model):
_inherit = 'res.partner'
reservations_count = fields.Integer('Reservations',
compute='_compute_reservations_count')
folios_count = fields.Integer('Folios', compute='_compute_folios_count')
def _compute_reservations_count(self):
hotel_reservation_obj = self.env['hotel.reservation']
for partner in self:
partner.reservations_count = hotel_reservation_obj.search_count([
('partner_id.id', '=', partner.id)
for record in self:
record.reservations_count = hotel_reservation_obj.search_count([
('partner_id.id', '=', record.id)
])
def _compute_folios_count(self):
hotel_folio_obj = self.env['hotel.folio']
for partner in self:
partner.folios_count = hotel_folio_obj.search_count([
('partner_id.id', '=', partner.id)
for record in self:
record.folios_count = hotel_folio_obj.search_count([
('partner_id.id', '=', record.id)
])
reservations_count = fields.Integer('Reservations',
compute='_compute_reservations_count')
folios_count = fields.Integer('Folios', compute='_compute_folios_count')

View File

@@ -1,24 +1,5 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2018 Alexandre Díaz <dev@redneboa.es>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models
@@ -28,13 +9,14 @@ class MailComposeMessage(models.TransientModel):
@api.multi
def send_mail(self, auto_commit=False):
if self._context.get('default_model') == 'hotel.folio' and self._context.get('default_res_id') and self._context.get('mark_so_as_sent'):
if self._context.get('default_model') == 'hotel.folio' and \
self._context.get('default_res_id') and self._context.get('mark_so_as_sent'):
folio = self.env['hotel.folio'].browse([
self._context['default_res_id']
])
if folio:
cmds = []
for lid in folio.room_lines._ids:
for lid in folio.room_lines.ids:
cmds.append((
1,
lid,

View File

@@ -1,24 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <alex@aloxa.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017-2018 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import re
import pytz
from openerp import models, fields, api, _
@@ -39,7 +21,7 @@ class HotelConfiguration(models.TransientModel):
parity_pricelist_id = fields.Many2one('product.pricelist',
'Product Pricelist')
parity_restrictions_id = fields.Many2one('hotel.virtual.room.restriction',
parity_restrictions_id = fields.Many2one('hotel.room.type.restriction',
'Restrictions')
default_arrival_hour = fields.Char('Default Arrival Hour (GMT)',
help="HH:mm Format", default="14:00")

View File

@@ -84,7 +84,7 @@ class TestHotel(TestMail):
cls._init_mock_hotel()
# Restriction Plan
cls.restriction_1 = cls.env['hotel.virtual.room.restriction'].create({
cls.restriction_1 = cls.env['hotel.room.type.restriction'].create({
'name': 'Restriction Test #1',
'active': True
})
@@ -221,8 +221,8 @@ class TestHotel(TestMail):
cls.hotel_vroom_budget.id: budget_product_id.product_tmpl_id.id,
cls.hotel_vroom_special.id: special_product_id.product_tmpl_id.id,
}
vroom_avail_obj = cls.env['hotel.virtual.room.availability']
vroom_rest_item_obj = cls.env['hotel.virtual.room.restriction.item']
vroom_avail_obj = cls.env['hotel.room.type.availability']
vroom_rest_item_obj = cls.env['hotel.room.type.restriction.item']
pricelist_item_obj = cls.env['product.pricelist.item']
for k_vr, v_vr in cls.avails_tmp.iteritems():
for i in range(0, len(v_vr)):

View File

@@ -43,11 +43,11 @@
id="cardex_smart_button"
icon="fa-user-plus"
name="%(launch_checkin_wizard_add)d"
attrs="{'invisible': [('cardex_pending_num','&lt;=',0)]}"
attrs="{'invisible': [('cardex_pending_count','&lt;=',0)]}"
context="{'partner_id': partner_id,'reservation_ids': room_lines,
'hidden_cardex': True, 'folio': active_id}">
<div class="o_form_field o_stat_info">
<span class="o_stat_value"><field name="cardex_pending_num"
<span class="o_stat_value"><field name="cardex_pending_count"
widget="statinfo" nolabel="1"/></span>
<span class="o_stat_text">Pending Checks</span>
</div>
@@ -189,7 +189,7 @@
context="{'partner_id': partner_id,'enter_date': checkin,
'exit_date': checkout,'reservation_id': id, 'hidden_cardex': True, 'edit_cardex': True }"
attrs="{'invisible':['|','|', ('state','not in',('confirm','booking')),
('cardex_pending','=', False),('parent_reservation','!=',False)]}"
('cardex_pending_count','=', 0),('parent_reservation','!=',False)]}"
/>
<field name="partner_id"/>
<field name="splitted" invisible="1" />
@@ -202,7 +202,7 @@
<field name="checkout" widget="date"/>
<field name="cardex_ids" invisible ="1"/>
<field name="to_assign" invisible="1"/>
<field name="cardex_pending" invisible="1"/>
<field name="cardex_pending_count" invisible="1"/>
<!-- <field name="qty_delivered" invisible="1"/> -->
<!-- attrs="{'readonly': [('qty_delivered_updateable', '=', False)]}"/> -->
<!-- <field name="qty_invoiced" invisible="1"/> -->
@@ -339,7 +339,7 @@
<group invisible="1">
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<!-- <field name="check_rooms" invisible="1"/> -->
<field name="cardex_pending" invisible="1"/>
<field name="cardex_pending_count" invisible="1"/>
<!-- <field name="pricelist_id" invisible="1"/> -->
<field name="nights" invisible="1"/>
</group>
@@ -524,8 +524,7 @@
<field name="invoices_paid"/>
<field name="booking_pending"/>
<field name="cardex_count"/>
<field name="cardex_pending"/>
<field name="cardex_pending_num"/>
<field name="cardex_pending_count"/>
<field name="checkins_reservations"/>
<field name="checkouts_reservations"/>
<field name="partner_internal_comment"/>
@@ -541,7 +540,7 @@
<ul>
<li t-if="record.name.raw_value"><field name="name"/></li>
<span t-if="record.cardex_count.value&gt;0" class="badge"><i class="fa fa-fw fa-bed"/><t t-esc="record.cardex_count.value"/></span>
<span t-if="record.cardex_pending_num.value&gt;0" class="badge"><i class="fa fa-fw fa-user-plus"/><t t-esc="record.cardex_pending_num.value"/></span>
<span t-if="record.cardex_pending_count.value&gt;0" class="badge"><i class="fa fa-fw fa-user-plus"/><t t-esc="record.cardex_pending_count.value"/></span>
</ul>
<div class="oe_kanban_partner_links"/>
</div>

View File

@@ -129,9 +129,9 @@
context="{'partner_id': partner_id,'enter_date': checkin,
'exit_date': checkout,'reservation_id': id, 'hidden_cardex': True, 'edit_cardex': True }"
attrs="{'invisible':['|', '|', ('state','not in',('confirm','booking')),
('cardex_pending','=', False),('parent_reservation','!=',False)]}">
('cardex_pending_count','=', 0),('parent_reservation','!=',False)]}">
<div class="o_form_field o_stat_info">
<span class="o_stat_value"><field name="cardex_pending_num"
<span class="o_stat_value"><field name="cardex_pending_count"
widget="statinfo" nolabel="1"/></span>
<span class="o_stat_text">Pending Checks</span>
</div>
@@ -194,7 +194,7 @@
</group>
<group class="oe_subtotal_footer" style="margin-right: 20px; !important" colspan="2" name="reservation_total" string="Amounts" attrs="{'invisible':[('folio_id','=', False)]}">
<!--
<field name="discount" string="Room Discount" attrs="{'invisible': [('discount_type','=','fixed')]}" />
<field name="discount" string="Room Discount" attrs="{'invisible': [('discount_type','=','fixed')]}" />
-->
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
<!--
@@ -202,7 +202,7 @@
-->
<button name="%(action_hotel_massive_price_change_reservation_days)d" string="Massive Day Prices"
type="action" class="oe_edit_only oe_link" icon="fa-bolt"/>
</div>
</div>
<!-- <field name="amount_discount" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
<!--
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
@@ -215,7 +215,7 @@
<field name="state" invisible="1"/>
<!-- <field name="invoice_status" invisible="1"/> -->
<!-- <field name="customer_lead" invisible="1"/> -->
<field name="currency_id" invisible="1"/>
<field name="currency_id" invisible="1"/>
<field name="price_subtotal" widget="monetary"/>
</group>
</group>
@@ -223,7 +223,7 @@
<group invisible="1">
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<!-- <field name="check_rooms" invisible="1"/> -->
<field name="cardex_pending" invisible="1"/>
<field name="cardex_pending_count" invisible="1"/>
<!-- <field name="pricelist_id" invisible="1"/> -->
<field name="nights" invisible="1"/>
<!-- <field name="product_uom" string="Rent(UOM)" invisible="1" /> -->
@@ -326,7 +326,7 @@
name="%(launch_checkin_wizard_add)d"
context="{'partner_id': partner_id,'enter_date': checkin,
'exit_date': checkout,'reservation_id': id, 'hidden_cardex': True, 'edit_cardex': True }"
attrs="{'invisible':['|','|', ('state','not in',('confirm','booking')),('cardex_pending','=', False),('parent_reservation','!=',False)]}"
attrs="{'invisible':['|','|', ('state','not in',('confirm','booking')),('cardex_pending_count','=', 0),('parent_reservation','!=',False)]}"
/>
<button type="action" class="oe_stat_button"
icon="fa fa-2x fa-list-ul"
@@ -347,7 +347,7 @@
<field name="cardex_ids" invisible ="1"/>
<field name="to_assign" invisible="1"/>
<!-- cardex_smart_button attrs depends on cardex_pending to be showed -->
<field name="cardex_pending" invisible="1"/>
<field name="cardex_pending_count" invisible="1"/>
<field name="folio_pending_amount" string="Folio Pending Amount"/>
<button type="object" class="oe_stat_button"
icon="fa fa-3x fa-money"

View File

@@ -3,8 +3,8 @@
<!-- FORM restriction -->
<record id="reservation_restriction_item_view_form" model="ir.ui.view">
<field name="name">hotel.virtual.room.restriction.item.form</field>
<field name="model">hotel.virtual.room.restriction.item</field>
<field name="name">hotel.room.type.restriction.item.form</field>
<field name="model">hotel.room.type.restriction.item</field>
<field name="arch" type="xml">
<form string="Restrictions">
<group>
@@ -38,8 +38,8 @@
<!-- TREE restriction -->
<record id="reservation_restriction_item_view_tree" model="ir.ui.view">
<field name="name">hotel.virtual.room.restriction.item.tree</field>
<field name="model">hotel.virtual.room.restriction.item</field>
<field name="name">hotel.room.type.restriction.item.tree</field>
<field name="model">hotel.room.type.restriction.item</field>
<field name="arch" type="xml">
<tree string="Restrictions">
<field name="applied_on"/>

View File

@@ -3,8 +3,8 @@
<!-- FORM restriction -->
<record id="reservation_restriction_view_form" model="ir.ui.view">
<field name="name">hotel.virtual.room.restriction.form</field>
<field name="model">hotel.virtual.room.restriction</field>
<field name="name">hotel.room.type.restriction.form</field>
<field name="model">hotel.room.type.restriction</field>
<field name="arch" type="xml">
<form string="Restrictions">
<sheet>
@@ -35,8 +35,8 @@
<!-- TREE restriction -->
<record id="reservation_restriction_view_tree" model="ir.ui.view">
<field name="name">hotel.virtual.room.restriction.tree</field>
<field name="model">hotel.virtual.room.restriction</field>
<field name="name">hotel.room.type.restriction.tree</field>
<field name="model">hotel.room.type.restriction</field>
<field name="arch" type="xml">
<tree string="Restrictions">
<field name="name"/>
@@ -48,7 +48,7 @@
<!-- Action of reservation restriction -->
<record model="ir.actions.act_window" id="reservation_restriction_action">
<field name="name">Reservation restrictions</field>
<field name="res_model">hotel.virtual.room.restriction</field>
<field name="res_model">hotel.room.type.restriction</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>

View File

@@ -3,8 +3,8 @@
<!-- FORM availability -->
<record id="virtual_room_availability_view_form" model="ir.ui.view">
<field name="name">hotel.virtual.room.availability.form</field>
<field name="model">hotel.virtual.room.availability</field>
<field name="name">hotel.room.type.availability.form</field>
<field name="model">hotel.room.type.availability</field>
<field name="arch" type="xml">
<form string="Availability">
<sheet>
@@ -29,8 +29,8 @@
<!-- TREE restriction -->
<record id="virtual_room_availability_view_tree" model="ir.ui.view">
<field name="name">hotel.virtual.room.availability.tree</field>
<field name="model">hotel.virtual.room.availability</field>
<field name="name">hotel.room.type.availability.tree</field>
<field name="model">hotel.room.type.availability</field>
<field name="arch" type="xml">
<tree string="Restrictions">
<!-- <field name="virtual_room_id" required="1"/> -->
@@ -46,7 +46,7 @@
<!-- Action of reservation restriction -->
<record model="ir.actions.act_window" id="virtual_room_availability_action">
<field name="name">Virtual Room Availability</field>
<field name="res_model">hotel.virtual.room.availability</field>
<field name="res_model">hotel.room.type.availability</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>

View File

@@ -1,12 +1,8 @@
# -*- coding: utf-8 -*-
import logging
from openerp import models, fields, api
from openerp.exceptions import UserError
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
class Wizard(models.TransientModel):
_name = 'checkin.wizard'
@@ -40,7 +36,8 @@ class Wizard(models.TransientModel):
for res in reservations:
# return the first room line with free space for a cardex
# TODO: add 'done' to res.state condition... Maybe too restrictive right now
if res.cardex_count < (res.adults + res.children) and res.state not in ["cancelled"]:
if res.cardex_count < (res.adults + res.children) and \
res.state not in ["cancelled"]:
return res
elif 'reservation_id' in self.env.context:
return self.env['hotel.reservation'].browse(
@@ -131,9 +128,8 @@ class Wizard(models.TransientModel):
op_select_partner = fields.Selection([
('S', 'Select a partner for checkin'),
('C', 'Create a new partner for checkin')],
default='S',
string='Partner for checkin')
('C', 'Create a new partner for checkin')
], default='S', string='Partner for checkin')
# checkin mode:
# 0 - no selection made by the user, so hide the client fields
# 1 - select a client for update his values and do the checkin
@@ -151,7 +147,7 @@ class Wizard(models.TransientModel):
'email': self.email_cardex,
'mobile': self.mobile_cardex,
}
self.partner_id.sudo().write(partner_vals);
self.partner_id.sudo().write(partner_vals)
elif self.op_select_partner == 'C':
partner_vals = {
'firstname': self.firstname_cardex,
@@ -164,9 +160,9 @@ class Wizard(models.TransientModel):
# prepare checkin values
cardex_val = {
'partner_id': self.partner_id.id,
'enter_date': self.enter_date,
'exit_date': self.exit_date
'partner_id': self.partner_id.id,
'enter_date': self.enter_date,
'exit_date': self.exit_date
}
record_id = self.env['hotel.reservation'].browse(
self.reservation_id.id)
@@ -207,19 +203,22 @@ class Wizard(models.TransientModel):
@api.onchange('partner_id')
def onchange_partner_id(self):
# update partner fields
self.firstname_cardex = self.partner_id.firstname;
self.lastname_cardex = self.partner_id.lastname;
self.email_cardex = self.partner_id.email;
self.mobile_cardex = self.partner_id.mobile;
write_vals = {
'firstname_cardex': self.partner_id.firstname,
'lastname_cardex': self.partner_id.lastname,
'email_cardex': self.partner_id.email,
'mobile_cardex': self.partner_id.mobile,
}
# show the checkin fields if a partner is selected
if self.op_select_partner == 'S' and self.partner_id.id != False:
self.checkin_mode = 1;
write_vals.update({'checkin_mode': 1})
self.write(write_vals)
@api.onchange('op_select_partner')
def onchange_op_select_partner(self):
# field one2many return false is record does not exist
if self.op_select_partner == 'S' and self.partner_id.id != False:
self.checkin_mode = 1;
if self.op_select_partner == 'S' and self.partner_id.id:
self.checkin_mode = 1
# field one2many return 0 on empty record (nothing typed)
elif self.op_select_partner == 'C' and self.partner_id.id == 0:
self.checkin_mode = 2;
self.checkin_mode = 2

View File

@@ -10,7 +10,7 @@
<group col="4">
<field options="{'no_quick_create': True, 'no_create_edit' : True, 'no_open': True}"
name="reservation_id" nolabel="1"
domain="[('folio_id','=',context.get('folio')), ('state', '!=', 'cancelled'), ('cardex_pending', '=', True)]"
domain="[('folio_id','=',context.get('folio')), ('state', '!=', 'cancelled'), ('cardex_pending_count', '>', 0)]"
style="max-width: 95%; width: 32.2em"/>
</group>
<group col="4">

View File

@@ -1,30 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <dev@redneboa.es>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import datetime, timedelta
# Copyright 2017 Dario Lodeiros
# Copyright 2018 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp.exceptions import ValidationError
from openerp import models, fields, api, _
from openerp.tools import (
DEFAULT_SERVER_DATETIME_FORMAT,
DEFAULT_SERVER_DATE_FORMAT)
class DuplicateReservationWizard(models.TransientModel):
@@ -44,16 +22,7 @@ class DuplicateReservationWizard(models.TransientModel):
if reservation_id.splitted:
raise ValidationError(_("Can't duplicate splitted reservations"))
hotel_room_obj = self.env['hotel.room']
hotel_vroom_obj = self.env['hotel.virtual.room']
room_id = hotel_room_obj.search([
('product_id', '=', reservation_id.product_id.id)
], limit=1)
vroom_ids = hotel_vroom_obj.search([
'|', ('room_ids', 'in', [room_id.id]),
('room_type_ids', 'in', [room_id.categ_id.id])
])
hotel_room_type_obj = self.env['hotel.room.type']
cmds_reservation_lines = []
for rline in reservation_id.reservation_lines:
@@ -63,41 +32,38 @@ class DuplicateReservationWizard(models.TransientModel):
}))
# Check Input
total_free_rooms = 0
for vroom in vroom_ids:
avails = otel_vroom_obj.check_availability_virtual_room(
reservation_id.checkin,
reservation_id.checkout,
virtual_room_id=vroom.id)
total_free_rooms += len(avails)
avails = hotel_room_type_obj.check_availability_virtual_room(
reservation_id.checkin,
reservation_id.checkout,
room_type_id=reservation_id.room_type_id.id)
total_free_rooms = len(avails)
if total_free_rooms < self.num:
raise ValidationError(_("Too much duplicated reservations! \
There are no '%d' free rooms") % self.num)
for i in range(0, self.num):
for vroom in vroom_ids:
free_rooms = hotel_vroom_obj.check_availability_virtual_room(
reservation_id.checkin,
reservation_id.checkout,
virtual_room_id=vroom.id)
if any(free_rooms):
new_reservation_id = hotel_reservation_obj.create({
'product_id': free_rooms[0].product_id.id,
'folio_id': reservation_id.folio_id.id,
'checkin': reservation_id.checkin,
'checkout': reservation_id.checkout,
'adults': reservation_id.adults,
'children': reservation_id.children,
'name': reservation_id.name,
'reservation_lines': cmds_reservation_lines,
'price_unit': reservation_id.price_unit,
})
if new_reservation_id:
rpartner_id = reservation_id.order_id.partner_id
new_reservation_id.order_id.partner_id = rpartner_id
break
else:
raise ValidationError(_("Unexpected Error: Can't found a \
free room"))
free_rooms = hotel_room_type_obj.check_availability_virtual_room(
reservation_id.checkin,
reservation_id.checkout,
virtual_room_id=reservation_id.room_type_id.id)
if any(free_rooms):
new_reservation_id = hotel_reservation_obj.create({
'room_id': free_rooms[0].id,
'room_type_id': free_rooms[0].room_type_id.id,
'folio_id': reservation_id.folio_id.id,
'checkin': reservation_id.checkin,
'checkout': reservation_id.checkout,
'adults': reservation_id.adults,
'children': reservation_id.children,
'name': reservation_id.name,
'reservation_lines': cmds_reservation_lines,
})
if new_reservation_id:
rpartner_id = reservation_id.order_id.partner_id
new_reservation_id.order_id.partner_id = rpartner_id
break
else:
raise ValidationError(_("Unexpected Error: Can't found a \
free room"))
return True

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import time
@@ -20,15 +19,16 @@ class FolioAdvancePaymentInv(models.TransientModel):
if self._count() == 1:
sale_obj = self.env['sale.order']
folio_obj = self.env['hotel.folio']
folio = folio_obj.browse(self._context.get('active_ids'))[0]
order = sale_obj.browse(folio_obj.mapped('order_id.id'))
if all([line.product_id.invoice_policy == 'order' for line in order.order_line]) or order.invoice_count:
if all([line.product_id.invoice_policy == 'order' for line in order.order_line]) \
or order.invoice_count:
return 'all'
return 'delivered'
@api.model
def _default_product_id(self):
product_id = self.env['ir.default'].sudo().get('sale.config.settings', 'deposit_product_id_setting')
product_id = self.env['ir.default'].sudo().get('sale.config.settings',
'deposit_product_id_setting')
return self.env['product.product'].browse(product_id)
@api.model
@@ -44,14 +44,21 @@ class FolioAdvancePaymentInv(models.TransientModel):
('all', 'Invoiceable lines (deduct down payments)'),
('percentage', 'Down payment (percentage)'),
('fixed', 'Down payment (fixed amount)')
], string='What do you want to invoice?', default=_get_advance_payment_method, required=True)
product_id = fields.Many2one('product.product', string='Down Payment Product', domain=[('type', '=', 'service')],
default=_default_product_id)
], string='What do you want to invoice?', default=_get_advance_payment_method,
required=True)
product_id = fields.Many2one('product.product', string='Down Payment Product',
domain=[('type', '=', 'service')], default=_default_product_id)
count = fields.Integer(default=_count, string='# of Orders')
amount = fields.Float('Down Payment Amount', digits=dp.get_precision('Account'), help="The amount to be invoiced in advance, taxes excluded.")
deposit_account_id = fields.Many2one("account.account", string="Income Account", domain=[('deprecated', '=', False)],
help="Account used for deposits", default=_default_deposit_account_id)
deposit_taxes_id = fields.Many2many("account.tax", string="Customer Taxes", help="Taxes used for deposits", default=_default_deposit_taxes_id)
amount = fields.Float('Down Payment Amount',
digits=dp.get_precision('Account'),
help="The amount to be invoiced in advance, taxes excluded.")
deposit_account_id = fields.Many2one("account.account", string="Income Account",
domain=[('deprecated', '=', False)],
help="Account used for deposits",
default=_default_deposit_account_id)
deposit_taxes_id = fields.Many2many("account.tax", string="Customer Taxes",
help="Taxes used for deposits",
default=_default_deposit_taxes_id)
@api.onchange('advance_payment_method')
def onchange_advance_payment_method(self):
@@ -66,7 +73,8 @@ class FolioAdvancePaymentInv(models.TransientModel):
account_id = False
if self.product_id.id:
account_id = self.product_id.property_account_income_id.id or self.product_id.categ_id.property_account_income_categ_id.id
account_id = self.product_id.property_account_income_id.id \
or self.product_id.categ_id.property_account_income_categ_id.id
if not account_id:
inc_acc = ir_property_obj.get('property_account_income_categ_id', 'product.category')
account_id = order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False
@@ -85,7 +93,8 @@ class FolioAdvancePaymentInv(models.TransientModel):
amount = self.amount
name = _('Down Payment')
del context
taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id)
taxes = self.product_id.taxes_id.filtered(
lambda r: not order.company_id or r.company_id == order.company_id)
if order.fiscal_position_id and taxes:
tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
@@ -114,15 +123,17 @@ class FolioAdvancePaymentInv(models.TransientModel):
})],
'currency_id': order.pricelist_id.currency_id.id,
'payment_term_id': order.payment_term_id.id,
'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id,
'fiscal_position_id': order.fiscal_position_id.id \
or order.partner_id.property_account_position_id.id,
'team_id': order.team_id.id,
'user_id': order.user_id.id,
'comment': order.note,
})
invoice.compute_taxes()
invoice.message_post_with_view('mail.message_origin_link',
values={'self': invoice, 'origin': order},
subtype_id=self.env.ref('mail.mt_note').id)
invoice.message_post_with_view(
'mail.message_origin_link',
values={'self': invoice, 'origin': order},
subtype_id=self.env.ref('mail.mt_note').id)
return invoice
@api.multi
@@ -139,7 +150,10 @@ class FolioAdvancePaymentInv(models.TransientModel):
if not self.product_id:
vals = self._prepare_deposit_product()
self.product_id = self.env['product.product'].create(vals)
self.env['ir.default'].sudo().set('sale.config.settings', 'deposit_product_id_setting', self.product_id.id)
self.env['ir.default'].sudo().set(
'sale.config.settings',
'deposit_product_id_setting',
self.product_id.id)
sale_line_obj = self.env['sale.order.line']
for order in sale_orders:
@@ -151,7 +165,8 @@ class FolioAdvancePaymentInv(models.TransientModel):
raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))
if self.product_id.type != 'service':
raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))
taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id)
taxes = self.product_id.taxes_id.filtered(
lambda r: not order.company_id or r.company_id == order.company_id)
if order.fiscal_position_id and taxes:
tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

View File

@@ -1,26 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <dev@redneboa.es>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import datetime, timedelta
from openerp.exceptions import ValidationError
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import timedelta
from openerp import models, fields, api
from openerp.tools import (
DEFAULT_SERVER_DATE_FORMAT,
@@ -53,7 +33,7 @@ class MassiveChangesWizard(models.TransientModel):
# virtual_room_ids = fields.Many2many('hotel.virtual.room',
# string="Virtual Rooms")
room_type_ids = fields.Many2many('hotel.room.type',
string="Room Types")
string="Room Types")
# Availability fields
change_avail = fields.Boolean(default=False)
@@ -62,7 +42,7 @@ class MassiveChangesWizard(models.TransientModel):
no_ota = fields.Boolean('No OTA', default=False)
# Restriction fields
restriction_id = fields.Many2one('hotel.virtual.room.restriction',
restriction_id = fields.Many2one('hotel.room.type.restriction',
'Restriction Plan')
change_min_stay = fields.Boolean(default=False)
min_stay = fields.Integer("Min. Stay")
@@ -95,8 +75,6 @@ class MassiveChangesWizard(models.TransientModel):
@api.multi
def is_valid_date(self, chkdate):
self.ensure_one()
date_start_dt = fields.Datetime.from_string(self.date_start)
date_end_dt = fields.Datetime.from_string(self.date_end)
wday = chkdate.timetuple()[6]
wedays = (self.dmo, self.dtu, self.dwe, self.dth, self.dfr, self.dsa,
self.dsu)
@@ -104,17 +82,17 @@ class MassiveChangesWizard(models.TransientModel):
and wedays[wday])
@api.model
def _save_prices(self, ndate, vrooms, record):
def _save_prices(self, ndate, room_types, record):
product_pricelist_item_obj = self.env['product.pricelist.item']
price = 0.0
operation = 'a'
if record.price[0] == '+' or record.price[0] == '-':
if record.price[-1] == '%':
price = float(record.price[1:-1])
operation = (record.price[0] == '+') and 'ap' or 'sp'
operation = 'ap' if (record.price[0] == '+') else 'sp'
else:
price = float(record.price[1:])
operation = (record.price[0] == '+') and 'a' or 's'
operation = 'a' if (record.price[0] == '+') else 's'
else:
if record.price[-1] == '%':
price = float(record.price[:-1])
@@ -126,17 +104,15 @@ class MassiveChangesWizard(models.TransientModel):
domain = [
('pricelist_id', '=', record.pricelist_id.id),
('date_start', '>=', ndate.strftime(
DEFAULT_SERVER_DATE_FORMAT)),
DEFAULT_SERVER_DATE_FORMAT)),
('date_end', '<=', ndate.strftime(
DEFAULT_SERVER_DATE_FORMAT)),
DEFAULT_SERVER_DATE_FORMAT)),
('compute_price', '=', 'fixed'),
('applied_on', '=', '1_product'),
]
product_tmpl_ids = vrooms.mapped(
'product_id.product_tmpl_id')
for vroom in vrooms:
prod_tmpl_id = vroom.product_id.product_tmpl_id
for room_type in room_types:
prod_tmpl_id = room_type.product_id.product_tmpl_id
pricelist_item_ids = product_pricelist_item_obj.search(
domain+[('product_tmpl_id', '=', prod_tmpl_id.id)])
if any(pricelist_item_ids):
@@ -161,17 +137,16 @@ class MassiveChangesWizard(models.TransientModel):
product_pricelist_item_obj.create({
'pricelist_id': record.pricelist_id.id,
'date_start': ndate.strftime(
DEFAULT_SERVER_DATE_FORMAT),
DEFAULT_SERVER_DATE_FORMAT),
'date_end': ndate.strftime(
DEFAULT_SERVER_DATE_FORMAT),
DEFAULT_SERVER_DATE_FORMAT),
'compute_price': 'fixed',
'applied_on': '1_product',
'product_tmpl_id': prod_tmpl_id.id,
'fixed_price': price,
})
@api.model
def _get_restrictions_values(self, ndate, vroom, record):
def _get_restrictions_values(self, record):
vals = {}
if record.change_min_stay:
vals.update({'min_stay': record.min_stay})
@@ -190,8 +165,8 @@ class MassiveChangesWizard(models.TransientModel):
return vals
@api.model
def _save_restrictions(self, ndate, vrooms, record):
hotel_vroom_re_it_obj = self.env['hotel.virtual.room.restriction.item']
def _save_restrictions(self, ndate, room_types, record):
hotel_room_type_re_it_obj = self.env['hotel.room.type.restriction.item']
domain = [
('date_start', '>=', ndate.strftime(DEFAULT_SERVER_DATE_FORMAT)),
('date_end', '<=', ndate.strftime(DEFAULT_SERVER_DATE_FORMAT)),
@@ -199,13 +174,13 @@ class MassiveChangesWizard(models.TransientModel):
('applied_on', '=', '0_virtual_room'),
]
for vroom in vrooms:
vals = self._get_restrictions_values(ndate, vroom, record)
for room_type in room_types:
vals = self._get_restrictions_values(record)
if not any(vals):
continue
rrest_item_ids = hotel_vroom_re_it_obj.search(
domain+[('virtual_room_id', '=', vroom.id)])
rrest_item_ids = hotel_room_type_re_it_obj.search(
domain+[('room_type_id', '=', room_type.id)])
if any(rrest_item_ids):
rrest_item_ids.write(vals)
else:
@@ -213,51 +188,50 @@ class MassiveChangesWizard(models.TransientModel):
'date_start': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'date_end': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'restriction_id': record.restriction_id.id,
'virtual_room_id': vroom.id,
'room_type_id': room_type.id,
'applied_on': '0_virtual_room',
})
hotel_vroom_re_it_obj.create(vals)
hotel_room_type_re_it_obj.create(vals)
@api.model
def _get_availability_values(self, ndate, vroom, record):
hotel_vroom_obj = self.env['hotel.virtual.room']
def _get_availability_values(self, ndate, room_type, record):
hotel_room_type_obj = self.env['hotel.room.type']
vals = {}
if record.change_no_ota:
vals.update({'no_ota': record.no_ota})
if record.change_avail:
cavail = len(hotel_vroom_obj.check_availability_virtual_room(
cavail = len(hotel_room_type_obj.check_availability_virtual_room(
ndate.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
ndate.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
virtual_room_id=vroom.id))
room_type_id=room_type.id))
vals.update({
'avail': min(cavail, vroom.total_rooms_count, record.avail),
'avail': min(cavail, room_type.total_rooms_count, record.avail),
})
return vals
@api.model
def _save_availability(self, ndate, vrooms, record):
hotel_vroom_obj = self.env['hotel.virtual.room']
hotel_vroom_avail_obj = self.env['hotel.virtual.room.availability']
def _save_availability(self, ndate, room_types, record):
hotel_room_type_avail_obj = self.env['hotel.room.type.availability']
domain = [('date', '=', ndate.strftime(DEFAULT_SERVER_DATE_FORMAT))]
for vroom in vrooms:
vals = self._get_availability_values(ndate, vroom, record)
for room_type in room_types:
vals = self._get_availability_values(ndate, room_type, record)
if not any(vals):
continue
vrooms_avail = hotel_vroom_avail_obj.search(
domain+[('virtual_room_id', '=', vroom.id)]
room_types_avail = hotel_room_type_avail_obj.search(
domain+[('room_type_id', '=', room_type.id)]
)
if any(vrooms_avail):
if any(room_types_avail):
# Mail module want a singleton
for vr_avail in vrooms_avail:
for vr_avail in room_types_avail:
vr_avail.write(vals)
else:
vals.update({
'date': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'virtual_room_id': vroom.id
'room_type_id': room_type.id
})
hotel_vroom_avail_obj.with_context({
hotel_room_type_avail_obj.with_context({
'mail_create_nosubscribe': True,
}).create(vals)
@@ -275,7 +249,7 @@ class MassiveChangesWizard(models.TransientModel):
@api.multi
def _do_massive_change(self):
hotel_vroom_obj = self.env['hotel.virtual.room']
hotel_room_type_obj = self.env['hotel.room.type']
for record in self:
date_start_dt = date_utils.get_datetime(record.date_start,
hours=False)
@@ -285,8 +259,8 @@ class MassiveChangesWizard(models.TransientModel):
hours=False) + 1
wedays = (record.dmo, record.dtu, record.dwe, record.dth,
record.dfr, record.dsa, record.dsu)
vrooms = record.applied_on == '1' and record.room_type_id \
or hotel_vroom_obj.search([])
room_types = record.room_type_id if record.applied_on == '1' \
else hotel_room_type_obj.search([])
for i in range(0, diff_days):
ndate = date_start_dt + timedelta(days=i)
@@ -294,9 +268,9 @@ class MassiveChangesWizard(models.TransientModel):
continue
if record.section == '0':
self._save_availability(ndate, vrooms, record)
self._save_availability(ndate, room_types, record)
elif record.section == '1':
self._save_restrictions(ndate, vrooms, record)
self._save_restrictions(ndate, room_types, record)
elif record.section == '2':
self._save_prices(ndate, vrooms, record)
self._save_prices(ndate, room_types, record)
return True

View File

@@ -1,24 +1,5 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <dev@redneboa.es>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api

View File

@@ -1,26 +1,7 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
# Alexandre Díaz <dev@redneboa.es>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from datetime import datetime, timedelta
from datetime import timedelta
from openerp.exceptions import ValidationError
from openerp import models, fields, api, _
from openerp.tools import (
@@ -38,7 +19,7 @@ class SplitReservationWizard(models.TransientModel):
@api.multi
def split_reservation(self):
reservation_id = self.env['hotel.reservation'].browse(
self.env.context.get('active_id'))
self.env.context.get('active_id'))
if reservation_id:
date_start_dt = date_utils.get_datetime(reservation_id.checkin)
date_end_dt = date_utils.get_datetime(reservation_id.checkout)
@@ -72,8 +53,7 @@ class SplitReservationWizard(models.TransientModel):
tprice[0] += rline.price
reservation_id.write({
'checkout': new_start_date_dt.strftime(
DEFAULT_SERVER_DATETIME_FORMAT),
'checkout': new_start_date_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'price_unit': tprice[0],
'splitted': True,
})

View File

@@ -1213,13 +1213,13 @@ msgstr "hotel.virtual.room"
#. module: hotel_calendar
#: model:ir.model,name:hotel_calendar.model_hotel_virtual_room_availability
msgid "hotel.virtual.room.availability"
msgstr "hotel.virtual.room.availability"
msgid "hotel.room.type.availability"
msgstr "hotel.room.type.availability"
#. module: hotel_calendar
#: model:ir.model,name:hotel_calendar.model_hotel_virtual_room_restriction_item
msgid "hotel.virtual.room.restriction.item"
msgstr "hotel.virtual.room.restriction.item"
msgid "hotel.room.type.restriction.item"
msgstr "hotel.room.type.restriction.item"
#. module: hotel_calendar
#: model:ir.model,name:hotel_calendar.model_virtual_room_pricelist_cached

View File

@@ -51,8 +51,8 @@ class HotelCalendarManagement(models.TransientModel):
restrictions, availability):
vroom_obj = self.env['hotel.room.type']
product_pricelist_item_obj = self.env['product.pricelist.item']
vroom_rest_item_obj = self.env['hotel.virtual.room.restriction.item']
vroom_avail_obj = self.env['hotel.virtual.room.availability']
vroom_rest_item_obj = self.env['hotel.room.type.restriction.item']
vroom_avail_obj = self.env['hotel.room.type.availability']
# Save Pricelist
for k_price in pricelist.keys():
@@ -186,7 +186,7 @@ class HotelCalendarManagement(models.TransientModel):
for i in range(0, date_diff):
cur_date = date_start + timedelta(days=i)
cur_date_str = cur_date.strftime(DEFAULT_SERVER_DATE_FORMAT)
avail = self.env['hotel.virtual.room.availability'].search([
avail = self.env['hotel.room.type.availability'].search([
('date', '=', cur_date_str),
('virtual_room_id', '=', vroom.id)
])
@@ -280,7 +280,7 @@ class HotelCalendarManagement(models.TransientModel):
restriction_id = int(restriction_id)
vals.update({'restriction_id': restriction_id})
vroom_rest_it_obj = self.env['hotel.virtual.room.restriction.item']
vroom_rest_it_obj = self.env['hotel.room.type.restriction.item']
restriction_item_ids = vroom_rest_it_obj.search([
('date_start', '>=', dfrom), ('date_end', '<=', dto),
('restriction_id', '=', restriction_id),

View File

@@ -171,7 +171,7 @@ class HotelReservation(models.Model):
room_type_ids = self.env['hotel.room.type'].search(
[],
order='hcal_sequence ASC')
vroom_rest_obj = self.env['hotel.virtual.room.restriction.item']
vroom_rest_obj = self.env['hotel.room.type.restriction.item']
for room_type_id in room_type_ids:
days = {}
for i in range(0, date_diff):

View File

@@ -4,7 +4,7 @@ from odoo import models, fields, api
class HotelVirtualRoomAvailability(models.Model):
_inherit = 'hotel.virtual.room.availability'
_inherit = 'hotel.room.type.availability'
@api.model
def create(self, vals):

View File

@@ -6,7 +6,7 @@ _logger = logging.getLogger(__name__)
class HotelVirtualRoomResrtrictionItem(models.Model):
_inherit = 'hotel.virtual.room.restriction.item'
_inherit = 'hotel.room.type.restriction.item'
@api.model
def create(self, vals):

View File

@@ -49,7 +49,7 @@ return AbstractModel.extend({
get_restrictions: function () {
return this._rpc({
model: 'hotel.virtual.room.restriction',
model: 'hotel.room.type.restriction',
method: 'search_read',
args: [false, ['id','name']],
context: Session.user_context,

View File

@@ -231,7 +231,7 @@ var HotelCalendarManagementView = View.extend({
// Get Restrictions
self._restriction_id = results['restriction_id'];
new Model('hotel.virtual.room.restriction').query(['id','name']).all().then(function(resultsRestrictions){
new Model('hotel.room.type.restriction').query(['id','name']).all().then(function(resultsRestrictions){
var $list = self.$el.find('#mpms-search #restriction_list');
$list.html('');
resultsRestrictions.forEach(function(item, index){

View File

@@ -109,7 +109,7 @@ class TestManagementCalendar(TestHotelCalendar):
doesn't match!")
# REMOVE RESTRICTIONS
rest_it_obj = self.env['hotel.virtual.room.restriction.item'].sudo(
rest_it_obj = self.env['hotel.room.type.restriction.item'].sudo(
self.user_hotel_manager)
rest_ids = rest_it_obj.search([
('applied_on', '=', '0_virtual_room'),
@@ -137,7 +137,7 @@ class TestManagementCalendar(TestHotelCalendar):
hotel_cal_mngt_obj = self.env['hotel.calendar.management'].sudo(
self.user_hotel_manager)
vroom_avail_obj = self.env['hotel.virtual.room.availability'].sudo(
vroom_avail_obj = self.env['hotel.room.type.availability'].sudo(
self.user_hotel_manager)
hcal_data = hotel_cal_mngt_obj.get_hcalendar_all_data(

View File

@@ -345,10 +345,10 @@ class VirtualRoomWizars(models.TransientModel):
date_start = date_utils.get_datetime(res.checkin)
date_end = date_utils.get_datetime(res.checkout)
date_diff = date_utils.date_diff(date_start, date_end, hours=False)
minstay_restrictions = self.env['hotel.virtual.room.restriction.item'].search([
minstay_restrictions = self.env['hotel.room.type.restriction.item'].search([
('virtual_room_id','=',res.virtual_room_id.id),
])
avail_restrictions = self.env['hotel.virtual.room.availability'].search([
avail_restrictions = self.env['hotel.room.type.availability'].search([
('virtual_room_id','=',res.virtual_room_id.id)
])
real_max = len(res.virtual_room_id.check_availability_virtual_room(

View File

@@ -53,8 +53,6 @@
<field name="origin_sale"/>
<field name="overbooking" invisible="1" />
<field name="to_assign" invisible="1"/>
<!-- cardex_smart_button attrs depends on cardex_pending to be showed -->
<field name="cardex_pending" invisible="1"/>
<field name="price_unit" string="Reservation Price"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<field name="price_total" string="Final Price"/>

View File

@@ -9,7 +9,7 @@ class HotelConnectorModelBinder(Component):
_apply_on = [
'channel.hotel.reservation',
'channel.hotel.virtual.room',
'channel.hotel.virtual.room.availability',
'channel.hotel.virtual.room.restriction',
'channel.hotel.room.type.availability',
'channel.hotel.room.type.restriction',
'channel.product.pricelist',
]

View File

@@ -23,7 +23,7 @@ class HotelChannelConnectorExporter(AbstractComponent):
@api.model
def push_availability(self):
vroom_avail_ids = self.env['hotel.virtual.room.availability'].search([
vroom_avail_ids = self.env['hotel.room.type.availability'].search([
('wpushed', '=', False),
('date', '>=', date_utils.now(hours=False).strftime(
DEFAULT_SERVER_DATE_FORMAT))
@@ -110,8 +110,8 @@ class HotelChannelConnectorExporter(AbstractComponent):
@api.model
def push_restrictions(self):
vroom_rest_obj = self.env['hotel.virtual.room.restriction']
rest_item_obj = self.env['hotel.virtual.room.restriction.item']
vroom_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', '>=', date_utils.now(hours=False).strftime(

View File

@@ -17,7 +17,7 @@ class HotelChannelConnectorImporter(AbstractComponent):
@api.model
def _get_room_values_availability(self, vroom_id, date_str, day_vals, set_max_avail):
virtual_room_avail_obj = self.env['hotel.virtual.room.availability']
virtual_room_avail_obj = self.env['hotel.room.type.availability']
vroom_avail = virtual_room_avail_obj.search([
('virtual_room_id', '=', vroom_id),
('date', '=', date_str)
@@ -46,7 +46,7 @@ class HotelChannelConnectorImporter(AbstractComponent):
@api.model
def _get_room_values_restrictions(self, restriction_plan_id, vroom_id, date_str, day_vals):
vroom_restr_item_obj = self.env['hotel.virtual.room.restriction.item']
vroom_restr_item_obj = self.env['hotel.room.type.restriction.item']
vroom_restr = vroom_restr_item_obj.search([
('virtual_room_id', '=', vroom_id),
('applied_on', '=', '0_virtual_room'),
@@ -90,7 +90,7 @@ class HotelChannelConnectorImporter(AbstractComponent):
@api.model
def _generate_room_values(self, dfrom, dto, values, set_max_avail=False):
virtual_room_restr_obj = self.env['hotel.virtual.room.restriction']
virtual_room_restr_obj = self.env['hotel.room.type.restriction']
hotel_virtual_room_obj = self.env['hotel.room.type']
def_restr_plan = virtual_room_restr_obj.search([('wpid', '=', '0')])
_logger.info("==== ROOM VALUES (%s -- %s)", dfrom, dto)
@@ -565,7 +565,7 @@ class HotelChannelConnectorImporter(AbstractComponent):
@api.model
def _generate_restrictions(self, restriction_plans):
restriction_obj = self.env['hotel.virtual.room.restriction']
restriction_obj = self.env['hotel.room.type.restriction']
count = 0
for plan in restriction_plans:
vals = {
@@ -590,8 +590,8 @@ class HotelChannelConnectorImporter(AbstractComponent):
@api.model
def _generate_restriction_items(self, plan_restrictions):
hotel_virtual_room_obj = self.env['hotel.room.type']
reserv_restriction_obj = self.env['hotel.virtual.room.restriction']
restriction_item_obj = self.env['hotel.virtual.room.restriction.item']
reserv_restriction_obj = self.env['hotel.room.type.restriction']
restriction_item_obj = self.env['hotel.room.type.restriction.item']
_logger.info("===== RESTRICTIONS")
_logger.info(plan_restrictions)
for k_rpid, v_rpid in plan_restrictions.iteritems():

View File

@@ -84,7 +84,7 @@ class website_wubook(http.Controller):
parity_restr_id = request.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id')
if parity_restr_id:
vroom_restr_obj = request.env['hotel.virtual.room.restriction']
vroom_restr_obj = request.env['hotel.room.type.restriction']
restr_id = vroom_restr_obj.sudo().browse(int(parity_restr_id))
if restr_id and restr_id.wpid and restr_id.wpid != '0':
wubook_obj.fetch_rplan_restrictions(dfrom, dto,

View File

@@ -1023,18 +1023,18 @@ msgstr "hotel.virtual.room"
#. module: hotel_wubook_proto
#: model:ir.model,name:hotel_wubook_proto.model_hotel_virtual_room_availability
msgid "hotel.virtual.room.availability"
msgstr "hotel.virtual.room.availability"
msgid "hotel.room.type.availability"
msgstr "hotel.room.type.availability"
#. module: hotel_wubook_proto
#: model:ir.model,name:hotel_wubook_proto.model_hotel_virtual_room_restriction
msgid "hotel.virtual.room.restriction"
msgstr "hotel.virtual.room.restriction"
msgid "hotel.room.type.restriction"
msgstr "hotel.room.type.restriction"
#. module: hotel_wubook_proto
#: model:ir.model,name:hotel_wubook_proto.model_hotel_virtual_room_restriction_item
msgid "hotel.virtual.room.restriction.item"
msgstr "hotel.virtual.room.restriction.item"
msgid "hotel.room.type.restriction.item"
msgstr "hotel.room.type.restriction.item"
#. module: hotel_wubook_proto
#: model:ir.model,name:hotel_wubook_proto.model_hotel_wizard_duplicate_reservation

View File

@@ -124,7 +124,7 @@ class HotelReservation(models.Model):
if user.has_group('hotel.group_hotel_call'):
vals.update({'to_read': True})
res = super(HotelReservation, self).create(vals)
self.env['hotel.virtual.room.availability'].refresh_availability(
self.env['hotel.room.type.availability'].refresh_availability(
vals['checkin'],
vals['checkout'],
vals['product_id'])
@@ -155,7 +155,7 @@ class HotelReservation(models.Model):
res = super(HotelReservation, self).write(vals)
vroom_avail_obj = self.env['hotel.virtual.room.availability']
vroom_avail_obj = self.env['hotel.room.type.availability']
for i in range(0, len(older_vals)):
vroom_avail_obj.refresh_availability(
older_vals[i]['checkin'],
@@ -183,7 +183,7 @@ class HotelReservation(models.Model):
res = super(HotelReservation, self).unlink()
if self._context.get('wubook_action', True) and \
self.env['wubook'].is_valid_account():
vroom_avail_obj = self.env['hotel.virtual.room.availability']
vroom_avail_obj = self.env['hotel.room.type.availability']
for record in vals:
vroom_avail_obj.refresh_availability(
record['checkin'],

View File

@@ -118,7 +118,7 @@ class HotelRoomType(models.Model):
restriction_plan_id = int(self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id'))
self.ensure_one()
restriction = self.env['hotel.virtual.room.restriction.item'].search([
restriction = self.env['hotel.room.type.restriction.item'].search([
('date_start', '=', date),
('date_end', '=', date),
('virtual_room_id', '=', self.id),

View File

@@ -7,9 +7,9 @@ from odoo.addons.component.core import Component
from odoo.addons.component_event import skip_if
class ChannelHotelVirtualRoomAvailability(models.Model):
_name = 'channel.hotel.virtual.room.availability'
_name = 'channel.hotel.room.type.availability'
_inherit = 'channel.binding'
_inherits = {'hotel.virtual.room.availability': 'odoo_id'}
_inherits = {'hotel.room.type.availability': 'odoo_id'}
_description = 'Channel Product Pricelist'
@api.model
@@ -54,10 +54,10 @@ class ChannelHotelVirtualRoomAvailability(models.Model):
}])
class HotelVirtualRoomAvailability(models.Model):
_inherit = 'hotel.virtual.room.availability'
_inherit = 'hotel.room.type.availability'
channel_bind_ids = fields.One2many(
comodel_name='channel.hotel.virtual.room.availability',
comodel_name='channel.hotel.room.type.availability',
inverse_name='odoo_id',
string='Hotel Virtual Room Availability Connector Bindings')
@@ -105,7 +105,7 @@ class HotelVirtualRoomAvailability(models.Model):
date_diff = date_utils.date_diff(checkin, checkout, hours=False)
vroom_obj = self.env['hotel.virtual.room']
virtual_room_avail_obj = self.env['hotel.virtual.room.availability']
virtual_room_avail_obj = self.env['hotel.room.type.availability']
vrooms = vroom_obj.search([
('room_ids.product_id', '=', product_id)
@@ -138,9 +138,9 @@ class HotelVirtualRoomAvailability(models.Model):
})
class ChannelBindingHotelVirtualRoomAvailabilityListener(Component):
_name = 'channel.binding.hotel.virtual.room.availability.listener'
_name = 'channel.binding.hotel.room.type.availability.listener'
_inherit = 'base.connector.listener'
_apply_on = ['channel.hotel.virtual.room.availability']
_apply_on = ['channel.hotel.room.type.availability']
@skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
def on_fix_channel_availability(self, record, fields=None):

View File

@@ -7,12 +7,12 @@ from odoo.addons.component.core import Component
from odoo.addons.component_event import skip_if
class ChannelHotelVirtualRoomRestriction(models.Model):
_name = 'channel.hotel.virtual.room.restriction'
_name = 'channel.hotel.room.type.restriction'
_inherit = 'channel.binding'
_inherits = {'hotel.virtual.room.restriction': 'odoo_id'}
_inherits = {'hotel.room.type.restriction': 'odoo_id'}
_description = 'Channel Hotel Virtual Room Restriction'
odoo_id = fields.Many2one(comodel_names='hotel.virtual.room.restriction',
odoo_id = fields.Many2one(comodel_names='hotel.room.type.restriction',
string='Hotel Virtual Room Restriction',
required=True,
ondelete='cascade')
@@ -71,17 +71,17 @@ class ChannelHotelVirtualRoomRestriction(models.Model):
return importer.import_restriction_plans()
class HotelVirtualRoomRestriction(models.Model):
_inherit = 'hotel.virtual.room.restriction'
_inherit = 'hotel.room.type.restriction'
channel_bind_ids = fields.One2many(
comodel_name='channel.hotel.virtual.room.restriction',
comodel_name='channel.hotel.room.type.restriction',
inverse_name='odoo_id',
string='Hotel Channel Connector Bindings')
@api.multi
@api.depends('name')
def name_get(self):
vroom_restriction_obj = self.env['hotel.virtual.room.restriction']
vroom_restriction_obj = self.env['hotel.room.type.restriction']
org_names = super(HotelVirtualRoomRestriction, self).name_get()
names = []
for name in org_names:
@@ -93,9 +93,9 @@ class HotelVirtualRoomRestriction(models.Model):
return names
class ChannelBindingHotelVirtualRoomRestrictionListener(Component):
_name = 'channel.binding.hotel.virtual.room.restriction.listener'
_name = 'channel.binding.hotel.room.type.restriction.listener'
_inherit = 'base.connector.listener'
_apply_on = ['channel.hotel.virtual.room.restriction']
_apply_on = ['channel.hotel.room.type.restriction']
@skip_if(lambda self, record, **kwargs: self.no_connector_export(record))
def on_record_write(self, record, fields=None):

View File

@@ -5,7 +5,7 @@ from openerp import models, fields, api
class ReservationRestrictionItem(models.Model):
_inherit = 'hotel.virtual.room.restriction.item'
_inherit = 'hotel.room.type.restriction.item'
channel_pushed = fields.Boolean("WuBook Pushed", default=False, readonly=True,
old_name='wpushed')

View File

@@ -77,7 +77,7 @@ class HotelChannelConnectorConfiguration(models.TransientModel):
'wscode': '',
})
# Create Restrictions
vroom_rest_obj = self.env['hotel.virtual.room.restriction']
vroom_rest_obj = self.env['hotel.room.type.restriction']
restriction_ids = vroom_rest_obj.search([])
for restriction in restriction_ids:
if restriction.wpid != '0':
@@ -119,7 +119,7 @@ class HotelChannelConnectorConfiguration(models.TransientModel):
restriction_id = int(self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id'))
vroom_restr_it_obj = self.env['hotel.virtual.room.restriction.item']
vroom_restr_it_obj = self.env['hotel.room.type.restriction.item']
# Secure Wubook Input
restriction_item_ids = vroom_restr_it_obj.search([
('applied_on', '=', '0_virtual_room'),
@@ -165,7 +165,7 @@ class HotelChannelConnectorConfiguration(models.TransientModel):
})
# Secure Wubook Input
availabity_ids = self.env['hotel.virtual.room.availability'].search([
availabity_ids = self.env['hotel.room.type.availability'].search([
('date', '<', now_utc_str),
])
if any(availabity_ids):
@@ -173,7 +173,7 @@ class HotelChannelConnectorConfiguration(models.TransientModel):
'wpushed': True
})
# Put to push availability
availabity_ids = self.env['hotel.virtual.room.availability'].search([
availabity_ids = self.env['hotel.room.type.availability'].search([
('wpushed', '=', True),
('date', '>=', now_utc_str),
])

View File

@@ -171,12 +171,12 @@ ListView.include({
} else if (this.dataset.model === 'wubook.channel.info') {
this.$buttons.append("<button class='oe_button oe_channel_connector_import_channels_info oe_highlight' type='button'>"+_t('Fetch from Channel')+"</button>");
this.$buttons.find('.oe_channel_connector_import_channels_info').on('click', import_channels_info.bind(this));
} else if (this.dataset.model === 'hotel.virtual.room.restriction') {
} else if (this.dataset.model === 'hotel.room.type.restriction') {
this.$buttons.append("<button class='oe_button oe_channel_connector_import_restriction_plans oe_highlight' type='button'>"+_t('Fetch from Channel')+"</button>");
this.$buttons.find('.oe_channel_connector_import_restriction_plans').on('click', import_restriction_plans.bind(this));
this.$buttons.append("<button class='oe_button oe_channel_connector_push_restriction_plans' style='background-color:red; color:white;' type='button'>"+_t('Push to Channel')+"</button>");
this.$buttons.find('.oe_channel_connector_push_restriction_plans').on('click', push_restriction_plans.bind(this));
} else if (this.dataset.model === 'hotel.virtual.room.availability') {
} else if (this.dataset.model === 'hotel.room.type.availability') {
this.$buttons.append("<button class='oe_button oe_channel_connector_import_availability oe_highlight' type='button'>"+_t('Fetch from Channel')+"</button>");
this.$buttons.find('.oe_channel_connector_import_availability').on('click', import_availability.bind(this));
this.$buttons.append("<button class='oe_button oe_channel_connector_push_availability' style='background-color:red; color:white;' type='button'>"+_t('Push to Channel')+"</button>");

View File

@@ -252,7 +252,7 @@ class TestHotelWubook(TestHotel):
})
# Update Restriction
vroom_restr_obj = cls.env['hotel.virtual.room.restriction']
vroom_restr_obj = cls.env['hotel.room.type.restriction']
default_restriction = vroom_restr_obj.search([
('wpid', '=', '0')
], limit=1)

View File

@@ -34,7 +34,7 @@ class TestReservationRestrictionItem(TestHotelWubook):
now_utc_dt = date_utils.now()
day_utc_dt = now_utc_dt + timedelta(days=20)
day_utc_str = day_utc_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)
rest_item_obj = self.env['hotel.virtual.room.restriction.item']
rest_item_obj = self.env['hotel.room.type.restriction.item']
restriction = rest_item_obj.search([], limit=1)
self.assertTrue(restriction, "Can't found restriction for test")
restriction.write({

View File

@@ -33,7 +33,7 @@ class TestReservationRestriction(TestHotelWubook):
self.assertTrue(any(wrests), "Any restriction found")
def test_create(self):
vroo_restriction_obj = self.env['hotel.virtual.room.restriction']
vroo_restriction_obj = self.env['hotel.room.type.restriction']
# Restriction Plan
restriction = vroo_restriction_obj.sudo(self.user_hotel_manager).\
create({
@@ -43,7 +43,7 @@ class TestReservationRestriction(TestHotelWubook):
self.assertTrue(restriction, "Can't create new restriction")
def test_write(self):
vroo_restriction_obj = self.env['hotel.virtual.room.restriction']
vroo_restriction_obj = self.env['hotel.room.type.restriction']
# Restriction Plan
restriction = vroo_restriction_obj.sudo(self.user_hotel_manager).\
create({
@@ -60,7 +60,7 @@ class TestReservationRestriction(TestHotelWubook):
"Can't modif restriction")
def test_unlink(self):
vroo_restriction_obj = self.env['hotel.virtual.room.restriction']
vroo_restriction_obj = self.env['hotel.room.type.restriction']
# Restriction Plan
restriction = vroo_restriction_obj.sudo(self.user_hotel_manager).\
create({
@@ -72,7 +72,7 @@ class TestReservationRestriction(TestHotelWubook):
restriction.sudo(self.user_hotel_manager).unlink()
def test_import_restriction_plans(self):
vroo_restriction_obj = self.env['hotel.virtual.room.restriction']
vroo_restriction_obj = self.env['hotel.room.type.restriction']
# Restriction Plan
restriction = vroo_restriction_obj.sudo(self.user_hotel_manager).\
create({
@@ -84,7 +84,7 @@ class TestReservationRestriction(TestHotelWubook):
restriction.sudo(self.user_hotel_manager).import_restriction_plans()
def test_name_get(self):
vroo_restriction_obj = self.env['hotel.virtual.room.restriction']
vroo_restriction_obj = self.env['hotel.room.type.restriction']
# Restriction Plan
restriction = vroo_restriction_obj.sudo(self.user_hotel_manager).\
create({

View File

@@ -32,7 +32,7 @@ class TestVirtualRoomAvailability(TestHotelWubook):
def test_write(self):
now_utc_dt = date_utils.now()
day_utc_dt = now_utc_dt + timedelta(days=1)
vroom_avail_obj = self.env['hotel.virtual.room.availability']
vroom_avail_obj = self.env['hotel.room.type.availability']
avail = vroom_avail_obj.search([
('virtual_room_id', '=', self.hotel_vroom_budget.id),
('date', '=', now_utc_dt.strftime(DEFAULT_SERVER_DATE_FORMAT))

View File

@@ -552,7 +552,7 @@ class TestWubook(TestHotelWubook):
checkout_utc_dt = checkin_utc_dt + timedelta(days=1)
checkout_dt = date_utils.dt_as_timezone(checkout_utc_dt,
self.tz_hotel)
vroom_restr_item_obj = self.env['hotel.virtual.room.restriction.item']
vroom_restr_item_obj = self.env['hotel.room.type.restriction.item']
vrooms = [self.hotel_vroom_budget, self.hotel_vroom_special]
values = self.create_wubook_rooms_values(

View File

@@ -2,8 +2,8 @@
<odoo>
<record id="view_channel_hotel_virtual_room_availability_form" model="ir.ui.view">
<field name="name">channel.hotel.virtual.room.availability.form</field>
<field name="model">channel.hotel.virtual.room.availability</field>
<field name="name">channel.hotel.room.type.availability.form</field>
<field name="model">channel.hotel.room.type.availability</field>
<field name="arch" type="xml">
<form string="Hotel Channel Room Availability">
<group>
@@ -15,7 +15,7 @@
</record>
<record id="view_channel_hotel_virtual_room_availability_tree" model="ir.ui.view">
<field name="name">channel.hotel.virtual.room.availability.tree</field>
<field name="name">channel.hotel.room.type.availability.tree</field>
<field name="model">channel.hotel.virtual.availability.room</field>
<field name="arch" type="xml">
<tree string="Hotel Channel Room Availability">

View File

@@ -2,8 +2,8 @@
<odoo>
<record id="view_channel_hotel_virtual_room_restriction_form" model="ir.ui.view">
<field name="name">channel.hotel.virtual.room.restriction.form</field>
<field name="model">channel.hotel.virtual.room.restriction</field>
<field name="name">channel.hotel.room.type.restriction.form</field>
<field name="model">channel.hotel.room.type.restriction</field>
<field name="arch" type="xml">
<form string="Hotel Channel Room Restriction">
<group>
@@ -15,7 +15,7 @@
</record>
<record id="view_channel_hotel_virtual_room_restriction_tree" model="ir.ui.view">
<field name="name">channel.hotel.virtual.room.restriction.tree</field>
<field name="name">channel.hotel.room.type.restriction.tree</field>
<field name="model">channel.hotel.virtual.restriction.room</field>
<field name="arch" type="xml">
<tree string="Hotel Channel Room Restriction">

View File

@@ -3,7 +3,7 @@
<!-- FORM availability -->
<record id="virtual_room_availability_view_form" model="ir.ui.view">
<field name="model">hotel.virtual.room.availability</field>
<field name="model">hotel.room.type.availability</field>
<field name="inherit_id" ref="hotel.virtual_room_availability_view_form" />
<field name="arch" type="xml">
<xpath expr="//sheet" position="inside">
@@ -24,7 +24,7 @@
<!-- TREE restriction -->
<record id="virtual_room_availability_view_tree" model="ir.ui.view">
<field name="model">hotel.virtual.room.availability</field>
<field name="model">hotel.room.type.availability</field>
<field name="inherit_id" ref="hotel.virtual_room_availability_view_tree" />
<field name="type">tree</field>
<field name="arch" type="xml">

View File

@@ -2,7 +2,7 @@
<odoo>
<record id="reservation_restriction_item_form_view" model="ir.ui.view">
<field name="model">hotel.virtual.room.restriction.item</field>
<field name="model">hotel.room.type.restriction.item</field>
<field name="inherit_id" ref="hotel.reservation_restriction_item_view_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='date_end']" position="attributes">

View File

@@ -2,7 +2,7 @@
<odoo>
<record id="reservation_restriction_view" model="ir.ui.view">
<field name="model">hotel.virtual.room.restriction</field>
<field name="model">hotel.room.type.restriction</field>
<field name="inherit_id" ref="hotel.reservation_restriction_view_form" />
<field name="arch" type="xml">
<xpath expr="//form[1]//sheet" position="before">

View File

@@ -33,7 +33,7 @@ class ImportPlanRestrictionsWizard(models.TransientModel):
@api.multi
def import_plan_restrictions(self):
restriction_id = self.env['hotel.virtual.room.restriction'].browse(
restriction_id = self.env['hotel.room.type.restriction'].browse(
self.env.context.get('active_id'))
if restriction_id:
for record in self:

View File

@@ -72,7 +72,7 @@ class WuBookInstaller(models.TransientModel):
self.env.cr.commit() # FIXME: Need do this
# Create Wubook Base Restrictions
restr_obj = self.env['hotel.virtual.room.restriction'].with_context({
restr_obj = self.env['hotel.room.type.restriction'].with_context({
'wubook_action': False
})
base_rest = restr_obj.search([('wpid', '=', '0')], limit=1)
@@ -108,7 +108,7 @@ class WuBookInstallerParity(models.TransientModel):
parity_pricelist_id = fields.Many2one('product.pricelist',
'Product Pricelist')
parity_restrictions_id = fields.Many2one('hotel.virtual.room.restriction',
parity_restrictions_id = fields.Many2one('hotel.room.type.restriction',
'Restrictions')
import_data = fields.Boolean('Import Data From WuBook', default=False)
date_start = fields.Date('Date Start')