Merge pull request #108 from hootel/pr_ine

Pr ine
This commit is contained in:
Darío Lodeiros
2019-06-03 12:47:33 +02:00
committed by GitHub
13 changed files with 441 additions and 451 deletions

23
hotel_ine/__init__.py Normal file
View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2019 Alda Hotels <informatica@aldahotels.com>
# Jose Luis Algara <osotranquilo@gmail.com>
#
# 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 . import wizard
from . import models

41
hotel_ine/__manifest__.py Normal file
View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Odoo, Open Source Management Solution
# Copyright (C) 2019 Jose Luis Algara Toledo <osotranquilo@gmail.com>
#
# 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/>.
#
##############################################################################
{
'name': 'Hotel Ine',
'description': """
Create de INE Report""",
'version': '1.0.0',
'license': 'AGPL-3',
'summary': "Export hotel data for INE report",
'author': "Jose Luis Algara (Alda hotels) <osotranquilo@gmail.com>",
'website': 'www.aldahotels.com',
'depends': ['hotel', 'hotel_l10n_es'],
'category': 'hotel/ine',
'data': [
'wizard/inewizard.xml',
'views/inherited_hotel_room_view.xml',
],
'demo': [
],
'installable': True,
'auto_install': False,
'application': False,
}

View File

@@ -0,0 +1 @@
from . import inherited_hotel_room

View File

@@ -0,0 +1,9 @@
# Copyright 2019 Jose Luis Algara <osotranquilo@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
class HotelRoom(models.Model):
_inherit = 'hotel.room'
in_ine = fields.Boolean('Included in the INE statistics', default=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<odoo>
<record id="hotel_room_view_form" model="ir.ui.view">
<field name="model">hotel.room</field>
<field name="inherit_id" ref="hotel.hotel_room_view_form" />
<field name="arch" type="xml">
<xpath expr="//notebook" position="inside">
<page string="I.N.E.">
<group>
<field name="in_ine" colspan="2"/>
</group>
</page>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2019 Alda Hotels <informatica@aldahotels.com>
# Jose Luis Algara <osotranquilo@gmail.com>
#
# 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 . import inewizard

View File

@@ -0,0 +1,315 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017-19 Alda Hotels <informatica@aldahotels.com>
# Jose Luis Algara <osotranquilo@gmail.com>
#
# 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 openerp import models, fields, api
import base64
import datetime
import calendar
import xml.etree.cElementTree as ET
from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)
def get_years():
year_list = []
for i in range(2017, get_year()+1):
year_list.append((i, str(i)))
return year_list
def get_year():
now = datetime.datetime.now()
return int(now.year)
def get_month():
now = datetime.datetime.now()
month = int(now.month)-1
if month <= 0:
month = 12
return month
class Wizard(models.TransientModel):
_name = 'ine.wizard'
txt_filename = fields.Char()
txt_binary = fields.Binary()
ine_month = fields.Selection([(1, 'January'), (2, 'February'),
(3, 'March'), (4, 'April'),
(5, 'May'), (6, 'June'), (7, 'July'),
(8, 'August'), (9, 'September'),
(10, 'October'), (11, 'November'),
(12, 'December'), ],
string='Month', default=get_month())
ine_year = fields.Selection(get_years(), default=get_year(), string='Year')
adr_screen = fields.Char()
rev_screen = fields.Char()
@api.one
def generate_file(self):
_logger.warning("Start Export INE XML file")
last_day = calendar.monthrange(self.ine_year, self.ine_month)[1]
ine_start_search = datetime.date(self.ine_year, self.ine_month, 1)
ine_end_search = ine_start_search + datetime.timedelta(days=last_day)
compan = self.env.user.company_id
active_room = self.env['hotel.room'].search([('in_ine', '=', True)])
message = ""
if not compan.property_name:
message = 'The NAME of the property is not established'
if not compan.name:
message = 'The NAME of the company is not established'
if not compan.vat:
message = 'The VAT is not established'
if not compan.ine_tourism:
message = 'The tourism number of the property is not established'
if message != "":
raise UserError(message)
return
encuesta = ET.Element("ENCUESTA")
cabezera = ET.SubElement(encuesta, "CABECERA")
fecha = ET.SubElement(cabezera, "FECHA_REFERENCIA")
ET.SubElement(fecha, "MES").text = str(self.ine_month)
ET.SubElement(fecha, "ANYO").text = str(self.ine_year)
ET.SubElement(cabezera, "DIAS_ABIERTO_MES_REFERENCIA").text = (
str(last_day))
ET.SubElement(cabezera, "RAZON_SOCIAL").text = compan.name
ET.SubElement(cabezera, "NOMBRE_ESTABLECIMIENTO").text = (
compan.property_name)
ET.SubElement(cabezera, "CIF_NIF").text = compan.vat[2:]
ET.SubElement(cabezera, "NUMERO_REGISTRO").text = compan.ine_tourism
ET.SubElement(cabezera, "DIRECCION").text = compan.street
ET.SubElement(cabezera, "CODIGO_POSTAL").text = compan.zip
ET.SubElement(cabezera, "LOCALIDAD").text = compan.city
ET.SubElement(cabezera, "MUNICIPIO").text = compan.city
ET.SubElement(cabezera, "PROVINCIA"
).text = compan.state_id.display_name
ET.SubElement(cabezera, "TELEFONO_1").text = (
compan.phone.replace(' ', '')[0:12])
ET.SubElement(cabezera, "TIPO").text = (
compan.ine_category_id.category_type)
ET.SubElement(cabezera, "CATEGORIA").text = compan.ine_category_id.name
ET.SubElement(cabezera, "HABITACIONES").text = str(len(active_room))
ET.SubElement(cabezera, "PLAZAS_DISPONIBLES_SIN_SUPLETORIAS"
).text = str(compan.ine_seats)
ET.SubElement(cabezera, "URL").text = compan.website
alojamiento = ET.SubElement(encuesta, "ALOJAMIENTO")
all_room_nights = self.env['hotel.reservation.line'].search([
('date', '>=', ine_start_search),
('date', '<=', ine_end_search),
('reservation_id.room_id.in_ine', '=', True),
('reservation_id.reservation_type', '=', 'normal'),
])
room_nights = all_room_nights.filtered(
lambda n: (self.get_codeine(n.reservation_id)))
# Creating the empty dictionary system
dic_tabla = []
for room_night in room_nights:
ine_code = self.get_codeine(room_night.reservation_id)
if not next((item for item in dic_tabla if item["ine"] == ine_code), False):
for x in range(1, last_day+1):
dic_tabla.append({'ine': ine_code,
'dia': x,
'entradas': 0,
'salidas': 0,
'pernocta': 0
})
# Adding overnight stays per day and INE code
for dia in range(1, last_day+1):
for room_night in room_nights.filtered(
lambda x: x.date == str(self.ine_year)+'-'+str(
self.ine_month).zfill(2)+'-'+str(dia).zfill(2)):
ine_code = self.get_codeine(room_night.reservation_id)
for idx, val in enumerate(dic_tabla):
if val['ine'] == ine_code and val['dia'] == dia:
dic_tabla[idx]['pernocta'] += room_night.reservation_id.adults
# Calculating outputs and entries
count = 1
last_stay = 0
for idx, row in enumerate(dic_tabla):
if count == last_day:
last_stay = 0
count = 1
count += 1
if last_stay < dic_tabla[idx]['pernocta']:
dic_tabla[idx]['entradas'] += dic_tabla[idx]['pernocta']
elif last_stay > dic_tabla[idx]['pernocta']:
dic_tabla[idx]['salidas'] += last_stay - dic_tabla[idx][
'pernocta']
last_stay = dic_tabla[idx]['pernocta']
# "Print" outputs and entries
ine_residen = ""
for idx, row in enumerate(dic_tabla):
if ine_residen != dic_tabla[idx]['ine']:
ine_residen = dic_tabla[idx]['ine']
residencia = ET.SubElement(alojamiento, "RESIDENCIA")
if len(dic_tabla[idx]['ine']) > 3:
ET.SubElement(residencia, "ID_PROVINCIA_ISLA"
).text = str(dic_tabla[idx]['ine'])
else:
ET.SubElement(residencia, "ID_PAIS"
).text = str(dic_tabla[idx]['ine'])
if ((dic_tabla[idx]['entradas'] != 0)
or (dic_tabla[idx]['salidas'] != 0)
or (dic_tabla[idx]['pernocta'] != 0)):
movimiento = ET.SubElement(residencia, "MOVIMIENTO")
ET.SubElement(movimiento, "N_DIA").text = (
"%02d" % dic_tabla[idx]['dia'])
ET.SubElement(movimiento, "ENTRADAS").text = str(
dic_tabla[idx]['entradas'])
ET.SubElement(movimiento, "SALIDAS").text = str(
dic_tabla[idx]['salidas'])
ET.SubElement(movimiento, "PERNOCTACIONES").text = str(
dic_tabla[idx]['pernocta'])
habitaciones = ET.SubElement(encuesta, "HABITACIONES")
# Bucle de HABITACIONES_MOVIMIENTO
ingresos = 0
habitaci = 0
hab_vend = 0
for dia in range(1, last_day+1):
suple = 0
doble = 0
dindi = 0
otras = 0
habitaci += len(active_room)
habitaci -= self.env['hotel.reservation.line'].search([
('date', '=', str(self.ine_year)+'-'+str(
self.ine_month).zfill(2)+'-'+str(dia).zfill(2)),
('reservation_id.reservation_type', '!=', 'normal'),
], count=True)
for room_night in room_nights.filtered(lambda x: x.date == str(
self.ine_year)+'-'+str(
self.ine_month).zfill(2)+'-'+str(
dia).zfill(2)):
ingresos += room_night.price
hab_vend += 1
if room_night.reservation_id.room_id.capacity == 2:
if room_night.reservation_id.adults == 1:
dindi += 1
else:
doble += 1
else:
otras += 1
if len(room_night.reservation_id.service_ids):
for service in room_night.reservation_id.service_ids:
if service.product_id.is_extra_bed:
suple += 1
habitaciones_m = ET.SubElement(habitaciones,
"HABITACIONES_MOVIMIENTO")
ET.SubElement(habitaciones_m,
"HABITACIONES_N_DIA").text = "%02d" % (dia)
ET.SubElement(habitaciones_m,
"PLAZAS_SUPLETORIAS").text = str(suple)
ET.SubElement(habitaciones_m,
"HABITACIONES_DOBLES_USO_DOBLE").text = str(doble)
ET.SubElement(habitaciones_m,
"HABITACIONES_DOBLES_USO_INDIVIDUAL").text = str(
dindi)
ET.SubElement(habitaciones_m,
"HABITACIONES_OTRAS").text = str(otras)
precios = ET.SubElement(encuesta, "PRECIOS")
ET.SubElement(precios,
"REVPAR_MENSUAL").text = str(round(ingresos/habitaci, 2))
ET.SubElement(precios,
"ADR_MENSUAL").text = str(round(ingresos/hab_vend, 2))
ET.SubElement(precios, "ADR_TOUROPERADOR_TRADICIONAL").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_TOUROPERADOR_TRADICIONAL"
).text = '0'
ET.SubElement(precios,
"ADR_TOUROPERADOR_ONLINE").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_TOUROPERADOR_ONLINE"
).text = '0'
ET.SubElement(precios,
"ADR_EMPRESAS").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_EMPRESAS").text = '0'
ET.SubElement(precios,
"ADR_AGENCIA_DE_VIAJE_TRADICIONAL").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_AGENCIA_TRADICIONAL"
).text = '0'
ET.SubElement(precios, "ADR_AGENCIA_DE_VIAJE_ONLINE").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_AGENCIA_ONLINE"
).text = '0'
ET.SubElement(precios, "ADR_PARTICULARES").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_PARTICULARES").text = '0'
ET.SubElement(precios,
"ADR_GRUPOS").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_GRUPOS").text = '0'
ET.SubElement(precios, "ADR_INTERNET").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_INTERNET").text = '0'
ET.SubElement(precios, "ADR_OTROS").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_OTROS").text = '0'
personal = ET.SubElement(encuesta, "PERSONAL_OCUPADO")
ET.SubElement(personal, "PERSONAL_NO_REMUNERADO").text = '0'
ET.SubElement(personal,
"PERSONAL_REMUNERADO_FIJO").text = str(
compan.ine_permanent_staff)
ET.SubElement(personal,
"PERSONAL_REMUNERADO_EVENTUAL").text = str(
compan.ine_eventual_staff)
xmlstr = '<?xml version="1.0" encoding="ISO-8859-1"?>'
xmlstr += ET.tostring(encuesta).decode('utf-8')
return self.write({
'txt_filename': 'INE_'+str(self.ine_month)+'_'+str(
self.ine_year) + '.' + 'xml',
'adr_screen': 'ADR en el mes de la encuesta: '+str(
round(ingresos/habitaci, 2)) + '€ y ',
'rev_screen': ' RevPar : '+str(round(ingresos/hab_vend, 2))+'',
'txt_binary': base64.encodestring(xmlstr.encode())
})
@api.model
def get_codeine(self, reserva):
response = False
code = reserva[0].partner_id.code_ine_id
if code:
response = code.code
else:
for l in reserva[0].folio_id.checkin_partner_ids:
if l.code_ine_id:
response = l.code_ine_id.code
return response

