Merge branch '11.0' into hotel_node_master

This commit is contained in:
Pablo
2018-11-07 20:46:00 +01:00
221 changed files with 2778 additions and 3396 deletions

View File

@@ -1,28 +0,0 @@
============================================================================================================================
Version Change Log (hotel)
============================================================================================================================
0.07 on 2013-10-31 by Murtuza Saleh
*Improved hotel.room kanban view as per in v9.
0.06 on 2013-10-29 by Ashish Thakkar
*Set the product_category_tree_view in the hotel_view.xml file.
*Improved the code to get the hierarchy in rooms,amenities and services.
0.05 on 2013-10-28 by Anu Patel
* Set the default value of check in date and check out date.
* Improved calculation of duration for hotel check in - checkout.
0.04 on 2013-10-28 by Anu Patel
* Improved ir.sequence for hotel.folio.
* Improved hotel folio line one2many field as faced problem because of product_uos field.
0.03 on 2013-10-25 by Anu Patel
* Improved on_change in hotel folio line where product_id onchange is not working.
* Removed on_chage from .xml file as there is no need to define there.
0.02 on 2013-10-26 by Anu Patel
* Improved the code for removed the workflow in hotel folio as workflow is no longer used in v9.
* Improved states used in hotel folio from sale order as per in v9.
0.01 on 2013-10-16 by Ashish Thakkar
* Made the module installable in v9.

View File

@@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnotel - Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models
from . import wizard
from . import report
from . import date_utils

View File

@@ -1,66 +1,60 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Alexandre Díaz
# Copyright 2018 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Hotel Management',
'version': '0.07',
'version': '11.0.2.0.0',
'author': 'Odoo Community Association (OCA),\
Darío Lodeiros,\
Jose Luis Algara,\
Alexandre Díaz',
'images': [],
Alexandre Díaz,\
Q. Barriuso,',
'category': 'Generic Modules/Hotel Management',
'website': '',
'website': 'https://github.com/hootel/hootel',
'depends': [
'sale_stock',
'account_payment_return',
],
'license': "",
'license': "AGPL-3",
'demo': ['data/hotel_data.xml'],
'data': [
'security/hotel_security.xml',
'security/ir.model.access.csv',
# 'security/ir.model.access.csv',
'wizard/massive_changes.xml',
'wizard/split_reservation.xml',
'wizard/duplicate_reservation.xml',
'views/res_config.xml',
'data/menus.xml',
'views/inherit_account_payment_views.xml',
'views/inherit_account_invoice_views.xml',
'wizard/hotel_wizard.xml',
'views/inherited_account_payment_views.xml',
'views/inherited_account_invoice_views.xml',
'wizard/checkinwizard.xml',
'wizard/massive_price_reservation_days.xml',
'wizard/folio_make_invoice_advance_views.xml',
'views/hotel_sequence.xml',
'views/hotel_report.xml',
'views/report_hotel_management.xml',
'views/currency_exchange.xml',
'views/hotel_floor.xml',
'views/hotel_folio.xml',
'views/inherit_res_partner.xml',
# 'views/hotel_service_type.xml',
# 'views/hotel_service_line.xml',
'views/hotel_room_type.xml',
'views/hotel_room.xml',
# 'views/hotel_service.xml',
'views/inherit_product_product.xml',
'views/hotel_room_amenities_type.xml',
'views/hotel_room_amenities.xml',
'data/hotel_sequence.xml',
'views/hotel_floor_views.xml',
'views/hotel_folio_views.xml',
'views/inherited_res_partner_views.xml',
'views/hotel_room_type_views.xml',
'views/hotel_room_views.xml',
'views/hotel_room_type_class_views.xml',
'views/general.xml',
'views/inherited_product_template_views.xml',
'views/hotel_room_amenities_type_views.xml',
'views/hotel_room_amenities_views.xml',
'views/hotel_room_type_restriction_views.xml',
'views/hotel_room_type_restriction_item_views.xml',
'views/hotel_reservation.xml',
# 'views/room_type_views.xml',
'views/cardex.xml',
'views/hotel_room_type_availability.xml',
# 'views/hotel_dashboard.xml',
'views/hotel_reservation_views.xml',
'views/hotel_room_closure_reason_views.xml',
'views/hotel_board_service_views.xml',
'views/hotel_checkin_partner_views.xml',
'views/hotel_room_type_availability_views.xml',
'data/cron_jobs.xml',
'data/records.xml',
'data/email_template_cancel.xml',
'data/email_template_reserv.xml',
'data/email_template_exit.xml',
'wizard/wizard_reservation.xml',
],
'css': ['static/src/css/room_kanban.css'],
'auto_install': False,
'installable': True
}

View File

@@ -3,20 +3,7 @@
<data noupdate="1">
<record id="daily_plan_checkin_out" model="ir.cron">
<field name="name">Daily Plan</field>
<field name="active" eval="True" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall">0</field>
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 05:00:00')"/>
<field name="model_id" ref="model_hotel_reservation" />
<field name="code">model.daily_plan()</field>
</record>
<!-- Scheduler For To Inform Guest About Reservation Before 24 Hours -->
<!-- Scheduler For To Inform Guest About Reservation Before 24 Hours -->
<record model="ir.cron" id="Guest_reservation_reminder_24hrs">
<field name="name">Inform Guest About Reservation Before 24 Hours</field>
<field name="interval_number">1</field>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -116,6 +116,7 @@
<field name="floor_id" search="[('name', '=', 'Second Floor')]"/>
<field name="list_price">25.00</field>
<field name="capacity">3</field>
</record>
</record
</data>
</odoo>

View File

@@ -13,13 +13,15 @@
sequence="15" parent="hotel_management_menu"
groups="hotel.group_hotel_user"/>
<menuitem id="menu_account_finance_xls_reports" name="XLS Reports" parent="hotel.hotel_reports_menu" sequence="50"/>
<menuitem id="menu_account_finance_xls_reports" name="XLS Reports"
parent="hotel.hotel_reports_menu" sequence="50"/>
<menuitem id="configuration_others" name="Configuration"
parent="hotel.hotel_configuration_menu" sequence="10"
groups="hotel.group_hotel_manager" />
groups="hotel.group_hotel_manager" />
<menuitem id="hotel_massive_change" parent="hotel.configuration_others"
sequence="10" action="action_hotel_massive_change" name="Massive Changes"/>
<menuitem id="hotel_massive_change" name="Massive Changes"
parent="hotel.configuration_others"
sequence="10" action="action_hotel_massive_change"/>
</odoo>

View File

@@ -6,13 +6,13 @@
</record>
<function id="default_generate_parity_pricelist_id"
<function id="default_pricelist_id"
model="ir.default" name="set"
eval="('res.config.settings', 'parity_pricelist_id', 1)"/>
eval="('res.config.settings', 'default_pricelist_id', 1)"/>
<function id="default_generate_parity_restrictions_id"
<function id="default_restriction_id"
model="ir.default" name="set"
eval="('res.config.settings', 'parity_restrictions_id', 1)"/>
eval="('res.config.settings', 'default_restriction_id', 1)"/>
<function id="default_generate_default_arrival_hour"
model="ir.default" name="set"

View File

@@ -1,206 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2018 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 dateutil import tz
from openerp.tools import (
DEFAULT_SERVER_DATETIME_FORMAT,
DEFAULT_SERVER_DATE_FORMAT)
from openerp import fields, _
from openerp.exceptions import ValidationError
# Generate a 'datetime' object from 'str_date' string with 'dtformat' format.
def _generate_datetime(str_date, dtformat, stz=False):
ndate = False
try:
ndate = datetime.strptime(str_date, dtformat)
ndate = ndate.replace(tzinfo=tz.gettz(stz and str(stz) or 'UTC'))
except ValueError:
return False
return ndate
# Try generate a 'datetime' object from 'str_date' string
# using all odoo formats
def get_datetime(str_date, dtformat=False, hours=True, end_day=False,
stz=False):
if dtformat:
date_dt = _generate_datetime(str_date, dtformat, stz=stz)
else:
date_dt = _generate_datetime(
str_date,
DEFAULT_SERVER_DATETIME_FORMAT,
stz=stz)
if not date_dt:
date_dt = _generate_datetime(
str_date,
DEFAULT_SERVER_DATE_FORMAT,
stz=stz)
if date_dt:
if end_day:
date_dt = dt_no_hours(date_dt, end_day=True)
elif not hours:
date_dt = dt_no_hours(date_dt)
return date_dt
# Compare two dates
def date_compare(str_date_a, str_date_b, hours=True):
date_dt_a = get_datetime(str_date_a)
date_dt_b = get_datetime(str_date_b)
if not hours:
date_dt_a = dt_no_hours(date_dt_a)
date_dt_b = dt_no_hours(date_dt_b)
return date_dt_a == date_dt_b
# Set hours to zero
def dt_no_hours(new_start_date_dt, end_day=False):
if not end_day:
return new_start_date_dt.replace(hour=0, minute=0, second=0,
microsecond=0)
else:
return new_start_date_dt.replace(hour=23, minute=59, second=59,
microsecond=999999)
# Get now 'datetime' object
def now(hours=False):
now_utc_dt = fields.datetime.now().replace(tzinfo=tz.tzutc())
if not hours:
now_utc_dt = now_utc_dt.replace(hour=0, minute=0, second=0,
microsecond=0)
return now_utc_dt
# Get the difference in days between 'str_date_start' and 'str_date_end'
def date_diff(date_start, date_end, hours=True, stz=False):
if not isinstance(date_start, datetime):
date_start_dt = get_datetime(date_start, stz=stz)
else:
date_start_dt = date_start
if not isinstance(date_end, datetime):
date_end_dt = get_datetime(date_end, stz=stz)
else:
date_end_dt = date_end
if not date_start_dt or not date_end_dt:
raise ValidationError(_("Invalid date. Can't compare it!"))
if not hours:
date_start_dt = dt_no_hours(date_start_dt)
date_end_dt = dt_no_hours(date_end_dt)
return abs((date_end_dt - date_start_dt).days)
# Get a new 'datetime' object from 'date_dt' usign the 'tz' timezone
def dt_as_timezone(date_dt, stz):
return date_dt.astimezone(tz.gettz(stz and str(stz) or 'UTC'))
# Generate a list of days start in 'cdate'
def generate_dates_list(cdate,
num_days,
outformat=DEFAULT_SERVER_DATE_FORMAT, stz=False):
ndate = get_datetime(cdate, stz=stz) if not isinstance(cdate, datetime) \
else cdate
return [(ndate + timedelta(days=i)).strftime(outformat)
for i in range(0, num_days)]
# Check if 'str_date' is between 'str_start_date' and 'str_end_date'
# 0 Inside
# -1 'str_date' is before 'str_start_date'
# 1 'str_date' is after 'str_end_date'
def date_in(str_date, str_start_date, str_end_date, hours=True, stz=False):
if not isinstance(str_date, datetime):
date_dt = get_datetime(str_date, stz=stz)
else:
date_dt = str_date
if not isinstance(str_start_date, datetime):
date_start_dt = get_datetime(str_date_start, stz=stz)
else:
date_start_dt = str_start_date
if not isinstance(str_end_date, datetime):
date_end_dt = get_datetime(str_end_date, stz=stz)
else:
date_end_dt = str_end_date
if not date_start_dt or not date_end_dt or not date_dt:
raise ValidationError(_("Invalid date. Can't compare it!"))
if not hours:
date_start_dt = dt_no_hours(date_start_dt)
date_end_dt = dt_no_hours(date_end_dt)
res = -2
if date_dt >= date_start_dt and date_dt <= date_end_dt:
res = 0
elif date_dt > date_end_dt:
res = 1
elif date_dt < date_start_dt:
res = -1
return res
# Check if 'str_start_date_a' and 'str_start_date_b'
# is between 'str_start_date_b' and 'str_end_date_b'
# 0 Inside
# -1 'str_date' is before 'str_start_date'
# 1 'str_date' is after 'str_end_date'
def range_dates_in(str_start_date_a,
str_end_date_a,
str_start_date_b,
str_end_date_b,
hours=True, stz=False):
date_start_dt_a = get_datetime(str_start_date_a, stz=stz)
date_end_dt_a = get_datetime(str_end_date_a, stz=stz)
date_start_dt_b = get_datetime(str_start_date_b, stz=stz)
date_end_dt_b = get_datetime(str_end_date_b, stz=stz)
if not date_start_dt_a or not date_end_dt_a \
or not date_start_dt_b or not date_end_dt_b:
raise ValidationError(_("Invalid date. Can't compare it!"))
if not hours:
date_start_dt_b = dt_no_hours(date_start_dt_b)
date_end_dt_b = dt_no_hours(date_end_dt_b)
res = -2
if date_start_dt_a >= date_start_dt_b and date_end_dt_a <= date_end_dt_b:
res = 0
elif date_start_dt_a < date_start_dt_b \
and date_end_dt_a >= date_start_dt_b:
res = -1
elif date_start_dt_a <= date_end_dt_b and date_end_dt_a > date_end_dt_b:
res = 1
return res

Binary file not shown.

View File

