Compare commits

...

3 Commits

Author SHA1 Message Date
oscar alvarez a7000eb130 Fix 2023-11-02 22:16:41 -05:00
oscar alvarez ee661d56a3 Add season to price list 2023-11-02 18:13:29 -05:00
oscar alvarez 05a7d332f9 Fix add reconcile booking from invoice 2023-11-02 17:49:55 -05:00
9 changed files with 158 additions and 35 deletions

View File

@ -28,8 +28,7 @@ Al igual que en las OTAS en Tryton Hotel las tarifas son una combinación de pre
• Max antelación • Max antelación
• No OTA • No OTA
Debe permitir realizar los cambios precios y restricciones por día o periodo o temporada en cada Debe permitir realizar los cambios precios y restricciones por día o periodo o temporada en cada tarifa existente.
tarifa existente.
Una tarifa (creada por precios y restricciones) está asociada a condiciones y políticas, como: Una tarifa (creada por precios y restricciones) está asociada a condiciones y políticas, como:

View File

@ -163,5 +163,6 @@ def register():
sale.SaleTransfer, sale.SaleTransfer,
party.CreateGuest, party.CreateGuest,
operation.NightAuditWizard, operation.NightAuditWizard,
invoice.InvoiceReconcileBooking,
siat.SiatSyncWizard, siat.SiatSyncWizard,
module='hotel', type_='wizard') module='hotel', type_='wizard')

View File

@ -364,6 +364,7 @@ class Folio(ModelSQL, ModelView):
'main_guest.address', 'main_guest.address',
'main_guest.addresses', 'main_guest.addresses',
'room.code', 'room.code',
'room.name',
'product.template.name', 'product.template.name',
'registration_state', 'registration_state',
'arrival_date', 'arrival_date',

View File

