2020-04-16 14:45:13 +02:00
|
|
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
|
|
# this repository contains the full copyright notices and license terms.
|
|
|
|
|
|
|
|
from decimal import Decimal
|
|
|
|
from datetime import date, timedelta, datetime
|
|
|
|
from trytond.model import ModelView, Workflow, ModelSQL, fields
|
2020-07-18 17:18:29 +02:00
|
|
|
from trytond.pyson import Eval, Bool
|
2020-04-16 14:45:13 +02:00
|
|
|
from trytond.pool import Pool
|
|
|
|
from trytond.report import Report
|
|
|
|
from trytond.wizard import Wizard, StateView, StateAction, Button, StateTransition
|
|
|
|
from trytond.transaction import Transaction
|
2021-07-21 14:56:53 +02:00
|
|
|
from trytond.model.exceptions import AccessError
|
|
|
|
from trytond.i18n import gettext
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
STATES_OP = {
|
|
|
|
'readonly': Eval('state').in_(['check_out', 'done', 'cancelled'])
|
|
|
|
}
|
|
|
|
|
|
|
|
STATES_MNT = {
|
|
|
|
'readonly': Eval('state') != 'draft',
|
|
|
|
}
|
|
|
|
|
|
|
|
COLOR_BOOKING = {
|
|
|
|
'draft': '#9b9f9f',
|
|
|
|
'check_in': '#e6bd0f',
|
|
|
|
'check_out': '#09a4cd',
|
|
|
|
'done': '#315274',
|
|
|
|
}
|
|
|
|
|
|
|
|
COLOR_MNT = {
|
|
|
|
'draft': '#e87a7a',
|
|
|
|
'confirmed': '#d45757',
|
|
|
|
'done': '#d45757',
|
|
|
|
}
|
|
|
|
|
|
|
|
INVOICE_STATES = [
|
|
|
|
('', ''),
|
2020-08-15 18:01:37 +02:00
|
|
|
('pending', 'Pending'),
|
2020-04-16 14:45:13 +02:00
|
|
|
('in_process', 'In Process'),
|
|
|
|
('invoiced', 'Invoiced'),
|
|
|
|
('paid', 'Paid')
|
|
|
|
]
|
|
|
|
|
2020-07-18 17:18:29 +02:00
|
|
|
COMPLEMENTARY = [
|
|
|
|
('', ''),
|
|
|
|
('in_house', 'In House'),
|
2021-09-13 19:24:22 +02:00
|
|
|
('courtesy', 'Courtesy')
|
2020-07-18 17:18:29 +02:00
|
|
|
]
|
|
|
|
|
2021-10-06 05:37:33 +02:00
|
|
|
_ZERO = Decimal('0')
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
|
2021-09-21 06:33:06 +02:00
|
|
|
# class Operation(Workflow, ModelSQL, ModelView):
|
|
|
|
# 'Operation'
|
|
|
|
# __name__ = 'hotel.operation'
|
|
|
|
# _rec_name = 'reference'
|
|
|
|
# reference = fields.Char('Reference', select=True, readonly=True)
|
|
|
|
# kind = fields.Selection([
|
|
|
|
# ('occupancy', 'Occupancy'),
|
|
|
|
# ('maintenance', 'Maintenance'),
|
|
|
|
# ('statement', 'Statement'),
|
|
|
|
# ], 'Kind')
|
|
|
|
# party = fields.Many2One('party.party', 'Party', select=True,
|
|
|
|
# states=STATES_OP, required=True)
|
|
|
|
# main_guest = fields.Many2One('party.party', 'Main Guest', select=True,
|
|
|
|
# states=STATES_OP, required=True)
|
|
|
|
# room = fields.Many2One('hotel.room', 'Room', select=True, required=False,
|
|
|
|
# states=STATES_OP)
|
|
|
|
# accommodation = fields.Many2One('product.product', 'Accommodation Product',
|
|
|
|
# domain=[('kind', '=', 'accommodation')], states=STATES_OP)
|
|
|
|
# start_date = fields.Date('Arrival Date', states=STATES_OP)
|
|
|
|
# end_date = fields.Date('Departure Date', states=STATES_OP)
|
|
|
|
# description = fields.Char('Description', states=STATES_OP)
|
|
|
|
# state = fields.Selection(OPERATION_STATES, 'State', readonly=True)
|
|
|
|
# state_string = state.translated('state')
|
|
|
|
# invoice_state = fields.Selection(INVOICE_STATES, 'Invoice State',
|
|
|
|
# readonly=True)
|
|
|
|
# lines = fields.One2Many('hotel.folio.charge', 'operation', 'Lines',
|
|
|
|
# states=STATES_OP)
|
|
|
|
# origin = fields.Reference('Origin', selection='get_origin', select=True,
|
|
|
|
# states={'readonly': True})
|
|
|
|
# guests = fields.One2Many('hotel.operation.guest', 'operation',
|
|
|
|
# 'Guests', add_remove=[], states=STATES_OP)
|
|
|
|
# price_list = fields.Many2One('product.price_list', 'Price List',
|
|
|
|
# states=STATES_OP, depends=['state', 'lines'])
|
|
|
|
# currency = fields.Many2One('currency.currency', 'Currency',
|
|
|
|
# required=True, depends=['state'])
|
|
|
|
# nights_quantity = fields.Function(fields.Integer('Nights'),
|
|
|
|
# 'get_nights_quantity')
|
|
|
|
# unit_price = fields.Numeric('Unit Price', digits=(16, 4), states=STATES_OP)
|
|
|
|
# unit_price_w_tax = fields.Function(fields.Numeric('Unit Price With Tax'),
|
|
|
|
# 'get_unit_price_w_tax')
|
|
|
|
# taxes_exception = fields.Boolean('Taxes Exception', states=STATES_OP)
|
|
|
|
# breakfast_included = fields.Boolean('Breakfast Included', states=STATES_OP)
|
|
|
|
# add_default_charges = fields.Boolean('Add Default Charges', states=STATES_OP)
|
|
|
|
# # sale = fields.Function(fields.Many2One('sale.sale', 'Sale'), 'get_sale')
|
|
|
|
# sale_line = fields.Many2One('sale.line', 'Sale Line', select=True)
|
|
|
|
# company = fields.Many2One('company.company', 'Company', states=STATES_OP)
|
|
|
|
# total_amount = fields.Function(fields.Numeric('Total Amount',
|
|
|
|
# digits=(16, 2)), 'get_total_amount')
|
|
|
|
# total_amount_today = fields.Function(fields.Numeric('Total Amount Today',
|
|
|
|
# digits=(16, 2)), 'get_total_amount')
|
|
|
|
# room_amount = fields.Function(fields.Numeric('Room Amount',
|
|
|
|
# digits=(16, 2)), 'get_room_amount')
|
|
|
|
# room_amount_today = fields.Function(fields.Numeric('Room Amount Today',
|
|
|
|
# digits=(16, 2)), 'get_room_amount')
|
|
|
|
# pending_payment = fields.Function(fields.Numeric('Pending Payment',
|
|
|
|
# digits=(16, 2)), 'get_pending_payment')
|
|
|
|
# notes = fields.Text('Notes', select=True, states=STATES_OP)
|
|
|
|
# complementary = fields.Boolean('Complementary', states=STATES_OP)
|
|
|
|
# type_complementary = fields.Selection(COMPLEMENTARY, 'Type Complementary', states={
|
|
|
|
# 'invisible': ~Bool(Eval('complementary')),
|
|
|
|
# 'required': Bool(Eval('complementary')),
|
|
|
|
# })
|
|
|
|
# operation_target = fields.Many2One('hotel.operation', 'Operation Target')
|
|
|
|
# transfered_operations = fields.One2Many('hotel.operation',
|
|
|
|
# 'operation_target', 'Transfered Operations', states=STATES_OP)
|
|
|
|
# vouchers = fields.Many2Many('hotel.operation-account.voucher', 'operation',
|
|
|
|
# 'voucher', 'Vouchers', states=STATES_OP, domain=[], depends=['party'])
|
|
|
|
# agent = fields.Many2One('commission.agent', 'Agent')
|
|
|
|
# # stock_moves = fields.Many2Many('hotel.operation-stock.move', 'operation',
|
|
|
|
# # 'move', 'Stock Moves', states={'readonly': True})
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def __setup__(cls):
|
|
|
|
# super(Operation, cls).__setup__()
|
|
|
|
# cls._transitions |= set((
|
|
|
|
# ('draft', 'open'),
|
|
|
|
# ('draft', 'cancelled'),
|
|
|
|
# ('open', 'draft'),
|
|
|
|
# ('open', 'closed'),
|
|
|
|
# ('closed', 'open'),
|
|
|
|
# ))
|
|
|
|
# cls._buttons.update({
|
|
|
|
# 'draft': {
|
|
|
|
# 'invisible': True,
|
|
|
|
# },
|
|
|
|
# 'open': {
|
|
|
|
# 'invisible': Eval('state') != 'draft',
|
|
|
|
# },
|
|
|
|
# 'close': {
|
|
|
|
# 'invisible': Eval('state') == 'closed',
|
|
|
|
# },
|
|
|
|
# 'cancel': {
|
|
|
|
# 'invisible': Eval('state') != 'draft',
|
|
|
|
# },
|
|
|
|
# 'bill': {
|
|
|
|
# 'invisible': Eval('invoice_state') == 'invoiced',
|
|
|
|
# },
|
|
|
|
# 'pay_advance': {
|
|
|
|
# 'invisible': Eval('state') == 'closed',
|
|
|
|
# },
|
|
|
|
# })
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def validate(cls, records):
|
|
|
|
# super(Operation, cls).validate(records)
|
|
|
|
# for r in records:
|
|
|
|
# operations = cls.search([
|
|
|
|
# ('room', '=', r.room.id),
|
|
|
|
# ('id', '!=', r.id),
|
|
|
|
# ('state', '!=', 'cancelled'),
|
|
|
|
# ('kind', '=', 'occupancy'),
|
|
|
|
# ['AND', ['OR',
|
|
|
|
# [
|
|
|
|
# ('start_date', '>=', r.start_date),
|
|
|
|
# ('end_date', '<', r.start_date),
|
|
|
|
# ], [
|
|
|
|
# ('start_date', '>=', r.end_date),
|
|
|
|
# ('end_date', '<=', r.end_date),
|
|
|
|
# ]
|
|
|
|
# ]]])
|
|
|
|
# if operations:
|
|
|
|
# raise AccessError(gettext('hotel.msg_occupied_room', s=r.room.name))
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def occupancy_rate(cls, start, end):
|
|
|
|
# pool = Pool()
|
|
|
|
# today_ = pool.get('ir.date').today()
|
|
|
|
# after_days = today_ + timedelta(days=3)
|
|
|
|
# before_days = today_ - timedelta(days=3)
|
|
|
|
# operations = cls.search([
|
|
|
|
# ('state', 'not in', ['closed', 'cancelled']),
|
|
|
|
# ('start_date', '>=', before_days),
|
|
|
|
# ('end_date', '<=', after_days),
|
|
|
|
# ])
|
|
|
|
# Room = pool.get('hotel.room')
|
|
|
|
# Housekeeping = pool.get('hotel.housekeeping')
|
|
|
|
# housekeepings = Housekeeping.search([
|
|
|
|
# ('state', '=', 'maintenance')
|
|
|
|
# ])
|
|
|
|
# room_ids = []
|
|
|
|
# for hk in housekeepings:
|
|
|
|
# room_ids.append(hk.room.id)
|
|
|
|
# rooms = Room.search([
|
|
|
|
# ('id', 'not in', room_ids)
|
|
|
|
# ])
|
|
|
|
# qty_booking = len(operations)
|
|
|
|
# qty_rooms = len(rooms)
|
|
|
|
# return qty_booking / qty_rooms
|
|
|
|
#
|
|
|
|
# def get_unit_price_w_tax(self, name=None):
|
|
|
|
# Tax = Pool().get('account.tax')
|
|
|
|
# res = self.unit_price
|
|
|
|
# if self.unit_price and self.accommodation and not self.taxes_exception:
|
|
|
|
# values = Tax.compute(
|
|
|
|
# self.accommodation.template.customer_taxes_used,
|
|
|
|
# self.unit_price or _ZERO, 1
|
|
|
|
# )
|
|
|
|
# if len(values) > 0:
|
|
|
|
# value = values[0]
|
|
|
|
# res = value['base'] + value['amount']
|
|
|
|
# return round(res, Operation.total_amount.digits[1])
|
|
|
|
#
|
|
|
|
# def get_pending_payment(self, name=None):
|
|
|
|
# res = _ZERO
|
|
|
|
# if self.total_amount:
|
|
|
|
# amount_paid = sum([v.amount_to_pay for v in self.vouchers])
|
|
|
|
# res = self.total_amount - amount_paid
|
|
|
|
# res = round(res, Operation.total_amount.digits[1])
|
|
|
|
# return res
|
|
|
|
#
|
|
|
|
# def get_total_amount(self, name=None):
|
|
|
|
# res = []
|
|
|
|
# if name == 'total_amount':
|
|
|
|
# if self.unit_price_w_tax and self.nights_quantity:
|
|
|
|
# res.append(self.room_amount)
|
|
|
|
# else:
|
|
|
|
# if self.unit_price_w_tax and self.nights_quantity:
|
|
|
|
# res.append(self.room_amount_today)
|
|
|
|
#
|
|
|
|
# res.extend([l.amount for l in self.lines if l.amount])
|
|
|
|
# if res:
|
|
|
|
# return round(sum(res), Operation.total_amount.digits[1])
|
|
|
|
# return _ZERO
|
|
|
|
#
|
|
|
|
# def get_room_amount(self, name=None):
|
|
|
|
# res = 0
|
|
|
|
# Date = Pool().get('ir.date')
|
|
|
|
# if self.unit_price_w_tax and self.nights_quantity:
|
|
|
|
# if name == 'room_amount':
|
|
|
|
# res = self.unit_price_w_tax * self.nights_quantity
|
|
|
|
# else:
|
|
|
|
# delta = (Date.today() - self.start_date).days
|
|
|
|
# res = self.unit_price_w_tax * delta
|
|
|
|
# return round(res, Operation.total_amount.digits[1])
|
|
|
|
#
|
|
|
|
# @staticmethod
|
|
|
|
# def default_invoice_state():
|
|
|
|
# return 'pending'
|
|
|
|
#
|
|
|
|
# @staticmethod
|
|
|
|
# def default_company():
|
|
|
|
# return Transaction().context.get('company')
|
|
|
|
#
|
|
|
|
# @staticmethod
|
|
|
|
# def default_currency():
|
|
|
|
# Company = Pool().get('company.company')
|
|
|
|
# company = Company(Transaction().context.get('company'))
|
|
|
|
# return company.currency.id
|
|
|
|
#
|
|
|
|
# @staticmethod
|
|
|
|
# def default_state():
|
|
|
|
# return 'draft'
|
|
|
|
#
|
|
|
|
# @staticmethod
|
|
|
|
# def default_kind():
|
|
|
|
# return 'occupancy'
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def search_rec_name(cls, name, clause):
|
|
|
|
# _, operator, value = clause
|
|
|
|
# if operator.startswith('!') or operator.startswith('not '):
|
|
|
|
# bool_op = 'AND'
|
|
|
|
# else:
|
|
|
|
# bool_op = 'OR'
|
|
|
|
# domain = [
|
|
|
|
# bool_op,
|
|
|
|
# ('main_guest', operator, value),
|
|
|
|
# ('reference', operator, value),
|
|
|
|
# ('room.name', operator, value),
|
|
|
|
# ('party.name', operator, value),
|
|
|
|
# ]
|
|
|
|
# return domain
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button
|
|
|
|
# @Workflow.transition('open')
|
|
|
|
# def open(cls, records):
|
|
|
|
# for rec in records:
|
|
|
|
# rec.update_housekeeping('check_in')
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button
|
|
|
|
# @Workflow.transition('closed')
|
|
|
|
# def close(cls, records):
|
|
|
|
# pass
|
|
|
|
# # for rec in records:
|
|
|
|
# # rec.update_housekeeping('check_out')
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button
|
|
|
|
# def bill(cls, records):
|
|
|
|
# for rec in records:
|
|
|
|
# if rec.complementary:
|
|
|
|
# return
|
|
|
|
# cls.create_sales([rec])
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button
|
|
|
|
# @Workflow.transition('draft')
|
|
|
|
# def draft(cls, records):
|
|
|
|
# pass
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button
|
|
|
|
# @Workflow.transition('cancelled')
|
|
|
|
# def cancel(cls, records):
|
|
|
|
# pass
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button_action('hotel.wizard_operation_check_out')
|
|
|
|
# def check_out_wizard(cls, records):
|
|
|
|
# pass
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# @ModelView.button_action('hotel.wizard_operation_advance_voucher')
|
|
|
|
# def pay_advance(cls, records):
|
|
|
|
# pass
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def validate_check_out_date(cls, records):
|
|
|
|
# Date = Pool().get('ir.date')
|
|
|
|
# today = Date.today()
|
|
|
|
# for rec in records:
|
|
|
|
# if rec.end_date != today:
|
|
|
|
# return False
|
|
|
|
#
|
|
|
|
# def update_housekeeping(self, state):
|
|
|
|
# pool = Pool()
|
|
|
|
# Housekeeping = pool.get('hotel.housekeeping')
|
|
|
|
# Configuration = pool.get('hotel.configuration')
|
|
|
|
# config = Configuration.get_configuration()
|
|
|
|
# if not config.cleaning_check_in or not config.cleaning_check_out \
|
|
|
|
# or not config.cleaning_occupied:
|
|
|
|
# raise AccessError(gettext('hotel.msg_missing_cleaning_configuration'))
|
|
|
|
# if state == 'check_in':
|
|
|
|
# values = {
|
|
|
|
# 'availability': 'occupied',
|
|
|
|
# 'cleaning_type': config.cleaning_occupied.id
|
|
|
|
# }
|
|
|
|
# elif state == 'check_out':
|
|
|
|
# values = {
|
|
|
|
# 'availability': 'available',
|
|
|
|
# 'state': 'dirty',
|
|
|
|
# 'cleaning_type': config.cleaning_check_out.id
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# housekeepings = Housekeeping.search([
|
|
|
|
# ('room', '=', self.room.id)
|
|
|
|
# ])
|
|
|
|
# if not housekeepings:
|
|
|
|
# raise AccessError(gettext('hotel.msg_missing_configuration_housekeeping_rooms'))
|
|
|
|
# Housekeeping.write(housekeepings, values)
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def _get_origin(cls):
|
|
|
|
# return ['hotel.operation.maintenance', 'hotel.folio']
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def copy(cls, operations, default=None):
|
|
|
|
# if default is None:
|
|
|
|
# default = {}
|
|
|
|
# else:
|
|
|
|
# default = default.copy()
|
|
|
|
# default.setdefault('state', 'draft')
|
|
|
|
# default.setdefault('invoice_state', '')
|
|
|
|
# return super(Operation, cls).copy(operations, default=default)
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_origin(cls):
|
|
|
|
# Model = Pool().get('ir.model')
|
|
|
|
# models = cls._get_origin()
|
|
|
|
# models = Model.search([
|
|
|
|
# ('model', 'in', models),
|
|
|
|
# ])
|
|
|
|
# return [(None, '')] + [(m.model, m.name) for m in models]
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_calendar(cls, args={}):
|
|
|
|
# Room = Pool().get('hotel.room')
|
|
|
|
# rooms = Room.search_read([], fields_names=['name', 'code'],
|
|
|
|
# order=[('code', 'ASC')]
|
|
|
|
# )
|
|
|
|
# resources = [{'id': str(r['id']), 'name': r['name']} for r in rooms]
|
|
|
|
#
|
|
|
|
# _date = args.get('date')
|
|
|
|
# if _date:
|
|
|
|
# _date = datetime.strptime(_date, 'YYYY-MM-DD')
|
|
|
|
# else:
|
|
|
|
# _date = date.today()
|
|
|
|
#
|
|
|
|
# start_date = _date - timedelta(days=15)
|
|
|
|
# end_date = _date + timedelta(days=45)
|
|
|
|
# operations = cls.search_read([
|
|
|
|
# ('start_date', '>=', start_date),
|
|
|
|
# ('start_date', '<=', end_date),
|
|
|
|
# ('kind', '=', 'occupancy'),
|
|
|
|
# ('state', 'in', ['draft', 'check_in', 'check_out', 'finished']),
|
|
|
|
# ], fields_names=['reference', 'kind', 'party.name', 'start_date',
|
|
|
|
# 'end_date', 'room', 'room.name', 'accommodation.rec_name',
|
|
|
|
# 'state', 'origin', 'main_guest.name']
|
|
|
|
# )
|
|
|
|
#
|
|
|
|
# events = []
|
|
|
|
# for o in operations:
|
|
|
|
# _state = o['state']
|
|
|
|
# if o['kind'] == 'occupancy':
|
|
|
|
# bg_color = COLOR_BOOKING[_state]
|
|
|
|
# else:
|
|
|
|
# bg_color = COLOR_MNT[_state]
|
|
|
|
# events.append({
|
|
|
|
# 'id': o['id'],
|
|
|
|
# 'resourceId': str(o['room']),
|
|
|
|
# 'title': o['party.name'] or ' ',
|
|
|
|
# 'reference': o['reference'],
|
|
|
|
# 'room': o['room.name'],
|
|
|
|
# 'accommodation': o['accommodation.rec_name'],
|
|
|
|
# 'start': str(o['start_date']),
|
|
|
|
# 'end': str(o['end_date']),
|
|
|
|
# 'resizable': False,
|
|
|
|
# 'bgColor': bg_color
|
|
|
|
# })
|
|
|
|
# return [resources, events]
|
|
|
|
#
|
|
|
|
# # @classmethod
|
|
|
|
# # def validate(cls, operations):
|
|
|
|
# # for op in operations:
|
|
|
|
# # op.check_dates(
|
|
|
|
# # op.start_date,
|
|
|
|
# # op.end_date,
|
|
|
|
# # op.room,
|
|
|
|
# # op,
|
|
|
|
# # )
|
|
|
|
# # super(Operation, cls).validate(operations)
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_available_rooms(cls, start_date, end_date, rooms_ids=[], oper=None):
|
|
|
|
# """
|
|
|
|
# Look for available rooms.
|
|
|
|
#
|
|
|
|
# given the date interval, return a list of room ids.
|
|
|
|
#
|
|
|
|
# a room is available if it has no operation that overlaps
|
|
|
|
# with the given date interval.
|
|
|
|
#
|
|
|
|
# the optional 'rooms' list is a list of room instance, is an
|
|
|
|
# additional filter, specifying the ids of the desirable rooms.
|
|
|
|
#
|
|
|
|
# the optional 'oper' is an operation object that has to be
|
|
|
|
# filtered out of the test. it is useful for validating an already
|
|
|
|
# existing operation.
|
|
|
|
# """
|
|
|
|
#
|
|
|
|
# if start_date >= end_date:
|
|
|
|
# raise AccessError(gettext('hotel.msg_invalid_date_range'))
|
|
|
|
#
|
|
|
|
# # define the domain of the operations that find a
|
|
|
|
# # room to be available
|
|
|
|
# dom = ['AND', ['OR',
|
|
|
|
# [
|
|
|
|
# ('start_date', '>=', start_date),
|
|
|
|
# ('start_date', '<', end_date),
|
|
|
|
# ('kind', '=', 'occupancy'),
|
|
|
|
# ], [
|
|
|
|
# ('end_date', '<=', end_date),
|
|
|
|
# ('end_date', '>', start_date),
|
|
|
|
# ('kind', '=', 'occupancy'),
|
|
|
|
# ], [
|
|
|
|
# ('start_date', '<=', start_date),
|
|
|
|
# ('end_date', '>=', end_date),
|
|
|
|
# ('kind', '=', 'occupancy'),
|
|
|
|
# ],
|
|
|
|
# ]]
|
|
|
|
# ## If oper was specified, do not compare the operations with it
|
|
|
|
# if oper is not None:
|
|
|
|
# dom.append(('id', '!=', oper.id))
|
|
|
|
#
|
|
|
|
# if rooms_ids:
|
|
|
|
# dom.append(('room', 'in', rooms_ids))
|
|
|
|
#
|
|
|
|
# operations = cls.search(dom)
|
|
|
|
# rooms_not_available_ids = [operation.room.id for operation in operations]
|
|
|
|
# rooms_available_ids = set(rooms_ids) - set(rooms_not_available_ids)
|
|
|
|
# return list(rooms_available_ids)
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def check_dates(cls, start_date, end_date, room, operation=None):
|
|
|
|
# rooms_ids = [room.id]
|
|
|
|
# available_rooms = cls.get_available_rooms(
|
|
|
|
# start_date, end_date, rooms_ids, operation
|
|
|
|
# )
|
|
|
|
# if room.id not in available_rooms:
|
|
|
|
# raise AccessError(gettext('hotel.overlap_operation_line', s=room.name))
|
|
|
|
#
|
|
|
|
# def get_nights_quantity(self, name=None):
|
|
|
|
# """
|
|
|
|
# Compute nights between start and end
|
|
|
|
# return a integer the mean days of occupancy.
|
|
|
|
# """
|
|
|
|
# nights = 0
|
|
|
|
# if self.start_date and self.end_date:
|
|
|
|
# nights = (self.end_date - self.start_date).days
|
|
|
|
# return nights
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_room_info(cls, op):
|
|
|
|
# description = ' \n'.join([
|
|
|
|
# op.accommodation.rec_name,
|
|
|
|
# 'Huesped Principal: ' + op.main_guest.name,
|
|
|
|
# 'Habitacion: ' + op.room.name,
|
|
|
|
# 'Llegada: ' + str(op.start_date),
|
|
|
|
# 'Salida: ' + str(op.end_date),
|
|
|
|
# ])
|
|
|
|
# return description
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_grouped_sales(cls, operations):
|
|
|
|
# res = {}
|
|
|
|
# transfered = []
|
|
|
|
# for op in operations:
|
|
|
|
# for top in op.transfered_operations:
|
|
|
|
# top.party = op.party
|
|
|
|
# transfered.append(top)
|
|
|
|
#
|
|
|
|
# operations.extend(transfered)
|
|
|
|
# filtered_ops = [op for op in operations if op.invoice_state == 'pending']
|
|
|
|
# for op in filtered_ops:
|
|
|
|
# if op.party.id not in res.keys():
|
|
|
|
# # Add room product to sale
|
|
|
|
# res[op.party.id] = {
|
|
|
|
# 'party': op.party.id,
|
|
|
|
# 'currency': op.currency.id,
|
|
|
|
# 'payment_term': None,
|
|
|
|
# 'guests_qty': len(op.guests) + 1,
|
|
|
|
# 'reference': op.reference,
|
|
|
|
# 'agent': op.agent or None,
|
|
|
|
# 'rooms': op.room.name,
|
|
|
|
# 'company': op.company.id,
|
|
|
|
# 'add_default_charges': op.add_default_charges,
|
|
|
|
# 'vouchers': op.vouchers,
|
|
|
|
# 'lines': [{
|
|
|
|
# 'operations': [op],
|
|
|
|
# 'description': cls.get_room_info(op),
|
|
|
|
# 'quantity': op.nights_quantity,
|
|
|
|
# 'product': op.accommodation,
|
|
|
|
# 'unit_price': op.unit_price,
|
|
|
|
# 'taxes_exception': op.taxes_exception,
|
|
|
|
# }]
|
|
|
|
# }
|
|
|
|
# else:
|
|
|
|
# res[op.party.id]['rooms'] += ' ' + op.room.name
|
|
|
|
# res[op.party.id]['lines'].append({
|
|
|
|
# 'operations': [op],
|
|
|
|
# 'description': cls.get_room_info(op),
|
|
|
|
# 'quantity': op.nights_quantity,
|
|
|
|
# 'product': op.accommodation,
|
|
|
|
# 'unit_price': op.unit_price,
|
|
|
|
# 'taxes_exception': op.taxes_exception,
|
|
|
|
# })
|
|
|
|
# for line in op.lines:
|
|
|
|
# if line.sale_line:
|
|
|
|
# continue
|
|
|
|
# invoice_party_id = line.invoice_to.id
|
|
|
|
# unit_price = op.currency.round(line.unit_price)
|
|
|
|
# if invoice_party_id != op.party.id:
|
|
|
|
# if invoice_party_id not in res.keys():
|
|
|
|
# res[invoice_party_id] = {
|
|
|
|
# 'party': line.invoice_to.id,
|
|
|
|
# 'currency': op.currency.id,
|
|
|
|
# 'payment_term': None,
|
|
|
|
# 'lines': [],
|
|
|
|
# }
|
|
|
|
# res[invoice_party_id]['lines'].append({
|
|
|
|
# 'description': ' | '.join([
|
|
|
|
# str(line.date_service),
|
|
|
|
# line.order or '',
|
|
|
|
# line.description or ''
|
|
|
|
# ]),
|
|
|
|
# 'quantity': line.quantity,
|
|
|
|
# 'product': line.product,
|
|
|
|
# 'operation_line': line,
|
|
|
|
# 'unit_price': unit_price,
|
|
|
|
# 'operation_line': line,
|
|
|
|
# 'taxes_exception': op.taxes_exception,
|
|
|
|
# })
|
|
|
|
# return res
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def create_sales(cls, records):
|
|
|
|
# pool = Pool()
|
|
|
|
# Date = pool.get('ir.date')
|
|
|
|
# SaleLine = pool.get('sale.line')
|
|
|
|
# FolioCharge = pool.get('hotel.folio.charge')
|
|
|
|
# Configuration = pool.get('hotel.configuration')
|
|
|
|
# SaleVoucher = pool.get('sale.sale-account.voucher')
|
|
|
|
# configuration = Configuration.get_configuration()
|
|
|
|
# date_ = Date.today()
|
|
|
|
# ctx = {}
|
|
|
|
# sales_to_create = cls.get_grouped_sales(records)
|
|
|
|
# for rec in sales_to_create.values():
|
|
|
|
# if rec.get('price_list'):
|
|
|
|
# ctx['price_list'] = rec.get('price_list')
|
|
|
|
# ctx['sale_date'] = date_
|
|
|
|
# ctx['currency'] = rec['currency']
|
|
|
|
# ctx['customer'] = rec.party.id
|
|
|
|
#
|
|
|
|
# sale = cls._get_new_sale(rec)
|
|
|
|
# sale.save()
|
|
|
|
# if rec.get('vouchers'):
|
|
|
|
# for v in rec['vouchers']:
|
|
|
|
# SaleVoucher.create([{
|
|
|
|
# 'voucher': v.id,
|
|
|
|
# 'sale': sale.id
|
|
|
|
# }])
|
|
|
|
#
|
|
|
|
# # Add and create default charges lines if exists
|
|
|
|
# if rec.get('guests_qty') and rec.get('add_default_charges'):
|
|
|
|
# for product in configuration.default_charges:
|
|
|
|
# if rec.party:
|
|
|
|
# taxes_ids = cls.get_taxes(sale, product)
|
|
|
|
# new_line = {
|
|
|
|
# 'sale': sale.id,
|
|
|
|
# 'type': 'line',
|
|
|
|
# 'unit': product.template.default_uom.id,
|
|
|
|
# 'quantity': rec['guests_qty'],
|
|
|
|
# 'unit_price': product.template.list_price,
|
|
|
|
# 'product': product.id,
|
|
|
|
# 'description': product.rec_name,
|
|
|
|
# }
|
|
|
|
# if taxes_ids:
|
|
|
|
# new_line.update({'taxes': [('add', taxes_ids)]})
|
|
|
|
# if new_line:
|
|
|
|
# SaleLine.create([new_line])
|
|
|
|
#
|
|
|
|
# for _line in rec['lines']:
|
|
|
|
# line, = SaleLine.create([cls._get_sale_line(sale, _line)])
|
|
|
|
# if _line.get('operations'):
|
|
|
|
# cls.write(_line.get('operations'), {
|
|
|
|
# 'sale_line': line.id,
|
|
|
|
# 'invoice_state': 'in_process'
|
|
|
|
# })
|
|
|
|
# else:
|
|
|
|
# FolioCharge.write([_line.get('operation_line')], {
|
|
|
|
# 'sale_line': line.id,
|
|
|
|
# 'state': 'invoiced',
|
|
|
|
# })
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_context_price(cls, sale, product):
|
|
|
|
# context = {}
|
|
|
|
#
|
|
|
|
# context['currency'] = sale.currency.id
|
|
|
|
# context['customer'] = sale.party.id
|
|
|
|
# context['price_list'] = sale.price_list.id if sale.price_list else None
|
|
|
|
# context['uom'] = product.template.default_uom.id
|
|
|
|
#
|
|
|
|
# # Set taxes before unit_price to have taxes in context of sale price
|
|
|
|
# taxes = []
|
|
|
|
# pattern = {}
|
|
|
|
# for tax in product.customer_taxes_used:
|
|
|
|
# if sale.party and sale.party.customer_tax_rule:
|
|
|
|
# tax_ids = sale.party.customer_tax_rule.apply(tax, pattern)
|
|
|
|
# if tax_ids:
|
|
|
|
# taxes.extend(tax_ids)
|
|
|
|
# continue
|
|
|
|
# taxes.append(tax.id)
|
|
|
|
# if sale.party and sale.party.customer_tax_rule:
|
|
|
|
# tax_ids = sale.party.customer_tax_rule.apply(None, pattern)
|
|
|
|
# if tax_ids:
|
|
|
|
# taxes.extend(tax_ids)
|
|
|
|
#
|
|
|
|
# context['taxes'] = taxes
|
|
|
|
# return context
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def get_taxes(cls, sale, product):
|
|
|
|
# ctx = cls.get_context_price(sale, product)
|
|
|
|
# return ctx['taxes']
|
|
|
|
#
|
|
|
|
# @classmethod
|
|
|
|
# def _get_sale_line(cls, sale, line):
|
|
|
|
# new_line = {
|
|
|
|
# 'sale': sale.id,
|
|
|
|
# 'type': 'line',
|
|
|
|
# 'unit': line['product'].template.default_uom.id,
|
|
|
|
# 'quantity': line['quantity'],
|
|
|
|
# 'unit_price': line['unit_price'],
|
|
|
|
# 'product': line['product'].id,
|
|
|
|
# 'description': line['description'],
|
|
|
|
# }
|
|
|
|
# if not line['taxes_exception']:
|
|
|
|
# taxes_ids = cls.get_taxes(sale, line['product'])
|
|
|
|
# if taxes_ids:
|
|
|
|
# new_line.update({'taxes': [('add', taxes_ids)]})
|
|
|
|
# return new_line
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# class OperationGuest(ModelSQL, ModelView):
|
|
|
|
# 'Operation Guest'
|
|
|
|
# __name__ = 'hotel.operation.guest'
|
|
|
|
# _rec_name = 'party'
|
|
|
|
# operation = fields.Many2One('hotel.operation', 'Operation',
|
|
|
|
# required=True, ondelete='CASCADE')
|
|
|
|
# party = fields.Many2One('party.party', 'Party', required=True)
|
|
|
|
#
|
|
|
|
# def get_rec_name(self, name):
|
|
|
|
# if self.party:
|
|
|
|
# return self.party.name
|
2021-10-06 05:37:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
class OperationMaintenance(Workflow, ModelSQL, ModelView):
|
|
|
|
'Operation Maintenance'
|
|
|
|
__name__ = 'hotel.operation.maintenance'
|
|
|
|
operation = fields.Many2One('hotel.operation', 'Operation', states=STATES_MNT)
|
|
|
|
room = fields.Many2One('hotel.room', 'Room', states=STATES_MNT, select=True,
|
|
|
|
required=True)
|
|
|
|
kind = fields.Selection([
|
|
|
|
('maintenance', 'Maintenance'),
|
|
|
|
], 'Kind', readonly=True, select=True)
|
|
|
|
start_date = fields.Date('Start Date', states=STATES_MNT, required=True,
|
|
|
|
select=True)
|
|
|
|
end_date = fields.Date('End Date', states=STATES_MNT, required=True,
|
|
|
|
select=True)
|
|
|
|
description = fields.Text('Description', states=STATES_MNT, select=True)
|
|
|
|
state = fields.Selection([
|
|
|
|
('draft', 'Draft'),
|
|
|
|
('confirmed', 'Confirmed'),
|
|
|
|
('finished', 'Finished'),
|
|
|
|
('cancelled', 'Canceled'),
|
|
|
|
], 'State', readonly=True, select=True)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(OperationMaintenance, cls).__setup__()
|
|
|
|
cls._transitions |= set((
|
|
|
|
('draft', 'confirmed'),
|
|
|
|
('draft', 'cancelled'),
|
|
|
|
('confirmed', 'finished'),
|
|
|
|
('confirmed', 'cancelled'),
|
|
|
|
))
|
|
|
|
cls._buttons.update({
|
|
|
|
'cancel': {
|
|
|
|
'invisible': ~Eval('state').in_(['draft', 'confirmed']),
|
|
|
|
},
|
|
|
|
'draft': {
|
|
|
|
'invisible': Eval('state') != 'confirmed',
|
|
|
|
},
|
|
|
|
'confirm': {
|
|
|
|
'invisible': Eval('state') != 'draft',
|
|
|
|
},
|
|
|
|
'finish': {
|
|
|
|
'invisible': Eval('state') != 'confirmed',
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def trigger_create(cls, records):
|
|
|
|
for mant in records:
|
|
|
|
mant.create_operation()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_kind():
|
|
|
|
return 'maintenance'
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_state():
|
|
|
|
return 'draft'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
@Workflow.transition('draft')
|
|
|
|
def draft(cls, records):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
@Workflow.transition('cancelled')
|
|
|
|
def cancel(cls, records):
|
|
|
|
for mant in records:
|
|
|
|
mant.delete_operation()
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
@Workflow.transition('confirmed')
|
|
|
|
def confirm(cls, records):
|
|
|
|
for mant in records:
|
|
|
|
mant.update_operation({'state': 'confirmed'})
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
@Workflow.transition('finished')
|
|
|
|
def finish(cls, records):
|
|
|
|
for mant in records:
|
|
|
|
mant.update_operation({'state': 'finished'})
|
|
|
|
|
|
|
|
def delete_operation(self):
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
Operation.delete([self.operation])
|
|
|
|
|
|
|
|
def create_operation(self):
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
values = {
|
|
|
|
'kind': 'maintenance',
|
|
|
|
'room': self.room,
|
|
|
|
'start_date': self.start_date,
|
|
|
|
'end_date': self.end_date,
|
|
|
|
'state': self.state,
|
|
|
|
'origin': str(self)
|
|
|
|
}
|
|
|
|
operation, = Operation.create([values])
|
|
|
|
self.write([self], {'operation': operation.id})
|
|
|
|
|
|
|
|
def update_operation(self, values):
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
Operation.write([self.operation], values)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def write(cls, records, values):
|
|
|
|
Room = Pool().get('hotel.room')
|
|
|
|
for rec in records:
|
|
|
|
if values.get('start_date') or values.get('end_date') or values.get('room'):
|
|
|
|
start_date = values.get('start_date') or rec.start_date
|
|
|
|
end_date = values.get('end_date') or rec.end_date
|
|
|
|
room = Room(values.get('room') or rec.room)
|
|
|
|
Operation().check_dates(start_date, end_date, room, rec.operation)
|
|
|
|
rec.update_operation({
|
|
|
|
'start_date': start_date,
|
|
|
|
'end_date': end_date,
|
|
|
|
'room': room.id,
|
|
|
|
})
|
|
|
|
super(OperationMaintenance, cls).write(records, values)
|
|
|
|
|
|
|
|
def check_method(self):
|
|
|
|
"""
|
|
|
|
Check the methods.
|
|
|
|
"""
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
Operation().check_dates(self.start_date, self.end_date, self.room,
|
|
|
|
self.operation)
|
2021-09-21 06:33:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
class FolioCharge(Workflow, ModelSQL, ModelView):
|
|
|
|
'Folio Charge'
|
|
|
|
__name__ = 'hotel.folio.charge'
|
|
|
|
folio = fields.Many2One('hotel.folio', 'Folio', required=True)
|
2020-04-16 14:45:13 +02:00
|
|
|
date_service = fields.Date('Date Service', select=True, required=True)
|
|
|
|
product = fields.Many2One('product.product', 'Product',
|
2021-10-06 02:27:25 +02:00
|
|
|
domain=[('salable', '=', True)], required=True)
|
2020-04-16 14:45:13 +02:00
|
|
|
quantity = fields.Integer('Quantity', required=True)
|
|
|
|
invoice_to = fields.Many2One('party.party', 'Invoice To', required=True)
|
|
|
|
unit_price = fields.Numeric('Unit Price', required=True)
|
|
|
|
unit_price_w_tax = fields.Function(fields.Numeric('Unit Price'),
|
|
|
|
'get_unit_price_w_tax')
|
|
|
|
order = fields.Char('Order', select=True)
|
|
|
|
description = fields.Char('Description', select=True)
|
|
|
|
state = fields.Selection(INVOICE_STATES, 'State', readonly=True)
|
|
|
|
state_string = state.translated('state')
|
2021-10-06 02:27:25 +02:00
|
|
|
invoice_line = fields.Many2One('account.invoice.line', 'Invoice Line',
|
|
|
|
readonly=True)
|
2020-12-03 16:59:33 +01:00
|
|
|
# sale = fields.Function(fields.Many2One('sale.sale', 'Sale'), 'get_sale')
|
2020-04-16 14:45:13 +02:00
|
|
|
amount = fields.Function(fields.Numeric('Amount',
|
|
|
|
digits=(16, 2)), 'get_amount')
|
|
|
|
taxed_amount = fields.Function(fields.Numeric('Amount with Tax',
|
|
|
|
digits=(16, 2)), 'get_taxed_amount')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
2021-09-21 06:33:06 +02:00
|
|
|
super(FolioCharge, cls).__setup__()
|
2020-04-16 14:45:13 +02:00
|
|
|
cls._buttons.update({
|
|
|
|
'transfer': {
|
|
|
|
'invisible': True,
|
|
|
|
},
|
|
|
|
'bill': {
|
|
|
|
'invisible': Eval('invoice_state') is not None,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_quantity():
|
|
|
|
return 1
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_date_service():
|
|
|
|
today = Pool().get('ir.date').today()
|
|
|
|
return today
|
|
|
|
|
|
|
|
def get_amount(self, name=None):
|
|
|
|
if self.quantity and self.unit_price:
|
|
|
|
return self.quantity * self.unit_price_w_tax
|
2021-07-30 17:34:10 +02:00
|
|
|
return 0
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
def get_unit_price_w_tax(self, name=None):
|
|
|
|
Tax = Pool().get('account.tax')
|
2020-08-17 17:58:45 +02:00
|
|
|
res = self.unit_price or 0
|
2020-04-16 14:45:13 +02:00
|
|
|
if self.unit_price:
|
|
|
|
values = Tax.compute(self.product.template.customer_taxes_used,
|
2020-08-17 17:58:45 +02:00
|
|
|
self.unit_price, 1)
|
2020-04-16 14:45:13 +02:00
|
|
|
if values:
|
|
|
|
value = values[0]
|
|
|
|
res = value['base'] + value['amount']
|
|
|
|
return res
|
|
|
|
|
|
|
|
def get_taxed_amount(self, name=None):
|
|
|
|
if self.quantity and self.unit_price:
|
|
|
|
return self.quantity * self.unit_price
|
|
|
|
|
2020-12-03 17:14:52 +01:00
|
|
|
# def get_sale(self, name=None):
|
|
|
|
# if self.sale_line:
|
|
|
|
# return self.sale_line.sale.id
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
# def compute_amount_with_tax(line):
|
|
|
|
# tax_amount = _ZERO
|
|
|
|
# amount = _ZERO
|
|
|
|
# if line.taxes:
|
|
|
|
# tax_list = Tax.compute(line.taxes, line.unit_price or _ZERO,
|
|
|
|
# line.quantity or 0.0)
|
|
|
|
#
|
|
|
|
# tax_amount = sum([t['amount'] for t in tax_list], _ZERO)
|
|
|
|
#
|
|
|
|
# if line.unit_price:
|
|
|
|
# amount = line.unit_price * Decimal(line.quantity)
|
|
|
|
# return amount + tax_amount
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def bill(cls, records):
|
|
|
|
cls.create_sales(records)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button_action('hotel.wizard_operation_line_transfer')
|
|
|
|
def transfer(cls, records):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@fields.depends('unit_price', 'product')
|
|
|
|
def on_change_product(self):
|
|
|
|
if self.product:
|
|
|
|
self.unit_price = self.product.template.list_price
|
|
|
|
self.description = self.product.description
|
|
|
|
|
|
|
|
|
|
|
|
class OpenMigrationStart(ModelView):
|
|
|
|
'Open Migration Start'
|
|
|
|
__name__ = 'hotel.open_migration.start'
|
|
|
|
start_date = fields.Date('Start Date', required=True)
|
|
|
|
end_date = fields.Date('End Date', required=True)
|
|
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_company():
|
|
|
|
return Transaction().context.get('company')
|
|
|
|
|
|
|
|
|
|
|
|
class OpenMigration(Wizard):
|
|
|
|
'Open Migration'
|
|
|
|
__name__ = 'hotel.open_migration'
|
|
|
|
start = StateView('hotel.open_migration.start',
|
|
|
|
'hotel.open_migration_start_view_form', [
|
|
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
|
|
Button('Open', 'print_', 'tryton-print', default=True),
|
|
|
|
])
|
|
|
|
print_ = StateAction('hotel.report_migration')
|
|
|
|
|
|
|
|
def do_print_(self, action):
|
|
|
|
data = {
|
|
|
|
'start_date': self.start.start_date,
|
|
|
|
'end_date': self.start.end_date,
|
|
|
|
'company': self.start.company.id,
|
|
|
|
}
|
|
|
|
return action, data
|
|
|
|
|
|
|
|
def transition_print_(self):
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class Migration(Report):
|
|
|
|
'Hotel Migration'
|
|
|
|
__name__ = 'hotel.migration'
|
|
|
|
|
|
|
|
@classmethod
|
2021-07-21 14:56:53 +02:00
|
|
|
def get_context(cls, records, header, data):
|
|
|
|
report_context = super().get_context(records, header, data)
|
2021-09-20 23:35:34 +02:00
|
|
|
Line = Pool().get('hotel.folio')
|
2020-04-16 14:45:13 +02:00
|
|
|
start = data['start_date']
|
|
|
|
end = data['end_date']
|
|
|
|
report_context['records'] = Line.search([
|
|
|
|
('arrival_date', '>=', start),
|
2021-04-07 21:03:51 +02:00
|
|
|
('arrival_date', '<=', end),
|
2020-04-16 14:45:13 +02:00
|
|
|
])
|
|
|
|
return report_context
|
|
|
|
|
|
|
|
|
|
|
|
class OperationReport(Report):
|
|
|
|
__name__ = 'hotel.operation'
|
|
|
|
|
|
|
|
@classmethod
|
2021-07-21 14:56:53 +02:00
|
|
|
def get_context(cls, records, header, data):
|
|
|
|
report_context = super().get_context(records, header, data)
|
2020-04-16 14:45:13 +02:00
|
|
|
user = Pool().get('res.user')(Transaction().user)
|
|
|
|
report_context['company'] = user.company
|
|
|
|
return report_context
|
|
|
|
|
|
|
|
|
|
|
|
class CheckOutOperationFailed(ModelView):
|
|
|
|
'Check Out Operation Failed'
|
|
|
|
__name__ = 'hotel.operation.check_out.failed'
|
|
|
|
|
|
|
|
|
|
|
|
class CheckOutOperation(Wizard):
|
|
|
|
'Check Out Operation'
|
|
|
|
__name__ = 'hotel.operation.check_out'
|
|
|
|
start = StateTransition()
|
|
|
|
failed = StateView('hotel.operation.check_out.failed',
|
|
|
|
'hotel.operation_check_out_failed_view_form', [
|
|
|
|
Button('Force Check Out', 'force', 'tryton-forward'),
|
|
|
|
Button('Cancel', 'end', 'tryton-cancel', True),
|
|
|
|
])
|
|
|
|
force = StateTransition()
|
|
|
|
|
|
|
|
def transition_start(self):
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
active_id = Transaction().context['active_id']
|
|
|
|
operations = Operation.browse([active_id])
|
|
|
|
if Operation.validate_check_out_date(operations):
|
|
|
|
return 'end'
|
|
|
|
else:
|
|
|
|
return 'failed'
|
|
|
|
|
|
|
|
def transition_force(self):
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
active_id = Transaction().context['active_id']
|
|
|
|
operations = Operation.browse([active_id])
|
|
|
|
Operation.check_out(operations)
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class ChangeRoomStart(ModelView):
|
|
|
|
'Change Room'
|
|
|
|
__name__ = 'hotel.operation.change_room.ask'
|
|
|
|
from_date = fields.Date('From Date', required=True)
|
|
|
|
room = fields.Many2One('hotel.room', 'Room', required=True, domain=[
|
|
|
|
# ('id', 'in', Eval('targets')),
|
|
|
|
])
|
|
|
|
accommodation = fields.Many2One('product.product',
|
|
|
|
'Accommodation', domain=[
|
|
|
|
('template.kind', '=', 'accommodation'),
|
|
|
|
], required=True)
|
|
|
|
targets = fields.Function(fields.Many2Many('hotel.room', None, None,
|
|
|
|
'Targets'), 'on_change_with_targets')
|
|
|
|
tranfer_charges = fields.Boolean('Transfer Charges')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_from_date():
|
|
|
|
today = Pool().get('ir.date').today()
|
|
|
|
return today
|
|
|
|
|
|
|
|
@fields.depends('from_date', 'accommodation')
|
|
|
|
def on_change_with_targets(self, name=None):
|
|
|
|
pool = Pool()
|
|
|
|
Operation = pool.get('hotel.operation')
|
|
|
|
RoomTemplate = pool.get('hotel.room-product.template')
|
|
|
|
operation = Operation(Transaction().context.get('active_id'))
|
|
|
|
res = []
|
|
|
|
if not self.accommodation or not self.from_date:
|
|
|
|
return res
|
|
|
|
|
|
|
|
room_templates = RoomTemplate.search([
|
|
|
|
('template.accommodation_capacity', '>=', self.accommodation.accommodation_capacity)
|
|
|
|
])
|
|
|
|
rooms_ids = [t.room.id for t in room_templates]
|
|
|
|
|
|
|
|
rooms_available_ids = Operation.get_available_rooms(
|
|
|
|
self.from_date,
|
|
|
|
operation.end_date,
|
|
|
|
rooms_ids=rooms_ids
|
|
|
|
)
|
|
|
|
|
|
|
|
return rooms_available_ids
|
|
|
|
|
|
|
|
|
|
|
|
class ChangeRoom(Wizard):
|
|
|
|
'Change Room'
|
|
|
|
__name__ = 'hotel.operation.change_room'
|
|
|
|
"""
|
|
|
|
this is the wizard that allows the front desk employee to transfer
|
|
|
|
original room, and create a new operation occupany.
|
|
|
|
"""
|
|
|
|
start = StateView('hotel.operation.change_room.ask',
|
|
|
|
'hotel.operation_change_room_view_form', [
|
|
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
|
|
Button('Change', 'change', 'tryton-ok'),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
change = StateTransition()
|
|
|
|
|
|
|
|
def transition_change(self):
|
|
|
|
pool = Pool()
|
|
|
|
Operation = pool.get('hotel.operation')
|
2021-09-21 06:33:06 +02:00
|
|
|
FolioCharge = pool.get('hotel.folio.charge')
|
2020-04-16 14:45:13 +02:00
|
|
|
operation = Operation(Transaction().context.get('active_id'))
|
|
|
|
|
|
|
|
new_operation = {
|
|
|
|
'reference': operation.reference,
|
|
|
|
'room': self.start.room.id,
|
|
|
|
'start_date': self.start.from_date,
|
|
|
|
'end_date': operation.end_date,
|
|
|
|
'party': operation.party.id,
|
|
|
|
'currency': operation.currency.id,
|
|
|
|
'company': operation.company.id,
|
|
|
|
'kind': operation.kind,
|
|
|
|
'main_guest': operation.main_guest.id,
|
|
|
|
'accommodation': self.start.accommodation.id,
|
|
|
|
'origin': str(operation.origin),
|
2020-08-15 18:01:37 +02:00
|
|
|
'state': 'open',
|
2020-04-16 14:45:13 +02:00
|
|
|
'unit_price': operation.unit_price,
|
|
|
|
'lines': []
|
|
|
|
}
|
|
|
|
lines_to_transfer = []
|
|
|
|
_operation, = Operation.create([new_operation])
|
|
|
|
if self.start.tranfer_charges:
|
|
|
|
for line in operation.lines:
|
|
|
|
if line.state is None:
|
|
|
|
lines_to_transfer.append(line)
|
|
|
|
|
|
|
|
if lines_to_transfer:
|
2021-09-21 06:33:06 +02:00
|
|
|
FolioCharge.write([lines_to_transfer], {'operation': _operation.id})
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
operation.end_date = self.start.from_date
|
2020-08-15 18:01:37 +02:00
|
|
|
operation.state = 'closed'
|
2020-04-16 14:45:13 +02:00
|
|
|
operation.target = _operation.id
|
|
|
|
operation.save()
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class TransferOperationStart(ModelView):
|
|
|
|
'Transfer Operation'
|
|
|
|
__name__ = 'hotel.operation.transfer_operation.ask'
|
|
|
|
operation = fields.Many2One('hotel.operation', 'Operation',
|
2020-08-29 17:19:37 +02:00
|
|
|
required=True, domain=[
|
|
|
|
('state', 'in', ['draft', 'open']),
|
|
|
|
])
|
2020-04-16 14:45:13 +02:00
|
|
|
tranfer_charges = fields.Boolean('Transfer Charges')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_tranfer_charges():
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
class TransferOperation(Wizard):
|
|
|
|
'Transfer Operation'
|
|
|
|
__name__ = 'hotel.operation.transfer_operation'
|
|
|
|
"""
|
|
|
|
this is the wizard that allows the front desk employee to transfer
|
|
|
|
original room, and create a new operation occupany.
|
|
|
|
"""
|
|
|
|
start = StateView('hotel.operation.transfer_operation.ask',
|
|
|
|
'hotel.operation_transfer_operation_view_form', [
|
|
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
|
|
Button('Transfer', 'transfer', 'tryton-ok'),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
transfer = StateTransition()
|
|
|
|
|
2020-08-29 17:19:37 +02:00
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(TransferOperation, cls).__setup__()
|
|
|
|
|
2020-04-16 14:45:13 +02:00
|
|
|
def transition_transfer(self):
|
|
|
|
pool = Pool()
|
|
|
|
Operation = pool.get('hotel.operation')
|
2021-09-21 06:33:06 +02:00
|
|
|
FolioCharge = pool.get('hotel.folio.charge')
|
2020-04-16 14:45:13 +02:00
|
|
|
current_op = Operation(Transaction().context.get('active_id'))
|
|
|
|
target_op = self.start.operation
|
2020-08-29 17:19:37 +02:00
|
|
|
if target_op.id == current_op.id:
|
2021-07-21 14:56:53 +02:00
|
|
|
raise AccessError(gettext('hotel.msg_operation_current'))
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
lines_to_transfer = []
|
|
|
|
if self.start.tranfer_charges:
|
|
|
|
for line in current_op.lines:
|
|
|
|
if line.state is None:
|
|
|
|
lines_to_transfer.append(line)
|
|
|
|
|
|
|
|
if lines_to_transfer:
|
2021-09-21 06:33:06 +02:00
|
|
|
FolioCharge.write(lines_to_transfer, {
|
2020-04-16 14:45:13 +02:00
|
|
|
'operation': target_op.id
|
|
|
|
})
|
|
|
|
|
2020-08-15 18:01:37 +02:00
|
|
|
current_op.state = 'transfered'
|
2020-04-16 14:45:13 +02:00
|
|
|
current_op.operation_target = target_op.id
|
|
|
|
current_op.save()
|
|
|
|
target_op.save()
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class TransferChargeStart(ModelView):
|
|
|
|
'Transfer Charge'
|
|
|
|
__name__ = 'hotel.operation.transfer_charge.ask'
|
|
|
|
operation = fields.Many2One('hotel.operation', 'Operation',
|
|
|
|
required=True, domain=[('state', '=', 'check_in')])
|
|
|
|
|
|
|
|
|
|
|
|
class TransferCharge(Wizard):
|
|
|
|
'Transfer Operation'
|
|
|
|
__name__ = 'hotel.operation.transfer_charge'
|
|
|
|
start = StateView('hotel.operation.transfer_charge.ask',
|
|
|
|
'hotel.operation_transfer_charge_view_form', [
|
|
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
|
|
Button('Transfer', 'transfer', 'tryton-ok'),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
transfer = StateTransition()
|
|
|
|
|
|
|
|
def transition_transfer(self):
|
|
|
|
pool = Pool()
|
2021-09-21 06:33:06 +02:00
|
|
|
FolioCharge = pool.get('hotel.folio.charge')
|
|
|
|
current_line = FolioCharge(Transaction().context.get('active_id'))
|
2020-04-16 14:45:13 +02:00
|
|
|
target_op = self.start.operation
|
|
|
|
|
|
|
|
current_operation = current_line.operation
|
|
|
|
current_line.operation = target_op.id
|
|
|
|
current_line.save()
|
|
|
|
current_operation.save()
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class OperationByConsumerReport(Report):
|
2021-09-21 06:33:06 +02:00
|
|
|
__name__ = 'hotel.folio.charge'
|
2020-04-16 14:45:13 +02:00
|
|
|
|
|
|
|
@classmethod
|
2021-07-21 14:56:53 +02:00
|
|
|
def get_context(cls, records, header, data):
|
|
|
|
report_context = super().get_context(records, header, data)
|
2020-04-16 14:45:13 +02:00
|
|
|
pool = Pool()
|
|
|
|
Operation = pool.get('hotel.operation')
|
|
|
|
user = pool.get('res.user')(Transaction().user)
|
|
|
|
consumer_lines = []
|
|
|
|
total_amount = 0
|
|
|
|
if records:
|
|
|
|
line = records[0]
|
|
|
|
operation = Operation(line.operation.id)
|
|
|
|
total_amount = operation.room_amount
|
|
|
|
for l in operation.lines:
|
|
|
|
if l.invoice_to.id == line.invoice_to.id:
|
|
|
|
consumer_lines.append(l)
|
|
|
|
total_amount += l.amount
|
|
|
|
setattr(operation, 'lines', consumer_lines)
|
|
|
|
setattr(operation, 'total_amount', total_amount)
|
|
|
|
|
|
|
|
report_context['records'] = [operation]
|
|
|
|
report_context['company'] = user.company
|
|
|
|
return report_context
|
|
|
|
|
|
|
|
|
|
|
|
class OperationBill(Wizard):
|
|
|
|
'Operation Bill'
|
|
|
|
__name__ = 'hotel.operation.bill'
|
|
|
|
start_state = 'create_bill'
|
|
|
|
create_bill = StateTransition()
|
|
|
|
|
|
|
|
def transition_create_bill(self):
|
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
ids = Transaction().context['active_ids']
|
|
|
|
operations = Operation.browse(ids)
|
|
|
|
Operation.bill(operations)
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class OperationVoucher(ModelSQL):
|
|
|
|
'Operation - Voucher'
|
|
|
|
__name__ = 'hotel.operation-account.voucher'
|
|
|
|
_table = 'operation_vouchers_rel'
|
|
|
|
operation = fields.Many2One('hotel.operation', 'Operation',
|
|
|
|
ondelete='CASCADE', select=True, required=True)
|
|
|
|
voucher = fields.Many2One('account.voucher', 'Voucher', select=True,
|
|
|
|
domain=[('voucher_type', '=', 'receipt')], ondelete='RESTRICT',
|
|
|
|
required=True)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def set_voucher_origin(cls, voucher_id, operation_id):
|
|
|
|
cls.create([{
|
|
|
|
'voucher': voucher_id,
|
|
|
|
'operation': operation_id,
|
|
|
|
}])
|
|
|
|
|
|
|
|
|
|
|
|
class StatisticsByMonthStart(ModelView):
|
|
|
|
'Statistics By Month Start'
|
|
|
|
__name__ = 'hotel.statistics_by_month.start'
|
|
|
|
period = fields.Many2One('account.period', 'Period', required=True)
|
|
|
|
company = fields.Many2One('company.company', 'Company', required=True)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_company():
|
|
|
|
return Transaction().context.get('company')
|
|
|
|
|
|
|
|
|
|
|
|
class StatisticsByMonth(Wizard):
|
|
|
|
'Statistics By Month'
|
|
|
|
__name__ = 'hotel.statistics_by_month'
|
|
|
|
start = StateView('hotel.statistics_by_month.start',
|
|
|
|
'hotel.print_hotel_statistics_by_month_start_view_form', [
|
|
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
|
|
Button('Open', 'print_', 'tryton-print', default=True),
|
|
|
|
])
|
|
|
|
print_ = StateAction('hotel.statistics_by_month_report')
|
|
|
|
|
|
|
|
def do_print_(self, action):
|
|
|
|
data = {
|
|
|
|
'period': self.start.period.id,
|
|
|
|
'company': self.start.company.id,
|
|
|
|
}
|
|
|
|
return action, data
|
|
|
|
|
|
|
|
def transition_print_(self):
|
|
|
|
return 'end'
|
|
|
|
|
|
|
|
|
|
|
|
class StatisticsByMonthReport(Report):
|
|
|
|
'Hotel Statistics By Month'
|
|
|
|
__name__ = 'hotel.statistics_by_month.report'
|
|
|
|
|
|
|
|
@classmethod
|
2021-07-21 14:56:53 +02:00
|
|
|
def get_context(cls, records, header, data):
|
|
|
|
report_context = super().get_context(records, header, data)
|
2020-04-16 14:45:13 +02:00
|
|
|
Operation = Pool().get('hotel.operation')
|
|
|
|
Period = Pool().get('account.period')
|
|
|
|
Company = Pool().get('company.company')
|
|
|
|
Rooms = Pool().get('hotel.room')
|
|
|
|
period = Period(data['period'])
|
|
|
|
company = Company(data['company'])
|
|
|
|
month_days = (period.end_date - period.start_date).days + 1
|
|
|
|
rooms_available = []
|
|
|
|
rooms_sold = []
|
|
|
|
beds_available = []
|
|
|
|
beds_sold = []
|
|
|
|
local_guests = []
|
|
|
|
foreign_guests = []
|
|
|
|
room1_sold = []
|
|
|
|
room2_sold = []
|
|
|
|
room_suite_sold = []
|
|
|
|
room_other_sold = []
|
|
|
|
guests_one_ng = []
|
|
|
|
guests_two_ng = []
|
|
|
|
guests_three_ng = []
|
|
|
|
guests_four_ng = []
|
|
|
|
guests_five_ng = []
|
|
|
|
guests_six_ng = []
|
|
|
|
guests_seven_ng = []
|
|
|
|
guests_eight_ng = []
|
|
|
|
guests_permanent_ng = []
|
|
|
|
reason_bussiness = []
|
|
|
|
reason_bussiness_foreign = []
|
|
|
|
reason_leisure = []
|
|
|
|
reason_leisure_foreign = []
|
|
|
|
reason_convention = []
|
|
|
|
reason_convention_foreign = []
|
|
|
|
reason_health = []
|
|
|
|
reason_health_foreign = []
|
|
|
|
reason_transport = []
|
|
|
|
reason_transport_foreign = []
|
|
|
|
reason_other = []
|
|
|
|
reason_other_foreign = []
|
|
|
|
total_guests = []
|
|
|
|
operations = Operation.search(['OR',
|
|
|
|
[
|
|
|
|
('start_date', '>=', period.start_date),
|
|
|
|
('start_date', '<=', period.end_date),
|
|
|
|
('kind', '=', 'occupancy'),
|
|
|
|
], [
|
|
|
|
('end_date', '>=', period.start_date),
|
|
|
|
('end_date', '<=', period.end_date),
|
|
|
|
('kind', '=', 'occupancy'),
|
|
|
|
]
|
|
|
|
])
|
|
|
|
rooms = Rooms.search([])
|
|
|
|
rooms_available = [len(rooms) * month_days]
|
|
|
|
for r in rooms:
|
|
|
|
beds_available.append(
|
|
|
|
r.main_accommodation.accommodation_capacity * month_days
|
|
|
|
)
|
|
|
|
|
|
|
|
def _get_ctx_dates(op):
|
|
|
|
start_date = op.start_date
|
|
|
|
end_date = op.end_date
|
|
|
|
if op.start_date < period.start_date:
|
|
|
|
start_date = period.start_date
|
|
|
|
if op.end_date > period.end_date:
|
|
|
|
end_date = period.end_date
|
|
|
|
|
|
|
|
sub_dates = [
|
|
|
|
str(start_date + timedelta(n))
|
|
|
|
for n in range((end_date - start_date).days)
|
|
|
|
]
|
|
|
|
return sub_dates
|
|
|
|
|
|
|
|
for op in operations:
|
|
|
|
room_capacity = op.room.main_accommodation.accommodation_capacity
|
|
|
|
ctx_dates = _get_ctx_dates(op)
|
|
|
|
len_ctx_dates = len(ctx_dates)
|
|
|
|
rooms_sold.append(len_ctx_dates)
|
|
|
|
beds_sold.append(len_ctx_dates * room_capacity)
|
|
|
|
qty_guests = len(op.guests)
|
|
|
|
if not qty_guests:
|
|
|
|
qty_guests = 1
|
|
|
|
total_guests.append(qty_guests)
|
|
|
|
is_local = True
|
|
|
|
if op.main_guest.type_document == '41':
|
|
|
|
is_local = False
|
|
|
|
foreign_guests.append(qty_guests)
|
|
|
|
else:
|
|
|
|
local_guests.append(qty_guests)
|
|
|
|
|
|
|
|
if room_capacity == 1:
|
|
|
|
room1_sold.append(qty_guests)
|
|
|
|
elif room_capacity == 2:
|
|
|
|
room2_sold.append(qty_guests)
|
|
|
|
elif room_capacity > 2:
|
|
|
|
room_suite_sold.append(qty_guests)
|
|
|
|
|
|
|
|
if len_ctx_dates == 1:
|
|
|
|
guests_one_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates == 2:
|
|
|
|
guests_two_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates == 3:
|
|
|
|
guests_three_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates == 4:
|
|
|
|
guests_four_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates == 5:
|
|
|
|
guests_five_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates == 6:
|
|
|
|
guests_six_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates == 7:
|
|
|
|
guests_seven_ng.append(qty_guests)
|
|
|
|
elif len_ctx_dates >= 8:
|
|
|
|
guests_eight_ng.append(qty_guests)
|
|
|
|
|
|
|
|
segment = 'bussiness'
|
|
|
|
if op.origin:
|
|
|
|
if hasattr(op.origin, 'booking'):
|
|
|
|
segment = op.origin.booking.segment
|
|
|
|
|
|
|
|
if segment == 'bussiness':
|
|
|
|
if is_local:
|
|
|
|
reason_bussiness.append(qty_guests)
|
|
|
|
else:
|
|
|
|
reason_bussiness_foreign.append(qty_guests)
|
|
|
|
elif segment == 'convention':
|
|
|
|
if is_local:
|
|
|
|
reason_convention.append(qty_guests)
|
|
|
|
else:
|
|
|
|
reason_convention_foreign.append(qty_guests)
|
|
|
|
elif segment == 'health':
|
|
|
|
if is_local:
|
|
|
|
reason_health.append(qty_guests)
|
|
|
|
else:
|
|
|
|
reason_health_foreign.append(qty_guests)
|
|
|
|
else:
|
|
|
|
if is_local:
|
|
|
|
reason_leisure.append(qty_guests)
|
|
|
|
else:
|
|
|
|
reason_leisure_foreign.append(qty_guests)
|
|
|
|
|
|
|
|
def _get_rate(val):
|
|
|
|
res = 0
|
|
|
|
if sum_total_guests > 0:
|
|
|
|
res = round(float(sum(val)) / sum_total_guests, 4)
|
|
|
|
return res
|
|
|
|
|
|
|
|
sum_total_guests = sum(total_guests)
|
|
|
|
rate_guests_one_ng = _get_rate(guests_one_ng)
|
|
|
|
rate_guests_two_ng = _get_rate(guests_two_ng)
|
|
|
|
rate_guests_three_ng = _get_rate(guests_three_ng)
|
|
|
|
rate_guests_four_ng = _get_rate(guests_four_ng)
|
|
|
|
rate_guests_five_ng = _get_rate(guests_five_ng)
|
|
|
|
rate_guests_six_ng = _get_rate(guests_six_ng)
|
|
|
|
rate_guests_seven_ng = _get_rate(guests_seven_ng)
|
|
|
|
rate_guests_eight_ng = _get_rate(guests_eight_ng)
|
|
|
|
|
|
|
|
report_context['period'] = period.name
|
|
|
|
report_context['company'] = company.party.name
|
|
|
|
report_context['rooms_available'] = sum(rooms_available)
|
|
|
|
report_context['rooms_sold'] = sum(rooms_sold)
|
|
|
|
report_context['beds_available'] = sum(beds_available)
|
|
|
|
report_context['beds_sold'] = sum(beds_sold)
|
|
|
|
report_context['local_guests'] = sum(local_guests)
|
|
|
|
report_context['foreign_guests'] = sum(foreign_guests)
|
|
|
|
report_context['room1_sold'] = sum(room1_sold)
|
|
|
|
report_context['room2_sold'] = sum(room2_sold)
|
|
|
|
report_context['room_suite_sold'] = sum(room_suite_sold)
|
|
|
|
report_context['room_other_sold'] = sum(room_other_sold)
|
|
|
|
report_context['guests_one_ng'] = rate_guests_one_ng
|
|
|
|
report_context['guests_two_ng'] = rate_guests_two_ng
|
|
|
|
report_context['guests_three_ng'] = rate_guests_three_ng
|
|
|
|
report_context['guests_four_ng'] = rate_guests_four_ng
|
|
|
|
report_context['guests_five_ng'] = rate_guests_five_ng
|
|
|
|
report_context['guests_six_ng'] = rate_guests_six_ng
|
|
|
|
report_context['guests_seven_ng'] = rate_guests_seven_ng
|
|
|
|
report_context['guests_eight_ng'] = rate_guests_eight_ng
|
|
|
|
report_context['guests_permanent_ng'] = sum(guests_permanent_ng)
|
|
|
|
report_context['reason_bussiness'] = sum(reason_bussiness)
|
|
|
|
report_context['reason_bussiness_foreign'] = sum(reason_bussiness_foreign)
|
|
|
|
report_context['reason_leisure'] = sum(reason_leisure)
|
|
|
|
report_context['reason_leisure_foreign'] = sum(reason_leisure_foreign)
|
|
|
|
report_context['reason_convention'] = sum(reason_convention)
|
|
|
|
report_context['reason_convention_foreign'] = sum(reason_convention_foreign)
|
|
|
|
report_context['reason_health'] = sum(reason_health)
|
|
|
|
report_context['reason_health_foreign'] = sum(reason_health_foreign)
|
|
|
|
report_context['reason_transport'] = sum(reason_transport)
|
|
|
|
report_context['reason_transport_foreign'] = sum(reason_transport_foreign)
|
|
|
|
report_context['reason_other_foreign'] = sum(reason_other_foreign)
|
|
|
|
report_context['reason_other'] = sum(reason_other)
|
|
|
|
|
|
|
|
return report_context
|