Merge PR #34 into 14.0

Signed-off-by DarioLodeiros
This commit is contained in:
OCA-git-bot
2021-07-10 08:22:52 +00:00
6 changed files with 578 additions and 142 deletions

View File

@@ -367,6 +367,9 @@ class PmsReservation(models.Model):
help="Field indicating type of cancellation. " help="Field indicating type of cancellation. "
"It can be 'late', 'intime' or 'noshow'", "It can be 'late', 'intime' or 'noshow'",
copy=False, copy=False,
compute="_compute_cancelled_reason",
readonly=False,
store=True,
selection=[("late", "Late"), ("intime", "In time"), ("noshow", "No Show")], selection=[("late", "Late"), ("intime", "In time"), ("noshow", "No Show")],
tracking=True, tracking=True,
) )
@@ -582,6 +585,16 @@ class PmsReservation(models.Model):
compute="_compute_discount", compute="_compute_discount",
tracking=True, tracking=True,
) )
services_discount = fields.Float(
string="Services discount (€)",
help="Services discount",
readonly=False,
store=True,
digits=("Discount"),
compute="_compute_services_discount",
tracking=True,
)
date_order = fields.Date( date_order = fields.Date(
string="Date Order", string="Date Order",
help="Order date of reservation", help="Order date of reservation",
@@ -1146,10 +1159,12 @@ class PmsReservation(models.Model):
for res in self: for res in self:
res.nights = len(res.reservation_line_ids) res.nights = len(res.reservation_line_ids)
@api.depends("service_ids.price_total") @api.depends("service_ids.price_total", "services_discount")
def _compute_price_services(self): def _compute_price_services(self):
for record in self: for record in self:
record.price_services = sum(record.mapped("service_ids.price_total")) record.price_services = (
sum(record.mapped("service_ids.price_total")) - record.services_discount
)
@api.depends("price_services", "price_total") @api.depends("price_services", "price_total")
def _compute_price_room_services_set(self): def _compute_price_room_services_set(self):
@@ -1157,7 +1172,8 @@ class PmsReservation(models.Model):
record.price_room_services_set = record.price_services + record.price_total record.price_room_services_set = record.price_services + record.price_total
@api.depends( @api.depends(
"reservation_line_ids.discount", "reservation_line_ids.cancel_discount" "reservation_line_ids.discount",
"reservation_line_ids.cancel_discount",
) )
def _compute_discount(self): def _compute_discount(self):
for record in self: for record in self:
@@ -1167,8 +1183,17 @@ class PmsReservation(models.Model):
price = line.price - first_discount price = line.price - first_discount
cancel_discount = price * ((line.cancel_discount or 0.0) * 0.01) cancel_discount = price * ((line.cancel_discount or 0.0) * 0.01)
discount += first_discount + cancel_discount discount += first_discount + cancel_discount
record.discount = discount record.discount = discount
@api.depends("service_ids.discount")
def _compute_services_discount(self):
for record in self:
services_discount = 0
for service in record.service_ids:
services_discount += service.discount
record.services_discount = services_discount
@api.depends("reservation_line_ids.price", "discount", "tax_ids") @api.depends("reservation_line_ids.price", "discount", "tax_ids")
def _compute_amount_reservation(self): def _compute_amount_reservation(self):
""" """
@@ -1660,37 +1685,39 @@ class PmsReservation(models.Model):
if not record.allowed_cancel: if not record.allowed_cancel:
raise UserError(_("This reservation cannot be cancelled")) raise UserError(_("This reservation cannot be cancelled"))
else: else:
cancel_reason = ( record.state = "cancel"
"intime"
if self._context.get("no_penalty", False)
else record.compute_cancelation_reason()
)
if self._context.get("no_penalty", False):
_logger.info("Modified Reservation - No Penalty")
record.write({"state": "cancel", "cancelled_reason": cancel_reason})
# record._compute_cancel_discount()
record.folio_id._compute_amount() record.folio_id._compute_amount()
def action_assign(self): def action_assign(self):
for record in self: for record in self:
record.to_assign = False record.to_assign = False
def compute_cancelation_reason(self): @api.depends("state")
self.ensure_one() def _compute_cancelled_reason(self):
pricelist = self.pricelist_id for record in self:
if pricelist and pricelist.cancelation_rule_id: # self.ensure_one()
tz_property = self.pms_property_id.tz if record.state == "cancel":
today = fields.Date.context_today(self.with_context(tz=tz_property)) pricelist = record.pricelist_id
days_diff = ( if record._context.get("no_penalty", False):
fields.Date.from_string(self.checkin) - fields.Date.from_string(today) record.cancelled_reason = "intime"
).days _logger.info("Modified Reservation - No Penalty")
if days_diff < 0: elif pricelist and pricelist.cancelation_rule_id:
return "noshow" tz_property = record.pms_property_id.tz
elif days_diff < pricelist.cancelation_rule_id.days_intime: today = fields.Date.context_today(
return "late" record.with_context(tz=tz_property)
else: )
return "intime" days_diff = (
return False fields.Date.from_string(record.checkin)
- fields.Date.from_string(today)
).days
if days_diff < 0:
record.cancelled_reason = "noshow"
elif days_diff < pricelist.cancelation_rule_id.days_intime:
record.cancelled_reason = "late"
else:
record.cancelled_reason = "intime"
else:
record.cancelled_reason = False
def action_reservation_checkout(self): def action_reservation_checkout(self):
for record in self: for record in self:

View File

@@ -388,56 +388,52 @@ class PmsReservationLine(models.Model):
def _compute_cancel_discount(self): def _compute_cancel_discount(self):
for line in self: for line in self:
line.cancel_discount = 0 line.cancel_discount = 0
# TODO: Review cancel logic reservation = line.reservation_id
# reservation = line.reservation_id pricelist = reservation.pricelist_id
# pricelist = reservation.pricelist_id if reservation.state == "cancel":
# if reservation.state == "cancel": if (
# if ( reservation.cancelled_reason
# reservation.cancelled_reason and pricelist
# and pricelist and pricelist.cancelation_rule_id
# and pricelist.cancelation_rule_id ):
# ): checkin = fields.Date.from_string(reservation.checkin)
# date_start_dt = fields.Date.from_string( checkout = fields.Date.from_string(reservation.checkout)
# reservation.checkin days = abs((checkin - checkout).days)
# ) rule = pricelist.cancelation_rule_id
# date_end_dt = fields.Date.from_string( discount = 0
# reservation.checkout if reservation.cancelled_reason == "late":
# ) discount = 100 - rule.penalty_late
# days = abs((date_end_dt - date_start_dt).days) if rule.apply_on_late == "first":
# rule = pricelist.cancelation_rule_id days = 1
# if reservation.cancelled_reason == "late": elif rule.apply_on_late == "days":
# discount = 100 - rule.penalty_late days = rule.days_late
# if rule.apply_on_late == "first": elif reservation.cancelled_reason == "noshow":
# days = 1 discount = 100 - rule.penalty_noshow
# elif rule.apply_on_late == "days": if rule.apply_on_noshow == "first":
# days = rule.days_late days = 1
# elif reservation.cancelled_reason == "noshow": elif rule.apply_on_noshow == "days":
# discount = 100 - rule.penalty_noshow days = rule.days_late - 1
# if rule.apply_on_noshow == "first": elif reservation.cancelled_reason == "intime":
# days = 1 discount = 100
# elif rule.apply_on_noshow == "days":
# days = rule.days_late - 1
# elif reservation.cancelled_reason == "intime":
# discount = 100
# checkin = reservation.checkin dates = []
# dates = [] for i in range(0, days):
# for i in range(0, days): dates.append(
# dates.append( fields.Date.from_string(
# ( fields.Date.from_string(checkin)
# fields.Date.from_string(checkin) + timedelta(days=i) + datetime.timedelta(days=i)
# ).strftime(DEFAULT_SERVER_DATE_FORMAT) )
# ) )
# reservation.reservation_line_ids.filtered( reservation.reservation_line_ids.filtered(
# lambda r: r.date in dates lambda r: r.date in dates
# ).update({"cancel_discount": discount}) ).update({"cancel_discount": discount})
# reservation.reservation_line_ids.filtered( reservation.reservation_line_ids.filtered(
# lambda r: r.date not in dates lambda r: r.date not in dates
# ).update({"cancel_discount": 100}) ).update({"cancel_discount": 100})
# else: else:
# reservation.reservation_line_ids.update({"cancel_discount": 0}) reservation.reservation_line_ids.update({"cancel_discount": 0})
# else: else:
# reservation.reservation_line_ids.update({"cancel_discount": 0}) reservation.reservation_line_ids.update({"cancel_discount": 0})
@api.depends("room_id", "pms_property_id", "date", "occupies_availability") @api.depends("room_id", "pms_property_id", "date", "occupies_availability")
def _compute_avail_id(self): def _compute_avail_id(self):
@@ -473,17 +469,6 @@ class PmsReservationLine(models.Model):
if duplicated: if duplicated:
raise ValidationError(_("Duplicated reservation line date")) raise ValidationError(_("Duplicated reservation line date"))
@api.constrains("state")
def constrains_service_cancel(self):
for record in self:
if record.state == "cancel":
room_services = record.reservation_id.service_ids
for service in room_services:
cancel_lines = service.service_line_ids.filtered(
lambda r: r.date == record.date
)
cancel_lines.day_qty = 0
@api.constrains("room_id") @api.constrains("room_id")
def _check_adults(self): def _check_adults(self):
for record in self.filtered("room_id"): for record in self.filtered("room_id"):

View File

@@ -168,7 +168,7 @@ class PmsService(models.Model):
) )
price_total = fields.Monetary( price_total = fields.Monetary(
string="Total", string="Total",
help="Total price without taxes", help="Total price with taxes",
readonly=True, readonly=True,
store=True, store=True,
compute="_compute_amount_service", compute="_compute_amount_service",
@@ -181,6 +181,15 @@ class PmsService(models.Model):
compute="_compute_amount_service", compute="_compute_amount_service",
) )
discount = fields.Float(
string="Discount (€)",
help="Discount of total price",
readonly=False,
store=True,
digits=("Discount"),
compute="_compute_discount",
)
# Compute and Search methods # Compute and Search methods
@api.depends("product_id") @api.depends("product_id")
def _compute_tax_ids(self): def _compute_tax_ids(self):
@@ -380,7 +389,16 @@ class PmsService(models.Model):
else: else:
service.service_line_ids = False service.service_line_ids = False
# Default methods @api.depends("service_line_ids.cancel_discount")
def _compute_discount(self):
for record in self:
discount = 0
for line in record.service_line_ids:
first_discount = line.price_day_total * ((line.discount or 0.0) * 0.01)
price = line.price_day_total - first_discount
cancel_discount = price * ((line.cancel_discount or 0.0) * 0.01)
discount += first_discount + cancel_discount
record.discount = discount
def name_get(self): def name_get(self):
result = [] result = []

