This commit is contained in:
oscar alvarez 2022-03-20 08:46:25 -05:00
parent 1b809c5739
commit ef1c4a0291
8 changed files with 95 additions and 85 deletions

View File

@ -127,7 +127,7 @@ class Booking(Workflow, ModelSQL, ModelView):
], depends=['party']) ], depends=['party'])
vip = fields.Boolean('V.I.P. Customer', states=STATES) vip = fields.Boolean('V.I.P. Customer', states=STATES)
ota_booking_code = fields.Char('OTA Code', select=True, ota_booking_code = fields.Char('OTA Code', select=True,
states={'invisible': ~Eval('media') == 'ota'} states={'invisible': Eval('media') != 'ota'}
) )
vehicles_num = fields.Integer('Vehicles Number', states=STATES, vehicles_num = fields.Integer('Vehicles Number', states=STATES,
help="Number of vehicles that bring with guests.") help="Number of vehicles that bring with guests.")
@ -141,10 +141,14 @@ class Booking(Workflow, ModelSQL, ModelView):
breakfast_included = fields.Boolean('Breakfast Included') breakfast_included = fields.Boolean('Breakfast Included')
channel_commission = fields.Function(fields.Numeric('Channel Commission', channel_commission = fields.Function(fields.Numeric('Channel Commission',
digits=(16, 2), depends=['lines']), 'get_channel_commission') digits=(16, 2), depends=['lines']), 'get_channel_commission')
channel_invoice = fields.Many2One('account.invoice', 'Invoice', channel_invoice = fields.Many2One('account.invoice', 'Channel Invoice',
states={'invisible': ~Eval('channel')}) states={
'invisible': ~Eval('channel'),
'readonly': True
})
channel_paymode = fields.Selection(PAYMENT_METHOD_CHANNEL, channel_paymode = fields.Selection(PAYMENT_METHOD_CHANNEL,
'Channel Paymode', states={'invisible': ~Eval('channel')}, 'Channel Paymode', states={'invisible': ~Eval('channel')},
depends=['channel']
) )
@classmethod @classmethod
@ -249,20 +253,19 @@ class Booking(Workflow, ModelSQL, ModelView):
@fields.depends('party', 'price_list', 'lines') @fields.depends('party', 'price_list', 'lines')
def on_change_party(self): def on_change_party(self):
if self.party: if self.party:
print(' aqui ...')
if self.party.sale_price_list: if self.party.sale_price_list:
self.price_list = self.party.sale_price_list.id self.price_list = self.party.sale_price_list.id
self.price_list.rec_name = self.party.sale_price_list.rec_name self.price_list.rec_name = self.party.sale_price_list.rec_name
for folio in self.lines: for folio in self.lines:
print(' aqui ...2') if self.party.type_document != '31':
if not folio.main_guest and self.party.type_document != '31':
print(' aqui ...3')
folio.main_guest = self.party.id folio.main_guest = self.party.id
@fields.depends('channel') @fields.depends('channel')
def on_change_channel(self): def on_change_channel(self):
if self.channel and self.channel.price_list: if self.channel:
self.price_list = self.channel.price_list self.channel_paymode = self.channel.payment_method
if self.channel.price_list:
self.price_list = self.channel.price_list
@classmethod @classmethod
@ModelView.button_action('hotel.wizard_select_rooms') @ModelView.button_action('hotel.wizard_select_rooms')
@ -418,8 +421,9 @@ class Booking(Workflow, ModelSQL, ModelView):
if not party: if not party:
raise UserError(gettext('hotel.msg_customer_is_required')) raise UserError(gettext('hotel.msg_customer_is_required'))
bk = fo.booking bk = fo.booking
# FIXME: Add agent print(' fo.booking ....', fo.booking)
agent_id = bk.channel.agent.id if bk.channel else None agent_id = bk.channel.agent.id if bk.channel else None
if party.id not in res.keys(): if party.id not in res.keys():
# Add room product to sale # Add room product to sale
@ -466,16 +470,21 @@ class Booking(Workflow, ModelSQL, ModelView):
}) })
for charge in charges: for charge in charges:
bk = charge.folio.booking
invoice_party_id = charge.invoice_to.id invoice_party_id = charge.invoice_to.id
unit_price = bk.currency.round(charge.unit_price) unit_price = bk.currency.round(charge.unit_price)
if invoice_party_id != party.id: if invoice_party_id not in res.keys():
if invoice_party_id not in res.keys(): res[invoice_party_id] = {
res[invoice_party_id] = { 'party': charge.invoice_to,
'party': charge.invoice_to, 'currency': bk.currency.id,
'currency': bk.currency.id, 'payment_term': None,
'payment_term': None, 'number': bk.number,
'lines': [], 'reference': charge.folio.registration_card,
} 'lines': [],
}
# if invoice_party_id != bk.party.id:
# else:
res[invoice_party_id]['lines'].append({ res[invoice_party_id]['lines'].append({
'description': ' | '.join([ 'description': ' | '.join([
str(charge.date_service), str(charge.date_service),
@ -528,6 +537,7 @@ class Booking(Workflow, ModelSQL, ModelView):
for charge in folio.charges: for charge in folio.charges:
if not charge.invoice_line and charge.to_invoice: if not charge.invoice_line and charge.to_invoice:
_charges.append(charge) _charges.append(charge)
print('_charges.... ', _charges)
return _folios, _charges return _folios, _charges
@classmethod @classmethod
@ -577,6 +587,7 @@ class Booking(Workflow, ModelSQL, ModelView):
pool = Pool() pool = Pool()
Invoice = pool.get('account.invoice') Invoice = pool.get('account.invoice')
InvoiceLine = pool.get('account.invoice.line') InvoiceLine = pool.get('account.invoice.line')
Foilo = pool.get('hotel.folio')
if not bk.channel: if not bk.channel:
return return
data = { data = {
@ -584,6 +595,7 @@ class Booking(Workflow, ModelSQL, ModelView):
'reference': bk.number, 'reference': bk.number,
'description': f"{bk.ota_booking_code} | {bk.party.name}", 'description': f"{bk.ota_booking_code} | {bk.party.name}",
'payment_term': bk.payment_term, 'payment_term': bk.payment_term,
'number': bk.number,
} }
invoice = cls._get_new_invoice(data) invoice = cls._get_new_invoice(data)
invoice.on_change_invoice_type() invoice.on_change_invoice_type()
@ -690,9 +702,7 @@ class Booking(Workflow, ModelSQL, ModelView):
if data.get('agent'): if data.get('agent'):
agent = Agent(data['agent']) agent = Agent(data['agent'])
journal, = Journal.search([ journal, = Journal.search([('type', '=', 'revenue')], limit=1)
('type', '=', 'revenue'),
], limit=1)
address = party.address_get(type='invoice') address = party.address_get(type='invoice')
payment_term = data.get('payment_term', None) payment_term = data.get('payment_term', None)

View File

@ -47,8 +47,8 @@ class SaleChannel(ModelSQL, ModelView):
currency = fields.Many2One('currency.currency', 'Currency', currency = fields.Many2One('currency.currency', 'Currency',
required=True) required=True)
price_list = fields.Many2One('product.price_list', 'Price List') price_list = fields.Many2One('product.price_list', 'Price List')
payment_method = fields.Selection(PAYMENT_METHOD_CHANNEL, 'Payment Method', payment_method = fields.Selection(PAYMENT_METHOD_CHANNEL,
required=True) 'Payment Method')
collection_mode = fields.Selection([ collection_mode = fields.Selection([
('', ''), ('', ''),
('anticipated', 'Anticipated'), ('anticipated', 'Anticipated'),
@ -57,16 +57,14 @@ class SaleChannel(ModelSQL, ModelView):
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
# alter table hotel_channel drop column commission;
# alter table hotel_channel drop column payment_method;
super(SaleChannel, cls).__setup__() super(SaleChannel, cls).__setup__()
@staticmethod @staticmethod
def default_company(): def default_company():
return Transaction().context.get('company') return Transaction().context.get('company')
@staticmethod
def default_payment_method():
return 'ota_collect'
@staticmethod @staticmethod
def default_currency(): def default_currency():
Company = Pool().get('company.company') Company = Pool().get('company.company')

View File

@ -93,7 +93,6 @@ INVOICE_STATES = [
] ]
PAYMENT_METHOD_CHANNEL = [ PAYMENT_METHOD_CHANNEL = [
('', ''),
('at_destination', 'At Destination'), ('at_destination', 'At Destination'),
('ota_collect', 'OTA Collect'), ('ota_collect', 'OTA Collect'),
] ]

View File

@ -91,18 +91,18 @@ class Folio(ModelSQL, ModelView):
contact = fields.Char('Contact', states=STATES_CHECKIN) contact = fields.Char('Contact', states=STATES_CHECKIN)
num_children = fields.Function(fields.Integer('No. Children'), num_children = fields.Function(fields.Integer('No. Children'),
'get_num_children') 'get_num_children')
nights_quantity = fields.Function(fields.Integer('Nights'), nights_quantity = fields.Integer('Nights', states={'readonly': True},
'on_change_with_nights_quantity') depends=['arrival_date', 'departure_date'])
host_quantity = fields.Integer('Host', states=STATES_CHECKIN) host_quantity = fields.Integer('Host', states=STATES_CHECKIN)
unit_digits = fields.Function(fields.Integer('Unit Digits'), 'get_unit_digits') unit_digits = fields.Function(fields.Integer('Unit Digits'), 'get_unit_digits')
notes = fields.Text('Notes') notes = fields.Text('Notes')
total_amount = fields.Function(fields.Numeric('Total Amount', total_amount = fields.Function(fields.Numeric('Total Amount',
digits=(16, 2)), 'get_totals') digits=(16, 2)), 'get_totals')
total_balance = fields.Function(fields.Numeric('Total Balance', total_balance = fields.Function(fields.Numeric('Total Balance',
digits=(16, 2), depends=['paid_by_channel']), 'get_totals') digits=(16, 2)), 'get_totals')
commission_amount = fields.Numeric('Commission Amount', digits=(16, 2), commission_amount = fields.Numeric('Commission Amount', digits=(16, 2),
depends=['product', 'departure_date', 'arrival_date'] depends=['nights_quantity', 'unit_price'], states={'readonly': True}
) )
guests = fields.One2Many('hotel.folio.guest', 'folio', 'Guests', guests = fields.One2Many('hotel.folio.guest', 'folio', 'Guests',
states={'readonly': Eval('registration_state').in_(['check_out'])}) states={'readonly': Eval('registration_state').in_(['check_out'])})
nationality = fields.Many2One('party.nationality', 'Nationality', nationality = fields.Many2One('party.nationality', 'Nationality',
@ -137,16 +137,16 @@ class Folio(ModelSQL, ModelView):
breakfast_included = fields.Boolean('Breakfast Included', states={ breakfast_included = fields.Boolean('Breakfast Included', states={
'readonly': Eval('registration_state') != 'check_in', 'readonly': Eval('registration_state') != 'check_in',
}) })
paid_by_channel = fields.Boolean('Paid By Channel') # paid_by_channel = fields.Boolean('Paid By Channel')
room_amount = fields.Function(fields.Numeric('Room Amount', room_amount = fields.Function(fields.Numeric('Room Amount',
digits=(16, 2)), 'get_change_with_room_amount') digits=(16, 2), depends=['nights_quantity', 'unit_price']
), 'on_change_with_room_amount')
stock_moves = fields.Many2Many('hotel.folio-stock.move', 'folio', stock_moves = fields.Many2Many('hotel.folio-stock.move', 'folio',
'move', 'Stock Moves', states={'readonly': True}) 'move', 'Stock Moves', states={'readonly': True})
# channel_invoice = fields.Function(fields.Many2One('account.invoice',
# 'Invoice', depends=['booking']), 'get_channel_invoice')
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
# UPDATE hotel_folio SET nights_quantity=(departure_date-arrival_date)
super(Folio, cls).__setup__() super(Folio, cls).__setup__()
cls._check_modify_exclude = [ cls._check_modify_exclude = [
'nationality', 'origin_country', 'target_country', 'nationality', 'origin_country', 'target_country',
@ -193,6 +193,14 @@ class Folio(ModelSQL, ModelView):
] ]
return domain return domain
@classmethod
def create(cls, values):
folios = super(Folio, cls).create(values)
for folio in folios:
folio.update_nights(folio.arrival_date, folio.departure_date)
folio.update_commission()
folio.save()
@classmethod @classmethod
@ModelView.button @ModelView.button
def check_in(cls, records): def check_in(cls, records):
@ -282,16 +290,11 @@ class Folio(ModelSQL, ModelView):
res = value['base'] + value['amount'] res = value['base'] + value['amount']
return res return res
@fields.depends('unit_price_w_tax', 'nights_quantity') @fields.depends('unit_price', 'nights_quantity', 'arrival_date', 'departure_date')
def get_change_with_room_amount(self, name=None): def on_change_with_room_amount(self, name=None):
res = 0 res = 0
Date = Pool().get('ir.date') if self.unit_price and self.nights_quantity:
if self.unit_price_w_tax and self.nights_quantity: res = self.unit_price * 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, Folio.total_amount.digits[1]) return round(res, Folio.total_amount.digits[1])
@staticmethod @staticmethod
@ -325,11 +328,6 @@ class Folio(ModelSQL, ModelView):
if self.invoice_line and self.invoice_line.invoice: if self.invoice_line and self.invoice_line.invoice:
return self.invoice_line.invoice.id return self.invoice_line.invoice.id
# @fields.depends('accommodation', 'product')
# def on_change_accommodation(self):
# if not self.accommodation:
# self.product = None
def get_room_info(self): def get_room_info(self):
description = ' \n'.join([ description = ' \n'.join([
self.product.rec_name, self.product.rec_name,
@ -340,7 +338,8 @@ class Folio(ModelSQL, ModelView):
]) ])
return description return description
@fields.depends('product', 'unit_price', 'uom', 'booking', 'nights_quantity') @fields.depends('product', 'unit_price', 'uom', 'booking',
'nights_quantity', 'commission_amount')
def on_change_product(self): def on_change_product(self):
Product = Pool().get('product.product') Product = Pool().get('product.product')
if self.product and self.booking: if self.product and self.booking:
@ -353,13 +352,26 @@ class Folio(ModelSQL, ModelView):
self.unit_price = self.booking.currency.round(self.unit_price) self.unit_price = self.booking.currency.round(self.unit_price)
else: else:
self.unit_price = self.product.list_price self.unit_price = self.product.list_price
self.update_commission()
@fields.depends('arrival_date', 'departure_date') def update_commission(self):
if self.nights_quantity and self.unit_price and self.booking:
if not self.booking.channel:
return
amount = self.on_change_with_room_amount()
self.commission_amount = self.booking.channel.compute(amount)
@fields.depends('arrival_date', 'departure_date', 'unit_price', 'booking')
def on_change_arrival_date(self): def on_change_arrival_date(self):
if not self.arrival_date or ( if self.arrival_date and self.departure_date:
self.departure_date and self.departure_date > self.arrival_date): self.update_nights(self.arrival_date, self.departure_date)
return self.update_commission()
self.departure_date = self.arrival_date + timedelta(days=1)
@fields.depends('arrival_date', 'departure_date', 'unit_price', 'booking')
def on_change_departure_date(self):
if self.arrival_date and self.departure_date:
self.update_nights(self.arrival_date, self.departure_date)
self.update_commission()
def check_method(self): def check_method(self):
""" """
@ -433,17 +445,8 @@ class Folio(ModelSQL, ModelView):
rooms_available_ids = set(rooms_ids) - set(rooms_not_available_ids) rooms_available_ids = set(rooms_ids) - set(rooms_not_available_ids)
return list(rooms_available_ids) return list(rooms_available_ids)
@fields.depends('arrival_date', 'departure_date') def update_nights(self, arrival_date, departure_date):
def on_change_with_nights_quantity(self, name=None): self.nights_quantity = (departure_date - arrival_date).days
"""
Compute nights between start and end
return a integer the mean days of occupancy.
"""
nights = 0
if not self.arrival_date or not self.departure_date:
return nights
nights = (self.departure_date - self.arrival_date).days
return nights
def get_totals(self, name): def get_totals(self, name):
""" """
@ -452,7 +455,7 @@ class Folio(ModelSQL, ModelView):
instead of flat price. Fee is linked to channel management. instead of flat price. Fee is linked to channel management.
""" """
res = [] res = []
if name == 'total_amount' or not self.paid_by_channel: if name == 'total_amount' or not self.invoice_line:
if self.nights_quantity and self.unit_price_w_tax: if self.nights_quantity and self.unit_price_w_tax:
res = [self.nights_quantity * self.unit_price_w_tax] res = [self.nights_quantity * self.unit_price_w_tax]
for charge in self.charges: for charge in self.charges:
@ -460,18 +463,16 @@ class Folio(ModelSQL, ModelView):
res = round(sum(res), Folio.total_amount.digits[1]) res = round(sum(res), Folio.total_amount.digits[1])
return res return res
@fields.depends('arrival_date', 'departure_date', 'product') @fields.depends('nights_quantity', 'unit_price', 'booking')
def on_change_with_commission_amount(self): def on_change_with_commission_amount(self):
""" """
Calculation of commission amount for channel based on booking Calculation of commission amount for channel based on booking
""" """
print(' - - - - >', self.arrival_date, self.product, self.departure_date)
res = Decimal(0) res = Decimal(0)
if all([self.arrival_date, self.product, self.departure_date]): if self.nights_quantity and self.unit_price and self.booking.channel:
if self.booking.channel: amount = self.on_change_with_room_amount()
print(self.room_amount) res = self.booking.channel.compute(amount)
res = self.booking.channel.compute(self.room_amount) return res
return res
class FolioGuest(ModelSQL, ModelView): class FolioGuest(ModelSQL, ModelView):

View File

@ -30,7 +30,9 @@ class Invoice(metaclass=PoolMeta):
booking = line.origin booking = line.origin
if not booking.vouchers: if not booking.vouchers:
continue continue
vouchers.extend(booking.vouchers) for voucher in booking.vouchers:
if invoice.party.id == voucher.party.id:
vouchers.append(voucher)
if vouchers: if vouchers:
invoice.create_move_advance(set(vouchers)) invoice.create_move_advance(set(vouchers))

View File

@ -26,8 +26,8 @@ this repository contains the full copyright notices and license terms. -->
<field name="origin_country"/> <field name="origin_country"/>
<label name="target_country"/> <label name="target_country"/>
<field name="target_country"/> <field name="target_country"/>
<!-- <label name="total_commission"/> <label name="room_amount"/>
<field name="total_commission"/> --> <field name="room_amount"/>
<notebook colspan="6"> <notebook colspan="6">
<page string="Charges" id="hotel_charges"> <page string="Charges" id="hotel_charges">
<field name="charges" colspan="4"/> <field name="charges" colspan="4"/>

View File

@ -76,12 +76,12 @@ this repository contains the full copyright notices and license terms. -->
<field name="channel_commission"/> <field name="channel_commission"/>
</page> </page>
</notebook> </notebook>
<group col="4" colspan="4" id="buttons"> <group col="5" colspan="4" id="buttons">
<label name="taxes_exception"/> <label name="taxes_exception"/>
<field name="taxes_exception"/> <field name="taxes_exception"/>
<button name="bill" string="Bill"/>
<label name="state"/> <label name="state"/>
<field name="state"/> <field name="state"/>
<button name="bill" string="Bill"/>
<button name="cancel" string="Cancel" icon="tryton-cancel"/> <button name="cancel" string="Cancel" icon="tryton-cancel"/>
<button name="not_show" string="Not Show" icon="tryton-cancel"/> <button name="not_show" string="Not Show" icon="tryton-cancel"/>
<button name="offer" string="Offer" icon="tryton-clear"/> <button name="offer" string="Offer" icon="tryton-clear"/>
@ -95,16 +95,16 @@ this repository contains the full copyright notices and license terms. -->
<label name="total_amount"/> <label name="total_amount"/>
<field name="total_amount"/> <field name="total_amount"/>
</group> </group>
<group col="4" colspan="1" xfill="1" id="advances"> <group col="2" colspan="1" xfill="1" id="advances">
<label name="total_advance"/> <label name="total_advance"/>
<field name="total_advance"/> <field name="total_advance"/>
<label name="pending_to_pay"/> <label name="pending_to_pay"/>
<field name="pending_to_pay"/> <field name="pending_to_pay"/>
</group> </group>
<group col="5" colspan="1" xfill="1" id="ota_management"> <group col="5" colspan="4" xfill="1" id="ota_management">
<button name="bill_to_channel" string="Bill to Channel"/>
<label name="channel_paymode"/> <label name="channel_paymode"/>
<field name="channel_paymode"/> <field name="channel_paymode"/>
<button name="bill_to_channel" string="Bill to Channel"/>
<label name="channel_invoice"/> <label name="channel_invoice"/>
<field name="channel_invoice"/> <field name="channel_invoice"/>
</group> </group>

View File

@ -19,7 +19,7 @@ this repository contains the full copyright notices and license terms. -->
<label name="credit_account"/> <label name="credit_account"/>
<field name="credit_account"/> <field name="credit_account"/>
<label name="payment_method"/> <label name="payment_method"/>
<field name="payment_method" widget="multiselection"/> <field name="payment_method"/>
<label name="collection_mode"/> <label name="collection_mode"/>
<field name="collection_mode"/> <field name="collection_mode"/>
<label name="price_list"/> <label name="price_list"/>