@ -4,6 +4,8 @@ from datetime import date
from trytond.pool import PoolMeta, Pool from trytond.pool import PoolMeta, Pool
from trytond.model import fields from trytond.model import fields
from trytond.wizard import StateTransition, Wizard
from trytond.transaction import Transaction
class Invoice(metaclass=PoolMeta): class Invoice(metaclass=PoolMeta):
@ -100,14 +102,6 @@ class Invoice(metaclass=PoolMeta):
if invoice.amount_to_pay == 0 and to_reconcile: if invoice.amount_to_pay == 0 and to_reconcile:
MoveLine.reconcile(to_reconcile) MoveLine.reconcile(to_reconcile)
@classmethod
def do_move_writeoff_advance(cls, invoices):
# Asiento de cancelacion de los anticipos en la reserva
# Para abono de pago en factura
Config = Pool().get('hotel.configuration')
config = Config.get_configuration()
pass
@classmethod @classmethod
def _post(cls, invoices): def _post(cls, invoices):
for invoice in invoices: for invoice in invoices:
@ -131,30 +125,106 @@ class Invoice(metaclass=PoolMeta):
invoice.auto_reconcile() invoice.auto_reconcile()
@classmethod @classmethod
def _add_payment(cls, inv, record, lines_ids): def set_booking_payments(cls, invoice):
Config = Pool().get('hotel.configuration')
config = Config.get_configuration()
acc_advance = config.advance_account
booking = None
payments = []
lines_paid = []
for line in invoice.lines:
if line.origin and line.origin.__name__ == 'hotel.folio':
folio = line.origin
booking = folio.booking
payments.append(folio.payments)
if booking:
payments.append(booking.payments)
lines_paid = []
lines_advance = []
for rec in payments:
lines_paid.extend(cls.set_payments_lines(invoice, rec))
lines_advance.extend(
cls.set_payments_lines(invoice, rec, acc_advance))
if lines_paid or lines_advance:
if acc_advance and lines_advance:
lines_paid.extend(
cls.do_move_writeoff_advance(
lines_advance, acc_advance, invoice))
if lines_paid:
lines_paid = [li.id for li in lines_paid]
cls.write([invoice], {'payment_lines': [('add', lines_paid)]})
@classmethod
def set_payments_lines(cls, inv, payments, account=None):
lines_paid = []
balance = 0 balance = 0
for as_line in record.payments: account_id = account.id if account else inv.account.id
for as_line in payments:
if as_line.move and as_line.party == inv.party: if as_line.move and as_line.party == inv.party:
balance += as_line.amount balance += as_line.amount
if as_line.amount > inv.total_amount or balance > inv.total_amount: if as_line.amount > inv.total_amount or balance > inv.total_amount:
break break
for mline in as_line.move.lines: for mline in as_line.move.lines:
if mline.account.id == inv.account.id and not mline.reconciliation: if mline.account.id == account_id and not mline.reconciliation:
lines_ids.append(mline.id) lines_paid.append(mline)
return lines_paid
@classmethod @classmethod
def set_booking_payments(cls, invoice): def do_move_writeoff_advance(cls, lines, account, inv):
lines_ids = [] # Asiento de cancelacion de los anticipos en la reserva
booking = None # conciliacion de los anticipos y abono de los pagos en factura
for line in invoice.lines: pool = Pool()
if line.origin and line.origin.__name__ == 'hotel.folio': Move = pool.get('account.move')
folio = line.origin MoveLine = pool.get('account.move.line')
booking = folio.booking Period = pool.get('account.period')
cls._add_payment(invoice, folio, lines_ids) Journal = pool.get('account.journal')
if booking: Reconciliation = pool.get('account.move.reconciliation')
cls._add_payment(invoice, booking, lines_ids) journal, = Journal.search_read([
if lines_ids: ('type', '=', 'write-off')
cls.write([invoice], {'payment_lines': [('add', lines_ids)]}) ], limit=1)
period_id = Period.find(inv.company.id, date=inv.invoice_date)
move, = Move.create([{
'journal': journal['id'],
'period': period_id,
'date': inv.invoice_date,
# 'origin': str(self),
'state': 'draft',
'description': inv.description,
}])
amount = 0
to_debit = []
advance_lines = []
for line in lines:
advance_lines.append(line.id)
amount += line.credit
to_debit.append({
'description': inv.reference,
'party': inv.party.id,
'account': account.id,
'debit': line.credit,
'credit': 0,
'move': move.id,
})
to_credit = [{
'description': inv.description,
'party': inv.party.id,
'account': inv.account.id,
'debit': 0,
'credit': amount,
'move': move.id,
}]
debit_lines = MoveLine.create(to_debit)
lines_ids = MoveLine.create(to_credit)
Reconciliation.create([{
'lines': [('add', debit_lines + advance_lines)],
'date': date.today(),
}])
Move.post([move])
return lines_ids
@classmethod @classmethod
def set_advances_from_origin(cls, invoice): def set_advances_from_origin(cls, invoice):
@ -170,6 +240,13 @@ class Invoice(metaclass=PoolMeta):
if vouchers: if vouchers:
invoice.create_move_advance(set(vouchers)) invoice.create_move_advance(set(vouchers))
@classmethod
def concile_booking_invoice(cls, record):
if record.state != 'posted':
return
cls.set_booking_payments(record)
record.auto_reconcile()
class InvoiceLine(metaclass=PoolMeta): class InvoiceLine(metaclass=PoolMeta):
__name__ = 'account.invoice.line' __name__ = 'account.invoice.line'
@ -189,3 +266,22 @@ class InvoiceLine(metaclass=PoolMeta):
for line in lines: for line in lines:
line.account = config.recognise_account.id line.account = config.recognise_account.id
return lines return lines
class InvoiceReconcileBooking(Wizard):
'Invoice Reconcile Booking'
__name__ = 'hotel.invoice_reconcile_booking'
start_state = 'reconcile_'
reconcile_ = StateTransition()
def transition_reconcile_(self):
Invoice = Pool().get('account.invoice')
invoice_ids = Transaction().context['active_ids']
if not invoice_ids:
return 'end'
invoices = Invoice.browse(invoice_ids)
for inv in invoices:
Invoice.concile_booking_invoice(inv)
return 'end'

