Compare commits
3 Commits
06c03d9d85
...
a7000eb130
Author | SHA1 | Date |
---|---|---|
oscar alvarez | a7000eb130 | |
oscar alvarez | ee661d56a3 | |
oscar alvarez | 05a7d332f9 |
3
TODO.md
3
TODO.md
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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')
|
||||||
|
|
1
folio.py
1
folio.py
|
@ -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',
|
||||||
|
|
144
invoice.py
144
invoice.py
|
@ -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'
|
||||||
|
|
|
@ -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>
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"/>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue