[IMP]pms: multiple autoinvoicing improvements

This commit is contained in:
Darío Lodeiros
2022-07-25 17:13:51 +02:00
parent 3deda9f413
commit c0cba08936
14 changed files with 244 additions and 603 deletions

View File

@@ -1,9 +1,11 @@
# Copyright 2020 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import timedelta
from math import ceil
import babel.dates
from dateutil import relativedelta
from odoo import _, api, fields, models
from odoo.osv import expression
@@ -44,6 +46,15 @@ class FolioSaleLine(models.Model):
comodel_name="pms.service",
ondelete="cascade",
)
pms_property_id = fields.Many2one(
string="Property",
help="Property with access to the element;",
readonly=True,
store=True,
comodel_name="pms.property",
related="folio_id.pms_property_id",
check_pms_properties=True,
)
is_board_service = fields.Boolean(
string="Board Service",
help="Indicates if the service included in "
@@ -51,7 +62,6 @@ class FolioSaleLine(models.Model):
store=True,
related="service_id.is_board_service",
)
name = fields.Text(
string="Description",
help="Description of folio sale line",
@@ -259,13 +269,6 @@ class FolioSaleLine(models.Model):
index=True,
related="folio_id.company_id",
)
folio_partner_id = fields.Many2one(
string="Customer",
help="Related customer with Folio Sale Line",
readonly=False,
store=True,
related="folio_id.partner_id",
)
origin_agency_id = fields.Many2one(
string="Origin Agency",
help="The agency where the folio sale line originates",
@@ -330,14 +333,38 @@ class FolioSaleLine(models.Model):
store=True,
compute="_compute_date_order",
)
default_invoice_to = fields.Many2one(
string="Invoice to",
help="""Indicates the contact to which this line will be
billed by default, if it is not established,
a guest or the generic contact will be used instead""",
comodel_name="res.partner",
ondelete="restrict",
)
autoinvoice_date = fields.Date(
string="Autoinvoice Date",
compute="_compute_autoinvoice_date",
store=True,
)
@api.depends(
"folio_id.agency_id",
"reservation_line_ids",
"reservation_id.agency_id",
"service_line_ids",
)
def _compute_origin_agency_id(self):
"""
Set the origin agency if the origin lines channel
match with the agency's channel
"""
for rec in self:
rec.origin_agency_id = rec.folio_id.agency_id
# TODO: ServiceLines agency
if rec.folio_id.agency_id and list(
set(rec.reservation_line_ids.mapped("sale_channel_id.id"))
) == rec.folio_id.agency_id.mapped("sale_channel_id.id"):
rec.origin_agency_id = rec.folio_id.agency_id
else:
rec.origin_agency_id = False
@api.depends("qty_to_invoice")
def _compute_service_order(self):
@@ -370,6 +397,54 @@ class FolioSaleLine(models.Model):
else:
record.date_order = 0
@api.depends(
"default_invoice_to",
"invoice_status",
"folio_id.last_checkout",
"reservation_id.checkout",
"service_id.reservation_id.checkout",
)
def _compute_autoinvoice_date(self):
self.autoinvoice_date = False
for record in self.filtered(lambda r: r.invoice_status == "to_invoice"):
record.autoinvoice_date = record._get_to_invoice_date()
def _get_to_invoice_date(self):
self.ensure_one()
partner = self.default_invoice_to
if self.reservation_id:
last_checkout = self.reservation_id.checkout
elif self.service_id and self.service_id.reservation_id:
last_checkout = self.service_id.reservation_id.checkout
else:
last_checkout = self.folio_id.last_checkout
invoicing_policy = (
self.pms_property_id.default_invoicing_policy
if not partner or partner.invoicing_policy == "property"
else partner.invoicing_policy
)
if invoicing_policy == "manual":
return False
if invoicing_policy == "checkout":
margin_days = (
self.pms_property_id.margin_days_autoinvoice
if not partner or partner.invoicing_policy == "property"
else partner.margin_days_autoinvoice
)
return last_checkout + timedelta(days=margin_days)
if invoicing_policy == "month_day":
month_day = (
self.pms_property_id.invoicing_month_day
if not partner or partner.invoicing_policy == "property"
else partner.invoicing_month_day
)
if last_checkout.day <= month_day:
self.autoinvoice_date = last_checkout.replace(day=month_day)
else:
self.autoinvoice_date = (
last_checkout + relativedelta.relativedelta(months=1)
).replace(day=month_day)
@api.depends("date_order")
def _compute_reservation_order(self):
for record in self:

View File