@@ -2999,13 +2999,13 @@ msgid "Action Needed"
msgstr "Action Needed"
#. module: hotel
#: model:ir.actions.act_window,name:hotel.action_cardex
msgid "Action cardex"
#: model:ir.actions.act_window,name:hotel.action_checkin_partner
msgid "Action checkin"
msgstr "Acción Checkin"
#. module: hotel
#: model:ir.actions.act_window,name:hotel.action_cardex_download
msgid "Action cardex download"
#: model:ir.actions.act_window,name:hotel.action_checkin_partner_download
msgid "Action checkin download"
msgstr "Accción descarga de checkin"
#. module: hotel
@@ -3311,39 +3311,39 @@ msgid "Capacity:"
msgstr "Capacidad:"
#. module: hotel
#: model:ir.ui.menu,name:hotel.menu_cardex
msgid "Cardex"
#: model:ir.ui.menu,name:hotel.menu_checkin_partner
msgid "Checkin"
msgstr "Checkin"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_cardex_pending
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_cardex_pending_num
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_cardex_pending
msgid "Cardex Pending"
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_checkin_partner_pending
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_checkin_partner_pending_num
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_checkin_partner_pending
msgid "Checkin Pending"
msgstr "Checkin Pendientes"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_cardex_pending_num
msgid "Cardex Pending Num"
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_checkin_partner_pending_num
msgid "Checkin Pending Num"
msgstr "Nº de Checkin Pendientes"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_cardex_count
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_cardex_count
msgid "Cardex counter"
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_checkin_partner_count
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_checkin_partner_count
msgid "Checkin counter"
msgstr "Contador de Checkin"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_cardex_ids
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_cardex_ids
msgid "Cardex ids"
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_checkin_partner_ids
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_checkin_partner_ids
msgid "Checkin ids"
msgstr "Checkin ids"
#. module: hotel
#: code:addons/hotel/models/hotel_folio.py:333
#: code:addons/hotel/models/hotel_reservation.py:359
#, python-format
msgid "Cardexs"
msgid "Checkins"
msgstr "Checkin"
#. module: hotel
@@ -3483,7 +3483,7 @@ msgstr "Niños"
#. module: hotel
#: model:ir.ui.view,arch_db:hotel.checkin_wizard_form_2
#: model:ir.ui.view,arch_db:hotel.view_tree_cardex
#: model:ir.ui.view,arch_db:hotel.view_tree_checkin_partner
msgid "Client name"
msgstr "Nombre de Cliente"
@@ -3653,7 +3653,7 @@ msgid "Create invoice/bill"
msgstr "Crear Factura/cuenta"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_create_uid
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_create_uid
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_create_uid
#: model:ir.model.fields,field_description:hotel.field_currency_exchange_create_uid
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_create_uid
@@ -3682,7 +3682,7 @@ msgid "Created by"
msgstr "Creado por"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_create_date
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_create_date
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_create_date
#: model:ir.model.fields,field_description:hotel.field_currency_exchange_create_date
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_create_date
@@ -3926,13 +3926,13 @@ msgid "Delivery address for current sales order."
msgstr "Dirección de entrega para el pedido de venta actual."
#. module: hotel
#: code:addons/hotel/models/cardex.py:38
#: code:addons/hotel/models/checkin.py:38
#, python-format
msgid "Departure date (%s) is prior to arrival on %s"
msgstr "La fecha de salida (%s) es anterior a la llegada el %s"
#. module: hotel
#: code:addons/hotel/models/cardex.py:80
#: code:addons/hotel/models/checkin.py:80
#, python-format
msgid "Departure date, is prior to arrival. Check it now. %s"
msgstr "La fecha de salida es anterior a la llegada. Revíselo ahora. %s"
@@ -3999,7 +3999,7 @@ msgid "Discount Type"
msgstr "Tipo de Descuento"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_display_name
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_display_name
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_display_name
#: model:ir.model.fields,field_description:hotel.field_currency_exchange_display_name
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_display_name
@@ -4098,7 +4098,7 @@ msgid "Duration in Days"
msgstr "Duración en días"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_email_cardex
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_email_checkin_partner
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_email
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_email
msgid "E-mail"
@@ -4127,13 +4127,13 @@ msgid "End Date"
msgstr "Fecha finalización"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_enter_date
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_enter_date
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_enter_date
msgid "Enter date"
msgstr "Fecha Entrada"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_exit_date
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_exit_date
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_exit_date
msgid "Exit date"
msgstr "Fecha Salida"
@@ -4444,7 +4444,7 @@ msgstr "Nombre del Hotel"
#. module: hotel
#: model:ir.ui.view,arch_db:hotel.view_hotel_config_settings
msgid "Hotel Parity"
msgid "Hotel Default"
msgstr "Emparejado"
#. module: hotel
@@ -4532,7 +4532,7 @@ msgid "Hotel services detail provide tocustomer and it will include in main Invo
msgstr "Los detalles de servicios al cliente que se incluirán en la Factura principal."
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_id
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_id
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_id
#: model:ir.model.fields,field_description:hotel.field_currency_exchange_id
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_id
@@ -4962,7 +4962,7 @@ msgid "Last Message Date"
msgstr "Last Message Date"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex___last_update
#: model:ir.model.fields,field_description:hotel.field_checkin_partner___last_update
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard___last_update
#: model:ir.model.fields,field_description:hotel.field_currency_exchange___last_update
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv___last_update
@@ -4997,7 +4997,7 @@ msgid "Last Updated"
msgstr "Actualizado el"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_write_uid
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_write_uid
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_write_uid
#: model:ir.model.fields,field_description:hotel.field_currency_exchange_write_uid
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_write_uid
@@ -5026,7 +5026,7 @@ msgid "Last Updated by"
msgstr "Última actualización de"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_write_date
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_write_date
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_write_date
#: model:ir.model.fields,field_description:hotel.field_currency_exchange_write_date
#: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_write_date
@@ -5288,7 +5288,7 @@ msgid "Minimum Stock Rules"
msgstr "Reglas de stock mínimo"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_mobile_cardex
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_mobile_checkin_partner
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_mobile
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_mobile
msgid "Mobile"
@@ -5570,7 +5570,7 @@ msgid "Partner for checkin"
msgstr "Partner for checkin"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_partner_id
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_partner_id
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_partner_id
msgid "Partner id"
msgstr "Id del cliente"
@@ -5831,7 +5831,7 @@ msgid "Product Category"
msgstr "Categoría de producto"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_hotel_config_settings_parity_pricelist_id
#: model:ir.model.fields,field_description:hotel.field_hotel_config_settings_default_pricelist_id
msgid "Product Pricelist"
msgstr "Lista de precios del producto"
@@ -6089,7 +6089,7 @@ msgid "Reservation has no adults"
msgstr "La reserva no tiene adultos"
#. module: hotel
#: model:ir.model.fields,field_description:hotel.field_cardex_reservation_id
#: model:ir.model.fields,field_description:hotel.field_checkin_partner_reservation_id
#: model:ir.model.fields,field_description:hotel.field_checkin_wizard_reservation_id
msgid "Reservation id"
msgstr "Reserva id"
@@ -6163,7 +6163,7 @@ msgstr "Nombre del Plan de Restricciones"
#. module: hotel
#: selection:hotel.wizard.massive.changes,section:0
#: model:ir.model.fields,field_description:hotel.field_hotel_config_settings_parity_restrictions_id
#: model:ir.model.fields,field_description:hotel.field_hotel_config_settings_default_restriction_id
#: model:ir.ui.menu,name:hotel.reservation_restriction_menu
#: model:ir.ui.view,arch_db:hotel.reservation_restriction_item_view_form
#: model:ir.ui.view,arch_db:hotel.reservation_restriction_item_view_tree
@@ -7477,8 +7477,8 @@ msgid "can't assign the same date to more than
msgstr "no puede asignar la misma fecha a más de una habitación virtual"
#. module: hotel
#: model:ir.model,name:hotel.model_cardex
msgid "cardex"
#: model:ir.model,name:hotel.model_checkin_partner
msgid "checkin"
msgstr "checkin"
#. module: hotel

View File

@@ -2,32 +2,29 @@
# Copyright 2018 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import currency_exchange
#~ from . import folio_room_line
from . import inherit_payment_return
from . import inherited_payment_return
from . import hotel_floor
from . import hotel_folio
from . import hotel_reservation
from . import hotel_room
from . import hotel_room_amenities
from . import hotel_room_amenities_type
from . import hotel_amenity
from . import hotel_amenity_type
from . import hotel_room_type
# from . import hotel_service_line
from . import hotel_service
# from . import hotel_service_type
from . import inherit_account_invoice
# from . import inherit_product_category
from . import inherit_product_product
from . import inherit_res_company
# from . import room_type
from . import inherit_account_payment
from . import inherited_account_invoice
from . import inherited_product_template
from . import inherited_res_company
from . import inherited_account_payment
from . import hotel_room_type_restriction
from . import hotel_room_type_restriction_item
from . import hotel_reservation_line
from . import cardex
from . import hotel_checkin_partner
from . import hotel_room_type_availability
from . import inherit_product_pricelist
from . import inherited_product_pricelist
from . import res_config
from . import inherit_res_partner
from . import inherited_res_partner
from . import inherited_mail_compose_message
#~ from . import hotel_dashboard
from . import hotel_room_type_class
from . import hotel_room_closure_reason
from . import hotel_service_line
from . import hotel_board_service

View File

@@ -1,68 +0,0 @@
# 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
class Cardex(models.Model):
_name = 'cardex'
# Validation for Departure date is after arrival date.
@api.constrains('exit_date')
def validation_dates(self):
if self.exit_date < self.enter_date:
raise models.ValidationError(
_('Departure date (%s) is prior to arrival on %s') %
(self.exit_date, self.enter_date))
def default_reservation_id(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].search([
('id', '=', self.env.context['reservation_id'])
])
return reservation
return False
def default_enter_date(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].search([
('id', '=', self.env.context['reservation_id'])
])
return reservation.checkin
return False
def default_exit_date(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].search([
('id', '=', self.env.context['reservation_id'])
])
return reservation.checkout
return False
def default_partner_id(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].search([
('id', '=', self.env.context['reservation_id'])
])
return reservation.partner_id
return False
@api.onchange('enter_date', 'exit_date')
def check_change_dates(self):
if self.exit_date <= self.enter_date:
date_1 = fields.Date.from_string(self.enter_date)
date_2 = date_1 + datetime.timedelta(days=1)
self.update({'exit_date': date_2, })
raise ValidationError(
_('Departure date, is prior to arrival. Check it now. %s') %
(date_2))
partner_id = fields.Many2one('res.partner', default=default_partner_id,
required=True)
reservation_id = fields.Many2one(
'hotel.reservation',
default=default_reservation_id, readonly=True)
enter_date = fields.Date(default=default_enter_date, required=True)
exit_date = fields.Date(default=default_exit_date, required=True)

View File

@@ -1,151 +0,0 @@
# 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):
_name = "currency.exchange"
_description = "currency"
name = fields.Char('Reg Number', readonly=True, default='New')
today_date = fields.Datetime('Date Ordered',
required=True,
default=(lambda *a:
time.strftime
(DEFAULT_SERVER_DATETIME_FORMAT)))
input_curr = fields.Many2one('res.currency', string='Input Currency',
track_visibility='always')
in_amount = fields.Float('Amount Taken', size=64, default=1.0)
out_curr = fields.Many2one('res.currency', string='Output Currency',
track_visibility='always')
out_amount = fields.Float('Subtotal', size=64)
folio_no = fields.Many2one('hotel.folio', 'Folio Number')
guest_name = fields.Many2one('res.partner', string='Guest Name')
room_number = fields.Char(string='Room Number')
state = fields.Selection([('draft', 'Draft'), ('done', 'Done'),
('cancel', 'Cancel')], 'State', default='draft')
rate = fields.Float('Rate(per unit)', size=64)
hotel_id = fields.Many2one('stock.warehouse', 'Hotel Name')
type = fields.Selection([('cash', 'Cash')], 'Type', default='cash')
tax = fields.Selection([('2', '2%'), ('5', '5%'), ('10', '10%')],
'Service Tax', default='2')
total = fields.Float('Amount Given')
@api.model
def create(self, vals):
"""
Overrides orm create method.
@param self: The object pointer
@param vals: dictionary of fields value.
"""
if not vals:
vals = {}
if self._context is None:
self._context = {}
seq_obj = self.env['ir.sequence']
vals['name'] = seq_obj.next_by_code('currency.exchange') or 'New'
return super(CurrencyExchangeRate, self).create(vals)
@api.onchange('folio_no')
def get_folio_no(self):
'''
When you change folio_no, based on that it will update
the guest_name,hotel_id and room_number as well
---------------------------------------------------------
@param self: object pointer
'''
for rec in self:
self.guest_name = False
self.hotel_id = False
self.room_number = False
if rec.folio_no and len(rec.folio_no.room_lines) != 0:
self.guest_name = rec.folio_no.partner_id.id
self.hotel_id = rec.folio_no.warehouse_id.id
self.room_number = rec.folio_no.room_lines[0].product_id.name
@api.multi
def act_cur_done(self):
"""
This method is used to change the state
to done of the currency exchange
---------------------------------------
@param self: object pointer
"""
self.write({'state': 'done'})
return True
@api.multi
def act_cur_cancel(self):
"""
This method is used to change the state
to cancel of the currency exchange
---------------------------------------
@param self: object pointer
"""
self.write({'state': 'cancel'})
return True
@api.multi
def act_cur_cancel_draft(self):
"""
This method is used to change the state
to draft of the currency exchange
---------------------------------------
@param self: object pointer
"""
self.write({'state': 'draft'})
return True
@api.model
def get_rate(self, a, b):
'''
Calculate rate between two currency
-----------------------------------
@param self: object pointer
'''
try:
url = 'http://finance.yahoo.com/d/quotes.csv?s=%s%s=X&f=l1' % (a,
b)
rate = urllib2.urlopen(url).read().rstrip()
return Decimal(rate)
except:
return Decimal('-1.00')
@api.onchange('input_curr', 'out_curr', 'in_amount')
def get_currency(self):
'''
When you change input_curr, out_curr or in_amount
it will update the out_amount of the currency exchange
------------------------------------------------------
@param self: object pointer
'''
self.out_amount = 0.0
if self.input_curr:
for rec in self:
result = rec.get_rate(self.input_curr.name,
self.out_curr.name)
if self.out_curr:
self.rate = result
if self.rate == Decimal('-1.00'):
raise except_orm(_('Warning'),
_('Please Check Your \
Network Connectivity.'))
self.out_amount = (float(result) * float(self.in_amount))
@api.onchange('out_amount', 'tax')
def tax_change(self):
'''
When you change out_amount or tax
it will update the total of the currency exchange
-------------------------------------------------
@param self: object pointer
'''
if self.out_amount:
ser_tax = ((self.out_amount) * (float(self.tax))) / 100
self.total = self.out_amount - ser_tax