View File

@@ -1,6 +1,8 @@
# Copyright 2017-2018 Alexandre Díaz # Copyright 2017-2018 Alexandre Díaz
# Copyright 2017 Dario Lodeiros # Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import datetime
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
@@ -71,7 +73,7 @@ class PmsServiceLine(models.Model):
) )
price_day_total = fields.Monetary( price_day_total = fields.Monetary(
string="Total", string="Total",
help="Total price without taxes", help="Total price with taxes",
readonly=True, readonly=True,
store=True, store=True,
compute="_compute_day_amount_service", compute="_compute_day_amount_service",
@@ -169,60 +171,35 @@ class PmsServiceLine(models.Model):
record.discount = 0 record.discount = 0
# TODO: Refact method and allowed cancelled single days # TODO: Refact method and allowed cancelled single days
@api.depends("service_id.reservation_id.cancelled_reason") @api.depends("service_id.reservation_id.reservation_line_ids.cancel_discount")
def _compute_cancel_discount(self): def _compute_cancel_discount(self):
for line in self: for line in self:
line.cancel_discount = 0 line.cancel_discount = 0
# TODO: Review cancel logic reservation = line.reservation_id
# reservation = line.reservation_id.reservation_id if reservation.state == "cancel":
# pricelist = reservation.pricelist_id if (
# if reservation.state == "cancel": reservation.cancelled_reason
# if ( and reservation.pricelist_id
# reservation.cancel_reason and reservation.pricelist_id.cancelation_rule_id
# and pricelist and reservation.reservation_line_ids.mapped("cancel_discount")
# and pricelist.cancelation_rule_id ):
# ): if line.is_board_service:
# date_start_dt = fields.Date.from_string( consumed_date = (
# reservation.checkin line.date
# ) if line.product_id.consumed_on == "before"
# date_end_dt = fields.Date.from_string( else line.date + datetime.timedelta(days=-1)
# reservation.checkout )
# ) line.cancel_discount = (
# days = abs((date_end_dt - date_start_dt).days) reservation.reservation_line_ids.filtered(
# rule = pricelist.cancelation_rule_id lambda l: l.date == consumed_date
# if reservation.cancelled_reason == "late": ).cancel_discount
# discount = 100 - rule.penalty_late )
# if rule.apply_on_late == "first": else:
# days = 1 line.cancel_discount = 100
# elif rule.apply_on_late == "days": else:
# days = rule.days_late line.cancel_discount = 0
# elif reservation.cancelled_reason == "noshow": else:
# discount = 100 - rule.penalty_noshow line.cancel_discount = 0
# if rule.apply_on_noshow == "first":
# days = 1
# elif rule.apply_on_noshow == "days":
# days = rule.days_late - 1
# elif reservation.cancelled_reason == "intime":
# discount = 100
# checkin = reservation.checkin
# dates = []
# for i in range(0, days):
# dates.append(
# (
# fields.Date.from_string(checkin) + timedelta(days=i)
# ).strftime(DEFAULT_SERVER_DATE_FORMAT)
# )
# reservation.reservation_line_ids.filtered(
# lambda r: r.date in dates
# ).update({"cancel_discount": discount})
# reservation.reservation_line_ids.filtered(
# lambda r: r.date not in dates
# ).update({"cancel_discount": 100})
# else:
# reservation.reservation_line_ids.update({"cancel_discount": 0})
# else:
# reservation.reservation_line_ids.update({"cancel_discount": 0})
@api.depends("day_qty") @api.depends("day_qty")
def _compute_auto_qty(self): def _compute_auto_qty(self):

View File

@@ -2569,3 +2569,425 @@ class TestPmsReservations(TestPms):
"Reservation from " + agency.name, "Reservation from " + agency.name,
"Partner name doesn't match with to the expected", "Partner name doesn't match with to the expected",
) )
@freeze_time("2010-11-10")
def test_cancel_discount_board_service(self):
"""
When a reservation is cancelled, service discount in case of board_services
must be equal to the discounts of each reservation_line.
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.product = self.env["product.product"].create(
{
"name": "Product test",
"per_day": True,
"consumed_on": "after",
}
)
self.board_service = self.env["pms.service"].create(
{
"is_board_service": True,
"product_id": self.product.id,
}
)
self.room_type_double.list_price = 25
reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today() + datetime.timedelta(days=-3),
"checkout": fields.date.today() + datetime.timedelta(days=3),
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"service_ids": [self.board_service.id],
}
)
# ACTION
reservation.action_cancel()
reservation.flush()
# ASSERT
self.assertEqual(
set(reservation.reservation_line_ids.mapped("cancel_discount")),
set(reservation.service_ids.service_line_ids.mapped("cancel_discount")),
"Cancel discount of reservation service lines must be the same "
"that reservation board services",
)
@freeze_time("2011-10-10")
def test_cancel_discount_reservation_line(self):
"""
When a reservation is cancelled, cancellation discount is given
by the cancellation rule associated with the reservation pricelist.
Each reservation_line calculates depending on the cancellation
reason which is the correspondig discount. In this case the
cancellation reason is'noshow' and the rule specifies that 50% must
be reducted every day, that is, on each of reseravtion_lines
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.room_type_double.list_price = 50
reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today() + datetime.timedelta(days=-3),
"checkout": fields.date.today() + datetime.timedelta(days=3),
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
}
)
# ACTION
reservation.action_cancel()
reservation.flush()
# ASSERT
self.assertEqual(
set(reservation.reservation_line_ids.mapped("cancel_discount")),
{self.cancelation_rule.penalty_noshow},
"Cancel discount of reservation_lines must be equal than cancellation rule penalty",
)
@freeze_time("2011-11-11")
def test_cancel_discount_service(self):
"""
When a reservation is cancelled, service discount in
services that are not board_services ALWAYS have to be 100%,
refardless of the cancellation rule associated with the pricelist
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.product = self.env["product.product"].create(
{
"name": "Product test",
"per_day": True,
"consumed_on": "after",
"is_extra_bed": True,
}
)
self.service = self.env["pms.service"].create(
{
"is_board_service": False,
"product_id": self.product.id,
}
)
reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today() + datetime.timedelta(days=-3),
"checkout": fields.date.today() + datetime.timedelta(days=3),
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"service_ids": [self.service.id],
}
)
expected_cancel_discount = 100
# ACTION
reservation.action_cancel()
reservation.flush()
# ASSERT
self.assertEqual(
{expected_cancel_discount},
set(reservation.service_ids.service_line_ids.mapped("cancel_discount")),
"Cancel discount of services must be 100%",
)
@freeze_time("2011-06-06")
def test_discount_in_service(self):
"""
Discount in pms.service is calculated from the
discounts that each if its service lines has,
in this case when reservation is cancelled a
50% cancellation discount is applied and
there aren't other different discounts
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.product = self.env["product.product"].create(
{
"name": "Product test",
"per_day": True,
"consumed_on": "after",
}
)
self.board_service = self.env["pms.service"].create(
{
"is_board_service": True,
"product_id": self.product.id,
}
)
self.room_type_double.list_price = 25
reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today() + datetime.timedelta(days=-3),
"checkout": fields.date.today() + datetime.timedelta(days=3),
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"service_ids": [self.board_service.id],
}
)
# ACTION
reservation.action_cancel()
reservation.flush()
expected_discount = sum(
sl.price_day_total * sl.cancel_discount / 100
for sl in self.board_service.service_line_ids
)
# ASSERT
self.assertEqual(
expected_discount,
self.board_service.discount,
"Service discount must be the sum of its services_lines discount",
)
@freeze_time("2011-11-11")
def test_services_discount_in_reservation(self):
"""
Services discount in reservation is equal to the sum of the discounts of all
its services, whether they are board_services or not
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.product1 = self.env["product.product"].create(
{
"name": "Product test1",
"per_day": True,
"consumed_on": "after",
"is_extra_bed": True,
}
)
self.service = self.env["pms.service"].create(
{
"is_board_service": False,
"product_id": self.product1.id,
}
)
self.service.flush()
self.product2 = self.env["product.product"].create(
{
"name": "Product test 2",
"per_person": True,
"consumed_on": "after",
}
)
self.board_service = self.env["pms.service"].create(
{
"is_board_service": True,
"product_id": self.product2.id,
}
)
self.room_type_double.list_price = 25
checkin = fields.date.today() + datetime.timedelta(days=-3)
checkout = fields.date.today() + datetime.timedelta(days=3)
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"service_ids": [self.service.id, self.board_service.id],
}
)
# ACTION
reservation.action_cancel()
reservation.flush()
expected_discount = sum(s.discount for s in reservation.service_ids)
# ASSERT
self.assertEqual(
expected_discount,
reservation.services_discount,
"Services discount isn't the expected",
)
@freeze_time("2011-12-12")
def test_price_services_in_reservation(self):
"""
Service price total in a reservation corresponds to the sum of prices
of all its services less the total discount of that services
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.product1 = self.env["product.product"].create(
{
"name": "Product test1",
"per_day": True,
"consumed_on": "after",
"is_extra_bed": True,
}
)
self.service = self.env["pms.service"].create(
{
"is_board_service": False,
"product_id": self.product1.id,
}
)
self.service.flush()
self.product2 = self.env["product.product"].create(
{
"name": "Product test 2",
"per_person": True,
"consumed_on": "after",
}
)
self.board_service = self.env["pms.service"].create(
{
"is_board_service": True,
"product_id": self.product2.id,
}
)
self.room_type_double.list_price = 25
checkin = fields.date.today() + datetime.timedelta(days=-3)
checkout = fields.date.today() + datetime.timedelta(days=3)
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"service_ids": [self.service.id, self.board_service.id],
}
)
# ACTION
reservation.action_cancel()
reservation.flush()
expected_price = (
self.service.price_total
+ self.board_service.price_total * reservation.adults
) - reservation.services_discount
# ASSERT
self.assertEqual(
expected_price,
reservation.price_services,
"Services price isn't the expected",
)
@freeze_time("2011-08-08")
def test_room_discount_in_reservation(self):
"""
Discount in pms.reservation is calculated from the
discounts that each if its reservation lines has,
in this case when reservation is cancelled a 50%
cancellation discount is applied and
there aren't other different discounts
"""
# ARRANGE
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"penalty_noshow": 50,
"apply_on_noshow": "all",
}
)
self.pricelist1.cancelation_rule_id = self.cancelation_rule.id
self.room_type_double.list_price = 30
checkin = fields.date.today() + datetime.timedelta(days=-3)
checkout = fields.date.today() + datetime.timedelta(days=3)
reservation = self.env["pms.reservation"].create(
{
"checkin": checkin,
"checkout": checkout,
"room_type_id": self.room_type_double.id,
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
}
)
# ACTION
reservation.action_cancel()
reservation.flush()
expected_discount = sum(
rl.price * rl.cancel_discount / 100
for rl in reservation.reservation_line_ids
)
# ASSERT
self.assertEqual(
expected_discount,
reservation.discount,
"Room discount isn't the expected",
)

View File

@@ -405,6 +405,12 @@
widget="monetary" widget="monetary"
options="{'currency_field': 'currency_id'}" options="{'currency_field': 'currency_id'}"
/> />
<field
name="services_discount"
string="Discount Services"
widget="monetary"
options="{'currency_field': 'currency_id'}"
/>
<field name="price_subtotal" invisible="1" /> <field name="price_subtotal" invisible="1" />
<div <div
class="oe_subtotal_footer_separator oe_inline o_td_label" class="oe_subtotal_footer_separator oe_inline o_td_label"
@@ -542,6 +548,7 @@
<field name="tax_ids" widget="many2many_tags" /> <field name="tax_ids" widget="many2many_tags" />
<field name="price_subtotal" /> <field name="price_subtotal" />
<field name="price_tax" /> <field name="price_tax" />
<field name="discount" />
<field name="price_total" /> <field name="price_total" />
<field name="service_line_ids" invisible="1"> <field name="service_line_ids" invisible="1">
<tree string="Days"> <tree string="Days">