From 7dbe789e01761aa4244144bb592c5e5ba36fe198 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Mon, 29 Apr 2019 12:55:54 +0200 Subject: [PATCH 01/23] [ADD] Data BI --- hotel_data_bi/README.rst | 74 ++++++++++++++ hotel_data_bi/__init__.py | 1 + hotel_data_bi/__manifest__.py | 32 ++++++ hotel_data_bi/models/__init__.py | 3 + hotel_data_bi/models/budget.py | 48 +++++++++ hotel_data_bi/models/data_bi.py | 107 ++++++++++++++++++++ hotel_data_bi/models/inherit_res_company.py | 13 +++ hotel_data_bi/security/data_bi.xml | 10 ++ hotel_data_bi/security/ir.model.access.csv | 4 + hotel_data_bi/static/description/icon.png | Bin 0 -> 66994 bytes hotel_data_bi/views/budget.xml | 71 +++++++++++++ hotel_data_bi/views/inherit_res_company.xml | 19 ++++ 12 files changed, 382 insertions(+) create mode 100644 hotel_data_bi/README.rst create mode 100644 hotel_data_bi/__init__.py create mode 100644 hotel_data_bi/__manifest__.py create mode 100644 hotel_data_bi/models/__init__.py create mode 100644 hotel_data_bi/models/budget.py create mode 100644 hotel_data_bi/models/data_bi.py create mode 100644 hotel_data_bi/models/inherit_res_company.py create mode 100644 hotel_data_bi/security/data_bi.xml create mode 100644 hotel_data_bi/security/ir.model.access.csv create mode 100644 hotel_data_bi/static/description/icon.png create mode 100644 hotel_data_bi/views/budget.xml create mode 100644 hotel_data_bi/views/inherit_res_company.xml diff --git a/hotel_data_bi/README.rst b/hotel_data_bi/README.rst new file mode 100644 index 000000000..accc16833 --- /dev/null +++ b/hotel_data_bi/README.rst @@ -0,0 +1,74 @@ +REVENUE EXPORTER +============= + +Export Odoo data for Revenue MyDataBI + +Usage +======= +To use this module, you need to: + +Create a user and give the "Hotel Management / Export data BI" permission. + +To connect to Odoo via xmlrpc there are examples in https://www.odoo.com/documentation/10.0/api_integration.html in the "Calling methods" section with examples in several languages. + +A python example: +import xmlrpclib + +url = 'https://www.example.org' + +username = 'username@example.org' + +password = '123passwordexample' + +db = 'example_db_name' + +common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url)) + +uid = common.authenticate(db, username, password, {}) + +models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url)) + +models.execute_kw(db, uid, password,'data_bi','export_data_bi', [ 8, '2018-01-01']) + +In the parameters of export_data_bi: + +archivo == 1 'Tarifa' + +archivo == 2 'Canal' + +archivo == 3 'Hotel' + +archivo == 4 'Pais' + +archivo == 5 'Regimen' + +archivo == 6 'Reservas' + +archivo == 7 'Capacidad' + +archivo == 8 'Tipo Habitación' + +archivo == 9 'Budget' + +archivo == 10 'Bloqueos' + +archivo == 11 'Motivo Bloqueo' + +archivo == 12 'Segmentos' + +archivo == 13 'Clientes' + +archivo == 14 'Estado Reservas' + +fechafoto = start date to take data + +in the example recive 8 'Tipo Habitación' from '2018-01-01' + + +Credits +======= + +Creator +------------ + +* Jose Luis Algara (Alda hotels) diff --git a/hotel_data_bi/__init__.py b/hotel_data_bi/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/hotel_data_bi/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/hotel_data_bi/__manifest__.py b/hotel_data_bi/__manifest__.py new file mode 100644 index 000000000..e0ca740b2 --- /dev/null +++ b/hotel_data_bi/__manifest__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright 2018-2019 Jose Luis Algara Toledo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Hotel Data Bi', + 'description': """ + Export hotel data for business intelligence + + To use this module you need to: + + Create a user and give the 'Hotel Management/Export data BI' permission. + """, + 'summary': "Export hotel data for business intelligence", + 'version': '2.0', + 'license': 'AGPL-3', + 'author': "Jose Luis Algara (Alda hotels) ", + 'website': 'www.aldahotels.com', + 'depends': ['hotel', 'hotel_l10n_es'], + 'category': 'hotel/revenue', + 'data': [ + 'views/budget.xml', + 'views/inherit_res_company.xml', + 'security/data_bi.xml', + 'security/ir.model.access.csv', + ], + 'demo': [ + ], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/hotel_data_bi/models/__init__.py b/hotel_data_bi/models/__init__.py new file mode 100644 index 000000000..1de849e11 --- /dev/null +++ b/hotel_data_bi/models/__init__.py @@ -0,0 +1,3 @@ +from . import inherit_res_company +from . import budget +from . import data_bi diff --git a/hotel_data_bi/models/budget.py b/hotel_data_bi/models/budget.py new file mode 100644 index 000000000..b184fbad4 --- /dev/null +++ b/hotel_data_bi/models/budget.py @@ -0,0 +1,48 @@ +# Copyright 2019 Jose Luis Algara (Alda hotels) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models +from datetime import date + + +def get_years(): + """Return a year list, to select in year field.""" + year_list = [] + for i in range(2018, 2036): + year_list.append((i, str(i))) + return year_list + + +class Budget(models.Model): + """Establish and save the budget for DataBI control by revenue""" + + _name = 'budget' + + # fecha Primer día del mes + 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', required=True) + year = fields.Selection(get_years(), string='Year', required=True) + room_nights = fields.Float("Room Nights", required=True, digits=(6, 2)) + # Número de Room Nights + room_revenue = fields.Float("Room Revenue", required=True, digits=(6, 2)) + # Ingresos por Reservas + estancias = fields.Integer("Number of Stays") # Número de Estancias + # ID_Tarifa numérico Código de la Tarifa + # ID_Canal numérico Código del Canal + # ID_Pais numérico Código del País + # ID_Regimen numérico Cóigo del Régimen + # ID_Tipo_Habitacion numérico Código del Tipo de Habitación + # iD_Segmento numérico Código del Segmento + # ID_Cliente numérico Código del Cliente + # Pension_Revenue numérico con dos decimales Ingresos por Pensión + + @api.model + def export_data_bi(self, + archivo=False, + fechafoto=date.today().strftime('%Y-%m-%d')): + apidata = self.env['data_bi'] + return apidata.export_data_bi(self) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py new file mode 100644 index 000000000..9812cd70c --- /dev/null +++ b/hotel_data_bi/models/data_bi.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2018 -2019 Alda Hotels +# Jose Luis Algara +# +# 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 . +# +############################################################################## +from openerp import models, fields, api, _ +from datetime import date, datetime, timedelta +import json +import logging +_logger = logging.getLogger(__name__) + + +def inv_percent(amount, percent): + """Return the amount to which a percentage was applied.""" + return round(amount*(100/float(100-percent)) - amount, 2) + + +class Data_Bi(models.Model): + """Management and export data for MopSolution MyDataBI.""" + + _name = 'data_bi' + + @api.model + def export_data_bi(self, + archivo=False, + fechafoto=date.today().strftime('%Y-%m-%d')): + u"""Prepare a Json Objet to export data for MyDataBI. + + Generate a dicctionary to by send in JSON + archivo = response file type + archivo == 1 'Tarifa' + archivo == 2 'Canal' + archivo == 3 'Hotel' + archivo == 4 'Pais' + archivo == 5 'Regimen' + archivo == 6 'Reservas' + archivo == 7 'Capacidad' + archivo == 8 'Tipo Habitación' + archivo == 9 'Budget' + archivo == 10 'Bloqueos' + archivo == 11 'Motivo Bloqueo' + archivo == 12 'Segmentos' + archivo == 13 'Clientes' + archivo == 14 'Estado Reservas' + fechafoto = start date to take data + """ + + if type(fechafoto) is dict: + fechafoto = date.today() + else: + fechafoto = datetime.strptime(fechafoto, '%Y-%m-%d').date() + + _logger.warning("Init Export Data_Bi Module") + + dic_export = [] # Diccionario con todo lo necesario para exportar. + # if (archivo == 0) or (archivo == 1): + # dic_export.append({'Tarifa': dic_tarifa}) + # if (archivo == 0) or (archivo == 2): + # dic_export.append({'Canal': dic_canal}) + # if (archivo == 0) or (archivo == 3): + # dic_export.append({'Hotel': dic_hotel}) + # if (archivo == 0) or (archivo == 4): + # dic_export.append({'Pais': dic_pais}) + # if (archivo == 0) or (archivo == 5): + # dic_export.append({'Regimen': dic_regimen}) + # if (archivo == 0) or (archivo == 6): + # dic_export.append({'Reservas': dic_reservas}) + # if (archivo == 0) or (archivo == 7): + # dic_export.append({'Capacidad': dic_capacidad}) + # if (archivo == 0) or (archivo == 8): + # dic_export.append({'Tipo Habitación': dic_tipo_habitacion}) + # if (archivo == 0) or (archivo == 9): + # dic_export.append({'Budget': dic_budget}) + # if (archivo == 0) or (archivo == 10): + # dic_export.append({'Bloqueos': dic_bloqueos}) + # if (archivo == 0) or (archivo == 11): + # dic_export.append({'Motivo Bloqueo': dic_moti_bloq}) + # if (archivo == 0) or (archivo == 12): + # dic_export.append({'Segmentos': dic_segmentos}) + # if (archivo == 0) or (archivo == 13): + # dic_export.append({'Clientes': dic_clientes}) + # if (archivo == 0) or (archivo == 14): + # dic_export.append({'Estado Reservas': dic_estados}) + + dictionaryToJson = json.dumps(dic_export) + _logger.warning("End Export Data_Bi Module to Json") + + # Debug Stop ------------------- + # import wdb; wdb.set_trace() + # Debug Stop ------------------- + return dictionaryToJson diff --git a/hotel_data_bi/models/inherit_res_company.py b/hotel_data_bi/models/inherit_res_company.py new file mode 100644 index 000000000..f33265dc0 --- /dev/null +++ b/hotel_data_bi/models/inherit_res_company.py @@ -0,0 +1,13 @@ +# Copyright 2019 Jose Luis Algara (Alda hotels) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class Inherit_res_company(models.Model): + _inherit = 'res.company' + + id_hotel = fields.Integer( + 'Unique ID for DataBI', default=0, + help='It must be unique to be able to identify the hotel, \ + within a hotel group.') diff --git a/hotel_data_bi/security/data_bi.xml b/hotel_data_bi/security/data_bi.xml new file mode 100644 index 000000000..521038794 --- /dev/null +++ b/hotel_data_bi/security/data_bi.xml @@ -0,0 +1,10 @@ + + + + + + + Hotel Management / Export data BI + + + diff --git a/hotel_data_bi/security/ir.model.access.csv b/hotel_data_bi/security/ir.model.access.csv new file mode 100644 index 000000000..a8f8fab40 --- /dev/null +++ b/hotel_data_bi/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +ir_model_hotel_budget,hoteldatabi.budget.manager,hotel_data_bi.model_budget,hotel.group_hotel_manager,1,1,1,1 +ir_model_hotel_budget_user,hoteldatabi.budget.user,hotel_data_bi.model_budget,hotel.group_hotel_user,0,0,0,0 +ir_model_hotel_data_bi_export_data,hoteldatabi.data_bi.export_data,hotel_data_bi.model_data_bi,hotel_data_bi.group_hotel_export_data,1,0,0,0 diff --git a/hotel_data_bi/static/description/icon.png b/hotel_data_bi/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0ad91d0d3ac40828ba5a8b003dd8b90fd44c658f GIT binary patch literal 66994 zcmdqIbx_+~_b=K$6c3KVN_cZZgu!9%cMMS?>hxVHt06(|xYULVkNX$)8$GD7Iri;|hoYf}F3iTm+X4=~^THZt31w7uwy=eQpcdA?ZrxC6Y!5Gc zu%U;chPtE`%$e8Xwhgb3vn#guojcNUKCTv4j!+LqOQ@~AiwyHleKRwoy|oOpfrtjb zhU-hHoxO@59IET53AXZcw34u9mXl?a_L0O6;0*P!VDxcza&edRkzxLOTuJQn?bm$F zjDI)raFk*GhbTi0ZN`@{IFwO@SCq#}KtO;|OoCTHL|jNvgqu;2UqFP9UxH77pNC&S zQh;Alke~5if6Um~;MO*hAO)p=&4v9W!))i_;VQ|;=k4vy>n+3!gWK{6NJvQV@eA?^ z3i4oE@VNWBcv$%GxVS(2_XrA5cPqHPtA{FGu!OJ$kC>IP z2#kcfn!5LC=YOv2{hF9?%cgQtg7$=>@&GJgOfow9>{jO zu8qM+tYl>z5I+3Q7=jD<$Pt+j08J!#J8v{xPtRn@H4O%iZOqgk%#=0On`I9sZz7yk z3CY~=e|*05{x1KML|v`*tN}FFq28djFgxpq?;fo?r9)qA`JazBjGG>n8dO|sDbSsh z-o4fFTBY}_x9`u3ZVktOzTOGty#3+-{raDc{`2|2Y5Gs+|7`T1&;JV@{ui45GsFLp z4*$8h|9t*GLd^fy-v8f2%cV;9d7c7oX0v9japiDG@M{r2lhhl3%2}NMO zC6F1R(hjOrIjz`@C}4lUa~b~}2n>U%ut()XlT4I!0UTtJ?V!lrihb_d>p@$=C$foG z?QRn{L8o7t=WPW8Ag2OZD`QRBHXp48JH9w^Cr1DhyM+@~^2v%l(iVrgd%w`NxekFj zGt_Y`@yw+ufd$VvLC@(ZU%?_Cg!C zr&ST;20nA1Lf8ovk6rdnCjCO!i8n_o__$fA%bIS`c7(ExMR)CfqNdP9XDb6i9B<5^ z^o&&G?EPD||9V9x@In<2r1HY@fohKevl$?YpF=e3vMu~X#&x&c^5*LN-8(Jy>-J32 zHGA}<)dl%GR=!Mbq=af;q+9lU@a}xKeMA}_6smvcb-Ip~j@+Ds_|S{Mrv3W4aa8nJCBg5WV(kx$LRxtPuB=Ebkyt zgfIJU(_cZ;zXL@(M@j>bz zKq(*>9nO5_S!B|dbD48F+#bV;%+N0d1Ca>@_GptJw!$JlHUyA`EYelHp=#aOjHr*> zm-TVuO9HMe0QsVzZVPq1N*>}4kX{K(Dj``esMJnyqprsp1r-ff-4RaD)U3DUk)OfU zIAYPJP)x`NBC95xoE=fL!}eo~NAEQUkF@%q(q@QDZgezoy-o;^=X^cPoLC3`YNk1X z0T!A~&43rHAdeqYwR0P9f3Z*cs+p(HMG1*fQn`Z^Yss+qc+{=MpkIF8zOFAehB`le z&@=~3-jF+s4CeegZwmv7)0rKeQRz1v^wP)4<&QZ~a-#SsAVf;~f93dA1h>*s$FN3F z|ET<1Rhm^QKYTEup=>#bSNJT?1FK5SP%6{p5Ze&Z4=Jz7owgRlpSKV60^_x_GA+0| zhITsMERS$MW5tE=Y84J&zs_FqOtp^#vP%|e$b1=G231%f zx#nU~?WU;|zbI^ntYM8q!?6(ae0}O>xvoM22%-cnMUb^aUg%Z=E_5e?6&uXvJ+3Nl z9wzb}WtlWQ!-F>2!QkQR(y_V`M6mir(# z_vy=_R3ySKO(4Cmm5*MFRp=4|?|E0axhxuc)31UFzv-ELD{AtN3W^)4l0+IgHvXKl z4B>AsHGUbKe2>|>M?iM~6II-quc4ODF`I;^2^X7$XaQ-?P^fMJ#nvsWY)4F}Op945T? z*(Irq|6=Ea!^7LaE~6VsUqfxhFyH(jv^+M6uD_DItrf4*_oTDcS;OpBkIK*Qy|ETV zs3Q~AAu9BAg9N1ARJgwS2C7l9EaV5hvuk0?Zi6Lq@yrRnG^6n!?z240r(i;mQYaQ- zp4ynA6k#Jp+4?|yfd2(ldy9|8^EgZ{Xe8H3QT9&xEj>r={m zA{4CD z=^jAL;GOjhYquPrf<;lT;O-2}T-L=r~ZoLzLF|X-&OKyY2GrAra}(*+f6N4xvQHn1h6jkNGmE*Cxf;3=t_aVAAosu|q zad^#xIX1k3T>dz-rX~vb1CPnuPAi4^-jUqxlTIEd#m^L8Bqe5sE$__Hr2hddb9YW!we|j z7;W7_hhmNYWl?QWKfY07|EQk14z&6s5u_fIt6yxF>eN^TzUy+ZzrWvgG}N7nw&SLc zRmzLJ-w7X4%gRBA-OtWZF{*iJFSr)Xf(Do1x{Ps+iEEZ1;H5yt2t|Aeo-t$nkqkvv zky1p!yN@KD<>6!xLF!QoT!bl^9$_XAK5$_TOxNN8kogG^3(F`{y17Ghy%*FEq%A+H zXrJQRuDmkpiL~}o_{o##rN++Nc9!t|r+ZLx*FY2bLefXW3cIw%I5G|@EZ;wUQ*93g z%WLPqNSZKrX$n?z)Yb5{GA+|A<@p}dZ!P%#HS}f6@2JkUs_EZdt9xn&gG4d0d}on_ zKcw;BnP_}8X%BxP-ElnNFE@;6?%oRpU$#(DSKaCpy8|=iTm^NNRbJo_j+%sutsV*U zB=#K$!N>&i6;?03J&*QLZ`=(oIv?u~ydNaB zpDs3d&19KOE%KrJd~e#rn|qlzXmi6RLuRAXi1!xnox;($WWR! zfS&G&lsj@~7jc(ldy;GVsi>+UXO-IA9jtzS&;0&5@n%D22B+rh)FA}%R&@O+%&Ria z;-ewAsF2XXzVVJ`odJ6oGeW(ex9mNSf1?WcL9{;EpDL#q?ORmFZj}G)vyQ0Id$O#= zFWrGWsBkZjF|husN1gmH$zhu%(n>X08>uvbpZPUMGzlz}-3tbLn& zq-CYyS4(FE_pEf)mA;bU^7vd0f#I?g&&X6gUb%gu2%SJ=0w3JL)w_dKVl5M1FYzd$ ziP?N*pzH0J_o70Kn(#rD=Z3-gFgGp!{qu+6T4vuaM~B=?b8yeg*o%)sXEiCh$tG{< z*zGtp6b?S@GSxsp6<8OmrbZnQV90Y=E(U{%PN{gW*`Kl6C@Nh`0Yzi%=o<9{6f9d; z8IvGi?_)Xg9IuKNLn4+uH#agn1hy5Vwszz?q-=fXMwbFa{^(>ouZXLoGB{@|R4!P# zD41TY%AMgF3GE20!~2_Z71k{e$Vn1y@Jh?o(=wj0YEvwxjaR|?A6LNss9MGKvZHb& zpvUvE1TvXlJmRg1ChaX+bHOm|OdX!S$&^kkag`u&Xk(7=T3xlf>H3AKEN)vVXV#$< zi~so32ruR?&)wUtb`aH@EYW}<#1DSf#J=khOaO31^<3yf1yemFpAtSSEU@J@r=?C$ zed@-?u=P|vnDQ*^BcN~jzG5EB?R>x(J+2!Ut&!MR8zwb9gQQ|`$)>h^(@q=;Ydqs`0?RSA3E=2N~!pd{Dydxyk~c@P$G#?q_MeGuOMe? z^Zd$qvZvR?0VNqnbum`4hXvO5aoJ^%MBH{W|^`Gv>^oP>xg-oRFJq)kcqFtK~dQF-<(-Mm?J6YoJhdTSz{ z^KXrQK(x^pq`>R#i$Hp|E*16ZTnrr8TVMA{}K=-3IH zaKf&NEa$@!wVu|tU9aXQJu!=WO+KfYD_W+IU1eNiu@eLxQ1hc{ zXp+3zom*B!1fpVL+iO)0B3ncvqR}kP23MCsH>0DYYXm6|S#1^x$NdB0EzxR0NEK(s zLs8~AsMTGp(fF-DMB^Ky>0H1e!r>R7+_~MK$(rZZDDAhsCp}o@Bu$_FF@ui!32kbc z1RM*CrpfAxg(H!n-7mT@c6hfG=N5_-(U*Mn0!v7(m(Yn;_qvcTfSZ!juyhAC%TW^! z^w($0T@FYYgxkK=kqu+{pe8cFg_jup;S~))mA&ZBg-Z&iajRE9!D!7d&ZAs zvsQGAv9ym?S2R>^lCT2TrY*a@wUO z_b&TRXQ;Ef|Jg)m%N`7;8z|vEc05K1f0n+7RWEI3fTg^uoC&nP7U^IgR>wHDZVi9XHn-4iIQt$#b_jMBjP9Z(4$);uBfRfR$_fp3l4-TE2s7rgEr#IJff7;ZXGIx#FI0_n62(cV{h0@zJ6&w$iC@ekx!Pn znc4ORL%>R3SfQ55A2LG86=K}ObEld6@zgwbZx=W1H7ZUbjPTa4_i|bjPTddKgL*h^ zmYu|z)6+-^2$K@N`zghu$=$7g1h)H0_78>3q8mwZE-t^uF(!ZD>qloCm0e|#or~@V z2e1bB!;Zz33UxGImhw%~x6R?Mfz5NFJGV1!CgHE|CHFktBJxCuV2u}Zcbgz1ckerS zrnpY`>wS!EY=e|^a}{;WGaZB^cMRceAILWR3B&ZHzOGpTsCXYml&Wsy;dBX_`%POo z(CF<+kqO7yq)}}RMaJLiCNM-ny^Foxq^_}NY|PM>pL#z5ImW}scS1}k6TI1%8U!ej zdJR&erVFKZAO5>TtC(a7{lpLgKYTKM{jFTm3CpFt>8;xzTXViqm#6)qLntbJ-vo;u{MFlh8 zcMM6f#Dc7QwN(Y!o?;!)r~4lkc3d3K{#;!^1=Dg>u*e1K8&*Y*H(}%jgrR8qNw9LfuFT9n9+QixMC(FB^@ct5eUf4Ow{c8 zNhYCNKECZx?od`?@9aP^`v;!7`6BXLSwTSeikzI}$w(qK?L(|pHJ1FM8m4emq~`tw zeID7_T!3+KKU>;(P!!7D!LQDVNXyLh-!40eFWSa+xR+CFq3O4+(%vf7*bQ|qFI#tj z8JpvnB0(aeqXZ1Cix>A=YJX7KT)lW}N?WzS@A?3X&CGwc02i;{?I!~b6wzuqU7l+W zv5S_KzxI225RO-Dyk<|*vg-NkLp3?vEbYBCCClX1mXg%Z8IHYSB^APfKs@sY99IVw zvquYSy)Z4lUWHJ(42AT&SSZ||i7HuTaB(jE$;Cr4G&2O!F~dR;6HU!QYr&RRt^om- zUT*e&E_=U_v$f?hWKP7ky~7kO@ClMG7IYN9Bp#lZpM+FHgtz{rBjLIRCbn_L*(T&g z=?MOg>`>6MktKS+NuKE#? z+=b-vnrWVFUdsur_ms?B72>PuS>Er7!k=F(w}xZGEH4W;SNMQ{_}==cAgOZsUs!f& zS&Vm|phlBY&|przCLmk8W#!&lYGUB{VC>)$%g9IYe#PdLk+I%c9ADG*pN_i?oT5H# z%2=DPBMf2orWlnATxm+~5lm?-7!Q7P!DXMu>n;)VuyJ?$S1qdas&VAzVxGWG6B{R- z0tDBro}%g{)5Cs8uJm%C?IaNW!p@=pocArDyY}G^zKgt6 zLrJNr%-?t>LgB5fOb%i>l#F8QF+DpwYm=2oDRWQq2$UuG=5+Jm=5+SVM9V(6i0#;8 zt{Ua2rq*V#Ed@3+W2J*9M1E6M97l7fDp-y&JSJl>1JuSCCh(+v5}4<0rjs(Xzus3rBywP6e2R)D&p8t9EO4-rdI2wqk^{-G;R?ZII z+9hD)TlRp|fzN;bNxs0=0qyLC)87kg)SHx(fNV@NyY1e0Sb8NIF-rzn_%YGP%p>8n zKY^`FedTiZBy5K`xiUo~mqgzamtfYnjO#wzEGCzR@MZ6qryl3}Vr6LC2VSDYb77{{ zJH9Qo`eg!sbNM&;$Hq@`N3C2pD+J0B*5w6FQSA<>+&1XhB153<_`p+!8}}KS`8TS# zdSsQyqi0ra#)D*|diNhVeFDQ|@_)RT^@1{0e=BRJ)0GqwF z9W2%7Ag;j#JKtnwm8FX~9NBhgN^E^G8WryNVMRaxJ6?T0>;S1r1`S2M*LD~pJIncW zQ&hND>R&siZ-BSsF|<{`o7TNcljejX_xB5R`=Z0`H-??-zEaoG|Al8KAHhl*NVpoch2KQayjKB(SYwc!vuZ;Zx2Ntr3Q z?$eFn^ERW1>$Ix;mCz|AQG2+J$SK5OwIWsEVs8+V629w%i#PO2Tdoqh_w!ie$P*=K zq)BB&?$z?<`77TJcO>k0vDmDHq;P7UD!8>+LUj_=gP&JkIX$FfUhnLlGP2gtJ@u*2 z=Ah;3B9x>a0|>l6+KA>Ncw=`AVstPH6s-*9|0VDo(J6M}QaGRPFG;)MAh!MlKz2lv z-am$!9UC%HzFJ3(hZoqk;l1tL^u&TS(D)*MfWP7E4ju>j>3nz9l0t0t>R~$ z0~!M>PLMhv@>?morqA-%!`|3O8O zmLf-$_Zil^%D_rACM&$eHe60tM{SE-C2qF7>8~u<1I~MXGc>{fdLWOLRA8!psn6HK ztDJf-a8k+&^q#)H{;Y)8es&yPy`*e<^a^?8r~~q4*{|^#xT}90#>vUq9*uyQ6o|Cm z%X^WnQb;sj$fsF9@=ajZYAY-AL%B$voqSd-{Q`<)O(uqN3bH}jGtD!nssmO`EzNz; z?)_`J^qPEedr!MB1xT*?I8Pso@Q{ixW^|!5(}qx#p{!eGMNG10AIqXB#~AkVZwC8cck%JY<=Nii zvbP!2&>`8%LjTU>@@YPWwu1m+8qa#FEZ?KuUMif3(I0b?Scs0;_bOcO4rll^R_*z+ zwT))JW%5em0_UE(^>zEkdY zd7Wt9+q;gN9aFHjj&=BXt@bja7eeLT!%Ss8PYdW3A$UTgK!*nstzK1Og!8_?F5fNIM=SRjKkTTW6 zgzuiNQ9Ucrr?ZviTv5h;J%yt%t|k_MAG1 zMvbuXHoJ$QeT>mTeZ3UJBnn-P9CE2$5!b=yi^7mdDl^}!LOzD=bTf6>Dm6mI>8B%v zYt!4iR@!T>r9#@(+}GDPmYlLuKdW=iD?-i#d%`eM%wUUSB9G=`0gFqKu{-v_)t~X;Oug=E>EIn{=@X5oI3s z;>ynWi2P*J-o>HsN>A)?h)=wHgneht$;a-b2IqKZW@sdDz+!K8 zE~pa-5KS*@Dz7OkZuyj83+mPeJO&o1Idi0ABQ45_VLWaA$;}_Ildl0AEg_yFn1xo& zy4EQLBv>Dj;_OgfQI#s3t1g-KjXsK;oA-X}!=1XH_ji{+j+R`R^04MHnbW#1PolDA zPu7o?F?7-f{^+ff?0|-ns$n}}cEkf6*Wp+E(}CmkK+YrOR`(Va)&2_5TGc%;God!+ zV+oEj55v(OOU`e=5f5xWczngcG+UnJFKlpH^ssR4gm}xYh-2`IT8}jmFHGL$q?ONH zBH$~`!z$aUj8L;o=iq17mjB5n?^iSa^nQQut=$Lm)oM-i541Q4^&?qAhcwy02*a6} zIzrzIf`&Dg^-Evyan>ll2{qBv`%_XwT@)|znG_crGe$HuqwHa7sQ0=1pt$wRj^1XU zvzRu6aIs6f+)rZY&p4vBI}(UQ=YlznFBa;N-FwA4O1O`6yZHeZGxnR~NcDPB~y z4tIsAv5<}%ACYYS0vj0R3>6(1%3Z0E4_sLTI9|+fV$HU^1oNz6?{aPQU3tsh5c zK-%3*u%{vvn61dk2OH0hH&V{UICb!FJR_5mbVN}Nd97!sfjIPaJKAr&33{tA(DJPF z5{!amDv+E|*LwVJHMGd&ehf06fQ-XMY)#U!x7MR(W$*gEF-2sDen1PZ;O!#k`AebA z&1Gk=Y(v`Cy7s^&uHw=nGFQiyiLlK2;T! z?9shw6zWX^5T|ejM_)gBP4bhx26d((4f+*kJ*l3yXKLM1r7D82*RP>z{%l!1N)H>grZAKk5;oB7R^45Wwo8FK_idz4Uqf!qsvzY-g$g zg{quhV_(-^HZzhD5bXp!IpoAH_Qj@Iv-kKPHu^e)C{TNjvAO6Nj$$jUtG7*fPQs(UE9VuD<^<#=%3a(;qDYmDc!vuzL8YkHD zpN!YdjJyNix;em@#Rntzo5-S)rt2>F?VG`8iTL&74kNhTQ7TGC$Bm8(_rCNs zBiSvpEa>iXtR+rOmC_wINY{UPxk*beAt0fZ?=GOl-r_D4t=7xMr8sFMzl)mM>etYS zoAKW*FW{_f`2IFpCBu})==8b8puAF)V}Hp#W2yIk*b_LM+`WDVfdp?J`B7ps7mQ!m zmt>rYcvFNe*V zDy9A)tRI;aSXg;z`Cd9dX&}d}s@Ym@n*AD#+A0OSoT8S5TJw?P1 zt4PZonFIhfRp{+iLp;FS?|;u%#x2ph;-nknqedwi`BA$|a`dpAM%l^}`Ia|K6{apJ zQ~hlduk&Xk7RjBBS_lN>VJ0Bv=@(JKbe%jrJdHt{eOhrDfYa%*H!siQby$?XX=5{WiKf|i};da6E8HM(vdqMQA%Q7M|{ zkv|g8972rZg6#s}%Eoy!F1=S#L$w0n?&baS$+Y^N$^Oo~=qwDv@a=E7;67VCSu$K6 z*$D|!bbG{T*YoL9)@r%jSF7p?JN9+SY=#VKs9@{0g19RAY?qwWEUjAQs%;mM$#qEF zFJqg_ybJGI;n7KFQEZOCw_4AFM7;U8?1Yr7mkra-7XJ>($uW_>fgXfAnQV2eBKU|Y z)9k`L`0Nr<97fcfo7T9r(({LtJ@%02%n!TeP4F+31;9KI<j+yC^N|k|xL`{34fgnRiIC0Wi`O$mLAFSm4wi0qw<;Lcou)tJezN4S;9>Ky zX+T811DoU|%uJcpqEYdSz>)YE|3_zrJzm|n&F!sX5jM}$g%c(|VF%JrLc^O!QyvvInC%Q%vCYcOsR0Oz zcLfGdwECNl2QFqYn1nSuCgGil%B|mH?EcmCFUtSI*t`SIyqlq8kxZD)|)+&<_5t= z!&fVNscyl)Bt)q2!_zX zgwqfDrPfni&U4Zp28zB$kylYc&CT9E3*K42TwfNH!|!1wLSGQ*Gn4L+As2Kx?|;10 zzc({FWOvxUCN$W5Hk)qnE~2$bb!Bt+bgb8)u3oL=G(tbmzM=wd7*nNoFHrZu{5Q;! zr~o-Gl~VzgUIg=59>R&5G<#8W>{n;n>U0~PGC6cojP zMZn@4TdY6@p9Q=>?yyF{a%fq?hwi+U_(kgA7lIFw) zore~@Jc~TDHIvH4*uDQjmWpvSd?x*?%C~y=EYo}L;$p=dTi1CMe|d;`1D0(4{hg(m zdAdLP1U!j7v}zj8W8{H1O)?L@W4uU=>V?GWuvC^X3%*Qq@~^>@<_0B6R&~=~tIkU))(= z$j)Mz3SRhX{Mp7`m9=EkEXD$R(6Vz{ZPghI9j942cT7_Icl-U1>FO?Ce@X1$o5&wr zk@CGBmNHO|DxEkLcAse^i)sfRdFEgoYMp02P{I63DkiB$*DB=+A0{yI95g#w3yj^o z1seR)OoiLUUUeS8YLM5LdQ_jqU?63k$-5Ho0W(>Fd8M0M0g7_XH%X1}0(jSoIc+$J ztRG3x7m#@c+zWZxmRLOzAE&M}v)jk7+Z(h~Qjrwb0YIbkcxbfv3B|swGEs|On4&q2 z#a?i?)EC-Cba=5eCfP6)@dw+&R!paA4b@pKooC*XT_f-1>~c{(#7U7~4aP1q<2SXX zZ`yCeSSkaF&E@4~w48H{0(0ZNknw_*C~lpy-rd6TL+2Tfvg*7%K%5p0!eMHxUypK` zNJKAqKhgaBWu?>5{m;t=9@J(Us@JtR-dpPqmDo~KUS;Uws2?<$>*X_823l}|1gg9y z-f&yq6b+bbBkQf6Fj3U0FEKSO>)&9jKobB`)!8ZP{K|GVQS$;?pHz(Zd~PDPI>tl! zA;!AT61#z$BFvX&1tMOBi_@4lx@z&Sla5(N6rvQLc95_a0b_tK<3W{%fX72*-RB@V z%SaXGI=7!bgVmn8RY za)tppHIU?@X$^&?XT~J-!)wAUb4w<`Ho9v#C5*G;Lsp;>rB;1Qo!$cj0ka62Z; zGlGSza+fK;yb5z+O|1ysFVu_!>d$`E_epR`OIxRAqi-c_lAL{kOi)^GYwzZA zw{o(igp61Zj&4Bb4A_XkoSh@u7kb}xA@?Q>nLT~|=7&GColIGYuuC~Bg#hirTp0Kh z4#Y56w1?ZL!TO!!XU@bjOc`ZW{Vp&Oh@@Ozeo~nabF#!R>?>Qf*j@G=zMVSha1s0@ z62+F*Lu2|lQ8T??)3OrGjCz7nnpcY=V@^^5m|bK9GDKFjr_MDX6`stC3{=c54Iaq< zSiobFuXKV$fCG*%=-4jVE}9iMDK+w`Sud`HJMrWgFXMNO)%nVInIkby2`VgfTn*u8 z=TZ2XAXzCfs@QiN_Q&H?H9*CYR(DRyuV3OF!c1^MaEY>!HDJXZOrdIFs;!oZWXN=mKbvrf@VNR`%j&q_3!YvKXmQW>ifPQx~!qBjblX8K({@O&S7K zz9}H$ti#ybmw2q|ab`j|3Ze2LSV+s%0T{8*(=^cka~^v4y-&kr5q{XSc|&dr4RP?H z?)Z;Jj${>gF<*}AUWdzpoSAe84GQACUC&5Oi1Ri`Ui{(_^oDJTKja0UQ+N3Q>n0`w z)dEX~l6Nn4H07j(&wP_6!qxi_@{~l&XQj$hc3kTOQ3adzb{#x+mM8AoYu7tzZS|)r z*Cv02kNyF6d)_#Ec%vq2yX1%9G%5)QZ&W@!J!b% z>+Ux^bAG$ey>^u|o)VFPC|D3t;}JntS6%1!k@~-E!rLrR@Bl9t^1_j#1VW*CqQ>Uc z#auBxx?w7OULIcSG}`^)KQuAGoKHex@7I#eyqYNq+rCjfzF9+^WTC|)#;|#;E{)tY zwgd)~eeF_;6VKYGzv_E4rdq*k9_Ot{wVTrog8>b+n*CpEZ^d>Gtf&B%I;kTTqUpd3 z|zZa1ml14X&MJ>WgfDX5YBs&M+S4;G}afd$Jd`=VY-RSgWf7N zH8nZk^A6kCOuk0Z*iN!>R@-o;PUE!nu*K|EV#5YSPJ~wtO5AxYGWCf76HT^x5kuB~ z$AVC4PRlFlWV8Bc=POq6tY!hm%Rg^aI1qLK%jmb9wFh6q@JvqnJZ!SwG z@RDeo4Mh}z8c9pl1)syO6kZvvngW5MWBMt5=MyYS3K4%oNZ)pVZ&N{ZfD)fm^H^ri z<;8Sk;?2oz4{^BfWF`>FT2MfeEh)Enl;WT!RN0<7FHm?Cpy)f1NnR3afIVN$Ty+qH zOP~{ge8Gk4nRvB8ULb1g(^{+2F3a9smID>7mq}S+aupJfB?y&I30KB3XuD0N`Kt)O zP({xdec8_0u8}*R_a1Z6OI+C}(-Wr2G&KyEzeGWUzlBcuOC)^EFekiUDX!%9K?fY8 zsKq6x{|y0+K&H~pN#Un0MAdwP;9+%KSoWMJgtVO#AkE4Z{F^< z#<8$xmPXj3^j@a!3du3vaX zlBUOI8BBbn5SECzCSV6yS^~2!W$aNaxZ4^&*68DFvv;sFcOT0iKE73!)>+!-%8K&+ zPOYFa+YOtLmJb^rTMk;AU@cTCoe3;iML~Hmm*uXB15XS>N{mQ_?g%~ z$&_k^8+Xwr@4_&{2efW2#@%;oc}4xBy3X%<{kvLWMTQanrx%}ISybp;w#qUeP9b_6 zd$+u|X4l~2fP@TvH&RV@obY$qerGY&c|sGZ&EB}ljnb8_m(vg8I-|#}n4YPE%06*K zMyP~Fc64iLf+tvxRASy1=x~(0a;2+XKgg!13-)pqeX5rC;uhy9d0Y|i#*szx_+6dz zKqNH5*kIsS>cP!iyzce)OcC#?bd`*6qSI4z*h?Ei-ak%F1QLKqhZx8}JKkV`mrthc^*_B(7){if)-;Eb5W$>3n)D7b$>4b^ z7z3^OH+S!VrdLaA1c92^3lu-c7pYD7%j05YjuyCvZcA)9d3(KyLJUSKD^|?&tCdYd zR##T{_vl{$RU=Qenu6wnFB5Mb@TBr(>CGJkCaSfF-_H8mOHHX-NM3diY|LGZN?R}C zga?nzU9f3hb;w=$UB)&GgvYU%NqO44+tSMG(N}W&U-tRdj;|OWX$@!&a{I78mJwjh zTsZZJiUcHx9aUJb{D4Myq%lRT#F{fN%b6Z?v*Ze-Pq3$S+oh`W7LsgD=^7YEKb$Kv zH5FVlGYq(J+KDf1QzHf3+NLR9%8OA2#Yd)ySRC&Yuz}vNaAq|Rewh5Tapjw9v_ZN0 zKwj|uwrzy%oKNBO{1>A#n`$gebKWn#TM*|>1$N|C+A+7dHS8|09!{IfUF>%q_5p=i z+oz3#qlS!5vagp`7y@3z<3|m5<>Nm$6d6#crh2ADq^Rah3LZSo&1hso~0?p^MI>g)BLDc z0(PLtrJbNFE^JvvX?!}@NBV60=U2Hmt+(n|d&Zc_tZyTiSEXs|Ik6LX(v7{9Vd6qD zcwozC8gyX-1H?wjX1|(UWcViAg!E6;FYR}u92>@7(jtpgfD?7P$z5O$Dze4X=QI|` zyZ6pm=B=*Os`X7x^*ESRu}9kyl0K70DzsXe5Hxl3Y8H+xR&U>h-6vqf#)#9i3JBI@ zTiokvhp%=^U(G58_q@W|=0{S>vobzDGbGdv{0k;6Au8ov)*P&BTc}z1GGv;UyZ6`( z4gWKYh<<6s)%5-Kl&;|v8<||-=5)vW9r9t4U_Q#uOJY&bZ|WgM}az5HCJv}?a(e*F%-H^10N^Y%2wrb~1G{7{rMvYp}j zpj9a7)MJBI`?UceY);c>NBtf4eycVX?Yq{KVfOo0OpNl1vp8*EYEY^spr_~X^rf@9 z&(2)&t@yK{0?FTg$$5+qY}rNe@jSvkBq7B2U06*$fSJ>JUC1j8m6xB67|hl2i*NEj zu@;PC?Oqo&2Ek*Uiaj_})x+~DRfLn(S)arb zbuQ$nBvDR=4f5M3&x_A@N@ST|WH>WK8Uhe1p>mJa+8xl-`6G5o_}Joj*_e$0#}d4{ z`?rVqrkDR+(IoktE?lA(izgbl2FTrS0BT!Moh@{?q0Qm?T;`(0-Av9DSFcnycxQE# zOsPax7eFKD=iGk1z(q3GIJfNaQGKFH&n`I*i%sPHRPsUUKoyc=Yfgk=di20S`>(^k zpY7l@ivhw|w9K{T6;W6OBbf$I89qZOm^oR8CNjSp8^*YB6Fm*{%vUv~IfHFLOVnE>G-xJ}#@9wj3=@ zdRR7Dq~l#%J2pOM9r4~I=Mg;RgALsGVwWvSDbGq*Xq-y=qsA@AjL9goHNbr<27ygylsgH0{LNK$ze$vhMB82Ox7nysyPA;RB&5>v4p!0)vc6>=LJy_7FFI1; zC^|AQNS}9^KO4gr4{%i#NJQuC>;EB$`Q^4Zx({)F3k}W>_TsouaMbcNSo|L(U1dO& zUAG-dT96iyk{nW6q`PAn8tD=ckZz=<%b~j&7#aa7=?3YLlqnNxeO zz1G?dA|DZ5pAx4W?Cju<4z@%8REP_brUITW%Q@9J))7d+95M*B?k{A&(i4eX2>G+q_8V+w}7*{HA zpzAf=`ESrsK5bXhS9j%x3A}A}WtE6L{{9F>!GbIF;PLjmsFSO(NID+T-B+8MSjnsTzolT*d&FIbDcV)bB zcHi5X%DFgU&v8+penuqvT@fI841YT88VGLbKIP(Kpy)}`J&`JgPo9=Zo|=9US|HgJ zi76)>YwbDqHYATXC2LCRVVI9a_7)$ZLUoVp$oAy;e4VoesG;eNS`66#?FF+nJT-Es z@@mRU=RcoLE2+Kl>L_owH87a^!Jd&$PT|rVUmCv=>cX!^6H@u#1HC1^mBo};lYuLM zGpDYz;VR_(GbU|h!DZ+9x@;$GJ7vP$IR9=;m2)VL5 z^X$E($;L{(e}fj`>dda|5XaTifrPr0f61-#P@2@2(ocs~PscS<|4u}j#!a|3P40`U zlQ3n>Tjits&_lqtwGp;6kD&yx+*#XJj~o8*Pxe?@?sjF7IjP3! zSs7JTRpbADpdtr)HTrz%b!iAVwST_SxS71It!iQ=U8CC&5Yb`7V)z;iMb#Wt!#nc7U*d)|7u9*E>B~p|*!0 zL0Vq>zr1^|#_MK&$t-N#vn%0CK&nae)wgH8-pbjh-G{3^FXP;j78iqYZL?r>z1LxT zIUmWdOjQ2^MN^cZHJm^G+_>XE3p0~!DZ{As%8V)4 zIkgdBAJT38W-ha%ZKUj-0=9m_FoXU`m_O%_nBu>xZfCtimDQ%r* zbIpHJ;l~S2w5-|Vs09i{kpGsKAi_4`+l!9f=1(4JM-k|FpI2v->ZD<9)crdjytlgm z5mS>V)}#A}mv5FXYdtLNYvHxr{dr)Y;h(D=P4$;u8II4R2Xeuk7~TcDHZw!dIc)-Q z4x2)FzSyPU-0Bm0P$CWHu}{*W)k%4wwp|UIUMyR`2Em6feMuIoV^KUitrpvH0!$a% zZLMh*V-`kMiML*qjx|NPv$KmckVfy-<`Y&7v(*%2^#j&g27}}b`$SMA&E4a)L&FS> zdXwA1?8(ag@y*pVv|gxuasMDY;QCXrDNp3oZUv%Tm^!+bahvqx)9+E4)x~CC&bU#m zju6!h*w%~Aa53S3$FMRPZd^BtMq2I%3!m=iCqz}_4_<8jx;;puo7_+7sMmt1QA$!>H7>5&`b8&KjQ%x)t*k_#tu(b+hBc#B2nGvg=^Mci{89UaxOv1M+t zZk{Tp_S(-b&AmrMH5zmB(`>@%G;fqr`!5Ei_aE0^haZhyjEibUa}Heyw_=cB)e|iD#WRobdqIIjKM}8?T>mMSU93ehuJo>RtDG3Zs=Y zV>_xW@mw_WG&)q>CWL*GGEEe*0%~pSLVi99FXRE^$UUV@k9~C6%pf8)ZuX zsG|JMOPFGWsjlgTj>0R+e_ciGPC;kV1ZMVCSz>#E<3DF z=eL#RcJMo+?+SNqf^dNquM>2~R*z48Z4=Zw;0P()STWDzz3f?Xe4XqruFs@p8O(4LTk(y0)s+nX#U(yD*6Xg*D#siM^xW z-IYK|TW5o@7;*H&R={&Vr>N`Y`i9)7)dh)z85$@a{!v*tq(`9Hr?RW?`Fs#13&H-E zDJHsqwVj7UDn&kB3LIO^cy*TwSQbIQbLX`uJTyghl*2+KrJ2*1j7&aoLQcx#*n}DncbD}-1R!0N2=>a!Thd!SJ zZg2!qg5ppEJa}|$qwOR5_3_@`F^~mP-2a|UPJVu%etKMbcsOuuySNXv6Zn{I!ChC2 zpmvUQ7~m{~NcNpAk+vALKl*gcs2g)Crfj~M0fb&}Y7L^{Q37Le z_>t{;@YZfVQ}Q5MSNz16x2g;&Z_3JjpC&Zr@UFE!!1>#T9nGo13A)O~?QLy{Q5D|q zSfAi_8|Q|@T!HPStl(~Auj{=o{VdeK(@61P6L!ce`u$PsE^vbR7*;tT3%*!bb$(Up z`S2K5)hfn|+JFKCe*IaNGVtk^1URakF*acXZ@XS_J^BcX;ZoUW$1>AR4V- zwuJ@q^BJowl0NW?QMU%VI7Ec>-}})&q%ZnR0`p3LW8}#DC+`2uE#dUCcDfz9qxShg?fLX~=i`9lt3*kWZ{LTv03IBIo&DzTnU9!|+Qa5fV+pBYCt2Z+C(V`n zaHpS$8OhB9Wf0+WC${m&)7u?1mXhNXQYc;8Rp|3(hu_IU_v6jE70bn#A%os=AU^cJ z?Rp~sCnGrDzN0ENymm6a$-X8@NGX%;>wDTdx~WtVzuWvP$-VUb4+RdfV51~Q3T}wx z)YEU2{c(&TBl7^)=j{8ipJto8DHTp9W~m}q=b^HIv0Vp$Bl5Y8Fi0aB76Rx*rV4WiL!7;Ny)B~wuBCr=GxLA0i&^>SpKLa%?!u0Eb?q94H5 zHlG(2^j^o;eV-|0Wv#P+T(4+)BY{tnR5n>}OB=o?zPY_CoyS{QFr;riDPauy!BP#; zvZ-aEuhwNQpo0#Xf4LyEJ+D z6H$+CfKtgIYf|MO6e+7Dg_7ana0{|ojh$U1oDo!$02~kmjcB?Q^`(IJ^Q>kZAT5l# z#svhq=bn`~F{<}8+E6xxnP4$~#Jf-zfX2yT)OOH*IViE56 zIFb~Xw6OGi-MAY3@>EIin4;vR|G$h5O{<#HnSDs2h^hLN}E5)Q<~1|vo^f0AE#V7D6Mt8yV1t)DQG)lL=gP^C9;6vwY6-jK*dvuhfDdj z{Y%d(k9mX9zy^8p+&^AZ2RGcYcQZ$l;S;kKLAy8T}LKssS7&gjU`weEGVf6cbPlviw0YNpn z8=X$+w|>H^*5`Eq(hw}C<3wI#jwEKT+(il$6n^d>7kh+Rw|_%aZyA4V@|y*`MYQLO z6odX;@gWrvpu!Xzt2svX`x#-jyy8f&;2`&OJ_YM zA)p@%p*Sk>DH?a%uPRTGmQ{!?@ouh4dq+!JcioLC(jxn5Lw^oLfgl-*dFlff0ZeJi zvYK|i7zeKV`&ccfrh>6biY8y=1z&X1X3l86*^-T*T-|yj!P1Rj3|7?2ALi*Agn)?# z(o0wp8A)589S|Kkg|Png=EVwW+dQ*8S1_`BONWp@2P+YyPJ%!Kehq#_4-NPu8++Do|pTl^eR$a zYBd^pHZjY#+}l?svBjVEf|18Zg;b>6V6q=0)fULYK9yG5FE2L}b15qhSdi)eRKueu zkp6L<+w-Ntk^1v+*uomM(e{|sqaNOBN7-@@x6a_c|jM45q%(+Jz8+5 zOq|C%ayec3VjBKE${2H9QM9`EfWb%-p087(HrQ2&-6*k{;T;YS))WTJOyCAJd8?MF zx3=g*O(&PDNYsMn#f4FoKu+s^hj_Wh8+eTZhP*Bis~q*b!#iWAQLg+ZTck~OU?co{ zuAKPGYL1gqY_Azd08Qe^S7?NCO5ORY@Z)Lc%CYazZ!BxB#BWU0mm{Ipx7TScA$ ziMgfvMNkqm?9FS2ZuJNYx{P7iTFsfTTHm&?|$Kf$* zC-e{t9UtP}-z!dZFpi1CmLMG#q8{(s6*aVi3#yz#{NPkBf_>MYs#%q_UGA2yRy3*N zG?GZnpT!@jZJ^l0SBWyF44X0>&TzX#dO2%S(k}IvlJ?P9UJ_J&m>wUrZ?AGw?z$!p z1RRPXMV{lb3W?&_CR?TmKN(D6TPVmnADT>)&lD^J)(Sr!RwLJ&oP-su zsPWgLhb<;NGxJLc>~YsQlsW5K3hv3Q!1#k2u9#Hh{a-3&ZVvN({ES1|L`5%B0v;P5 zQG!E-KnQ)mpN$Q3sG)YieRyOCMIuckW)*^fKi8()m4kbu-;!A6tUGy{*xPqf>#3EZ zs*4{A%}lItl#go1UywyIQ8$f)l7{PuKBhx@>+HcQ#U5TJ)cpx8=d)`AlZi|T^3_H4 z#5(ct&a((sDZ&G=_ozz&$BFUdX3X4*msrN=d1z@80>Tn{u;uB3%l6;t{WDSON#Der ztwD=XNpolwtju`re$#>y+$dX&kC}PS4(jJ>#s9*@jZ-jN)0d=NES2Zrw5p6TJv~#{3tsY-ROE_ zXXVb3?t6+#^IiF;a67L;vWcBK(bhGZi268%#NWY7ITXUFx{IRRj!c>sdar+DS>B0~mS|@bou!c1&L1O21>NZ=TimUGZCt><>)$;--HZhYlSWF8 z-=c=S@whvA8N-mI;GpCYuTI3*vWC?+)j>%wa4U2CvsKJ@Z|A=QaL*yBBj#7V6NOOS zWdzA2`7ZW;0WCa^+6{@F;_;n`I#qug1)1WbGqME zfzr-cKqgC()0KzV&(l@^OJ_Ee_m5)1(gdpXB_-C*2Krd>RtrwTs@v!D?}lmvo|Z|U zH&*?uZEb(jtjchtcr-Ln{h7k@1AcU{siXsan~X#)1X?u*H5is2zVqUY%ds15Aqr|* zL+FM7w$WlNsG+eICWu)f&$+JTAxX8Y8s)%^RT)w&K&DYhd|ObkQ?;`1afeT?sP;6Z zCDgJ>P4;?OzYH?4H5cAjaz2PNav@pO^8TI2`r?&t;5Cn8(WJi5LZB_7qiZb=O2Npv-vLeKuG&D1+A}d6qB^&_40hl;dJ!u&v)G4W8y3|A#M}&rs+vexz8w z^vG!(f;5IP8Devo3hBgi=4*gsr#}qMpk5M!3gJB%oS%y{*g2sJ`k61SRT^w^n3smJ zA>vf?sN+=g7t0;@cxocorJcFsn()cJ%TT41D%@BLGH)sW)-~LZ?fyJzOZN!()UQMv zv?_~!MXx206Xu(vQp8$M&nyD7vp#d2#m^a5WYCM$*LB4X(#6l{|6<6} zUnE?}_CoO`QQ65tuk4lt#Guttk3FU1biOS3-_78b^D9x+R7MU!>E(QV6mWN1i@yID z;n$GYarZl+pUO*KaL$Y5EkQIqz~nT?*yrEUnsoYzgFL(oFx&_sN}Vp8dxc7Cb#-h^ zj?#~Y92lij*?#|YH=N{>#)j6m;X?1pp=4$4*C{U;$pz(?nj~U3>Yd@UZZXi;Wz=n+LuS@RB#bj0zhX2VOM)2Rm{K^79jC+Xi@Br`J!n zP9;@o8*R@3R4N)28Z85bo|Y@wP#PG?Gbjp-Q`9&rwk4#O;G*sd z9sJ0A#TnKU-_uFhhfrR)+MVa3mdnw#X~8ig_T=^BNmb5=MlxAl zj87nO_>bSEi3t$F_@B-f?PL5&6U-}zDfCnH5ei(p_jKm*8x8I)y@shU@Xh4pbiM$r z-{?l3*UQDi*}~q}*fA~@b21(lQk0aWnR4=yJ#-D}@+XcUKxi=ghAq+88koF)Fh(8@ z*t;HFp(f}Q@{eCE*z*H&Jo9(!g{V^NGI1wNJC*dBy$UTkMJsK54>zli{yr{JQhr$z zHcPILo`89w?mB*CcAGQBnd~c191P$k!_^3gAS14=4KEsUAmk}!AO~{933kkag{@RK zTOwF3TDqFrcuUw0Ny5XmM)TXV8xF(TR2BBoQ8WJDrKN{q>(%`nx6Y@j7+Ss9?iNvQ z7N5JBd)xk}mE-O0V&5MhFf=R5%J$YHBFdW4BnmlRMz4TvpA+dMU06( z?DNElJXGg~-Hj2{>18Ey48 zW9i>A_dfm0vhMiZ=;)Y@oHc4CLN(rVdFc`0?%qi;a8oVFkvwKXIkm7mV&y^>wl1TD z1*Y^8$})0o8UNVyu;DR|H|m2=a^3CNr(_cuOAmRn38L2&8FfpLr%zMVAd;El?f+8V z`xQGNW6(lAk;o`bo*uc=gqiH8@5c6O>+St~kN}xdPa-{?{yulIi_G7b1+uhBrex{k zGPE#7H*is;^<-J$ha@RM-G8X!@E%%5GOg;6*zowP_x5VpLQ4~i;B*blOFX=s7XLX4 zH9DNb-w4lIqFA<5x>dOL6|!L&i@VaSr3`#QO_+!by6Dx~D$E`VB)4 zb;JcoWMOG(Sy`!>t^O^~lUbdep+(Rak|yU=lg`tZo13tV$D}EqK?^$ams8AWA=)3{B^iq`PWyqSCdMu#qb1iI4xH`|!LDRl4jOx1TWieHtjmlAZ} z{kR6*$dqY|EC8l0#%kGK1Hhy3(A70V(Kxp;JJh5bpdGFMR<7l0rx+BLmb&+k*80NzevL)lR~T4rSC^O6_9&}>fwQDq1*)u z2s+-L18y8mj4YL(!qvIM8&M%6TT3gTUT0@C+6Qz;F5!b~**fUA5$6T=8Uw04=5$G; zcE0*dqUjC4-CbJi&qs`jjhKMbSYDTQrF5P+1_;8?H%}<}HxTln)H(QC*SIQmkmwlp zfGyqC=}NM`HW(#8o#qNG;NMdC$c5iS;4kzYv8UUyQ+bIP+ahbHL1|mV+pX)>^z@Um zD$$0Hn}I;l_0*aDQ60ZA3+||>C>_V;W_OR>u}ynHSoWD*9;J#Y=O=n4%U44%#*Zs& z{2$JVcU`w<>`;=Fj6yaJ4$i?dfZ;lf?63n#94^fTPwhaBW6c`#}oS^aX% zC)XKKT8jBTHs5PojT9raYwktAqw;8YlFX6?7xB0I#I(To<4Py~m)5Jdi)mAMj`s*g zMy7!K{RIz)%W>JigKTvbnkLX+kEnLjgzfKz@2k#Rlk!Sc5R?~8xiU!c@caaflwu7` z8{*pks=3oInhiPdaV+Y156wxFxPvR3^Nh-%4)4nI!4gEp?Zj9tds#VjaDxY9E0Erwp%l3q4KgNbr?F} zoQDA>!_lbzAghd#)@}94-hPCs#fm?p?E{x5BEXX+!DtLhul;I4rwTWdB9oVStLfH&s(Fz71FTc97dkyz%MI3is){hhN=oB2CdGeHs@ zvsoLFsK}6dDpnR^-t5Fyvxe;qQ5KxuO5Js0OO$7Kbl9PF#nTnQx%j*FLALE!%@6XGONo{-!Sr6?y69Ez>&9xX-!lGVRyvzjx?SG!+>*cs)Z#J>83CWmbh@X_g2?c-%nD!>uW(f zJO1xMs4^N!`k!*=lLI`-ol(^NXG( zHHtaOnWzy~W19%Zj?`Kl&kQ&EU*8*C0$f839lbOoJ5826VqjNGzShFQ^!m}8;7nN# zDeEyTGt-;hxEV(;z~82$VqR4LsApi%5+RbErrdXAME?5Czr6(yQL^;0x;|=?{X#$So7ZQipn$B@4(V@Gx(7zjub1D^a?|Gl+R@gObH=;9|UeD%dJ;i-Ae)n@nq2sCAYiJPM!|6O#j~PzCBP(W`yNeid&%0 zy8bsUPk)5PLB@= zkEgp}r75F%Ezlt(@zeRy)7j%2%^MgvGCy(90)YH5o)wF?Q(85jcG2JRd>Qx)V1rwq zp_ued^&-)VUw@_BCojT>R7mlcDFyD)IdP)ta4Mh?sFgIT^?ap#6dV_S@lcI?cG^NyYmUF70Vk7`mS~WAgX}lO?dusXZ)J-4X#WsE|N(DK16yke+*S{~0MowIGAjZ+arYU;|na!ERB{cW8v zE_c88bm6zIxzPC^EzjHv^wp!$SbBr%Osn#;Ef254Xd8W4$bxTGG!(4)DgPvlT2(DK zU0uTtYNW}@@j<8#sv`kc&$k&T9hbG^jfTB5I~Q#(#|6Nj7XnpFSP9KANd*Gw&tJok z6~m93Ar1D>s6S(+s6@!_R<%ApxzgaMAc1n^=-M`} zMIIfW%@gluy7S;v|q=5#$dGr=Hs>Gtk* zdV0XtRUK2@n~8%fyH+;9xO;S*lfz4_)%)@2;4xdCGW{jUAD3znq7ZWb5TM=3O$;pj zC+8rI<{v&V;s#1U2lg9qG4#v-vtwN5f@}~YvsL-$rdwx)`!%kgj}K;$?vZ7n_*&Q2 z!HHqZRp%~SN?>a!$jP`we`_K{5&JXBck(|LH^#9*)#VFp%@BSfPV=YagaQN zHlmNl?3>VVtx=Vuv%^d8J8cQZM8b%|)9{n0OBgf~T27>okS&>7sF($sn^1Q=nm#WP z)DwX0$zBI832+l9<%d-0#|}BMb)RFuGVMby`|nE2vW6m;)+<-d?lqXbfQ~jBZq#w? zZW)ZlaW37SHMAfs!^ZUGeEdcuq|p0Hc1Q};KVX3Pd#l1rhcyZ)9e=Y>48@GPN8!kj zO4c+oiPZU*ssO;@MDx~wtAn)&Vdv>s-_LZ#mQ;w_mix2Z+oa#aja2^cC&qToekBdy zw6vz6%L*q*3ra|KgMRh(L#Fji7v{7bC*U#q4XS1G*79wMHsw_l@b6e?c^YMZBYM_) z>QQ0sL+Zy)Sc^FGy$}X6m?PD?yZ#HOH0Y$EjwYZdUu1Ho6yOq}j_dvkk+da_VhAzr zK9wf{@rO%CuHDuYr|+m9>6BwMtf`|0ZZs`eJlN-dOy|%f2pP4n-)Y%oROa8+X*&Y*)#m^xk9 zluS|$+qJjVBNGj|xxaf=fb~uWt=vBz>!O$b*0!fQntR$n7sR$Bv84V(Z zL|)vQG!W>JH`Q&9hj_b2F*Lt@^2eM5NuQ~WkV%OWaUFIvmc*rESH)ZbU8R_H?Sct! z@{q>=ebJW9_ek%I1@X1tM89H_!B!01S<83jEc&5K`BQ7Do++-pB-Cko7)-P|K$pZ1 zxZc6Ata_o(p$a*9c~nHz!9|gII?=W|sDL*bR+0qM;;dNq&PS!}KU3I)t}lKzk>!>` zi=@9hhtS}^=6Eo+ApkM&<2Tm4(ycnNb#ooDOnme1n6`^OIe78@|9f{p)DXF*zzX1 zd2l4h@62`wXzTrbSNL8iC(}P3JjN1y#oxcpA&(TyT z724jso;eqeh=-+(a%)^?V|3#V*M=A(Wf`Et-QcU9w*%PYeuMV>t2b!CdzqzbPNuE% zscl*e8G;5fK#t7!d&3^b<{8!%jDdU5FFs+lXac1Z-*N_mHOjKTf5wD~v5{;wQr z6`YwzfTH0WPB1^}k7g()$JT0*EW-%=dq^hD=3k2^!vwfJI4f-IqoMkxr_vG7GcRLw z`zmw60xZK5zeWZ6LGV77@6QM$ngtTtj|ONBs~xoEDwYm5e7I$mG3s9R%erP=FjoJ? z@v2Oi>C1WnkA_CX#a5sR7q(U~C|A5-Y1{v|39sw4wys6|CF*?pe@{L307rH~2Fw{K zPpdOamupB(@%H}uv2I3}AT*>himTcQo2z@J5Wi&4&lJ9l0;(>;=T4JAg!SzI`T+wc z>%D_7IXIZrDYB#t_GWf#OxJ2l>~K(#$DG?31TW+o@9dlNXE0z$7HCUOA&Da$8+bvB zjmM^0!&AW~9~5V5HAYXI3kYngQw)?}Oo+ysraIA6Mt9CW(oG&!KaQnjAKKUv7TStn z$Fsh!piz7S!eY?MFuVc`kCuBePl}}_ zd8s-~{@<#(CXld{Uxj&b!Hs+E`AfCHz>Idhz;aXSaczR7T$d&{+1tg%xVQ&hQC}#B zneb6TU&oi4&J)3=vKD+4xx|4-G+Ov+Pj)t1fIwrqo|(71nhS+BvCcVDn^pe2kIhRD z&V@s4_m2tm%g^pJbGqzSH8wu;m$Lhw(%Rn@9o(#4(nCd0gCBEtJ|!0k>Xw1AxS@)P z3o3Al1hQ-&>kaKRWl=!&{!S~y8aWyoJA#Z?Cm5ZnA&+Cm`sU_8s$zGMxqpW|Nbt| zL0YoE$^_}X_{5zNv=|_hyI{K7SfVMImvO6y&^G6>dG$>T{VOE(V93JqMH}SB1!Znw zAuwQS0Q42t&@hJ!#*RavF95O=5(8~H0zr#mMkvObAdh$P4#jr|K$@7~C znxY*1SE(XF_KvpuvxH)3m-)m&jO@lXkzSBu13AM;G*T`RezEK*px>|(;YCv?hx8&2 zuTTo~$Csg((u-`}bZbx<@sgQ*=AX^>V?mLx-4?lt|C?94lVLlI_Z<#^>%M6q{-*dM zg7_;U8Lk!$Mj35vZz+?eGo!~H=hT7c<&7D>Iwb4n??@n&)2K5tF4mBcLKa_vXr-PZ zChff!KS^1T@v>CAK^iF2UdlEku)G3a6Azza$ZM^4*7zniVTsw*kPXMEQ=)(rW#G}? zpF@pMjxg=B{(Bd(qHWDRG$TrV+C5{p;#*Vt1IHyQ3j0=D4a`$#?D@MfUV`r8zWAE< z2^2x{eyO98rHTq9#7Zrr8l<>I;lbCp6%;)l-%RwD9CRZEEPk?R>i znul|y>0r>i_(sSf)E)A5KS0S$oBST^EE+ghriL&^u8VJKBk|D<& z*z|@P_@HCqZjdn2^ug8gXB8M$DG1{mi&hR9@ptw=_Jm3@eh>XF56+2T3@GQJLeIM_ zNr|-#YF`Z^zFpVrb7yI+C@oMt>4j4J2agk=jl{#MB1h89ZXPlXO*%AC}xmjqM-T94;W_bDZ>a$tI=XbbY##ew(Rmsqv$O&LB!^>c2}sLj+MAc4Hmu> zFnlbe{x6}6<$$L~zMgI|m`f37#txcMet)Cqgi~jOfodiQqQSGGi#T{oIHAk-+$gCr z4cF2s+x!g|Pbk8Q20F!|Nog?9jx*iuhyaIDqX-!|RILM$BnL6gZwy`$s2VJrSe}e{ zL^^QKmzY0)m4eo&6mh2D--8IY?nIq&7%ZBIhRi_X{-}u-G-Sn}gp7f_v`t&)7Xv1d z1{}2jt0~@|Tpt~DEP>A*)tO84&39FvPH&+RHP=lXAK-FE0zJe7a*^`axqM}(ZRXI=J@8b?Ym7uz!ooX7K? z*}nJbq9fBfi?{ErqteA>;Uc3et6sPWc<8^7=T(wuwgWL^koFe`JpT!Js+%*y3-7k4 zav=uzycW;x0sofF1H66l>cR1=qmo>3Wi0Z1&u>{8ZB7hJfyMx(U768b6qof9DKcL& zPo6s?_!`xHA`=3Zae_vg^^~Nj#ct?@NeGgdzNhb~d50exaFP|3rd*j<41{Tp-ivQj zhFNvi=qI0V7P(-S_@zon_7GqvM&hXOWTvtb5}*brwuKfi*{q#YJcfR%=Ss`|!cIqo zdxUvNPym5{e-XM=ta-qvNGVmsY9wP-Do^)j)I!oCmS~$S$Ye{7Lk>+c&%2o8SrWpn zeBY8acJgwxmIX_drkbS;ITDBIxQ+^wPC^2XwU|4qb)7vcOF4XC_Now&^!EN$u+cEF zE|@A+t)KA_n4_o{DoTtWw%msWuhUbHhe7R6fiC2J!T(-fpP5QNG+d4fP z4$6lUf&?1oumLAz81uV5zzHwlgwv+1O2=CAU~kW#E4*R?6rMCQaKA0D5D{Bs){%j*``Y4{B^6bmLU zkB&OI%8cCpQJ*NkWkV?;1prlcvanZEXCs$A)Guc6XahB=yEUW7+CYJv5KmmTMQ#zjSX(CtLY*amQKwDhKlO z#6)nqY3~ToS2~yMXDbAabuP47TD=I8@EkT|&wp@^mY__cPc)AyU)Y}k&k^(=D4aSz zI<^IH@ry@g)}?JVl9htTnFSs04ht9NW+u%z*Ga+jTbcBp{2)K zJ6FYUcBupCHVmIgC5lB05`ii=u>}L?f)FeSo&yAl(i4OjCo~ve9qlmw-wXGO=Iu~U zQTM|&|7Jr6E;6it*H(4SjwdSso)JG>5Ha0cv)~q{%TSx9E~q$#Hg970d(ZpBpPV=* zQo0C#N6NAHz5s-y>A;2G-?Q6+9*gJ@OR&kmw+WZf zKmN}POw<9Jc|ix$B{?(`i0S~x@%c-fD0vRGmR;VvU(}bVW>Xi~Ojxv9UGFefk9z{! z(kQPc`#n~^ps&BD`R~hu;|Hk2^B`r?$PkzqALG$_n-80nOZG|KnlnJ?DEuVI^y`OQ ziFWqVpR@Vy64X7Gr)Z+GTD`a&GZ!U)uuk>EPm-j)1vxdXRF(8b z(fgD$hLA9MEuh+Zur9L#!XVDX4yBYqkZ3+JJogn_t+c$8x5ECes?PXft->Bru03E0 z1}KP5X@Ij+X#b9(rV^444Gz;wW~y=OKQ~u9?G|G`#WhsQj2mZf!>@}5XYYlsGETB7 zvKch(w4h3m@0CmD6sH91MwHsGpGIdWu3xvjLnj5c@r=1nPd9}w<`)To?#O* zjX5TIf(XN~SEWSf?mK>8a%Z%o8d@p)&wNAD^Goy21~nSRa)2nztwGx*Y-He_f)8TD z#M(e9IEe-$GzkBt8b=bE)Oy6;LK&LQ^X5n^XCV~+9+P|hEJ=Z2-P9YG2$`tC1_m@8 z(KWCu7o;wQlmU%D*YRG;5vL8x5^fgNG&kJybbA#<>@|m8&&~$P&y?uow98d>+*oHJ zKUZ0cW#aal&H#AkB3+r8%<^M+J_G^DgKfnB{2=xoCd3{V{P8pH)z#f}JHBe$pSJqV zaZWKFS|51hl}G!-cbtAVpg)?uc7=uD_sXwq{ZmS;V6eVH`s=WW-VLfMwUU{p6kjpV ztHW}SzEYy^O6XYP!84a#d*-ol#WS(=4M88TG_Jws_O-mhLpV!?p!>V@+&#J%Vz0O# z;$jc)TJRi4!q$Oipzt3-p2Dy}i=HGTA}tnTa5Ij+D0QLYohG^um5{r|6sBW5%o4uP z+&s79yR$!kDI1_&rtPMkJg23ltKuDs^I`JO@}D-j)F$(C=y1ZI1z?n+xA0zT#}&)n zlAUvWoBJrnO=-Q96aP3zPxn+Jna$*ae?m)Vd11DYbqVYDy#_PUnWz(Wn)RP!esFE4@(6_Mo{Rj#P)I->s@(=q8Q#8&DYmX_c7zM=jdL{yc&RS+YQJ z`1wz^>Tn9XY(ck*ni|^iy{qZV!?@KB!S$CF29ZVIC|!1W(aG&z9(}T_tg3Q{rUPer z;#>Z%_o~!?1~C;Chk1nkH|{5A=*SLnjZf~+4S5j?0nDj`w7gN(_gNwPjIY3JsQl?}s^{BJS zU7-4SHZa1TGA=Xu>7@koi#&;H-~#+xw|gVd->c*TJPO1#T6ciM(_dq;=OW;$_suVh zhr!@DungSZSz{*@T8p^GIqH)mVfWms+AhEe10x9km^q^<3DdS{#x~RgKeJ+N@9_B0 zlQ!-A9(jku_;K&f?pPdEmAAT*ql|vcmEZ58+4`rDe&{ivEpFVG5Ao_6e2eZF7d;+E zxN!NH@?4j8*dp+vh5TU7*w=}0zGAjSEywqAx3lxCjN)z5>-09!qo;XdX4u>@q`Mmd0qJrWk&_Xpr| zx#ygH_Fn5*f_6>wza8U7VoIqsQ9B23CAiqU)Z)MV+Wr;WvuQVFQBqb}$d!7v*U*?P z=fvbSNgmTHx5G=N`MKf*L!Q=*$zhd_$>0PjTynrE1U>Xhe?<7SD^=!<4=}}BSz6H> zMu!xAmWUU(t%ru^tR+MWV-|Tzc$^x2ZsZD6Ew`vq_|L?Y=FF5q z&1DvtgV}lHfc}~{N?DwHdU_5%1>76z(O6m7fQ0IggN>E?6KU1GzD-xh`!&B5r9=Wc z(%xf+(^HDxqTo<|(KefZX@UhioC2mo{+{*(xM32Ay1Kfi+n4QeAFE0s#z8<@T$HDY zZ*xm?{_aljlGyzad*H=(>$Ua>*0pYsC=lYH0?Qqpcr{a1GvOnQrQ^%}JI-SfqV znqYA8VflPfQ+>b_FxBV~wjPekVf8%c>b;^A^KY}Piaa+2m{wVl^vGKa)4khNiG=0y z^wO+?npSS1(z%R@A3I$B{{36h)C^W_&Kgoh^?H6JTF+czcFMAIpVDI?Lc}TMYGJhY z4{i}5**Fz(?SaY+$YWH6nL0b=T!qO(;UU0(>_Z+?#)qmkI8ZOZs4TuKVzaiYUGbLy zGj5iYko>5)!m*Copg)zM9Ufy*j~%ZpzbVJMX!-=s)IRGS7@VM*J@uRXNZTW(^asD{ z!kRu^eOnYQM_!RR#Kr2)g{>i<@_4&9XWEd%&(9Ms5Ms2fk!Ox&vn=8>#*NH>G2|^jB#~^ z`18oox!#Q6JO$00v_ zZlR2P2nveq0Ji!Ydy+VP^e}_yXkdi;y&h?m0*L%WDh>%Z&iXEomjAcYQDAA&bL(cc zprA*1oM9o<^p{lK{2>nfwBZMtkb(Z?AT-oi_}tnsLqjpQF=EzQIPid>1@meczRIZb zB1!vYE48L;NzPxz8g+((Jk?^*)fwj|sfJ8uRy^J7)gR8ZL>o3wTU1(~F_BkCE!@63!urwQUFA{+deh>{N%#|j_`^gSHDv3?;R{oezIZYG-Wrw>_5{Y&#=zb%x` z54SW<(`(AF>2E2_-fAeMI6l~6I7o}=Tzx_y_#0rLnqM)krzZ%m!Z;otUdL5MU!Sqo z4vqM9os%~~o~K0am@C9P1OVmBPqcqEIB5y6ATpLkJ&zQR0MrdN%*oPc1X|;7yc@{Y_(!# zPu`&0!A@W@h#B4y-;nKWVPZCwWuyr^kUqqZPbY|h5hNL(2rna+0{xdSMjWv|rn0!> ztWYq7Tgq38p{nPP!_W?1Cg$#Vk|4jaIy^eS4NRmF5ar3BeC9{0 ztPTae%!QUl9_aVt26J-c)*clNChkM=l7W4paCQu-|E7g}_fntKlA z%f=zff}cXD27Mih<@olpwdV`44;trRH)@XLQ-0&%39s|j5_Iq$UFOhZ|u;m5phi}GOBH4WOR}i&Ji-s-CVx$?kwVMxS>Oiq0J{Ki1w#9e(!1H+;4V@ z<6N;8;2t05`06L8gcsbCpBtw!gv504Ypuq`HG3_EKFb!mUBjYTy{lJsC;nN!Tc4t% zFbP)AnDdo5?8Wy%HMt}UsRcdF1Xgv2d%#s9QooYzjRqcg0EEWWpJo49`R z6)ev>Uu}M+NIgZ7*Dafz1Jlmd-uw6Z!znjl_LZ~RlJ|p2uoXZ5LNd#~-?9Ly%Zal)h<1l~ZVH61`k5U8Mt&1HaT*!`Imix{`` z-TK#J9&itw>def{(bXS*tn-V*IuQJocdDhdsBk@9+x+j}#SL;NRdtJyQT+vzWNGt# zOlaid;$rE?aCB<>EZw-P49^Kr1sRh2Y{@mXqEk(Ou}EEdRQq3M&uj)Gv>oG?PJ3~^ z<#E(&?Bp!n6oQ?p8OP#uR~-#4Kjp{^q-7@@3Meq^XcYb21PXz0W|v)v3YqU}1G}cS zHt{8X*s7CbU^{+HiHq+6U50oe;YIPp->7YGPKyW#J)aGP))CG4sKhHcagbA)le%qWP%k>xV5G3Ch9HL)!m5kL_v< z@o08xoVx`(Q)Q-~NtK2t+oP*<0A?*ZB76&$)D0h_^h54iP6emr@%Jh|UiqNOIo5#7 zNfCG~;Jo;1sUa1%Xu%no>=^NNwqiESG{}4M{$*4h-vj^$kasW#JLhte#$Lt&(?fja zqy$59Dn=MmGUx+y{BuqPQV3j>wO!RJwcV2S-ax&Gyv_9`S!hdP)uNhBe9zjf0b3^Z zx}2-Gr)kG~d9H=ocQ`l#rJrG*PwDaNZUo?g%`Ziuk0#tZ?~BRr5VMA$ajedKSA*#F zVa`X%MF)2O+ugV;&(nB`lPweO_OeU`a>;xiFkwi`PrZAzq(X!>8Q~Ra^oR5zV5>Y; zq{E9v$4^q%KaiurTl(xA+vvj?QpB0Yfw>4Rl+IQKX@XE&15b@9;=1Vy3Pjp}U^kuT zW(yQCp{mz(Cd#X&NUojMbDZOwMoLhFnb6Eo;u%|&l^S-PLvw4|bu}~*J0(y?*MkXC z^_nZkkEvgx1}tcQKU;0yK%U>c=A^2}NWH)5_lVWfH?0Cs1iO%_a9xn<2NB?X`2fk@ zVQXv$lv{DNQ*=@4OyETKEjSvEyGa6!T$zdtEnMR3*RRz6Q?9pSVXsy_+ne8Z`r0yK zd)9bNOoQh8nGblI7A-kQecvR|bYd$h9v&}h*s4nsdf0>( z;8%3@UJFUop`pOv9(N||&10y`J!ia_5;F2$ORPn`+oxr#GPR!8#*{p={dE&BWQ7@yBQ}5y*26t|I0+XU}^)b}tyNDMV&G zx{u@Gb=2&79zlG(blUYt3|N%a0$D;N*b!1pee|+m_+Lf2gX&4ZOgz6?Qkfc~$mZv+ zGOrOY3ewO3UZup!&6!5^WUST+Q9ac+hZmiVuM^v$x3uxS*4#h8gAf-J7lVtZHoi6T zBOUn>=6-o{IQPll?M6?_2M}xMZ-8hzra*yja>F$3j3hJn~=SoW?OtC9XGc zDN40hh&QZ(5gu5!f;hb3b+$80gD;y0**=V=3|`$C*%VPza*!&cEXZ8K194nVKR3`r z6;A{9090>B(cdRwoon{WM2?3{fEXOw610SmYv)tKAd5(0vNKl5P|Jmt!FH@2Y)i`c zNMmX5e=0G7r{>_SMB_6|gco_jNdsyu15qi}_MvAZ72Fu}&)_-zYDLd>4vCSnurG8>34tAdrATwt9_5UX%>O-20dW8b)PW zLnz3#$Z8~=?`BPAx^|j`N&{CbRxeKO63LP0-BleA#m?gR!i>&oY933zpOmSNon*lH z&IIt8bH?=UE6^niW|ShuizWB*MhO(R6pSI`rRBc z^Udyl_O@~fp_-$s-jcDou0k<{W;x@w1DJwle6+K`Vj%pIEZ4ehY-q?T!BWm~Qp3%2 z!CGGj0llmFjX%T_;oC$;SnHaMaI6BdO-BgZm`;66Jv76l>TD~B<2LDt4GaTYSANje ztJBJY#iXc(OF%DMX@1ED-8(&Uy_+y6KRncfd)oDkSYNC&Pty|x*wI9P!sSfa z)R8s3w^QX#3%&aWERL8jNf#&~9gCpvCRD3OMp{}0i=t^!Jhqcny;n6t#c8(1`x!M_ zb`8pf^PXwDDc6f2Z9Xj_t$;VZicKkhTRua{1xC(+_=DkfGz|6b_7x0&cbDM2zX7l5j-3(C5v7Lf%Zck1v+QyEKC{M z!j`hVyTjL-JyI@U!wkfLZcR`D!hF^B8-@tvjvLSV@4tat+HvM;$lFpF^F|M zjfNY<4eYQtcnaR_E(RO~dKbvJ$dmdrzsvvCze;<4vKH6#DU~Hb zFTjEot35@+V;DO;e3b&%Q(*pD$xTknHHrYp?apre4Lv4}ea{q~R7R8q5u~w=g#~NPEJOK0tdLK= zZ}6b1+)Q&RVICboaviuwm8?`_<>|zLGtu|_4DK3zdm&d^P(a!l<%hEBBT9yC+~Rt8 zaH~+I@C4OyJ)D03^NW(ER7JdPT2lV54TJ7$;Dq{7IM$*{lROl46$vPzY&2I-HhWKN}r4h|gq?u9C3fZ$Nb zL)oS#g>q+CP>e&=qji=qDHqa#00|ljLSf(iHWq{1pKr&rmVfDo>=Wp`X3J<0Y?ei^ zC~+04kndYNv5%p|#;g4GIC{8!?}fYtG05icfWOfs&CcwHC#mkF~O?@S} z%dF3>AxxEJ6AdZLo8RE^x$2stE!My$gzoS43$$-9WD}5f0tg5EKC;*3IYNiruic$S z28S1ijtsjD4Z0SU4Y~}wx_cITu6hm^hLlwXFRG8#2EZU%Fkguo!teMc-V(jRtAAfC zjgk(gU_3CqXgaxsXZj!QW)+;l*PQ18Baf}!z@20#I<*B_#{i6$Lj#5BlI60NpXYJP z0!I;C`|*`6oT4GJ&P$E~mxC42R?4ue2PX9`@v7O?-G=;-xK~)}Z~PhigyU#zpk|JF z@@x?86flgo$&!OJ>_Oe3yL&xCh0=)+{PX129{`je6N@)OfC9z=4AvL0 zWrOJJ>h4mI{GFVg{=|DIK30PDC0$U{^r@=OsKNQ}r&e*;?^`@gT3O7Ia~}?7boCmX ztS>%J1bth-^jT%S$n0Rnn0i>}SzzY3PxIPr)1aS(#o(IBVl-u&TtTW!MFp^OAv0qC z#_Vn8P=K84*N~I%3Gsr00E%tIxTU^07hCpuWi+D&@k&Vx^*~)xsRA&Qx2o@Y-S@nf zm1x_n*3xeAKQ*vZI4_XAT;qR=Zw;t(v#?zt&x?PUeEv36OJuhc`1Fu}z8&QuSd_vZ zW}(I$TrLzWp#~hXt;K1-WRgw^+$#R#3IScGF-}pM;dMh8^yX;VsC@pgdWO6$KNmeL zr$=wfo{7TwF0;C=)^5qr?b#IQP#~;lzzCtJ9Lue(z`Ld1@xXtm$o6a{DBpdafFtV8KMQxMF`X`LWc6OyZ2R0kTlt#hBb{HY*OLD9=(6~VQ>Sh%K%8%)97 z$yoSy&yBdfC=*E>7eT^#bT;wuEaC&p8C=lQ__Ts0A_r6D9_Oh!`BS{_)0kywF!+!*xasOH)mt6vT{Ib?LgFkBze)pIzf$N{SXH6Cfcq1Wo^*ol$~$0 z5q080M#9TM$sp$%JvjTA{01I(riqBn500$kbUn_6zuIkj=3L>a{Hm`?HP?61Q$ue1QVO!<@u-~ zKO3ZTBfM-6){oo-uIf~wNLIewX3uykK5jPD)rC&le&w8f88m~4_sdtjgPRYLPHJ0F zHwg$oQU;!>U_?jX3O`~loc2+^JUEw z3lm+z@4cG`I#z!v(XyuthFiL7htpN{(X$cB6^t5-?KqWGs!iCE4ZGT@F;=bf&) z2S&TMVckvfenQfPvabq|zDb0zgLm?Crr9%X>>Pr}W>6Cu*1jXGfiGQYdnZq>n2EWD zfdJj|A+&eBk2c9Hax{5q>+&C7>c#g(*Mgc;Sq1a2Qa+IgRPx>t-01G9N=^#M`>38Z z2HybxBO6l;*|ng@O_Vxh>3A(&_AF7CgPp{~*!ZaR`sL&J5C7UuW)4fAN>lT}&M|KQ z0v0xP!^O`b*Bodqw1r6C{G;lGEk{_36dy*Y<{p*iJ*2_J-q~_>2-EG|3!uA@+CAY| z70!7+&RTGS8Nl*@eoqn-{)L*6l{MgLO#mzp)npRedmqpr zV!#=@^q%DUO~=P`1qhv$QP8QYlvH=^-((QeWqH-UmX#NEvLV_R6k>>}i=gUf0z2>s zxh;zpqx@y#d7+BtPyK8~-dBq@#%FI(B+zs;fa1KY-C2buv(M6n%!)+`j4h7wr;@DsuoGB=grKkYGT5P&znh?q;-lK&G`PJrm$r zEi{Y+dBp~7xn;?hCSoJLo=B1RuV2>n-XC4gi#1IT^h-t%GL-N}m4PFTZ0&Bg6d*jL zleRZ?d$tVV*o2X74MumfZWN!N;xO#blFUSfYTU_v9CVugqRSTCBsHW{4`)|8zZIVz z8Z>zIX(zU%|GW?7Dpc;q+ZBL#^;7yZY6A%qea|;bm+u!t%hE;9_Rb;JH92<9_@9VH z8$9lNTmAWBlPPFkO1~i>%O|~^4Tte%3I$#KGrhBEAjbPjgr2B#(9>BeN7;4x1}gaC zPeZzSw|Q}ii9NjW3pKQ2-aY=lZe6DXqqfqi)qVHhswB|dwRQVA8vD{v3o?>%b@Lc> z{#2NWdq(*Djb^RSeLChNxO1FetwifwprndEE+r+Ua@HOSy6d91p~1rp`)ianPl+jI zrhOzrs^=_z`#LP*vvbj)_ut{Gv4-*9xZ2`LTZSYn>P*>1vR`De`PmG>CL@OUVr%Jg zs;bdkQxcQP1(2JQq2GJw_Zq!hKxYO4o2|D;`ozN-BK!>xwHVDt&sTQrUYIf79j92* zb(C)Py=2FTtR5H(MIAfyhEYpC8Ao;diRWMBeca*E2um-T+6^4&0pfcmb7U-FU zpG~Rp(rX|hK_!Pb*;A4Z@KGN>E!iYY8FP(b5{%GE5EUR){6e>l{e@F^YYL`85Vr1P zJ78nm67+PF)p}{`p-D(Gxy8W5WLv52K2+AVK0+ihhcEYZaQ9ej_*xb-5&exISe-UG z>bpPYh}9=y@X%O4ST=v0BslRWMx<4H(YKKNp_1q0*88c|DWWg{9o6^eb0%5{m088i zMvfbGVlXYR!canJejjFe#V8F|bMpahAY|Sl_|QAK3sRow-pBqoA}S)d(F2?0ZAg9d zZwwdN(}kokMw?fmXxc09%odWnZr1vVnLK#%KZaGfNqMm0ymLK$Fz}@6BJqG)*XolVeX(0W3@7DwrOS zT*b)Jx@$Q@9!0%sk^%o)UxW&CaodTG=0S&kqsBvBQ_0a+r^ai{Zfp5A1m)UiCwJtZ zHwd~@)ldk4BTP)}DMv&@sZis^MtMF>w~~DyGa&&sSfzpt=H}3k`9uR(;XeN8u3?I0 zKkvs=m1F`iyOXb_3!d=`Qff`=@FMe|+2Vzh6b?3e?xjeHHzQ8M-^l#iUWRqr)TX2t z)n$oz*7s-uXvIy=caO6E{f?L`yDR*n90Jo7E8#gWpn^JzVe2?3(!&|T!!tc8)HRLS z6V(JtG+B6a_qz!j@~GKO;@UALPT-GeY}{+TU%h@_#91nxXh+9eF;Oe|`G~W8zm*lZeF$R` z+AyEtWzZ6g5dZWIMBb*5r5D+wVe|8o&?iz%%h2GuNh{(>0Zsv7PIR1hhx*q7WWk>S zDV~wf>RIc(_Oj@*!O+@gZ^@OW#!3;kRxOWIMNEvDw zuR6#j!K{1v0<)7i8XH1tEEe>TAHDq(H`G?YZ~J`Jnm~N@Wu*cTnGmuVeyHQpV1Nl{ z*f{mh&nFUfvNQic09GuZPf0PaAemUcni^i6N;z)zz5PCkn*Z{^JT4{eDL&}lD(DVg zXV3fIeXtf{!r^}Dxa~@Ig?Bh+P8Mb2CC*V|?p)FWt88hBLkl&p+C&ditlo_6Cm@u- zW1M+izo^5q1u?D%d@Q69y&=B~sA@M$&`ziLsA0?s?}OD5aC!>rT{ zI~zwcDs+Z`sP*1B>=-3SHJCv~SLaisctj+wY~IW7};bLcby(muX`szV9FO{?iY$O?y3@yA)Y3Eb`LX(!;F)Hmkj ze1&W`@7HPAfZB|~OxO_)qc%hkLv(0Nr!IMuS(SE>?6b;pBz3kb3y~bH`rF40)qk6= z*OnnxNi+z>a7U#DC|TaaYpCGpmn0}4DdMzy$CW*~8}aJV+9VnY9~Lucs(ZCM9sDX}z<~|X;=GjysONSy5ZC{@Hb69Z z`8p*_iHM_$RA6ER!R#a4FYvGYNGrpkll!*pnDZS7}5eb8*c2Ci&4gMvB&I;wBfJ<8=aPIM#A z6{*|jZq+CoF{H1XZ5=ituz}-Y*5uToqrcrJn;c1f9p5M7rioeGFYpcMk`XvVeDwxZ z?YPP`l-Mzb`|rZfUS5e>!q4*8BM!iXLe18Uq_K-ZH#_S>`LGGh9Z-#XC9Z941w6%3n85|%4QPXA6 zr7C*}{UteQN4nxA?4J9mgymjlvTYF(=)J}tSh&8b@^st(IJ?OnH9^#8MsY_NRj~zm zKFQS$++IoK{20=uLLoA^>g-e8`TXj`W9#S7%Z1gVW5&Bj%*mVS^nFq)ZOMaev?%Hx zqwQ$aD!7Ws1i8iA*kLK#E;+JbxL+MvzvO;WNaJwBowJyFDhltUNh4_ z5EWfrZA?hGJ7~$(8Ah&Lkizkg5?$S61sKs`EVWh6>uc)|4Dy;sei>WPSypwVxJJ^w z9a3)708!xq=e0Yfd(eS2TY|K$hlFb3IJpLNhpkeY@p*Rf$b$L}?dt=9FCq9^kY=WcrpkY6Hk<@DlMVLL zjBhDzVcN1^^{H4Tep}65`eWX$v`hj-YXt+}nI;<} zBarvJo9f2zzp8}t+12;;IYx9W)+I3ZbiO|GrjMg!uKD$Pb>_HHhL^qfMLE86eFRH* z9edW}oWck=CB<<)m@%ruCH?8Q{`}PS>LE(jmCDgwuT;VY)#IIglxmyZ!F!DXT2BSE zNAD7by3%9XyxRx-Cyby4?h2g}E9>e`%FuuyVB*e%l(JpYfSs)NSwa4SD0XZ$x&%J3 zfVr;hwLFT-s;L^<6s8A%>cQAfCJAizB9MPQBcv0h3BlpZ5DQqaUf8NuKoSSGVO9RI zSw81tzoO~Y*<{1bhkEudv~&7^)m5JeMH+6~NqT)!9G+?B4cEI5DoHdBAgy8#eY{Hx zH-WNgjMHF%Mlh0zpC^Rt>?aH~*9OxQT8j1Gzn_cfrBr5fyrVKdYKtvh0xI0e2~elW zWGNLbRMlM5E}((*kWVSsRZ;{7c4)l%!=}|79k|*3VZb zw{=vN?RI^6-+Y8%NHU1+ef^>dNrpvGU)Q&O%5ju9d7iY0NIb!hJU;NgZwO^P&ifT> z{l34oX;|RnDb`=XH$`tTqAl>C-aOSs2_wYOZ>ZU_o>Ty0Yd&6uY<(jnp_lOFrrOwL z)}GDy^V=`jy;|MTL&}zwhPfIzmfAXZQDR7ofE*H=pI}y`Rb7Rq$tE`ZLMYRCD0vMS02I zsN*w(R4uaEd!iBgtpp5)_Y;fb4=OtJA!KkvFY(b+k50W8;qU z6H6;eq?$bi2_c{`Fm_@^lEWMlGGt~0ONjF&52jC<@wWOORdbO5V(bc3vwm`tU+IDO zLuKSY8*><3vG#BrST7r-y#oGZK1P6u2fYd5RWP0?cR|d7Risaq8^QLxBL+#-Y88qs z8_pA)Y7N;sY;WDB^cWk3tN6FjzrQ{OA=68~`w0#c(K1#xZ`h1g*k(6wtdH%@JFZcr zJ6}Ppw+3CW58L!Uxf?`Tz#VyX4>7*#&RCtk<|FM-W;c5$zk2o>`sxXl4YGfA*Duc+ zBS*MMvhPlMl+wf}LE&Wh@hX5E`1HsM-|L!*EUnzBSQlyP2#Y$gip}gfi#!UspK@w} z_Zh(b16C?;%w1GyD5476iZfS_l2PXsVm-8y)e0Sopn`4>MIfffhi?+b#z9ugf0#)! zbzEb8L%iuQ!mij8QNw^?jOQN*vfP|_ULKx+O=X$w1IZe1*USv-R70(eyKCOVRTg(|?8`fi}C8`;uOk=aM`tr}%waw;$$;6%;< zt$S=?tW|K<(Vxoknk%!K^tSV%8coejEx2@k!ayuwuYo^x01Xq5$_cZ`53(G1m$#wG z=NJNd>5Ny4?G<0eHjs76^S}c%qzzwa@Eo05bDb-U6dGkhz#vZYKf;YYrzecx^lCG8qH z#^;CL00r#DkJ`)|{vRmm|0x|8q&naB#Vw8Z&cU_pf|Y@(_q*usj@6Tu6P@0blbG@K zNNOZGv@q&M)lvIlh_r61l`IvIV;?Xowp6#XRnCx~aQ#pr$!;tNOfdlfJc*7SAiW*H znq%}zkdoMbQb=H?5%b*~t7|Kiw;|PTlsh$A zWVHq~MU~omgIf-0xu2Jl*4Oca?gzX?$T(gzP)2zrPD9bl!4hkk03d%m zkzRfH-Mt_hbUoAcXoJ#nX@I!(7f$(OydM-r!^Mc{r0bd6mnU9mW8*Ldn-tPkl@eU6 zGiuyG@9w#>wC-B$bo|7dqF?QL+C5IsN;h5*{}C5e$F5Tw7(OM-)4Voc=Z&@*+ue1m zhaQLdc`5w&>_(<#k-+7azFD(_wJ-j^jTb=kuv^fA-BvGG}z;J7^BH z3@*5+K7DwyGDGB==*mz2F&X?-#8`uA$7^`7r>@K*pm6DK8n|giN}u2U6~pyk;N#eK z|G+pwEJgG>QB|-hby)Jj5E}zY|?gj%V$2~I!}EU z1HwKel+r6at>aCRay>SLW6WYbx}PaF=f9>3w9r^*3;x;qHa~5g=5j)5z|v`u^v2Am zquWhu&Q9tduR#Z7%AwGmg$mCM<)-eB@VIxq>(h=4w|yvCF`pqX{{P=%qFIgml8UM7 z$eU(o55^l_ywQr2z-?wTo?qxl#h00|z4R3eoCZ*j01H7pL6x7grktCnm1Jb))P8vN zQYP7kpfgz~^NCjaeXH=&r)~Ma=M@qx!WPW;Tl-}I58bf|1Xn&_0x#e9q^Vcjh&A6w zis6ZkUK6ARKxePE!nhoiumFBVuGYEtUk5pyvwLyUhQH8?;M(Bu#@_&%WSCv>$n&yg zUVubA2_?^ae^9C{OU&hL2AEh@bcX`p@;#2=QiG3E7a@T20Gdo~Q>P!G!HF)p?WzU_ zgKfKAW-gjiJ{1y`x1)O{H7_Eq9qnzt2AcN$nLf?|y#-hh-n?m85g(f+I~CZxL{%Ck zR}l^QpRO}!(Bccm;(IN3oO*~MiJ-e7Vz!!E?g0zV#{A_L%Qz*!h9Rxn&SQVKZsMEn z$0ZADkI!N9H2k`zx7uZ`4|4KWhHx9Z)`FAD3vGCu?RYwF?)oW3iT?!}gfhS9if`gk%Q)?;fG_l?ycRn@!ok z4tT?de+|XNC=DWg)K_$6gZ%K|RLidc0Cnp4A1+{nTRq6rUC&4HUyD=Z>}&DGz<;+s5_o zM#YnyRnZ}$(GqOiZbjbw+{b7~=Vydy!ysJ%6|_`ZytwzxjxIShGxc^eVtVP2;$`lu zTtHr5i^ZhEpWq#7FrjDM+eYUIHs!e9ctsqgCzq#=T3KE%yWuLh$je@_ zcIs^lW+FjdpvV$%#v)AXgha*74-8Y8hx=@JZfAzvgC}r7RlFsmjW)5$nS% zH!0XZ=_O997ypPXEY#!gmx2b2TWhrvDqWh~c z6624AH632QmJL#O-@t4+p1L)IMj`QBCTRxAX*6O)fwfdSq4apJFE zNNfIS`wbIOVoJVz69O=}EX}k`xo&K5)pqRSN4JZMMNoX;Av7fZxU$nKn{${nXZmIcx=AA<2 z|Bp2j`d`i{L8l0hT=C_=8(e%=T!_B5gOHlWQq7K~1Jry7y9PW*$)RvYQ8DNk6^2#G?p$2D8dA322&%>RH*96wmgz zF$HME#{wAj36D+F=NoauD->y9Jj3xaNw#^J>#U=1x1a|ZIVE&deR68%WUD(l`(n|j zE{ItTnXF}WycAPG$oFjrH9*I4|#3T(`+bn4J@Y3S{b86mfE zEP`|H@HI%Lwlt{`kORQ9l{>ip>-F&n3mqR+5z8R6uS((9+*YHDv^zlZF2*0sQ3 z!`z=JqwGajk)^O39&1-m3mR>6+kb4kBvH+h-5rh_^H+1eMUn$@RSc?WQaev3b!Et8 zs&r`*W4g>Lyzxf1xl-)~BM`0lFxjwu4xqe7#Q8%5) z6!P8qa&HJILnHHF87Uzg1kiYp z;JWVgU@Gmys4FPu;>yY`&2MpaC{+?>;i#~9SLH=(r*3t?<~a&{SmSgf6tUYbWkZ$n zCCSB+=<6Mij_9RlH{u^@lO+s5&qdsvxj{k_XHxQ_y3fMRpEvs*irSQt74yY* z$;n-OpXR68DzvnJmld=ug znsL=NnGWwzMMtO2;wU@1} z;(t)D1PONIX?1Djv9-Uo32O6A<$FRr1P@#GlemsiHYzOeg_CjO*W5nue zYKV%df-22?mP8X{qTlju#oW6dO$32g3Tnk5hZ>%IQr&FG;kgI65T|bRcRe^1U}`Q0 zx*ujyUVKvvRy*V}$+JCHAe3q~lTC6|eK+6!rLO5K(fI9Dqt3M~N62T|12%Jv0Xc%N zYCajt+FDw*m#<5YWUU>2T}*B4XNhOyT^N;^x^MAiYBOiO-UDSjeLTe;={rheG=d9P z53I$_q&~T%1p_|zRK-S-rR<7R<0T*e(Q~yBwL=+`JQ&C4v0a@Q#5ZrEs#|ZnDyiJ> z9m^Q}{)yMemxHVlDsq|*N=h0vv8*fyh~?9K z@T?R{1(a5G*51?Jf9?71`RU2;`RVym2H)8@RP9iVD#zFKk2doFmSBJja3wR_IodjB zmr+`AD#7#*3Ryz8SWl%IZ1e%T5%j*-o^^ zV>E)J#o3ZI=b3dI6psfbkmuRuK>X?Ep8H|u5wOErxKql4=U=1a%7H`F-V=lN;l{1= z=tOU7GH%-m=}^(E5w|Jtu`+X#@EmKwjHgLI?ZAhlLP-o}lJL$&%>VZ01G-2>Hb@`u zOh3$_79Ou|Uv94CB{?ui$D7&2CFu5Io%BG-KeBpxoi#~8iMHpmJ)Tvh@76zGk%`95 z99so@o;bRA<^Z`E+ML~30Elg}Qc*4* zhYW90yc{rf%O(lilnwc1{EPnF2dDrkk^=Fo469S1lT1}=P6?6q78JBUERdNGEaQg+ z)bxFdvTOe?G@|4)g?BB8E?0LZOK^n+eAtRqrA}3*L+&jc{bEo&$?%M8`T;U<`|2eP zQCgbu4h2d5^zF@R+evO>-@V%a2s>1tZ(~z0ptxvZK_k zz1na+4Y@vwpD@g*aEZj=*?b+d<9sa3vJ?u1e^zMUS=iE~Mjaoyo8t;OCEbRzrHDyo zHY8f~^7Gg`gyV4HV?_7%4Bc6lcf23=_ph7iw)8* zi-k3qu2DFdX>XV5>I=-*$*e71UBUuy{YCHE?JIO@D;+bY+(ol`HwnCd5%NYq;R+v7 zI26?zU_TyRrE8$w_=X+0XFOU- z;U;Kw|1CgO5*mCcrE#-WUCJjqO^NLC348S)QmQw8Df^H31=NR$oet8uF8D@LY9P_9 zEPz7od;bI^+Xnqa^HYgKMo1}DUg^AWN&KT*W>*ake2&#-%M_D==+oe#eWxC?B0n6k z*g{|$9+eZ2|M$r-(EL;69WgOONt6XSvT88rsh;_z#y85iK0oyuH+gUU%hu{9eP4%u z$5&`&S-R+RVsreDI*H{V?A0jba>OOdg$g^8K+ z7IlqWM7pqNo}F`^9iqGA{5|`vhr{=@xBvge9G2wDzt`5x`jWjko#tsf)_2_-f4efv z2!1Kx0{+@$z*apVWVq^09c{{MXOllvpvA;jdBT=96fUv){#vlq9b1uq;rkQLG zrv0J|rb0FYJfP{84(Wk9ET*;)S>v?WDvlS(aNmZCy}eOxj8G+nA7pm?~684p$}f`li1VP;akX6~K$7HYlIGk4htNGX=JhiHZ4s zrZFo-S*0J%qIS$h_x%E-#+k}iHt>be%Vb$PgJ2WtURmdt6cA=y>+i1=5*z#Nf1!*gjE#-OOdq!9 z&J=KosV(*v_6hRG?hiT+S-(c6+a-R4FM|A`@TV~-K4+w?v4I5#X_$YDs%+3|p*plQ zvn9y;Iu|E`j&D!eKF)y6C%gI7TmO7#V=%9CGrr5Zfvk zyU?pzE_xL*JF)bkt(|8&OG_)_ln1puD>FyyzADn6)?V5FT%1`mu{WtIjiIypYaS1S--RPjX;^#Sg)ZtF>7T zVQiF6u>k&0I9~Yw9Yi%{efSz|VsL(v@K5-Az-SkelG5USR6UMg&np;Rs8;m789NR| z^3z?-Q{mIs=MNEnma~R=N%5@wV(+s23Nlb!6Wc6#wR8q1>`I=?D|5`cH_?$L0pI~X z*SWcyLdzGy2-Ayc5c*<9vx#@$82PVXX<}njm0o#KEh>`PqyG*bc!yK_zb55gjs51V z5-)_8GBC3v0vr=4l8X)bYbf5HTQa4*PT^{>gzYi;aJ1$<7G;sEDZ8+5bB$bk!Mu~f;k7?JCC!j zQ$WLZf>__Zl``f(xCkrI{+p>o9k*VLrlO^hnZS}{AzihD!4qs**&y=MiJl^U`EVy) z$6zTgzBgMeTdJ5})9E?uX$=KH(+FMH@{lTJH0LZ8?YFxkq5nsE0@S*89jEoZ>yx|g zF`JtSvNU?JdekeDtCai^R#hz0q4K$bW9cr=}+@-E;|t_*1ld3atbT*yN0h zDsC2{{9L=YEEK!KNX(+Jion0yKW~VC3Jdgh3tKPKYJMs;<|{T{Cu=y4u$|E_{jKz3Zv+F=bgIiJz;0 z@Vg(EUaGiga}HA};d=Q7Pd}H{;T2B-09eLOLy`?(D32TJqxmZ^Fzh`}ZX{{Cu(Xrz$(BV6U>TXZvOlrU5HWqT(Ih;0fv@hB&fq%AYd*gy> z?2baA$kvvD{og~8zhH3fr_B77Ax4PmFG_b7CvklbL||yaE!r6-gT+6Bf9fiZ5VU7$ zJ&c6^XyMnQNlX`VtL!QY62Zm%PQ7c-`&+hqE%KIdF!k;PS4RLR)&B}-v9b~>#(Z2 zZhaUL5J{yQL`pzF=?>|xO_xY_gQS3fbjKzoHn2Ah0@Bjb(%o#jyZIJA?|aU9&-q;+ z|8dQ|)|xTq7-P;c#(merwhg<4OoIV#?@<6vMRYO)3Nc3)7b9$t&Bi&NWt3|t25#a{rJ8O)CVhOGbI<%;c-I#}M!(`?<*{$XH0d!H5?-D&Lao_!W8@NV_^ z1hp7a69!aZYjyN)oQyM$kM-|b&G6t{SKcIza}MJr%F=!H&eX`wW-ZCcG|t~^HDXK9 zEpZ(mw;fOz#|I)vrq+>>iG5Mm0YiKaIC9xYnVhghtHih@F0*{pQRH@WPcT9^&m^U*{Qd z7*ztbzo=nH{|e(wku-Dix8M!LcZaY$SsZ$Sim!UV)TG6Wpm3A-!Q7)gd8$>=yfz&( zmWiXI-NIR^<)NBh#<-s4t%R7NcX;@65cvqrVYl~uTs3@wTpTY&xyV?;yBo9&uQtkB zF55btX=!QuFBi?JP)Ei`xdnuV*}3N5aZ-xJy9oVobQw zwjSBpV=(LdIgq0QmfWRfq>_K<9dWd4Gpi0cnAU!2a3w#wSO#p%0k5 znk#Sc=zCtfg5Z#(j40kK8jB%@cO*lZ0(K*X`=?ltEK?s43OyTHZaG;9O*P5cpwCwq zKEZdqpKm^H%==f|-`bbzw>Z1#7NL2$QGy)9)#%9JEyhPU*Ur>g6G4O%cIn( z3D&BdUJ1v@nsXD4h2^vn&rwDVvhZHgXj^f~Kt?jk<4ZFa41GM#R!g&G{Ai-hxSi0e zK`BEM8qMC}YLhW1GIJA5 zPN=glJJ{5SWwRv`A=_BFw1(!5C?ntCqjj58qhc#Cbx;Gf1v=p|gBvGcJ^7|6WriQx zateHr5pvlUbP0X-7WU+#9iw2l5eE^PqeH~d>Jm@p(1s;$j-VOSD4Zb-B~Y|Q_^_~O zqn6U}!FAGsAt2@wrK|ArcK!V-ygiaNllSxan4`5e@h3?MKR2C%eRntEeaiZA&cnf6 ze`x_^Q6Tt@0K`_Kdp44DkLu%AaHX)=la3?ow1f0mz=}~UUgcz`E*E8*@E&olc##;I zfV{XKc@)r_#0c7xdyE-@JXL6Q@sI48(!?;;;cx6;%elyw7UQKc2buc^`z6I*;VC=| zconLZr_RWI=L@hg316Rf-Ei;U?~cx5n`NwRCoBdpM9dfRk81gBJM2`Pe?STJ?|H`< z-R-=(AD9;HWsjk7&Ogtb((vrjBmKe}lILNQ1S%UPBzzY?957%u8mSknqs_b`g&Qiu z{3Nm5u$nP*@GABzE0JQZB}Li*++odWda$$1bL6Zh^H#A$l^D}ALp}f!e-hgv`AIYu zFLhu*Dn=Q@@$((KbNH}DiUgn#sS|TtW9bxC*5bK%Q36|)8P+bIkzsADHaG9M?=O1J zxtklU4DZIVMifhUPkm8w{J963z^a5% zV;6JefH;mC(15c@dC=*sQ`S1)qgGI0^UwVHRPZ!$sJPSRpI2%!&t+6{nS?y#4-88H z7(kx8W7;^RSoiulsle>`?&w~)Q`DrdZ*1UK~D4FQgDk$RjCp00}7fOP< zVrc@RegxN)61Y7U0(C@^InqwkI|T|RPOa}MmWZ+pNm5c9gaxMAt0MA-Jv`62M^EwZ znS0E&^!CA?v(W}Z4+ENp0-tY*_P$fcS`-{8%oL{g_31Y~C2#srd)-}cPF7Sz@sW!7 z(Fh=BCL-ITDs(83Tjf(OM%WIk7J(!f;bXgGK5m5pPen5w#8(=<6`7LXB!-=N&ti0! z=4B&GFvh;PY7{M4haW+WzS6vz`N`G%<<6N-OcKY^oa+7Ru|k;#eMY8Cf!6}=cfX(D z+!9a95L$u>B94by!}}#x-$Q`LxL-s#B&X0@=)i@=-R%NXQE`zngIL$8bsX){7CcFl zdYxP|2_nYu>Y=^jkI8b7*<8-JvwPWO@>mu?RoHAt*P z(z;rUQBJ`OEZq-T0nb&f8!bGSb%6mTQRpR@8%h+TTQ2?S2{b(m&G*svbM+I`v)l)I zs1jM6w$y(;>nDaD<*L&r02=@ic&2>7tZJ*q*3tK)u_G_opZHgx7+rYDSL3I0nK6r5 z5wB^Y9C?e_>fXf&WdOc+pD96jUE>(DQ5DXS7EOHLE=w2Ni_o6*}>$jDG$ZW9b!UE z$pF6~O{f??8BbN)k%K_p61w{UzaC3%Hz|O=4giaITLpK#YidsMFaL4+2B74Tgm4h< z^kR0JWvITz`G)LWE&D1_re|E;=aMT^ktR85E4&x89w#!Vy3M7cX=`P;hFxkVb=wLP z@<)wne6hCLx;gN;i3mTQqv$um(Xkw09wrO!oI)Ay7m6O6%-Tr%lyZz94omcw6r`^ zV8lSj>Z1_TiFtq%e7iap3ii%C45AKS5TQzvHbRn(wYff!CXi7<+POF?br4`(E)EBiVi2TR=XK%e3&^??ox?<4G26iaf@{(_v!y4#Bwo7D$QuYy12z8+Ui|Fq0 z!tn@Njq5l94XQtu)g+OUwKZ#f-zP~iP<$LKG>YaEQ*^WDrA{Z0jzY8U_XDFFLUMnv_}y6(=44i5I9&4DhdNUB&1%&%GlKWp7*I^YGsJ4EP_Lgx8W-09 zca-4n_6}*r&k^1ww5}yjAoB)r9|gtPVxxlFb-*3!#wIqBf$i{|9;A5#&yVYf9*Bb$ z-oun=A+P0_Sis*5tK`t9F0gt`DuIh*1I>fgiXPI}qopqpaX0@NckSg^qpf0|UJJ>^D0f@u9ynplZ`RWmm&mG%~5Fe#j z#exGDfm_xVpNFH%-LLd`;k3UB0jzc))rK_yUQX-BLo8(_t02Kg&OVSR_G&}f_UadC$Pn*R=V^(XudJCU^#)s$}MVI zjWzM~ir;<=3_o7tpT`$4yh{U^N7!+jV(hTaIy*7Bb^tIQCpI)Vwl{65Nf-P`B9@Ud1T<}%}kyrs_br1y~Hx%TbfZUVsY=I`to^fb+2C8fq?6}bhu(X4oA zauJd=WT~$8F?+p@D7%IXWET=I>;-6zRq~DXP3v6!IrN}uUP6ad5;5aGX$C04yVsoDj^5D__cI4C{#dr3}mGNQ!VmD z41QvXG1>=ls*t9_K|@9~Ym_Zgkwf+-Qvi4ed8g)(yx~EzszkxsXEWzD6L;6d@z61T z%~Bse4sg)i)4y`2{JrCSod-1(4_yvO*e1s%7PGL&4eunWhRvB2bMFkR_Yy~lNFXRx zGltb1Nb~G!>50V4K#V!pu6=b36Xofi1qb`N?oFigi~H#mIn&PhUu(VVlBJQyP(-fzM>uN^aM}_v6o`0> zWb#Fxj=i>g4OLtlPrMtT)O!;YXVWm}6{2_{uRCtnv>}3}2*cF|J|<_w#{#Y%$q4Osb|` zM!#)T4m}Ue?G+w(TCo)<$R*W3uHuSj`Lt##ga-yR5S$x)$hB}*k|Pp8yl31+EMgc zpAlg|OqhYkD2Djbi9&wx;gZsKUC+R5Hv)hd2U39gl{<{vO`qF*Gr=1 z17uR5h8tMFOFZ;w3@|VZ`k2za>a!8Q^Pvi>Q2QVAVQ)mF$P^{UtjvV(RG02gh3?Xz zWz2!5^>q}ERh%#IslC)`$#U(vJEI!&3P?-dDlu$`bx9u!HDIp(VM#|Snw}&i3|JLF z+4+2<&wv}H=rE2D;>*y)WeCmd)SHS{DC$}=tSk{r5w*UeW;j$Y^lmQJ8r9K+u(A-K z1qI!RD&sZzmaQ&N$-jRpH};R)DI8$#j7uR*5Um?l4To!>pcHMYG2n$UHYmKt-GNXS z^?U)2H)uii2$^4X=qkVwHE2az%q)MRWBTCv=4OEWt$*tqqNWo2$9dk>M0M&SWE}k+ z{i7Nc3DIm&rYNz~MrdZjsc?egITDId;`2ijal~eWH`dUyT-QbsVKD&Z$me00AKUW} z2MrZLYs-hmMF@STZ&4!IC@Wc-XQ#@86 zmUS-r%c=*nzc|%2aBfvz`nBL{^g+JvsozaQk!IN<782r>z=x7a&%84j+71}@K1mA+ z*x_$_ml08M!85%brRi`UlpdA`Xs1dvhM)ly-Yni z{L1Ok@F=bKn84%DX`nB{7rghqmxB>pS@=T=%x{wQc#u>dyH896MdVsY>jDx=DP0Bj zcei@XhLt zICh~sXP&HIOw6<-)v4{vZ0rU>pR~|IC33#8hE_6Iczp45jCH7UCHPcb0)T7auiRv% zXKs;^WgG@+c~Ds40urxhl+AZ&^A!iW^C7+~XZEwe;?&fyU%nzb^B5@YMXW+0xF+|C z8!7FN!+8>rH-*>vW#!-nRGuzXzDoM{1&|Mj$Hk_KEbtl+UnzUpBTj1NeT8za2K$Sy zRG}cnqH!3WF~KVWG%=_PN>V05)&~Zh%)+W!redq=`WK52tNYEmKJCLMNfK=$%)qkz z0#dfhiRseq;=Wt7t1>14wF3R=0JuXFZPFBD7mfEqqW=-I_~{cNH6Jc|qHyF7tzluu zV%`tZ)cX+yT1XK9Gs}}8%n0B_N|PY=DO5dU+~#dHTfB2*AHdXlOr23vQ@JZ<5NOKk7I%&E->Q`IG{vqG>pf2H^9_MREV%|5Jr2rqgc7PS&;G>bJ z+&``9cqW+J%5Xd>us=OoAWkj0>MZ29OePWg(6@N&(nA;=#&Z~^RO#d)pkElG1wD93onRZ_Z%5#qTuhP zBSQHC)f`2}UC5$7I3-=42B<;N%K{Rs8@=~Wp^QvLMi(PbXFX}#Jg@;P2^`ylhHjq5 zKde4ntx82VIHuS2cO&{QY27TJ^YMpc<4z-l%VaMa{M7Tn1Kxh~L<`t%YF@z`gm=r* z3^8&A9(py>3?@dQ_#y2;I0r3MYmm-^>|7Sd6#k0ptQ9V8+sTy7iZ|f}l(L7*$z{2@ zD7^Lhj`CNVAY7I)U$;GFKQZB>P5$PhQzAk&we{BDy5~vcTUSoTSSr#;BvoQ&rAmer z6uxg`IuT`hLPPTBd3$XK7k*AB`>RLVN<=GxeOj?X7!G(z!XxG7qxdzvAB4T!&)2$q zsNBe;xc@}n5cT^kwx^A~HMG`kJ}elPrj+X@#ZBOTQf?jL7@9I0DJ zgpb9#+W4Nm*gFX_l_{G%pfuz6hGEdBfpVyBm#l}B6ctZ-e2pfM&+)nQ@XkY&ke1x2IN%is5)8-g=| zv;y)$`0>G9y^p(Bi?RyEYR*dPb6^OgZ2fySK#7k76-jDV+FpMTEI0g%s0@x^Y58no z(RficO2~?%k?#5EN&E@Bnr}-BJ)OpH_z5?FTGvvo3D}#4TnQEbLPVjE0eJ&xLNc9{ zsm$>Y$`69w57HzUD7Z&j0t`XkZIY#0Rk}gl6+G~{efHOPa#f=hTK%KwLlZz+*!+dP z@D#7dZcbPZq6)IN9X2{d_h4Ql(TRr2tI0q+Df&h{pepeTGd3m`a4F+!>^3r6I6tk_ zAg@s>I4+QBZ@}BY!#|%ae=e?WS~Xp32VAk-d@mk*!}xu&!kC1wqnLZ~XUnjsWs;p9 zulxE)(8<%MPrI8`{B+-gfnEMeJC%f3Z*krazQ6skx&I|^#+==#8#FSrZe})BRg^oT z8+P`0zF#|9`%HRoVOCFL{B{Dse2@?`h%e)0&wLK}7q16vo54eb_v0;h?tWLbtj^4e z^s|sLt3ly%18u$OO6CE!$ZqqGw0|WRb$))%c{XWrBV6)z6+644rmM{;MRYf`$ebnf zrgMP5=!V(UnU9mReKVugS@Cu{>FlRCzC_Sy)H@K5e?hE#g{nQ5L|@_L_7iP1l)wzK zd+IBRQ{# zO3d~#rMnbH!|#ITd=khxXgpZ;&CV&aMH3kXA|JT#4`&z2NJzH-v^Na7@9$3gotvLe zPlJmN=C3I2=Um?HT)%-a4zRgYndf^|&rCirFfO?)9aAcvK3ATkG(!vW9<)vkwV3K5 zSDJOS*Tn0Ljg19EpHJ@`dkI2PXB_I}=?sLC=k}MiJS;s|c2@$ZPJdxXhJ6}0A%I|?6P3<+U4;FmNo0>DjLU511GWTW7I9Wq~LVAw2{J$=aB(r}udnSks zqD9N>Jj$kLHQb)6ls06B0SJia`+@C^&@DWC5%njADIX`s*5_RotSx-YbkA>q=<(17 z|GtVw0M*y_Y;~Bu2Nfr$z|_G7W3^{~v4epbW(#I z`Q|i(0a6IOlD?BGBCRNmrTs7^wXdcP_5B-_}%i5pp7HJ{YpA|W16v!j<-E|@-qPuewByDkavI*WU%s2zZxPG;VWI%yXa z7BK)yNJR6qyY0q&2!CIimmjYnrvT3sIP&@qK!G0yR*$|^?|!Dr{%*(bAo%16~9p`Pv4F3Y`tK$ee< z4Je}AVQKnq@|(MR=ut&aw!epnBGTHO6U0E1m%7Qgob?_eXKpI9eP6MysNQrrquZdU zes=vEFbPz!KX+VAxG>{dlPO+1N$HPxPu{;6{9qUMJBo{CNUfF)PxS!}DX zRPw?0`T5|YfzQcz<-NVaoI->gw5C?JgAG|(I{n@a*`Rf`<_J#dxVzE8M)dyL-QuXdNQhghDHU`~tKIEq!lizu)}% zLXx zK-(lw0+py2;ZM5dQ_1;{@6EHbt0@UNnwnS?J|%TW+;6)&0W=*9HdBM2a0@nuPuSI~ z!yHWN_YGy$`uH+N&_^S{`P%m9>o7k&z_jzI1!ewdY10_Ptq#F{xEU(760A*qFM;fh zH>jSisa<`2b~eAPX@HLWR7vnkoP%UaG+0HNmBKcyUQ>NL(&Bi5>QY&h9)bSMMB8CHxYqV6^ekiS(ZDexG!*FS0(DK-mc93K2(O4 z4MCYy@c7wc$9H#am}3i>!X{18Gp%8!$=i{EvIDSjUJm--93?s>X0DE99BHYGtY?z> z%Id!get{X&DW08m&7bWR*|*d>J@_xxP%ody6s!u%E!$8Np^5_#dRx$qK~^C@UrP=O z0*t+n^?y##>(45)o2RBk7Ejl{(#Ysfd#_KNPw)dc+K%=mvqS1C>If=9-BBMkVAbtn zR|a&8>Q)0f`u1F6*-MVtM(z#s24xqUs!N-{e;fG$KyG?Ol)5A`mXTeGr5&-nFJX4) zA$jJddRQod^TeQ9`$eC#dEJYe^9H`=H;i8j+gAHWB5!7IurEf^$6qa!td<3F8otqqS!}%-L>y7 zQw{>h8;cJH?wQc{7^~|y?hD!m(*wy3954o;dx*ZBHH@-8tcEka>qvbJ_~8m5%n&ia zCHvGs1<-!}KHOdVxmIHu{nn$YzHeSRjVyf-Rl0d&@a^dtt%S;MjSsuR$;|9QqoWt3 zDb?vh0{^cp9x#G-H0?`l_VYYd54e%ycr=OXc3LF0Xd}E+|$}%wI>XfRi zd4nHNVZlKhjVxX^Z&93#pK$`}R*HiMRkU_)_4xby+s$%sWOZ0imKquw6mg{j`|q#y zZ3!_=gq@YhzlvAvHp#M04K~%z-#YT(!_|^vn$5cgXtFVpAksWE*PZot+ez@sl+Vi^ zZ4$={bUEm1xbe8S`qiI;Kbknz5gPiQjX%@PUr;D|qXvi%vbQHcE&S}l&c4*10g{t# znL`DTF)0;fO5FPT`57+O)lF}(rV~dXm6*+QMC6Pt{Um!fuo@cP2I-vcyt*o#0eJI{ z_aiTSZ^I`i+^`!g5&&PwyOnb7C;H*kyNElzEqlAUd6tCygA(Mswzb1wRhle=0|S_t z7-SbF**OeYSXcm9E(nBsGzG5P(yRDUUF8+SG{tfeKDnqnt>FBPLLX#F3f9wxy3YD) zCxJ9zS7Bl*PsH*6oSf>c&dhUe4Akw#Li~QzUp18pUd*W}MMOrqEy4Ybb$Q6#WcN1( zue^QT-8FHV9**eC609*N%zQcIt*eT6DNWM93Z@nn%boYt*qWQ~mQGWKp?T2!ynXi5 zW>k+gao&o3?IJ2Ng6slgm$K(`Z?t4?`yKS#lFq_R5qrelu;A$%SSwqL zxwOQ7!TZpGbrQKM`Eg?+3y9UjYzh0UK+q(#8dJ1@Nj4187kpe3z0)x#35$zasYJvS zsFz~C?}(otya_8wBgPDea37-nQm41Sf85K@L>h7xANAJ~f00tOwz_a1 zb?2&)osO7XwHwogGzX0a35f5Z1MW!TBR;Hd}ILF8R>WVXqPW$X9kjdJx>;VE3P}* z#x$+MHqU~^UdhA>kbAE<)^PIj5@VncZkXSnw$4o4FZA zyKVC0Cj0KZfdi}F!LIf5-jjS4U!glnDUN&evtU(8Oc4plCZcE67hr$a*wkFna|IhJ zRn>Gq>Ae4LZ&l2xcV}YwRI6xw!Q-Ul;cjF+asI=jxAUbt(6&K-bmDAWj5oPw;ioIW znc41?t;K-XND&RV&d-?(5YjQP?(TsDw78ZKH}7#t0V}Hl#!chClbW>^-?MEsNQ7O4 zxY!1PnWUtoq62s8z`EDLqUY9`wWdAm1`|C;>ObnCW3x*%+uLvBFf#GXn8iItaig+M zo)2Ko^cKou2+QC-S+=qEHCtZ+cY=>%dzSr|#cg;9|y918wsO#(a z0UH~;WITA8-|@-A#e^-^F#XG~2L|akgnswf&G+MFK&<)Ge1e(^wuVM}E(m0GWvl|7 zl!G`m>%CV|6UUTK$oICwQ71|tnbOf*k#^r&Bm!&z*jXvE-P1@;TCbpl= zVyy0kG>mF4qV^u2jwPrS;Ns$D9mD{c$kib`=Vh8H6*ff%_G4C<61HR3k!EVMQ;Yn+ z@zQ4|6xicgCqUJDMadc1#FEvPcwvdSm&cC=5V2l^&hUQ6(7^es!>``&k}!24Svo>V z5r`nV>vp@n9y`Airnnt(9;(+nuiiNz(mBZ(9}t9?Sq1kQ?f+>>)=Zn+FX5HpYpOSZ zC1iQ697Dnhh3j&f45G_i?T)$gKY8rzkv?2Nk_XPAbOps2`a>Ytv!G+qI#1=&29A=Q zW~VT;O;i>jo}r$@>SpTX%|>wDI@xmD#(hskgpmmxyQMTyfV>L2v_7*c00H4dQ`ifB zKJn_=<_ByKyW~Y-9PAJY!)lfAYo7|`!`y@Z^RnQNvO*PpMj~jxDepJC1{bbht;ivPlVT^9sKxF3aN|O5i&|TKW?8;*=&8=J%kQiOc?DbzS zFMsr}wxeMEYXqC@bfNesolSR7TWchxf-_3DZ-oG?DVeyoY-MT+N=oufa`MdmXoD2M zyxxKoia1lr=)%wdRqP_zKBu^0w@VS0%9pU+w_b@&QLNsJ56LftS2u;B$;bc;)v^h*^NmnqV+TKt|M2uF)I{st3%Tq>CUthz_z77U+AqR(5!a>5<|YA_ zX7<|swJ#ef$K^#0bS~L2OmLlKyK|)}w6jf2On9^06xh%AgRFCuM&1?`kI99# zC1~Q|e^KfJGcK8U1o->MkYS^wM|he!Zb!EqRm%|$Mn*+t{+2_Ip0ZWc0m=tuAuv)& zmMla4#rmeo>($A{`9VA$tH)RT0%qwen&f1n&THM`yzoSLpiNcvrk!9$&#sOAO~-^o z5$+{%kpf<)1JB%K^6r7s8BnVvZsTcV!a)Hhk~T0%e}3I*oD1ayaK-zp!TFS%t7Oo8ITlnU7oXenojJAMlEieh zrqLj?^9>^c;5j5>e3FBf*xEGR4My_2Cx>4(cAKIHEFF2I8!8?4exKaIL_!?4a51)7 z8yRT}nhpih1hP`e(sx9n8k?c1ETem+6Wdp+b;>F( zqw1*xs!b{--1@15!+DQ~=3hO*iQTjw`V_C0aIa|`87MMI$uohwxfF0}TB(Aif&Int7f5E-O}wISUTi#4y{`$D+MtZa23YH#ZQdFR{-He0wcw#;H~e zOO^XXMDXbBBGi9fQurDexO`~jXWS@E{5&X~Tl-iE6O!J~SM`HNW<+K$^&?SzX<9z? z$C!K(XP-sW0t3HaAvcFYpV}fAem5sF%hqyS*tb3Kxtw40yYIz4iNBbnP>hVEjSqETz_U2< zY|2y=+(NT0Jr^6Kyx<)$Q?t%0bDCkw8j3!nr$>pq;BvX*5W58 z$=TNX`bhnC2baEjG!fDVv%VdW$Hd|qzh3)&I2}~y!JH~h1K=e;H=w*VfvC!;;Pq9e z4>IC~fxQ7rR5P?IRS089+pPm;5Q`E2c8 znTjAmLIp!6XDyy4YbrScvf`KwbpUG8|!qE-BKZHM^mR`>hHlksoz^SPF#<#mo{=OXP(jjNH6SNKduYF z1v1eJt*mlazG{6?*a+hXd)L6$tT0E*n|xJHJzV$CJ(B!=0gYTR^0f1K6WaUUJO zAAoxw);4?AZUmB2)XG^5eOz{I2s#gEme>ehnlrWA&>svzO5RhCqq!D~D`O?ujqVP< z#!(cLiCbj-MnRvd1Hs1#31~I?b#*fit8DVSyl=YU*5KOTgP=za-PcS1GYq0K?w8N$ zKeT=s+Ns#{_wcauHu1J_uypfu^mVhaU;u6?t~8B!Kbxf1*!r;%EYuBq7N|)Ff7D4T z<$V~wrO8bG&J93xe!(FRpGY zcfC_jC<-2GYHOK5rsnQ`w$?Z2?E@~*ZG3M~HTX>;c0xTIFY%06D&numd@n*0Yu!@6 zJ?>w-J^g8Tn7>jnyxgkALGnCATm{H-R3zdVUb>wLH`LD^R>p%El<|*4YH?((F@5c` zHY;s_i^T$nj-%O+K?7};o6Whg;XK%0UGt19{OJ0&MA~UTX2NfR;T-X%torrof#Uy2zL{i8ZE)*9aPIehd4xMg|B zFccy%FD}k_4=5-}$%%*@0K_;R%Fj1Q8=nvIu%jy*97A} zf1({GDK_i?TrzimQVE&diR?5M^winG#S51Jfvl@_Kq|68c8ngh2$oH%C|u3LU^O6H z(wy9*TQf_5EXQ3GIe}1?qq^9WEQ=2xjp8f#t7uo-=;;Df<&PWY?OLcL5${bn;=&}; z|By)224AZ>i9~%BTmG_k?jf$?Qp=iibyxE0P-vLGx{FpOZixN|iicP9pe6ZR)2ZdM z_8Qx&f$_|NWs6&{51=$Fwb2aWtr8^*!%piaM3wPlxN3#^n?$C;$acNq&qbVRsUIiC z^K-TUI^Wu)Mc#Yf6(C4c>njdtK{%{%$yJ8o&zN*oJim}?%a-O~yt-4=;oZYWMM^j1*H-T| zKC(z}z*PoG@CwKukehK`oV$%q%U7hczH!xezlN1=DfEr$QM8w5ke0Mn?w#ulyX`;% zq~gt{OV4RkfrA|2ryLS{=7F&N7O|yRwX7A8mQE$^K4fWW>Vb20?P{ftpGjo1(iBiH zs|(CzeM2^_<3w6GxCk|_(*uAVK5AnjnW*3))poC*p)O27nX~Uy`Bh#t1$18x?3`;+ zF0!1L{TLG9be;c`RzFO_X1BRV0K`|+IS1;rRq!@GK%0eRu(;H#HOk;<5Su#h7}f$N zSs7a$*o13U#9y_3O!;L{`0%H`LD?o@yO8Ml53@ceMp=T6FG>mCZNuUyPF}D8B_7JW z+6`@o99i~ioeyf9O~Yep`Po*AI@P(Jd z%(J0!?xTmH@d#cvBP0BEC=u}R0UM1V@^}-0@FfQk2xcJsouq#?e}9y$$7Vpi{zo%# z8wl;1@k99YM)gl3NkQS4(Xazs1mNd@J^qiMGd#K~2+HaRz}EPm&A^wxM7OPFAsiNl z!~Evp`GsG)u@=w&^WlHG@_!%xS6BXj-u>9^|J(c@gZ`h*|1s!)=H%ba|M}m)h5?9? zhzg+FzWwK*fPOuGSVH3eP8cxVz>o3pFOdEpUHkjGCxCh|9A6$Ef3I@P`j4{o|M>d + + + + + + + + + + budget.form (in hotel_data_bi) + budget + +
+ + + + +
+
+
+ + + + + +
+
+
+
+
+
+
+
+
+ + + + budget.tree (in hotel_data_bi) + budget + + + + + + + + + + + +
diff --git a/hotel_data_bi/views/inherit_res_company.xml b/hotel_data_bi/views/inherit_res_company.xml new file mode 100644 index 000000000..2f829839b --- /dev/null +++ b/hotel_data_bi/views/inherit_res_company.xml @@ -0,0 +1,19 @@ + + + + + + + + databi.config.view_company_form + res.company + + + + + + + + + + From ab6c5b0cd82861ad53a33022f5493cf3c11cbf2b Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 11:28:25 +0200 Subject: [PATCH 02/23] [ADD] Tarifa & Canal --- hotel_data_bi/models/data_bi.py | 46 ++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 9812cd70c..42db9834a 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -44,6 +44,7 @@ class Data_Bi(models.Model): Generate a dicctionary to by send in JSON archivo = response file type + archivo == 0 'ALL' archivo == 1 'Tarifa' archivo == 2 'Canal' archivo == 3 'Hotel' @@ -68,11 +69,21 @@ class Data_Bi(models.Model): _logger.warning("Init Export Data_Bi Module") + if not isinstance(archivo, int): + archivo = 0 + dic_param = [] + dic_param.append({'Archivo': archivo, + 'Fechafoto': fechafoto.strftime('%Y-%m-%d')}) + compan = self.env.user.company_id + dic_export = [] # Diccionario con todo lo necesario para exportar. - # if (archivo == 0) or (archivo == 1): - # dic_export.append({'Tarifa': dic_tarifa}) - # if (archivo == 0) or (archivo == 2): - # dic_export.append({'Canal': dic_canal}) + if (archivo == 0) or (archivo == 1): + dic_tarifa = self.data_bi_tarifa(compan.id_hotel) + dic_export.append({'Tarifa': dic_tarifa}) + + if (archivo == 0) or (archivo == 2): + dic_canal = self.data_bi_canal(compan.id_hotel) + dic_export.append({'Canal': dic_canal}) # if (archivo == 0) or (archivo == 3): # dic_export.append({'Hotel': dic_hotel}) # if (archivo == 0) or (archivo == 4): @@ -98,10 +109,31 @@ class Data_Bi(models.Model): # if (archivo == 0) or (archivo == 14): # dic_export.append({'Estado Reservas': dic_estados}) + # Debug Stop ------------------- + import wdb; wdb.set_trace() + # Debug Stop ------------------- dictionaryToJson = json.dumps(dic_export) _logger.warning("End Export Data_Bi Module to Json") - # Debug Stop ------------------- - # import wdb; wdb.set_trace() - # Debug Stop ------------------- return dictionaryToJson + + @api.model + def data_bi_tarifa(self, compan): + dic_tarifa = [] # Diccionario con las tarifas + tarifas = self.env['product.pricelist'].search_read([], ['name']) + for tarifa in tarifas: + dic_tarifa.append({'ID_Hotel': compan, + 'ID_Tarifa': tarifa['id'], + 'Descripcion': tarifa['name']}) + return dic_tarifa + + @api.model + def data_bi_canal(self, compan): + dic_canal = [] # Diccionario con los Canales + canal_array = ['Directo', 'OTA', 'Call-Center', 'Agencia', + 'Touroperador'] + for i in range(0, len(canal_array)): + dic_canal.append({'ID_Hotel': compan, + 'ID_Canal': i, + 'Descripcion': canal_array[i]}) + return dic_canal From 96668b71ca82a5df3bfc5b23bdd3f853fffc3817 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 11:48:22 +0200 Subject: [PATCH 03/23] [ADD] Hotel & Countries --- hotel_data_bi/models/data_bi.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 42db9834a..1c3ecaba0 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -84,10 +84,12 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 2): dic_canal = self.data_bi_canal(compan.id_hotel) dic_export.append({'Canal': dic_canal}) - # if (archivo == 0) or (archivo == 3): - # dic_export.append({'Hotel': dic_hotel}) - # if (archivo == 0) or (archivo == 4): - # dic_export.append({'Pais': dic_pais}) + if (archivo == 0) or (archivo == 3): + dic_hotel = self.data_bi_hotel(compan) + dic_export.append({'Hotel': dic_hotel}) + if (archivo == 0) or (archivo == 4): + dic_pais = self.data_bi_pais(compan.id_hotel) + dic_export.append({'Pais': dic_pais}) # if (archivo == 0) or (archivo == 5): # dic_export.append({'Regimen': dic_regimen}) # if (archivo == 0) or (archivo == 6): @@ -137,3 +139,21 @@ class Data_Bi(models.Model): 'ID_Canal': i, 'Descripcion': canal_array[i]}) return dic_canal + + @api.model + def data_bi_hotel(self, compan): + dic_hotel = [] # Diccionario con el/los nombre de los hoteles + dic_hotel.append({'ID_Hotel': compan.id_hotel, + 'Descripcion': compan.property_name}) + return dic_hotel + + @api.model + def data_bi_pais(self, compan): + dic_pais = [] + # Diccionario con los nombre de los Paises usando los del INE + paises = self.env['code.ine'].search_read([], ['code', 'name']) + for pais in paises: + dic_pais.append({'ID_Hotel': compan, + 'ID_Pais': pais['code'], + 'Descripcion': pais['name']}) + return dic_pais From 68c98764849df35b24634d1640eede3c2eec2455 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 12:01:38 +0200 Subject: [PATCH 04/23] [ADD] Board Services --- hotel_data_bi/models/data_bi.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 1c3ecaba0..c0e5d49ef 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -90,8 +90,9 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 4): dic_pais = self.data_bi_pais(compan.id_hotel) dic_export.append({'Pais': dic_pais}) - # if (archivo == 0) or (archivo == 5): - # dic_export.append({'Regimen': dic_regimen}) + if (archivo == 0) or (archivo == 5): + dic_regimen = self.data_bi_regimen(compan.id_hotel) + dic_export.append({'Regimen': dic_regimen}) # if (archivo == 0) or (archivo == 6): # dic_export.append({'Reservas': dic_reservas}) # if (archivo == 0) or (archivo == 7): @@ -157,3 +158,16 @@ class Data_Bi(models.Model): 'ID_Pais': pais['code'], 'Descripcion': pais['name']}) return dic_pais + + @api.model + def data_bi_regimen(self, compan): + dic_regimen = [] # Diccionario con los Board Services + board_services = self.env['hotel.board.service'].search_read([]) + dic_regimen.append({'ID_Hotel': compan, + 'ID_Regimen': 0, + 'Descripcion': 'Sin régimen'}) + for board_service in board_services: + dic_regimen.append({'ID_Hotel': compan, + 'ID_Regimen': board_service['id'], + 'Descripcion': board_service['name']}) + return dic_regimen From 0c51c26cfb8c0bc48ef6ccaced6a95edeeafb1bc Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 12:29:29 +0200 Subject: [PATCH 05/23] [ADD] Estados --- hotel_data_bi/models/data_bi.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index c0e5d49ef..fce35333c 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -80,7 +80,6 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 1): dic_tarifa = self.data_bi_tarifa(compan.id_hotel) dic_export.append({'Tarifa': dic_tarifa}) - if (archivo == 0) or (archivo == 2): dic_canal = self.data_bi_canal(compan.id_hotel) dic_export.append({'Canal': dic_canal}) @@ -109,8 +108,9 @@ class Data_Bi(models.Model): # dic_export.append({'Segmentos': dic_segmentos}) # if (archivo == 0) or (archivo == 13): # dic_export.append({'Clientes': dic_clientes}) - # if (archivo == 0) or (archivo == 14): - # dic_export.append({'Estado Reservas': dic_estados}) + if (archivo == 0) or (archivo == 14): + dic_estados = self.data_bi_estados(compan.id_hotel) + dic_export.append({'Estado Reservas': dic_estados}) # Debug Stop ------------------- import wdb; wdb.set_trace() @@ -171,3 +171,15 @@ class Data_Bi(models.Model): 'ID_Regimen': board_service['id'], 'Descripcion': board_service['name']}) return dic_regimen + + @api.model + def data_bi_estados(self, compan): + dic_estados = [] # Diccionario con los Estados Reserva + estado_array_txt = ['Borrador', 'Confirmada', 'Hospedandose', + 'Checkout', 'Cancelada'] + estado_array = ['draft', 'confirm', 'booking', 'done', 'cancelled'] + for i in range(0, len(estado_array)): + dic_estados.append({'ID_Hotel': compan, + 'ID_EstadoReserva': i, + 'Descripcion': estado_array_txt[i]}) + return dic_estados From 7ed090290fc5051963b65176019e69184a6c9bb6 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 13:35:46 +0200 Subject: [PATCH 06/23] [ADD] Room tyes & Capacity & Budget --- hotel_data_bi/models/data_bi.py | 70 ++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index fce35333c..3ef31ddb0 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -94,12 +94,18 @@ class Data_Bi(models.Model): dic_export.append({'Regimen': dic_regimen}) # if (archivo == 0) or (archivo == 6): # dic_export.append({'Reservas': dic_reservas}) - # if (archivo == 0) or (archivo == 7): - # dic_export.append({'Capacidad': dic_capacidad}) - # if (archivo == 0) or (archivo == 8): - # dic_export.append({'Tipo Habitación': dic_tipo_habitacion}) - # if (archivo == 0) or (archivo == 9): - # dic_export.append({'Budget': dic_budget}) + if (archivo == 0) or (archivo == 7) or (archivo == 8): + room_types = self.env['hotel.room.type'].search([]) + if (archivo == 0) or (archivo == 7): + dic_capacidad = self.data_bi_capacidad(compan.id_hotel, room_types) + dic_export.append({'Capacidad': dic_capacidad}) + if (archivo == 0) or (archivo == 8): + dic_tipo_habitacion = self.data_bi_habitacione(compan.id_hotel, + room_types) + dic_export.append({'Tipo Habitación': dic_tipo_habitacion}) + if (archivo == 0) or (archivo == 9): + dic_budget = self.data_bi_budget(compan.id_hotel) + dic_export.append({'Budget': dic_budget}) # if (archivo == 0) or (archivo == 10): # dic_export.append({'Bloqueos': dic_bloqueos}) # if (archivo == 0) or (archivo == 11): @@ -183,3 +189,55 @@ class Data_Bi(models.Model): 'ID_EstadoReserva': i, 'Descripcion': estado_array_txt[i]}) return dic_estados + + @api.model + def data_bi_habitacione(self, compan, rooms): + dic_tipo_habitacion = [] # Diccionario con Virtuals Rooms + for room in rooms: + dic_tipo_habitacion.append({ + 'ID_Hotel': compan, + 'ID_Tipo_Habitacion': room['id'], + 'Descripcion': room['name'], + 'Estancias': room['capacity']}) + return dic_tipo_habitacion + + @api.model + def data_bi_capacidad(self, compan, rooms): + dic_capacidad = [] # Diccionario con las capacidades + for room in rooms: + dic_capacidad.append({ + 'ID_Hotel': compan, + 'Hasta_Fecha': + (date.today() + timedelta(days=365 * 3)).strftime("%Y-%m-%d"), + 'ID_Tipo_Habitacion': room['id'], + 'Nro_Habitaciones': room['total_rooms_count']}) + return dic_capacidad + + @api.model + def data_bi_budget(self, compan): + budgets = self.env['budget'].search([]) + dic_budget = [] # Diccionario con las previsiones Budget + for budget in budgets: + dic_budget.append({'ID_Hotel': compan, + 'Fecha': str(budget.year) + '-' + + str(budget.month).zfill(2) + '-01', + # 'ID_Tarifa': 0, + # 'ID_Canal': 0, + # 'ID_Pais': 0, + # 'ID_Regimen': 0, + # 'ID_Tipo_Habitacion': 0, + # 'ID_Cliente': 0, + 'Room_Nights': budget.room_nights, + 'Room_Revenue': budget.room_revenue, + # 'Pension_Revenue': 0, + 'Estancias': budget.estancias}) + # Fecha fecha Primer día del mes + # ID_Tarifa numérico Código de la Tarifa + # ID_Canal numérico Código del Canal + # ID_Pais numérico Código del País + # ID_Regimen numérico Cóigo del Régimen + # ID_Tipo_Habitacion numérico Código del Tipo de Habitación + # iD_Segmento numérico Código del Segmento + # ID_Cliente numérico Código del Cliente + # Pension_Revenue numérico con dos decimales Ingresos por Pensión + return dic_budget From f7fb1cf47724316941282846eea08e7b5a57c332 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 13:42:28 +0200 Subject: [PATCH 07/23] [ADD] Reason for blocking --- hotel_data_bi/models/data_bi.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 3ef31ddb0..a0bfacdad 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -108,8 +108,9 @@ class Data_Bi(models.Model): dic_export.append({'Budget': dic_budget}) # if (archivo == 0) or (archivo == 10): # dic_export.append({'Bloqueos': dic_bloqueos}) - # if (archivo == 0) or (archivo == 11): - # dic_export.append({'Motivo Bloqueo': dic_moti_bloq}) + if (archivo == 0) or (archivo == 11): + dic_moti_bloq = self.data_bi_moti_bloq(compan.id_hotel) + dic_export.append({'Motivo Bloqueo': dic_moti_bloq}) # if (archivo == 0) or (archivo == 12): # dic_export.append({'Segmentos': dic_segmentos}) # if (archivo == 0) or (archivo == 13): @@ -241,3 +242,14 @@ class Data_Bi(models.Model): # ID_Cliente numérico Código del Cliente # Pension_Revenue numérico con dos decimales Ingresos por Pensión return dic_budget + + @api.model + def data_bi_moti_bloq(self, compan): + dic_moti_bloq = [] # Diccionario con Motivo de Bloqueos + bloqeo_array = ['Staff', _('Out of Service')] + for i in range(0, len(bloqeo_array)): + dic_moti_bloq.append({'ID_Hotel': compan, + 'ID_Motivo_Bloqueo': i, + 'Descripcion': bloqeo_array[i].encode( + 'ascii', 'xmlcharrefreplace')}) + return dic_moti_bloq From 478a4b1ed4e151dd9db4c32f37ac508c2ff90108 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 14:08:29 +0200 Subject: [PATCH 08/23] [ADD] Segmentation --- hotel_data_bi/models/data_bi.py | 37 ++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index a0bfacdad..843cf9945 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -111,24 +111,26 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 11): dic_moti_bloq = self.data_bi_moti_bloq(compan.id_hotel) dic_export.append({'Motivo Bloqueo': dic_moti_bloq}) - # if (archivo == 0) or (archivo == 12): - # dic_export.append({'Segmentos': dic_segmentos}) + if (archivo == 0) or (archivo == 12): + dic_segmentos = self.data_bi_segment(compan.id_hotel) + dic_export.append({'Segmentos': dic_segmentos}) # if (archivo == 0) or (archivo == 13): # dic_export.append({'Clientes': dic_clientes}) if (archivo == 0) or (archivo == 14): dic_estados = self.data_bi_estados(compan.id_hotel) dic_export.append({'Estado Reservas': dic_estados}) + dictionaryToJson = json.dumps(dic_export) + _logger.warning("End Export Data_Bi Module to Json") # Debug Stop ------------------- import wdb; wdb.set_trace() # Debug Stop ------------------- - dictionaryToJson = json.dumps(dic_export) - _logger.warning("End Export Data_Bi Module to Json") return dictionaryToJson @api.model def data_bi_tarifa(self, compan): + _logger.info("DataBi: Calculating all fees") dic_tarifa = [] # Diccionario con las tarifas tarifas = self.env['product.pricelist'].search_read([], ['name']) for tarifa in tarifas: @@ -139,6 +141,7 @@ class Data_Bi(models.Model): @api.model def data_bi_canal(self, compan): + _logger.info("DataBi: Calculating all channels") dic_canal = [] # Diccionario con los Canales canal_array = ['Directo', 'OTA', 'Call-Center', 'Agencia', 'Touroperador'] @@ -150,6 +153,7 @@ class Data_Bi(models.Model): @api.model def data_bi_hotel(self, compan): + _logger.info("DataBi: Calculating hotel names") dic_hotel = [] # Diccionario con el/los nombre de los hoteles dic_hotel.append({'ID_Hotel': compan.id_hotel, 'Descripcion': compan.property_name}) @@ -157,6 +161,7 @@ class Data_Bi(models.Model): @api.model def data_bi_pais(self, compan): + _logger.info("DataBi: Calculating all countries") dic_pais = [] # Diccionario con los nombre de los Paises usando los del INE paises = self.env['code.ine'].search_read([], ['code', 'name']) @@ -168,6 +173,7 @@ class Data_Bi(models.Model): @api.model def data_bi_regimen(self, compan): + _logger.info("DataBi: Calculating all board services") dic_regimen = [] # Diccionario con los Board Services board_services = self.env['hotel.board.service'].search_read([]) dic_regimen.append({'ID_Hotel': compan, @@ -181,6 +187,7 @@ class Data_Bi(models.Model): @api.model def data_bi_estados(self, compan): + _logger.info("DataBi: Calculating all the states of the reserves") dic_estados = [] # Diccionario con los Estados Reserva estado_array_txt = ['Borrador', 'Confirmada', 'Hospedandose', 'Checkout', 'Cancelada'] @@ -193,7 +200,8 @@ class Data_Bi(models.Model): @api.model def data_bi_habitacione(self, compan, rooms): - dic_tipo_habitacion = [] # Diccionario con Virtuals Rooms + _logger.info("DataBi: Calculating all room types") + dic_tipo_habitacion = [] # Diccionario con Rooms types for room in rooms: dic_tipo_habitacion.append({ 'ID_Hotel': compan, @@ -204,6 +212,7 @@ class Data_Bi(models.Model): @api.model def data_bi_capacidad(self, compan, rooms): + _logger.info("DataBi: Calculating all the capacitys") dic_capacidad = [] # Diccionario con las capacidades for room in rooms: dic_capacidad.append({ @@ -216,6 +225,7 @@ class Data_Bi(models.Model): @api.model def data_bi_budget(self, compan): + _logger.info("DataBi: Calculating budget") budgets = self.env['budget'].search([]) dic_budget = [] # Diccionario con las previsiones Budget for budget in budgets: @@ -245,11 +255,24 @@ class Data_Bi(models.Model): @api.model def data_bi_moti_bloq(self, compan): + _logger.info("DataBi: Calculating all blocking reasons") dic_moti_bloq = [] # Diccionario con Motivo de Bloqueos bloqeo_array = ['Staff', _('Out of Service')] for i in range(0, len(bloqeo_array)): dic_moti_bloq.append({'ID_Hotel': compan, 'ID_Motivo_Bloqueo': i, - 'Descripcion': bloqeo_array[i].encode( - 'ascii', 'xmlcharrefreplace')}) + 'Descripcion': bloqeo_array[i]}) return dic_moti_bloq + + @api.model + def data_bi_segment(self, compan): + _logger.info("DataBi: Calculating all the segmentations") + dic_segmentos = [] # Diccionario con Segmentación + lineas = self.env['res.partner.category'].search([]) + for linea in lineas: + if linea.parent_id.name: + seg_desc = linea.parent_id.name + " / " + linea.name + dic_segmentos.append({'ID_Hotel': compan, + 'ID_Segmento': linea.id, + 'Descripcion': seg_desc}) + return dic_segmentos From 48d55d48eae33bc101c4d621361b8294ca2af073 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Tue, 30 Apr 2019 20:28:14 +0200 Subject: [PATCH 09/23] [ADD] Clients --- hotel_data_bi/models/data_bi.py | 57 +++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 843cf9945..2e9623940 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -114,8 +114,9 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 12): dic_segmentos = self.data_bi_segment(compan.id_hotel) dic_export.append({'Segmentos': dic_segmentos}) - # if (archivo == 0) or (archivo == 13): - # dic_export.append({'Clientes': dic_clientes}) + if (archivo == 0) or (archivo == 13): + dic_clientes = self.data_bi_client(compan.id_hotel) + dic_export.append({'Clientes': dic_clientes}) if (archivo == 0) or (archivo == 14): dic_estados = self.data_bi_estados(compan.id_hotel) dic_export.append({'Estado Reservas': dic_estados}) @@ -276,3 +277,55 @@ class Data_Bi(models.Model): 'ID_Segmento': linea.id, 'Descripcion': seg_desc}) return dic_segmentos + + @api.model + def data_bi_client(self, compan): + dic_clientes = [] # Diccionario con Clientes (OTAs y agencias) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 0, + 'Descripcion': u'Ninguno'}) + lineas = self.env['channel.ota.info'].search([]) + + for linea in lineas: + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': linea.id, + 'Descripcion': linea.name}) + + lineas = self.env['res.partner'].search([('is_tour_operator', + '=', True)]) + id_cli_count = 700 + for linea in lineas: + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': id_cli_count, + 'Descripcion': linea.name}) + id_cli_count += 1 + + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 999, + 'Descripcion': u'Web Propia'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 901, + 'Descripcion': u'Expedia Empaquedata'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 902, + 'Descripcion': u'Expedia Sin Comisión'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 903, + 'Descripcion': u'Puerta'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 904, + 'Descripcion': u'E-Mail'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 905, + 'Descripcion': u'Teléfono'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 906, + 'Descripcion': u'Call-Center'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 907, + 'Descripcion': u'Agencia'}) + dic_clientes.append({'ID_Hotel': compan, + 'ID_Cliente': 908, + 'Descripcion': u'Touroperador'}) + + return dic_clientes From 5c7903c99b1d0f0b4c47f3529cc49d2b6f4edc3d Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Thu, 2 May 2019 13:47:38 +0200 Subject: [PATCH 10/23] [ADD] calculation of locked rooms --- hotel_data_bi/models/data_bi.py | 38 ++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 2e9623940..4abd18212 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -68,7 +68,6 @@ class Data_Bi(models.Model): fechafoto = datetime.strptime(fechafoto, '%Y-%m-%d').date() _logger.warning("Init Export Data_Bi Module") - if not isinstance(archivo, int): archivo = 0 dic_param = [] @@ -76,6 +75,9 @@ class Data_Bi(models.Model): 'Fechafoto': fechafoto.strftime('%Y-%m-%d')}) compan = self.env.user.company_id + days_ago = 60 + limit_ago = (fechafoto - timedelta(days=days_ago)).strftime('%Y-%m-%d') + dic_export = [] # Diccionario con todo lo necesario para exportar. if (archivo == 0) or (archivo == 1): dic_tarifa = self.data_bi_tarifa(compan.id_hotel) @@ -106,8 +108,11 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 9): dic_budget = self.data_bi_budget(compan.id_hotel) dic_export.append({'Budget': dic_budget}) - # if (archivo == 0) or (archivo == 10): - # dic_export.append({'Bloqueos': dic_bloqueos}) + if (archivo == 0) or (archivo == 10): + line_res = self.env['hotel.reservation.line'].search( + [('date', '>=', limit_ago)], order="date") + dic_bloqueos = self.data_bi_bloqueos(compan.id_hotel, line_res) + dic_export.append({'Bloqueos': dic_bloqueos}) if (archivo == 0) or (archivo == 11): dic_moti_bloq = self.data_bi_moti_bloq(compan.id_hotel) dic_export.append({'Motivo Bloqueo': dic_moti_bloq}) @@ -329,3 +334,30 @@ class Data_Bi(models.Model): 'Descripcion': u'Touroperador'}) return dic_clientes + + @api.model + def data_bi_bloqueos(self, compan, lines): + _logger.info("DataBi: Calculating all reservations blocked") + dic_bloqueos = [] # Diccionario con Bloqueos + lines = lines.filtered( + lambda n: (n.reservation_id.reservation_type != 'normal') and ( + n.reservation_id.state != 'cancelled')) + for line in lines: + # if linea.reservation_id.state != 'cancelled': + if line.reservation_id.reservation_type == 'out': + id_m_b = 1 + else: + id_m_b = 0 + dic_bloqueos.append({ + 'ID_Hotel': compan, + 'Fecha_desde': line.date, + 'Fecha_hasta': (datetime.strptime(line.date, "%Y-%m-%d") + + timedelta(days=1)).strftime("%Y-%m-%d"), + 'ID_Tipo_Habitacion': line.reservation_id.room_type_id.id, + 'ID_Motivo_Bloqueo': id_m_b, + 'Nro_Habitaciones': 1}) + return dic_bloqueos + + # # Debug Stop ------------------- + # import wdb; wdb.set_trace() + # # Debug Stop ------------------- From c86ff3f6f44b1d0f515383d115552106ba3d1dea Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Thu, 9 May 2019 18:54:35 +0200 Subject: [PATCH 11/23] [ADD] Expedia comision rate field --- hotel_data_bi/models/inherit_res_company.py | 11 +++++++++++ hotel_data_bi/views/inherit_res_company.xml | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hotel_data_bi/models/inherit_res_company.py b/hotel_data_bi/models/inherit_res_company.py index f33265dc0..303bf541a 100644 --- a/hotel_data_bi/models/inherit_res_company.py +++ b/hotel_data_bi/models/inherit_res_company.py @@ -11,3 +11,14 @@ class Inherit_res_company(models.Model): 'Unique ID for DataBI', default=0, help='It must be unique to be able to identify the hotel, \ within a hotel group.') + expedia_rate = fields.Integer( + 'Expedia Rate DataBI', + default=18, required=True, digits=(2), + help='It is the commission percentage negotiated with the \ + Expedia company, expressed with two digits. \ + Example: 18 = 18% commission.') + data_bi_days = fields.Integer( + 'Days to download', + default=60, required=True, digits=(3), + help='Number of days, which are downloaded data, \ + backwards, by default are 60 days to download.') diff --git a/hotel_data_bi/views/inherit_res_company.xml b/hotel_data_bi/views/inherit_res_company.xml index 2f829839b..05b3865ab 100644 --- a/hotel_data_bi/views/inherit_res_company.xml +++ b/hotel_data_bi/views/inherit_res_company.xml @@ -10,7 +10,11 @@ - + + + + + From cbaf0fd8fa17d4caeec2445920c05e5e689c3287 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Thu, 9 May 2019 21:17:06 +0200 Subject: [PATCH 12/23] [ADD] reservations calculus --- hotel_data_bi/models/data_bi.py | 221 +++++++++++++++++++++++++++++--- 1 file changed, 203 insertions(+), 18 deletions(-) diff --git a/hotel_data_bi/models/data_bi.py b/hotel_data_bi/models/data_bi.py index 4abd18212..bd7ce8ec4 100644 --- a/hotel_data_bi/models/data_bi.py +++ b/hotel_data_bi/models/data_bi.py @@ -19,7 +19,7 @@ # along with this program. If not, see . # ############################################################################## -from openerp import models, fields, api, _ +from openerp import models, api, _ from datetime import date, datetime, timedelta import json import logging @@ -74,11 +74,17 @@ class Data_Bi(models.Model): dic_param.append({'Archivo': archivo, 'Fechafoto': fechafoto.strftime('%Y-%m-%d')}) compan = self.env.user.company_id - - days_ago = 60 - limit_ago = (fechafoto - timedelta(days=days_ago)).strftime('%Y-%m-%d') + limit_ago = (fechafoto - timedelta( + days=self.env.user.company_id.data_bi_days)).strftime('%Y-%m-%d') dic_export = [] # Diccionario con todo lo necesario para exportar. + if (archivo == 0) or (archivo == 7) or (archivo == 8): + room_types = self.env['hotel.room.type'].search([]) + if (archivo == 0) or (archivo == 10) or (archivo == 6): + line_res = self.env['hotel.reservation.line'].search( + [('date', '>=', limit_ago)], order="id") + estado_array = ['draft', 'confirm', 'booking', 'done', 'cancelled'] + if (archivo == 0) or (archivo == 1): dic_tarifa = self.data_bi_tarifa(compan.id_hotel) dic_export.append({'Tarifa': dic_tarifa}) @@ -94,10 +100,6 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 5): dic_regimen = self.data_bi_regimen(compan.id_hotel) dic_export.append({'Regimen': dic_regimen}) - # if (archivo == 0) or (archivo == 6): - # dic_export.append({'Reservas': dic_reservas}) - if (archivo == 0) or (archivo == 7) or (archivo == 8): - room_types = self.env['hotel.room.type'].search([]) if (archivo == 0) or (archivo == 7): dic_capacidad = self.data_bi_capacidad(compan.id_hotel, room_types) dic_export.append({'Capacidad': dic_capacidad}) @@ -109,8 +111,6 @@ class Data_Bi(models.Model): dic_budget = self.data_bi_budget(compan.id_hotel) dic_export.append({'Budget': dic_budget}) if (archivo == 0) or (archivo == 10): - line_res = self.env['hotel.reservation.line'].search( - [('date', '>=', limit_ago)], order="date") dic_bloqueos = self.data_bi_bloqueos(compan.id_hotel, line_res) dic_export.append({'Bloqueos': dic_bloqueos}) if (archivo == 0) or (archivo == 11): @@ -119,17 +119,23 @@ class Data_Bi(models.Model): if (archivo == 0) or (archivo == 12): dic_segmentos = self.data_bi_segment(compan.id_hotel) dic_export.append({'Segmentos': dic_segmentos}) - if (archivo == 0) or (archivo == 13): + if (archivo == 0) or (archivo == 13) or (archivo == 6): dic_clientes = self.data_bi_client(compan.id_hotel) dic_export.append({'Clientes': dic_clientes}) if (archivo == 0) or (archivo == 14): - dic_estados = self.data_bi_estados(compan.id_hotel) + dic_estados = self.data_bi_estados(compan.id_hotel, estado_array) dic_export.append({'Estado Reservas': dic_estados}) + if (archivo == 0) or (archivo == 6): + dic_reservas = self.data_bi_reservas(compan.id_hotel, + line_res, + estado_array, + dic_clientes) + dic_export.append({'Reservas': dic_reservas}) dictionaryToJson = json.dumps(dic_export) _logger.warning("End Export Data_Bi Module to Json") # Debug Stop ------------------- - import wdb; wdb.set_trace() + # import wdb; wdb.set_trace() # Debug Stop ------------------- return dictionaryToJson @@ -149,8 +155,8 @@ class Data_Bi(models.Model): def data_bi_canal(self, compan): _logger.info("DataBi: Calculating all channels") dic_canal = [] # Diccionario con los Canales - canal_array = ['Directo', 'OTA', 'Call-Center', 'Agencia', - 'Touroperador'] + canal_array = ['Puerta', 'Mail', 'Telefono', 'Call Center', 'Web', + 'Agencia', 'Touroperador', 'Virtual Door'] for i in range(0, len(canal_array)): dic_canal.append({'ID_Hotel': compan, 'ID_Canal': i, @@ -192,12 +198,12 @@ class Data_Bi(models.Model): return dic_regimen @api.model - def data_bi_estados(self, compan): + def data_bi_estados(self, compan, estado_array): _logger.info("DataBi: Calculating all the states of the reserves") dic_estados = [] # Diccionario con los Estados Reserva estado_array_txt = ['Borrador', 'Confirmada', 'Hospedandose', 'Checkout', 'Cancelada'] - estado_array = ['draft', 'confirm', 'booking', 'done', 'cancelled'] + # estado_array = ['draft', 'confirm', 'booking', 'done', 'cancelled'] for i in range(0, len(estado_array)): dic_estados.append({'ID_Hotel': compan, 'ID_EstadoReserva': i, @@ -332,7 +338,6 @@ class Data_Bi(models.Model): dic_clientes.append({'ID_Hotel': compan, 'ID_Cliente': 908, 'Descripcion': u'Touroperador'}) - return dic_clientes @api.model @@ -358,6 +363,186 @@ class Data_Bi(models.Model): 'Nro_Habitaciones': 1}) return dic_bloqueos + @api.model + def data_bi_reservas(self, compan, lineas, estado_array, dic_clientes): + dic_reservas = [] + lineas = lineas.filtered( + lambda n: (n.reservation_id.reservation_type == 'normal') and ( + n.price > 0)) + channels = {'door': 0, + 'mail': 1, + 'phone': 2, + 'call': 3, + 'web': 4, + 'agency': 5, + 'operator': 6, + 'virtualdoor': 7} + + for linea in lineas: + id_segmen = 0 + if len(linea.reservation_id.segmentation_ids) > 0: + id_segmen = linea.reservation_id.segmentation_ids[0].id + elif len(linea.reservation_id.partner_id.category_id) > 0: + id_segmen = ( + linea.reservation_id.partner_id.category_id[0].id) + precio_neto = linea.price + precio_dto = 0 + precio_iva = 0 + precio_comision = 0 + + if linea.reservation_id.ota_id.id: + ota_prices = self.data_bi_comisiones_ota(linea) + precio_neto = ota_prices[0]['precio_neto'] + precio_dto = ota_prices[0]['precio_dto'] + precio_iva = ota_prices[0]['precio_iva'] + precio_comision = ota_prices[0]['precio_comision'] + + # if linea.reservation_id.id == 6742: + # # # Debug Stop ------------------- + # import wdb; wdb.set_trace() + # # # Debug Stop ------------------- + if linea.reservation_id.discount != 0: + precio_dto = linea.price * ( + linea.reservation_id.discount/100) + + dic_reservas.append({ + 'ID_Reserva': linea.reservation_id.folio_id.name, + 'ID_Hotel': compan, + 'ID_EstadoReserva': estado_array.index( + linea.reservation_id.state), + 'FechaVenta': linea.reservation_id.create_date[0:10], + 'ID_Segmento': id_segmen, + # 'ID_Cliente': channel_c, + 'ID_Canal': channels[linea.reservation_id.channel_type], + 'FechaExtraccion': date.today().strftime('%Y-%m-%d'), + 'Entrada': linea.date, + 'Salida': (datetime.strptime(linea.date, "%Y-%m-%d") + + timedelta(days=1)).strftime("%Y-%m-%d"), + 'Noches': 1, + 'ID_TipoHabitacion': linea.reservation_id.room_type_id.id, + 'ID_HabitacionDuerme': + linea.reservation_id.room_id.room_type_id.id, + 'ID_Regimen': 0, + 'Adultos': linea.reservation_id.adults, + 'Menores': linea.reservation_id.children, + 'Cunas': 0, + 'PrecioDiario': precio_neto, + 'PrecioComision': precio_comision, + 'PrecioIva': precio_iva, + 'PrecioDto': precio_dto, + 'ID_Tarifa': linea.reservation_id.pricelist_id.id, + # 'ID_Pais': id_codeine + }) + # ID_Reserva numérico Código único de la reserva + # ID_Hotel numérico Código del Hotel + # ID_EstadoReserva numérico Código del estado de la reserva + # FechaVenta fecha Fecha de la venta de la reserva + # ID_Segmento numérico Código del Segmento de la reserva + # ID_Cliente Numérico Código del Cliente de la reserva + # ID_Canal numérico Código del Canal + # FechaExtraccion fecha Fecha de la extracción de los datos (Foto) + # Entrada fecha Fecha de entrada + # Salida fecha Fecha de salida + # Noches numérico Nro. de noches de la reserva + # ID_TipoHabitacion numérico Código del Tipo de Habitación + # ID_Regimen numérico Código del Tipo de Régimen + # Adultos numérico Nro. de adultos + # Menores numérico Nro. de menores + # Cunas numérico Nro. de cunas + # PrecioDiario numérico con 2 decimales Precio por noche de la reserva + # ID_Tarifa numérico Código de la tarifa aplicada a la reserva + # ID_Pais numérico Código del país + return dic_reservas + + @api.model + def data_bi_comisiones_ota(self, reserva): + response_dic = [] + precio_neto = reserva.price + precio_comision = 0 + precio_iva = 0 + precio_dto = 0 + if reserva.reservation_id.ota_id.ota_id == "2": + # Booking. 15% comision + precio_comision = (precio_neto*15/100) + precio_neto -= precio_comision + precio_iva = (precio_neto*10/100) + precio_neto -= precio_iva + + if reserva.reservation_id.ota_id.ota_id == "9": + # Hotelbeds 20% comision + precio_comision = (precio_neto*20/100) + precio_neto -= precio_comision + precio_iva = (precio_neto*10/100) + precio_neto -= precio_iva + + if reserva.reservation_id.ota_id.ota_id == "11": + # HRS 20% comision + precio_comision = (precio_neto*20/100) + precio_neto -= precio_comision + precio_iva = (precio_neto*10/100) + precio_neto -= precio_iva + + if reserva.reservation_id.ota_id.ota_id == "1": + # Expedia. + precio_comision = (precio_neto*15/100) + precio_neto -= precio_comision + precio_iva = (precio_neto*10/100) + precio_neto -= precio_iva + data = json.loads( + reserva.reservation_id.channel_bind_ids.channel_raw_data) + + jsonBooked = data['booked_rooms'][0] + if jsonBooked.get('ancillary').get( + 'channel_rate_name') is not None: + jsonRate = jsonBooked.get('ancillary').get( + 'channel_rate_name') + # _logger.warning("EXPEDIA ancillary : %s - %s", + # jsonRate, reserva.id) + + elif jsonBooked.get('roomdays')[0].get( + 'ancillary').get( + 'channel_rate_name') is not None: + jsonRate = jsonBooked.get( + 'roomdays')[0].get( + 'ancillary').get('channel_rate_name') + # _logger.warning("EXPEDIA roomdays : %s - %s", + # jsonRate, reserva.id) + + else: + _logger.critical( + "EXPEDIA Tarifa No Contemplada : " + + jsonBooked) + + jsonRefundable = jsonRate.upper().find('REFUNDABLE') + # _logger.warning("EXPEDIA Tarifa : %s", jsonRate) + # _logger.warning("EXPEDIA Tarifa : %s y %s", + # jsonRate, str(jsonRefundable)) + + # 10 % Iva + precio_iva = round((precio_neto-(precio_neto/1.1)), 2) + # 18 % comision ? + precio_comision = inv_percent( + precio_neto, self.env.user.company_id.expedia_rate) + precio_neto += precio_comision + # 3% Refundable ? + if jsonRefundable >= 0: + precio_dto = inv_percent(precio_neto, 3) + precio_neto += precio_dto + # _logger.warning("ODOO: %s , precio_neto: %s , precio_comision: \ + # %s , precio_iva: %s , precio_dto: %s", reserva.price, + # precio_neto, precio_comision, precio_iva, + # precio_dto) + + response_dic.append({'ota': reserva.reservation_id.ota_id.id, + 'ota_id': reserva.reservation_id.ota_id.ota_id, + 'precio_odoo': reserva.price, + 'precio_neto': precio_neto, + 'precio_comision': precio_comision, + 'precio_iva': precio_iva, + 'precio_dto': precio_dto, + }) + return response_dic + # # Debug Stop ------------------- # import wdb; wdb.set_trace() # # Debug Stop ------------------- From 264ae5db18bb47061b240ee97025d199657b91b1 Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 10 May 2019 13:09:32 +0200 Subject: [PATCH 13/23] [ADD] add rate plan id from wubook --- .../models/channel_backend/common.py | 6 ++++++ .../models/hotel_reservation/importer.py | 8 ++++++++ .../views/inherited_channel_connector_backend_views.xml | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/hotel_channel_connector_wubook/models/channel_backend/common.py b/hotel_channel_connector_wubook/models/channel_backend/common.py index 3c3197d30..db7f59134 100644 --- a/hotel_channel_connector_wubook/models/channel_backend/common.py +++ b/hotel_channel_connector_wubook/models/channel_backend/common.py @@ -22,10 +22,16 @@ class ChannelBackend(models.Model): def _get_default_server(self): return 'https://wired.wubook.net/xrws/' + def _get_default_wubook_parity(self): + return self.env['ir.default'].sudo().get('res.config.settings', 'default_pricelist_id') + lcode = fields.Char('Channel Service lcode') pkey = fields.Char('Channel Service PKey') server = fields.Char('Channel Service Server', default=_get_default_server) + wubook_parity_pricelist_id = fields.Many2one('product.pricelist', 'WuBook Parity Pricelist', + required=True, + default=_get_default_wubook_parity) @contextmanager @api.multi diff --git a/hotel_channel_connector_wubook/models/hotel_reservation/importer.py b/hotel_channel_connector_wubook/models/hotel_reservation/importer.py index e05277326..b8c81b667 100644 --- a/hotel_channel_connector_wubook/models/hotel_reservation/importer.py +++ b/hotel_channel_connector_wubook/models/hotel_reservation/importer.py @@ -121,6 +121,8 @@ class HotelReservationImporter(Component): if 'tax_inclusive' in broom['ancillary'] and not broom['ancillary']['tax_inclusive']: _logger.info("--- Incoming Reservation without taxes included!") tax_inclusive = False + # rate_id ( 0: WuBook Parity (aka standard rate); > 0: the id of the booked pricing plan) + rate_id = 0 # Generate Reservation Day Lines reservation_lines = [] tprice = 0.0 @@ -141,6 +143,11 @@ class HotelReservationImporter(Component): 'price': room_day_price, })) tprice += room_day_price + rate_id = brday['rate_id'] + # TODO: Review different pricelist in the different booked rooms (folio in Odoo) + rate_id = rate_id > 0 and rate_id or self.env['channel.backend'].sudo().search([ + ('id', '=', self.backend_record.id) + ]).wubook_parity_pricelist_id # Get OTA ota_id = self.env['channel.ota.info'].search([ ('backend_id', '=', self.backend_record.id), @@ -163,6 +170,7 @@ class HotelReservationImporter(Component): 'checkout': checkout_str, 'adults': persons, 'children': book['children'], + 'pricelist_id': rate_id.id, 'reservation_line_ids': reservation_lines, 'to_assign': True, 'state': is_cancellation and 'cancelled' or 'confirm', diff --git a/hotel_channel_connector_wubook/views/inherited_channel_connector_backend_views.xml b/hotel_channel_connector_wubook/views/inherited_channel_connector_backend_views.xml index 4014bed20..b21995300 100644 --- a/hotel_channel_connector_wubook/views/inherited_channel_connector_backend_views.xml +++ b/hotel_channel_connector_wubook/views/inherited_channel_connector_backend_views.xml @@ -9,6 +9,15 @@ + + + + + + + + + From 6069513d02e8160075a119e430091615e8d23c3a Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Fri, 10 May 2019 14:24:01 +0200 Subject: [PATCH 14/23] [ADD] Security in DataBi --- hotel_data_bi/security/ir.model.access.csv | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hotel_data_bi/security/ir.model.access.csv b/hotel_data_bi/security/ir.model.access.csv index a8f8fab40..99a2df307 100644 --- a/hotel_data_bi/security/ir.model.access.csv +++ b/hotel_data_bi/security/ir.model.access.csv @@ -2,3 +2,13 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink ir_model_hotel_budget,hoteldatabi.budget.manager,hotel_data_bi.model_budget,hotel.group_hotel_manager,1,1,1,1 ir_model_hotel_budget_user,hoteldatabi.budget.user,hotel_data_bi.model_budget,hotel.group_hotel_user,0,0,0,0 ir_model_hotel_data_bi_export_data,hoteldatabi.data_bi.export_data,hotel_data_bi.model_data_bi,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_room_type,hoteldatabi.hotel_room_type,hotel.model_hotel_room_type,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_hotel_reservation_line,hoteldatabi.hotel_reservation_line,hotel.model_hotel_reservation_line,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_hotel_reservation,hoteldatabi.hotel_reservation,hotel.model_hotel_reservation,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_hotel_board_service,hoteldatabi.hotel_board_service,hotel.model_hotel_board_service,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_code_ine,hoteldatabi.code_ine,hotel_l10n_es.model_code_ine,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_budget ,hoteldatabi.budget,hotel_data_bi.model_budget,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_channel_ota_info,hoteldatabi.channel_ota_info,hotel_channel_connector.model_channel_ota_info,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_hotel_folio,hoteldatabi.hotel_folio,hotel.model_hotel_folio,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_hotel_room,hoteldatabi.hotel_room,hotel.model_hotel_room,hotel_data_bi.group_hotel_export_data,1,0,0,0 +access_channel_hotel_reservation,hoteldatabi.channel_hotel_reservation,hotel_channel_connector.model_channel_hotel_reservation,hotel_data_bi.group_hotel_export_data,1,0,0,0 From c31a1a3554abf1790d59e2f21bbcd320abdbdd79 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Fri, 10 May 2019 14:24:36 +0200 Subject: [PATCH 15/23] [FIX] depends --- hotel_data_bi/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotel_data_bi/__manifest__.py b/hotel_data_bi/__manifest__.py index e0ca740b2..2b398871e 100644 --- a/hotel_data_bi/__manifest__.py +++ b/hotel_data_bi/__manifest__.py @@ -16,7 +16,7 @@ 'license': 'AGPL-3', 'author': "Jose Luis Algara (Alda hotels) ", 'website': 'www.aldahotels.com', - 'depends': ['hotel', 'hotel_l10n_es'], + 'depends': ['hotel', 'hotel_l10n_es', 'hotel_channel_connector'], 'category': 'hotel/revenue', 'data': [ 'views/budget.xml', From 05bc5921e87808f7efd5aa4cda6b96a1c265c6f6 Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Fri, 10 May 2019 21:55:20 +0200 Subject: [PATCH 16/23] [DEL] Readonly checkin fields --- .../inherit_hotel_checkin_partner_views.xml | 39 ++++--------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml b/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml index b263b170b..853dd6c65 100755 --- a/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml +++ b/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml @@ -69,42 +69,19 @@ + ]}" /> + ]}" /> - - - - - + ]}" /> + + + + + {"no_create": True} From 8fc258dc634bcd69319128bf74a373193455d8df Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Fri, 10 May 2019 23:23:39 +0200 Subject: [PATCH 17/23] [ADD] Avoid create room from folio form --- hotel/views/hotel_reservation_views.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index 0e0b223ed..cafbe4e78 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -395,7 +395,7 @@ OverBooking!