16
invoice.xml Normal file
View File

@ -0,0 +1,16 @@
<?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. -->
<tryton>
<data>
<record model="ir.action.wizard" id="act_invoice_reconcile_booking">
<field name="name">Reconcile with Booking</field>
<field name="wiz_name">hotel.invoice_reconcile_booking</field>
</record>
<record model="ir.action.keyword" id="act_invoice_reconcile_draft_keyword">
<field name="keyword">form_action</field>
<field name="model">account.invoice,-1</field>
<field name="action" ref="act_invoice_reconcile_booking"/>
</record>
</data>
</tryton>

View File

@ -24,3 +24,8 @@ class Template(metaclass=PoolMeta):
class PriceList(metaclass=PoolMeta): class PriceList(metaclass=PoolMeta):
__name__ = 'product.price_list' __name__ = 'product.price_list'
breakfast_included = fields.Boolean('Breakfast Included') breakfast_included = fields.Boolean('Breakfast Included')
season = fields.Selection([
('high', 'High'),
('low', 'Low'),
('middle', 'Middle'),
], 'Season')

View File

@ -1,5 +1,5 @@
[tryton] [tryton]
version=6.0.119 version=6.0.120
depends: depends:
party party
company company
@ -43,4 +43,5 @@ xml:
analytic.xml analytic.xml
rate_plan.xml rate_plan.xml
housekeeping.xml housekeeping.xml
invoice.xml
siat.xml siat.xml

View File

@ -28,8 +28,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="storage_by_default"/> <field name="storage_by_default"/>
<label name="payment_term"/> <label name="payment_term"/>
<field name="payment_term"/> <field name="payment_term"/>
<label name="offset_journal"/>
<field name="offset_journal"/>
<label name="booking_email"/> <label name="booking_email"/>
<field name="booking_email"/> <field name="booking_email"/>
<label name="check_in_email"/> <label name="check_in_email"/>
@ -38,16 +36,20 @@ this repository contains the full copyright notices and license terms. -->
<field name="payments_email"/> <field name="payments_email"/>
<label name="customer_experience_email"/> <label name="customer_experience_email"/>
<field name="customer_experience_email"/> <field name="customer_experience_email"/>
<label name="accounting_revenue"/>
<field name="accounting_revenue"/>
<label name="recognise_account"/>
<field name="recognise_account"/>
<label name="advance_account"/>
<field name="advance_account"/>
<label name="space_booking"/> <label name="space_booking"/>
<field name="space_booking"/> <field name="space_booking"/>
<label name="charge_sequence"/> <label name="charge_sequence"/>
<field name="charge_sequence"/> <field name="charge_sequence"/>
<label name="offset_journal"/>
<field name="offset_journal"/>
<group col="6" string="Accounting" id="account" colspan="4">
<label name="accounting_revenue"/>
<field name="accounting_revenue"/>
<label name="recognise_account"/>
<field name="recognise_account"/>
<label name="advance_account"/>
<field name="advance_account"/>
</group>
<field name="default_charges" colspan="2"/> <field name="default_charges" colspan="2"/>
<field name="children_policies" colspan="2"/> <field name="children_policies" colspan="2"/>
<label name="token_siat"/> <label name="token_siat"/>

View File

@ -5,5 +5,7 @@ this repository contains the full copyright notices and license terms. -->
<xpath expr="/form/field[@name='unit']" position="after"> <xpath expr="/form/field[@name='unit']" position="after">
<label name="breakfast_included"/> <label name="breakfast_included"/>
<field name="breakfast_included"/> <field name="breakfast_included"/>
<label name="season"/>
<field name="season"/>
</xpath> </xpath>
</data> </data>