odoo-addon-pms 16.0.0.4.0.6__py3-none-any.whl → 16.0.0.15.0.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/pms/README.rst +1 -1
- odoo/addons/pms/__manifest__.py +1 -1
- odoo/addons/pms/i18n/de.po +14077 -0
- odoo/addons/pms/i18n/es.po +11 -12
- odoo/addons/pms/i18n/it.po +1080 -888
- odoo/addons/pms/i18n/pms.pot +10 -10
- odoo/addons/pms/models/account_move.py +1 -1
- odoo/addons/pms/models/pms_availability.py +7 -9
- odoo/addons/pms/models/pms_folio.py +15 -3
- odoo/addons/pms/models/pms_reservation.py +41 -31
- odoo/addons/pms/models/pms_reservation_line.py +26 -0
- odoo/addons/pms/static/description/index.html +1 -1
- odoo/addons/pms/tests/__init__.py +1 -0
- odoo/addons/pms/tests/test_pms_reservation.py +104 -0
- odoo/addons/pms/tests/test_pms_reservation_line.py +225 -0
- odoo/addons/pms/views/pms_property_views.xml +1 -0
- {odoo_addon_pms-16.0.0.4.0.6.dist-info → odoo_addon_pms-16.0.0.15.0.10.dist-info}/METADATA +2 -2
- {odoo_addon_pms-16.0.0.4.0.6.dist-info → odoo_addon_pms-16.0.0.15.0.10.dist-info}/RECORD +20 -18
- {odoo_addon_pms-16.0.0.4.0.6.dist-info → odoo_addon_pms-16.0.0.15.0.10.dist-info}/WHEEL +0 -0
- {odoo_addon_pms-16.0.0.4.0.6.dist-info → odoo_addon_pms-16.0.0.15.0.10.dist-info}/top_level.txt +0 -0
odoo/addons/pms/i18n/pms.pot
CHANGED
|
@@ -10625,6 +10625,16 @@ msgstr ""
|
|
|
10625
10625
|
msgid "Terms and conditions"
|
|
10626
10626
|
msgstr ""
|
|
10627
10627
|
|
|
10628
|
+
#. module: pms
|
|
10629
|
+
#. odoo-python
|
|
10630
|
+
#: code:addons/pms/models/pms_reservation_line.py:0
|
|
10631
|
+
#, python-format
|
|
10632
|
+
msgid ""
|
|
10633
|
+
"The '%(incompatible_class)s' is not compatible with the reservation type "
|
|
10634
|
+
"class '%(reservation_class)s'. Please select a compatible class room for "
|
|
10635
|
+
"this reservation."
|
|
10636
|
+
msgstr ""
|
|
10637
|
+
|
|
10628
10638
|
#. module: pms
|
|
10629
10639
|
#: model:ir.model.fields,help:pms.field_res_partner_id_number__name
|
|
10630
10640
|
msgid "The ID itself. For example, Driver License number of this person"
|
|
@@ -11061,16 +11071,6 @@ msgstr ""
|
|
|
11061
11071
|
msgid "The revenue manager in the folio"
|
|
11062
11072
|
msgstr ""
|
|
11063
11073
|
|
|
11064
|
-
#. module: pms
|
|
11065
|
-
#. odoo-python
|
|
11066
|
-
#: code:addons/pms/models/pms_reservation.py:0
|
|
11067
|
-
#, python-format
|
|
11068
|
-
msgid ""
|
|
11069
|
-
"The room %(room)s (type: %(room_type)s) is not\n"
|
|
11070
|
-
" compatible with the room type %(record_room_type)s\n"
|
|
11071
|
-
" (type: %(record_room_class)s)"
|
|
11072
|
-
msgstr ""
|
|
11073
|
-
|
|
11074
11074
|
#. module: pms
|
|
11075
11075
|
#. odoo-python
|
|
11076
11076
|
#: code:addons/pms/wizards/wizard_split_join_swap_reservation.py:0
|
|
@@ -285,7 +285,7 @@ class AccountMove(models.Model):
|
|
|
285
285
|
lambda line,
|
|
286
286
|
pay_term_lines=pay_term_lines,
|
|
287
287
|
move=move: line.account_id == pay_term_lines.account_id
|
|
288
|
-
and line.folio_ids in move.folio_ids
|
|
288
|
+
and line.payment_id.folio_ids in move.folio_ids
|
|
289
289
|
)
|
|
290
290
|
)
|
|
291
291
|
to_reconcile = self.match_pays_by_amount(
|
|
@@ -89,23 +89,21 @@ class PmsAvailability(models.Model):
|
|
|
89
89
|
"reservation_line_ids",
|
|
90
90
|
"reservation_line_ids.occupies_availability",
|
|
91
91
|
"room_type_id.total_rooms_count",
|
|
92
|
+
"reservation_line_ids.room_id",
|
|
93
|
+
"reservation_line_ids.date",
|
|
92
94
|
"parent_avail_id",
|
|
93
95
|
"parent_avail_id.reservation_line_ids",
|
|
94
96
|
"parent_avail_id.reservation_line_ids.occupies_availability",
|
|
97
|
+
"parent_avail_id.reservation_line_ids.room_id",
|
|
98
|
+
"parent_avail_id.reservation_line_ids.date",
|
|
95
99
|
"child_avail_ids",
|
|
96
100
|
"child_avail_ids.reservation_line_ids",
|
|
97
101
|
"child_avail_ids.reservation_line_ids.occupies_availability",
|
|
102
|
+
"child_avail_ids.reservation_line_ids.room_id",
|
|
103
|
+
"child_avail_ids.reservation_line_ids.date",
|
|
98
104
|
)
|
|
99
105
|
def _compute_real_avail(self):
|
|
100
106
|
for record in self:
|
|
101
|
-
Rooms = self.env["pms.room"]
|
|
102
|
-
total_rooms = Rooms.search_count(
|
|
103
|
-
[
|
|
104
|
-
("active", "=", True),
|
|
105
|
-
("room_type_id", "=", record.room_type_id.id),
|
|
106
|
-
("pms_property_id", "=", record.pms_property_id.id),
|
|
107
|
-
]
|
|
108
|
-
)
|
|
109
107
|
room_ids = record.room_type_id.room_ids.filtered(
|
|
110
108
|
lambda r, record=record: r.pms_property_id == record.pms_property_id
|
|
111
109
|
and r.active
|
|
@@ -118,7 +116,7 @@ class PmsAvailability(models.Model):
|
|
|
118
116
|
pms_property_id=record.pms_property_id.id,
|
|
119
117
|
)
|
|
120
118
|
)
|
|
121
|
-
record.real_avail =
|
|
119
|
+
record.real_avail = len(room_ids) - count_rooms_not_avail
|
|
122
120
|
|
|
123
121
|
@api.depends("reservation_line_ids", "reservation_line_ids.room_id")
|
|
124
122
|
def _compute_parent_avail_id(self):
|
|
@@ -609,6 +609,10 @@ class PmsFolio(models.Model):
|
|
|
609
609
|
folio_lines_to_invoice = folio.sale_line_ids.filtered(
|
|
610
610
|
lambda r: r.id in list(lines_to_invoice.keys())
|
|
611
611
|
)
|
|
612
|
+
# Avoid create invoices without invoicing lines
|
|
613
|
+
# (display_type is False)
|
|
614
|
+
if not folio_lines_to_invoice.filtered(lambda r: not r.display_type):
|
|
615
|
+
continue
|
|
612
616
|
groups_invoice_lines = folio._get_groups_invoice_lines(
|
|
613
617
|
lines_to_invoice=folio_lines_to_invoice,
|
|
614
618
|
partner_invoice_id=partner_invoice_id,
|
|
@@ -2318,10 +2322,18 @@ class PmsFolio(models.Model):
|
|
|
2318
2322
|
old_note = reservation.sale_line_ids.filtered(
|
|
2319
2323
|
lambda x: x.auto_reservation_note
|
|
2320
2324
|
)
|
|
2321
|
-
if old_note:
|
|
2322
|
-
sale_reservation_vals.append((2, old_note.id))
|
|
2323
2325
|
note_vals = self._get_reservation_note_vals(reservation, sequence)
|
|
2324
|
-
|
|
2326
|
+
create_note = True
|
|
2327
|
+
if old_note:
|
|
2328
|
+
if (
|
|
2329
|
+
not note_vals
|
|
2330
|
+
or old_note.name != note_vals[2]["name"]
|
|
2331
|
+
or old_note.reservation_id.id != note_vals[2]["reservation_id"]
|
|
2332
|
+
):
|
|
2333
|
+
sale_reservation_vals.append((2, old_note.id))
|
|
2334
|
+
else:
|
|
2335
|
+
create_note = False
|
|
2336
|
+
if note_vals and create_note:
|
|
2325
2337
|
sale_reservation_vals.append(note_vals)
|
|
2326
2338
|
expected_reservation_lines = self.env["pms.reservation.line"].read_group(
|
|
2327
2339
|
[
|
|
@@ -1088,12 +1088,7 @@ class PmsReservation(models.Model):
|
|
|
1088
1088
|
# Reservations can be cancelled
|
|
1089
1089
|
for record in self:
|
|
1090
1090
|
record.allowed_cancel = (
|
|
1091
|
-
True
|
|
1092
|
-
if (
|
|
1093
|
-
record.state not in ["done"]
|
|
1094
|
-
and fields.Date.today() <= record.checkout
|
|
1095
|
-
)
|
|
1096
|
-
else False
|
|
1091
|
+
True if (record.state not in ["done", "onboard"]) else False
|
|
1097
1092
|
)
|
|
1098
1093
|
|
|
1099
1094
|
def _compute_ready_for_checkin(self):
|
|
@@ -1295,9 +1290,7 @@ class PmsReservation(models.Model):
|
|
|
1295
1290
|
@api.depends("service_ids.price_total", "services_discount")
|
|
1296
1291
|
def _compute_price_services(self):
|
|
1297
1292
|
for record in self:
|
|
1298
|
-
record.price_services = (
|
|
1299
|
-
sum(record.mapped("service_ids.price_total")) - record.services_discount
|
|
1300
|
-
)
|
|
1293
|
+
record.price_services = sum(record.mapped("service_ids.price_total"))
|
|
1301
1294
|
|
|
1302
1295
|
@api.depends("price_services", "price_total")
|
|
1303
1296
|
def _compute_price_room_services_set(self):
|
|
@@ -1384,7 +1377,9 @@ class PmsReservation(models.Model):
|
|
|
1384
1377
|
if record.partner_id and record.partner_id != record.agency_id:
|
|
1385
1378
|
record.partner_name = record.partner_id.name
|
|
1386
1379
|
if (record.folio_id and not record.partner_name) or (
|
|
1387
|
-
record.folio_id
|
|
1380
|
+
record.folio_id
|
|
1381
|
+
and record.folio_id.partner_name
|
|
1382
|
+
and record.folio_id.partner_name != record.partner_name
|
|
1388
1383
|
):
|
|
1389
1384
|
record.partner_name = record.folio_id.partner_name
|
|
1390
1385
|
elif record.agency_id and not record.partner_name:
|
|
@@ -1842,10 +1837,9 @@ class PmsReservation(models.Model):
|
|
|
1842
1837
|
)
|
|
1843
1838
|
)
|
|
1844
1839
|
|
|
1845
|
-
@api.constrains(
|
|
1846
|
-
"reservation_line_ids", "reservation_line_ids.room_id", "room_type_id"
|
|
1847
|
-
)
|
|
1840
|
+
@api.constrains("reservation_line_ids", "room_type_id")
|
|
1848
1841
|
def _check_room_class_compatibility(self):
|
|
1842
|
+
incompatible_class = False
|
|
1849
1843
|
for record in self:
|
|
1850
1844
|
if (
|
|
1851
1845
|
record.room_type_id
|
|
@@ -1854,20 +1848,24 @@ class PmsReservation(models.Model):
|
|
|
1854
1848
|
):
|
|
1855
1849
|
for line in record.reservation_line_ids:
|
|
1856
1850
|
if (
|
|
1857
|
-
line.room_id.room_type_id.class_id
|
|
1858
|
-
!= record.room_type_id.class_id
|
|
1851
|
+
line.room_id.room_type_id.class_id.overnight
|
|
1852
|
+
!= record.room_type_id.class_id.overnight
|
|
1859
1853
|
):
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1854
|
+
incompatible_class = line.room_id.room_type_id.class_id.name
|
|
1855
|
+
if incompatible_class:
|
|
1856
|
+
raise ValidationError(
|
|
1857
|
+
_(
|
|
1858
|
+
(
|
|
1859
|
+
"The '%(incompatible_class)s' is not compatible with the "
|
|
1860
|
+
"reservation type class '%(reservation_class)s'. Please select "
|
|
1861
|
+
"a compatible class room for this reservation."
|
|
1862
|
+
),
|
|
1863
|
+
{
|
|
1864
|
+
"incompatible_class": incompatible_class,
|
|
1865
|
+
"reservation_class": record.room_type_id.class_id.name,
|
|
1866
|
+
},
|
|
1867
|
+
)
|
|
1868
|
+
)
|
|
1871
1869
|
|
|
1872
1870
|
# Action methods
|
|
1873
1871
|
def open_partner(self):
|
|
@@ -2504,17 +2502,29 @@ class PmsReservation(models.Model):
|
|
|
2504
2502
|
self.ensure_one()
|
|
2505
2503
|
if self.reservation_type != "normal":
|
|
2506
2504
|
return False
|
|
2507
|
-
tax_products = self._get_tourist_tax_products(
|
|
2505
|
+
tax_products = self._get_tourist_tax_products(
|
|
2506
|
+
pms_property_id=self.pms_property_id.id
|
|
2507
|
+
)
|
|
2508
2508
|
if not tax_products:
|
|
2509
2509
|
return []
|
|
2510
2510
|
|
|
2511
2511
|
nightly_dates = self._get_nightly_dates()
|
|
2512
|
-
grouped_lines = self._build_grouped_tax_lines(
|
|
2512
|
+
grouped_lines = self._build_grouped_tax_lines(
|
|
2513
|
+
tax_products,
|
|
2514
|
+
nightly_dates,
|
|
2515
|
+
)
|
|
2513
2516
|
existing_services = self._get_existing_tourist_tax_services()
|
|
2514
2517
|
return self._build_service_commands(grouped_lines, existing_services)
|
|
2515
2518
|
|
|
2516
|
-
def _get_tourist_tax_products(self):
|
|
2517
|
-
return self.env["product.product"].search(
|
|
2519
|
+
def _get_tourist_tax_products(self, pms_property_id):
|
|
2520
|
+
return self.env["product.product"].search(
|
|
2521
|
+
[
|
|
2522
|
+
("is_tourist_tax", "=", True),
|
|
2523
|
+
"|",
|
|
2524
|
+
("pms_property_ids", "=", False),
|
|
2525
|
+
("pms_property_ids", "in", pms_property_id),
|
|
2526
|
+
]
|
|
2527
|
+
)
|
|
2518
2528
|
|
|
2519
2529
|
def _get_nightly_dates(self):
|
|
2520
2530
|
return [
|
|
@@ -2618,7 +2628,7 @@ class PmsReservation(models.Model):
|
|
|
2618
2628
|
"folio_id": self.folio_id.id,
|
|
2619
2629
|
"product_id": product.id,
|
|
2620
2630
|
"name": product.name,
|
|
2621
|
-
"per_day":
|
|
2631
|
+
"per_day": False,
|
|
2622
2632
|
"service_line_ids": [(0, 0, line) for line in new_lines],
|
|
2623
2633
|
},
|
|
2624
2634
|
)
|
|
@@ -660,3 +660,29 @@ class PmsReservationLine(models.Model):
|
|
|
660
660
|
if record.pms_property_id.block_create_past_reservations:
|
|
661
661
|
if record.date < fields.Date.today():
|
|
662
662
|
raise ValidationError(_("You can't create past reservations"))
|
|
663
|
+
|
|
664
|
+
@api.constrains("room_id")
|
|
665
|
+
def _check_room_class_compatibility(self):
|
|
666
|
+
incompatible_class = False
|
|
667
|
+
for record in self:
|
|
668
|
+
if (
|
|
669
|
+
record.room_id
|
|
670
|
+
and record.reservation_id.room_type_id
|
|
671
|
+
and (
|
|
672
|
+
record.room_id.room_type_id.class_id.overnight
|
|
673
|
+
!= record.reservation_id.room_type_id.class_id.overnight
|
|
674
|
+
)
|
|
675
|
+
):
|
|
676
|
+
incompatible_class = True
|
|
677
|
+
if incompatible_class:
|
|
678
|
+
raise ValidationError(
|
|
679
|
+
_(
|
|
680
|
+
"The '%(incompatible_class)s' is not compatible with the "
|
|
681
|
+
"reservation type class '%(reservation_class)s'. Please select "
|
|
682
|
+
"a compatible class room for this reservation."
|
|
683
|
+
)
|
|
684
|
+
% {
|
|
685
|
+
"incompatible_class": incompatible_class,
|
|
686
|
+
"reservation_class": record.room_id.room_type_id.class_id.name,
|
|
687
|
+
}
|
|
688
|
+
)
|
|
@@ -372,7 +372,7 @@ ul.auto-toc {
|
|
|
372
372
|
!! This file is generated by oca-gen-addon-readme !!
|
|
373
373
|
!! changes will be overwritten. !!
|
|
374
374
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
375
|
-
!! source digest: sha256:
|
|
375
|
+
!! source digest: sha256:1932d20cb515244c940884a7573b46a3b589228ee1ebb94ad7f300612769a869
|
|
376
376
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
|
377
377
|
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/pms/tree/16.0/pms"><img alt="OCA/pms" src="https://img.shields.io/badge/github-OCA%2Fpms-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/pms-16-0/pms-16-0-pms"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/pms&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
|
378
378
|
<p>This module is an all-in-one property management system (PMS) focused on medium-sized properties
|
|
@@ -38,6 +38,7 @@ from . import test_pms_wizard_split_join_swap_reservation
|
|
|
38
38
|
from . import test_product_template
|
|
39
39
|
from . import test_pms_multiproperty
|
|
40
40
|
from . import test_shared_room
|
|
41
|
+
from . import test_pms_reservation_line
|
|
41
42
|
|
|
42
43
|
# from . import test_automated_mails
|
|
43
44
|
from . import test_pms_service
|
|
@@ -45,6 +45,50 @@ class TestPmsReservations(TestPms, AccountTestInvoicingCommon):
|
|
|
45
45
|
}
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
+
# Additional room type class for incompatible test
|
|
49
|
+
cls.room_type_class_day = cls.env["pms.room.type.class"].create(
|
|
50
|
+
{
|
|
51
|
+
"name": "Day Use",
|
|
52
|
+
"overnight": False,
|
|
53
|
+
"default_code": "DAY",
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
cls.room_type_class_overnight = cls.env["pms.room.type.class"].create(
|
|
57
|
+
{
|
|
58
|
+
"name": "Overnight",
|
|
59
|
+
"overnight": True,
|
|
60
|
+
"default_code": "OVN",
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
cls.room_type_day = cls.env["pms.room.type"].create(
|
|
65
|
+
{
|
|
66
|
+
"pms_property_ids": [cls.pms_property1.id],
|
|
67
|
+
"name": "Day Room",
|
|
68
|
+
"default_code": "DAY_Test",
|
|
69
|
+
"class_id": cls.room_type_class_day.id,
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
cls.room_type_overnight = cls.env["pms.room.type"].create(
|
|
74
|
+
{
|
|
75
|
+
"pms_property_ids": [cls.pms_property1.id],
|
|
76
|
+
"name": "Overnight Room",
|
|
77
|
+
"default_code": "OVN_Test",
|
|
78
|
+
"class_id": cls.room_type_class_overnight.id,
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
cls.room_day = cls.env["pms.room"].create(
|
|
83
|
+
{
|
|
84
|
+
"pms_property_id": cls.pms_property1.id,
|
|
85
|
+
"name": "Day 201",
|
|
86
|
+
"room_type_id": cls.room_type_day.id,
|
|
87
|
+
"capacity": 1,
|
|
88
|
+
"extra_beds_allowed": 0,
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
48
92
|
# create rooms
|
|
49
93
|
cls.room1 = cls.env["pms.room"].create(
|
|
50
94
|
{
|
|
@@ -3399,3 +3443,63 @@ class TestPmsReservations(TestPms, AccountTestInvoicingCommon):
|
|
|
3399
3443
|
"Sale_channel_origin_id of folio must be the same as "
|
|
3400
3444
|
"sale_channel_origin of rservation",
|
|
3401
3445
|
)
|
|
3446
|
+
|
|
3447
|
+
@freeze_time("2000-12-01")
|
|
3448
|
+
def test_modify_reservation_with_compatible_overnight_classes(self):
|
|
3449
|
+
"""
|
|
3450
|
+
Check that when modifying a reservation with compatible overnight
|
|
3451
|
+
classes, the reservation is modified correctly.
|
|
3452
|
+
"""
|
|
3453
|
+
# ARRANGE
|
|
3454
|
+
checkin = fields.date.today()
|
|
3455
|
+
checkout = fields.date.today() + datetime.timedelta(days=3)
|
|
3456
|
+
reservation_vals = {
|
|
3457
|
+
"checkin": checkin,
|
|
3458
|
+
"checkout": checkout,
|
|
3459
|
+
"room_type_id": self.room_type_double.id,
|
|
3460
|
+
"partner_id": self.partner1.id,
|
|
3461
|
+
"pms_property_id": self.pms_property1.id,
|
|
3462
|
+
"sale_channel_origin_id": self.sale_channel_direct.id,
|
|
3463
|
+
}
|
|
3464
|
+
reservation = self.env["pms.reservation"].create(reservation_vals)
|
|
3465
|
+
|
|
3466
|
+
# ACT
|
|
3467
|
+
reservation.write(
|
|
3468
|
+
{
|
|
3469
|
+
"room_type_id": self.room_type_overnight.id,
|
|
3470
|
+
}
|
|
3471
|
+
)
|
|
3472
|
+
|
|
3473
|
+
# ASSERT
|
|
3474
|
+
self.assertEqual(
|
|
3475
|
+
reservation.room_type_id.id,
|
|
3476
|
+
self.room_type_overnight.id,
|
|
3477
|
+
"The reservation should be modified with the new room type",
|
|
3478
|
+
)
|
|
3479
|
+
|
|
3480
|
+
@freeze_time("2000-12-01")
|
|
3481
|
+
def test_modify_reservation_with_incompatible_overnight_classes(self):
|
|
3482
|
+
"""
|
|
3483
|
+
Check that when modifying a reservation with incompatible overnight
|
|
3484
|
+
classes, the reservation raises an error.
|
|
3485
|
+
"""
|
|
3486
|
+
# ARRANGE
|
|
3487
|
+
checkin = fields.date.today()
|
|
3488
|
+
checkout = fields.date.today() + datetime.timedelta(days=3)
|
|
3489
|
+
reservation_vals = {
|
|
3490
|
+
"checkin": checkin,
|
|
3491
|
+
"checkout": checkout,
|
|
3492
|
+
"room_type_id": self.room_type_double.id,
|
|
3493
|
+
"partner_id": self.partner1.id,
|
|
3494
|
+
"pms_property_id": self.pms_property1.id,
|
|
3495
|
+
"sale_channel_origin_id": self.sale_channel_direct.id,
|
|
3496
|
+
}
|
|
3497
|
+
reservation = self.env["pms.reservation"].create(reservation_vals)
|
|
3498
|
+
|
|
3499
|
+
# ACT & ASSERT
|
|
3500
|
+
with self.assertRaises(ValidationError):
|
|
3501
|
+
reservation.write(
|
|
3502
|
+
{
|
|
3503
|
+
"room_type_id": self.room_type_day.id,
|
|
3504
|
+
}
|
|
3505
|
+
)
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
from freezegun import freeze_time
|
|
4
|
+
|
|
5
|
+
from odoo import fields
|
|
6
|
+
from odoo.exceptions import ValidationError
|
|
7
|
+
from odoo.tests import tagged
|
|
8
|
+
|
|
9
|
+
from .common import TestPms
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@tagged("post_install", "-at_install")
|
|
13
|
+
class TestPmsReservationLines(TestPms):
|
|
14
|
+
@classmethod
|
|
15
|
+
def setUpClass(cls):
|
|
16
|
+
super().setUpClass()
|
|
17
|
+
user = cls.env["res.users"].browse(1)
|
|
18
|
+
cls.env = cls.env(user=user)
|
|
19
|
+
# create a room type availability
|
|
20
|
+
cls.room_type_availability = cls.env["pms.availability.plan"].create(
|
|
21
|
+
{
|
|
22
|
+
"name": "Availability plan for TEST",
|
|
23
|
+
"pms_pricelist_ids": [(6, 0, [cls.pricelist1.id])],
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# create room type
|
|
28
|
+
cls.room_type_double = cls.env["pms.room.type"].create(
|
|
29
|
+
{
|
|
30
|
+
"pms_property_ids": [cls.pms_property1.id],
|
|
31
|
+
"name": "Double Test",
|
|
32
|
+
"default_code": "DBL_Test",
|
|
33
|
+
"class_id": cls.room_type_class1.id,
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
cls.room_type_triple = cls.env["pms.room.type"].create(
|
|
38
|
+
{
|
|
39
|
+
"pms_property_ids": [cls.pms_property1.id],
|
|
40
|
+
"name": "Triple Test",
|
|
41
|
+
"default_code": "TRP_Test",
|
|
42
|
+
"class_id": cls.room_type_class1.id,
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Additional room type class for incompatible test
|
|
47
|
+
cls.room_type_class_day = cls.env["pms.room.type.class"].create(
|
|
48
|
+
{
|
|
49
|
+
"name": "Day Use",
|
|
50
|
+
"overnight": False,
|
|
51
|
+
"default_code": "DAY",
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
cls.room_type_class_overnight = cls.env["pms.room.type.class"].create(
|
|
55
|
+
{
|
|
56
|
+
"name": "Overnight",
|
|
57
|
+
"overnight": True,
|
|
58
|
+
"default_code": "OVN",
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
cls.room_type_day = cls.env["pms.room.type"].create(
|
|
63
|
+
{
|
|
64
|
+
"pms_property_ids": [cls.pms_property1.id],
|
|
65
|
+
"name": "Day Room",
|
|
66
|
+
"default_code": "DAY_Test",
|
|
67
|
+
"class_id": cls.room_type_class_day.id,
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
cls.room_type_overnight = cls.env["pms.room.type"].create(
|
|
72
|
+
{
|
|
73
|
+
"pms_property_ids": [cls.pms_property1.id],
|
|
74
|
+
"name": "Overnight Room",
|
|
75
|
+
"default_code": "OVN_Test",
|
|
76
|
+
"class_id": cls.room_type_class_overnight.id,
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
cls.room_day = cls.env["pms.room"].create(
|
|
81
|
+
{
|
|
82
|
+
"pms_property_id": cls.pms_property1.id,
|
|
83
|
+
"name": "Day 201",
|
|
84
|
+
"room_type_id": cls.room_type_day.id,
|
|
85
|
+
"capacity": 1,
|
|
86
|
+
"extra_beds_allowed": 0,
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
cls.room_overnight = cls.env["pms.room"].create(
|
|
90
|
+
{
|
|
91
|
+
"pms_property_id": cls.pms_property1.id,
|
|
92
|
+
"name": "Overnight 202",
|
|
93
|
+
"room_type_id": cls.room_type_overnight.id,
|
|
94
|
+
"capacity": 1,
|
|
95
|
+
"extra_beds_allowed": 0,
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# create rooms
|
|
100
|
+
cls.room1 = cls.env["pms.room"].create(
|
|
101
|
+
{
|
|
102
|
+
"pms_property_id": cls.pms_property1.id,
|
|
103
|
+
"name": "Double 101",
|
|
104
|
+
"room_type_id": cls.room_type_double.id,
|
|
105
|
+
"capacity": 2,
|
|
106
|
+
"extra_beds_allowed": 1,
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
cls.room2 = cls.env["pms.room"].create(
|
|
111
|
+
{
|
|
112
|
+
"pms_property_id": cls.pms_property1.id,
|
|
113
|
+
"name": "Double 102",
|
|
114
|
+
"room_type_id": cls.room_type_double.id,
|
|
115
|
+
"capacity": 2,
|
|
116
|
+
"extra_beds_allowed": 1,
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
cls.room3 = cls.env["pms.room"].create(
|
|
121
|
+
{
|
|
122
|
+
"pms_property_id": cls.pms_property1.id,
|
|
123
|
+
"name": "Double 103",
|
|
124
|
+
"room_type_id": cls.room_type_double.id,
|
|
125
|
+
"capacity": 2,
|
|
126
|
+
"extra_beds_allowed": 1,
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
cls.room4 = cls.env["pms.room"].create(
|
|
131
|
+
{
|
|
132
|
+
"pms_property_id": cls.pms_property1.id,
|
|
133
|
+
"name": "Triple 104",
|
|
134
|
+
"room_type_id": cls.room_type_triple.id,
|
|
135
|
+
"capacity": 3,
|
|
136
|
+
"extra_beds_allowed": 1,
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
cls.partner1 = cls.env["res.partner"].create(
|
|
140
|
+
{
|
|
141
|
+
"firstname": "Jaime",
|
|
142
|
+
"lastname": "García",
|
|
143
|
+
"email": "jaime@example.com",
|
|
144
|
+
"birthdate_date": "1983-03-01",
|
|
145
|
+
"gender": "male",
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
cls.id_category = cls.env["res.partner.id_category"].create(
|
|
149
|
+
{"name": "DNI", "code": "D"}
|
|
150
|
+
)
|
|
151
|
+
cls.sale_channel_direct = cls.env["pms.sale.channel"].create(
|
|
152
|
+
{"name": "sale channel direct", "channel_type": "direct"}
|
|
153
|
+
)
|
|
154
|
+
cls.sale_channel1 = cls.env["pms.sale.channel"].create(
|
|
155
|
+
{"name": "saleChannel1", "channel_type": "indirect"}
|
|
156
|
+
)
|
|
157
|
+
cls.agency1 = cls.env["res.partner"].create(
|
|
158
|
+
{
|
|
159
|
+
"firstname": "partner1",
|
|
160
|
+
"is_agency": True,
|
|
161
|
+
"invoice_to_agency": "always",
|
|
162
|
+
"default_commission": 15,
|
|
163
|
+
"sale_channel_id": cls.sale_channel1.id,
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
@freeze_time("2000-12-01")
|
|
168
|
+
def test_modify_reservation_line_with_compatible_overnight_classes(self):
|
|
169
|
+
"""
|
|
170
|
+
Check that when modifying a reservation with compatible overnight
|
|
171
|
+
classes, the reservation is modified correctly.
|
|
172
|
+
"""
|
|
173
|
+
# ARRANGE
|
|
174
|
+
checkin = fields.date.today()
|
|
175
|
+
checkout = fields.date.today() + datetime.timedelta(days=3)
|
|
176
|
+
reservation_vals = {
|
|
177
|
+
"checkin": checkin,
|
|
178
|
+
"checkout": checkout,
|
|
179
|
+
"room_type_id": self.room_type_double.id,
|
|
180
|
+
"partner_id": self.partner1.id,
|
|
181
|
+
"pms_property_id": self.pms_property1.id,
|
|
182
|
+
"sale_channel_origin_id": self.sale_channel_direct.id,
|
|
183
|
+
}
|
|
184
|
+
reservation = self.env["pms.reservation"].create(reservation_vals)
|
|
185
|
+
|
|
186
|
+
# ACT
|
|
187
|
+
reservation.reservation_line_ids[0].write(
|
|
188
|
+
{
|
|
189
|
+
"room_id": self.room_overnight.id,
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# ASSERT
|
|
194
|
+
self.assertEqual(
|
|
195
|
+
reservation.reservation_line_ids[0].room_id.room_type_id.id,
|
|
196
|
+
self.room_type_overnight.id,
|
|
197
|
+
"The reservation should be modified with the new room type",
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
@freeze_time("2000-12-01")
|
|
201
|
+
def test_modify_reservation_with_incompatible_overnight_classes(self):
|
|
202
|
+
"""
|
|
203
|
+
Check that when modifying a reservation with incompatible overnight
|
|
204
|
+
classes, the reservation raises an error.
|
|
205
|
+
"""
|
|
206
|
+
# ARRANGE
|
|
207
|
+
checkin = fields.date.today()
|
|
208
|
+
checkout = fields.date.today() + datetime.timedelta(days=3)
|
|
209
|
+
reservation_vals = {
|
|
210
|
+
"checkin": checkin,
|
|
211
|
+
"checkout": checkout,
|
|
212
|
+
"room_type_id": self.room_type_double.id,
|
|
213
|
+
"partner_id": self.partner1.id,
|
|
214
|
+
"pms_property_id": self.pms_property1.id,
|
|
215
|
+
"sale_channel_origin_id": self.sale_channel_direct.id,
|
|
216
|
+
}
|
|
217
|
+
reservation = self.env["pms.reservation"].create(reservation_vals)
|
|
218
|
+
|
|
219
|
+
# ACT & ASSERT
|
|
220
|
+
with self.assertRaises(ValidationError):
|
|
221
|
+
reservation.reservation_line_ids[0].write(
|
|
222
|
+
{
|
|
223
|
+
"room_id": self.room_day.id,
|
|
224
|
+
}
|
|
225
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: odoo-addon-pms
|
|
3
|
-
Version: 16.0.0.
|
|
3
|
+
Version: 16.0.0.15.0.10
|
|
4
4
|
Summary: A property management system
|
|
5
5
|
Home-page: https://github.com/OCA/pms
|
|
6
6
|
Author: Commit [Sun], Odoo Community Association (OCA)
|
|
@@ -36,7 +36,7 @@ PMS (Property Management System)
|
|
|
36
36
|
!! This file is generated by oca-gen-addon-readme !!
|
|
37
37
|
!! changes will be overwritten. !!
|
|
38
38
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
39
|
-
!! source digest: sha256:
|
|
39
|
+
!! source digest: sha256:1932d20cb515244c940884a7573b46a3b589228ee1ebb94ad7f300612769a869
|
|
40
40
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
41
41
|
|
|
42
42
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|