+ options="{'no_create': True,'no_open': True}" style="margin-right: 30px;" /> @@ -463,7 +463,7 @@ 'exit_date': checkout,'reservation_id': id, 'hidden_checkin_partner': True, 'edit_checkin_partner': True }" attrs="{'invisible':['|','|', ('state','not in',('confirm','booking')),('checkin_partner_pending_count','=', 0),('parent_reservation','!=',False)]}" /> - + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + hotel.shared.room.kanban + hotel.shared.room + kanban + + + false + + + + +
+
+
    +
  • + +
  • +
  • Room Type:
  • +
  • + Beds +
  • +
+
+
+
+
+
+
+
+ + + + hotel.shared.room.search + hotel.shared.room + + + + + + + + + + + + hotel.shared.room.tree + hotel.shared.room + + + + + + + + + + + + + + Hotel Shared Room + hotel.shared.room + form + + + kanban,tree,form + + + + + diff --git a/hotel_calendar/models/inherited_hotel_reservation.py b/hotel_calendar/models/inherited_hotel_reservation.py index 234697d86..7fa767d11 100644 --- a/hotel_calendar/models/inherited_hotel_reservation.py +++ b/hotel_calendar/models/inherited_hotel_reservation.py @@ -141,7 +141,7 @@ class HotelReservation(models.Model): 'capacity': room.capacity, 'class_name': room.room_type_id.class_id.name, 'class_id': room.room_type_id.class_id.id, - 'shared': room.shared_room, + 'shared_id': room.shared_room_id, 'price': room.room_type_id and ['pricelist', room.room_type_id.id, pricelist_id, room.room_type_id.name] or 0, diff --git a/hotel_channel_connector/models/hotel_room_type/common.py b/hotel_channel_connector/models/hotel_room_type/common.py index 629988c64..8c5b6224a 100644 --- a/hotel_channel_connector/models/hotel_room_type/common.py +++ b/hotel_channel_connector/models/hotel_room_type/common.py @@ -31,8 +31,8 @@ class ChannelHotelRoomType(models.Model): string='Room Type', required=True, ondelete='cascade') - channel_short_code = fields.Char("Channel Short Code", old_name='wscode') - ota_capacity = fields.Integer("OTA's Capacity", default=1, old_name='wcapacity', + channel_short_code = fields.Char("Channel Short Code") + ota_capacity = fields.Integer("OTA's Capacity", default=1, help="The capacity of the room for OTAs.") default_quota = fields.Integer("Default Quota", @@ -52,8 +52,8 @@ class ChannelHotelRoomType(models.Model): max_price = fields.Float('Max. Price', default=200.0, digits=dp.get_precision('Product Price'), help="Setup the max price to prevent incidents while editing your prices.") - @api.onchange('default_quota', 'default_max_avail') - def _onchange_availability(self): + @api.constrains('default_quota', 'default_max_avail', 'total_rooms_count') + def _constrains_availability(self): for rec in self: to_eval = [] to_eval.append(rec.total_rooms_count) @@ -64,8 +64,8 @@ class ChannelHotelRoomType(models.Model): rec.default_availability = min(to_eval) - @api.onchange('room_ids') - def _get_capacity(self): + @api.constrains('room_ids') + def _constrain_capacity(self): for rec in self: rec.ota_capacity = rec.odoo_id.get_capacity() From 9fdd42200e149f38a543b6a7a141baeeaa1597ed Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Mon, 13 May 2019 10:25:20 +0200 Subject: [PATCH 23/23] [IMP] Translates --- hotel/i18n/es.po | 3220 +++++++++++++++++++++------------------------- 1 file changed, 1447 insertions(+), 1773 deletions(-) diff --git a/hotel/i18n/es.po b/hotel/i18n/es.po index 27f44e1d2..f5586adac 100644 --- a/hotel/i18n/es.po +++ b/hotel/i18n/es.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-04-28 21:22+0000\n" -"PO-Revision-Date: 2019-04-28 23:37+0200\n" +"POT-Creation-Date: 2019-05-13 08:15+0000\n" +"PO-Revision-Date: 2019-05-13 10:24+0200\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -17,6 +17,1057 @@ msgstr "" "Language: es\n" "X-Generator: Poedit 1.8.7.1\n" +#. module: hotel +#: model:mail.template,body_html:hotel.mail_template_hotel_cancel +msgid "" +"\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +" \"Alda\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" www.aldahotels.com\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
Tu reserva se ha cancelado en ${object.company_id.property_name}
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"\n" +"
\n" +"
Hola ${object.partner_id.firstname}
\n" +" Tu reserva en ${object.company_id.property_name} se ha anulado correctamente. No es necesario que hagas nada más.\n" +" Si la cancelación conlleva la devolución de alguna cantidad, nos pondremos en contacto contigo.\n" +" En caso de que tengas alguna duda, estaremos encantados de atenderte.\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +"
Contactar\n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \"Cancelación\"\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
Datos de tu reserva cancelada
\n" +" ${object.partner_id.name}\n" +"
\n" +" % if object.partner_id.contact_address:\n" +" ${object.partner_id.contact_address}
\n" +" % endif\n" +"
\n" +" % for rline in object.get_grouped_reservations_json('cancelled'):\n" +" ${rline['num']} x ${rline['room_type']['name']}\n" +" % if rline['childrens'] > 0:\n" +" (${rline['adults']} Adults + ${rline['childrens']} Childrens)\n" +" % else:\n" +" (${rline['adults']} Adults)\n" +" %endif\n" +" \n" +"
\n" +" Entrada: ${format_tz(rline['checkin'], format=\"%d de %B de %Y\")}
\n" +" Salida: ${format_tz(rline['checkout'], format=\"%d de %B de %Y\")}
\n" +" Nº de noches: ${rline['nights']}

\n" +" % endfor\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \"Pago\"\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
IMPORTES
\n" +" Noches: ${len(object.room_lines[0].reservation_lines)}
\n" +" Base imponible: ${object.amount_untaxed} €
\n" +" I.V.A (10%): ${object.amount_tax} €
\n" +" Precio total: ${object.amount_total} €
\n" +" Coste de cancelación: [[importe]]
\n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
NUESTRAS REDES SOCIALES 
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"Facebook\"\n" +" \n" +"
Facebook
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"
\n" +"
Toda la actualidad de nuestros alojamientos, así como ofertas y promociones.
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +"
Dale a Me gusta
\n" +"
\n" +" \n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"Instagram\"\n" +" \n" +"
Instagram
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"
\n" +"
Cada detalle cuenta, y es por eso que tratamos de reflejarlo en nuestras fotos.
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +"
#Entra\n" +"
\n" +"
\n" +" \n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"Twitter\"\n" +" \n" +"
Twitter
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"
\n" +"
Propuestas al minuto para hacer de tu viaje una experiencia inmejorable.
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +"
Síguenos\n" +"
\n" +"
\n" +" \n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
¡Esperamos verte pronto!
\n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +" \"Alda\n" +" \n" +" \n" +" \n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información y del Comercio Electrónico, así como de la Ley Orgánica 15/1999 del 13 de Diciembre de Protección de Datos de Carácter Personal y demás legislación concordante, se le informa que sus datos personales figuran en un fichero automatizado cuya responsabilidad es de ALDA COMPOSTELA S.L. Praza da Algalia de Arriba, 3 C.P. 15704 Santiago de Compostela. Los datos personales que existen en nuestro poder están protegidos por nuestra Política de Privacidad y solo serán utilizados para los fines propios de nuestra actividad. Para ejercer sus derechos de acceso, rectificación, cancelación u oposición debe enviar un correo electrónico a info@aldahotels.com indicándonos la opción a realizar. Este correo podría ser confidencial. Si recibe este e-mail por error, por favor elimínelo, así como cualquier documento adjunto, y notifíquelo a su emisor. Si usted no es el destinatario del mensaje, sepa que no está permitida ninguna difusión, copia o utilización no autorizada.
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" Antes de imprimir este mensaje, compruebe que es verdaderamente necesario. El medioambiente es cosa de todos. \n" +"
\n" +"
\n" +" \n" +"
\n" +"
\n" +" \n" +" " +msgstr "" +"\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +" \"Alda\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" www.aldahotels.com\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
Tu reserva se ha cancelado en ${object.company_id.property_name}
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"\n" +"
\n" +"
Hola ${object.partner_id.firstname}
\n" +" Tu reserva en ${object.company_id.property_name} se ha anulado correctamente. No es necesario que hagas nada más.\n" +" Si la cancelación conlleva la devolución de alguna cantidad, nos pondremos en contacto contigo.\n" +" En caso de que tengas alguna duda, estaremos encantados de atenderte.\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +"
Contactar\n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \"Cancelación\"\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
Datos de tu reserva cancelada
\n" +" ${object.partner_id.name}\n" +"
\n" +" % if object.partner_id.contact_address:\n" +" ${object.partner_id.contact_address}
\n" +" % endif\n" +"
\n" +" % for rline in object.get_grouped_reservations_json('cancelled'):\n" +" ${rline['num']} x ${rline['room_type']['name']}\n" +" % if rline['childrens'] > 0:\n" +" (${rline['adults']} Adults + ${rline['childrens']} Childrens)\n" +" % else:\n" +" (${rline['adults']} Adults)\n" +" %endif\n" +" \n" +"
\n" +" Entrada: ${format_tz(rline['checkin'], format=\"%d de %B de %Y\")}
\n" +" Salida: ${format_tz(rline['checkout'], format=\"%d de %B de %Y\")}
\n" +" Nº de noches: ${rline['nights']}

\n" +" % endfor\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \"Pago\"\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
IMPORTES
\n" +" Noches: ${len(object.room_lines[0].reservation_lines)}
\n" +" Base imponible: ${object.amount_untaxed} €
\n" +" I.V.A (10%): ${object.amount_tax} €
\n" +" Precio total: ${object.amount_total} €
\n" +" Coste de cancelación: [[importe]]
\n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
NUESTRAS REDES SOCIALES 
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"Facebook\"\n" +" \n" +"
Facebook
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"
\n" +"
Toda la actualidad de nuestros alojamientos, así como ofertas y promociones.
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +"
Dale a Me gusta
\n" +"
\n" +" \n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"Instagram\"\n" +" \n" +"
Instagram
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"
\n" +"
Cada detalle cuenta, y es por eso que tratamos de reflejarlo en nuestras fotos.
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +"
#Entra\n" +"
\n" +"
\n" +" \n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \"Twitter\"\n" +" \n" +"
Twitter
\n" +" \n" +" \n" +" \n" +" \n" +"
 \n" +"
\n" +"
Propuestas al minuto para hacer de tu viaje una experiencia inmejorable.
\n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +"
Síguenos\n" +"
\n" +"
\n" +" \n" +"
\n" +"
\n" +"
\n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
¡Esperamos verte pronto!
\n" +"
\n" +" \n" +" \n" +" \n" +"
\n" +" \"Alda\n" +" \n" +" \n" +" \n" +"
\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información y del Comercio Electrónico, así como de la Ley Orgánica 15/1999 del 13 de Diciembre de Protección de Datos de Carácter Personal y demás legislación concordante, se le informa que sus datos personales figuran en un fichero automatizado cuya responsabilidad es de ALDA COMPOSTELA S.L. Praza da Algalia de Arriba, 3 C.P. 15704 Santiago de Compostela. Los datos personales que existen en nuestro poder están protegidos por nuestra Política de Privacidad y solo serán utilizados para los fines propios de nuestra actividad. Para ejercer sus derechos de acceso, rectificación, cancelación u oposición debe enviar un correo electrónico a info@aldahotels.com indicándonos la opción a realizar. Este correo podría ser confidencial. Si recibe este e-mail por error, por favor elimínelo, así como cualquier documento adjunto, y notifíquelo a su emisor. Si usted no es el destinatario del mensaje, sepa que no está permitida ninguna difusión, copia o utilización no autorizada.
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" Antes de imprimir este mensaje, compruebe que es verdaderamente necesario. El medioambiente es cosa de todos. \n" +"
\n" +"
\n" +" \n" +"
\n" +"
\n" +" \n" +" " + #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_product_variant_count msgid "# Product Variants" @@ -49,7 +1100,7 @@ msgid "%s limit exceeded for %s" msgstr "%s limite excedido por %s" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:655 +#: code:addons/hotel/models/hotel_reservation.py:653 #, python-format msgid "%s people do not fit in this room! ;)" msgstr "%s personas no caben en esta habitación!" @@ -171,1395 +1222,6 @@ msgstr "Total" msgid "Your Reference:" msgstr "Su referencia:" -#. module: hotel -#: model:mail.template,body_html:hotel.mail_template_hotel_cancel -msgid "" -"\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Alda\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" www.aldahotels.com\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
Tu reserva se ha cancelado en ${object.company_id.property_name}
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
 \n" -"\n" -"
\n" -"
Hola ${object.partner_id.firstname}
\n" -" Tu reserva en ${object.company_id.property_name} se ha anulado correctamente. No es necesario que hagas nada más.\n" -" Si la cancelación conlleva la devolución de alguna cantidad, nos pondremos en contacto contigo.\n" -" En caso de que tengas alguna duda, estaremos encantados de atenderte.\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -"
Contactar\n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Cancelación\"\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
Datos de tu reserva cancelada
\n" -" ${object.partner_id.name}\n" -"
\n" -" % if object.partner_id.contact_address:\n" -" ${object.partner_id.contact_address}
\n" -" % endif\n" -"
\n" -" % for rline in object.get_grouped_reservations_json('cancelled'):\n" -" ${rline['num']} x ${rline['room_type']['name']}\n" -" % if rline['childrens'] > 0:\n" -" (${rline['adults']} Adults + ${rline['childrens']} Childrens)\n" -" % else:\n" -" (${rline['adults']} Adults)\n" -" %endif\n" -" \n" -"
\n" -" Entrada: ${format_tz(rline['checkin'], format=\"%d de %B de %Y\")}
\n" -" Salida: ${format_tz(rline['checkout'], format=\"%d de %B de %Y\")}
\n" -" Nº de noches: ${rline['nights']}

\n" -" % endfor\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Pago\"\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
IMPORTES
\n" -" Noches: ${len(object.room_lines[0].reservation_lines)}
\n" -" Base imponible: ${object.amount_untaxed} €
\n" -" I.V.A (10%): ${object.amount_tax} €
\n" -" Precio total: ${object.amount_total} €
\n" -" Coste de cancelación: [[importe]]
\n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
NUESTRAS REDES SOCIALES 
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \"Facebook\"\n" -" \n" -"
Facebook
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
 \n" -"
\n" -"
Toda la actualidad de nuestros alojamientos, así como ofertas y promociones.
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
Dale\n" -" a Me gusta
\n" -"
\n" -" \n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \"Instagram\"\n" -" \n" -"
Instagram
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
 \n" -"
\n" -"
Cada detalle cuenta, y es por eso que tratamos de reflejarlo en nuestras fotos.
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
#Entra\n" -"
\n" -"
\n" -" \n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \"Twitter\"\n" -" \n" -"
Twitter
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
 \n" -"
\n" -"
Propuestas al minuto para hacer de tu viaje una experiencia inmejorable.
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
Síguenos\n" -"
\n" -"
\n" -" \n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
¡Esperamos verte\n" -" pronto!
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Alda\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
“En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información y del Comercio Electrónico (LSSI-CE), así como lo dispuesto en el Reglamento General de Protección de Datos y demás legislación concordante, le informamos de que sus datos personales figuran en un sistema de tratamiento automatizado cuya responsabilidad es de Hoteles Rías Altas SL, con dirección postal a efecto de notificación en PLAZA DE ALGALIA DE ARRIBA, Nº 3 – 15704 SANTIAGO DE COMPOSTELA. Los datos personales que existen en nuestro poder están protegidos por nuestra Política de Privacidad y serán tratados con la finalidad de atender su solicitud de información o contacto, así como mantenerle informado de nuestros productos y servicios, actuales o futuros. Los datos no se cederán a terceros salvo en los casos en que exista una obligación legal. Para ejercer sus derechos de acceso, rectificación, cancelación, oposición, limitación, supresión y/o portabilidad debe enviar un correo electrónico a protecciondatos@aldahotels.com” “Este correo podría ser confidencial. Si recibe este e-mail por error, por favor elimínelo, así como cualquier documento adjunto, y notifíquelo a su emisor. Si usted no es el destinatario del mensaje, sepa que no está permitida ninguna difusión, copia o utilización no autorizada.”
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" Antes de imprimir este mensaje, compruebe que es verdaderamente necesario. El medioambiente es cosa de todos. \n" -"
\n" -"
\n" -" \n" -"
\n" -"
\n" -msgstr "" -"\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Alda\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" www.aldahotels.com\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
Tu reserva se ha cancelado en ${object.company_id.property_name}
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"\n" -"
\n" -"
Hola ${object.partner_id.firstname}
\n" -" Tu reserva en ${object.company_id.property_name} se ha anulado correctamente. No es necesario que hagas nada más.\n" -" Si la cancelación conlleva la devolución de alguna cantidad, nos pondremos en contacto contigo.\n" -" En caso de que tengas alguna duda, estaremos encantados de atenderte.\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -"
Contactar\n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Cancelación\"\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
Datos de tu reserva cancelada
\n" -" ${object.partner_id.name}\n" -"
\n" -" % if object.partner_id.contact_address:\n" -" ${object.partner_id.contact_address}
\n" -" % endif\n" -"
\n" -" % for rline in object.get_grouped_reservations_json('cancelled'):\n" -" \n" -" ${rline['num']} x ${rline['room_type']['name']}\n" -" % if rline['childrens'] == 0:\n" -" (${rline['adults']} Adultos)\n" -" % else:\n" -" (${rline['adults']} Adultos + ${rline['childrens']} Niños)\n" -" % endif\n" -"
\n" -"
\n" -"
\n" -" Entrada: ${format_tz(rline['checkin']+ ' 00:00:00', format=\"%d de %B de %Y\")}
\n" -" Salida: ${format_tz(rline['checkout']+ ' 00:00:00', format=\"%d de %B de %Y\")}
\n" -" Nº de noches: ${rline['nights']}

\n" -" % endfor\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Pago\"\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
IMPORTES
\n" -" Noches: ${len(object.room_lines[0].reservation_lines)}
\n" -" Base imponible: ${object.amount_untaxed} €
\n" -" I.V.A (10%): ${object.amount_tax} €
\n" -" Precio total: ${object.amount_total} €
\n" -" Coste de cancelación: [[importe]]
\n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
NUESTRAS REDES SOCIALES
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \"Facebook\"\n" -" \n" -"
Facebook
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
Toda la actualidad de nuestros alojamientos, así como ofertas y promociones.
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
Dale\n" -" a Me gusta
\n" -"
\n" -" \n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \"Instagram\"\n" -" \n" -"
Instagram
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
Cada detalle cuenta, y es por eso que tratamos de reflejarlo en nuestras fotos.
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
#Entra\n" -"
\n" -"
\n" -" \n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \"Twitter\"\n" -" \n" -"
Twitter
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -"
Propuestas al minuto para hacer de tu viaje una experiencia inmejorable.
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
Síguenos\n" -"
\n" -"
\n" -" \n" -"
\n" -"
\n" -"
\n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
¡Esperamos verte\n" -" pronto!
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \"Alda\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
“En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información y del Comercio Electrónico (LSSI-CE), así como lo dispuesto en el Reglamento General de Protección de Datos y demás legislación concordante, le informamos de que sus datos personales figuran en un sistema de tratamiento automatizado cuya responsabilidad es de Hoteles Rías Altas SL, con dirección postal a efecto de notificación en PLAZA DE ALGALIA DE ARRIBA, Nº 3 – 15704 SANTIAGO DE COMPOSTELA. Los datos personales que existen en nuestro poder están protegidos por nuestra Política de Privacidad y serán tratados con la finalidad de atender su solicitud de información o contacto, así como mantenerle informado de nuestros productos y servicios, actuales o futuros. Los datos no se cederán a terceros salvo en los casos en que exista una obligación legal. Para ejercer sus derechos de acceso, rectificación, cancelación, oposición, limitación, supresión y/o portabilidad debe enviar un correo electrónico a protecciondatos@aldahotels.com” “Este correo podría ser confidencial. Si recibe este e-mail por error, por favor elimínelo, así como cualquier documento adjunto, y notifíquelo a su emisor. Si usted no es el destinatario del mensaje, sepa que no está permitida ninguna difusión, copia o utilización no autorizada.”
\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" Antes de imprimir este mensaje, compruebe que es verdaderamente necesario. El medioambiente es cosa de todos. \n" -"
\n" -"
\n" -" \n" -"
\n" -"
\n" - #. module: hotel #: model:mail.template,body_html:hotel.mail_template_hotel_reservation msgid "" @@ -1571,34 +1233,28 @@ msgid "" " padding: 0;\n" " min-width: 100% !important;\n" " }\n" -"\n" " a {\n" " color: #5e96ea;\n" " text-decoration: none;\n" " font-weight: bold;\n" " }\n" -"\n" " img {\n" " height: auto;\n" " }\n" -"\n" " .content {\n" " border: 1px solid #eeeeee;\n" " }\n" -"\n" " .logo {\n" " font-family: sans-serif;\n" " font-size: 36px;\n" " font-weight: bold;\n" " color: #ffffff;\n" " }\n" -"\n" " .link a {\n" " font-family: sans-serif;\n" " font-size: 12px;\n" " color: #ffffff;\n" " }\n" -"\n" " .subheading {\n" " font-size: 14px;\n" " color: #cccccc;\n" @@ -1608,7 +1264,6 @@ msgid "" " text-transform: uppercase;\n" " letter-spacing: 1px;\n" " }\n" -"\n" " .h1 {\n" " font-family: sans-serif;\n" " font-size: 48px;\n" @@ -1617,7 +1272,6 @@ msgid "" " color: #ffffff;\n" " padding: 0 0 0 0;\n" " }\n" -"\n" " .h2 {\n" " font-family: sans-serif;\n" " font-size: 18px;\n" @@ -1627,7 +1281,6 @@ msgid "" " text-transform: uppercase;\n" " letter-spacing: 0.5px;\n" " }\n" -"\n" " .h3 {\n" " font-family: sans-serif;\n" " font-size: 24px;\n" @@ -1635,7 +1288,6 @@ msgid "" " color: #555555;\n" " padding: 0 0 0 0;\n" " }\n" -"\n" " .h4 {\n" " font-family: sans-serif;\n" " font-size: 18px;\n" @@ -1643,7 +1295,6 @@ msgid "" " color: #666666;\n" " padding: 0 0 0 0;\n" " }\n" -"\n" " .paragraph {\n" " font-family: sans-serif;\n" " font-size: 14px;\n" @@ -1652,7 +1303,6 @@ msgid "" " font-weight: 200;\n" " padding: 20px 0 0 0;\n" " }\n" -"\n" " .listitem {\n" " font-family: sans-serif;\n" " font-size: 15px;\n" @@ -1660,39 +1310,32 @@ msgid "" " font-weight: 200;\n" " padding: 0 0 20px 0;\n" " }\n" -"\n" " .smalltext {\n" " font-family: sans-serif;\n" " font-size: 14px;\n" " color: #cccccc;\n" " padding: 3px 0 0 0;\n" " }\n" -"\n" " .borderbottom {\n" " border-bottom: 1px solid #f2eeed;\n" " }\n" -"\n" " /*Media Queries*/\n" " @media only screen and (max-width: 651px) {\n" " .columns {\n" " width: 100% !important;\n" " }\n" -"\n" " .columncontainer {\n" " display: block !important;\n" " width: 100% !important;\n" " }\n" -"\n" " .paragraph,\n" " .listitem {\n" " font-size: 18px;\n" " }\n" -"\n" " .link {\n" " float: left;\n" " }\n" " }\n" -"\n" " @media only screen and (min-width: 651px) {\n" " .content {\n" " width: 650px !important;\n" @@ -1859,13 +1502,13 @@ msgid "" " \n" " \"Restauracion\"\n" " \n" -" Restauración\n" +" Desayunos\n" " \n" " \n" " \n" " \"Parking\"\n" " \n" -" Parking\n" +" Parking concertado\n" " \n" " \n" " \n" @@ -2180,8 +1823,7 @@ msgid "" " conocer como llegar desde su ubicación actual\n" "

\n" "\n" -"

Si vienes en coche, podrás aparcar en los alrededores del hotel, aunque la zona de playa cuenta con zona azul. También disponemos de parking propio para clientes (bajo disponibilidad).

\n" -" \n" +"

Si vienes en coche, podrás aparcar en los alrededores del hotel, aunque cuentan con zona azul, de lunes a viernes, de 10:00 a 14:00 h y de 16:00 a 20:00 h. Los sábados de 10:00 a 14:00 h. También disponemos de convenio con un parking en la misma calle del hotel.

\n" " \n" " \n" " \n" @@ -2222,8 +1864,7 @@ msgid "" " \n" " \n" " \n" -" Si vienes en autobús podrás venir desde A Coruña en las líneas 20, 22 y 1A, que te dejarán cerca de Ponte da Pasaxe. Desde allí, tendrás unos 15 minutos andando hasta el hotel.
\n" -" \n" +" Si vienes en autobús, la mayoría de líneas tienen parada en la Plaza de Galicia. Una vez en esta parada, el hotel se cuentra a 5 minutos andando.
\n" " \n" " \n" " \n" @@ -2253,7 +1894,7 @@ msgid "" " ${object.company_id.city}\n" " \n" " \n" -" Santa Cristina es un lugar privilegiado. Playas de arena fina y blanca, paisajes impresionantes y unos alrededores dignos de conocer.\n" +" Ciudad declarada Patrimonio de la Humanidad por la UNESCO y meta de una milenaria ruta de peregrinación: el Camino de Santiago.\n" " \n" " \n" " \n" @@ -2264,7 +1905,7 @@ msgid "" "
\n" " \n" " \n" " \n" -"

Si vienes en coche, podrás aparcar en los alrededores del hotel, aunque la zona de playa cuenta con zona azul. También disponemos de parking propio para clientes (bajo disponibilidad).

\n" -" \n" +"

Si vienes en coche, podrás aparcar en los alrededores del hotel, aunque cuentan con zona azul, de lunes a viernes, de 10:00 a 14:00 h y de 16:00 a 20:00 h. Los sábados de 10:00 a 14:00 h. También disponemos de convenio con un parking en la misma calle del hotel.

\n" " \n" " \n" " \n" @@ -3248,8 +2869,7 @@ msgstr "" " \n" " \n" " \n" -" Si vienes en autobús podrás venir desde A Coruña en las líneas 20, 22 y 1A, que te dejarán cerca de Ponte da Pasaxe. Desde allí, tendrás unos 15 minutos andando hasta el hotel.
\n" -" \n" +" Si vienes en autobús, la mayoría de líneas tienen parada en la Plaza de Galicia. Una vez en esta parada, el hotel se cuentra a 5 minutos andando.
\n" " \n" " \n" " \n" @@ -3279,7 +2899,7 @@ msgstr "" " ${object.company_id.city}\n" " \n" " \n" -" Santa Cristina es un lugar privilegiado. Playas de arena fina y blanca, paisajes impresionantes y unos alrededores dignos de conocer.\n" +" Ciudad declarada Patrimonio de la Humanidad por la UNESCO y meta de una milenaria ruta de peregrinación: el Camino de Santiago.\n" " \n" " \n" " \n" @@ -3290,7 +2910,7 @@ msgstr "" "
\n" " \n" " \n" " \n" " \n" -" \n" +"
\n" "\n" " \n" -" \n" +" \n" "
\n" -" \n" -" \n" +"
\n" +" \n" " \n" -"
\n" -" \"Alda\n" -" \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" -"
\n" -" \n" -" \n" -"
www.aldahotels.com\n" +"
\n" +" \"Alda\n" +" \n" +" \n" +" \n" " \n" -"
\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" -"
www.aldahotels.com\n" "
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" " \n" " \n" "\n" @@ -4258,104 +3878,104 @@ msgstr "" " \n" " \n" " \n" -" \n" -" \n" -"
¡Muchas gracias por tu visita!\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" " \n" " \n" -"
¡Muchas gracias por tu visita!\n" "
\n" -"

__

\n" +"
\n" +"

__

\n" "
Hola ${object.partner_id.firstname},
\n" -" Esperamos que hayas disfrutado de la ciudad, y que muy especialmente te hayas sentido a gusto en nuestro alojamiento. Todo el equipo de ${object.company_id.property_name} te agradece tu estancia en nuestro centro y te desea un feliz regreso.
\n" -" Recibe un cordial saludo y esperamos volver a verte.
\n" +"
Hola ${object.partner_id.firstname},
\n" +" Esperamos que hayas disfrutado de la ciudad, y que muy especialmente te hayas sentido a gusto en nuestro alojamiento. Todo el equipo de ${object.company_id.property_name} te agradece tu estancia en nuestro centro y te desea un feliz regreso.
\n" +" Recibe un cordial saludo y esperamos volver a verte.
\n" "
\n" +"
\n" " \n" " \n" " \n" " \n" " \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" -"
Disfruta de tu descuento de cliente\n" +" \n" +" \n" +" \n" " \n" -"
\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" " \n" -"
Disfruta de tu descuento de cliente\n" "
\n" -"

__

\n" +"
\n" +"

__

\n" "
\n" -" \n" -" \n" -"
Solo por ser cliente de Alda Hotels disfruta, automáticamente, de hasta un 10% de descuento en cualquiera de nuestros establecimientos, totalmente transferible y sin fecha de caducidad.
\n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" " \n" -"
Solo por ser cliente de Alda Hotels disfruta, automáticamente, de hasta un 10% de descuento en cualquiera de nuestros establecimientos, totalmente transferible y sin fecha de caducidad.
\n" "
\n" +"
\n" "
\n" -" \"Descuento\n" -" \n" -" \n" +"
\n" +" \"Descuento\n" +" \n" +" \n" " \n" -"
\n" +"
\n" "
\n" +"
\n" " \n" " \n" " \n" " \n" " \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" -"
¿Tienes algo que comentarnos?\n" +" \n" +" \n" +" \n" " \n" -"
\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" " \n" -"
¿Tienes algo que comentarnos?\n" "
\n" -"

__

\n" +"
\n" +"

__

\n" "
\n" -" \n" -" \n" -"
Cada día intentamos dar un mejor servicio, es por ello que si quieres aportar alguna propuesta o crítica constructiva, te invitamos a utilizar el siguiente formulario. Estamos encantados de recibir tus propuestas. Todas serán leídas y tenidas en cuenta, y atenderemos aquellas que nos permitan nuestros medios y posibilidades.
\n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" " \n" -"
Cada día intentamos dar un mejor servicio, es por ello que si quieres aportar alguna propuesta o crítica constructiva, te invitamos a utilizar el siguiente formulario. Estamos encantados de recibir tus propuestas. Todas serán leídas y tenidas en cuenta, y atenderemos aquellas que nos permitan nuestros medios y posibilidades.
\n" "
\n" +" \n" " \n" -" \n" -"
\n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" " \n" " \n" -"
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" " \n" " \n" " \n" @@ -4396,58 +4016,58 @@ msgstr "" " \n" " \n" " \n" -" \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" -" \n" -"
\n" -" \"Localización\"\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" -"
\n" +" \"Localización\"\n" "
\n" +"
\n" "
\n" -" \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" -" \n" +" \n" +"
nuestros alojamientos\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" -"
nuestros alojamientos
Descubre dónde estamos\n" +" Descubre dónde estamos\n" "
Estamos presentes a lo largo del territorio peninsular. Si quieres saber dónde puedes alojarte con nosotros, pincha en el mapa.
\n" +"
Estamos presentes a lo largo del territorio peninsular. Si quieres saber dónde puedes alojarte con nosotros, pincha en el mapa.
\n" "
\n" +"
\n" "
\n" -" \"Mapa\"\n" +" \"Mapa\"\n" " \n" -" \n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" " \n" " \n" -"
\n" -"
\n" +"
\n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" +"
\n" "
\n" +" \n" " \n" " \n" " \n" @@ -4461,60 +4081,60 @@ msgstr "" " \n" " \n" " \n" -" \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" " \n" " \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" +"
\n" +" \n" +" \n" +" \n" " \n" -"
\n" +" \n" +" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" +"
\n" "
\n" +"
\n" "
\n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" +"
\n" "
\n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" +"
\n" "
\n" -" \n" -" \n" -"
\n" -" \n" -" \n" +" \n" " \n" -"
\n" +" \n" +" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" " \n" " \n" " \n" " \n" " \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" " \n" -"
NUESTRAS REDES SOCIALES\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" @@ -4523,103 +4143,103 @@ msgstr "" " \n" " \n" " \n" -"
NUESTRAS REDES SOCIALES\n" "  \n" "
\n" +"
\n" "
\n" +"
\n" " \n" " \n" " \n" " \n" " \n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" -" \n" -" \n" " \n" -"
\n" -" \n" -" \n" -"
\"Facebook\"\n" +" \n" +" \n" +" \n" " \n" -"
\n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" +" \n" " \n" " \n" -" \n" " \n" -"
\"Facebook\"\n" "
Facebook Facebook
\n" -" \n" -" \n" -"
 \n" +" \n" +" \n" +" \n" +" \n" " \n" -"
 \n" "
\n" +"
\n" "
Toda la actualidad de nuestros alojamientos, así como ofertas y promociones. Toda la actualidad de nuestros alojamientos, así como ofertas y promociones.
\n" -" \n" -" \n" -"
\n" +" \n" +" \n" +" \n" +" \n" " \n" -"
\n" " \n" "\n" -" \n" -"
Dale a Me gusta
\n" +"
\n" +"
Dale a Me gusta
\n" "
\n" " \n" "
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" "
\n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" " \n" -"
\"Instagram\"\n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" -"
\"Instagram\"\n" "
Instagram Instagram
\n" -" \n" -" \n" -"
 \n" +" \n" +" \n" +" \n" +" \n" " \n" -"
 \n" "
\n" +"
\n" "
Cada detalle cuenta, y es por eso que tratamos de reflejarlo en nuestras fotos.\n" +" Cada detalle cuenta, y es por eso que tratamos de reflejarlo en nuestras fotos.\n" "
\n" -" \n" -" \n" -"
\n" +" \n" +" \n" +" \n" +" \n" " \n" -"
\n" " \n" -" \n" -"
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" "
\n" -" \n" -" \n" -"
\n" -" \n" -" \n" -" \n" " \n" -"
\"Twitter\"\n" +" \n" +" \n" +" \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" " \n" -" \n" " \n" -"
\"Twitter\"\n" "
Twitter\n" +" Twitter\n" "
\n" -" \n" -" \n" -"
 \n" +" \n" +" \n" +" \n" +" \n" " \n" -"
 \n" "
\n" +"
\n" "
Propuestas al minuto para hacer de tu viaje una experiencia inmejorable.\n" +" Propuestas al minuto para hacer de tu viaje una experiencia inmejorable.\n" "
\n" -" \n" -" \n" -"
\n" +" \n" +" \n" +" \n" +" \n" " \n" -"
\n" " \n" -" \n" -"
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" "
\n" +"
\n" " \n" " \n" " \n" @@ -4697,49 +4317,49 @@ msgstr "" " \n" " \n" " \n" -" \n" -" \n" -"
¡Muchas gracias por alojarte con nosotros!\n" +" \n" +" \n" +" \n" " \n" " \n" " \n" -"
¡Muchas gracias por alojarte con nosotros!\n" "
\n" +"
\n" " \n" " \n" " \n" -" \n" -" \n" -" \n" +"
\n" +" \n" +" \n" " \n" -"
\n" -" \"Alda\n" -" \n" -" \n" +"
\n" +" \"Alda\n" +" \n" +" \n" " \n" -"
\n" +"
\n" " \n" " \n" " \n" " \n" -" \n" -" \n" -" \n" -" \n" +"
En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información y del Comercio Electrónico, así como de la Ley Orgánica 15/1999 del 13 de Diciembre de Protección de Datos de Carácter Personal y demás legislación concordante, se le informa que sus datos personales figuran en un fichero automatizado cuya responsabilidad es de ALDA COMPOSTELA S.L. Praza da Algalia de Arriba, 3 C.P. 15704 Santiago de Compostela. Los datos personales que existen en nuestro poder están protegidos por nuestra Política de Privacidad y solo serán utilizados para los fines propios de nuestra actividad. Para ejercer sus derechos de acceso, rectificación, cancelación u oposición debe enviar un correo electrónico a info@aldahotels.com indicándonos la opción a realizar. Este correo podría ser confidencial. Si recibe este e-mail por error, por favor elimínelo, así como cualquier documento adjunto, y notifíquelo a su emisor. Si usted no es el destinatario del mensaje, sepa que no está permitida ninguna difusión, copia o utilización no autorizada.\n" +" \n" +" \n" +" \n" " \n" " \n" " \n" -"
En cumplimiento de la Ley 34/2002 de Servicios de la Sociedad de la Información y del Comercio Electrónico, así como de la Ley Orgánica 15/1999 del 13 de Diciembre de Protección de Datos de Carácter Personal y demás legislación concordante, se le informa que sus datos personales figuran en un fichero automatizado cuya responsabilidad es de ALDA COMPOSTELA S.L. Praza da Algalia de Arriba, 3 C.P. 15704 Santiago de Compostela. Los datos personales que existen en nuestro poder están protegidos por nuestra Política de Privacidad y solo serán utilizados para los fines propios de nuestra actividad. Para ejercer sus derechos de acceso, rectificación, cancelación u oposición debe enviar un correo electrónico a info@aldahotels.com indicándonos la opción a realizar. Este correo podría ser confidencial. Si recibe este e-mail por error, por favor elimínelo, así como cualquier documento adjunto, y notifíquelo a su emisor. Si usted no es el destinatario del mensaje, sepa que no está permitida ninguna difusión, copia o utilización no autorizada.
\n" -" \n" -" \n" -"
Antes de imprimir este mensaje, compruebe que es verdaderamente necesario. El medioambiente es cosa de todos. \n" +"
\n" +" \n" +" \n" +" \n" " \n" " \n" -"
Antes de imprimir este mensaje, compruebe que es verdaderamente necesario. El medioambiente es cosa de todos. \n" "
\n" +"
\n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" -" \n" +" \n" "
" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_description_sale +#: model:ir.model.fields,help:hotel.field_hotel_shared_room_description_sale msgid "A description of the Product that you want to communicate to your customers. This description will be copied to every Sales Order, Delivery Order and Customer Invoice/Credit Note" msgstr "Descripción que quieras comunicar a tus cleintes. Este descripción será copiada en los pedidos de venta, y otros documentos de cliente" @@ -4778,15 +4399,15 @@ msgid "" "A service is a non-material product you provide.\n" "A digital content is a non-material product you sell online. The files attached to the products are the one that are sold on the e-commerce such as e-books, music, pictures,... The \"Digital Product\" module has to be installed." msgstr "" -"Un producto almacenable es un producto para el que gestiona el stock. La aplicación \"Inventario\" debe instalarse.\n" +"Un producto almacenable es un producto para el que usted gestiona el stock. La aplicación \"Inventario\" debe instalarse.\n" "Por el contrario, un producto consumible es un producto para el que no se gestiona el stock.\n" "Un servicio es un producto no material que usted proporciona.\n" -"Un contenido digital es un producto no material que vende en línea. Los archivos adjuntos a los productos son los que se venden en el comercio electrónico, tales como libros electrónicos, música, fotos... El módulo \"Producto Digital\" tiene que estar instalado." +"Un contenido digital es un producto no material que vende en línea. Los archivos adjuntos a los productos son los que se venden en el comercio electrónico, tales como libros electrónicos, música, fotos, ... El módulo \"Producto Digital\" debe instalado." #. module: hotel #: model:ir.model.fields,help:hotel.field_folio_advance_payment_inv_deposit_account_id msgid "Account used for deposits" -msgstr "Cuenta utilizada para depósitos" +msgstr "Cuenta utilizada para los depósitos" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_message_needaction @@ -4807,6 +4428,7 @@ msgstr "Acción Checkin" #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_class_active #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_restriction_active #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_active +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_active msgid "Active" msgstr "Activo" @@ -4945,7 +4567,7 @@ msgstr "Cuenta analítica" #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_analytic_tag_ids #: model:ir.model.fields,field_description:hotel.field_hotel_service_analytic_tag_ids msgid "Analytic Tags" -msgstr "Etiquetas analíticas" +msgstr "Etiquetas Analíticas" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_applied_on @@ -4975,6 +4597,7 @@ msgstr "Artículos" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_floor_id +#: model:ir.model.fields,help:hotel.field_hotel_shared_room_floor_id msgid "At which floor the room is located." msgstr "En qué piso está ubicada la habitación." @@ -4986,7 +4609,7 @@ msgstr "Atributos" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_auto_invoice msgid "Auto Payment Invoice" -msgstr "Asociar Pagos automáticamete" +msgstr "Autoasociar pago a la factura" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_preconfirm @@ -5008,7 +4631,7 @@ msgstr "Checkout automático de reservas pasadas" #. module: hotel #: model:ir.model.fields,help:hotel.field_folio_advance_payment_inv_auto_invoice msgid "Automatic validation and link payment to invoice" -msgstr "Validar y Asociar pagos automáticamente" +msgstr "Validación y asociación del pago de la ficha automático" #. module: hotel #: selection:hotel.wizard.massive.changes,section:0 @@ -5025,6 +4648,17 @@ msgstr "Código de barras" msgid "Base price to compute the customer price. Sometimes called the catalog price." msgstr "Precio base para calcular el precio de los clientes. A veces llamado precio de catálogo." +#. module: hotel +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_bed_ids +msgid "Bed" +msgstr "Cama" + +#. module: hotel +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_beds +#: model:ir.ui.view,arch_db:hotel.hotel_shared_shared_room_view_kanban +msgid "Beds" +msgstr "Camas" + #. module: hotel #: selection:product.template,consumed_on:0 msgid "Before night" @@ -5047,7 +4681,7 @@ msgstr "Nombre" #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_wizard_board_service_room_id #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_wizard_board_service_room_id msgid "Board Service" -msgstr "Board Service" +msgstr "Servicio" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_board_service_board_service_line_ids @@ -5060,7 +4694,7 @@ msgstr "Línea de BoardService" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_board_service_room_type_line_hotel_board_service_room_type_id msgid "Board Service Room" -msgstr "Board Service Habitación" +msgstr "Board Service Room" #. module: hotel #: model:ir.model,name:hotel.model_hotel_board_service_room_type @@ -5317,7 +4951,7 @@ msgstr "Checkin Pendiente" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_checkin_partner_pending_count msgid "Checkin Pending Num" -msgstr "Checkins Pendientes" +msgstr "Checkin Pending Num" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_checkin_partner_view_search @@ -5480,7 +5114,7 @@ msgstr "Confirmación de los detalles de su reserva en ${object.company_id.prope #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_folio_confirmation_date msgid "Confirmation Date" -msgstr "Fecha confirmación" +msgstr "Fecha de confirmación" #. module: hotel #: selection:hotel.folio,state:0 @@ -5492,7 +5126,7 @@ msgstr "Confirmado" #: model:ir.model.fields,field_description:hotel.field_product_product_consumed_on #: model:ir.model.fields,field_description:hotel.field_product_template_consumed_on msgid "Consumed" -msgstr "Consumed" +msgstr "Consumido" #. module: hotel #: model:ir.model,name:hotel.model_res_partner @@ -5598,6 +5232,7 @@ msgstr "Creado por" #: model:ir.model.fields,field_description:hotel.field_hotel_service_create_uid #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_create_uid #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard_create_uid +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_create_uid #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation_create_uid #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_create_uid #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days_create_uid @@ -5632,6 +5267,7 @@ msgstr "Creado por" #: model:ir.model.fields,field_description:hotel.field_hotel_service_create_date #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_create_date #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard_create_date +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_create_date #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation_create_date #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_create_date #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days_create_date @@ -5705,14 +5341,14 @@ msgstr "Ref. Cliente" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_folio_client_order_ref msgid "Customer Reference" -msgstr "Referencia cliente" +msgstr "Referencia de cliente" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_deposit_taxes_id #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_taxes_id #: model:ir.ui.view,arch_db:hotel.hotel_amenity_view_form msgid "Customer Taxes" -msgstr "Impuestos cliente" +msgstr "Impuestos de cliente" #. module: hotel #: model:ir.ui.menu,name:hotel.menu_hotel_customer @@ -5740,7 +5376,7 @@ msgid "Date" msgstr "Fecha" #. module: hotel -#: code:addons/hotel/models/hotel_room_type.py:137 +#: code:addons/hotel/models/hotel_room_type.py:135 #, python-format msgid "Date From and days are mandatory" msgstr "Fecha desde y días son obligatorios" @@ -5815,7 +5451,7 @@ msgstr "Hora de Salida por defecto (HH:MM)" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_type_uom_id msgid "Default Unit of Measure used for all stock operation." -msgstr "Unidad de medida predeterminada utilizada para todas las operaciones de stock." +msgstr "Unidad de medida por defecto utilizada para todas las operaciones de stock." #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_type_uom_po_id @@ -5898,6 +5534,7 @@ msgstr "Descripción en Recepciones" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_amenity_view_form #: model:ir.ui.view,arch_db:hotel.hotel_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form msgid "Descriptions" msgstr "Descripciones" @@ -5915,7 +5552,7 @@ msgstr "Desc.(%)" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_discount msgid "Discount" -msgstr "Descuento" +msgstr "Discount" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_line_discount @@ -5959,6 +5596,7 @@ msgstr "Habitación con descuento" #: model:ir.model.fields,field_description:hotel.field_hotel_service_display_name #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_display_name #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard_display_name +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_display_name #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation_display_name #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_display_name #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days_display_name @@ -5992,13 +5630,13 @@ msgstr "Adelanto" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_amount msgid "Down Payment Amount" -msgstr "Cantidad del Depósito" +msgstr "Cantidad de pago anticipado" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_line_advance_inv_product_id #: model:ir.ui.view,arch_db:hotel.view_folio_advance_payment_inv msgid "Down Payment Product" -msgstr "Producto de Depósito" +msgstr "Producto de pago anticipado" #. module: hotel #: selection:folio.advance.payment.inv,advance_payment_method:0 @@ -6153,7 +5791,7 @@ msgstr "Fichas" #. module: hotel #: model:ir.model,name:hotel.model_folio_advance_payment_inv msgid "Folios Advance Payment Invoice" -msgstr "Wizard de facturación de Fichas" +msgstr "Folios Advance Payment Invoice" #. module: hotel #: model:ir.model.fields,help:hotel.field_folio_advance_payment_inv_folio_ids @@ -6271,7 +5909,7 @@ msgstr "Agrupar por" #: model:ir.ui.view,arch_db:hotel.hotel_amenity_search #: model:ir.ui.view,arch_db:hotel.hotel_service_view_search msgid "Group By..." -msgstr "Agrupar Por..." +msgstr "Agrupar por..." #. module: hotel #: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_group_folios @@ -6295,19 +5933,19 @@ msgstr "Formato HH:mm" #: model:ir.model.fields,field_description:hotel.field_hotel_folio_has_cancelled_reservations_to_send #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_has_cancelled_reservations_to_send msgid "Has Cancelled Reservations To Send" -msgstr "Tienes reservas Canceladas por enviar" +msgstr "Tiene reservas canceladas para enviar por mail" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_folio_has_checkout_to_send #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_has_checkout_to_send msgid "Has Checkout To Send" -msgstr "Tiene Checkout por enviar" +msgstr "Has Checkout To Send" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_folio_has_confirmed_reservations_to_send #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_has_confirmed_reservations_to_send msgid "Has Confirmed Reservations To Send" -msgstr "Tiene reservas confirmadas por enviar" +msgstr "Has Confirmed Reservations To Send" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_account_invoice_has_folios_outstanding @@ -6424,6 +6062,7 @@ msgstr "Motivos de Cierre de habitaciones" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_room_type_id +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_room_type_id #: model:ir.ui.view,arch_db:hotel.hotel_room_type_class_view_form #: model:ir.ui.view,arch_db:hotel.hotel_room_type_view_form #: model:ir.ui.view,arch_db:hotel.hotel_room_type_view_tree @@ -6456,10 +6095,19 @@ msgstr "Servicios" msgid "Hotel Services and its charges" msgstr "Hotel Services and its charges" +#. module: hotel +#: model:ir.actions.act_window,name:hotel.action_hotel_shared_room_form +#: model:ir.model,name:hotel.model_hotel_shared_room +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_tree +#: model:ir.ui.view,arch_db:hotel.hotel_shared_shared_room_view_search +msgid "Hotel Shared Room" +msgstr "Habitación Compartida" + #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_class_id msgid "Hotel Type Class" -msgstr "Categoría de Habitación" +msgstr "Hotel Type Class" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_floor_view_form @@ -6506,6 +6154,7 @@ msgstr "Hotel services detail provide to customer and it will include in main In #: model:ir.model.fields,field_description:hotel.field_hotel_service_id #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_id #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard_id +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_id #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation_id #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_id #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days_id @@ -6540,7 +6189,7 @@ msgstr "Si el idioma seleccionado está cargado en el sistema, todos los documen #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_type_restriction_active msgid "If unchecked, it will allow you to hide the restriction plan without removing it." -msgstr "Si lo deseleccionar, se desactivará el plan de restricciones sin eliminarlo." +msgstr "If unchecked, it will allow you to hide the restriction plan without removing it." #. module: hotel #: code:addons/hotel/wizard/folio_make_invoice_advance.py:458 @@ -6600,6 +6249,7 @@ msgstr "Inform Guest About Reservation Before 24 Hours" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_amenity_view_form #: model:ir.ui.view,arch_db:hotel.hotel_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form msgid "Information" msgstr "Información" @@ -6633,7 +6283,7 @@ msgid "International Article Number used for product identification." msgstr "Número de artículo internacional usado para la identificación de producto." #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1239 +#: code:addons/hotel/models/hotel_reservation.py:1237 #, python-format msgid "Invalid Nights! Max is '%d'" msgstr "Núm de noches inválidad! Máximo s on '%d'" @@ -6670,7 +6320,7 @@ msgstr "Factura" #: model:ir.model.fields,field_description:hotel.field_hotel_folio_partner_invoice_id #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_partner_invoice_id msgid "Invoice Address" -msgstr "Dirección de factura" +msgstr "Dirección de Factura" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_folio_view_search @@ -6681,7 +6331,7 @@ msgstr "Dirección de Facturación" #: model:ir.model.fields,field_description:hotel.field_hotel_folio_invoice_count #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_invoice_count msgid "Invoice Count" -msgstr "Contador de Facturas" +msgstr "Invoice Count" #. module: hotel #: model:ir.actions.act_window,name:hotel.action_view_folio_advance_payment_inv @@ -6700,7 +6350,7 @@ msgstr "Linea de Factura" #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_line_invoice_line_ids #: model:ir.model.fields,field_description:hotel.field_hotel_service_invoice_line_ids msgid "Invoice Lines" -msgstr "Líneas de factura" +msgstr "Líneas de la factura" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_folio_invoice_status @@ -6791,11 +6441,6 @@ msgstr "Es Operadora Tuística" msgid "Is extra bed" msgstr "Es cama supletoria" -#. module: hotel -#: model:ir.ui.view,arch_db:hotel.hotel_room_view_form -msgid "It allows several reservations on the same room simultaneously based on the capacity of people" -msgstr "Permite varias reservas en la misma habitación contando solo la capacidad de plazas" - #. module: hotel #: code:addons/hotel/models/hotel_checkin_partner.py:142 #, python-format @@ -6854,6 +6499,7 @@ msgstr "Fecha del último mensaje" #: model:ir.model.fields,field_description:hotel.field_hotel_service___last_update #: model:ir.model.fields,field_description:hotel.field_hotel_service_line___last_update #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard___last_update +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room___last_update #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation___last_update #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes___last_update #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days___last_update @@ -6893,6 +6539,7 @@ msgstr "Actualizado el" #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_write_uid #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard_write_uid #: model:ir.model.fields,field_description:hotel.field_hotel_service_write_uid +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_write_uid #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation_write_uid #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_write_uid #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days_write_uid @@ -6927,6 +6574,7 @@ msgstr "Última actualización de" #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_write_date #: model:ir.model.fields,field_description:hotel.field_hotel_service_wizard_write_date #: model:ir.model.fields,field_description:hotel.field_hotel_service_write_date +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_write_date #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_duplicate_reservation_write_date #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_changes_write_date #: model:ir.model.fields,field_description:hotel.field_hotel_wizard_massive_price_reservation_days_write_date @@ -6956,7 +6604,7 @@ msgstr "Pago restrasado" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_cancelation_rule_apply_on_late msgid "Late apply on" -msgstr "Apllicar cancelación tardía en" +msgstr "Aplicar cancelación tardía en" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_cancelation_rule_days_late @@ -6976,7 +6624,7 @@ msgstr "Líneas" #. module: hotel #: model:ir.model,name:hotel.model_line_advance_inv msgid "Lines Advance Invoice" -msgstr "Líneas de factura" +msgstr "Lines Advance Invoice" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_type_room_amenity_ids @@ -7113,7 +6761,7 @@ msgstr "Máx. días en tiempo antes del checkin" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_cancelation_rule_days_intime msgid "Maximum number of days for free cancellation before Checkin" -msgstr "Máximo número de días antes del Checkin para la cancelación sin cargos" +msgstr "Máximo número de días de libre cancelación antes del Checkin" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_image_medium @@ -7187,12 +6835,14 @@ msgstr "Mis Reservas" #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_name #: model:ir.model.fields,field_description:hotel.field_room_closure_reason_name #: model:ir.ui.view,arch_db:hotel.hotel_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form #: model:ir.ui.view,arch_db:hotel.room_type_restriction_view_form msgid "Name" msgstr "Nombre" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form msgid "Name in reports" msgstr "Nombre en Informes" @@ -7244,7 +6894,7 @@ msgid "Nights" msgstr "Noches" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:572 +#: code:addons/hotel/models/hotel_reservation.py:570 #, python-format msgid "No Checkins!" msgstr "Sin Checkins!" @@ -7261,7 +6911,7 @@ msgid "No Show apply on" msgstr "No Show aplicar en" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:571 +#: code:addons/hotel/models/hotel_reservation.py:569 #, python-format msgid "No checkin was made for this reservation" msgstr "No se ha llegado a realizar ningún checkin en esta reserva!" @@ -7301,7 +6951,7 @@ msgstr "Número de acciones" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_wizard_rooms_num msgid "Number of Rooms" -msgstr "Número de habitaciones" +msgstr "Number of Rooms" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_reservation_children @@ -7742,7 +7392,7 @@ msgstr "Tarifa" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_product_id msgid "Product Room Type" -msgstr "Producto del tipo de habitación" +msgstr "Producto Tipo Habitación" #. module: hotel #: model:ir.model,name:hotel.model_product_template @@ -7854,7 +7504,7 @@ msgstr "Referencia" #. module: hotel #: code:addons/hotel/models/hotel_folio.py:317 -#: code:addons/hotel/models/hotel_reservation.py:1079 +#: code:addons/hotel/models/hotel_reservation.py:1077 #: model:ir.ui.view,arch_db:hotel.account_payment_view_form_folio #, python-format msgid "Register Payment" @@ -7913,13 +7563,13 @@ msgstr "Detalles de la Reseva" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_reservation_line_ids msgid "Reservation Line" -msgstr "Reservation Line" +msgstr "Línea Reserva" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_account_invoice_line_reservation_line_ids #: model:ir.model.fields,field_description:hotel.field_line_advance_inv_reservation_line_ids msgid "Reservation Lines" -msgstr "Reservation Lines" +msgstr "Líneas Reserva" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_reservation_no @@ -7951,7 +7601,7 @@ msgstr "Servicios" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_reservation_view_form msgid "Reservation Total" -msgstr "Reservation Total" +msgstr "Total Reserva" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_folio_wizard @@ -7959,13 +7609,13 @@ msgid "Reservation Wizard" msgstr "Reservation Wizard" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:642 +#: code:addons/hotel/models/hotel_reservation.py:640 #, python-format msgid "Reservation has no adults" msgstr "La reserva no tiene adultos" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:640 +#: code:addons/hotel/models/hotel_reservation.py:638 #, python-format msgid "Reservation persons can't be higher than room capacity" msgstr "Las personas de la reserva no pueden superiores a la capacidad de la habitación" @@ -8008,7 +7658,7 @@ msgstr "Reservas a 7 días" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_reservation_view_tree msgid "Reserved Unit Type" -msgstr "Reserved Unit Type" +msgstr "Tipo Reservado" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_folio_wizard_reservation_wizard_ids @@ -8126,6 +7776,7 @@ msgstr "Líneas de habitación" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_name +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_name msgid "Room Name" msgstr "Nombre Habitación" @@ -8137,7 +7788,7 @@ msgstr "Habitación No" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_price_room_services_set msgid "Room Services Total" -msgstr "Total de servicios de habitación" +msgstr "Total Servicios Habitación" #. module: hotel #: selection:hotel.wizard.massive.changes,applied_on:0 @@ -8151,19 +7802,20 @@ msgstr "Total de servicios de habitación" #: model:ir.ui.view,arch_db:hotel.hotel_folio_wizard #: model:ir.ui.view,arch_db:hotel.hotel_reservation_view_search #: model:ir.ui.view,arch_db:hotel.hotel_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form msgid "Room Type" msgstr "Tipo de Habitación" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_room_amenity_ids msgid "Room Type Amenities" -msgstr "Características del tipo de habitación" +msgstr "Room Type Amenities" #. module: hotel #: model:ir.actions.act_window,name:hotel.open_hotel_room_type_class_form_tree #: model:ir.model,name:hotel.model_hotel_room_type_class msgid "Room Type Class" -msgstr "Tipo Habitación" +msgstr "Categoría del Tipo de Habitación" #. module: hotel #: sql_constraint:hotel.room.type:0 @@ -8172,6 +7824,7 @@ msgstr "El código de la habitación debe ser único!" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_room_view_kanban +#: model:ir.ui.view,arch_db:hotel.hotel_shared_shared_room_view_kanban msgid "Room Type:" msgstr "Tipo de Habitación:" @@ -8194,7 +7847,7 @@ msgid "Room capacity can't be less than one" msgstr "La capacidad de la habitación no puede ser menor que uno" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1160 +#: code:addons/hotel/models/hotel_reservation.py:1158 #, python-format msgid "Room line Check In Date Should be less than the Check Out Date!" msgstr "La fecha de entrada debe ser menor que la fecha de salida!" @@ -8210,7 +7863,7 @@ msgstr "Habitaciones" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_wizard_room_type_id msgid "Rooms Type" -msgstr "Tipos de Habitación" +msgstr "Tipo Habitación" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_route_ids @@ -8220,6 +7873,7 @@ msgstr "Rutas" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_description_sale #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_description_sale +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_description_sale msgid "Sale Description" msgstr "Descripción de venta" @@ -8260,7 +7914,7 @@ msgstr "Sábado" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_account_payment_save_date msgid "Save Date" -msgstr "Fecha guardada\t" +msgstr "Fecha Guardada\t" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_account_payment_save_journal_id @@ -8276,7 +7930,7 @@ msgstr "Sección" #: model:ir.model.fields,field_description:hotel.field_hotel_folio_segmentation_ids #: model:ir.model.fields,field_description:hotel.field_hotel_reservation_segmentation_ids msgid "Segmentation" -msgstr "Segmentación" +msgstr "Segmentation" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_folio_view_form @@ -8323,6 +7977,7 @@ msgstr "Enviar Mail de Salida" #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_class_sequence #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_sequence #: model:ir.model.fields,field_description:hotel.field_hotel_service_sequence +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_sequence msgid "Sequence" msgstr "Secuencia" @@ -8357,7 +8012,7 @@ msgstr "Líneas de servicio" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_service_line_service_id msgid "Service Room" -msgstr "Servicios habitación" +msgstr "Servicio Habitación" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_service_name @@ -8430,17 +8085,17 @@ msgstr "Establecer hora de salida por defecto" #. module: hotel #: model:ir.ui.view,arch_db:hotel.view_hotel_config_settings msgid "Set pricelist default" -msgstr "Establecer tarifa por defecto" +msgstr "Establcer tarifa por defecto" #. module: hotel #: model:ir.ui.view,arch_db:hotel.view_hotel_config_settings msgid "Set restrictions default" -msgstr "Establecer plan de restricciones por defecto" +msgstr "Establcer plan de restricciones por defecto" #. module: hotel #: model:ir.ui.view,arch_db:hotel.view_hotel_config_settings msgid "Set time-zone" -msgstr "Establecer Zona Horaria" +msgstr "Establcer Zona Horaria" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_folio_view_form @@ -8458,10 +8113,16 @@ msgid "Shared Folio" msgstr "Compartir Ficha" #. module: hotel -#: model:ir.model.fields,field_description:hotel.field_hotel_room_shared_room +#: model:ir.model.fields,field_description:hotel.field_hotel_room_shared_room_id +#: model:ir.model.fields,field_description:hotel.field_hotel_room_type_shared_room msgid "Shared Room" msgstr "Habitación Compartida" +#. module: hotel +#: model:ir.ui.menu,name:hotel.menu_open_hotel_shared_room_form +msgid "Shared Rooms" +msgstr "Habitaciones Compartidas" + #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_checkin_partner_view_search msgid "Show all checkins for Tomorrow" @@ -8611,7 +8272,7 @@ msgstr "Cuenta de entrada de stock" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_stock_move_ids msgid "Stock Move" -msgstr "Movimiento de stock" +msgstr "Movimiento de Stock" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_property_stock_account_output @@ -8718,7 +8379,7 @@ msgstr "Términos y condiciones" #: model:ir.model.fields,help:hotel.field_hotel_room_type_active #: model:ir.model.fields,help:hotel.field_hotel_room_type_class_active msgid "The active field allows you to hide the category without removing it." -msgstr "El campo activo te permite ocultar la categoría sin eliminarla." +msgstr "The active field allows you to hide the category without removing it." #. module: hotel #: model:ir.model.fields,help:hotel.field_folio_advance_payment_inv_amount @@ -8759,8 +8420,8 @@ msgid "The product used to invoice a down payment should have an invoice policy msgstr "The product used to invoice a down payment should have an invoice policy set to \"Ordered quantities\". Please update your deposit product to be able to create a deposit invoice." #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:697 -#: code:addons/hotel/models/hotel_reservation.py:1188 +#: code:addons/hotel/models/hotel_reservation.py:695 +#: code:addons/hotel/models/hotel_reservation.py:1186 #, python-format msgid "The room already is completed" msgstr "La habitación ya está completa" @@ -8828,7 +8489,7 @@ msgid "This guest is already registered in the room" msgstr "Este huésped ya está registrado en ésta habitación" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1366 +#: code:addons/hotel/models/hotel_reservation.py:1364 #, python-format msgid "This is the parent reservation" msgstr "Esta es la reserva padre" @@ -8845,13 +8506,13 @@ msgid "This pay is related with msgstr "Este pago esta vínculado con más de una Reserva." #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1288 +#: code:addons/hotel/models/hotel_reservation.py:1286 #, python-format msgid "This reservation can't be unified" msgstr "Esta reserva no se puede unificar" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1317 +#: code:addons/hotel/models/hotel_reservation.py:1315 #, python-format msgid "This reservation can't be unified: They all need to be in the same room" msgstr "Esta reserva no se puede unificar: todos deben estar en la misma habitación" @@ -8873,6 +8534,11 @@ msgstr "Esta reserva es solo una parte de una reserva dividida, puedes revisarlo msgid "This room is occupied!, please, choice other room or change the reservation date" msgstr "Esta habitación está ocupada, elige otra habitación u otras fechas para la estancia" +#. module: hotel +#: model:ir.model.fields,help:hotel.field_hotel_room_type_shared_room +msgid "This room type is reservation by beds" +msgstr "This room type is reservation by beds" + #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_type_property_stock_production msgid "This stock location will be used, instead of the default one, as the source location for stock moves generated by manufacturing orders." @@ -8968,7 +8634,7 @@ msgstr "Total" #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_wizard_total_price #: model:ir.ui.view,arch_db:hotel.report_folio_document msgid "Total Price" -msgstr "Precio total" +msgstr "Precio Total" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_hotel_room_type_total_rooms_count @@ -8979,12 +8645,12 @@ msgstr "Total Habitaciones" #: model:ir.ui.view,arch_db:hotel.hotel_folio_view_form #: model:ir.ui.view,arch_db:hotel.hotel_folio_view_tree msgid "Total amount" -msgstr "Importe total" +msgstr "Cantidad Total" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_account_payment_amount_total_folio msgid "Total amount in folio" -msgstr "Cantidad total en ficha de reserva" +msgstr "Monto total en ficha de reserva" #. module: hotel #: model:ir.ui.view,arch_db:hotel.hotel_folio_view_tree @@ -9040,7 +8706,9 @@ msgstr "Tipos" #. module: hotel #: model:ir.model,name:hotel.model_hotel_floor #: model:ir.model.fields,field_description:hotel.field_hotel_room_floor_id +#: model:ir.model.fields,field_description:hotel.field_hotel_shared_room_floor_id #: model:ir.ui.view,arch_db:hotel.hotel_room_view_form +#: model:ir.ui.view,arch_db:hotel.hotel_shared_room_view_form msgid "Ubication" msgstr "Ubicación" @@ -9067,7 +8735,7 @@ msgid "Unexpected Error: Can't found a f msgstr "Unexpected Error: Can't found a free room" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1274 +#: code:addons/hotel/models/hotel_reservation.py:1272 #, python-format msgid "Unexpected error copying record. Can't split reservation!" msgstr "Ouch!. No hemos podido dividir la reserva!" @@ -9202,7 +8870,7 @@ msgid "Warning" msgstr "Aviso" #. module: hotel -#: code:addons/hotel/models/hotel_service.py:332 +#: code:addons/hotel/models/hotel_service.py:337 #, python-format msgid "Warning for %s" msgstr "Aviso para %s" @@ -9222,7 +8890,7 @@ msgstr "No podemos crear una ficha vacía" #: code:addons/hotel/wizard/wizard_reservation.py:221 #, python-format msgid "We need know the customer!" -msgstr "Necesitamos conocer el cliente!" +msgstr "Necesitamos conoces el cliente!" #. module: hotel #: code:addons/hotel/models/inherited_account_invoice.py:50 @@ -9267,7 +8935,7 @@ msgstr "Peso" #. module: hotel #: model:ir.model.fields,field_description:hotel.field_folio_advance_payment_inv_advance_payment_method msgid "What do you want to invoice?" -msgstr "Qué quieres facturar?" +msgstr "¿Qué quiere facturar?" #. module: hotel #: model:ir.model.fields,help:hotel.field_hotel_room_type_property_stock_account_input @@ -9282,16 +8950,22 @@ msgstr "Cuando se realiza una valoración de inventario en tiempo real, la contr #. module: hotel #: model:ir.ui.menu,name:hotel.menu_account_finance_xls_reports msgid "XLS Reports" -msgstr "Informe XLS" +msgstr "XLS Reports" #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:772 +#: code:addons/hotel/models/inherited_account_invoice.py:119 +#, python-format +msgid "You cannot delete an invoice after it has been validated (and received a number). You can set it back to \"Draft\" state and modify its content, then re-confirm it." +msgstr "You cannot delete an invoice after it has been validated (and received a number). You can set it back to \"Draft\" state and modify its content, then re-confirm it." + +#. module: hotel +#: code:addons/hotel/models/hotel_reservation.py:770 #, python-format msgid "You tried to change/confirm reservation with room those already reserved in this reservation period: %s " msgstr "Estás intentando cambiar/confirmar una reserva con una habitación ya reservada en este periodo: %s " #. module: hotel -#: code:addons/hotel/models/hotel_reservation.py:1174 +#: code:addons/hotel/models/hotel_reservation.py:1172 #, python-format msgid "You tried to change/confirm reservation with room those already reserved in this reservation period: %s " msgstr "Estás intentando hacer una reserva en una habitación que ya está reservada en este periódo: %s "