diff --git a/__init__.py b/__init__.py
index 383fb5c..8d4ba77 100644
--- a/__init__.py
+++ b/__init__.py
@@ -60,6 +60,7 @@ def register():
folio.StatisticsByMonthStart,
folio.Folio,
folio.FolioCharge,
+ folio.HotelFolioTax,
folio.FolioStockMove,
folio.OpenMigrationStart,
stock.Move,
diff --git a/booking.py b/booking.py
index 3bca53a..e104552 100644
--- a/booking.py
+++ b/booking.py
@@ -15,6 +15,7 @@ from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.exceptions import UserError
from trytond.i18n import gettext
+from trytond.modules.account.tax import TaxableMixin
from .constants import (
STATE_BOOKING, REGISTRATION_STATE, REASON, GUARANTEE, SATISFACTION,
MEDIA, PLAN, INVOICE_METHOD, COMPLEMENTARY, PAYMENT_METHOD_CHANNEL,
@@ -65,7 +66,6 @@ class Booking(Workflow, ModelSQL, ModelView):
'invisible': ~Bool(Eval('complementary')),
'required': Bool(Eval('complementary')),
})
- # rename to channel
channel = fields.Many2One('hotel.channel', 'Channel',
states={
'invisible': Eval('media') != 'ota',
@@ -291,6 +291,48 @@ class Booking(Workflow, ModelSQL, ModelView):
now = datetime.now()
return now
+ def _round_taxes(self, taxes):
+ if not self.currency:
+ return
+ for taxline in taxes.values():
+ taxline['amount'] = self.currency.round(taxline['amount'])
+
+ def _get_taxes(self):
+ pool = Pool()
+ Tax = pool.get('account.tax')
+ Configuration = pool.get('account.configuration')
+
+ taxes = {}
+ with Transaction().set_context({}):
+ config = Configuration(1)
+ tax_rounding = config.get_multivalue('tax_rounding')
+
+ def compute(_taxes, unit_price, quantity):
+ 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
+ if self.currency:
+ taxline['base'] = self.currency.round(taxline['base'])
+ if taxline not in taxes:
+ taxes[taxline] = taxline
+ else:
+ taxes[taxline]['base'] += taxline['base']
+ taxes[taxline]['amount'] += taxline['amount']
+ if tax_rounding == 'line':
+ self._round_taxes(taxes)
+
+ for folio in self.lines:
+ compute(folio.taxes, folio.unit_price, folio.nights_quantity)
+
+ for charge in folio.charges:
+ compute(folio.taxes, charge.unit_price, charge.quantity)
+
+ if tax_rounding == 'document':
+ self._round_taxes(taxes)
+ return taxes
+
def get_invoices(self, name=None):
res = []
for folio in self.lines:
@@ -969,22 +1011,24 @@ class Booking(Workflow, ModelSQL, ModelView):
return res
def get_tax_amount(self, name):
- Tax = Pool().get('account.tax')
- Booking = Pool().get('hotel.booking')
-
- res = _ZERO
- for line in self.lines:
- taxes_ids = Booking.get_taxes(line.product)
- if taxes_ids:
- taxes = Tax.browse(taxes_ids)
- tax_list = Tax.compute(
- taxes, line.unit_price or _ZERO, line.nights_quantity or 0
- )
-
- tax_amount = sum([t['amount'] for t in tax_list], _ZERO)
- res += tax_amount
-
- res = Decimal(round(res, 2))
+ # Tax = Pool().get('account.tax')
+ # Booking = Pool().get('hotel.booking')
+ #
+ # res = _ZERO
+ # for folio in self.lines:
+ # taxes_ids = Booking.get_taxes(line.product)
+ # if taxes_ids:
+ # taxes = Tax.browse(taxes_ids)
+ # tax_list = Tax.compute(
+ # taxes, line.unit_price or _ZERO, line.nights_quantity or 0
+ # )
+ #
+ # tax_amount = sum([t['amount'] for t in tax_list], _ZERO)
+ # res += tax_amount
+ #
+ # res = Decimal(round(res, 2))
+ taxes_computed = self._get_taxes()
+ res = sum([t['amount'] for t in taxes_computed], _ZERO)
return res
def get_untaxed_amount(self, name):
diff --git a/folio.py b/folio.py
index dfade19..f3df1a1 100644
--- a/folio.py
+++ b/folio.py
@@ -140,6 +140,13 @@ class Folio(ModelSQL, ModelView):
stock_moves = fields.Function(fields.One2Many('stock.move', 'origin', 'Moves',
readonly=True), 'get_stock_moves')
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',
+ ('group', '=', None),
+ ('group.kind', 'in', ['sale', 'both'])],
+ ],
+ )
@classmethod
def __setup__(cls):
@@ -228,6 +235,10 @@ class Folio(ModelSQL, ModelView):
gettext('hotel.msg_room_no_clean', s=self.room.name)
)
+ # def get_tax_amount(self):
+ # return sum(
+ # (v['amount'] for v in self._get_taxes().values()), Decimal(0))
+
@classmethod
@ModelView.button
def check_out(cls, records):
@@ -1737,3 +1748,13 @@ class RegistrationCardReport(Report):
_records.append(rec)
report_context['records'] = _records
return report_context
+
+
+class HotelFolioTax(ModelSQL):
+ 'Hotel Folio - Tax'
+ __name__ = 'hotel.folio-account.tax'
+ _table = 'hotel_folio_account_tax'
+ folio = fields.Many2One('hotel.folio', 'Folio', ondelete='CASCADE',
+ select=True, required=True)
+ tax = fields.Many2One('account.tax', 'Tax', ondelete='RESTRICT',
+ select=True, required=True)
diff --git a/statement.fodt b/statement.fodt
index dba6c0d..a2be929 100644
Binary files a/statement.fodt and b/statement.fodt differ
diff --git a/tryton.cfg b/tryton.cfg
index f7cb1c7..802ea5d 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -1,5 +1,5 @@
[tryton]
-version=6.0.25
+version=6.0.26
depends:
party
company
diff --git a/view/board_folio_form.xml b/view/board_folio_form.xml
index 180d3c9..7382ae2 100644
--- a/view/board_folio_form.xml
+++ b/view/board_folio_form.xml
@@ -37,6 +37,9 @@ this repository contains the full copyright notices and license terms. -->
+
+
+
diff --git a/view/booking_folio_form.xml b/view/booking_folio_form.xml
index b5b37d7..a895433 100644
--- a/view/booking_folio_form.xml
+++ b/view/booking_folio_form.xml
@@ -35,6 +35,9 @@ this repository contains the full copyright notices and license terms. -->
+
+
+