@@ -4,11 +4,8 @@
import datetime
import logging
from datetime import timedelta
from itertools import groupby
from dateutil import relativedelta
from odoo import _, api, fields, models
from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.tools import float_compare, float_is_zero
@@ -625,13 +622,11 @@ class PmsFolio(models.Model):
folio_lines_to_invoice = folio.sale_line_ids.filtered(
lambda l: l.id in list(lines_to_invoice.keys())
)
folio_partner_invoice_id = partner_invoice_id
if not folio_partner_invoice_id:
folio_partner_invoice_id = folio._get_default_partner_invoice_id()
folio._set_default_partner_invoice_id(
folio_lines_to_invoice, partner_invoice_id
)
groups_invoice_lines = folio._get_groups_invoice_lines(
lines_to_invoice=folio_lines_to_invoice,
partner_invoice_id=folio_partner_invoice_id,
)
for group in groups_invoice_lines:
folio = folio.with_company(folio.company_id)
@@ -698,60 +693,49 @@ class PmsFolio(models.Model):
invoice_vals_list.append(invoice_vals)
return invoice_vals_list
def _get_groups_invoice_lines(self, lines_to_invoice, partner_invoice_id):
def _get_groups_invoice_lines(self, lines_to_invoice):
self.ensure_one()
target_lines = lines_to_invoice
if self._context.get("lines_auto_add") and partner_invoice_id:
folio_partner_invoice = self.env["res.partner"].browse(partner_invoice_id)
if folio_partner_invoice.default_invoice_lines == "overnights":
target_lines = target_lines.filtered(
lambda r: r.is_board_service
or (r.reservation_line_ids and r.reservation_id.overnight_room)
)
elif folio_partner_invoice.default_invoice_lines == "reservations":
target_lines = target_lines.filtered(
lambda r: r.is_board_service or r.reservation_line_ids
)
elif folio_partner_invoice.default_invoice_lines == "services":
target_lines = target_lines.filtered(
lambda r: not r.is_board_service or r.service_line_ids
)
groups_invoice_lines = [
{
"partner_id": partner_invoice_id,
"lines": target_lines,
}
]
if (
self.autoinvoice_date
and self.autoinvoice_date <= fields.Date.today()
and len(target_lines) < len(lines_to_invoice)
):
other_partner_to_invoice = self.partner_invoice_ids.filtered(
lambda p: p.id != partner_invoice_id
)
if not other_partner_to_invoice:
other_partner_to_invoice = self.env.ref("pms.various_pms_partner")
groups_invoice_lines = []
partners = lines_to_invoice.mapped("default_invoice_to")
for partner in partners:
groups_invoice_lines.append(
{
"partner_id": other_partner_to_invoice.id,
"lines": lines_to_invoice - target_lines,
"partner_id": partner.id,
"lines": lines_to_invoice.filtered(
lambda l: l.default_invoice_to == partner
),
}
)
return groups_invoice_lines
def _get_default_partner_invoice_id(self):
def _set_default_partner_invoice_id(
self, lines_to_invoice, folio_partner_invoice_id=False
):
# By priotiy:
# 1º- Partner set in parameter,
# 2º- Partner in default_invoice_to in line
# 3º- Partner in folio,
# 4º- Partner in checkins,
# 5º- Generic various partner
self.ensure_one()
folio_partner_invoice_id = False
if self.partner_id and self.partner_id.vat:
folio_partner_invoice_id = self.partner_id.id
if not folio_partner_invoice_id:
folio_partner_invoice_id = (
self.partner_invoice_ids[0].id if self.partner_invoice_ids else False
for line in lines_to_invoice:
if not folio_partner_invoice_id and line.default_invoice_to:
folio_partner_invoice_id = line.default_invoice_to
if (
not folio_partner_invoice_id
and self.partner_id
and self.partner_id._check_enought_invoice_data()
and not self.partner_id.is_agency
):
folio_partner_invoice_id = self.partner_id.id
checkin_invoice_partner = self.checkin_partner_ids.filtered(
lambda c: c.partner_id and c.partner_id._check_enought_invoice_data()
)
if not folio_partner_invoice_id:
folio_partner_invoice_id = self.env.ref("pms.various_pms_partner").id
return folio_partner_invoice_id
if not folio_partner_invoice_id and checkin_invoice_partner:
folio_partner_invoice_id = checkin_invoice_partner[0].partner_id
if not folio_partner_invoice_id:
folio_partner_invoice_id = self.env.ref("pms.various_pms_partner").id
line.default_invoice_to = folio_partner_invoice_id
def _get_tax_amount_by_group(self):
self.ensure_one()
@@ -789,42 +773,6 @@ class PmsFolio(models.Model):
else:
return False
@api.depends("partner_id", "invoice_status", "last_checkout", "partner_invoice_ids")
def _compute_autoinvoice_date(self):
self.autoinvoice_date = False
for record in self.filtered(lambda r: r.invoice_status == "to_invoice"):
record.autoinvoice_date = record._get_to_invoice_date()
def _get_to_invoice_date(self):
self.ensure_one()
partner = self.partner_id
invoicing_policy = (
self.pms_property_id.default_invoicing_policy
if not partner or partner.invoicing_policy == "property"
else partner.invoicing_policy
)
if invoicing_policy == "manual":
return False
if invoicing_policy == "checkout":
margin_days = (
self.pms_property_id.margin_days_autoinvoice
if not partner or partner.invoicing_policy == "property"
else partner.margin_days_autoinvoice
)
return self.last_checkout + timedelta(days=margin_days)
if invoicing_policy == "month_day":
month_day = (
self.pms_property_id.invoicing_month_day
if not partner or partner.invoicing_policy == "property"
else partner.invoicing_month_day
)
if self.last_checkout.day <= month_day:
self.autoinvoice_date = self.last_checkout.replace(day=month_day)
else:
self.autoinvoice_date = (
self.last_checkout + relativedelta.relativedelta(months=1)
).replace(day=month_day)
@api.depends("reservation_ids", "reservation_ids.state")
def _compute_number_of_rooms(self):
for folio in self:
@@ -848,6 +796,7 @@ class PmsFolio(models.Model):
"reservation_ids",
"service_ids",
"service_ids.reservation_id",
"service_ids.default_invoice_to",
"service_ids.service_line_ids.price_day_total",
"service_ids.service_line_ids.discount",
"service_ids.service_line_ids.cancel_discount",
@@ -857,6 +806,7 @@ class PmsFolio(models.Model):
"reservation_ids.reservation_line_ids.price",
"reservation_ids.reservation_line_ids.discount",
"reservation_ids.reservation_line_ids.cancel_discount",
"reservation_ids.reservation_line_ids.default_invoice_to",
"reservation_ids.tax_ids",
)
def _compute_sale_line_ids(self):
@@ -1054,7 +1004,7 @@ class PmsFolio(models.Model):
"reservation_ids",
"reservation_ids.sale_channel_ids",
"service_ids",
"service_ids.sale_channel_ids",
"service_ids.sale_channel_origin_id",
)
def _compute_sale_channel_ids(self):
for record in self:
@@ -1063,8 +1013,6 @@ class PmsFolio(models.Model):
for sale in record.reservation_ids.mapped("sale_channel_ids.id"):
sale_channel_ids.append(sale)
if record.service_ids:
# si es un board service que mire sale_channel_ids
# y si es un servicio a secas entonces que coja el origen
for sale in record.service_ids.mapped("sale_channel_origin_id.id"):
sale_channel_ids.append(sale)
sale_channel_ids = list(set(sale_channel_ids))
@@ -1910,9 +1858,17 @@ class PmsFolio(models.Model):
self = self.with_context(lines_auto_add=True)
lines_to_invoice = dict()
for line in self.sale_line_ids:
lines_to_invoice[line.id] = (
0 if line.display_type else line.qty_to_invoice
)
if not self._context.get("autoinvoice"):
lines_to_invoice[line.id] = (
0 if line.display_type else line.qty_to_invoice
)
elif (
line.autoinvoice_date
and line.autoinvoice_date <= fields.Date.today()
):
lines_to_invoice[line.id] = (
0 if line.display_type else line.qty_to_invoice
)
invoice_vals_list = self.get_invoice_vals_list(
final=final,
lines_to_invoice=lines_to_invoice,
@@ -2375,8 +2331,8 @@ class PmsFolio(models.Model):
("reservation_id", "=", reservation.id),
("cancel_discount", "<", 100),
],
["price", "discount", "cancel_discount"],
["price", "discount", "cancel_discount"],
["price", "discount", "cancel_discount", "default_invoice_to"],
["price", "discount", "cancel_discount", "default_invoice_to"],
lazy=False,
)
current_sale_line_ids = reservation.sale_line_ids.filtered(
@@ -2391,13 +2347,17 @@ class PmsFolio(models.Model):
final_discount = self.concat_discounts(
item["discount"], item["cancel_discount"]
)
partner_invoice = lines_to.mapped("default_invoice_to")
if current_sale_line_ids and index <= (len(current_sale_line_ids) - 1):
current = {
"price_unit": item["price"],
"discount": final_discount,
"reservation_line_ids": [(6, 0, lines_to.ids)],
"sequence": sequence,
"default_invoice_to": partner_invoice[0].id
if partner_invoice
else current_sale_line_ids[index].default_invoice_to,
}
sale_reservation_vals.append(
(1, current_sale_line_ids[index].id, current)
@@ -2412,6 +2372,9 @@ class PmsFolio(models.Model):
"tax_ids": [(6, 0, reservation.tax_ids.ids)],
"reservation_line_ids": [(6, 0, lines_to.ids)],
"sequence": sequence,
"default_invoice_to": partner_invoice[0].id
if partner_invoice
else False,
}
sale_reservation_vals.append((0, 0, new))
folio_sale_lines_to_remove = []
@@ -2434,8 +2397,8 @@ class PmsFolio(models.Model):
("service_id", "=", service.id),
("cancel_discount", "<", 100),
],
["price_unit", "discount", "cancel_discount"],
["price_unit", "discount", "cancel_discount"],
["price_unit", "discount", "cancel_discount", "default_invoice_to"],
["price_unit", "discount", "cancel_discount", "default_invoice_to"],
lazy=False,
)
current_sale_service_ids = reservation.sale_line_ids.filtered(
@@ -2449,7 +2412,7 @@ class PmsFolio(models.Model):
final_discount = self.concat_discounts(
item["discount"], item["cancel_discount"]
)
partner_invoice = lines_to.mapped("default_invoice_to")
if current_sale_service_ids and index <= (
len(current_sale_service_ids) - 1
):
@@ -2458,6 +2421,9 @@ class PmsFolio(models.Model):
"discount": final_discount,
"service_line_ids": [(6, 0, lines_to.ids)],
"sequence": sequence,
"default_invoice_to": partner_invoice[0].id
if partner_invoice
else current_sale_service_ids[index].default_invoice_to,
}
sale_service_vals.append(
(1, current_sale_service_ids[index].id, current)
@@ -2473,6 +2439,9 @@ class PmsFolio(models.Model):
"product_id": service.product_id.id,
"tax_ids": [(6, 0, service.tax_ids.ids)],
"sequence": sequence,
"default_invoice_to": partner_invoice[0].id
if partner_invoice
else False,
}
sale_service_vals.append((0, 0, new))
sequence = sequence + 1

