Add invoice folio improvement

This commit is contained in:
oscar alvarez 2022-10-02 19:19:35 -05:00
parent 13f3fbd94e
commit 024ac2c965
6 changed files with 193 additions and 67 deletions

View file

@ -66,6 +66,7 @@ def register():
folio.HotelFolioTax,
folio.FolioStockMove,
folio.OpenMigrationStart,
folio.FolioInvoiceStart,
stock.Move,
sale.InvoiceIncomeDailyStart,
service.Service,
@ -112,6 +113,7 @@ def register():
folio.GuestsList,
folio.StatisticsByMonth,
folio.ReverseCheckout,
folio.FolioInvoice,
service.CreateDailyServices,
room.Housekeeping,
sale.InvoiceIncomeDaily,

View file

@ -597,7 +597,7 @@ class Booking(Workflow, ModelSQL, ModelView):
MoveLine.reconcile(to_reconcile_lines)
@classmethod
def get_grouped_invoices(cls, folios, charges):
def get_grouped_invoices(cls, folios, charges, kind=None):
res = {}
for fo in folios:
if fo.booking.party:
@ -610,6 +610,17 @@ class Booking(Workflow, ModelSQL, ModelView):
bk = fo.booking
agent_id = bk.channel.agent.id if bk.channel else None
folio2Invoice = {
'folios': [fo],
'description': fo.get_room_info(),
'quantity': fo.nights_quantity,
'product': fo.product,
'unit_price': fo.unit_price,
'taxes': fo.taxes,
'origin': str(bk),
'taxes_exception': bk.taxes_exception,
}
if party.id not in res.keys():
# Add room product to sale
reference = ''
@ -633,66 +644,50 @@ class Booking(Workflow, ModelSQL, ModelView):
'price_list': bk.price_list.id if bk.price_list else None,
'add_default_charges': False,
'vouchers': bk.vouchers,
'lines': [{
'folios': [fo],
'description': fo.get_room_info(),
'quantity': fo.nights_quantity,
'product': fo.product,
'unit_price': fo.unit_price,
'taxes': fo.taxes,
'origin': str(bk),
'taxes_exception': bk.taxes_exception,
}]
'lines': []
}
else:
res[party.id]['rooms'] += ' ' + fo.room.name
res[party.id]['lines'].append({
'folios': [fo],
'description': fo.get_room_info(),
'quantity': fo.nights_quantity,
'product': fo.product,
'unit_price': fo.unit_price,
'taxes': fo.taxes,
'origin': str(bk),
'taxes_exception': bk.taxes_exception,
})
for charge in charges:
bk = charge.folio.booking
invoice_party = charge.invoice_to or bk.party
if kind in (None, 'all', 'only_accommodation'):
res[party.id]['lines'].append(folio2Invoice)
invoice_party_id = invoice_party.id
unit_price = bk.currency.round(charge.unit_price)
if invoice_party_id not in res.keys():
res[invoice_party_id] = {
'party': invoice_party,
'currency': bk.currency.id,
'payment_term': bk.payment_term,
'number': bk.number,
'reference': charge.folio.registration_card,
'lines': [],
}
if kind in (None, 'all', 'only_charges'):
for charge in charges:
bk = charge.folio.booking
invoice_party = charge.invoice_to or bk.party
res[invoice_party_id]['lines'].append({
'description': ' | '.join([
str(charge.date_service),
charge.order or '',
charge.description or ''
]),
'quantity': charge.quantity,
'product': charge.product,
'unit_price': unit_price,
'charge': charge,
'origin': str(bk),
'taxes': charge.folio.taxes,
'taxes_exception': bk.taxes_exception,
})
invoice_party_id = invoice_party.id
unit_price = bk.currency.round(charge.unit_price)
if invoice_party_id not in res.keys():
res[invoice_party_id] = {
'party': invoice_party,
'currency': bk.currency.id,
'payment_term': bk.payment_term,
'number': bk.number,
'reference': charge.folio.registration_card,
'lines': [],
}
res[invoice_party_id]['lines'].append({
'description': ' | '.join([
str(charge.date_service),
charge.order or '',
charge.description or ''
]),
'quantity': charge.quantity,
'product': charge.product,
'unit_price': unit_price,
'charge': charge,
'origin': str(bk),
'taxes': charge.folio.taxes,
'taxes_exception': bk.taxes_exception,
})
return res
@classmethod
def _get_invoice_line(cls, invoice, line, record=None):
product = line['product']
print(' line taxes....', line['taxes'])
new_line = {
'type': 'line',
'invoice': invoice.id,
@ -869,7 +864,7 @@ class Booking(Workflow, ModelSQL, ModelView):
pass
@classmethod
def create_invoice(cls, folios):
def create_invoice(cls, folios, kind=None):
pool = Pool()
Configuration = pool.get('hotel.configuration')
Folio = pool.get('hotel.folio')
@ -883,7 +878,7 @@ class Booking(Workflow, ModelSQL, ModelView):
if not _folios and not _charges:
return
invoice_to_create = cls.get_grouped_invoices(_folios, _charges)
invoice_to_create = cls.get_grouped_invoices(_folios, _charges, kind)
for rec in invoice_to_create.values():
invoice = cls._get_new_invoice(rec)
invoice.on_change_invoice_type()

View file

@ -258,11 +258,16 @@ class Folio(ModelSQL, ModelView):
cls.write([record], {'registration_state': 'check_out'})
cls.update_room(record, 'check_out')
# @classmethod
# @ModelView.button
# def bill(cls, records):
# for rec in records:
# rec.create_invoice()
@classmethod
@ModelView.button
@ModelView.button_action('hotel.wizard_folio_invoice')
def bill(cls, records):
for rec in records:
rec.create_invoice()
pass
@classmethod
@ModelView.button_action('hotel.wizard_booking_advance_voucher')
@ -329,10 +334,10 @@ class Folio(ModelSQL, ModelView):
moves.append(charge.move.id)
return moves
def create_invoice(self):
def create_invoice(self, kind=None):
pool = Pool()
Booking = pool.get('hotel.booking')
Booking.create_invoice([self])
Booking.create_invoice([self], kind)
Booking.check_finished([self.booking])
def get_unit_price_w_tax(self, name=None):
@ -1842,3 +1847,32 @@ class HotelFolioTax(ModelSQL):
select=True, required=True)
tax = fields.Many2One('account.tax', 'Tax', ondelete='RESTRICT',
select=True, required=True)
class FolioInvoiceStart(ModelView):
'Folio Invoice Form'
__name__ = 'hotel.folio_invoice.start'
kind = fields.Selection([
('all', 'All'),
('only_charges', 'Only Charges'),
('only_accommodation', 'Only Accommodation'),
], 'Kind', required=True)
class FolioInvoice(Wizard):
'Wizard Folio Invoice'
__name__ = 'hotel.folio_invoice'
start = StateView('hotel.folio_invoice.start',
'hotel.folio_invoice_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Invoice', 'invoice', 'tryton-ok', default=True),
])
invoice = StateTransition()
def transition_invoice(self):
pool = Pool()
Folio = pool.get('hotel.folio')
active_id = Transaction().context.get('active_id', False)
folio = Folio(active_id)
folio.create_invoice(kind=self.start.kind)
return 'end'