View File

@@ -0,0 +1,14 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
class HotelRoomAmenitie(models.Model):
_name = 'hotel.amenity'
_description = 'Room amenities'
name = fields.Char('Amenity Name', required=True)
active = fields.Boolean('Active', default=True)
default_code = fields.Char('Internal Reference')
room_amenity_type_id = fields.Many2one('hotel.amenity.type',
'Amenity Catagory')

View File

@@ -0,0 +1,15 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
class HotelRoomAmenitieType(models.Model):
_name = 'hotel.amenity.type'
_description = 'Amenities Type'
name = fields.Char('Amenity Name', required=True)
active = fields.Boolean('Active', default=True)
room_amenity_ids = fields.One2many('hotel.amenity',
'room_amenity_type_id',
'Amenities in this category')

View File

@@ -0,0 +1,15 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
class HotelBoardService(models.Model):
_name = "hotel.board.service"
_description = "Board Services"
name = fields.Char('Board Name', size=64, required=True, index=True)
service_ids = fields.Many2many(comodel_name='product.template',
relation='hotel_board_services_room',
column1='board_id',
column2='service_id')
sequence = fields.Integer('Sequence')

View File

@@ -0,0 +1,74 @@
# Copyright 2017 Dario Lodeiros
# Copyright 2018 Alexandre Diaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import datetime
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class HotelCheckinPartner(models.Model):
_name = 'hotel.checkin.partner'
def _default_reservation_id(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].browse([
self.env.context['reservation_id']
])
return reservation
return False
def _default_enter_date(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].browse([
self.env.context['reservation_id']
])
return reservation.checkin
return False
def _default_exit_date(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].browse([
self.env.context['reservation_id']
])
return reservation.checkout
return False
def _default_partner_id(self):
if 'reservation_id' in self.env.context:
reservation = self.env['hotel.reservation'].browse([
self.env.context['reservation_id']
])
return reservation.partner_id
return False
partner_id = fields.Many2one('res.partner', default=_default_partner_id,
required=True)
reservation_id = fields.Many2one(
'hotel.reservation',
default=_default_reservation_id, readonly=True)
enter_date = fields.Date(default=_default_enter_date, required=True)
exit_date = fields.Date(default=_default_exit_date, required=True)
# Validation for Departure date is after arrival date.
@api.multi
@api.constrains('exit_date','enter_date')
def _check_exit_date(self):
for record in self:
date_in = fields.Date.from_string(record.enter_date)
date_out = fields.Date.from_string(record.exit_date)
if date_out < date_in:
raise models.ValidationError(
_('Departure date (%s) is prior to arrival on %s') %
(date_out, date_in))
@api.onchange('enter_date', 'exit_date')
def _onchange_enter_date(self):
date_in = fields.Date.from_string(self.enter_date)
date_out = fields.Date.from_string(self.exit_date)
if date_out <= date_in:
date_out = date_in + datetime.timedelta(days=1)
self.update({'exit_date': date_out})
raise ValidationError(
_('Departure date, is prior to arrival. Check it now. %s') %
date_out)

View File

@@ -1,260 +0,0 @@
# Copyright 2018 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import json
from datetime import datetime, timedelta
from babel.dates import format_datetime, format_date
from odoo import models, api, _, fields
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
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_count(
[('sate', '=', 'confirm')])
folios_count = self.env['hotel.folio'].search_count(
[('sate', '=', 'sales_order')])
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':
self.kanban_dashboard_graph = json.dumps(self.get_bar_graph_datas())
elif self.graph_type == 'line':
self.kanban_dashboard_graph = json.dumps(self.get_line_graph_datas())
@api.one
def _kanban_dashboard_graph(self):
self.kanban_dashboard_graph = json.dumps(self.get_bar_graph_datas())
#~ if (self.type in ['sale', 'purchase']):
#~ self.kanban_dashboard_graph = json.dumps(self.get_bar_graph_datas())
#~ elif (self.type in ['cash', 'bank']):
#~ self.kanban_dashboard_graph = json.dumps(self.get_line_graph_datas())
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')
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)
@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:
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'})
# 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)+"')"
for i in range(1,15):
next_date = today + timedelta(days=i)
query += " UNION ALL ("+select_sql_clause+" and date(checkin) = '"+next_date.strftime(DF)+"')"
self.env.cr.execute(query)
query_results = self.env.cr.dictfetchall()
for index_k, index_v in enumerate(query_results):
data[index_k]['value'] = index_v.get('total')
return [{'values': data}]
@api.multi
def get_journal_dashboard_datas(self):
#~ currency = self.currency_id or self.company_id.currency_id
#~ number_to_reconcile = last_balance = account_sum = 0
#~ ac_bnk_stmt = []
#~ title = ''
#~ number_draft = number_waiting = number_late = 0
#~ sum_draft = sum_waiting = sum_late = 0.0
#~ if self.type in ['bank', 'cash']:
#~ last_bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids)], order="date desc, id desc", limit=1)
#~ last_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0
#~ #Get the number of items to reconcile for that bank journal
#~ self.env.cr.execute("""SELECT COUNT(DISTINCT(statement_line_id))
#~ FROM account_move where statement_line_id
#~ IN (SELECT line.id
#~ FROM account_bank_statement_line AS line
#~ LEFT JOIN account_bank_statement AS st
#~ ON line.statement_id = st.id
#~ WHERE st.journal_id IN %s and st.state = 'open')""", (tuple(self.ids),))
#~ already_reconciled = self.env.cr.fetchone()[0]
#~ self.env.cr.execute("""SELECT COUNT(line.id)
#~ FROM account_bank_statement_line AS line
#~ LEFT JOIN account_bank_statement AS st
#~ ON line.statement_id = st.id
#~ WHERE st.journal_id IN %s and st.state = 'open'""", (tuple(self.ids),))
#~ all_lines = self.env.cr.fetchone()[0]
#~ number_to_reconcile = all_lines - already_reconciled
#~ # optimization to read sum of balance from account_move_line
#~ account_ids = tuple(filter(None, [self.default_debit_account_id.id, self.default_credit_account_id.id]))
#~ if account_ids:
#~ amount_field = 'balance' if (not self.currency_id or self.currency_id == self.company_id.currency_id) else 'amount_currency'
#~ query = """SELECT sum(%s) FROM account_move_line WHERE account_id in %%s AND date <= %%s;""" % (amount_field,)
#~ self.env.cr.execute(query, (account_ids, fields.Date.today(),))
#~ query_results = self.env.cr.dictfetchall()
#~ if query_results and query_results[0].get('sum') != None:
#~ account_sum = query_results[0].get('sum')
#~ #TODO need to check if all invoices are in the same currency than the journal!!!!
#~ elif self.type in ['sale', 'purchase']:
#~ title = _('Bills to pay') if self.type == 'purchase' else _('Invoices owed to you')
#~ # optimization to find total and sum of invoice that are in draft, open state
#~ query = """SELECT state, amount_total, currency_id AS currency, type FROM account_invoice WHERE journal_id = %s AND state NOT IN ('paid', 'cancel');"""
#~ self.env.cr.execute(query, (self.id,))
#~ query_results = self.env.cr.dictfetchall()
#~ today = datetime.today()
#~ query = """SELECT amount_total, currency_id AS currency, type FROM account_invoice WHERE journal_id = %s AND date < %s AND state = 'open';"""
#~ self.env.cr.execute(query, (self.id, today))
#~ late_query_results = self.env.cr.dictfetchall()
#~ for result in query_results:
#~ if result['type'] in ['in_refund', 'out_refund']:
#~ factor = -1
#~ else:
#~ factor = 1
#~ cur = self.env['res.currency'].browse(result.get('currency'))
#~ if result.get('state') in ['draft', 'proforma', 'proforma2']:
#~ number_draft += 1
#~ sum_draft += cur.compute(result.get('amount_total'), currency) * factor
#~ elif result.get('state') == 'open':
#~ number_waiting += 1
#~ sum_waiting += cur.compute(result.get('amount_total'), currency) * factor
#~ for result in late_query_results:
#~ if result['type'] in ['in_refund', 'out_refund']:
#~ factor = -1
#~ else:
#~ factor = 1
#~ cur = self.env['res.currency'].browse(result.get('currency'))
#~ number_late += 1
#~ sum_late += cur.compute(result.get('amount_total'), currency) * factor
#~ difference = currency.round(last_balance-account_sum) + 0.0
return {
'graph': self.graph_type,
'number_to_reconcile': 11,
'account_balance': 4314,
'last_balance': 252,
'difference': 432,
'number_draft': 32,
'number_waiting': 44,
'number_late': 23,
'sum_draft': 2424245,
'sum_waiting': 3124312,
'sum_late': 23123,
'currency_id': 1,
'bank_statements_source': 'fonte',
'title': 'titulo',
}
@api.multi
def get_line_graph_datas(self):
data = []
today = datetime.strptime(fields.Date.context_today(self), DF)
days=30
for i in range(-1, days + 1):
ndate = today + timedelta(days=i)
ndate_str = ndate.strftime(DF)
day_onboard = self.env['hotel.reservation.line'].search_count([('date','=',ndate)])
locale = self._context.get('lang') or 'en_US'
short_name = format_date(ndate, 'd', locale=locale)
name = format_date(ndate, 'd LLLL Y', locale=locale)
data.append({'x':short_name,'y':day_onboard, 'name':name})
return [{'values': data, 'area': True}]
@api.multi
def action_create_new(self):
#~ ctx = self._context.copy()
#~ model = 'account.invoice'
#~ if self.type == 'sale':
#~ ctx.update({'journal_type': self.type, 'default_type': 'out_invoice', 'type': 'out_invoice', 'default_journal_id': self.id})
#~ if ctx.get('refund'):
#~ ctx.update({'default_type':'out_refund', 'type':'out_refund'})
#~ view_id = self.env.ref('account.invoice_form').id
#~ elif self.type == 'purchase':
#~ ctx.update({'journal_type': self.type, 'default_type': 'in_invoice', 'type': 'in_invoice', 'default_journal_id': self.id})
#~ if ctx.get('refund'):
#~ ctx.update({'default_type': 'in_refund', 'type': 'in_refund'})
#~ view_id = self.env.ref('account.invoice_supplier_form').id
#~ else:
#~ ctx.update({'default_journal_id': self.id})
#~ view_id = self.env.ref('account.view_move_form').id
#~ model = 'account.move'
model = "hotel.folio"
view_id = self.env.ref('hotel.view_hotel_folio1_form').id
ctx=''
return {
'name': _('Create invoice/bill'),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': model,
'view_id': view_id,
'context': ctx,
}
@api.multi
def open_action(self):
"""return action based on type for related journals"""
#~ action_name = self._context.get('action_name', False)
#~ if not action_name:
#~ if self.type == 'bank':
#~ action_name = 'action_bank_statement_tree'
#~ elif self.type == 'cash':
#~ action_name = 'action_view_bank_statement_tree'
#~ elif self.type == 'sale':
#~ action_name = 'action_invoice_tree1'
#~ elif self.type == 'purchase':
#~ action_name = 'action_invoice_tree2'
#~ else:
#~ action_name = 'action_move_journal_line'
#~ _journal_invoice_type_map = {
#~ ('sale', None): 'out_invoice',
#~ ('purchase', None): 'in_invoice',
#~ ('sale', 'refund'): 'out_refund',
#~ ('purchase', 'refund'): 'in_refund',
#~ ('bank', None): 'bank',
#~ ('cash', None): 'cash',
#~ ('general', None): 'general',
#~ }
#~ invoice_type = _journal_invoice_type_map[(self.type, self._context.get('invoice_type'))]
#~ ctx = self._context.copy()
#~ ctx.pop('group_by', None)
#~ ctx.update({
#~ 'journal_type': self.type,
#~ 'default_journal_id': self.id,
#~ 'search_default_journal_id': self.id,
#~ 'default_type': invoice_type,
#~ 'type': invoice_type
#~ })
#~ [action] = self.env.ref('account.%s' % action_name).read()
#~ action['context'] = ctx
#~ action['domain'] = self._context.get('use_domain', [])
#~ if action_name in ['action_bank_statement_tree', 'action_view_bank_statement_tree']:
#~ action['views'] = False
#~ action['view_id'] = False
return False

View File