View File

@@ -607,7 +607,7 @@ class PmsProperty(models.Model):
"""
folios = self.env["pms.folio"].search(
[
("autoinvoice_date", "=", fields.date.today()),
("sale_line_ids.autoinvoice_date", "=", fields.date.today()),
("invoice_status", "=", "to_invoice"),
]
)

View File

@@ -1635,12 +1635,10 @@ class PmsReservation(models.Model):
else:
record.lang = self.env["res.lang"].get_installed()
@api.depends(
"reservation_line_ids",
"reservation_line_ids.sale_channel_id",
"service_ids",
"service_ids.sale_channel_ids",
"service_ids.sale_channel_origin_id",
)
def _compute_sale_channel_ids(self):
@@ -1650,7 +1648,7 @@ class PmsReservation(models.Model):
for sale in record.reservation_line_ids.mapped("sale_channel_id.id"):
sale_channel_ids.append(sale)
if record.service_ids:
for sale in record.service_ids.mapped("sale_channel_ids.id"):
for sale in record.service_ids.mapped("sale_channel_origin_id.id"):
sale_channel_ids.append(sale)
sale_channel_ids = list(set(sale_channel_ids))
record.sale_channel_ids = [(6, 0, sale_channel_ids)]

View File

@@ -45,8 +45,7 @@ class PmsReservationLine(models.Model):
)
pms_property_id = fields.Many2one(
string="Property",
help="Property with access to the element;"
" if not set, all properties can access",
help="Property with access to the element",
readonly=True,
store=True,
comodel_name="pms.property",
@@ -119,6 +118,17 @@ class PmsReservationLine(models.Model):
comodel_name="pms.sale.channel",
check_pms_properties=True,
)
default_invoice_to = fields.Many2one(
string="Invoice to",
help="""Indicates the contact to which this line will be
billed by default, if it is not established,
a guest or the generic contact will be used instead""",
readonly=False,
store=True,
compute="_compute_default_invoice_to",
comodel_name="res.partner",
ondelete="restrict",
)
_sql_constraints = [
(
@@ -502,6 +512,19 @@ class PmsReservationLine(models.Model):
)
return records
@api.depends("sale_channel_id", "reservation_id.agency_id")
def _compute_default_invoice_to(self):
for record in self:
agency = record.reservation_id.agency_id
if (
agency
and agency.invoice_to_agency == "always"
and agency.sale_channel_id == record.sale_channel_id
):
record.default_invoice_to = agency
elif not record.default_invoice_to:
record.default_invoice_to = False
# Constraints and onchanges
@api.constrains("date")
def constrains_duplicated_date(self):

View File

@@ -146,14 +146,6 @@ class PmsService(models.Model):
("no", "Nothing to Invoice"),
],
)
sale_channel_ids = fields.Many2many(
string="Sale Channels",
help="Sale Channels through which service lines were managed",
store=True,
compute="_compute_sale_channel_ids",
comodel_name="pms.sale.channel",
check_pms_properties=True,
)
sale_channel_origin_id = fields.Many2one(
string="Sale Channel Origin",
help="Sale Channel through which service was created, the original",
@@ -199,6 +191,17 @@ class PmsService(models.Model):
""",
default=False,
)
default_invoice_to = fields.Many2one(
string="Invoice to",
help="""Indicates the contact to which this line will be
billed by default, if it is not established,
a guest or the generic contact will be used instead""",
readonly=False,
store=True,
compute="_compute_default_invoice_to",
comodel_name="res.partner",
ondelete="restrict",
)
# Compute and Search methods
@api.depends("product_id")
@@ -427,12 +430,18 @@ class PmsService(models.Model):
line.discount = record.discount
line.cancel_discount = 0
@api.depends("service_line_ids", "service_line_ids.sale_channel_id")
def _compute_sale_channel_ids(self):
@api.depends("sale_channel_origin_id", "folio_id.agency_id")
def _compute_default_invoice_to(self):
for record in self:
record.sale_channel_ids = [
(6, 0, record.mapped("service_line_ids.sale_channel_id.id"))
]
agency = record.folio_id.agency_id
if (
agency
and agency.invoice_to_agency == "always"
and agency.sale_channel_id == record.sale_channel_origin_id
):
record.default_invoice_to = agency
elif not record.default_invoice_to:
record.default_invoice_to = False
def name_get(self):
result = []
@@ -566,7 +575,6 @@ class PmsService(models.Model):
lines_to_update_channel = self.env["pms.service.line"]
if "sale_channel_origin_id" in vals:
folios_to_update_channel = self.get_folios_to_update_channel(vals)
lines_to_update_channel = self.get_service_lines_to_update_channel(vals)
res = super(PmsService, self).write(vals)
if folios_to_update_channel:
folios_to_update_channel.sale_channel_origin_id = vals[
@@ -590,13 +598,3 @@ class PmsService(models.Model):
):
folios_to_update_channel += folio
return folios_to_update_channel
def get_service_lines_to_update_channel(self, vals):
lines_to_update_channel = self.env["pms.service.line"]
for record in self:
for service_line in record.service_line_ids:
if service_line.sale_channel_id == self.sale_channel_origin_id and (
vals["sale_channel_origin_id"] != service_line.sale_channel_id.id
):
lines_to_update_channel += service_line
return lines_to_update_channel

