Checked with linter
This commit is contained in:
parent
1fdd3c5a26
commit
b6c9f18bb1
BIN
booking.fodt
BIN
booking.fodt
Binary file not shown.
240
booking.py
240
booking.py
|
@ -1,10 +1,8 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import os
|
||||
from datetime import datetime, timedelta, date
|
||||
from decimal import Decimal
|
||||
|
||||
from trytond.tools import file_open
|
||||
from trytond.model import Workflow, ModelView, ModelSQL, fields
|
||||
from trytond.wizard import (
|
||||
Wizard, StateView, Button, StateTransition, StateReport
|
||||
|
@ -91,7 +89,7 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
states=STATES, domain=[('id', If(In('company',
|
||||
Eval('context', {})), '=', '!='), Get(Eval('context', {}),
|
||||
'company', 0))], readonly=True)
|
||||
lines = fields.One2Many('hotel.folio', 'booking', 'Lines',
|
||||
lines = fields.One2Many('hotel.folio', 'booking', 'Folios',
|
||||
states={
|
||||
'required': Eval('state') == 'confirmed',
|
||||
'readonly': Eval('registration_state').in_(['check_in', 'check_out']),
|
||||
|
@ -130,7 +128,6 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
created_channel = fields.DateTime('Created Channel', states={'readonly': True})
|
||||
vouchers = fields.Many2Many('hotel.booking-account.voucher', 'booking',
|
||||
'voucher', 'Vouchers', states={'readonly': False})
|
||||
vip = fields.Boolean('V.I.P. Customer', states=STATES)
|
||||
ota_booking_code = fields.Char('OTA Code', select=True,
|
||||
states={'invisible': Eval('media') != 'ota'}
|
||||
)
|
||||
|
@ -166,20 +163,15 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
readonly=True), 'get_stock_moves')
|
||||
channel_icon = fields.Function(fields.Char('Channel Icon'),
|
||||
'get_channel_icon')
|
||||
emails = fields.One2Many('email.activity', 'origin',
|
||||
'Emails', readonly=True,
|
||||
# domain=[
|
||||
# ('patient', '=', Eval('patient')),
|
||||
# ('urgent', '=', True),
|
||||
# ]
|
||||
)
|
||||
payment_method = fields.Selection([
|
||||
('', ''),
|
||||
('holder_pay_all', 'Holder Pay All'),
|
||||
('holder_pay_acco', 'Holder Pay Accommodation'),
|
||||
('guests_pay', 'Guests Pay'),
|
||||
], 'Pyament Method', states=STATES)
|
||||
emails = fields.One2Many('email.activity', 'origin', 'Emails',
|
||||
readonly=True)
|
||||
responsible_payment = fields.Selection([
|
||||
('holder', 'Holder'),
|
||||
('holder_guest', 'Holder / Guest'),
|
||||
('guest', 'Guest'),
|
||||
], 'Responsible for Payment', states={'required': True})
|
||||
credit_card = fields.Char('Credit Card', states=STATES)
|
||||
vip = fields.Boolean('V.I.P. Customer', states=STATES)
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
|
@ -197,10 +189,12 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
))
|
||||
cls._buttons.update({
|
||||
'select_rooms': {
|
||||
'invisible': Eval('state').in_(['finished', 'cancelled', 'not_show']),
|
||||
'invisible': Eval('state').in_(
|
||||
['finished', 'cancelled', 'not_show']),
|
||||
},
|
||||
'update_holder': {
|
||||
'invisible': Eval('state').in_(['finished', 'cancelled', 'not_show']),
|
||||
'invisible': Eval('state').in_(
|
||||
['finished', 'cancelled', 'not_show']),
|
||||
},
|
||||
'cancel': {
|
||||
'invisible': Eval('state').in_(
|
||||
|
@ -229,10 +223,13 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
},
|
||||
'bill_to_channel': {
|
||||
'invisible': ~Eval('channel'),
|
||||
'readonly': (Eval('channel_paymode') != 'ota_collect') | Eval('channel_invoice', True),
|
||||
},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
def default_responsible_payment():
|
||||
return 'holder'
|
||||
|
||||
@staticmethod
|
||||
def default_payment_term():
|
||||
Config = Pool().get('hotel.configuration')
|
||||
|
@ -339,8 +336,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
l_taxes = Tax.compute(Tax.browse(_taxes), unit_price, quantity)
|
||||
for tax in l_taxes:
|
||||
taxline = TaxableMixin._compute_tax_line(**tax)
|
||||
# Base must always be rounded per folio as there will be one
|
||||
# tax folio per taxable_lines
|
||||
# Base must always be rounded per folio as there will
|
||||
# be one tax folio per taxable_lines
|
||||
if self.currency:
|
||||
taxline['base'] = self.currency.round(taxline['base'])
|
||||
if taxline not in taxes:
|
||||
|
@ -393,7 +390,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
line.reference = self.ota_booking_code
|
||||
|
||||
def is_person(self):
|
||||
if self.party.type_document in ('12', '13', '21', '22', '41', '42', '47'):
|
||||
if self.party.type_document in (
|
||||
'12', '13', '21', '22', '41', '42', '47'):
|
||||
return True
|
||||
|
||||
@fields.depends('party', 'price_list', 'lines')
|
||||
|
@ -413,7 +411,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
self.party = self.channel.agent.party.id
|
||||
elif self.channel.invoice_to == 'customer':
|
||||
self.party = None
|
||||
self.channel_paymode = self.channel.payment_method
|
||||
if self.channel.payment_method == 'ota_collect':
|
||||
self.responsible_payment = 'holder'
|
||||
if self.channel.price_list:
|
||||
self.price_list = self.channel.price_list
|
||||
|
||||
|
@ -460,7 +459,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
@Workflow.transition('confirmed')
|
||||
def confirm(cls, records):
|
||||
for rec in records:
|
||||
# FIXME check if does not exist previous occupancy if exist update state
|
||||
# FIXME check if does not exist previous occupancy
|
||||
# if exist update state
|
||||
rec.update_folio('pending')
|
||||
cls.create_channel_voucher(rec)
|
||||
|
||||
|
@ -492,7 +492,7 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
def create_channel_voucher(cls, bk):
|
||||
Voucher = Pool().get('account.voucher')
|
||||
# If ota_collect is paymode for folios
|
||||
if not bk.channel or bk.channel_paymode != 'ota_collect':
|
||||
if not bk.channel or bk.responsible_payment != 'ota_collect':
|
||||
return
|
||||
|
||||
payment_mode = bk.channel.payment_mode
|
||||
|
@ -647,7 +647,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
reference = fo.registration_card
|
||||
else:
|
||||
reference = ','.join(
|
||||
[fo.registration_card for fo in folios if fo.registration_card or '']
|
||||
[fo.registration_card for fo in folios
|
||||
if fo.registration_card or '']
|
||||
)
|
||||
res[party.id] = {
|
||||
'party': party,
|
||||
|
@ -731,11 +732,11 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
Move = Pool().get('stock.move')
|
||||
moves = {}
|
||||
to_create = []
|
||||
for folo in self.lines:
|
||||
for folio in self.lines:
|
||||
for charge in folio.charges:
|
||||
move = self.get_move(charge)
|
||||
if move:
|
||||
moves[line.id] = move
|
||||
moves[folio.id] = move
|
||||
for m in moves:
|
||||
moves[m].state = 'draft'
|
||||
to_create.append(moves[m]._save_values)
|
||||
|
@ -749,9 +750,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
'''
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Date = pool.get('ir.date')
|
||||
|
||||
if not self.product or self.product.type != 'goods' and self.quantity <= 0:
|
||||
product = self.product
|
||||
if not product or product.type != 'goods' and self.quantity <= 0:
|
||||
return
|
||||
|
||||
if not charge.folio.storage:
|
||||
|
@ -759,9 +759,10 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
customer_location = self.party.customer_location
|
||||
move = Move()
|
||||
move.quantity = self.quantity
|
||||
move.uom = self.product.default_uom
|
||||
move.product = self.product
|
||||
# Add on create charge take default storage from folio if isn not present
|
||||
move.uom = product.default_uom
|
||||
move.product = product
|
||||
# Add on create charge take default storage
|
||||
# from folio if isn not present
|
||||
move.from_location = charge.folio.storage
|
||||
move.to_location = customer_location
|
||||
move.state = 'draft'
|
||||
|
@ -797,7 +798,6 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
Invoice = pool.get('account.invoice')
|
||||
Config = pool.get('account.voucher_configuration')
|
||||
config = Config.get_configuration()
|
||||
lines_to_create = []
|
||||
commission = bk.currency.round(bk.channel_commission)
|
||||
note, = Note.create([{
|
||||
'description': bk.number,
|
||||
|
@ -872,7 +872,7 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
invoice.save()
|
||||
invoice, = Invoice.browse([invoice.id])
|
||||
try:
|
||||
Invoice.submit(invoices)
|
||||
Invoice.submit([invoice])
|
||||
invoice.save()
|
||||
except:
|
||||
pass
|
||||
|
@ -893,7 +893,6 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
invoice = {}
|
||||
_folios, _charges = cls.pending_to_invoice(folios)
|
||||
|
||||
booking = folios[0].booking
|
||||
if not _folios and not _charges:
|
||||
return
|
||||
|
||||
|
@ -945,16 +944,15 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
def _get_new_invoice(cls, data):
|
||||
pool = Pool()
|
||||
Invoice = pool.get('account.invoice')
|
||||
Party = pool.get('party.party')
|
||||
Agent = pool.get('commission.agent')
|
||||
Journal = pool.get('account.journal')
|
||||
PaymentTerm = pool.get('account.invoice.payment_term')
|
||||
Date = pool.get('ir.date')
|
||||
date_ = Date.today()
|
||||
|
||||
price_list_id = None
|
||||
if data.get('price_list'):
|
||||
price_list_id = data['price_list']
|
||||
# price_list_id = None
|
||||
# if data.get('price_list'):
|
||||
# price_list_id = data['price_list']
|
||||
|
||||
company_id = Transaction().context.get('company')
|
||||
party = data['party']
|
||||
|
@ -977,7 +975,6 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
payment_terms = PaymentTerm.search([])
|
||||
payment_term = payment_terms[0]
|
||||
|
||||
|
||||
return Invoice(
|
||||
company=company_id,
|
||||
payment_term=payment_term.id,
|
||||
|
@ -999,9 +996,8 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
Folio.write(list(self.lines), {'registration_state': state})
|
||||
|
||||
@classmethod
|
||||
def get_context_price(cls,
|
||||
product, party=None, currency=None, _date=None, price_list=None,
|
||||
taxes_exception=False):
|
||||
def get_context_price(cls, product, party=None, currency=None,
|
||||
_date=None, price_list=None, taxes_exception=False):
|
||||
context = {}
|
||||
if currency:
|
||||
context['currency'] = currency.id
|
||||
|
@ -1035,12 +1031,11 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
|
||||
def get_total_advance(self, name):
|
||||
Advance = Pool().get('hotel.booking-account.voucher')
|
||||
Payments = Pool().get('hotel.booking-statement.line')
|
||||
advances = Advance.search([('booking', '=', self.id)])
|
||||
res = sum([ad.voucher.amount_to_pay for ad in advances])
|
||||
payments = sum([pay.amount for pay in self.payments])
|
||||
advance_by_channel = _ZERO
|
||||
if self.channel and self.channel_paymode == 'ota_collect':
|
||||
if self.channel and self.responsible_payment == 'holder':
|
||||
advance_by_channel = self.channel_commission
|
||||
return res + payments + advance_by_channel
|
||||
|
||||
|
@ -1086,8 +1081,9 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
return res
|
||||
|
||||
def get_channel_commission(self, name):
|
||||
res = [line.commission_amount for line in self.lines if line.commission_amount]
|
||||
total_commission = sum(res)
|
||||
res = [line.commission_amount
|
||||
for line in self.lines if line.commission_amount]
|
||||
# total_commission = sum(res)
|
||||
base_comm = [folio.on_change_with_room_amount() for folio in self.lines]
|
||||
for comm in self.extra_commissions:
|
||||
extras = sum(base_comm) * Decimal(comm.commission / 100)
|
||||
|
@ -1105,7 +1101,7 @@ class Booking(Workflow, ModelSQL, ModelView):
|
|||
return
|
||||
template.subject = f'{template.subject} No. {self.number}'
|
||||
if email:
|
||||
res = Template.send(template, self, email, attach=True)
|
||||
Template.send(template, self, email, attach=True)
|
||||
Activity.create([{
|
||||
'template': template.id,
|
||||
'origin': str(self),
|
||||
|
@ -1197,7 +1193,8 @@ class SelectRoomsAsk(ModelView):
|
|||
unit_price = booking.currency.round(unit_price)
|
||||
return unit_price
|
||||
|
||||
@fields.depends('arrival_date', 'departure_date', 'accommodation', 'overbooking')
|
||||
@fields.depends('arrival_date', 'departure_date', 'accommodation',
|
||||
'overbooking')
|
||||
def on_change_with_targets(self, name=None):
|
||||
pool = Pool()
|
||||
RoomTemplate = pool.get('hotel.room-product.template')
|
||||
|
@ -1230,7 +1227,8 @@ class SelectRooms(Wizard):
|
|||
this is the wizard that allows the front desk employee to select
|
||||
rooms, based on the requirements listed by the customer.
|
||||
"""
|
||||
start = StateView('hotel.booking.select_rooms.ask',
|
||||
start = StateView(
|
||||
'hotel.booking.select_rooms.ask',
|
||||
'hotel.view_select_rooms_form', [
|
||||
Button('Exit', 'end', 'tryton-cancel'),
|
||||
Button('Add and Continue', 'add_continue', 'tryton-forward'),
|
||||
|
@ -1322,7 +1320,8 @@ class BookingForecastStart(ModelView):
|
|||
class BookingForecast(Wizard):
|
||||
'Booking Forecast'
|
||||
__name__ = 'hotel.print_booking_forecast'
|
||||
start = StateView('hotel.print_booking_forecast.start',
|
||||
start = StateView(
|
||||
'hotel.print_booking_forecast.start',
|
||||
'hotel.print_booking_forecast_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Print', 'print_', 'tryton-print', default=True),
|
||||
|
@ -1425,11 +1424,12 @@ class RoomsOccupancyStart(ModelView):
|
|||
class RoomsOccupancy(Wizard):
|
||||
'Rooms Occupancy'
|
||||
__name__ = 'hotel.print_rooms_occupancy'
|
||||
start = StateView('hotel.print_rooms_occupancy.start',
|
||||
'hotel.print_rooms_occupancy_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'print_', 'tryton-print', default=True),
|
||||
])
|
||||
start = StateView(
|
||||
'hotel.print_rooms_occupancy.start',
|
||||
'hotel.print_rooms_occupancy_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'print_', 'tryton-print', default=True),
|
||||
])
|
||||
print_ = StateReport('hotel.rooms_occupancy.report')
|
||||
|
||||
def do_print_(self, action):
|
||||
|
@ -1526,7 +1526,6 @@ class BookingDailyStart(ModelView):
|
|||
('', ''),
|
||||
], 'State')
|
||||
|
||||
|
||||
@staticmethod
|
||||
def default_date():
|
||||
Date_ = Pool().get('ir.date')
|
||||
|
@ -1691,7 +1690,8 @@ class UpdateHolderStart(ModelView):
|
|||
class UpdateHolder(Wizard):
|
||||
'Update Holder'
|
||||
__name__ = 'hotel.update_holder'
|
||||
start = StateView('hotel.update_holder.start',
|
||||
start = StateView(
|
||||
'hotel.update_holder.start',
|
||||
'hotel.update_holder_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Update', 'update', 'tryton-ok', default=True),
|
||||
|
@ -1732,7 +1732,7 @@ class UpdateHolder(Wizard):
|
|||
return res
|
||||
|
||||
def _set_cms(self, action, rec, email, mobile=None, phone=None):
|
||||
cms = [] # contact_mechanisms
|
||||
cms = [] # contact_mechanisms
|
||||
if mobile:
|
||||
cms.append({'type': 'mobile', 'value': mobile})
|
||||
if email:
|
||||
|
@ -1755,7 +1755,6 @@ class UpdateHolder(Wizard):
|
|||
edit = True
|
||||
booking = Booking(active_id)
|
||||
_party = self.start
|
||||
rec_company = {}
|
||||
to_folio = {}
|
||||
if _party.vehicle_plate:
|
||||
to_folio['vehicle_plate'] = _party.vehicle_plate
|
||||
|
@ -2068,7 +2067,7 @@ class BookingChannelCommision(ModelSQL):
|
|||
|
||||
class StatementPaymentForm(ModelView):
|
||||
'Statement Payment Form'
|
||||
__name__ = 'sale_shop.payment_form.start'
|
||||
__name__ = 'hotel.payment_form.start'
|
||||
statement = fields.Many2One('account.statement', 'Statement',
|
||||
required=True, domain=['OR', [
|
||||
('create_uid.login', '=', Eval('user')),
|
||||
|
@ -2084,16 +2083,25 @@ class StatementPaymentForm(ModelView):
|
|||
kind = fields.Selection([
|
||||
('booking', 'Booking'),
|
||||
('folio', 'Folio'),
|
||||
],'Kind')
|
||||
], 'Kind', required=True)
|
||||
folio = fields.Many2One('hotel.folio', 'Folio', domain=[
|
||||
('id', 'in', Eval('folios')),
|
||||
], states={
|
||||
'invisible': Eval('kind') == 'booking'
|
||||
}, depends=['folios']
|
||||
)
|
||||
voucher = fields.Char('Voucher', states={
|
||||
'required': Bool(Eval('require_voucher')),
|
||||
}, depends=['require_voucher'])
|
||||
party = fields.Many2One('party.party', 'Party')
|
||||
user = fields.Many2One('res.user', 'User', states={
|
||||
'readonly': True
|
||||
})
|
||||
require_voucher = fields.Boolean('Require Voucher',
|
||||
depends=['statement'])
|
||||
party = fields.Many2One('party.party', 'Party', domain=[
|
||||
('id', 'in', Eval('parties'))
|
||||
], required=True)
|
||||
user = fields.Many2One('res.user', 'User', states={'readonly': True})
|
||||
require_voucher = fields.Boolean('Require Voucher', depends=['statement'])
|
||||
# parties = fields.Function(fields.Many2Many('party.party', None, None,
|
||||
# 'Parties'), 'get_parties')
|
||||
parties = fields.Many2Many('party.party', None, None, 'Parties')
|
||||
folios = fields.Many2Many('hotel.folio', None, None, 'Folios')
|
||||
|
||||
@classmethod
|
||||
def default_require_voucher(cls):
|
||||
|
@ -2118,11 +2126,14 @@ class StatementPaymentForm(ModelView):
|
|||
return self.statement.journal.require_voucher
|
||||
return False
|
||||
|
||||
# def get_parties(self, name=None):
|
||||
# active_id = Transaction().context['active_id']
|
||||
|
||||
|
||||
class WizardStatementPayment(Wizard):
|
||||
'Wizard Statement Payment'
|
||||
__name__ = 'sale_shop.payment_form'
|
||||
start = StateView('sale_shop.payment_form.start',
|
||||
__name__ = 'hotel.payment_form'
|
||||
start = StateView('hotel.payment_form.start',
|
||||
'hotel.statement_payment_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Pay', 'pay_', 'tryton-ok', default=True),
|
||||
|
@ -2135,34 +2146,54 @@ class WizardStatementPayment(Wizard):
|
|||
Folio = pool.get('hotel.folio')
|
||||
model = Transaction().context['active_model']
|
||||
active_id = Transaction().context['active_id']
|
||||
parties_ids = []
|
||||
folios_ids = []
|
||||
folio_id = None
|
||||
party_id = None
|
||||
pending_to_pay = 0
|
||||
kind = 'booking'
|
||||
if model == "hotel.booking":
|
||||
booking = Booking(active_id)
|
||||
if not booking.party:
|
||||
raise UserError(gettext(
|
||||
'hotel.msg_missing_party_holder'))
|
||||
raise UserError(gettext('hotel.msg_missing_party_holder'))
|
||||
|
||||
party = None
|
||||
if booking.channel and booking.channel_paymode == 'ota_collect':
|
||||
if booking.responsible_payment in ('holder', 'holder_guest'):
|
||||
parties_ids.append(booking.party.id)
|
||||
if booking.responsible_payment in ('guest', 'holder_guest'):
|
||||
for folio in booking.lines:
|
||||
if folio.main_guest != booking.channel.agent.party:
|
||||
party = folio.main_guest
|
||||
break
|
||||
else:
|
||||
party = booking.party
|
||||
parties_ids.append(folio.main_guest.id)
|
||||
folios_ids.append(folio.id)
|
||||
# if folio.main_guest != booking.channel.agent.party:
|
||||
# party = folio.main_guest
|
||||
# break
|
||||
# else:
|
||||
# party = booking.party
|
||||
|
||||
if not party:
|
||||
raise UserError(gettext('hotel.msg_missing_customer'))
|
||||
# if not party:
|
||||
# raise UserError(gettext('hotel.msg_missing_customer'))
|
||||
pending_to_pay = booking.pending_to_pay
|
||||
print('booking.pending_to_pay....', booking.pending_to_pay)
|
||||
else:
|
||||
kind = 'folio'
|
||||
folio = Folio(active_id)
|
||||
folios_ids.append(folio.id)
|
||||
party = folio.main_guest
|
||||
pending_to_pay = folio.pending_charges
|
||||
parties_ids.append(folio.main_guest.id)
|
||||
if folio.booking.responsible_payment == 'guest':
|
||||
pending_to_pay = folio.pending_total
|
||||
elif folio.booking.responsible_payment == 'holder_guest':
|
||||
pending_to_pay = folio.pending_charges
|
||||
if folio.booking.party == folio.main_guest and folio.booking.responsible_payment == 'holder':
|
||||
pending_to_pay = folio.booking.pending_to_pay
|
||||
|
||||
return {
|
||||
'currency_digits': 2,
|
||||
'party': party.id,
|
||||
'amount_to_pay': pending_to_pay
|
||||
'party': party_id,
|
||||
'folio': folio_id,
|
||||
'parties': parties_ids,
|
||||
'folios': folios_ids,
|
||||
'amount_to_pay': pending_to_pay,
|
||||
'kind': kind,
|
||||
}
|
||||
|
||||
def transition_pay_(self):
|
||||
|
@ -2174,22 +2205,30 @@ class WizardStatementPayment(Wizard):
|
|||
active_id = Transaction().context.get('active_id', False)
|
||||
|
||||
form = self.start
|
||||
target_model = 'booking'
|
||||
if form.kind == 'booking':
|
||||
record = Booking(active_id)
|
||||
description = record.number
|
||||
else:
|
||||
target_model = 'folio'
|
||||
record = Folio(active_id)
|
||||
description = record.registration_card
|
||||
if record.booking.responsible_payment != 'holder':
|
||||
description = record.registration_card
|
||||
else:
|
||||
record = record.booking
|
||||
description = record.number
|
||||
target_model = 'booking'
|
||||
|
||||
try:
|
||||
account = form.party.account_receivable.id
|
||||
except:
|
||||
raise UserError(gettext(
|
||||
'sale_shop.party_without_account_receivable'))
|
||||
'hotel.party_without_account_receivable'))
|
||||
|
||||
number = ''
|
||||
if form.voucher:
|
||||
number = form.voucher
|
||||
|
||||
if form.amount_to_pay:
|
||||
line = StatementLine(
|
||||
statement=form.statement.id,
|
||||
|
@ -2208,15 +2247,26 @@ class WizardStatementPayment(Wizard):
|
|||
# We keep to mark all concepts charges/folios as paid if
|
||||
# the customer to pay all pending values
|
||||
if form.kind == 'folio':
|
||||
if form.amount_to_pay >= record.pending_total:
|
||||
for charge in record.charges:
|
||||
charge.status = 'paid'
|
||||
charge.save()
|
||||
record.payment_status = 'paid'
|
||||
else:
|
||||
if target_model == 'folio':
|
||||
folio = record
|
||||
if folio.booking.responsible_payment == 'guest':
|
||||
pending = folio.pending_total
|
||||
elif folio.booking.responsible_payment == 'holder_guest':
|
||||
pending = folio.pending_charges
|
||||
if form.amount_to_pay >= pending:
|
||||
for charge in record.charges:
|
||||
if charge.status == 'paid':
|
||||
continue
|
||||
charge.status = 'paid'
|
||||
charge.save()
|
||||
folio.payment_status = 'paid'
|
||||
|
||||
if target_model == 'booking':
|
||||
if form.amount_to_pay >= record.pending_to_pay:
|
||||
for folio in record.lines:
|
||||
for charge in folio.charges:
|
||||
if charge.status == 'paid':
|
||||
continue
|
||||
charge.status = 'paid'
|
||||
charge.save()
|
||||
folio.payment_status = 'paid'
|
||||
|
|
|
@ -344,10 +344,10 @@ this repository contains the full copyright notices and license terms. -->
|
|||
|
||||
<record model="ir.action.wizard" id="wizard_statement_payment_form">
|
||||
<field name="name">Pay</field>
|
||||
<field name="wiz_name">sale_shop.payment_form</field>
|
||||
<field name="wiz_name">hotel.payment_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="statement_payment_view_form">
|
||||
<field name="model">sale_shop.payment_form.start</field>
|
||||
<field name="model">hotel.payment_form.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">statement_payment_form</field>
|
||||
</record>
|
||||
|
|
|
@ -101,6 +101,6 @@ class ChannelTax(ModelSQL):
|
|||
__name__ = 'hotel.channel-account.tax'
|
||||
_table = 'hotel_channel_taxes_rel'
|
||||
channel = fields.Many2One('hotel.channel', 'Sale Channel',
|
||||
ondelete='CASCADE', select=True, required=True)
|
||||
ondelete='CASCADE', select=True, required=True)
|
||||
tax = fields.Many2One('account.tax', 'Tax', ondelete='RESTRICT',
|
||||
required=True)
|
||||
required=True)
|
||||
|
|
|
@ -8,7 +8,6 @@ class Company(metaclass=PoolMeta):
|
|||
__name__ = 'company.company'
|
||||
mig_code = fields.Char('Migration Code')
|
||||
city_code = fields.Char('City Code')
|
||||
property_code = fields.Char('Property Code', help='Code on channel manager')
|
||||
rnt_code = fields.Char('Registro Nacional de Turismo')
|
||||
matricula_mercantil = fields.Char('Matricula Mercantil')
|
||||
logo_link = fields.Char('Logo Link')
|
||||
|
|
40
dash.py
40
dash.py
|
@ -1,45 +1,47 @@
|
|||
# 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 trytond.pool import PoolMeta
|
||||
from trytond.model import fields, ModelView, ModelSQL
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.modules.dash.dash import DashAppBase
|
||||
|
||||
|
||||
class DashApp(metaclass=PoolMeta):
|
||||
__name__ = 'dash.app'
|
||||
__name__ = "dash.app"
|
||||
|
||||
@classmethod
|
||||
def _get_origin(cls):
|
||||
origins = super(DashApp, cls)._get_origin()
|
||||
origins.extend([
|
||||
'dash.app.hotel_planner',
|
||||
'dash.app.housekeeping',
|
||||
'dash.app.web_checkin',
|
||||
])
|
||||
origins.extend(
|
||||
[
|
||||
"dash.app.hotel_planner",
|
||||
"dash.app.housekeeping",
|
||||
"dash.app.web_checkin",
|
||||
]
|
||||
)
|
||||
return origins
|
||||
|
||||
@classmethod
|
||||
def get_selection(cls):
|
||||
options = super(DashApp, cls).get_selection()
|
||||
options.extend([
|
||||
('hotel_planner', 'Planner'),
|
||||
('housekeeping', 'Housekeeping'),
|
||||
('web_checkin', 'Housekeeping'),
|
||||
])
|
||||
options.extend(
|
||||
[
|
||||
("hotel_planner", "Planner"),
|
||||
("housekeeping", "Housekeeping"),
|
||||
("web_checkin", "Housekeeping"),
|
||||
]
|
||||
)
|
||||
return options
|
||||
|
||||
|
||||
class AppHotelPlanner(DashAppBase):
|
||||
'App Hotel Planner'
|
||||
__name__ = 'dash.app.hotel_planner'
|
||||
"App Hotel Planner"
|
||||
__name__ = "dash.app.hotel_planner"
|
||||
|
||||
|
||||
class AppHousekeeping(DashAppBase):
|
||||
'App Housekeeping'
|
||||
__name__ = 'dash.app.housekeeping'
|
||||
"App Housekeeping"
|
||||
__name__ = "dash.app.housekeeping"
|
||||
|
||||
|
||||
class AppWebCheckIn(DashAppBase):
|
||||
'App Web Check-In'
|
||||
__name__ = 'dash.app.web_checkin'
|
||||
"App Web Check-In"
|
||||
__name__ = "dash.app.web_checkin"
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# 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 trytond.pool import PoolMeta
|
||||
from trytond.model import fields, ModelView, ModelSQL
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class EmailActivity(metaclass=PoolMeta):
|
||||
|
|
257
folio.py
257
folio.py
|
@ -15,8 +15,9 @@ from trytond.transaction import Transaction
|
|||
from trytond.model.exceptions import AccessError
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.i18n import gettext
|
||||
from .constants import (REGISTRATION_STATE, COMPLEMENTARY, INVOICE_STATES,
|
||||
COLOR_BOOKING, COLOR_MNT)
|
||||
from .constants import (
|
||||
REGISTRATION_STATE, COMPLEMENTARY, INVOICE_STATES
|
||||
)
|
||||
from .room import ROOM_STATUS
|
||||
|
||||
|
||||
|
@ -74,10 +75,7 @@ class Folio(ModelSQL, ModelView):
|
|||
'get_unit_price_w_tax')
|
||||
uom = fields.Many2One('product.uom', 'UOM', readonly=True)
|
||||
main_guest = fields.Many2One('party.party', 'Main Guest', select=True,
|
||||
states={
|
||||
'readonly': True
|
||||
}
|
||||
)
|
||||
states={'readonly': True})
|
||||
contact = fields.Char('Contact', states=STATES_CHECKIN)
|
||||
party_holder = fields.Function(fields.Many2One('party.party',
|
||||
'Party Holder'), 'get_party_holder')
|
||||
|
@ -91,9 +89,7 @@ class Folio(ModelSQL, ModelView):
|
|||
unit_digits = fields.Function(fields.Integer('Unit Digits'), 'get_unit_digits')
|
||||
notes = fields.Text('Notes')
|
||||
total_amount = fields.Function(fields.Numeric('Total Amount',
|
||||
digits=(16, 2)), 'get_totals')
|
||||
total_balance = fields.Function(fields.Numeric('Total Balance',
|
||||
digits=(16, 2)), 'get_totals')
|
||||
digits=(16, 2)), 'get_total_amount')
|
||||
commission_amount = fields.Numeric('Commission Amount', digits=(16, 2),
|
||||
depends=['nights_quantity', 'unit_price'], states={'readonly': True}
|
||||
)
|
||||
|
@ -146,10 +142,12 @@ class Folio(ModelSQL, ModelView):
|
|||
vehicle_plate = fields.Char('Vehicle Plate')
|
||||
taxes = fields.Many2Many('hotel.folio-account.tax', 'folio', 'tax', 'Taxes',
|
||||
order=[('tax.sequence', 'ASC'), ('tax.id', 'ASC')],
|
||||
domain=[('parent', '=', None), ['OR',
|
||||
domain=[
|
||||
('parent', '=', None), ['OR',
|
||||
('group', '=', None),
|
||||
('group.kind', 'in', ['sale', 'both'])],
|
||||
('group.kind', 'in', ['sale', 'both'])
|
||||
],
|
||||
],
|
||||
)
|
||||
room_status = fields.Function(fields.Selection(ROOM_STATUS,
|
||||
'Room Status'), 'get_room_status')
|
||||
|
@ -189,11 +187,12 @@ class Folio(ModelSQL, ModelView):
|
|||
'invisible': Eval('registration_state') != 'check_out',
|
||||
},
|
||||
'do_payment': {
|
||||
'invisible': Eval('registration_state').in_(['no_show', 'cancelled', 'pending']),
|
||||
'invisible': Eval('registration_state').in_([
|
||||
'no_show', 'cancelled', 'pending'
|
||||
]),
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@staticmethod
|
||||
def default_to_invoice():
|
||||
return True
|
||||
|
@ -215,20 +214,18 @@ class Folio(ModelSQL, ModelView):
|
|||
def do_payment(cls, records):
|
||||
pass
|
||||
|
||||
def get_pending_to_pay(self, name):
|
||||
accommodation = 0
|
||||
charges = 0
|
||||
def get_pending_to_pay(self, name=None):
|
||||
bk = self.booking
|
||||
res = 0
|
||||
if name == 'pending_accommodation':
|
||||
if bk.channel_paymode != 'ota_collect' or (
|
||||
bk.payment_term and bk.payment_term.payment_type == 1):
|
||||
if self.payment_status != 'paid' and (
|
||||
not bk.payment_term or bk.payment_term.payment_type == 1):
|
||||
res = self.get_total_accommodation()
|
||||
if name == 'pending_charges':
|
||||
total_charges = self.get_total_charges()
|
||||
charge_paid = 0
|
||||
for charge in self.charges:
|
||||
if charge.invoice_line and \
|
||||
charge.invoice_line.invoice.state == 'paid':
|
||||
if charge.status == 'paid':
|
||||
charge_paid += charge.amount
|
||||
res = total_charges - charge_paid
|
||||
if name == 'pending_total':
|
||||
|
@ -285,17 +282,17 @@ class Folio(ModelSQL, ModelView):
|
|||
@classmethod
|
||||
@ModelView.button
|
||||
def check_in(cls, records):
|
||||
for rec in records:
|
||||
# rec.booking.party.pre_validate()
|
||||
if rec.booking.state == 'offer':
|
||||
for record in records:
|
||||
record.validate_check_in()
|
||||
if record.booking.state == 'offer':
|
||||
raise UserError(gettext('hotel.msg_missing_confirm_booking'))
|
||||
if rec.main_guest is None:
|
||||
if record.main_guest is None:
|
||||
raise UserError(gettext('hotel.msg_missing_main_guest'))
|
||||
if rec.room is None:
|
||||
if record.room is None:
|
||||
raise UserError(gettext('hotel.msg_missing_select_room'))
|
||||
rec.set_registration_number()
|
||||
rec.check_room()
|
||||
cls.update_room(rec, 'check_in')
|
||||
record.set_registration_number()
|
||||
record.check_room()
|
||||
cls.update_room(record, 'check_in')
|
||||
cls.write(records, {'registration_state': 'check_in'})
|
||||
|
||||
def check_room(self):
|
||||
|
@ -308,16 +305,40 @@ class Folio(ModelSQL, ModelView):
|
|||
if self.room:
|
||||
return self.room.state
|
||||
|
||||
def validate_check_in(self):
|
||||
if self.arrival_date > date.today():
|
||||
raise UserError(gettext('hotel.msg_cannot_check_in_future'))
|
||||
|
||||
def validate_check_out(self):
|
||||
bk = self.booking
|
||||
|
||||
def _check_accommodation(folio):
|
||||
if folio.payment_status == 'pending':
|
||||
raise UserError(gettext('hotel.msg_accommodation_not_paid'))
|
||||
|
||||
def _check_charges(folio):
|
||||
for charge in folio.charges:
|
||||
if charge.status == 'pending':
|
||||
raise UserError(gettext('hotel.msg_charges_not_paid'))
|
||||
break
|
||||
|
||||
if bk.responsible_payment == 'guest':
|
||||
_check_charges(self)
|
||||
_check_accommodation(self)
|
||||
elif bk.responsible_payment == 'holder':
|
||||
if self.main_guest == bk.party:
|
||||
for folio in bk.lines:
|
||||
_check_charges(folio)
|
||||
_check_accommodation(folio)
|
||||
else:
|
||||
for folio in bk.lines:
|
||||
_check_charges(folio)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def check_out(cls, records):
|
||||
for record in records:
|
||||
for charge in record.charges:
|
||||
if charge.status == 'pending':
|
||||
raise UserError(
|
||||
gettext('hotel.msg_charges_not_paid',
|
||||
product=charge.product.name)
|
||||
)
|
||||
record.validate_check_out()
|
||||
cls.write([record], {'registration_state': 'check_out'})
|
||||
cls.update_room(record, 'check_out')
|
||||
|
||||
|
@ -401,8 +422,7 @@ class Folio(ModelSQL, ModelView):
|
|||
res = value['base'] + value['amount']
|
||||
return res
|
||||
|
||||
@fields.depends('unit_price', 'nights_quantity', 'arrival_date',
|
||||
'departure_date')
|
||||
@fields.depends('unit_price', 'nights_quantity')
|
||||
def on_change_with_room_amount(self, name=None):
|
||||
res = 0
|
||||
if self.unit_price and self.nights_quantity:
|
||||
|
@ -554,19 +574,17 @@ class Folio(ModelSQL, ModelView):
|
|||
|
||||
folios = cls.search(dom)
|
||||
rooms_not_available_ids = [folio.room.id for folio in folios]
|
||||
dom = ['AND',
|
||||
['OR',
|
||||
[
|
||||
('start_date', '>=', start_date),
|
||||
('start_date', '<=', end_date),
|
||||
], [
|
||||
('end_date', '<=', end_date),
|
||||
('end_date', '>=', start_date),
|
||||
], [
|
||||
('start_date', '<=', start_date),
|
||||
('end_date', '>=', end_date),
|
||||
],
|
||||
],
|
||||
dom = ['AND', ['OR',
|
||||
[
|
||||
('start_date', '>=', start_date),
|
||||
('start_date', '<=', end_date),
|
||||
], [
|
||||
('end_date', '<=', end_date),
|
||||
('end_date', '>=', start_date),
|
||||
], [
|
||||
('start_date', '<=', start_date),
|
||||
('end_date', '>=', end_date),
|
||||
]],
|
||||
('state', 'in', ('in_progress', 'finished')),
|
||||
]
|
||||
maintenance = Maintenance.search(dom)
|
||||
|
@ -643,18 +661,15 @@ class Folio(ModelSQL, ModelView):
|
|||
res.append(charge.amount)
|
||||
return sum(res)
|
||||
|
||||
def get_totals(self, name):
|
||||
def get_total_amount(self, name):
|
||||
"""
|
||||
The total amount of folio based on room flat price.
|
||||
TODO: If room fee is applied should be used for total price calculation
|
||||
instead of flat price. Fee is linked to channel management.
|
||||
"""
|
||||
res = []
|
||||
amount_nights = self.get_total_accommodation()
|
||||
if name == 'total_amount' or (name == 'total_balance' and not self.invoice_line):
|
||||
res.append(amount_nights)
|
||||
charges = self.get_total_charges()
|
||||
res.append(charges)
|
||||
res.append(self.get_total_accommodation())
|
||||
res.append(self.get_total_charges())
|
||||
res = round(sum(res), Folio.total_amount.digits[1])
|
||||
return res
|
||||
|
||||
|
@ -664,7 +679,8 @@ class Folio(ModelSQL, ModelView):
|
|||
Calculation of commission amount for channel based on booking
|
||||
"""
|
||||
res = Decimal(0)
|
||||
if self.nights_quantity and self.unit_price and self.booking and self.booking.channel:
|
||||
if self.nights_quantity and self.unit_price and self.booking and \
|
||||
self.booking.channel:
|
||||
amount = self.on_change_with_room_amount()
|
||||
res = self.booking.channel.compute(amount)
|
||||
return res
|
||||
|
@ -889,7 +905,7 @@ class FolioGuest(ModelSQL, ModelView):
|
|||
self.target_country = self.nationality.id
|
||||
self.origin_country = self.nationality.id
|
||||
|
||||
@fields.depends('id_number','name', 'sex', 'email', 'mobile',
|
||||
@fields.depends('id_number', 'name', 'sex', 'email', 'mobile',
|
||||
'visa_number', 'visa_date', 'birthday', 'nationality')
|
||||
def on_change_id_number(self):
|
||||
if self.id_number:
|
||||
|
@ -1199,11 +1215,12 @@ class OpenMigrationStart(ModelView):
|
|||
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),
|
||||
])
|
||||
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):
|
||||
|
@ -1257,7 +1274,8 @@ class CheckOutOperation(Wizard):
|
|||
'Check Out Operation'
|
||||
__name__ = 'hotel.operation.check_out'
|
||||
start = StateTransition()
|
||||
failed = StateView('hotel.operation.check_out.failed',
|
||||
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),
|
||||
|
@ -1288,8 +1306,8 @@ class ChangeRoomStart(ModelView):
|
|||
room = fields.Many2One('hotel.room', 'Room', required=True, domain=[
|
||||
# ('id', 'in', Eval('targets')),
|
||||
])
|
||||
accommodation = fields.Many2One('product.product',
|
||||
'Accommodation', domain=[
|
||||
accommodation = fields.Many2One('product.product', 'Accommodation',
|
||||
domain=[
|
||||
('template.kind', '=', 'accommodation'),
|
||||
], required=True)
|
||||
targets = fields.Function(fields.Many2Many('hotel.room', None, None,
|
||||
|
@ -1308,11 +1326,12 @@ class ChangeRoomStart(ModelView):
|
|||
RoomTemplate = pool.get('hotel.room-product.template')
|
||||
operation = Operation(Transaction().context.get('active_id'))
|
||||
res = []
|
||||
if not self.accommodation or not self.from_date:
|
||||
acco = self.accommodation
|
||||
if not acco or not self.from_date:
|
||||
return res
|
||||
|
||||
room_templates = RoomTemplate.search([
|
||||
('template.accommodation_capacity', '>=', self.accommodation.accommodation_capacity)
|
||||
('template.accommodation_capacity', '>=', acco.accommodation_capacity)
|
||||
])
|
||||
rooms_ids = [t.room.id for t in room_templates]
|
||||
|
||||
|
@ -1332,7 +1351,8 @@ class ChangeRoom(Wizard):
|
|||
this is the wizard that allows the front desk employee to transfer
|
||||
original room, and create a new operation occupany.
|
||||
"""
|
||||
start = StateView('hotel.folio.change_room.ask',
|
||||
start = StateView(
|
||||
'hotel.folio.change_room.ask',
|
||||
'hotel.folio_change_room_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Change', 'change', 'tryton-ok'),
|
||||
|
@ -1341,36 +1361,32 @@ class ChangeRoom(Wizard):
|
|||
change = StateTransition()
|
||||
|
||||
def transition_change(self):
|
||||
pool = Pool()
|
||||
Folio = pool.get('hotel.folio')
|
||||
FolioCharge = pool.get('hotel.folio.charge')
|
||||
operation = Folio(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),
|
||||
'state': 'open',
|
||||
'unit_price': operation.unit_price,
|
||||
'lines': []
|
||||
}
|
||||
lines_to_transfer = []
|
||||
# pool = Pool()
|
||||
# Folio = pool.get('hotel.folio')
|
||||
# operation = Folio(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),
|
||||
# 'state': 'open',
|
||||
# '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:
|
||||
# FolioCharge.write([lines_to_transfer], {'operation': _operation.id})
|
||||
#
|
||||
# operation.end_date = self.start.from_date
|
||||
# operation.state = 'closed'
|
||||
|
@ -1382,10 +1398,9 @@ class ChangeRoom(Wizard):
|
|||
class TransferOperationStart(ModelView):
|
||||
'Transfer Operation'
|
||||
__name__ = 'hotel.folio.transfer_operation.ask'
|
||||
folio = fields.Many2One('hotel.folio', 'Folio',
|
||||
required=True, domain=[
|
||||
('state', 'in', ['draft', 'open']),
|
||||
])
|
||||
folio = fields.Many2One('hotel.folio', 'Folio', required=True, domain=[
|
||||
('state', 'in', ['draft', 'open']),
|
||||
])
|
||||
tranfer_charges = fields.Boolean('Transfer Charges')
|
||||
|
||||
@staticmethod
|
||||
|
@ -1400,7 +1415,8 @@ class TransferOperation(Wizard):
|
|||
this is the wizard that allows the front desk employee to transfer
|
||||
original room, and create a new operation occupany.
|
||||
"""
|
||||
start = StateView('hotel.folio.transfer_operation.ask',
|
||||
start = StateView(
|
||||
'hotel.folio.transfer_operation.ask',
|
||||
'hotel.folio_transfer_operation_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Transfer', 'transfer', 'tryton-ok'),
|
||||
|
@ -1408,10 +1424,6 @@ class TransferOperation(Wizard):
|
|||
)
|
||||
transfer = StateTransition()
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super(TransferOperation, cls).__setup__()
|
||||
|
||||
def transition_transfer(self):
|
||||
pool = Pool()
|
||||
Operation = pool.get('hotel.folio')
|
||||
|
@ -1442,14 +1454,15 @@ class TransferOperation(Wizard):
|
|||
class TransferChargeStart(ModelView):
|
||||
'Transfer Charge'
|
||||
__name__ = 'hotel.folio.transfer_charge.ask'
|
||||
folio = fields.Many2One('hotel.folio', 'Operation',
|
||||
required=True, domain=[('state', '=', 'check_in')])
|
||||
folio = fields.Many2One('hotel.folio', 'Operation', required=True, domain=[
|
||||
('state', '=', 'check_in')])
|
||||
|
||||
|
||||
class TransferCharge(Wizard):
|
||||
'Transfer Operation'
|
||||
__name__ = 'hotel.folio.transfer_charge'
|
||||
start = StateView('hotel.folio.transfer_charge.ask',
|
||||
start = StateView(
|
||||
'hotel.folio.transfer_charge.ask',
|
||||
'hotel.folio_transfer_charge_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Transfer', 'transfer', 'tryton-ok'),
|
||||
|
@ -1485,8 +1498,8 @@ class OperationByConsumerReport(Report):
|
|||
line = records[0]
|
||||
folio = Folio(line.folio.id)
|
||||
total_amount = folio.room_amount
|
||||
for l in folio.lines:
|
||||
if l.invoice_to and l.invoice_to.id == line.invoice_to.id:
|
||||
for ch in folio.lines:
|
||||
if ch.invoice_to and ch.invoice_to.id == line.invoice_to.id:
|
||||
consumer_lines.append(l)
|
||||
total_amount += l.amount
|
||||
setattr(folio, 'lines', consumer_lines)
|
||||
|
@ -1515,10 +1528,10 @@ class OperationVoucher(ModelSQL):
|
|||
'Operation - Voucher'
|
||||
__name__ = 'hotel.folio-account.voucher'
|
||||
_table = 'folio_vouchers_rel'
|
||||
folio = fields.Many2One('hotel.folio', 'Folio',
|
||||
ondelete='CASCADE', required=True)
|
||||
folio = fields.Many2One('hotel.folio', 'Folio', ondelete='CASCADE',
|
||||
required=True)
|
||||
voucher = fields.Many2One('account.voucher', 'Voucher', required=True,
|
||||
domain=[('voucher_type', '=', 'receipt')], ondelete='RESTRICT')
|
||||
domain=[('voucher_type', '=', 'receipt')], ondelete='RESTRICT')
|
||||
|
||||
@classmethod
|
||||
def set_voucher_origin(cls, voucher_id, folio_id):
|
||||
|
@ -1547,7 +1560,7 @@ class FolioStockMove(ModelSQL):
|
|||
__name__ = 'hotel.folio-stock.move'
|
||||
_table = 'hotel_folio_stock_move_rel'
|
||||
folio = fields.Many2One('hotel.folio', 'Folio',
|
||||
ondelete='CASCADE', select=True, required=True)
|
||||
ondelete='CASCADE', select=True, required=True)
|
||||
move = fields.Many2One('stock.move', 'Move', select=True,
|
||||
ondelete='RESTRICT', required=True)
|
||||
|
||||
|
@ -1566,11 +1579,12 @@ class StatisticsByMonthStart(ModelView):
|
|||
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),
|
||||
])
|
||||
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):
|
||||
|
@ -1630,8 +1644,7 @@ class StatisticsByMonthReport(Report):
|
|||
reason_other = []
|
||||
reason_other_foreign = []
|
||||
total_guests = []
|
||||
folios = Operation.search(['OR',
|
||||
[
|
||||
folios = Operation.search(['OR', [
|
||||
('start_date', '>=', period.start_date),
|
||||
('start_date', '<=', period.end_date),
|
||||
('kind', '=', 'occupancy'),
|
||||
|
@ -1801,7 +1814,8 @@ class GuestsListStart(ModelView):
|
|||
class GuestsList(Wizard):
|
||||
'Guests List'
|
||||
__name__ = 'hotel.print_guests_list'
|
||||
start = StateView('hotel.print_guests_list.start',
|
||||
start = StateView(
|
||||
'hotel.print_guests_list.start',
|
||||
'hotel.print_guests_list_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'print_', 'tryton-print', default=True),
|
||||
|
@ -1914,9 +1928,9 @@ class HotelFolioTax(ModelSQL):
|
|||
__name__ = 'hotel.folio-account.tax'
|
||||
_table = 'hotel_folio_account_tax'
|
||||
folio = fields.Many2One('hotel.folio', 'Folio', ondelete='CASCADE',
|
||||
select=True, required=True)
|
||||
required=True)
|
||||
tax = fields.Many2One('account.tax', 'Tax', ondelete='RESTRICT',
|
||||
select=True, required=True)
|
||||
required=True)
|
||||
|
||||
|
||||
class FolioInvoiceStart(ModelView):
|
||||
|
@ -1932,7 +1946,8 @@ class FolioInvoiceStart(ModelView):
|
|||
class FolioInvoice(Wizard):
|
||||
'Wizard Folio Invoice'
|
||||
__name__ = 'hotel.folio_invoice'
|
||||
start = StateView('hotel.folio_invoice.start',
|
||||
start = StateView(
|
||||
'hotel.folio_invoice.start',
|
||||
'hotel.folio_invoice_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Invoice', 'invoice', 'tryton-ok', default=True),
|
||||
|
|
2
guest.py
2
guest.py
|
@ -2,8 +2,6 @@
|
|||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Tag(ModelSQL, ModelView):
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.pyson import Eval
|
||||
from trytond.model import Workflow, ModelView, ModelSQL, fields, Unique
|
||||
from trytond.wizard import Wizard, StateView, Button, StateReport
|
||||
from trytond.report import Report
|
||||
from trytond.transaction import Transaction
|
||||
from datetime import datetime
|
||||
from trytond.pool import Pool
|
||||
|
||||
STATES = {'invisible': (Eval('type') != 'service')}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
from datetime import date
|
||||
from trytond.pool import PoolMeta, Pool
|
||||
|
||||
|
||||
class Invoice(metaclass=PoolMeta):
|
||||
__name__ = 'account.invoice'
|
||||
|
||||
|
@ -66,7 +67,6 @@ class Invoice(metaclass=PoolMeta):
|
|||
|
||||
@classmethod
|
||||
def set_advances_from_origin(cls, invoice):
|
||||
advances_to_add = []
|
||||
vouchers = []
|
||||
for line in invoice.lines:
|
||||
if line.origin and line.origin.__name__ == 'hotel.booking':
|
||||
|
|
|
@ -90,8 +90,14 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_can_no_delete_booking">
|
||||
<field name="text">You can not delete a booking with number!</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_accommodation_not_paid">
|
||||
<field name="text">The accommodation isn't paid!</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_charges_not_paid">
|
||||
<field name="text">There is charges without payment! "%(product)s"</field>
|
||||
<field name="text">There is charges without payment!"</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_cannot_check_in_future">
|
||||
<field name="text">It can not check-in of future dates! "%(product)s"</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
14
operation.py
14
operation.py
|
@ -1,11 +1,10 @@
|
|||
#This file is part of Presik. The COPYRIGHT file at the top level of
|
||||
# This file is part of Presik. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.model import ModelView, ModelSQL, fields, Workflow
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.pool import Pool
|
||||
from trytond.wizard import (
|
||||
Wizard, StateView, StateAction, Button, StateTransition)
|
||||
from trytond.wizard import Wizard, StateView, Button, StateTransition
|
||||
|
||||
|
||||
class Maintenance(Workflow, ModelSQL, ModelView):
|
||||
|
@ -148,7 +147,8 @@ class NightAudit(Wizard):
|
|||
"""
|
||||
This is the wizard for night audit
|
||||
"""
|
||||
start = StateView('hotel.night_audit.start',
|
||||
start = StateView(
|
||||
'hotel.night_audit.start',
|
||||
'hotel.hotel_night_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Ok', 'accept', 'tryton-ok'),
|
||||
|
@ -157,9 +157,7 @@ class NightAudit(Wizard):
|
|||
accept = StateTransition()
|
||||
|
||||
def transition_accept(self):
|
||||
pool = Pool()
|
||||
Folio = pool.get('hotel.folio')
|
||||
FolioCharge = pool.get('hotel.folio.charge')
|
||||
FolioCharge = Pool().get('hotel.folio.charge')
|
||||
pending = FolioCharge.search([
|
||||
('move', '=', None),
|
||||
('product.template.type', '=', 'goods'),
|
||||
|
|
9
party.py
9
party.py
|
@ -1,6 +1,6 @@
|
|||
#This file is part of Hotel module for Tryton. The COPYRIGHT file at
|
||||
#the top level of this repository contains the full copyright notices
|
||||
#and license terms.
|
||||
# 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 trytond.pool import PoolMeta, Pool
|
||||
from trytond.model import fields
|
||||
from trytond.wizard import Wizard, StateView, Button, StateTransition
|
||||
|
@ -23,7 +23,8 @@ class Party(metaclass=PoolMeta):
|
|||
class CreateGuest(Wizard):
|
||||
'Create Party to Guest'
|
||||
__name__ = 'hotel.party.guest'
|
||||
start = StateView('party.party',
|
||||
start = StateView(
|
||||
'party.party',
|
||||
'hotel.view_party_guest', [
|
||||
Button('Exit', 'end', 'tryton-cancel'),
|
||||
Button('Create', 'create_', 'tryton-ok', default=True),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# 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 trytond.model import fields
|
||||
from trytond.pool import PoolMeta
|
||||
from trytond.pyson import Eval
|
||||
|
|
Binary file not shown.
Binary file not shown.
9
room.py
9
room.py
|
@ -1,12 +1,10 @@
|
|||
#This file is part of Presik. The COPYRIGHT file at the top level of
|
||||
# This file is part of Presik. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from datetime import datetime, date, timedelta
|
||||
|
||||
from trytond.model import ModelView, ModelSQL, Workflow, fields
|
||||
from trytond.pyson import Eval
|
||||
from trytond.wizard import (
|
||||
Wizard, StateView, Button, StateTransition, StateReport
|
||||
)
|
||||
from trytond.wizard import Wizard, StateView, Button, StateReport
|
||||
from trytond.pool import Pool
|
||||
from trytond.report import Report
|
||||
from trytond.transaction import Transaction
|
||||
|
@ -303,7 +301,8 @@ class HousekeepingStart(ModelView):
|
|||
class Housekeeping(Wizard):
|
||||
'Housekeeping Service'
|
||||
__name__ = 'hotel.print_housekeeping'
|
||||
start = StateView('hotel.print_housekeeping.start',
|
||||
start = StateView(
|
||||
'hotel.print_housekeeping.start',
|
||||
'hotel.print_housekeeping_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'print_', 'tryton-print', default=True),
|
||||
|
|
3
sale.py
3
sale.py
|
@ -33,7 +33,8 @@ class InvoiceIncomeDailyStart(ModelView):
|
|||
class InvoiceIncomeDaily(Wizard):
|
||||
'Invoice Income Daily'
|
||||
__name__ = 'hotel.invoice_income_daily'
|
||||
start = StateView('hotel.invoice_income_daily.start',
|
||||
start = StateView(
|
||||
'hotel.invoice_income_daily.start',
|
||||
'hotel.invoice_income_daily_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Print', 'print_', 'tryton-ok', default=True),
|
||||
|
|
|
@ -348,7 +348,7 @@ class CreateDailyServices(Wizard):
|
|||
booking = fol.booking
|
||||
if booking.plan == 'no_breakfast':
|
||||
continue
|
||||
if kind == 'lunch' and booking.plan in ['half_american', 'bed_breakfast'] :
|
||||
if kind == 'lunch' and booking.plan in ['half_american', 'bed_breakfast']:
|
||||
continue
|
||||
if kind == 'dinner' and booking.plan == 'bed_breakfast':
|
||||
continue
|
||||
|
|
16
statement.py
16
statement.py
|
@ -1,17 +1,7 @@
|
|||
# This file is part of the hotel module for Tryton.
|
||||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
# 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 trytond.model import fields, ModelView, ModelSQL, Workflow
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Button, StateTransition, StateView, Wizard, StateReport
|
||||
from trytond.pyson import Eval
|
||||
from trytond.i18n import gettext
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.report import Report
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
|
||||
class StatementLine(metaclass=PoolMeta):
|
||||
|
|
4
stock.py
4
stock.py
|
@ -1,8 +1,6 @@
|
|||
# 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 trytond.model import Workflow, ModelView, fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
|
||||
class Move(metaclass=PoolMeta):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[tryton]
|
||||
version=6.0.37
|
||||
version=6.0.38
|
||||
depends:
|
||||
party
|
||||
company
|
||||
|
|
|
@ -67,8 +67,8 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<field name="registration_state"/>
|
||||
<label name="total_amount"/>
|
||||
<field name="total_amount"/>
|
||||
<label name="total_balance"/>
|
||||
<field name="total_balance"/>
|
||||
<label name="pending_total"/>
|
||||
<field name="pending_total"/>
|
||||
<label name="to_invoice"/>
|
||||
<field name="to_invoice"/>
|
||||
<button name="check_in" string="Check In"/>
|
||||
|
|
|
@ -53,11 +53,13 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<field name="notes" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<group col="8" colspan="6" id="state_buttons">
|
||||
<group col="10" colspan="6" id="state_buttons">
|
||||
<label name="registration_state"/>
|
||||
<field name="registration_state"/>
|
||||
<label name="total_amount"/>
|
||||
<field name="total_amount"/>
|
||||
<label name="pending_total"/>
|
||||
<field name="pending_total"/>
|
||||
<group col="6" colspan="4" id="actions_buttons">
|
||||
<label name="to_invoice"/>
|
||||
<field name="to_invoice"/>
|
||||
|
|
|
@ -12,24 +12,22 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<field name="contact" colspan="3"/>
|
||||
<label name="booking_date"/>
|
||||
<field name="booking_date"/>
|
||||
<label name="plan"/>
|
||||
<field name="plan"/>
|
||||
<label name="responsible_payment"/>
|
||||
<field name="responsible_payment"/>
|
||||
<label name="media"/>
|
||||
<field name="media"/>
|
||||
<label name="plan"/>
|
||||
<field name="plan"/>
|
||||
<label name="price_list"/>
|
||||
<field name="price_list" widget="selection"/>
|
||||
<label name="payment_term"/>
|
||||
<field name="payment_term" widget="selection"/>
|
||||
<label name="reason"/>
|
||||
<field name="reason"/>
|
||||
<label name="channel"/>
|
||||
<field name="channel" widget="selection"/>
|
||||
<label name="ota_booking_code"/>
|
||||
<field name="ota_booking_code"/>
|
||||
<label name="channel_paymode"/>
|
||||
<field name="channel_paymode"/>
|
||||
<label name="guarantee"/>
|
||||
<field name="guarantee"/>
|
||||
<label name="price_list"/>
|
||||
<field name="price_list" widget="selection"/>
|
||||
<label name="payment_term"/>
|
||||
<field name="payment_term" widget="selection"/>
|
||||
<group col="5" id="actions" colspan="5">
|
||||
<button name="do_payment" string="Pay / Advance" icon="tryton-currency"/>
|
||||
<button name="select_rooms" string="Rooms" icon="tryton-board"/>
|
||||
|
@ -61,6 +59,8 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<field name="currency"/>
|
||||
<label name="credit_card"/>
|
||||
<field name="credit_card"/>
|
||||
<label name="guarantee"/>
|
||||
<field name="guarantee"/>
|
||||
<group col="6" id="people_num" colspan="4">
|
||||
<label name="guests_num"/>
|
||||
<field name="guests_num"/>
|
||||
|
|
|
@ -12,8 +12,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<field name="city_code"/>
|
||||
<label name="rnt_code"/>
|
||||
<field name="rnt_code"/>
|
||||
<label name="property_code"/>
|
||||
<field name="property_code"/>
|
||||
<label name="logo_link"/>
|
||||
<field name="logo_link" widget="url"/>
|
||||
</page>
|
||||
|
|
|
@ -7,13 +7,16 @@ copyright notices and license terms. -->
|
|||
<field name="statement" widget="selection"/>
|
||||
<label name="kind"/>
|
||||
<field name="kind"/>
|
||||
<label name="user"/>
|
||||
<field name="user" widget="selection"/>
|
||||
<label name="party"/>
|
||||
<field name="party" widget="selection"/>
|
||||
<label name="amount_to_pay"/>
|
||||
<field name="amount_to_pay"/>
|
||||
<label name="party"/>
|
||||
<field name="party"/>
|
||||
<label name="folio"/>
|
||||
<field name="folio" widget="selection"/>
|
||||
<label name="voucher"/>
|
||||
<field name="voucher"/>
|
||||
<field name="user" invisible="1"/>
|
||||
<field name="require_voucher" invisible="1"/>
|
||||
<field name="parties" invisible="1"/>
|
||||
<field name="folios" invisible="1"/>
|
||||
</form>
|
||||
|
|
Loading…
Reference in New Issue