@@ -1,6 +1,6 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
from odoo import models, fields
class HotelFloor(models.Model):
@@ -8,4 +8,4 @@ class HotelFloor(models.Model):
_description = "Ubication"
name = fields.Char('Ubication Name', size=64, required=True, index=True)
sequence = fields.Integer('Sequence', size=64)
sequence = fields.Integer('Sequence')

View File

@@ -48,6 +48,7 @@ class HotelFolio(models.Model):
default=lambda self: _('New'))
partner_id = fields.Many2one('res.partner',
track_visibility='onchange')
closure_reason_id = fields.Many2one('room.closure.reason')
# partner_invoice_id = fields.Many2one('res.partner',
# string='Invoice Address',
# readonly=True, required=True,
@@ -104,13 +105,11 @@ class HotelFolio(models.Model):
string="Payments")
booking_pending = fields.Integer('Booking pending',
compute='_compute_cardex_count')
cardex_count = fields.Integer('Cardex counter',
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')
compute='_compute_checkin_partner_count')
checkin_partner_count = fields.Integer('Checkin counter',
compute='_compute_checkin_partner_count')
checkin_partner_pending_count = fields.Integer('Checkin Pending',
compute='_compute_checkin_partner_count')
partner_internal_comment = fields.Text(string='Internal Partner Notes',
related='partner_id.comment')
internal_comment = fields.Text(string='Internal Folio Notes')
@@ -189,7 +188,7 @@ class HotelFolio(models.Model):
self.ensure_one()
partner = self.partner_id.id
amount = self.pending_amount
view_id = self.env.ref('hotel.view_account_payment_folio_form').id
view_id = self.env.ref('hotel.account_payment_view_form_folio').id
return{
'name': _('Register Payment'),
'view_type': 'form',
@@ -351,19 +350,13 @@ class HotelFolio(models.Model):
#~ 'fiscal_position_id': False,
#~ })
return
addr = self.partner_id.address_get(['invoice'])
#TEMP:
values = { 'user_id': self.partner_id.user_id.id or self.env.uid,
'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')}
#~ values = {
#~ '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
#~ }
pricelist = self.partner_id.property_product_pricelist and \
self.partner_id.property_product_pricelist.id or \
self.env['ir.default'].sudo().get('res.config.settings', 'default_pricelist_id')
values = {'user_id': self.partner_id.user_id.id or self.env.uid,
'pricelist_id': pricelist
}
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(
@@ -373,6 +366,24 @@ class HotelFolio(models.Model):
values['team_id'] = self.partner_id.team_id.id
self.update(values)
@api.multi
@api.onchange('pricelist_id')
def onchange_pricelist_id(self):
values = {'reservation_type': self.env['hotel.folio'].calcule_reservation_type(
self.pricelist_id.is_staff,
self.reservation_type)}
self.update(values)
@api.model
def calcule_reservation_type(self, is_staff, current_type):
if current_type == 'out':
return 'out'
elif is_staff:
return 'staff'
else:
return 'normal'
@api.multi
def action_invoice_create(self, grouped=False, states=None):
'''
@@ -454,54 +465,29 @@ class HotelFolio(models.Model):
self.ensure_one()
rooms = self.mapped('room_lines.id')
return {
'name': _('Cardexs'),
'name': _('Checkins'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'cardex',
'res_model': 'hotel.checkin.partner',
'type': 'ir.actions.act_window',
'domain': [('reservation_id', 'in', rooms)],
'target': 'new',
}
@api.model
def daily_plan(self):
_logger.info('daily_plan')
self._cr.execute("update hotel_folio set checkins_reservations = 0, \
checkouts_reservations = 0 where checkins_reservations > 0 \
or checkouts_reservations > 0")
folios_in = self.env['hotel.folio'].search([
('room_lines.is_checkin', '=', True)
])
folios_out = self.env['hotel.folio'].search([
('room_lines.is_checkout', '=', True)
])
for fol in folios_in:
count_checkin = fol.room_lines.search_count([
('is_checkin', '=', True), ('folio_id.id', '=', fol.id)
])
fol.write({'checkins_reservations': count_checkin})
for fol in folios_out:
count_checkout = fol.room_lines.search_count([
('is_checkout', '=', True),
('folio_id.id', '=', fol.id)
])
fol.write({'checkouts_reservations': count_checkout})
return True
@api.multi
def _compute_cardex_count(self):
_logger.info('_compute_cardex_amount')
def _compute_checkin_partner_count(self):
_logger.info('_compute_checkin_partner_amount')
for record in self:
if record.reservation_type == 'normal' and record.room_lines:
write_vals = {}
filtered_reservs = record.room_lines.filtered(
lambda x: x.state != 'cancelled' and \
not x.parent_reservation)
mapped_cardex = filtered_reservs.mapped('cardex_ids.id')
record.cardex_count = len(mapped_cardex)
mapped_cardex_count = filtered_reservs.mapped(
lambda x: (x.adults + x.children) - len(x.cardex_ids))
record.cardex_pending_count = sum(mapped_cardex_count)
mapped_checkin_partner = filtered_reservs.mapped('checkin_partner_ids.id')
record.checkin_partner_count = len(mapped_checkin_partner)
mapped_checkin_partner_count = filtered_reservs.mapped(
lambda x: (x.adults + x.children) - len(x.checkin_partner_ids))
record.checkin_partner_pending_count = sum(mapped_checkin_partner_count)
"""
MAILING PROCESS

View File

@@ -11,7 +11,6 @@ from odoo.tools import (
DEFAULT_SERVER_DATETIME_FORMAT)
from odoo import models, fields, api, _
from odoo.addons import decimal_precision as dp
from odoo.addons.hotel import date_utils
_logger = logging.getLogger(__name__)
@@ -159,6 +158,7 @@ class HotelReservation(models.Model):
required=True, track_visibility='onchange')
partner_id = fields.Many2one(related='folio_id.partner_id')
closure_reason_id = fields.Many2one(related='folio_id.closure_reason_id')
company_id = fields.Many2one('res.company', 'Company')
reservation_line_ids = fields.One2many('hotel.reservation.line',
'reservation_id',
@@ -178,23 +178,22 @@ class HotelReservation(models.Model):
pricelist_id = fields.Many2one('product.pricelist',
related='folio_id.pricelist_id',
readonly="1")
cardex_ids = fields.One2many('cardex', 'reservation_id')
# TODO: As cardex_count is a computed field, it can't not be used in a domain filer
# Non-stored field hotel.reservation.cardex_count cannot be searched
checkin_partner_ids = fields.One2many('hotel.checkin.partner', 'reservation_id')
# TODO: As checkin_partner_count is a computed field, it can't not be used in a domain filer
# Non-stored field hotel.reservation.checkin_partner_count cannot be searched
# searching on a computed field can also be enabled by setting the search parameter.
# The value is a method name returning a Domains
cardex_count = fields.Integer('Cardex counter',
compute='_compute_cardex_count')
cardex_pending_count = fields.Integer('Cardex Pending Num',
compute='_compute_cardex_count',
search='_search_cardex_pending')
checkin_partner_count = fields.Integer('Checkin counter',
compute='_compute_checkin_partner_count')
checkin_partner_pending_count = fields.Integer('Checkin Pending Num',
compute='_compute_checkin_partner_count',
search='_search_checkin_partner_pending')
# check_rooms = fields.Boolean('Check Rooms')
is_checkin = fields.Boolean()
is_checkout = fields.Boolean()
splitted = fields.Boolean('Splitted', default=False)
parent_reservation = fields.Many2one('hotel.reservation',
'Parent Reservation')
overbooking = fields.Boolean('Is Overbooking', default=False)
reselling = fields.Boolean('Is Reselling', default=False)
nights = fields.Integer('Nights', compute='_computed_nights', store=True)
channel_type = fields.Selection([
@@ -350,11 +349,12 @@ class HotelReservation(models.Model):
@api.model
def _autoassign(self, values):
res = {}
checkin = values.get('checkin')
checkin = values.get('checkin')
checkout = values.get('checkout')
room_type = values.get('room_type_id')
if checkin and checkout and room_type:
room_chosen = self.env['hotel.room.type'].check_availability_room(checkin, checkout, room_type)[0]
# Check room_chosen exist
res.update({
'room_id': room_chosen.id
})
@@ -407,6 +407,7 @@ class HotelReservation(models.Model):
'parent_reservation': self.parent_reservation.id,
'state': self.state,
'overbooking': self.overbooking,
'reselling': self.reselling,
'price_unit': self.price_unit,
'splitted': self.splitted,
# 'room_type_id': self.room_type_id.id,
@@ -442,14 +443,27 @@ class HotelReservation(models.Model):
@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 \
pricelist = 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.env['ir.default'].sudo().get('res.config.settings', 'default_pricelist_id')
values = {
'pricelist_id': pricelist,
}
self.update(values)
@api.multi
@api.onchange('pricelist_id')
def onchange_pricelist_id(self):
values = {'reservation_type': self.env['hotel.folio'].calcule_reservation_type(
self.pricelist_id.is_staff,
self.reservation_type)}
self.update(values)
@api.onchange('reservation_type')
def assign_partner_company_on_out_service(self):
if self.reservation_type == 'out':
self.update({'partner_id': self.env.user.company_id.partner_id.id})
# When we need to overwrite the prices even if they were already established
@api.onchange('room_type_id', 'pricelist_id', 'reservation_type')
def onchange_overwrite_price_by_day(self):
@@ -498,7 +512,7 @@ class HotelReservation(models.Model):
def onchange_room_availabiltiy_domain(self):
self.ensure_one()
if self.checkin and self.checkout:
if self.overbooking:
if self.overbooking or self.reselling:
return
occupied = self.env['hotel.reservation'].get_reservations(
self.checkin,
@@ -524,11 +538,6 @@ class HotelReservation(models.Model):
def _generate_color(self):
self.ensure_one()
now_utc_dt = fields.Datetime.now()
# unused variables
# diff_checkin_now = date_utils.date_diff(now_utc_dt, self.checkin,
# hours=False)
# diff_checkout_now = date_utils.date_diff(now_utc_dt, self.checkout,
# hours=False)
ir_values_obj = self.env['ir.default']
reserv_color = '#FFFFFF'
@@ -628,15 +637,10 @@ class HotelReservation(models.Model):
hotel_reserv_obj = self.env['hotel.reservation']
for record in self:
vals = {}
if record.cardex_ids:
if record.checkin_partner_ids:
vals.update({'state': 'booking'})
else:
vals.update({'state': 'confirm'})
if record.checkin_is_today():
vals.update({'is_checkin': True})
folio = hotel_folio_obj.browse(record.folio_id.id)
folio.checkins_reservations = folio.room_lines.search_count([
('folio_id', '=', folio.id), ('is_checkin', '=', True)])
record.write(vals)
if record.splitted:
@@ -669,14 +673,6 @@ class HotelReservation(models.Model):
'state': 'cancelled',
'discount': 100.0,
})
if record.checkin_is_today:
record.is_checkin = False
folio = self.env['hotel.folio'].browse(record.folio_id.id)
folio.checkins_reservations = folio.room_lines.search_count([
('folio_id', '=', folio.id),
('is_checkin', '=', True)
])
if record.splitted:
master_reservation = record.parent_reservation or record
splitted_reservs = self.env['hotel.reservation'].search([
@@ -748,7 +744,7 @@ class HotelReservation(models.Model):
if not vals:
vals = {}
pricelist_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_pricelist_id')
'res.config.settings', 'default_pricelist_id')
#~ pricelist_id = vals.get('pricelist_id') or self.pricelist_id.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
@@ -793,7 +789,7 @@ class HotelReservation(models.Model):
partner = self.partner_id.id
amount = min(self.amount_reservation, self.folio_pending_amount)
note = self.folio_id.name + ' (' + self.name + ')'
view_id = self.env.ref('hotel.view_account_payment_folio_form').id
view_id = self.env.ref('hotel.account_payment_view_form_folio').id
return{
'name': _('Register Payment'),
'view_type': 'form',
@@ -833,7 +829,8 @@ class HotelReservation(models.Model):
domain = [('reservation_line_ids.date', '>=', dfrom),
('reservation_line_ids.date', '<', dto),
('state', '!=', 'cancelled'),
('overbooking', '=', False)]
('overbooking', '=', False),
('reselling', '=', False),]
return domain
@api.model
@@ -863,7 +860,7 @@ class HotelReservation(models.Model):
return reservations_dates
# TODO: Use default values on checkin /checkout is empty
@api.constrains('checkin', 'checkout', 'state', 'room_id', 'overbooking')
@api.constrains('checkin', 'checkout', 'state', 'room_id', 'overbooking', 'reselling')
def check_dates(self):
"""
1.-When date_order is less then checkin date or
@@ -893,89 +890,33 @@ class HotelReservation(models.Model):
"""
@api.multi
def _compute_cardex_count(self):
_logger.info('_compute_cardex_count')
def _compute_checkin_partner_count(self):
_logger.info('_compute_checkin_partner_count')
for record in self:
record.cardex_count = len(record.cardex_ids)
record.cardex_pending_count = (record.adults + record.children) \
- len(record.cardex_ids)
record.checkin_partner_count = len(record.checkin_partner_ids)
record.checkin_partner_pending_count = (record.adults + record.children) \
- len(record.checkin_partner_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):
def _search_checkin_partner_pending(self, operator, value):
self.ensure_one()
recs = self.search([]).filtered(lambda x: x.cardex_pending_count > 0)
recs = self.search([]).filtered(lambda x: x.checkin_partner_pending_count > 0)
return [('id', 'in', [x.id for x in recs])] if recs else []
@api.multi
def action_reservation_checkout(self):
for record in self:
record.state = 'done'
if record.checkout_is_today():
record.is_checkout = False
folio = self.env['hotel.folio'].browse(self.folio_id.id)
folio.checkouts_reservations = folio.room_lines.search_count([
('folio_id', '=', folio.id),
('is_checkout', '=', True)
])
@api.model
def daily_plan(self):
_logger.info('daily_plan')
today_str = fields.Date.today()
yesterday_utc_dt = datetime.now() - timedelta(days=1)
yesterday_str = yesterday_utc_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)
reservations_to_checkout = self.env['hotel.reservation'].search([
('state', 'not in', ['done']),
('checkout', '<', today_str)
])
for res in reservations_to_checkout:
res.action_reservation_checkout()
reservations = self.env['hotel.reservation'].search([
('reservation_line_ids.date', 'in', [today_str, yesterday_str]),
('state', 'in', ['confirm', 'booking'])
])
self._cr.execute("update hotel_reservation set is_checkin = False, \
is_checkout = False where is_checkin = True or \
is_checkout = True")
checkins_res = reservations.filtered(lambda x: (
x.state in ('confirm','draft')
and date_utils.date_compare(x.checkin, today_str, hours=False)
and x.reservation_type == 'normal'))
checkins_res.write({'is_checkin': True})
checkouts_res = reservations.filtered(lambda x: (
x.state not in ('done','cancelled')
and date_utils.date_compare(x.checkout, today_str,
hours=False)
and x.reservation_type == 'normal'))
checkouts_res.write({'is_checkout': True})
self.env['hotel.folio'].daily_plan()
return True
@api.model
def checkin_is_today(self):
self.ensure_one()
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
@api.model
def checkout_is_today(self):
self.ensure_one()
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.checkout == today
@api.multi
def action_checks(self):
self.ensure_one()
return {
'name': _('Cardexs'),
'name': _('Checkins'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'cardex',
'res_model': 'hotel.checkin.partner',
'type': 'ir.actions.act_window',
'domain': [('reservation_id', '=', self.id)],
'target': 'new',

View File

@@ -1,5 +1,6 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# Copyright 2018 Pablo Quesada
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
@@ -18,11 +19,6 @@ class HotelRoom(models.Model):
room_type_id = fields.Many2one('hotel.room.type', 'Hotel Room Type')
floor_id = fields.Many2one('hotel.floor', 'Ubication',
help='At which floor the room is located.')
# TODO Q. Should the amenities be on the Room Type ? -
room_amenities = fields.Many2many('hotel.room.amenities', 'temp_tab',
'room_amenities', 'rcateg_id',
string='Room Amenities',
help='List of room amenities.')
max_adult = fields.Integer('Max Adult')
max_child = fields.Integer('Max Child')
capacity = fields.Integer('Capacity')

View File

@@ -1,29 +0,0 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
class HotelRoomAmenities(models.Model):
_name = 'hotel.room.amenities'
_description = 'Room amenities'
# The record's name
name = fields.Char('Amenity Name', required=True)
# Used for activate records
active = fields.Boolean('Active', default=True)
default_code = fields.Char('Internal Reference', store=True)
# room_categ_id = fields.Many2one('product.product', 'Product Category',
# required=True, delegate=True,
# ondelete='cascade')
room_amenities_type_id = fields.Many2one('hotel.room.amenities.type',
'Amenity Catagory')
# room_ids = fields.Many2man('hotel.room','Rooms')
# @api.multi
# def unlink(self):
# # self.room_categ_id.unlink()
# return super(HotelRoomAmenities, self).unlink()

View File

@@ -1,26 +0,0 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
class HotelRoomAmenitiesType(models.Model):
_name = 'hotel.room.amenities.type'
_description = 'Amenities Type'
# The record's name
name = fields.Char('Amenity Name', required=True)
# Used for activate records
active = fields.Boolean('Active', default=True)
room_amenities_ids = fields.One2many('hotel.room.amenities',
'room_amenities_type_id',
'Amenities in this category')
# cat_id = fields.Many2one('product.category', 'category', required=True,
# delegate=True, ondelete='cascade')
# @api.multi
# def unlink(self):
# # self.cat_id.unlink()
# return super(HotelRoomAmenitiesType, self).unlink()

View File

@@ -0,0 +1,10 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
class RoomClosureReason(models.Model):
_name = "room.closure.reason"
_description = "Cause of out of service"
name = fields.Char('Name', required=True)
description = fields.Text('Description')

View File

@@ -5,7 +5,7 @@ from odoo import models, fields, api
class HotelRoomType(models.Model):
""" Before creating a 'room type', you need to consider the following:
With the term 'room type' is meant a type of residential accommodation: for
With the term 'room type' is meant a sales type of residential accommodation: for
example, a Double Room, a Economic Room, an Apartment, a Tent, a Caravan...
"""
_name = "hotel.room.type"
@@ -17,6 +17,12 @@ class HotelRoomType(models.Model):
required=True, delegate=True,
ondelete='cascade')
room_ids = fields.One2many('hotel.room', 'room_type_id', 'Rooms')
class_id = fields.Many2one('hotel.room.type.class', 'Hotel Type Class')
room_amenity_ids = fields.Many2many('hotel.amenity',
'hotel_room_type_aminity_rel',
'room_type_ids', 'amenity_ids',
string='Room Type Amenities',
help='List of Amenities.')
# TODO Hierarchical relationship for parent-child tree ?
# parent_id = fields.Many2one ...

View File

@@ -1,25 +1,17 @@
# 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 HotelRoomTypeAvailability(models.Model):
_inherit = 'mail.thread'
_name = 'hotel.room.type.availability'
_inherit = 'mail.thread'
# room_type_id = fields.Many2one('hotel.virtual.room', 'Virtual Room',
# required=True, track_visibility='always',
# ondelete='cascade')
room_type_id = fields.Many2one('hotel.room.type', 'Room Type',
required=True, track_visibility='always',
ondelete='cascade')
avail = fields.Integer('Avail', default=0, track_visibility='always')
no_ota = fields.Boolean('No OTA', default=False, track_visibility='always')
booked = fields.Boolean('Booked', default=False, readonly=True,
track_visibility='always')
date = fields.Date('Date', required=True, track_visibility='always')
_sql_constraints = [
@@ -30,25 +22,15 @@ class HotelRoomTypeAvailability(models.Model):
@api.constrains('avail')
def _check_avail(self):
if self.avail < 0:
self.avail = 0
room_type_obj = self.env['hotel.room.type']
cavail = len(room_type_obj.check_availability_room(
self.date,
self.date,
room_type_id=self.room_type_id.id))
max_avail = min(cavail,
self.room_type_id.total_rooms_count)
if self.avail > max_avail:
self.avail = max_avail
@api.constrains('date', 'room_type_id')
def _check_date_room_type_id(self):
count = self.search_count([
('date', '=', self.date),
('room_type_id', '=', self.room_type_id.id)
])
if count > 1:
raise ValidationError(_("can't assign the same date to more than \
one room type"))
for record in self:
if record.avail < 0:
record.avail = 0
else:
room_type_obj = self.env['hotel.room.type']
cavail = len(room_type_obj.check_availability_room(
record.date,
record.date,
room_type_id=record.room_type_id.id))
max_avail = min(cavail, record.room_type_id.total_rooms_count)
if record.avail > max_avail:
record.avail = max_avail

View File

@@ -0,0 +1,25 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
class HotelRoomTypeClass(models.Model):
""" Before creating a 'room type_class', you need to consider the following:
With the term 'room type class' is meant a physicial class of
residential accommodation: for example, a Room, a Bed, an Apartment,
a Tent, a Caravan...
"""
_name = "hotel.room.type.class"
_description = "Room Type Class"
_order = "sequence, name, code_class"
name = fields.Char('Class Name', required=True, translate=True)
room_type_ids = fields.One2many('hotel.room.type', 'class_id', 'Types')
active = fields.Boolean('Active', default=True,
help="The active field allows you to hide the \
category without removing it.")
sequence = fields.Integer('Sequence', default=0)
code_class = fields.Char('Code')
_sql_constraints = [('code_class_unique', 'unique(code_class)',
'code must be unique!')]

View File

@@ -19,13 +19,13 @@ class HotelRoomTypeRestriction(models.Model):
@api.depends('name')
def name_get(self):
restriction_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id')
'res.config.settings', 'default_restriction_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))
names.append((record.id, '%s (Default)' % record.name))
else:
names.append((record.id, record.name))
return names

View File

@@ -1,9 +1,7 @@
# 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
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
class HotelRoomTypeRestrictionItem(models.Model):
@@ -12,18 +10,9 @@ class HotelRoomTypeRestrictionItem(models.Model):
restriction_id = fields.Many2one('hotel.room.type.restriction',
'Restriction Plan', ondelete='cascade',
index=True)
# room_type_id = fields.Many2one('hotel.virtual.room', 'Virtual Room',
# required=True, ondelete='cascade')
room_type_id = fields.Many2one('hotel.room.type', 'Room Type',
required=True, ondelete='cascade')
date = fields.Date('Date')
applied_on = fields.Selection([
('1_global', 'Global'),
# ('0_room_type', 'Virtual Room')], string="Apply On", required=True,
# default='0_room_type',
('0_room_type', 'Room Type')], string="Apply On", required=True,
default='0_room_type',
help='Pricelist Item applicable on selected option')
min_stay = fields.Integer("Min. Stay")
min_stay_arrival = fields.Integer("Min. Stay Arrival")
@@ -37,22 +26,19 @@ class HotelRoomTypeRestrictionItem(models.Model):
'unique(restriction_id, room_type_id, date)',
'Only can exists one restriction in the same day for the same room type!')]
@api.multi
@api.constrains('min_stay', 'min_stay_arrival', 'max_stay',
'max_stay_arrival')
def _check_min_stay_min_stay_arrival_max_stay(self):
if self.min_stay < 0:
raise ValidationError(_("Min. Stay can't be less than zero"))
elif self.min_stay_arrival < 0:
raise ValidationError(
("Min. Stay Arrival can't be less than zero"))
elif self.max_stay < 0:
raise ValidationError(_("Max. Stay can't be less than zero"))
elif self.max_stay_arrival < 0:
raise ValidationError(
("Max. Stay Arrival can't be less than zero"))
def _check_min_stay(self):
for record in self:
if record.self.min_stay < 0:
raise ValidationError(_("Min. Stay can't be less than zero"))
elif record.min_stay_arrival < 0:
raise ValidationError(
("Min. Stay Arrival can't be less than zero"))
elif record.max_stay < 0:
raise ValidationError(_("Max. Stay can't be less than zero"))
elif record.max_stay_arrival < 0:
raise ValidationError(
("Max. Stay Arrival can't be less than zero"))
@api.constrains('applied_on')
def _check_applied_on(self):
count = self.search_count([('applied_on', '=', '1_global')])
if count > 1:
raise ValidationError(_("Already exists an global rule"))

View File

@@ -1,74 +1,123 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import time
import logging
from odoo import models, fields, api
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
_logger = logging.getLogger(__name__)
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from datetime import timedelta
class HotelService(models.Model):
_name = 'hotel.service'
_description = 'Hotel Services and its charges'
@api.model
def _service_checkin(self):
if 'checkin' in self._context:
return self._context['checkin']
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
@api.model
def _service_checkout(self):
if 'checkout' in self._context:
return self._context['checkout']
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
@api.model
def _default_ser_room_line(self):
if 'room_lines' in self.env.context and self.env.context['room_lines']:
if self.env.context.get('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'].browse([
(ids)], limit=1)
return False
name = fields.Char('Service description')
# services in the hotel are products
product_id = fields.Many2one('product.product', 'Service', required=True)
folio_id = fields.Many2one('hotel.folio', 'Folio', ondelete='cascade')
ser_room_line = fields.Many2one('hotel.reservation', 'Room',
default=_default_ser_room_line)
list_price = fields.Float(
related='product_id.list_price')
service_line_ids = fields.One2many('hotel.service.line', 'service_id')
product_qty = fields.Integer('Quantity')
pricelist_id = fields.Many2one(related='folio_id.pricelist_id')
channel_type = fields.Selection([
('door', 'Door'),
('mail', 'Mail'),
('phone', 'Phone'),
('call', 'Call Center'),
('web', 'Web')], 'Sales Channel')
currency_id = fields.Many2one('res.currency',
related='pricelist_id.currency_id',
string='Currency', readonly=True, required=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')
ser_checkin = fields.Datetime('From Date', required=True,
default=_service_checkin)
ser_checkout = fields.Datetime('To Date', required=True,
default=_service_checkout)
@api.onchange('product_id')
def onchange_product_calc_qty(self):
"""
Compute the default quantity according to the
configuration of the selected product
"""
for record in self:
product = record.product_id
reservation = record.ser_room_line
if product and reservation:
qty = 1
if product.per_day:
qty = qty * reservation.nights
if product.per_person:
qty = qty * (reservation.adults + reservation.children)
record.product_qty = qty
@api.onchange('product_qty')
def onchange_product_qty_days_selection(self):
"""
Try to calculate the days on which the product
should be served as long as the product is per day
"""
for record in self:
reservation = record.ser_room_line
if record.product_id.per_day:
days_diff = (
fields.Date.from_string(reservation.checkout) - fields.Date.from_string(reservation.checkin)
).days
record.update(record.prepare_service_lines(
reservation.checkin,
days_diff))
else:
record.update(record.prepare_service_lines(
reservation.checkin, 1))
##WIP##
@api.multi
def prepare_service_lines(self, dfrom, days, vals=False):
self.ensure_one()
old_qty = 0
cmds = [(5, 0, 0)]
old_lines_days = self.mapped('service_line_ids.date')
for day in self.service_line_ids:
old_qty = old_qty + day.day_qty
qty_day = (self.product_qty - old_qty) // (days - len(old_line_days))
rest_day = (self.product_qty - old_qty) % (days - len(old_line_days))
for i in range(0, days):
idate = (fields.Date.from_string(dfrom) + timedelta(days=i)).strftime(
DEFAULT_SERVER_DATE_FORMAT)
old_line = self.service_line_ids.filtered(lambda r: r.date == idate)
if idate not in old_lines_days:
cmds.append((0, False, {
'date': idate,
'day_qty': qty_day
}))
else:
cmds.append((4, old_line.id))
return {'service_line_ids': cmds}
# TODO Hierarchical relationship for parent-child tree
# parent_id = fields.Many2one ...
# service_id = fields.Many2one('product.product', 'Service_id',
# required=True, ondelete='cascade',
# delegate=True)
# service_type_id = fields.Many2one('hotel.service.type',
# 'Service Catagory')
# service_line_id = fields.Many2one('hotel.service.line',
# 'Service Line')
# @api.multi
# def unlink(self):
# # for record in self:
# # record.service_id.unlink()
# return super(HotelServices, self).unlink()
@api.depends('qty_product', 'tax_id')
def _compute_amount_service(self):
"""
Compute the amounts of the service line.
"""
for record in self:
product = record.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'],
})

View File

@@ -1,243 +1,32 @@
# 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 time
import logging
from odoo import models, fields, api, _
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
from odoo.addons import decimal_precision as dp
from odoo.exceptions import ValidationError
class HotelServiceLine(models.Model):
_name = 'hotel.service.line'
_description = 'hotel Service line'
_name = "hotel.service.line"
_order = "date"
@api.one
def copy(self, default=None):
'''
@param self: object pointer
@param default: dict of default values to be set
'''
line_id = self.service_line_id.id
sale_line_obj = self.env['sale.order.line'].browse(line_id)
return sale_line_obj.copy(default=default)
service_id = fields.Many2one('hotel.service', string='Service',
ondelete='cascade', required=True,
copy=False)
date = fields.Date('Date')
day_qty = fields.Integer('Units')
product_id = fields.Many2one(related='service_id.product_id')
@api.multi
def _amount_line(self, field_name, arg):
'''
@param self: object pointer
@param field_name: Names of fields.
@param arg: User defined arguments
'''
total_amount = 0
@api.constrains('day_qty')
def no_free_resources(self):
for record in self:
line = record.service_line_id
total_amount += line._amount_line(field_name, arg)
return total_amount
limit = record.product_id.daily_limit
if limit > 0:
out_qty = sum(self.env['hotel.service.line'].search([(
'product_id', '=', record.product_id,
'date', '=', record.date)]).mapped('day_qty'))
if limit < out_qty + record.day_qty:
raise ValidationError(
_("Limit exceeded for %s")% record.date)
@api.multi
def _number_packages(self, field_name, arg):
'''
@param self: object pointer
@param field_name: Names of fields.
@param arg: User defined arguments
'''
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):
if 'checkin' in self._context:
return self._context['checkin']
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
@api.model
def _service_checkout(self):
if 'checkout' in self._context:
return self._context['checkout']
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
@api.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 False
# The record's name
name = fields.Char('Service line', required=True)
# services in the hotel are products
product_id = fields.Many2one('product.product', 'Service')
list_price = fields.Float(
related='product_id.list_price')
# TODO refactor to services_ids
# services_line_id = fields.Many2one('hotel.services', 'Service Line',
# ondelete='cascade')
# FIXME You can add services to a folio ?
folio_id = fields.Many2one('hotel.folio', 'Folio', ondelete='cascade')
channel_type = fields.Selection([
('door', 'Door'),
('mail', 'Mail'),
('phone', 'Phone'),
('call', 'Call Center'),
('web', 'Web')], 'Sales Channel')
ser_checkin = fields.Date('From Date', required=True,
default=_service_checkin)
ser_checkout = fields.Date('To Date', required=True,
default=_service_checkout)
ser_room_line = fields.Many2one('hotel.reservation', 'Room',
default=_default_ser_room_line)
@api.model
def create(self, vals):
"""
Overrides orm create method.
@param self: The object pointer
@param vals: dictionary of fields value.
@return: new record set for hotel service line.
"""
if 'folio_id' in vals:
folio = self.env['hotel.folio'].browse(vals['folio_id'])
vals.update({'order_id': folio.order_id.id})
user = self.env['res.users'].browse(self.env.uid)
if user.has_group('hotel.group_hotel_call'):
vals.update({'channel_type': 'call'})
return super(HotelServiceLine, self).create(vals)
# ~ @api.multi
# ~ def unlink(self):
# ~ """
# ~ Overrides orm unlink method.
# ~ @param self: The object pointer
# ~ @return: True/False.
# ~ """
# ~ s_line_obj = self.env['sale.order.line']
# ~ for line in self:
# ~ if line.service_line_id:
# ~ sale_unlink_obj = s_line_obj.browse([line.service_line_id.id])
# ~ sale_unlink_obj.unlink()
# ~ return super(HotelServiceLine, self).unlink()
@api.onchange('product_id')
def product_id_change_hotel(self):
'''
@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:
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.update(write_vals)
#~ self.price_unit = tax_obj._fix_tax_included_price(prod.price,
#~ prod.taxes_id,
#~ self.tax_id)
# ~ _logger.info(self._context)
# ~ if 'folio_id' in self._context:
# ~ _logger.info(self._context)
# ~ domain_rooms = []
# ~ rooms_lines = self.env['hotel.reservation'].search([('folio_id','=',folio_id)])
# ~ room_ids = room_lines.mapped('id')
# ~ domain_rooms.append(('id','in',room_ids))
# ~ return {'domain': {'ser_room_line': domain_rooms}}
#
# ~ @api.onchange('folio_id')
# ~ def folio_id_change(self):
# ~ self.ensure_one()
# ~ _logger.info(self.mapped('folio_id.room_lines'))
# ~ rooms = self.mapped('folio_id.room_lines.id')
# ~ return {'domain': {'ser_room_line': rooms}}
#~ @api.onchange('product_uom')
#~ def product_uom_change(self):
#~ '''
#~ @param self: object pointer
#~ '''
# ~ if not self.product_uom:
# ~ self.price_unit = 0.0
# ~ return
# ~ self.price_unit = self.product_id.lst_price
# ~ if self.folio_id.partner_id:
# ~ prod = self.product_id.with_context(
# ~ lang=self.folio_id.partner_id.lang,
# ~ partner=self.folio_id.partner_id.id,
# ~ quantity=1,
# ~ date_order=self.folio_id.date_order,
# ~ pricelist=self.folio_id.pricelist_id.id,
# ~ uom=self.product_uom.id
# ~ )
# ~ tax_obj = self.env['account.tax']
# ~ self.price_unit = tax_obj._fix_tax_included_price(prod.price,
# ~ prod.taxes_id,
# ~ self.tax_id)
@api.onchange('ser_checkin', 'ser_checkout')
def on_change_checkout(self):
'''
When you change checkin or checkout it will checked it
and update the qty of hotel service line
-----------------------------------------------------------------
@param self: object pointer
'''
now_utc = fields.Date.today()
if not self.ser_checkin:
self.ser_checkin = now_utc
if not self.ser_checkout:
self.ser_checkout = now_utc
chkin_utc_dt = fields.Date.from_string(self.ser_checkin)
chkout_utc_dt = fields.Date.from_string(self.ser_checkout)
if chkout_utc_dt < chkin_utc_dt:
raise UserError(_('Checkout must be greater or equal checkin date'))
if self.ser_checkin and self.ser_checkout:
diffDate = abs((self.ser_checkout - self.ser_checkin).days) + 1
# FIXME: Finalize method!
@api.multi
def button_confirm(self):
'''
@param self: object pointer
'''
self.ensure_one()
self.service_line_id.button_confirm()
@api.multi
def button_done(self):
'''
@param self: object pointer
'''
self.ensure_one()
self.service_line_id.button_done()
@api.one
def copy_data(self, default=None):
'''
@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)
return sale_line_obj.copy_data(default=default)
@api.multi
def unlink(self):
for record in self:
record.service_line_id.unlink()
return super(HotelServiceLine, self).unlink()

View File

@@ -1,23 +0,0 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
class HotelServiceType(models.Model):
_name = "hotel.service.type"
_description = "Service Type"
name = fields.Char('Service Type', required=True)
# Used for activate records
active = fields.Boolean('Active?', default=True)
# ser_id = fields.Many2one('product.category', 'category', required=True,
# delegate=True, index=True, ondelete='cascade')
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()

View File

@@ -1,11 +0,0 @@
# 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')
isamenitytype = fields.Boolean('Is Amenities Type')
isservicetype = fields.Boolean('Is Service Type')

View File

@@ -1,12 +0,0 @@
# 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 ProductProduct(models.Model):
_inherit = "product.product"
is_room_type = fields.Boolean('Is a Room Type', default=False)
# iscategid = fields.Boolean('Is categ id')
# isservice = fields.Boolean('Is Service id')

View File

@@ -1,10 +1,8 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# 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
_logger = logging.getLogger(__name__)
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class AccountInvoice(models.Model):
@@ -12,12 +10,11 @@ class AccountInvoice(models.Model):
@api.model
def create(self, vals):
cr, uid, context = self.env.args
context = dict(context)
if context.get('invoice_origin', False):
vals.update({'origin': context['invoice_origin']})
if self.env.context.get('invoice_origin', False):
vals.update({'origin': self.env.context.get['invoice_origin']})
return super(AccountInvoice, self).create(vals)
"""WIP"""
@api.multi
def action_folio_payments(self):
self.ensure_one()
@@ -70,16 +67,3 @@ class AccountInvoice(models.Model):
raise ValidationError(vat_error)
return super(AccountInvoice, self).action_invoice_open()
# ~ @api.multi
# ~ def confirm_paid(self):
# ~ '''
# ~ This method change pos orders states to done when folio invoice
# ~ is in done.
# ~ ----------------------------------------------------------
# ~ @param self: object pointer
# ~ '''
# ~ pos_order_obj = self.env['pos.order']
# ~ res = super(AccountInvoice, self).confirm_paid()
# ~ pos_odr_rec = pos_order_obj.search([('invoice_id', 'in', self._ids)])
# ~ pos_odr_rec and pos_odr_rec.write({'state': 'done'})
# ~ return res

View File

@@ -1,10 +1,7 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from openerp.exceptions import except_orm
from openerp import models, fields, api, _
_logger = logging.getLogger(__name__)
from odoo.exceptions import except_orm
from odoo import models, fields, api, _
class AccountPayment(models.Model):
_inherit = 'account.payment'
@@ -15,6 +12,7 @@ class AccountPayment(models.Model):
string="Total amount in folio",
)
"""WIP"""
@api.multi
def return_payment_folio(self):
journal = self.journal_id
@@ -78,7 +76,7 @@ class AccountPayment(models.Model):
return
if not any(fol):
return
elif len(fol) > 1:
if len(fol) > 1:
raise except_orm(_('Warning'), _('This pay is related with \
more than one Reservation.'))
else:

View File

@@ -15,13 +15,7 @@ class MailComposeMessage(models.TransientModel):
self._context['default_res_id']
])
if folio:
cmds = []
for lid in folio.room_lines.ids:
cmds.append((
1,
lid,
{'to_send': False}
))
if cmds:
cmds = [(1, lid, {'to_send': False}) for lid in folio.room_lines.ids]
if any(cmds):
folio.room_lines = cmds
return super(MailComposeMessage, self).send_mail(auto_commit=auto_commit)

View File

@@ -1,23 +1,24 @@
# Copyright 2017 Alexandre Díaz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, api
from odoo import models, fields, api
class ProductPricelist(models.Model):
_inherit = 'product.pricelist'
is_staff = fields.Boolean('Is Staff')
@api.multi
@api.depends('name')
def name_get(self):
pricelist_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_pricelist_id')
'res.config.settings', 'default_pricelist_id')
if pricelist_id:
pricelist_id = int(pricelist_id)
org_names = super(ProductPricelist, self).name_get()
names = []
for name in org_names:
if name[0] == pricelist_id:
names.append((name[0], '%s (Parity)' % name[1]))
names.append((name[0], '%s (Default)' % name[1]))
else:
names.append((name[0], name[1]))
return names

View File

@@ -0,0 +1,12 @@
# 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
class ProductTemplate(models.Model):
_inherit = "product.template"
is_hotel_service = fields.Boolean('Is a Hotel Service', default=False)
per_day = fields.Boolean('Unit increment per day')
per_person = fields.Boolean('Unit increment per person')
daily_limit = fields.Integer('Daily limit')