View File

@@ -126,12 +126,6 @@ class PmsServiceLine(models.Model):
readonly=True,
store=True,
)
sale_channel_id = fields.Many2one(
string="Sale Channel",
help="Sale Channel through which service line was created",
comodel_name="pms.sale.channel",
check_pms_properties=True,
)
auto_qty = fields.Boolean(
string="Qty automated setted",
help="Show if the day qty was calculated automatically",
@@ -139,6 +133,16 @@ class PmsServiceLine(models.Model):
readonly=False,
store=True,
)
default_invoice_to = fields.Many2one(
string="Invoice to",
help="""Indicates the contact to which this line will be
billed by default, if it is not established,
a guest or the generic contact will be used instead""",
comodel_name="res.partner",
store=True,
related="service_id.default_invoice_to",
ondelete="restrict",
)
@api.depends("day_qty", "discount", "price_unit", "tax_ids")
def _compute_day_amount_service(self):
@@ -255,15 +259,6 @@ class PmsServiceLine(models.Model):
% (record.service_id.product_id.name, record.date)
)
@api.model
def create(self, vals):
if vals.get("service_id") and not vals.get("sale_channel_id"):
service = self.env["pms.service"].browse(vals["service_id"])
if service.sale_channel_origin_id:
vals["sale_channel_id"] = service.sale_channel_origin_id.id
record = super(PmsServiceLine, self).create(vals)
return record
# Business methods
def _cancel_discount(self):
for record in self:

View File

@@ -192,22 +192,6 @@ class ResPartner(models.Model):
string="Days from Checkout",
help="Days from Checkout to generate the invoice",
)
default_invoice_lines = fields.Selection(
string="Invoice...",
help="""Use to preconfigure the sale lines to autoinvoice
for this partner. All (invoice reservations and services),
Only overnights to invoice only the reservations
with overnight and board services(exclude parkings, salon, etc...),
All reservations to include all reservations,
and Services only include services not boards""",
selection=[
("all", "All"),
("overnights", "Only Overnights"),
("reservations", "All reservations"),
("services", "Services"),
],
default="all",
)
vat_document_type = fields.Selection(
string="Document Type",
help="""The vat document type of the partner,

View File

@@ -239,7 +239,6 @@ class TestPmsFolioInvoice(TestPms):
r1.folio_id.invoice_status,
"The status after a partial invoicing is not correct",
)
# qty to 2 to 1st folio sale line
dict_lines[
r1.folio_id.sale_line_ids.filtered(lambda l: not l.display_type)[0].id
@@ -699,9 +698,9 @@ class TestPmsFolioInvoice(TestPms):
)
# ASSERT
self.assertEqual(
self.assertIn(
datetime.date.today() + datetime.timedelta(days=3),
self.reservation1.folio_id.autoinvoice_date,
self.reservation1.folio_id.mapped("sale_line_ids.autoinvoice_date"),
"The autoinvoice date in folio with property checkout policy is wrong",
)
@@ -729,18 +728,21 @@ class TestPmsFolioInvoice(TestPms):
"sale_channel_origin_id": self.sale_channel_direct1.id,
}
)
self.reservation1.reservation_line_ids.default_invoice_to = self.partner_id
# ASSERT
self.assertEqual(
datetime.date.today() + datetime.timedelta(days=5),
self.reservation1.folio_id.autoinvoice_date,
self.reservation1.folio_id.sale_line_ids.filtered(
lambda l: l.invoice_status == "to_invoice"
)[0].autoinvoice_date,
"The autoinvoice date in folio with property checkout policy is wrong",
)
def test_autoinvoice_paid_folio_overnights_partner_policy(self):
"""
Test create and invoice the cron by partner preconfig automation
with only overnights reservations (included board services)
with partner setted as default invoiced to in reservation lines
--------------------------------------
Set partner invoicing_policy to checkout, create a reservation
with room, board service and normal service, run autoinvoicing
@@ -750,9 +752,18 @@ class TestPmsFolioInvoice(TestPms):
"""
# ARRANGE
self.create_configuration_accounting_scenario()
self.partner_id2 = self.env["res.partner"].create(
{
"name": "Sara",
"vat": "ES123456787",
"country_id": self.env.ref("base.es").id,
"city": "Madrid",
"zip": "28013",
"street": "Street 321",
}
)
self.partner_id.invoicing_policy = "checkout"
self.partner_id.margin_days_autoinvoice = 0
self.partner_id.default_invoice_lines = "overnights"
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
@@ -796,7 +807,7 @@ class TestPmsFolioInvoice(TestPms):
"checkout": datetime.date.today(),
"adults": 2,
"room_type_id": self.demo_room_type_double.id,
"partner_id": self.partner_id.id,
"partner_id": self.partner_id2.id,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_direct1.id,
}
@@ -810,6 +821,11 @@ class TestPmsFolioInvoice(TestPms):
)
folio = self.reservation1.folio_id
reservation1 = self.reservation1
reservation1.reservation_line_ids.default_invoice_to = self.partner_id
reservation1.service_ids.filtered(
"is_board_service"
).default_invoice_to = self.partner_id
folio.do_payment(
journal=self.env["account.journal"].browse(
reservation1.folio_id.pms_property_id._get_payment_methods().ids[0]
@@ -850,7 +866,6 @@ class TestPmsFolioInvoice(TestPms):
# ARRANGE
self.partner_id.invoicing_policy = "checkout"
self.partner_id.margin_days_autoinvoice = 0
self.partner_id.default_invoice_lines = "overnights"
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",

View File

@@ -116,270 +116,6 @@ class TestPmsService(TestPms):
"sale_channel_origin of board_Service must be the same as its reservation",
)
@freeze_time("2002-01-03")
def test_board_service_origin_as_sale_channel_in_lines(self):
"""
The lines of board_service when created have as sale_channel_id
the sale_channel_origin_id of its board_service
Board_service ---> sale_channel_origin = Door
|
---> service_line.sale_channel? It must be DOOR
"""
# ARRANGE
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
}
)
self.board_service1 = self.env["pms.board.service"].create(
{
"name": "Test Board Service 1",
"default_code": "CB1",
}
)
self.board_service_line1 = self.env["pms.board.service.line"].create(
{
"product_id": self.product1.id,
"pms_board_service_id": self.board_service1.id,
"amount": 10,
}
)
self.board_service_room_type1 = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type_double.id,
"pms_board_service_id": self.board_service1.id,
}
)
# ACT
self.reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today(),
"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,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_door.id,
}
)
# ASSERT
self.assertEqual(
self.reservation.service_ids.sale_channel_origin_id,
self.reservation.service_ids.service_line_ids.mapped("sale_channel_id"),
"sale_channel_origin of board_Service must be the same as its service_lines",
)
@freeze_time("2002-01-05")
def test_sale_channel_in_new_line_of_board_service(self):
"""
When adding a line to a board_service already created, by default,
the sale_channel of the line will be the same as the sale_channel_origin_id
of its board_service
Reservation --> sale_channel_ids = { Door, Phone }
|
--> board_service.sale_channel_origin = Door
|
--> board_service.service_line[0].sale_channel = Door
--> NEW board_service.service_line[1].sale_channel?
It must be Door --CHECKING THIS--
"""
# ARRANGE
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
}
)
self.board_service1 = self.env["pms.board.service"].create(
{
"name": "Test Board Service 1",
"default_code": "CB1",
}
)
self.board_service_line1 = self.env["pms.board.service.line"].create(
{
"product_id": self.product1.id,
"pms_board_service_id": self.board_service1.id,
"amount": 10,
}
)
self.board_service_room_type1 = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type_double.id,
"pms_board_service_id": self.board_service1.id,
}
)
self.reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today(),
"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,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_door.id,
}
)
# ACT
self.env["pms.service.line"].create(
{
"service_id": self.reservation.service_ids.id,
}
)
# ASSERT
self.assertEqual(
self.reservation.service_ids.sale_channel_origin_id,
self.reservation.service_ids.service_line_ids.mapped("sale_channel_id"),
"sale_channel_origin of board_Service must corresponds to the"
"sale_channel_id of its new service_line",
)
@freeze_time("2002-01-07")
def test_sale_channel_different_in_lines_check_sale_channel_ids(self):
"""
Check that sale_channel_ids is calculated well (in board_service, folio and
reservation) when a board service has lines from different sale_channels
Reservation --> sale_channel_ids = { Door, Phone } --CHECKING THIS--
|
--> board_service.sale_channel_origin = Door
|
--> board_service.service_line[0].sale_channel = Door
--> board_service.service_line[1].sale_channel = Phone
reservation.folio_id.sale_channel_ids = { Door, Phone } --CHECKING THIS--
"""
# ARRANGE
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
}
)
self.board_service1 = self.env["pms.board.service"].create(
{
"name": "Test Board Service 1",
"default_code": "CB1",
}
)
self.board_service_line1 = self.env["pms.board.service.line"].create(
{
"product_id": self.product1.id,
"pms_board_service_id": self.board_service1.id,
"amount": 10,
}
)
self.board_service_room_type1 = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type_double.id,
"pms_board_service_id": self.board_service1.id,
}
)
self.reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today(),
"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,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_door.id,
}
)
# ACT
self.env["pms.service.line"].create(
{
"service_id": self.reservation.service_ids.id,
"sale_channel_id": self.sale_channel_phone.id,
}
)
sale_channel_ids = [
self.reservation.folio_id.sale_channel_ids.ids,
self.reservation.sale_channel_ids.ids,
self.reservation.service_ids.sale_channel_ids.ids,
]
expected_sale_channel_ids = [
self.sale_channel_door.id,
self.sale_channel_phone.id,
]
# ASSERT
for sale_channel in sale_channel_ids:
with self.subTest(k=sale_channel):
self.assertItemsEqual(
sale_channel,
expected_sale_channel_ids,
"sale_channel_ids must contain sale_channel_id of all board_service_lines",
)
@freeze_time("2002-01-09")
def test_sale_channel_equal_in_lines_check_sale_channel_ids(self):
"""
Check that sale_channel_ids of service is calculated correctly when its lines
have the sale sale_channel_id
"""
# ARRANGE
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
}
)
self.board_service1 = self.env["pms.board.service"].create(
{
"name": "Test Board Service 1",
"default_code": "CB1",
}
)
self.board_service_line1 = self.env["pms.board.service.line"].create(
{
"product_id": self.product1.id,
"pms_board_service_id": self.board_service1.id,
"amount": 10,
}
)
self.board_service_room_type1 = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type_double.id,
"pms_board_service_id": self.board_service1.id,
}
)
# ACT
self.reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today(),
"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,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_door.id,
}
)
self.env["pms.service.line"].create(
{
"service_id": self.reservation.service_ids.id,
}
)
# ASSERT
self.assertEqual(
self.reservation.service_ids.sale_channel_ids,
self.reservation.service_ids.service_line_ids.mapped("sale_channel_id"),
"""sale_channel_ids of board_Service must correspond
to the sale_channel_id set of its service_lines""",
)
@freeze_time("2002-01-11")
def test_change_origin_board_service_not_change_reservation_origin(self):
"""
@@ -447,158 +183,6 @@ class TestPmsService(TestPms):
with sale_channel_origin_id of its reservation""",
)
@freeze_time("2002-01-13")
def test_change_origin_board_service_change_in_lines(self):
"""
Check that when changing sale_channel_origin_id of board_service they
change their lines matching the changed channel
Service --> sale_channel_origin_id = Door sale_channel_ids = {Door, Phone}
|
--> service_line[0].sale_channel_id = Door
|
--> service_line[1].sale_channel_id = Phone
Change service origin to mail, expected results:
Service --> sale_channel_origin_id = Mail sale_channel_ids = {Mail, Phone}
|
--> service_line[0].sale_channel_id = Mail -----------CHECKING THIS---
|
--> service_line[1].sale_channel_id = Phone
"""
# ARRANGE
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
}
)
self.board_service1 = self.env["pms.board.service"].create(
{
"name": "Test Board Service 1",
"default_code": "CB1",
}
)
self.board_service_line1 = self.env["pms.board.service.line"].create(
{
"product_id": self.product1.id,
"pms_board_service_id": self.board_service1.id,
"amount": 10,
}
)
self.board_service_room_type1 = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type_double.id,
"pms_board_service_id": self.board_service1.id,
}
)
self.reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today(),
"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,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_door.id,
}
)
self.env["pms.service.line"].create(
{
"service_id": self.reservation.service_ids.id,
"sale_channel_id": self.sale_channel_phone.id,
}
)
# ACT
self.reservation.service_ids.sale_channel_origin_id = self.sale_channel_mail
# ASSERT
self.assertIn(
self.sale_channel_mail,
self.reservation.service_ids.service_line_ids.mapped("sale_channel_id"),
"""new sale_channel_origin_id of board service
must be changed in lines with same sale_channel""",
)
@freeze_time("2002-01-15")
def test_change_origin_board_service_no_change_in_lines(self):
"""
Check that when changing sale_channel_origin_id of board_service, those of its
service_lines that didn't match with the changed origin shouldn't be changed
Service --> sale_channel_origin_id = Door sale_channel_ids = {Door, Phone}
|
--> service_line[0].sale_channel_id = Door
|
--> service_line[1].sale_channel_id = Phone
Change service origin to mail, expected results:
Service --> sale_channel_origin_id = Mail sale_channel_ids = {Mail, Phone}
|
--> service_line[0].sale_channel_id = Mail
|
--> service_line[1].sale_channel_id = Phone -----------CHECKING THIS---
"""
# ARRANGE
self.product1 = self.env["product.product"].create(
{
"name": "Test Product 1",
}
)
self.board_service1 = self.env["pms.board.service"].create(
{
"name": "Test Board Service 1",
"default_code": "CB1",
}
)
self.board_service_line1 = self.env["pms.board.service.line"].create(
{
"product_id": self.product1.id,
"pms_board_service_id": self.board_service1.id,
"amount": 10,
}
)
self.board_service_room_type1 = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type_double.id,
"pms_board_service_id": self.board_service1.id,
}
)
self.reservation = self.env["pms.reservation"].create(
{
"checkin": fields.date.today(),
"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,
"board_service_room_id": self.board_service_room_type1.id,
"sale_channel_origin_id": self.sale_channel_door.id,
}
)
self.env["pms.service.line"].create(
{
"service_id": self.reservation.service_ids.id,
"sale_channel_id": self.sale_channel_phone.id,
}
)
# ACT
self.reservation.service_ids.sale_channel_origin_id = self.sale_channel_mail
# ASSERT
self.assertIn(
self.sale_channel_phone,
self.reservation.service_ids.service_line_ids.mapped("sale_channel_id"),
"""new sale_channel_origin_id of board service
mustn't changed in lines with different sale_channel""",
)
@freeze_time("2002-01-17")
def test_change_origin_board_service_in_sale_channels(self):
"""

View File

@@ -500,6 +500,7 @@
attrs="{'column_invisible': [('parent.state','!=','cancel')]}"
/>
<field name="sale_channel_id" />
<field name="default_invoice_to" />
<field name="pms_property_id" invisible="1" />
</tree>
</field>
@@ -564,6 +565,10 @@
force_save="1"
/>
<field name="sale_channel_origin_id" />
<field
name="default_invoice_to"
optional="hide"
/>
<button
type="object"
class="oe_stat_button"

View File

@@ -9,7 +9,6 @@
<field name="product_id" />
<field name="day_qty" />
<field name="date" />
<field name="sale_channel_id" />
<field name="price_unit" />
<field
name="discount"
@@ -30,7 +29,6 @@
<field name="product_id" />
<field name="day_qty" />
<field name="date" />
<field name="sale_channel_id" />
<field name="price_unit" />
<field
name="discount"

View File

@@ -28,7 +28,7 @@
force_save="1"
/>
<field name="sale_channel_origin_id" />
<field name="sale_channel_ids" widget="many2many_tags" />
<field name="default_invoice_to" />
</group>
<field name="tax_ids" widget="many2many_tags" invisible="1" />
@@ -38,7 +38,6 @@
<field name="service_line_ids" nolabel="1">
<tree string="Days" editable="bottom">
<field name="date" />
<field name="sale_channel_id" />
<field name="day_qty" />
<field name="price_unit" />
<field
@@ -91,7 +90,7 @@
force_save="1"
/>
<field name="sale_channel_origin_id" />
<field name="sale_channel_ids" />
<field name="default_invoice_to" />
<button
type="object"
class="oe_stat_button"
@@ -106,7 +105,6 @@
<field name="service_line_ids" invisible="1">
<tree string="Days">
<field name="date" />
<field name="sale_channel_id" />
<field name="day_qty" />
<field
name="discount"

View File

@@ -157,7 +157,6 @@
name="margin_days_autoinvoice"
attrs="{'invisible': [('invoicing_policy', '!=', 'checkout')]}"
/>
<field name="default_invoice_lines" />
</group>
</xpath>
</field>