View file

@ -198,6 +198,16 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.action.wizard" id="wizard_folio_invoice">
<field name="name">Folio Invoice</field>
<field name="wiz_name">hotel.folio_invoice</field>
</record>
<record model="ir.ui.view" id="folio_invoice_view_form">
<field name="model">hotel.folio_invoice.start</field>
<field name="type">form</field>
<field name="name">folio_invoice_form</field>
</record>
<!-- <record model="ir.ui.view" id="operation_maintenance_view_tree">
<field name="model">hotel.operation.maintenance</field>
<field name="type">tree</field>
@ -269,5 +279,6 @@ this repository contains the full copyright notices and license terms. -->
<menuitem parent="hotel.menu_reporting" id="menu_statistics_by_month"
action="wizard_print_statistics_by_month"/> -->
</data>
</tryton>

View file

@ -52,7 +52,7 @@ msgstr "Icono"
msgctxt "field:dash.app.housekeeping,kind:"
msgid "Kind"
msgstr "Tipo"
msgstr "Clase"
msgctxt "field:dash.app.web_checkin,company:"
msgid "Company"
@ -480,7 +480,7 @@ msgstr "Hora de Check Out"
msgctxt "field:hotel.configuration,children_policies:"
msgid "Children Policies"
msgstr ""
msgstr "Política de Niños"
msgctxt "field:hotel.configuration,cleaning_check_in:"
msgid "Cleaning Check In"
@ -500,7 +500,7 @@ msgstr "Empresa"
msgctxt "field:hotel.configuration,country:"
msgid "Default Country"
msgstr ""
msgstr "Pais por Defecto"
msgctxt "field:hotel.configuration,customer_experience_email:"
msgid "Customer Experience Email"
@ -528,7 +528,7 @@ msgstr "Secuencia de Servicio"
msgctxt "field:hotel.configuration,nationality:"
msgid "Default Nationality"
msgstr ""
msgstr "Nacionalidad por Defecto"
msgctxt "field:hotel.configuration,payment_term:"
msgid "Payment Term"
@ -656,7 +656,7 @@ msgstr "Tercero a Facturar"
msgctxt "field:hotel.folio,party_holder:"
msgid "Party Holder"
msgstr ""
msgstr "Cliente Titular"
msgctxt "field:hotel.folio,product:"
msgid "Product"
@ -918,6 +918,10 @@ msgctxt "field:hotel.folio.guest,visa_number:"
msgid "Visa Number"
msgstr "Número de Visa"
msgctxt "field:hotel.folio_invoice.start,kind:"
msgid "Kind"
msgstr "Clase"
msgctxt "field:hotel.invoice_income_daily.start,company:"
msgid "Company"
msgstr "Empresa"
@ -1516,7 +1520,7 @@ msgstr "Persona o compañia que realiza la reserva."
msgctxt "help:hotel.booking,pax:"
msgid "Number of persons in house."
msgstr ""
msgstr "Número de personas en este folio."
msgctxt "help:hotel.booking,plan:"
msgid "Plans offered by hotel and selected by guest for booking."
@ -1534,7 +1538,7 @@ msgstr "Modo de Cobro"
msgctxt "help:hotel.children_policy,limit_age:"
msgid "In years"
msgstr ""
msgstr "En años"
msgctxt "help:hotel.configuration,age_children_policy:"
msgid "In Days"
@ -1618,7 +1622,7 @@ msgstr "Comision Extra"
msgctxt "model:hotel.children_policy,name:"
msgid "Children Policy"
msgstr ""
msgstr "Política de Niños"
msgctxt "model:hotel.cleaning_days,name:"
msgid "Cleanning Days"
@ -1656,6 +1660,10 @@ msgctxt "model:hotel.folio.guest,name:"
msgid "Folio Guest"
msgstr "Huesped"
msgctxt "model:hotel.folio_invoice.start,name:"
msgid "Folio Invoice Form"
msgstr "Facturar Folio"
msgctxt "model:hotel.invoice_income_daily.start,name:"
msgid "Invoice Income Daily Start"
msgstr "Relacion Diaria de Caja"
@ -1790,7 +1798,7 @@ msgstr "Mantenimiento"
msgctxt "model:ir.action,name:act_hotel_night_audit"
msgid "Night Audit"
msgstr ""
msgstr "Auditoria Nocturna"
msgctxt "model:ir.action,name:act_location_tree"
msgid "Locations"
@ -1896,6 +1904,10 @@ msgctxt "model:ir.action,name:wizard_booking_advance_voucher"
msgid "Comprobante de Anticipo"
msgstr "Comprobante de Anticipo"
msgctxt "model:ir.action,name:wizard_folio_invoice"
msgid "Folio Invoice"
msgstr "Facturar Folio"
msgctxt "model:ir.action,name:wizard_hotel_create_daily_services"
msgid "Create Daily Services"
msgstr "Crear Servicios"
@ -2241,7 +2253,7 @@ msgstr "Ciudad de Migración"
msgctxt "model:ir.ui.menu,name:menu_hotel_night_audit"
msgid "Night Audit"
msgstr ""
msgstr "Auditoria Nocturna"
msgctxt "model:ir.ui.menu,name:menu_hotel_room"
msgid "Room"
@ -6364,6 +6376,11 @@ msgctxt "selection:dash.app.web_checkin,kind:"
msgid "Internal"
msgstr "Interno"
#, fuzzy
msgctxt "selection:hotel.amenities,type:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.amenities,type:"
msgid "Lingerie Room"
msgstr "Lenceria"
@ -6380,6 +6397,11 @@ msgctxt "selection:hotel.booking,channel_paymode:"
msgid "OTA Collect"
msgstr "OTA Collect"
#, fuzzy
msgctxt "selection:hotel.booking,guarantee:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.booking,guarantee:"
msgid "Credit Card"
msgstr "Tarjeta de Crédito"
@ -6404,6 +6426,11 @@ msgctxt "selection:hotel.booking,invoice_method:"
msgid "By Main Guest"
msgstr "Por Huesped Principal"
#, fuzzy
msgctxt "selection:hotel.booking,media:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.booking,media:"
msgid "Channel Manager"
msgstr "Gestor de Canales"
@ -6512,6 +6539,11 @@ msgctxt "selection:hotel.booking,reason:"
msgid "Weddings"
msgstr "Bodas"
#, fuzzy
msgctxt "selection:hotel.booking,registration_state:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.booking,registration_state:"
msgid "Check In"
msgstr "Check In"
@ -6528,6 +6560,11 @@ msgctxt "selection:hotel.booking,registration_state:"
msgid "Pending"
msgstr "Pendiente"
#, fuzzy
msgctxt "selection:hotel.booking,satisfaction:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.booking,satisfaction:"
msgid "Bad"
msgstr "Mala"
@ -6568,6 +6605,11 @@ msgctxt "selection:hotel.booking,state:"
msgid "Offer"
msgstr "Oferta"
#, fuzzy
msgctxt "selection:hotel.booking,type_complementary:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.booking,type_complementary:"
msgid "Courtesy"
msgstr "Cortesia"
@ -6604,6 +6646,11 @@ msgctxt "selection:hotel.channel,invoice_to:"
msgid "Customer"
msgstr "Cliente / Titular"
#, fuzzy
msgctxt "selection:hotel.channel,payment_method:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.channel,payment_method:"
msgid "At Destination"
msgstr "En Destino"
@ -6648,6 +6695,11 @@ msgctxt "selection:hotel.cleaning_days,weekday:"
msgid "Wednesday"
msgstr "Miércoles"
#, fuzzy
msgctxt "selection:hotel.configuration,full_clean_time:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:hotel.configuration,full_clean_time:"
msgid "By Time"
msgstr "Por Tiempo"
@ -6784,6 +6836,18 @@ msgctxt "selection:hotel.folio.guest,type_guest:"
msgid "Child"
msgstr "Niño/a"
msgctxt "selection:hotel.folio_invoice.start,kind:"
msgid "All"
msgstr "Todo"
msgctxt "selection:hotel.folio_invoice.start,kind:"
msgid "Only Accommodation"
msgstr "Solo Alojamiento"
msgctxt "selection:hotel.folio_invoice.start,kind:"
msgid "Only Charges"
msgstr "Solo Cargos"
msgctxt "selection:hotel.maintenance,criticality:"
msgid "Important"
msgstr "Importante"
@ -7016,6 +7080,11 @@ msgctxt "selection:party.party,type_document:"
msgid "PEP"
msgstr ""
#, fuzzy
msgctxt "selection:product.template,kind:"
msgid ""
msgstr "Punto de Orden"
msgctxt "selection:product.template,kind:"
msgid "Accommodation"
msgstr "Acomodación"
@ -7268,6 +7337,14 @@ msgctxt "wizard_button:hotel.daily_services,start,end:"
msgid "Cancel"
msgstr "Cancelar"
msgctxt "wizard_button:hotel.folio_invoice,start,end:"
msgid "Cancel"
msgstr "Cancelar"
msgctxt "wizard_button:hotel.folio_invoice,start,invoice:"
msgid "Invoice"
msgstr "Facturar"
msgctxt "wizard_button:hotel.invoice_income_daily,start,end:"
msgid "Cancel"
msgstr "Cancelar"

View file

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="kind"/>
<field name="kind"/>
</form>