View File

@@ -1,7 +1,7 @@
# 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, _
from odoo import models, fields
class ResCompany(models.Model):

View File

@@ -1,8 +1,7 @@
# 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, _
from openerp import models, fields
class ResPartner(models.Model):
_inherit = 'res.partner'
@@ -21,6 +20,5 @@ class ResPartner(models.Model):
('partner_id.id', '=', record.id)
])
reservations_count = fields.Integer('Reservations',
compute='_compute_reservations_count')
reservations_count = fields.Integer('Reservations', compute='_compute_reservations_count')
folios_count = fields.Integer('Folios', compute='_compute_folios_count')

View File

@@ -19,9 +19,9 @@ def _tz_get(self):
class HotelConfiguration(models.TransientModel):
_inherit = 'res.config.settings'
parity_pricelist_id = fields.Many2one('product.pricelist',
default_pricelist_id = fields.Many2one('product.pricelist',
'Product Pricelist')
parity_restrictions_id = fields.Many2one('hotel.room.type.restriction',
default_restriction_id = fields.Many2one('hotel.room.type.restriction',
'Restrictions')
default_arrival_hour = fields.Char('Default Arrival Hour (GMT)',
help="HH:mm Format", default="14:00")
@@ -39,11 +39,11 @@ class HotelConfiguration(models.TransientModel):
super(HotelConfiguration, self).set_values()
self.env['ir.default'].sudo().set(
'res.config.settings', 'parity_pricelist_id',
self.parity_pricelist_id.id)
'res.config.settings', 'default_pricelist_id',
self.default_pricelist_id.id)
self.env['ir.default'].sudo().set(
'res.config.settings', 'parity_restrictions_id',
self.parity_restrictions_id.id)
'res.config.settings', 'default_restriction_id',
self.default_restriction_id.id)
self.env['ir.default'].sudo().set(
'res.config.settings', 'tz_hotel', self.tz_hotel)
self.env['ir.default'].sudo().set(
@@ -58,10 +58,10 @@ class HotelConfiguration(models.TransientModel):
res = super(HotelConfiguration, self).get_values()
# ONLY FOR v11. DO NOT FORWARD-PORT
parity_pricelist_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_pricelist_id')
parity_restrictions_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'parity_restrictions_id')
default_pricelist_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'default_pricelist_id')
default_restriction_id = self.env['ir.default'].sudo().get(
'res.config.settings', 'default_restriction_id')
tz_hotel = self.env['ir.default'].sudo().get(
'res.config.settings', 'tz_hotel')
default_arrival_hour = self.env['ir.default'].sudo().get(
@@ -69,8 +69,8 @@ class HotelConfiguration(models.TransientModel):
default_departure_hour = self.env['ir.default'].sudo().get(
'res.config.settings', 'default_departure_hour')
res.update(
parity_pricelist_id=parity_pricelist_id,
parity_restrictions_id=parity_restrictions_id,
default_pricelist_id=default_pricelist_id,
default_restriction_id=default_restriction_id,
tz_hotel=tz_hotel,
default_arrival_hour=default_arrival_hour,
default_departure_hour=default_departure_hour,

View File

@@ -1,6 +0,0 @@
# -*- 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 . import hotel_report

View File

@@ -1,41 +0,0 @@
# -*- 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
from openerp import models
# Old SXW engine was removed already in v11. You should update your code with
# current engine tools.
# class FolioReport():
# def __init__(self, cr, uid, name, context):
# super(FolioReport, self).__init__(cr, uid, name, context)
# self.localcontext.update({'time': time,
# 'get_data': self.get_data,
# 'get_Total': self.getTotal,
# 'get_total': self.gettotal,
# })
# self.temp = 0.0
#
# def get_data(self, date_start, date_end):
# folio_obj = self.pool.get('hotel.folio')
# tids = folio_obj.search(self.cr, self.uid,
# [('checkin_date', '>=', date_start),
# ('checkout_date', '<=', date_end)])
# res = folio_obj.browse(self.cr, self.uid, tids)
# return res
#
# def gettotal(self, total):
# self.temp = self.temp + float(total)
# return total
#
# def getTotal(self):
# return self.temp
#
#
# class ReportLunchorder(models.AbstractModel):
# _name = 'report.hotel.report_hotel_folio'
# _inherit = 'report.report_xlsx.abstract'
# _template = 'hotel.report_hotel_folio'
# _wrapped_report_class = FolioReport

View File

@@ -1,13 +0,0 @@
<?xml version="1.0"?>
<odoo>
<!--Report for hotel folio -->
<report id="hotel_folio_details"
string="Folio Total"
model="hotel.folio"
name="folio.total"
rml="hotel/report/total_folio.rml"
menu="False"
auto="False"/>
</odoo>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0"?>
<odoo>
<report
id="action_report_viajero"
model="cardex"
string="Parte de Viajero"
report_type="qweb-pdf"
name="report.viajero"
file="report.viajero" />
<record id="action_report_viajero" model="ir.actions.report.xml">
<field name="paperformat_id" ref="report_viajero_paperformat"/>
<field name="report_type">qweb-pdf</field>
<field name="pdfjs_enabled">1</field>
<field name="pdfjs_auto_print">1</field>
<field name="pdfjs_print_dpi">201</field>
</record>
</odoo>

View File

@@ -1 +0,0 @@
,slimbook,slimbook-PRO,26.07.2018 11:51,file:///home/slimbook/.config/libreoffice/4;

View File

@@ -14,8 +14,8 @@ access_hotel_folio_line,hotel_folio.line.user,model_hotel_reservation,hotel.grou
access_hotel_folio_line_call,hotel_folio.line.call,model_hotel_reservation,hotel.group_hotel_call,1,1,1,1
access_hotel_invoice_call,account.invoice.call,account.model_account_invoice,hotel.group_hotel_call,1,1,1,1
access_hotel_invoice_user,account.invoice.user,account.model_account_invoice,hotel.group_hotel_user,1,1,1,1
access_hotel_model_cardex_call,hotel.currency_exchange.call,hotel.model_cardex,hotel.group_hotel_call,1,1,1,1
access_hotel_model_cardex_user,hotel.currency_exchange.user,hotel.model_cardex,hotel.group_hotel_user,1,1,1,1
access_hotel_model_checkin_partner_call,hotel.currency_exchange.call,hotel.model_checkin_partner,hotel.group_hotel_call,1,1,1,1
access_hotel_model_checkin_partner_user,hotel.currency_exchange.user,hotel.model_checkin_partner,hotel.group_hotel_user,1,1,1,1
access_hotel_order_call,hotel.order.call,sale.model_sale_order,hotel.group_hotel_call,1,1,1,1
access_hotel_order_line_call,hotel.order.line.call,sale.model_sale_order_line,hotel.group_hotel_call,1,1,1,1
access_hotel_order_line_user,hotel.order.line.user,sale.model_sale_order_line,hotel.group_hotel_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
14 access_hotel_folio_line_call hotel_folio.line.call model_hotel_reservation hotel.group_hotel_call 1 1 1 1
15 access_hotel_invoice_call account.invoice.call account.model_account_invoice hotel.group_hotel_call 1 1 1 1
16 access_hotel_invoice_user account.invoice.user account.model_account_invoice hotel.group_hotel_user 1 1 1 1
17 access_hotel_model_cardex_call access_hotel_model_checkin_partner_call hotel.currency_exchange.call hotel.model_cardex hotel.model_checkin_partner hotel.group_hotel_call 1 1 1 1
18 access_hotel_model_cardex_user access_hotel_model_checkin_partner_user hotel.currency_exchange.user hotel.model_cardex hotel.model_checkin_partner hotel.group_hotel_user 1 1 1 1
19 access_hotel_order_call hotel.order.call sale.model_sale_order hotel.group_hotel_call 1 1 1 1
20 access_hotel_order_line_call hotel.order.line.call sale.model_sale_order_line hotel.group_hotel_call 1 1 1 1
21 access_hotel_order_line_user hotel.order.line.user sale.model_sale_order_line hotel.group_hotel_user 1 1 1 1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,56 +0,0 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h1 style="font-size:200%; font-family:courier; color:black; text-align:center;"> HOTEL MANAGEMENT SYSTEM </h1>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12" style = "background-color: #009688; height:200px;">
<h1 style="font-family:courier; color:white ; text-align:right ; margin-right:1cm; margin-top: 35px"> HOTEL BOOKING </h1>
<p style="font-size:120%; font-family:courier; color:white ; text-align:right; margin-right: 2cm"> Book your room. </p>
<img style="position:relative;top:-120px; width: 200px; height:200px" src= "hotel1.png">
<img style="top:35px; width: 80px; height:80px; margin-right:2cm" src= "room.png" align="right">
<img style="position:relative; top:-170px; width:75px; height:75px;" src="book.png">
<img style="position:relative; top:-170px; width:70px; height:70px;" src="checkin.png">
<img style="position:relative; top:-170px; width:70px; height:70px;" src="key.png">
</div>
<div class="oe_span12" style = "background-color: #f1c40f; height:200px;">
<h1 style="font-family:courier; color:white ; text-align:left ; margin-top: 35px"> ALL INCLUSIVE </h1>
<p style="font-size:120%; font-family:courier; color:white ; text-align: left;"> Facilities provided </p>
<img style="top:35px;" src= "inc1.png">
<img style="top:35px; width: 50px; height: 50px;" src= "inc2.png" align="right">
<img style="top:35px; width: 50px; height: 50px;" src= "inc3.png" align="right">
<img style="top:35px; width: 50px; height: 50px;" src= "inc4.png" align="right">
<img style="top:50px; width: 50px; height: 50px;" src= "inc5.png" align="right">
</div>
<div class="oe_span12" style = "background-color: #f44336; height:200px;" >
<h1 style="font-family:courier; color:white ; text-align:right ; margin-right: 5cm; margin-top: 35px"> AMENITIES </h1>
<p style="font-size:120%; font-family:courier; color:white ; text-align:right; margin-right:2cm"> Extra class hotel service </p>
<img style="width:100px; height: 100px; margin-right:2cm" src="star_icon.png" align="right" >
<img style="top:35px; width:50px; height:50px; left:200px" src="gym.png">
<img style="width:80px; height:60px;" src="pool_icon.png" align="left">
<img style="width:60px; height:60px;" src="car.png">
</div>
<div class="oe_span12" style = "background-color: #cddc39; height:200px;" >
<h1 style="font-family:courier; color:white; text-align:left ; margin-top: 35px"> RESTURANTS </h1>
<p style="font-size:120%; font-family:courier; color:white ; text-align:left;"> Bon Appetite ! </p>
<img style="bottom:20px; width:250px; height: 150px" src="menu_waitor.png">
<img style="top:35px; width: 60px; height: 60px;" src= "plate.png" align="right">
<img style="top:35px; width: 60px; height: 60px;" src= "menu.png" align="right">
</div>
<div class="oe_span12" style = "background-color: #3ed37d; height:200px;" >
<h1 style="font-family:courier; color:white ; text-align:right ; margin-right:1cm; margin-top: 35px"> Currency Exchange </h1>
<p style="font-size:120%; font-family:courier; color:white ; text-align:right; margin-right:3cm"> Exchange currency on the go </p>
<img style="position:relative; top:-90px; width:110px; heigth:110px" src= "currency.png">
<img style="position:relative; top:-20px; width: 80px; height:80px; margin-right:1cm" src= "money.png" align="right">
</div>
<div class="oe_span12" style = "background-color: #34495e; height:200px;" >
<h1 style="font-family:courier; color:white ; text-align:left ; margin-right: 5cm; margin-top: 35px"> REPORTS </h1>
<p style="font-size:120%; font-family:courier; color:white ; text-align:left; margin-right:3cm"> Manage and Analyze </p>
<img style="position:relative; top:-80px; width: 150px; height:150px" src= "report1.png" align="right">
<img style="position:relative; top:-50px; width:100px; height:100px;" src="report.png" align="right">
</div>
</div>
</section>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,28 @@
odoo.define('hotel.ListController', function(require) {
'use strict';
/*
* Hotel
* GNU Public License
* Alexandre Díaz <dev@redneboa.es>
*/
var ListController = require('web.ListController');
var Core = require('web.core');
var _t = Core._t;
ListController.include({
renderButtons: function () {
this._super.apply(this, arguments); // Sets this.$buttons
var self = this;
if (this.modelName === 'hotel.reservation') {
this.$buttons.append("<button class='btn btn-sm oe_open_reservation_wizard oe_highlight' type='button'>"+_t('Open Wizard')+"</button>");
this.$buttons.find('.oe_open_reservation_wizard').on('click', function(){
self.do_action('hotel.open_wizard_reservations');
});
}
}
});
});

View File

@@ -96,16 +96,16 @@ class TestHotel(TestMail):
# Minimal Hotel Configuration
cls.tz_hotel = 'Europe/Madrid'
cls.parity_pricelist_id = cls.pricelist_1.id
cls.parity_restrictions_id = cls.restriction_1.id
cls.default_pricelist_id = cls.pricelist_1.id
cls.default_restriction_id = cls.restriction_1.id
cls.env['ir.values'].sudo().set_default('res.config.settings',
'tz_hotel', cls.tz_hotel)
cls.env['ir.values'].sudo().set_default('res.config.settings',
'parity_pricelist_id',
cls.parity_pricelist_id)
'default_pricelist_id',
cls.default_pricelist_id)
cls.env['ir.values'].sudo().set_default('res.config.settings',
'parity_restrictions_id',
cls.parity_restrictions_id)
'default_restriction_id',
cls.default_restriction_id)
# User Groups
user_group_hotel_manager = cls.env.ref('hotel.group_hotel_manager')
@@ -234,14 +234,14 @@ class TestHotel(TestMail):
})
room_type_rest_item_obj.create({
'room_type_id': k_vr,
'restriction_id': cls.parity_restrictions_id,
'restriction_id': cls.default_restriction_id,
'date_start': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'date_end': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'applied_on': '0_room_type',
'min_stay': cls.restrictions_min_stay_tmp[k_vr][i],
})
pricelist_item_obj.create({
'pricelist_id': cls.parity_pricelist_id,
'pricelist_id': cls.default_pricelist_id,
'date_start': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'date_end': ndate.strftime(DEFAULT_SERVER_DATE_FORMAT),
'compute_price': 'fixed',

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--==================================================== Currency ==================================================== -->
<!-- Form view of currency exchange -->
<record model="ir.ui.view" id="view_currency_exchange_form">
<field name="name">currency.exchange.form</field>
<field name="model">currency.exchange</field>
<field name="arch" type="xml">
<form string=" Currency Exchange">
<header>
<button name="cur_confirm" string="Done" states='draft' icon="gtk-ok" />
<button name="cur_cancel" string="Cancel" states='draft' icon="gtk-cancel" />
<button name="cur_cancel_draft" string="do_draft" states='cancel' icon="gtk-ok" />
<button name="%(report_hotel_currency)d" states='done' type="action" string="Print" class="oe_highlight" />
<field name="state" widget="statusbar" statusbar_visible="draft,done" />
</header>
<sheet>
<div class="oe_title ">
<label for="name" string="Name" />
<h1>
<field name="name" select="1" />
</h1>
</div>
<separator string="Details" />
<newline />
<group colspan="2" col="4">
<field name="today_date" />
<newline />
</group>
<group colspan="2" col="4">
<field name="folio_no" required="1" />
<field name="guest_name" required="1" />
<field name="room_number" required="1" />
<field name="hotel_id" />
<field name="type" />
</group>
<separator string="Currency Exchange" />
<newline />
<group colspan="2" col="4">
<field name="input_curr" />
<field name="in_amount" select="1" widget="monetary"
options="{'currency_field': 'input_curr'}" />
<field name="out_curr" />
<field name="rate" />
</group>
<group colspan="2" col="4">
<field name="out_amount" widget="monetary"
options="{'currency_field': 'out_curr'}" />
<newline />
<field name="tax" style="width:15%%;" />
</group>
<separator string="Total Amount" />
<newline />
<h1>
<field name="total" widget="monetary" options="{'currency_field': 'out_curr'}" />
</h1>
<group colspan="2" col="4"></group>
</sheet>
</form>
</field>
</record>
<!-- Tree view of currency exchange -->
<record model="ir.ui.view" id="view_currency_exchange_tree">
<field name="name">currency.exchange.tree</field>
<field name="model">currency.exchange</field>
<field name="arch" type="xml">
<tree string=" Currency Exchange">
<field name="name" />
<field name="today_date" />
<field name="guest_name" />
<field name="total" sum="Total" />
</tree>
</field>
</record>
<!-- Action of currency exchange -->
<record model="ir.actions.act_window" id="open_currency_exchange_tree">
<field name="name">Currency Exchange</field>
<field name="res_model">currency.exchange</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>

11
hotel/views/general.xml Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- Backend stuff -->
<template id="assets_backend" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/hotel/static/src/js/views/list/list_controller.js"></script>
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--==================================================== Board Services ==================================================== -->
<!-- Form view of hotel board service -->
<record model="ir.ui.view" id="hotel_board_service_view_form">
<field name="name">hotel.board.service.form</field>
<field name="model">hotel.board.service</field>
<field name="arch" type="xml">
<form string="Hotel Board Service">
<sheet>
<group>
<field name="name" select="1" />
<field name="sequence" />
</group>
<group>
<field name="service_ids" />
</group>
</sheet>
</form>
</field>
</record>
<!-- Tree view of hotel floor -->
<record model="ir.ui.view" id="hotel_board_service_view_tree">
<field name="name">hotel.board.service.tree</field>
<field name="model">hotel.board.service</field>
<field name="arch" type="xml">
<tree string="Hotel Board Services">
<field name="name" />
<field name="sequence" />
</tree>
</field>
</record>
<!-- Action of hotel floor -->
<record model="ir.actions.act_window" id="open_hotel_board_service_form_tree">
<field name="name">Board Services</field>
<field name="res_model">hotel.board.service</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Board Services" id="menu_open_hotel_board_service_form_tree"
action="open_hotel_board_service_form_tree" sequence="25"
parent="hotel.configuration_others" />
</odoo>

View File

@@ -1,57 +1,57 @@
<?xml version="1.0"?>
<odoo>
<!-- Action to open INE Codes list -->
<act_window
id="action_cardex"
name="Action cardex"
res_model="cardex"
view_mode="tree,form" />
<act_window
id="action_cardex_download"
name="Action cardex download"
res_model="cardex"
view_mode="form" /> <!-- Menu item to open INE Codes list -->
<menuitem
id="menu_cardex"
name="Cardex"
parent="hotel.hotel_reports_menu"
sequence="25"
action="action_cardex" />
<record id="view_form_cardex" model="ir.ui.view">
<field name="name">Cardex Form</field>
<field name="model">cardex</field>
<field name="arch" type="xml">
<form>
<sheet>
<group name="group_top">
<group name="group_left">
<field name="partner_id" required="True"/>
<field name="enter_date"/>
<field name="exit_date"/>
</group>
<group name="group_left">
<field name="reservation_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_tree_cardex" model="ir.ui.view">
<field name="name">Cardex Tree</field>
<field name="model">cardex</field>
<field name="arch" type="xml">
<tree>
<field name="partner_id" string="Client name"/>
<field name="enter_date"/>
<field name="exit_date"/>
<field name="reservation_id"/>
<!-- button type="action" class="oe_stat_button" id="cardex_smart_button" icon="fa-bed" /-->
</tree>
</field>
</record>
</odoo>
<?xml version="1.0"?>
<odoo>
<!-- Action to open INE Codes list -->
<act_window
id="action_checkin_partner"
name="Action checkin"
res_model='hotel.checkin.partner'
view_mode="tree,form" />
<act_window
id="action_checkin_partner_download"
name="Action checkin download"
res_model='hotel.checkin.partner'
view_mode="form" /> <!-- Menu item to open INE Codes list -->
<menuitem
id="menu_hotel_checkin_partner"
name="Checkins"
parent="hotel.hotel_reports_menu"
sequence="25"
action="action_checkin_partner" />
<record id="hotel_checkin_partner_view_form" model="ir.ui.view">
<field name="name">Checkin Form</field>
<field name="model">hotel.checkin.partner</field>
<field name="arch" type="xml">
<form>
<sheet>
<group name="group_top">
<group name="group_left">
<field name="partner_id" required="True"/>
<field name="enter_date"/>
<field name="exit_date"/>
</group>
<group name="group_left">
<field name="reservation_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="hotel_checkin_partner_view_tree" model="ir.ui.view">
<field name="name">Checkin Tree</field>
<field name="model">hotel.checkin.partner</field>
<field name="arch" type="xml">
<tree>
<field name="partner_id" string="Client name"/>
<field name="enter_date"/>
<field name="exit_date"/>
<field name="reservation_id"/>
<!-- button type="action" class="oe_stat_button" id="checkin_partner_smart_button" icon="fa-bed" /-->
</tree>
</field>
</record>
</odoo>

View File

@@ -1,210 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="dashboard_sales_action_id" model="ir.actions.act_window">
<field name="name">Folios</field>
<field name="res_model">hotel.dashboard</field>
</record>
<record id="dashboard_sales_order_action_id" model="ir.actions.act_window">
<field name="name">Folios</field>
<field name="res_model">hotel.dashboard</field>
</record>
<record id="dashboard_sales_done_action_id" model="ir.actions.act_window">
<field name="name">Folios</field>
<field name="res_model">hotel.dashboard</field>
</record>
<record id="dashboard_sales_cancel_action_id" model="ir.actions.act_window">
<field name="name">Folios</field>
<field name="res_model">hotel.dashboard</field>
</record>
<record id="hotel_dashboard_kanban_view" model="ir.ui.view">
<field name="name">hotel.dashboard.view</field>
<field name="model">hotel.dashboard</field>
<field name="arch" type="xml">
<kanban create="false" class="oe_background_grey o_kanban_dashboard o_account_kanban">
<field name="id"/>
<field name="name"/>
<field name="graph_type"/>
<field name="show_on_dashboard"/>
<field name="kanban_dashboard"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(0)}">
<t t-value="JSON.parse(record.kanban_dashboard.raw_value)" t-set="dashboard"/>
<t t-value="record.type.raw_value" t-set="journal_type"/>
<t t-value="record.name.raw_value" t-set="dashboard_name"/>
<t t-value="record.graph_type.raw_value" t-set="graph_type"/>
<t t-call="JournalTop"/>
<div class="container o_kanban_card_content o_visible">
<div class="row">
<t t-if="dashboard_name == 'Chekins Dashboard'" t-call="JournalBodySalePurchase"/>
<t t-if="dashboard_name != 'Chekins Dashboard'" t-call="JournalBodySalePurchase"/>
</div>
<t t-call="JournalBodyGraph"/>
</div><div class="container o_kanban_card_manage_pane o_invisible">
<t t-call="JournalManage"/>
</div>
</div>
</t>
<t t-name="JournalTop">
<div class="o_kanban_card_header">
<div class="o_kanban_card_header_title">
<div class="o_primary">
<a type="object" name="open_action"><field name="name"/></a>
</div>
<div class="o_secondary" t-att-title="dashboard.title">
<field name="type"/>
</div>
</div>
<div class="o_kanban_manage_button_section">
<a class="o_kanban_manage_toggle_button" href="#">More <i class="fa fa-caret-down"/></a>
</div>
</div>
</t>
<t t-name="JournalManage">
<div class="row">
<div class="col-xs-4 o_kanban_card_manage_section o_kanban_manage_view">
<div class="o_kanban_card_manage_title">
<span>View</span>
</div>
<div>
<a>
<span>Invoices</span>
</a>
</div>
<div>
<a>
<span>Refunds</span>
</a>
</div>
<div>
<a>Payments Matching</a>
</div>
<div>
<a>Journal Items</a>
</div>
</div>
<div class="col-xs-4 o_kanban_card_manage_section o_kanban_manage_new">
<div class="o_kanban_card_manage_title">
<span>New</span>
</div>
<div>
<a>
<span>Invoice</span>
</a>
</div>
<div>
<a>
<span>Refund</span>
</a>
</div>
</div>
<div class="col-xs-4 o_kanban_card_manage_section o_kanban_manage_reports">
<div class="o_kanban_card_manage_title">
<span>Reports</span>
</div>
<div>
<a>Invoices Analysis</a>
</div>
</div>
</div>
<div class="row o_kanban_card_settings">
<div class="col-xs-6">
<a><i t-attf-class="fa o_dashboard_star #{record.show_on_dashboard.raw_value ? 'fa-star' : 'fa-star-o'}" title="Click to add/remove from favorite"/> Favorite</a>
</div>
<div class="col-xs-6 text-right">
<a type="edit">Settings</a>
</div>
</div>
</t>
<t t-name="JournalBodySalePurchase">
<div class="col-xs-6 o_kanban_primary_left">
<t>
<button type="object" name="action_create_new" class="btn btn-primary btn-sm o_invoice_new">
<span>New</span>
</button>
</t>
</div>
<div class="col-xs-6 o_kanban_primary_right">
<div class="row">
<div class="col-xs-6">
<a type="object" name="open_action" context="{'search_default_draft': '1', 'search_default_proforma': '1'}">
<span> Draft</span>
</a>
</div>
<div class="col-xs-6 text-right">
<span><t t-esc="dashboard.sum_draft"/></span>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<a type="object" name="open_action" context="{'search_default_unpaid': '1'}">
<span> Payments to do</span>
</a>
</div>
<div class="col-xs-6 text-right">
<span><t t-esc="dashboard.sum_waiting"/></span>
</div>
</div>
</div>
</t>
<t t-name="JournalBodyGraph">
<div class="o_kanban_graph_section">
<span t-if="graph_type == 'line'">
<field name="kanban_dashboard_graph" t-att-graph_type="'line'" widget="dashboard_graph"/>
</span>
<span t-if="graph_type == 'bar'">
<field name="kanban_dashboard_graph" t-att-graph_type="'bar'" widget="dashboard_graph"/>
</span>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="hotel_dashboard_action" model="ir.actions.act_window">
<field name="name">Hotel Dashboard</field>
<field name="res_model">hotel.dashboard</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="context">{}</field>
<field name="view_mode">kanban</field>
<field name="view_id" ref="hotel_dashboard_kanban_view"/>
</record>
<menuitem id="employees_dashboard_menu"
parent="hotel_management_menu"
sequence="1"
name="Dashboard"
action="hotel_dashboard_action"/>
<data noupdate="0">
<record model="hotel.dashboard" id="chekins_dashboard">
<field name="name">Chekins Dashboard</field>
<field name="type">sales</field>
<field name="graph_type">bar</field>
<field name="show_on_dashboard">1</field>
</record>
<record model="hotel.dashboard" id="onboard_dashboard">
<field name="name">On Board</field>
<field name="type">sales</field>
<field name="graph_type">line</field>
<field name="show_on_dashboard">1</field>
</record>
</data>
</odoo>

Some files were not shown because too many files have changed in this diff Show More