diff --git a/pms_api_rest/__manifest__.py b/pms_api_rest/__manifest__.py
index fdde38e46..1c48864e8 100644
--- a/pms_api_rest/__manifest__.py
+++ b/pms_api_rest/__manifest__.py
@@ -21,6 +21,7 @@
"python": ["jwt", "simplejson", "marshmallow", "jose"],
},
"data": [
+ "security/ir.model.access.csv",
"data/sql_reports.xml",
"data/auth_jwt_validator.xml",
"data/pms_app_reset_password_template.xml",
diff --git a/pms_api_rest/models/__init__.py b/pms_api_rest/models/__init__.py
index 09f08a589..06aad4285 100644
--- a/pms_api_rest/models/__init__.py
+++ b/pms_api_rest/models/__init__.py
@@ -5,3 +5,4 @@ from . import sql_export
from . import pms_room_type_class
from . import account_bank_statement
from . import product_template
+from . import ota_property_settings
diff --git a/pms_api_rest/models/ota_property_settings.py b/pms_api_rest/models/ota_property_settings.py
new file mode 100644
index 000000000..0298b8bbc
--- /dev/null
+++ b/pms_api_rest/models/ota_property_settings.py
@@ -0,0 +1,34 @@
+from odoo import fields, models
+
+
+class OtaPropertySettings(models.Model):
+ _name = "ota.property.settings"
+
+ pms_property_id = fields.Many2one(
+ string="PMS Property",
+ help="PMS Property",
+ comodel_name="pms.property",
+ default=lambda self: self.env.user.get_active_property_ids()[0],
+ )
+ agency_id = fields.Many2one(
+ string="Partner",
+ help="Partner",
+ comodel_name="res.partner",
+ domain=[("is_agency", "=", True)],
+ )
+ pms_api_alowed_payments = fields.Boolean(
+ string="PMS API Allowed Payments",
+ help="PMS API Allowed Payments",
+ )
+ pms_api_payment_journal_id = fields.Many2one(
+ string="Payment Journal",
+ help="Payment Journal",
+ comodel_name="account.journal",
+ )
+ pms_api_payment_identifier = fields.Char(
+ string="Payment Identifier",
+ help="""
+ Text string used by the OTA to identify a prepaid reservation.
+ The string will be searched within the partnerRequests parameter.
+ """,
+ )
diff --git a/pms_api_rest/models/pms_property.py b/pms_api_rest/models/pms_property.py
index c15c95dd1..3ef24dd61 100644
--- a/pms_api_rest/models/pms_property.py
+++ b/pms_api_rest/models/pms_property.py
@@ -93,3 +93,10 @@ class PmsProperty(models.Model):
string="Hotel image",
store=True,
)
+
+ ota_property_settings_ids = fields.One2many(
+ string="OTA Property Settings",
+ help="OTA Property Settings",
+ comodel_name="ota.property.settings",
+ inverse_name="pms_property_id",
+ )
diff --git a/pms_api_rest/models/res_users.py b/pms_api_rest/models/res_users.py
index c394fb418..0708fb705 100644
--- a/pms_api_rest/models/res_users.py
+++ b/pms_api_rest/models/res_users.py
@@ -22,6 +22,17 @@ class ResUsers(models.Model):
readonly=False,
)
+ pms_api_client = fields.Boolean(
+ string="PMS API Client",
+ help="PMS API Client",
+ )
+
+ pms_api_payment_journal_id = fields.Many2one(
+ string="Payment Journal",
+ help="Payment Journal",
+ comodel_name="account.journal",
+ )
+
def _get_default_avail_rule_fields(self):
default_avail_rule_fields = self.env["ir.model.fields"].search(
[
diff --git a/pms_api_rest/security/ir.model.access.csv b/pms_api_rest/security/ir.model.access.csv
new file mode 100644
index 000000000..f818625d3
--- /dev/null
+++ b/pms_api_rest/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+user_access_ota_property_settings,user_access_ota_property_settings,model_ota_property_settings,pms.group_pms_user,1,0,0,0
+manager_access_ota_property_settings,manager_access_ota_property_settings,model_ota_property_settings,pms.group_pms_manager,1,1,1,1
diff --git a/pms_api_rest/services/pms_folio_service.py b/pms_api_rest/services/pms_folio_service.py
index 6c4e61da7..508a7c923 100644
--- a/pms_api_rest/services/pms_folio_service.py
+++ b/pms_api_rest/services/pms_folio_service.py
@@ -772,12 +772,7 @@ class PmsFolioService(Component):
("ref", "ilike", transaction.reference),
]
):
- # TODO: Move this to the user API payment configuration
- journal = (
- self.env["channel.wubook.backend"]
- .search([("pms_property_id", "=", folio.pms_property_id.id)])
- .wubook_journal_id
- )
+ journal = transaction.journalId
if transaction.transactionType == "inbound":
folio.do_payment(
journal,
@@ -1438,7 +1433,7 @@ class PmsFolioService(Component):
# - Channel Manager
# - Booking Engine
# - ...
- if "neobookings" in self.env.user.login:
+ if self.env.user.pms_api_client:
return "external_app"
return "internal_app"
@@ -1605,6 +1600,8 @@ class PmsFolioService(Component):
skip_compute_service_ids=True,
force_overbooking=True if call_type == "external_app" else False,
).write(folio_vals)
+ # Compute OTA transactions
+ pms_folio_info.transactions = self.normalize_payments_structure(pms_folio_info)
if pms_folio_info.transactions:
self.compute_transactions(folio, pms_folio_info.transactions)
# Force update availability
@@ -1618,6 +1615,54 @@ class PmsFolioService(Component):
date_to=date_to,
)
+ def normalize_payments_structure(self, pms_folio_info):
+ """
+ This method use the OTA payment structure to normalize the structure
+ and incorporate them in the transactions datamodel param
+ """
+ if pms_folio_info.transactions:
+ for transaction in pms_folio_info.transactions:
+ if not transaction.journalId:
+ ota_conf = self.env["ota.property.settings"].search(
+ [
+ ("pms_property_id", "=", pms_folio_info.pmsPropertyId),
+ ("agency_id", "=", self.env.user.partner_id.id),
+ ]
+ )
+ transaction.journalId = ota_conf.pms_api_payment_journal_id.id
+ elif pms_folio_info.agencyId:
+ ota_conf = self.env["ota.property.settings"].search(
+ [
+ ("pms_property_id", "=", pms_folio_info.pmsPropertyId),
+ ("agency_id", "=", pms_folio_info.agencyId),
+ ]
+ )
+ # TODO: Review where to input the data to identify payments,
+ # as partnerRequest in the reservation doesn't seem like the best location.
+ if (
+ ota_conf
+ and ota_conf.pms_api_alowed_payments
+ and any(
+ [
+ reservation.partnerRequests
+ and ota_conf.pms_api_payment_identifier
+ in reservation.partnerRequests
+ for reservation in pms_folio_info.reservations
+ ]
+ )
+ ):
+ journal = ota_conf.pms_api_payment_journal_id
+ pmsTransactionInfo = self.env.datamodels["pms.transaction.info"]
+ pms_folio_info.transactions = [
+ pmsTransactionInfo(
+ journalId=journal.id,
+ transactionType="inbound",
+ amount=pms_folio_info.totalPrice,
+ date=fields.Date.today().strftime("%Y-%m-%d"),
+ reference=pms_folio_info.externalReference,
+ )
+ ]
+
def wrapper_reservations(self, folio, info_reservations):
"""
This method is used to create or update the reservations in folio
diff --git a/pms_api_rest/views/pms_property_views.xml b/pms_api_rest/views/pms_property_views.xml
index 39b4a2bfc..03a52368f 100644
--- a/pms_api_rest/views/pms_property_views.xml
+++ b/pms_api_rest/views/pms_property_views.xml
@@ -90,6 +90,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pms_api_rest/views/res_users_views.xml b/pms_api_rest/views/res_users_views.xml
index 0049c4906..7233cd26a 100644
--- a/pms_api_rest/views/res_users_views.xml
+++ b/pms_api_rest/views/res_users_views.xml
@@ -17,6 +17,18 @@
options="{'no_create': True}"
domain="['&',('model_id', '=', 'pms.availability.plan.rule'), ('name', 'in', ('min_stay', 'max_stay', 'quota', 'max_stay_arrival', 'closed_arrival', 'closed', 'closed_departure', 'min_stay_arrival', 'max_avail'))]"
/>
+
+