View File

@@ -1,15 +1,16 @@
<?xml version="1.0"?>
<odoo>
<openerp>
<data>
<act_window
id="action_ine_download"
name="Action INE File Download"
name="I.N.E. File Download"
res_model="ine.wizard"
view_mode="form"
/>
<record id="ine_wizard_form" model="ir.ui.view">
<field name="name">ine.wizard.form</field>
<record id="view_ine_download" model="ir.ui.view">
<field name="name">INE File Download</field>
<field name="model">ine.wizard</field>
<field name="arch" type="xml">
<form>
@@ -21,13 +22,13 @@
<div>
<button name="generate_file" class="oe_form_button_save btn btn-primary btn-sm" type="object" string="Generate file"/>
<field name="txt_filename" invisible="1"/>
<field name="txt_binary" filename="txt_filename" readonly="1" style="margin-left: 20px;"/>
<field name="txt_binary" filename="txt_filename" readonly="1" style="margin-left: 20px;font-size: large;"/>
</div>
<separator string="ADR y RevPar"/>
<group>
<div>
<field name="adr_screen" readonly="1"/>
<field name="rev_screen" readonly="1"/>
<field name="adr_screen" style="font-size: large;" readonly="1"/>
<field name="rev_screen" style="font-size: large;" class="oe_title" readonly="1"/>
</div>
</group>
<group>
@@ -48,4 +49,6 @@
action="action_ine_download"
/>
</odoo>
</data>
</openerp>

View File

@@ -43,7 +43,6 @@
'report/report_parte_viajero.xml',
'views/report_viajero.xml',
'wizard/police_wizard.xml',
'wizard/ine_wizard.xml',
'views/category_tourism.xml',
'views/code_ine.xml',
'views/inherit_res_company.xml',

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -21,4 +21,3 @@
##############################################################################
from . import police_wizard
from . import ine_wizard

View File

@@ -1,441 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Alda Hotels <informatica@aldahotels.com>
# Jose Luis Algara <osotranquilo@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import models, fields, api, _
import base64
import datetime
import calendar
import xml.etree.cElementTree as ET
from openerp.exceptions import UserError
def get_years():
year_list = []
for i in range(2017, get_year()+1):
year_list.append((i, str(i)))
return year_list
def get_year():
now = datetime.datetime.now()
return int(now.year)
def get_month():
now = datetime.datetime.now()
month = int(now.month)-1
if month <= 0:
month = 12
return month
class IneWizard(models.TransientModel):
_name = 'ine.wizard'
txt_filename = fields.Char()
txt_binary = fields.Binary()
ine_month = fields.Selection([(1, 'January'), (2, 'February'),
(3, 'March'), (4, 'April'),
(5, 'May'), (6, 'June'), (7, 'July'),
(8, 'August'), (9, 'September'),
(10, 'October'), (11, 'November'),
(12, 'December'), ],
string='Month', default=get_month())
ine_year = fields.Selection(get_years(), default=get_year(), string='Year')
adr_screen = fields.Char()
rev_screen = fields.Char()
@api.one
def generate_file(self):
month_first_date = datetime.datetime(self.ine_year, self.ine_month, 1)
last_day = calendar.monthrange(self.ine_year, self.ine_month)[1] - 1
month_end_date = month_first_date + datetime.timedelta(days=last_day)
m_f_d_search = datetime.date(self.ine_year, self.ine_month, 1)
m_e_d_search = m_f_d_search + datetime.timedelta(days=last_day)
last_day += 1
# Seleccionamos los que tienen Entrada en el mes + salida en el mes +
# entrada antes y salida despues. Ordenandolos.
lines = self.env['hotel.checkin.partner'].search(
['|', '|', '&', ('exit_date', '>=', m_f_d_search),
('exit_date', '<=', m_e_d_search), '&',
('enter_date', '>=', m_f_d_search),
('enter_date', '<=', m_e_d_search), '&',
('enter_date', '<=', m_f_d_search),
('exit_date', '>=', m_e_d_search)], order="enter_date")
lines = lines.sorted(
key=lambda r: str(r.partner_id.code_ine_id)+r.enter_date)
if len(lines) > 0:
company = self.env.user.company_id
encuesta = ET.Element("ENCUESTA")
cabezera = ET.SubElement(encuesta, "CABECERA")
fecha = ET.SubElement(cabezera, "FECHA_REFERENCIA")
ET.SubElement(fecha, "MES").text = '{:02d}'.format(self.ine_month)
ET.SubElement(fecha, "ANYO").text = str(self.ine_year)
month_end_date = (
datetime.datetime(self.ine_year, self.ine_month, 1) +
datetime.timedelta(days=calendar.monthrange(
self.ine_year, self.ine_month)[1] - 1))
ET.SubElement(cabezera, "DIAS_ABIERTO_MES_REFERENCIA").text = (
str(month_end_date.day))
ET.SubElement(cabezera, "RAZON_SOCIAL").text = company.name
ET.SubElement(cabezera, "NOMBRE_ESTABLECIMIENTO").text = (
company.property_name)
ET.SubElement(cabezera, "CIF_NIF").text = company.vat[2:]
ET.SubElement(cabezera, "NUMERO_REGISTRO").text = company.ine_tourism
ET.SubElement(cabezera, "DIRECCION").text = company.street
ET.SubElement(cabezera, "CODIGO_POSTAL").text = company.zip
ET.SubElement(cabezera, "LOCALIDAD").text = company.city
ET.SubElement(cabezera, "MUNICIPIO").text = company.city
ET.SubElement(cabezera, "PROVINCIA"
).text = company.state_id.display_name
ET.SubElement(cabezera, "TELEFONO_1").text = (
company.phone.replace(' ', '')[0:12])
ET.SubElement(cabezera, "TIPO").text = company.ine_category_id.category_type
ET.SubElement(cabezera, "CATEGORIA").text = company.ine_category_id.name
active_room = self.env['hotel.room'].search_count(
[('capacity', '>', 0)])
ET.SubElement(cabezera, "HABITACIONES").text = str(active_room)
ET.SubElement(cabezera, "PLAZAS_DISPONIBLES_SIN_SUPLETORIAS"
).text = str(company.ine_seats)
ET.SubElement(cabezera, "URL").text = company.website
alojamiento = ET.SubElement(encuesta, "ALOJAMIENTO")
# Bucle de RESIDENCIA
# Init Variables
ine_entrada = []
ine_salidas = []
ine_pernoct = []
ine_pernoct_total = []
for x in range(last_day+1):
ine_entrada.append(0)
ine_salidas.append(0)
ine_pernoct.append(0)
ine_pernoct_total.append(0)
# Cabezera
code_control = lines[0].partner_id.code_ine_id.code
if code_control is False:
raise UserError(_('ERROR: Usuario sin codigo de INE: '
+ lines[0].partner_id.name))
for line in lines:
# Si ha cambiado el codigo
if code_control != line.partner_id.code_ine_id.code:
residencia = ET.SubElement(alojamiento, "RESIDENCIA")
if len(code_control) > 3:
ET.SubElement(residencia, "ID_PROVINCIA_ISLA"
).text = str(code_control)
else:
ET.SubElement(residencia, "ID_PAIS"
).text = str(code_control)
for x in range(1, last_day+1):
if ine_entrada[x]+ine_salidas[x]+ine_pernoct[x] > 0:
movimiento = ET.SubElement(residencia,
"MOVIMIENTO")
ET.SubElement(movimiento, "N_DIA"
).text = "%02d" % (x)
ET.SubElement(movimiento, "ENTRADAS"
).text = str(ine_entrada[x])
ET.SubElement(movimiento, "SALIDAS"
).text = str(ine_salidas[x])
ET.SubElement(movimiento, "PERNOCTACIONES"
).text = str(ine_pernoct[x])
# Guardamos el total de pernoctaciones/dia
ine_pernoct_total[x] += ine_pernoct[x]
# Reset Variables
ine_entrada = []
ine_salidas = []
ine_pernoct = []
for x in xrange(last_day+1):
ine_entrada.append(0)
ine_salidas.append(0)
ine_pernoct.append(0)
code_control = line.partner_id.code_ine_id.code
# Hacemos las sumas
f_entrada = line.enter_date.split('-')
f_salida = line.exit_date.split('-')
# Ha entrado este mes
if int(f_entrada[1]) == self.ine_month:
ine_entrada[int(f_entrada[2])] += 1
cuenta_entrada = int(f_entrada[2])
else:
# No marco entrada y cuento desde el dia 1
cuenta_entrada = 1
# Ha salido este mes
if int(f_salida[1]) == self.ine_month:
ine_salidas[int(f_salida[2])] += 1
cuenta_salida = int(f_salida[2])
else:
# No marco entrada y cuento desde el dia 1
cuenta_salida = last_day+1
# Contando pernoctaciones
for i in range(cuenta_salida-cuenta_entrada):
ine_pernoct[cuenta_entrada+i] += 1
# Fin de cuenta desde Cardex
habitaciones = ET.SubElement(encuesta, "HABITACIONES")
# Bucle de HABITACIONES_MOVIMIENTO
month_adr_sum = 0
month_adr_rooms = 0
month_revpar_staff_rooms = 0
movimientos = []
# Reset Variables
ine_entrada = []
ine_salidas = []
for x in range(last_day+1):
ine_entrada.append(0)
ine_salidas.append(0)
for x in range(last_day+1):
movimientos.append([0, 0, 0, 0, 0, 0, active_room])
# movimientos.append(['suple','doble','indi','otra','adr_sum',
# 'adr_rum','adr_staff'])
lines_res = self.env['hotel.reservation'].search(
['|', '|', '&', ('checkout', '>=', str(m_f_d_search)),
('checkout', '<=', str(m_e_d_search)), '&',
('checkin', '>=', str(m_f_d_search)),
('checkin', '<=', str(m_e_d_search)), '&',
('checkin', '<=', str(m_f_d_search)),
('checkout', '>=', str(m_e_d_search))], order="checkin")
for line_res in lines_res:
room = line_res.room_id
# No es Staff o Out y esta booking
if (line_res.reservation_type == 'normal') and (
(line_res.state == 'booking') or (line_res.state == 'done')):
# calculamos capacidad de habitacion
# !!!!! ATENCION !!!!
# pendiente de añadir un campo con las supletorias.
# asumimos de momento que por defecto supletorias sera
# 0 por ejemplo para todas......
# cambiar/calcular la siguiente linea.
suple_room = 0
capacidad = room.capacity + suple_room
# Cuadramos adultos con los checkin realizados.
if line_res.adults > line_res.checkin_partner_count:
adultos = line_res.checkin_partner_count
else:
adultos = line_res.adults
f_entrada = line_res.checkin.split('-')
f_salida = line_res.checkout.split('-')
f_entrada[2] = f_entrada[2].split()[0]
f_salida[2] = f_salida[2].split()[0]
# Ha entrado este mes
if int(f_entrada[1]) == self.ine_month:
ine_entrada[int(f_entrada[2])] += 1
cuenta_entrada = int(f_entrada[2])
else:
# No marco entrada y cuento desde el dia 1
cuenta_entrada = 1
# Ha salido este mes?
if int(f_salida[1]) == self.ine_month:
ine_salidas[int(f_salida[2])] += 1
cuenta_salida = int(f_salida[2])
else:
# No marco salida y cuento hasta el dia last_day
cuenta_salida = last_day + 1
# para las noches que ha estado
for dia_x in range(cuenta_entrada, cuenta_salida+1):
# si no supera el numero de habitaciones ni de
# pernoctaciones totales del dia...
if ((movimientos[dia_x-1][1]+movimientos[dia_x-1][2] +
movimientos[dia_x-1][3]) < active_room and (
((movimientos[dia_x-1][1]*2) +
movimientos[dia_x-1][2] +
movimientos[dia_x-1][3]) <
ine_pernoct_total[dia_x-1])):
if capacidad == 1:
# Habitacion Individual
movimientos[dia_x-1][3] += 1
if adultos > 1:
# Supletorias
movimientos[dia_x-1][0] += 1
elif capacidad == 2:
# Habitacion Doble
if adultos == 1:
# Uso individual
movimientos[dia_x-1][2] += 1
else:
# Doble
movimientos[dia_x-1][1] += 1
if adultos > 2:
# Doble + supletorias
movimientos[dia_x-1][0] += (adultos-2)
elif capacidad > 2:
# Otras Habitaciones
movimientos[dia_x-1][3] += 1
else:
raise UserError(str(dia_x) +
'Exceso de habitaciones ' +
str(line_res) + ' ' + line_res.name +
' ' + line_res.partner_id.name +
' PERNOCT.: ' +
str(ine_pernoct_total[dia_x-1]))
# ADR y RevPar
for xx_lines in line_res.reservation_line_ids:
# ADR calculo
xx_dia = xx_lines.date.split('-')
if int(xx_dia[1]) == self.ine_month:
movimientos[int(xx_dia[2])][4] += xx_lines.price
movimientos[int(xx_dia[2])][5] += 1
else:
# Staff o Out
for xx_lines in line_res.reservation_line_ids:
xx_dia = xx_lines.date.split('-')
if int(xx_dia[1]) == self.ine_month:
# Restamos una Habitacion no valida para RevPar
movimientos[int(xx_dia[2])][6] -= 1
for dia_x in xrange(1, last_day+1):
# Si la suma de los durmiendo es superior a pernoctaciones INE
suma_durmiendo = ((movimientos[dia_x][1]*2)
+ movimientos[dia_x][2]
+ movimientos[dia_x][3])
if suma_durmiendo > ine_pernoct_total[dia_x]:
suma_durmiendo = (suma_durmiendo -
ine_pernoct_total[dia_x])
if suma_durmiendo == 1:
if movimientos[dia_x][2] > 0:
# quitamos una individual
movimientos[dia_x][2] -= 1
elif movimientos[dia_x][3] > 0:
# quitamos una otras
movimientos[dia_x][3] -= 1
elif suma_durmiendo == 2:
if movimientos[dia_x][1] > 0:
# quitamos una doble
movimientos[dia_x][1] -= 1
elif movimientos[dia_x][3] > 0:
# quitamos una otras
movimientos[dia_x][3] -= 1
habitaciones_m = ET.SubElement(habitaciones,
"HABITACIONES_MOVIMIENTO")
ET.SubElement(habitaciones_m,
"HABITACIONES_N_DIA").text = "%02d" % (dia_x)
if ine_pernoct_total[dia_x] > company.ine_seats:
# Añadimos Supletorias por si excedemos plazas
movimientos[dia_x][0] = (ine_pernoct_total[dia_x]
- company.ine_seats)
ET.SubElement(habitaciones_m,
"PLAZAS_SUPLETORIAS").text = str(
movimientos[dia_x][0])
ET.SubElement(habitaciones_m,
"HABITACIONES_DOBLES_USO_DOBLE").text = str(
movimientos[dia_x][1])
ET.SubElement(habitaciones_m,
"HABITACIONES_DOBLES_USO_INDIVIDUAL").text = str(
movimientos[dia_x][2])
ET.SubElement(habitaciones_m,
"HABITACIONES_OTRAS").text = str(
movimientos[dia_x][3])
# calculo ADR
month_adr_sum += movimientos[dia_x][4]
month_adr_rooms += movimientos[dia_x][5]
month_revpar_staff_rooms += movimientos[dia_x][6]
precios = ET.SubElement(encuesta, "PRECIOS")
ET.SubElement(precios,
"REVPAR_MENSUAL").text = str(
round(month_adr_sum/month_revpar_staff_rooms, 2))
ET.SubElement(precios,
"ADR_MENSUAL").text = str(
round(month_adr_sum/month_adr_rooms, 2))
ET.SubElement(precios, "ADR_TOUROPERADOR_TRADICIONAL").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_TOUROPERADOR_TRADICIONAL"
).text = '0'
ET.SubElement(precios,
"ADR_TOUROPERADOR_ONLINE").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_TOUROPERADOR_ONLINE"
).text = '0'
ET.SubElement(precios,
"ADR_EMPRESAS").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_EMPRESAS").text = '0'
ET.SubElement(precios,
"ADR_AGENCIA_DE_VIAJE_TRADICIONAL").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_AGENCIA_TRADICIONAL"
).text = '0'
ET.SubElement(precios, "ADR_AGENCIA_DE_VIAJE_ONLINE").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_AGENCIA_ONLINE"
).text = '0'
ET.SubElement(precios, "ADR_PARTICULARES").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_PARTICULARES").text = '0'
ET.SubElement(precios,
"ADR_GRUPOS").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_GRUPOS").text = '0'
ET.SubElement(precios, "ADR_INTERNET").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_INTERNET").text = '0'
ET.SubElement(precios, "ADR_OTROS").text = '0'
ET.SubElement(precios,
"PCTN_HABITACIONES_OCUPADAS_OTROS").text = '0'
personal = ET.SubElement(encuesta, "PERSONAL_OCUPADO")
ET.SubElement(personal, "PERSONAL_NO_REMUNERADO").text = '0'
ET.SubElement(personal,
"PERSONAL_REMUNERADO_FIJO").text = str(
company.permanentstaff)
ET.SubElement(personal,
"PERSONAL_REMUNERADO_EVENTUAL").text = str(
company.eventualstaff)
xmlstr = '<?xml version="1.0" encoding="ISO-8859-1"?>'
xmlstr += ET.tostring(encuesta)
# file=base64.encodestring( xmlstr )
return self.write({
'txt_filename': 'INE_'+str(self.ine_month)+'_'+str(
self.ine_year) + '.' + 'xml',
'adr_screen': _('ADR in the month of the survey: ')+str(
round(month_adr_sum/month_adr_rooms, 2))+_('€ and '),
'rev_screen': ' RevPar : '+str(round(
month_adr_sum/month_revpar_staff_rooms, 2))+'',
'txt_binary': base64.encodestring(xmlstr)
})
else:
return self.write({
'rev_screen': _('No data in this month')
})