mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
Merge branch '14.0' into 14.0-pms_improvements_layout_precheckin
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# Do NOT update manually; changes here will be overwritten by Copier
|
||||
_commit: v1.1.4
|
||||
_commit: v1.3.4
|
||||
_src_path: https://github.com/OCA/oca-addons-repo-template.git
|
||||
ci: Travis
|
||||
dependency_installation_mode: OCA
|
||||
generate_requirements_txt: true
|
||||
include_wkhtmltopdf: false
|
||||
odoo_version: 14.0
|
||||
rebel_module_groups: []
|
||||
repo_description:
|
||||
All-in-One Property Management System (PMS) focused on medium-sizeations.
|
||||
repo_description: All-in-One Property Management System (PMS) focused on medium-sizeations.
|
||||
repo_name: Property Management System
|
||||
repo_slug: pms
|
||||
travis_apt_packages: []
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
env:
|
||||
browser: true
|
||||
es6: true
|
||||
|
||||
# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449
|
||||
parserOptions:
|
||||
@@ -14,7 +15,7 @@ globals:
|
||||
moment: readonly
|
||||
odoo: readonly
|
||||
openerp: readonly
|
||||
Promise: readonly
|
||||
owl: readonly
|
||||
|
||||
# Styling is handled by Prettier, so we only need to enable AST rules;
|
||||
# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890
|
||||
|
||||
4
.github/workflows/pre-commit.yml
vendored
4
.github/workflows/pre-commit.yml
vendored
@@ -10,4 +10,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
# The pylint-odoo version we use here does not support python 3.10
|
||||
# https://github.com/OCA/oca-addons-repo-template/issues/80
|
||||
python-version: "3.9"
|
||||
- uses: pre-commit/action@v2.0.0
|
||||
|
||||
69
.github/workflows/stale.yml
vendored
Normal file
69
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * 0"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Stale PRs and issues policy
|
||||
uses: actions/stale@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# General settings.
|
||||
ascending: true
|
||||
remove-stale-when-updated: true
|
||||
# Pull Requests settings.
|
||||
# 120+30 day stale policy for PRs
|
||||
# * Except PRs marked as "no stale"
|
||||
days-before-pr-stale: 120
|
||||
days-before-pr-close: 30
|
||||
exempt-pr-labels: "no stale"
|
||||
stale-pr-label: "stale"
|
||||
stale-pr-message: >
|
||||
There hasn't been any activity on this pull request in the past 4 months, so
|
||||
it has been marked as stale and it will be closed automatically if no
|
||||
further activity occurs in the next 30 days.
|
||||
|
||||
If you want this PR to never become stale, please ask a PSC member to apply
|
||||
the "no stale" label.
|
||||
# Issues settings.
|
||||
# 180+30 day stale policy for open issues
|
||||
# * Except Issues marked as "no stale"
|
||||
days-before-issue-stale: 180
|
||||
days-before-issue-close: 30
|
||||
exempt-issue-labels: "no stale,needs more information"
|
||||
stale-issue-label: "stale"
|
||||
stale-issue-message: >
|
||||
There hasn't been any activity on this issue in the past 6 months, so it has
|
||||
been marked as stale and it will be closed automatically if no further
|
||||
activity occurs in the next 30 days.
|
||||
|
||||
If you want this issue to never become stale, please ask a PSC member to
|
||||
apply the "no stale" label.
|
||||
|
||||
# 15+30 day stale policy for issues pending more information
|
||||
# * Issues that are pending more information
|
||||
# * Except Issues marked as "no stale"
|
||||
- name: Needs more information stale issues policy
|
||||
uses: actions/stale@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
ascending: true
|
||||
only-labels: "needs more information"
|
||||
exempt-issue-labels: "no stale"
|
||||
days-before-stale: 15
|
||||
days-before-close: 30
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-label: "stale"
|
||||
stale-issue-message: >
|
||||
This issue needs more information and there hasn't been any activity
|
||||
recently, so it has been marked as stale and it will be closed automatically
|
||||
if no further activity occurs in the next 30 days.
|
||||
|
||||
If you think this is a mistake, please ask a PSC member to remove the "needs
|
||||
more information" label.
|
||||
@@ -5,7 +5,7 @@ exclude: |
|
||||
# Files and folders generated by bots, to avoid loops
|
||||
^setup/|/static/description/index\.html$|
|
||||
# We don't want to mess with tool-generated files
|
||||
.svg$|/tests/([^/]+/)?cassettes/|
|
||||
.svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|
|
||||
# Maybe reactivate this when all README files include prettier ignore tags?
|
||||
^README\.md$|
|
||||
# Library files can have extraneous formatting (even minimized)
|
||||
|
||||
@@ -21,9 +21,9 @@ addon | version | maintainers | summary
|
||||
--- | --- | --- | ---
|
||||
[multi_pms_properties](multi_pms_properties/) | 14.0.1.0.0 | | Multi Properties Manager
|
||||
[payment_acquirer_multi_pms_properties](payment_acquirer_multi_pms_properties/) | 14.0.1.0.1 | | Payment Acquirer Multiproperty
|
||||
[pms](pms/) | 14.0.2.20.0 | | A property management system
|
||||
[pms](pms/) | 14.0.2.20.3 | | A property management system
|
||||
[pms_housekeeping](pms_housekeeping/) | 14.0.1.0.1 | | Housekeeping
|
||||
[pms_l10n_es](pms_l10n_es/) | 14.0.2.1.1 | | PMS Spanish Adaptation
|
||||
[pms_l10n_es](pms_l10n_es/) | 14.0.2.2.0 | | PMS Spanish Adaptation
|
||||
[pms_rooming_xls](pms_rooming_xls/) | 14.0.1.0.0 | | Rooming xlsx Management
|
||||
|
||||
[//]: # (end addons)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
"name": "PMS (Property Management System)",
|
||||
"summary": "A property management system",
|
||||
"version": "14.0.2.20.0",
|
||||
"version": "14.0.2.20.3",
|
||||
"development_status": "Alpha",
|
||||
"category": "Generic Modules/Property Management System",
|
||||
"website": "https://github.com/OCA/pms",
|
||||
@@ -88,6 +88,7 @@
|
||||
"views/precheckin_portal_templates.xml",
|
||||
"wizards/wizard_massive_changes.xml",
|
||||
"wizards/wizard_advanced_filters.xml",
|
||||
"views/payment_transaction_views.xml",
|
||||
],
|
||||
"demo": [
|
||||
"demo/pms_master_data.xml",
|
||||
|
||||
@@ -4,6 +4,7 @@ from odoo import _, fields, http, tools
|
||||
from odoo.exceptions import AccessError, MissingError
|
||||
from odoo.http import request
|
||||
|
||||
from odoo.addons.payment.controllers.portal import PaymentProcessing
|
||||
from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
|
||||
|
||||
|
||||
@@ -26,10 +27,127 @@ class PortalFolio(CustomerPortal):
|
||||
|
||||
def _folio_get_page_view_values(self, folio, access_token, **kwargs):
|
||||
values = {"folio": folio, "token": access_token}
|
||||
payment_inputs = request.env["payment.acquirer"]._get_available_payment_input(
|
||||
partner=folio.partner_id, company=folio.company_id
|
||||
)
|
||||
is_public_user = request.env.user._is_public()
|
||||
if is_public_user:
|
||||
payment_inputs.pop("pms", None)
|
||||
token_count = (
|
||||
request.env["payment.token"]
|
||||
.sudo()
|
||||
.search_count(
|
||||
[
|
||||
("acquirer_id.company_id", "=", folio.company_id.id),
|
||||
("partner_id", "=", folio.partner_id.id),
|
||||
]
|
||||
)
|
||||
)
|
||||
values["existing_token"] = token_count > 0
|
||||
values.update(payment_inputs)
|
||||
values["partner_id"] = (
|
||||
folio.partner_id if is_public_user else request.env.user.partner_id,
|
||||
)
|
||||
return self._get_page_view_values(
|
||||
folio, access_token, values, "my_folios_history", False, **kwargs
|
||||
)
|
||||
|
||||
@http.route(
|
||||
"/folio/pay/<int:folio_id>/form_tx", type="json", auth="public", website=True
|
||||
)
|
||||
def folio_pay_form(
|
||||
self, acquirer_id, folio_id, save_token=False, access_token=None, **kwargs
|
||||
):
|
||||
folio_sudo = request.env["pms.folio"].sudo().browse(folio_id)
|
||||
if not folio_sudo:
|
||||
return False
|
||||
|
||||
try:
|
||||
acquirer_id = int(acquirer_id)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
if request.env.user._is_public():
|
||||
save_token = False # we avoid to create a token for the public user
|
||||
|
||||
success_url = kwargs.get(
|
||||
"success_url",
|
||||
"%s?%s" % (folio_sudo.access_url, access_token if access_token else ""),
|
||||
)
|
||||
vals = {
|
||||
"acquirer_id": acquirer_id,
|
||||
"return_url": success_url,
|
||||
}
|
||||
|
||||
if save_token:
|
||||
vals["type"] = "form_save"
|
||||
transaction = folio_sudo._create_payment_transaction(vals)
|
||||
PaymentProcessing.add_payment_transaction(transaction)
|
||||
if not transaction:
|
||||
return False
|
||||
tx_ids_list = set(request.session.get("__payment_tx_ids__", [])) | set(
|
||||
transaction.ids
|
||||
)
|
||||
request.session["__payment_tx_ids__"] = list(tx_ids_list)
|
||||
return transaction.render_folio_button(
|
||||
folio_sudo,
|
||||
submit_txt=_("Pay & Confirm"),
|
||||
render_values={
|
||||
"type": "form_save" if save_token else "form",
|
||||
"alias_usage": _(
|
||||
"If we store your payment information on our server, "
|
||||
"subscription payments will be made automatically."
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
# @http.route(
|
||||
# '/invoice/pay/<int:invoice_id>/s2s_token_tx',
|
||||
# type='http',
|
||||
# auth='public',
|
||||
# website=True
|
||||
# )
|
||||
# def invoice_pay_token(self, invoice_id, pm_id=None, **kwargs):
|
||||
# """ Use a token to perform a s2s transaction """
|
||||
# error_url = kwargs.get('error_url', '/my')
|
||||
# access_token = kwargs.get('access_token')
|
||||
# params = {}
|
||||
# if access_token:
|
||||
# params['access_token'] = access_token
|
||||
#
|
||||
# invoice_sudo = request.env['account.move'].sudo().browse(invoice_id).exists()
|
||||
# if not invoice_sudo:
|
||||
# params['error'] = 'pay_invoice_invalid_doc'
|
||||
# return request.redirect(_build_url_w_params(error_url, params))
|
||||
#
|
||||
# success_url = kwargs.get(
|
||||
# 'success_url',
|
||||
# "%s?%s" % (
|
||||
# invoice_sudo.access_url,
|
||||
# url_encode({'access_token': access_token}) if access_token else '')
|
||||
# )
|
||||
# try:
|
||||
# token = request.env['payment.token'].sudo().browse(int(pm_id))
|
||||
# except (ValueError, TypeError):
|
||||
# token = False
|
||||
# token_owner = invoice_sudo.partner_id if \
|
||||
# request.env.user._is_public() else request.env.user.partner_id
|
||||
# if not token or token.partner_id != token_owner:
|
||||
# params['error'] = 'pay_invoice_invalid_token'
|
||||
# return request.redirect(_build_url_w_params(error_url, params))
|
||||
#
|
||||
# vals = {
|
||||
# 'payment_token_id': token.id,
|
||||
# 'type': 'server2server',
|
||||
# 'return_url': _build_url_w_params(success_url, params),
|
||||
# }
|
||||
#
|
||||
# tx = invoice_sudo._create_payment_transaction(vals)
|
||||
# PaymentProcessing.add_payment_transaction(tx)
|
||||
#
|
||||
# params['success'] = 'pay_invoice'
|
||||
# return request.redirect('/payment/process')
|
||||
|
||||
@http.route(
|
||||
["/my/folios", "/my/folios/page/<int:page>"],
|
||||
type="http",
|
||||
|
||||
132
pms/i18n/pms.pot
132
pms/i18n/pms.pot
@@ -169,6 +169,21 @@ msgstr ""
|
||||
msgid "<i class=\"fa fa-download\"/> Download"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_folio_page_payment
|
||||
msgid "<i class=\"fa fa-fw fa-arrow-circle-right\"/> Pay Now"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_folio_page_payment
|
||||
msgid "<i class=\"fa fa-fw fa-check-circle\"/> Paid"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_folio_page_payment
|
||||
msgid "<i class=\"fa fa-fw fa-check-circle\"/> Pending"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.pms_reservation_view_form
|
||||
msgid ""
|
||||
@@ -784,6 +799,18 @@ msgid ""
|
||||
"Customer Invoice/Credit Note"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/pms_folio.py:0
|
||||
#, python-format
|
||||
msgid "A journal must be specified for the acquirer %s."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/pms_folio.py:0
|
||||
#, python-format
|
||||
msgid "A payment acquirer is required to create a transaction."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,help:pms.field_folio_advance_payment_inv__advance_payment_method
|
||||
msgid ""
|
||||
@@ -800,6 +827,18 @@ msgid ""
|
||||
"A service is a non-material product you provide."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/pms_folio.py:0
|
||||
#, python-format
|
||||
msgid "A transaction can't be linked to folios having different currencies."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/pms_folio.py:0
|
||||
#, python-format
|
||||
msgid "A transaction can't be linked to folios having different partners."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_property__user_ids
|
||||
msgid "Accepted Users"
|
||||
@@ -1267,13 +1306,18 @@ msgid "Apply Pricelist"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_board_service_room_type__by_default
|
||||
msgid "Apply by Default"
|
||||
#: model_terms:ir.ui.view,arch_db:pms.massive_changes_wizard
|
||||
msgid "Apply and close"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.massive_changes_wizard
|
||||
msgid "Apply changes"
|
||||
msgid "Apply and continue"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_board_service_room_type__by_default
|
||||
msgid "Apply by Default"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
@@ -2200,6 +2244,11 @@ msgstr ""
|
||||
msgid "Class to which the room type belongs"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_folio_payment
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_availability_plan_rule__closed
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_massive_changes_wizard__closed
|
||||
@@ -2469,13 +2518,6 @@ msgstr ""
|
||||
msgid "Contacts"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,help:pms.field_folio_sale_line__product_uom_category_id
|
||||
msgid ""
|
||||
"Conversion between Units of Measure can only occur if they belong to the "
|
||||
"same category. The conversion will be made based on the ratios."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_room_type__standard_price
|
||||
msgid "Cost"
|
||||
@@ -2988,7 +3030,6 @@ msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,help:pms.field_pms_folio__credit_card_details
|
||||
#: model:ir.model.fields,help:pms.field_pms_reservation__credit_card_details
|
||||
msgid "Details of partner credit card"
|
||||
msgstr ""
|
||||
|
||||
@@ -3104,6 +3145,7 @@ msgstr ""
|
||||
#: model:ir.model.fields,field_description:pms.field_ir_config_parameter__display_name
|
||||
#: model:ir.model.fields,field_description:pms.field_ir_http__display_name
|
||||
#: model:ir.model.fields,field_description:pms.field_mail_compose_message__display_name
|
||||
#: model:ir.model.fields,field_description:pms.field_payment_transaction__display_name
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_advanced_filters_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_amenity__display_name
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_amenity_type__display_name
|
||||
@@ -3734,6 +3776,7 @@ msgstr ""
|
||||
#: model:ir.model.fields,field_description:pms.field_account_move__folio_ids
|
||||
#: model:ir.model.fields,field_description:pms.field_account_move_line__folio_ids
|
||||
#: model:ir.model.fields,field_description:pms.field_account_payment__folio_ids
|
||||
#: model:ir.model.fields,field_description:pms.field_payment_transaction__folio_ids
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_property__pms_folio_ids
|
||||
#: model:ir.model.fields,field_description:pms.field_res_partner__pms_folio_ids
|
||||
#: model:ir.model.fields,field_description:pms.field_res_users__pms_folio_ids
|
||||
@@ -4071,6 +4114,7 @@ msgstr ""
|
||||
#: model:ir.model.fields,field_description:pms.field_ir_config_parameter__id
|
||||
#: model:ir.model.fields,field_description:pms.field_ir_http__id
|
||||
#: model:ir.model.fields,field_description:pms.field_mail_compose_message__id
|
||||
#: model:ir.model.fields,field_description:pms.field_payment_transaction__id
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_advanced_filters_wizard__id
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_amenity__id
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_amenity_type__id
|
||||
@@ -4227,6 +4271,14 @@ msgstr ""
|
||||
msgid "If unchecked, it will allow you to hide the room type"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/controllers/pms_portal.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"If we store your payment information on our server, subscription payments "
|
||||
"will be made automatically."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_checkin_partner__image_128
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_property__image_1920
|
||||
@@ -4591,6 +4643,18 @@ msgstr ""
|
||||
msgid "Invalid reservation"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/pms_folio.py:0
|
||||
#, python-format
|
||||
msgid "Invalid token found! Token acquirer %s != %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/pms_folio.py:0
|
||||
#, python-format
|
||||
msgid "Invalid token found! Token partner %s != %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_my_folio_precheckin
|
||||
msgid "Invitation email sent"
|
||||
@@ -4942,6 +5006,7 @@ msgstr ""
|
||||
#: model:ir.model.fields,field_description:pms.field_ir_config_parameter____last_update
|
||||
#: model:ir.model.fields,field_description:pms.field_ir_http____last_update
|
||||
#: model:ir.model.fields,field_description:pms.field_mail_compose_message____last_update
|
||||
#: model:ir.model.fields,field_description:pms.field_payment_transaction____last_update
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_advanced_filters_wizard____last_update
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_amenity____last_update
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_amenity_type____last_update
|
||||
@@ -5238,6 +5303,12 @@ msgstr ""
|
||||
msgid "Massive changes on Pricelist & Availability Plans"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/wizards/wizard_massive_changes.py:0
|
||||
#, python-format
|
||||
msgid "Massive changes on Pricelist and Availability Plans"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_folio__max_reservation_priority
|
||||
#: model:ir.model.fields,help:pms.field_pms_folio__max_reservation_priority
|
||||
@@ -6183,6 +6254,24 @@ msgstr ""
|
||||
msgid "Pay"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/controllers/pms_portal.py:0
|
||||
#, python-format
|
||||
msgid "Pay & Confirm"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: code:addons/pms/models/payment_transaction.py:0
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_folio_payment
|
||||
#, python-format
|
||||
msgid "Pay Now"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.portal_folio_payment
|
||||
msgid "Pay with"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_property__debit_limit
|
||||
msgid "Payable Limit"
|
||||
@@ -6241,6 +6330,11 @@ msgstr ""
|
||||
msgid "Payment Tokens"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model,name:pms.model_payment_transaction
|
||||
msgid "Payment Transaction"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,help:pms.field_pms_folio__payment_term_id
|
||||
msgid "Payment terms for current folio."
|
||||
@@ -8198,6 +8292,14 @@ msgstr ""
|
||||
msgid "Services on Board Service included in Room"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,help:pms.field_pms_reservation__overnight_room
|
||||
#: model:ir.model.fields,help:pms.field_pms_reservation_line__overnight_room
|
||||
#: model:ir.model.fields,help:pms.field_pms_room_type__overnight_room
|
||||
#: model:ir.model.fields,help:pms.field_pms_room_type_class__overnight
|
||||
msgid "Set False if if these types of spaces are not used for overnight stays"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model_terms:ir.ui.view,arch_db:pms.pms_folio_view_form
|
||||
msgid "Set to Done"
|
||||
@@ -9685,6 +9787,14 @@ msgstr ""
|
||||
msgid "Use a barcode to identify this contact."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_reservation__overnight_room
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_reservation_line__overnight_room
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_room_type__overnight_room
|
||||
#: model:ir.model.fields,field_description:pms.field_pms_room_type_class__overnight
|
||||
msgid "Use for overnight stays"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms
|
||||
#: model:ir.model.fields,help:pms.field_account_journal__allowed_pms_payments
|
||||
msgid "Use to pay for reservations"
|
||||
|
||||
@@ -47,3 +47,4 @@ from . import account_journal
|
||||
from . import pms_availability
|
||||
from . import res_partner_id_number
|
||||
from . import pms_automated_mails
|
||||
from . import payment_transaction
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
from odoo import fields, models
|
||||
from odoo import _, fields, models
|
||||
|
||||
|
||||
class PaymentTransaction(models.Model):
|
||||
_name = "payment.transaction"
|
||||
_inherit = "payment.transaction"
|
||||
|
||||
folio_ids = fields.Many2many(
|
||||
string="Folios",
|
||||
comodel_name="pms.folio",
|
||||
ondelete="cascade",
|
||||
relation="account_bank_statement_folio_rel",
|
||||
column1="account_journal_id",
|
||||
relation="payment_transaction_folio_rel",
|
||||
column1="payment_transaction_id",
|
||||
column2="folio_id",
|
||||
)
|
||||
|
||||
@@ -20,3 +20,23 @@ class PaymentTransaction(models.Model):
|
||||
if self.folio_ids:
|
||||
add_payment_vals["folio_ids"] = [(6, 0, self.folio_ids.ids)]
|
||||
return super(PaymentTransaction, self)._create_payment(add_payment_vals)
|
||||
|
||||
def render_folio_button(self, folio, submit_txt=None, render_values=None):
|
||||
values = {
|
||||
"partner_id": folio.partner_id.id,
|
||||
"type": self.type,
|
||||
}
|
||||
if render_values:
|
||||
values.update(render_values)
|
||||
return (
|
||||
self.acquirer_id.with_context(
|
||||
submit_class="btn btn-primary", submit_txt=submit_txt or _("Pay Now")
|
||||
)
|
||||
.sudo()
|
||||
.render(
|
||||
self.reference,
|
||||
folio.pending_amount,
|
||||
folio.currency_id.id,
|
||||
values=values,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -325,10 +325,12 @@ class PmsCheckinPartner(models.Model):
|
||||
record.state = "draft"
|
||||
if record.reservation_id.state == "cancel":
|
||||
record.state = "cancel"
|
||||
elif record.state in ("draft", "cancel"):
|
||||
elif record.state in ("draft", "precheckin", "cancel"):
|
||||
if any(
|
||||
not getattr(record, field)
|
||||
for field in record._checkin_mandatory_fields()
|
||||
for field in record._checkin_mandatory_fields(
|
||||
country=record.nationality_id
|
||||
)
|
||||
):
|
||||
record.state = "draft"
|
||||
else:
|
||||
@@ -610,14 +612,9 @@ class PmsCheckinPartner(models.Model):
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _checkin_mandatory_fields(self, depends=False):
|
||||
def _checkin_mandatory_fields(self, country=False, depends=False):
|
||||
mandatory_fields = [
|
||||
"name",
|
||||
"birthdate_date",
|
||||
"gender",
|
||||
"document_number",
|
||||
"document_type",
|
||||
"document_expedition_date",
|
||||
]
|
||||
# api.depends need "reservation_id.state" in the lambda function
|
||||
if depends:
|
||||
|
||||
@@ -185,9 +185,9 @@ class PmsFolio(models.Model):
|
||||
readonly=True,
|
||||
copy=False,
|
||||
comodel_name="payment.transaction",
|
||||
relation="folio_transaction_rel",
|
||||
relation="payment_transaction_folio_rel",
|
||||
column1="folio_id",
|
||||
column2="transaction_id",
|
||||
column2="payment_transaction_id",
|
||||
)
|
||||
payment_ids = fields.Many2many(
|
||||
string="Bank Payments",
|
||||
@@ -964,7 +964,9 @@ class PmsFolio(models.Model):
|
||||
}
|
||||
record.update(vals)
|
||||
else:
|
||||
journals = record.pms_property_id._get_payment_methods()
|
||||
journals = record.pms_property_id._get_payment_methods(
|
||||
automatic_included=True
|
||||
)
|
||||
paid_out = 0
|
||||
for journal in journals:
|
||||
paid_out += sum(
|
||||
@@ -1955,3 +1957,78 @@ class PmsFolio(models.Model):
|
||||
}
|
||||
self.env["res.partner.id_number"].create(number_values)
|
||||
record.partner_id = partner
|
||||
|
||||
def _create_payment_transaction(self, vals):
|
||||
# Ensure the currencies are the same.
|
||||
currency = self[0].currency_id
|
||||
if any(folio.currency_id != currency for folio in self):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"A transaction can't be linked to folios having different currencies."
|
||||
)
|
||||
)
|
||||
|
||||
# Ensure the partner are the same.
|
||||
partner = self[0].partner_id
|
||||
if any(folio.partner_id != partner for folio in self):
|
||||
raise ValidationError(
|
||||
_("A transaction can't be linked to folios having different partners.")
|
||||
)
|
||||
|
||||
# Try to retrieve the acquirer. However, fallback to the token's acquirer.
|
||||
acquirer_id = vals.get("acquirer_id")
|
||||
acquirer = None
|
||||
payment_token_id = vals.get("payment_token_id")
|
||||
|
||||
if payment_token_id:
|
||||
payment_token = self.env["payment.token"].sudo().browse(payment_token_id)
|
||||
|
||||
# Check payment_token/acquirer matching or take the acquirer from token
|
||||
if acquirer_id:
|
||||
acquirer = self.env["payment.acquirer"].browse(acquirer_id)
|
||||
if payment_token and payment_token.acquirer_id != acquirer:
|
||||
raise ValidationError(
|
||||
_("Invalid token found! Token acquirer %s != %s")
|
||||
% (payment_token.acquirer_id.name, acquirer.name)
|
||||
)
|
||||
if payment_token and payment_token.partner_id != partner:
|
||||
raise ValidationError(
|
||||
_("Invalid token found! Token partner %s != %s")
|
||||
% (payment_token.partner.name, partner.name)
|
||||
)
|
||||
else:
|
||||
acquirer = payment_token.acquirer_id
|
||||
|
||||
# Check an acquirer is there.
|
||||
if not acquirer_id and not acquirer:
|
||||
raise ValidationError(
|
||||
_("A payment acquirer is required to create a transaction.")
|
||||
)
|
||||
|
||||
if not acquirer:
|
||||
acquirer = self.env["payment.acquirer"].browse(acquirer_id)
|
||||
|
||||
# Check a journal is set on acquirer.
|
||||
if not acquirer.journal_id:
|
||||
raise ValidationError(
|
||||
_("A journal must be specified for the acquirer %s.", acquirer.name)
|
||||
)
|
||||
|
||||
if not acquirer_id and acquirer:
|
||||
vals["acquirer_id"] = acquirer.id
|
||||
|
||||
vals.update(
|
||||
{
|
||||
"amount": sum(self.mapped("amount_total")),
|
||||
"currency_id": currency.id,
|
||||
"partner_id": partner.id,
|
||||
"folio_ids": [(6, 0, self.ids)],
|
||||
}
|
||||
)
|
||||
transaction = self.env["payment.transaction"].create(vals)
|
||||
|
||||
# Process directly if payment_token
|
||||
if transaction.payment_token_id:
|
||||
transaction.s2s_do_transaction()
|
||||
|
||||
return transaction
|
||||
|
||||
@@ -151,16 +151,20 @@ class PmsProperty(models.Model):
|
||||
@api.depends_context(
|
||||
"checkin",
|
||||
"checkout",
|
||||
"real_avail",
|
||||
"room_type_id",
|
||||
"ubication_id",
|
||||
"capacity",
|
||||
"amenity_ids",
|
||||
"pricelist_id",
|
||||
"class_id",
|
||||
"overnight_rooms",
|
||||
"current_lines",
|
||||
)
|
||||
def _compute_free_room_ids(self):
|
||||
checkin = self._context["checkin"]
|
||||
checkout = self._context["checkout"]
|
||||
|
||||
if isinstance(checkin, str):
|
||||
checkin = datetime.datetime.strptime(
|
||||
checkin, DEFAULT_SERVER_DATE_FORMAT
|
||||
@@ -175,11 +179,14 @@ class PmsProperty(models.Model):
|
||||
|
||||
pricelist_id = self.env.context.get("pricelist_id", False)
|
||||
room_type_id = self.env.context.get("room_type_id", False)
|
||||
class_id = self._context.get("class_id", False)
|
||||
real_avail = self._context.get("real_avail", False)
|
||||
overnight_rooms = self._context.get("overnight_rooms", False)
|
||||
for pms_property in self:
|
||||
free_rooms = pms_property.get_real_free_rooms(
|
||||
checkin, checkout, current_lines
|
||||
)
|
||||
if pricelist_id:
|
||||
if pricelist_id and not real_avail:
|
||||
# TODO: only closed_departure take account checkout date!
|
||||
domain_rules = [
|
||||
("date", ">=", checkin),
|
||||
@@ -208,6 +215,14 @@ class PmsProperty(models.Model):
|
||||
free_rooms = free_rooms.filtered(
|
||||
lambda x: x.room_type_id.id not in room_types_to_remove
|
||||
)
|
||||
if class_id:
|
||||
free_rooms = free_rooms.filtered(
|
||||
lambda x: x.room_type_id.class_id.id == class_id
|
||||
)
|
||||
if overnight_rooms:
|
||||
free_rooms = free_rooms.filtered(
|
||||
lambda x: x.room_type_id.overnight_room
|
||||
)
|
||||
if len(free_rooms) > 0:
|
||||
pms_property.free_room_ids = free_rooms.ids
|
||||
else:
|
||||
@@ -261,11 +276,14 @@ class PmsProperty(models.Model):
|
||||
@api.depends_context(
|
||||
"checkin",
|
||||
"checkout",
|
||||
"real_avail",
|
||||
"room_type_id",
|
||||
"ubication_id",
|
||||
"capacity",
|
||||
"amenity_ids",
|
||||
"pricelist_id",
|
||||
"class_id",
|
||||
"overnight_rooms",
|
||||
"current_lines",
|
||||
)
|
||||
def _compute_availability(self):
|
||||
@@ -283,12 +301,18 @@ class PmsProperty(models.Model):
|
||||
room_type_id = self.env.context.get("room_type_id", False)
|
||||
pricelist_id = self.env.context.get("pricelist_id", False)
|
||||
current_lines = self.env.context.get("current_lines", [])
|
||||
class_id = self._context.get("class_id", False)
|
||||
real_avail = self._context.get("real_avail", False)
|
||||
overnight_rooms = self._context.get("overnight_rooms", False)
|
||||
pms_property = record.with_context(
|
||||
checkin=checkin,
|
||||
checkout=checkout,
|
||||
room_type_id=room_type_id,
|
||||
current_lines=current_lines,
|
||||
pricelist_id=pricelist_id,
|
||||
class_id=class_id,
|
||||
real_avail=real_avail,
|
||||
overnight_rooms=overnight_rooms,
|
||||
)
|
||||
count_free_rooms = len(pms_property.free_room_ids)
|
||||
if current_lines and not isinstance(current_lines, list):
|
||||
@@ -305,7 +329,7 @@ class PmsProperty(models.Model):
|
||||
pricelist = False
|
||||
if pricelist_id:
|
||||
pricelist = self.env["product.pricelist"].browse(pricelist_id)
|
||||
if pricelist and pricelist.availability_plan_id:
|
||||
if pricelist and pricelist.availability_plan_id and not real_avail:
|
||||
domain_rules.append(
|
||||
("availability_plan_id", "=", pricelist.availability_plan_id.id)
|
||||
)
|
||||
@@ -404,12 +428,14 @@ class PmsProperty(models.Model):
|
||||
dt = dt.replace(tzinfo=None)
|
||||
return dt
|
||||
|
||||
def _get_payment_methods(self):
|
||||
def _get_payment_methods(self, automatic_included=False):
|
||||
# We use automatic_included to True to see absolutely
|
||||
# all the journals with associated payments, if it is
|
||||
# false, we will only see those journals that can be used
|
||||
# to pay manually
|
||||
self.ensure_one()
|
||||
payment_methods = self.env["account.journal"].search(
|
||||
[
|
||||
("allowed_pms_payments", "=", True),
|
||||
"&",
|
||||
("type", "in", ["cash", "bank"]),
|
||||
"|",
|
||||
("pms_property_ids", "in", self.id),
|
||||
@@ -422,6 +448,8 @@ class PmsProperty(models.Model):
|
||||
("company_id", "=", False),
|
||||
]
|
||||
)
|
||||
if not automatic_included:
|
||||
payment_methods = payment_methods.filtered(lambda p: p.allowed_pms_payments)
|
||||
return payment_methods
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -643,7 +643,6 @@ class PmsReservation(models.Model):
|
||||
comodel_name="res.partner",
|
||||
inverse_name="reservation_possible_customer_id",
|
||||
)
|
||||
|
||||
is_mail_send = fields.Boolean(string="Mail Sent", default=False)
|
||||
|
||||
is_modified_reservation = fields.Boolean(
|
||||
@@ -652,7 +651,10 @@ class PmsReservation(models.Model):
|
||||
readonly=False,
|
||||
store=True,
|
||||
)
|
||||
|
||||
overnight_room = fields.Boolean(
|
||||
related="room_type_id.overnight_room",
|
||||
store=True,
|
||||
)
|
||||
lang = fields.Many2one(
|
||||
string="Language", comodel_name="res.lang", compute="_compute_lang"
|
||||
)
|
||||
@@ -804,6 +806,7 @@ class PmsReservation(models.Model):
|
||||
"reservation_line_ids.room_id",
|
||||
"reservation_line_ids.occupies_availability",
|
||||
"preferred_room_id",
|
||||
"room_type_id",
|
||||
"pricelist_id",
|
||||
"pms_property_id",
|
||||
)
|
||||
@@ -812,7 +815,9 @@ class PmsReservation(models.Model):
|
||||
if reservation.checkin and reservation.checkout:
|
||||
if reservation.overbooking or reservation.state in ("cancel"):
|
||||
reservation.allowed_room_ids = self.env["pms.room"].search(
|
||||
[("active", "=", True)]
|
||||
[
|
||||
("active", "=", True),
|
||||
]
|
||||
)
|
||||
return
|
||||
pms_property = reservation.pms_property_id
|
||||
@@ -822,9 +827,12 @@ class PmsReservation(models.Model):
|
||||
room_type_id=False, # Allows to choose any available room
|
||||
current_lines=reservation.reservation_line_ids.ids,
|
||||
pricelist_id=reservation.pricelist_id.id,
|
||||
class_id=reservation.room_type_id.class_id.id
|
||||
if reservation.room_type_id
|
||||
else False,
|
||||
real_avail=True,
|
||||
)
|
||||
reservation.allowed_room_ids = pms_property.free_room_ids
|
||||
|
||||
else:
|
||||
reservation.allowed_room_ids = False
|
||||
|
||||
@@ -1045,6 +1053,7 @@ class PmsReservation(models.Model):
|
||||
True
|
||||
if (
|
||||
record.reservation_type != "out"
|
||||
and record.overnight_room
|
||||
and record.state in ["draft", "confirm", "arrival_delayed"]
|
||||
and record.checkin <= fields.Date.today()
|
||||
)
|
||||
@@ -1197,9 +1206,11 @@ class PmsReservation(models.Model):
|
||||
reservation.commission_amount = 0
|
||||
|
||||
# REVIEW: Dont run with set room_type_id -> room_id(compute)-> No set adults¿?
|
||||
@api.depends("preferred_room_id", "reservation_type")
|
||||
@api.depends("preferred_room_id", "reservation_type", "overnight_room")
|
||||
def _compute_adults(self):
|
||||
for reservation in self:
|
||||
if not reservation.overnight_room:
|
||||
reservation.adults = 0
|
||||
if reservation.preferred_room_id and reservation.reservation_type != "out":
|
||||
if reservation.adults == 0:
|
||||
reservation.adults = reservation.preferred_room_id.capacity
|
||||
@@ -1384,7 +1395,7 @@ class PmsReservation(models.Model):
|
||||
|
||||
def _compute_checkin_partner_count(self):
|
||||
for record in self:
|
||||
if record.reservation_type != "out":
|
||||
if record.reservation_type != "out" and record.overnight_room:
|
||||
record.checkin_partner_count = len(record.checkin_partner_ids)
|
||||
record.checkin_partner_pending_count = record.adults - len(
|
||||
record.checkin_partner_ids
|
||||
@@ -1488,6 +1499,7 @@ class PmsReservation(models.Model):
|
||||
return [
|
||||
("state", "in", ("draft", "confirm", "arrival_delayed")),
|
||||
("checkin", "<=", today),
|
||||
("adults", ">", 0),
|
||||
]
|
||||
|
||||
def _search_allowed_checkout(self, operator, value):
|
||||
@@ -1505,6 +1517,7 @@ class PmsReservation(models.Model):
|
||||
return [
|
||||
("state", "in", ("onboard", "departure_delayed")),
|
||||
("checkout", ">=", today),
|
||||
("adults", ">", 0),
|
||||
]
|
||||
|
||||
def _search_allowed_cancel(self, operator, value):
|
||||
@@ -2014,7 +2027,9 @@ class PmsReservation(models.Model):
|
||||
("checkin", "<", fields.Date.today()),
|
||||
]
|
||||
)
|
||||
arrival_delayed_reservations.state = "arrival_delayed"
|
||||
for record in arrival_delayed_reservations:
|
||||
if record.overnight_room:
|
||||
record.state = "arrival_delayed"
|
||||
|
||||
@api.model
|
||||
def auto_departure_delayed(self):
|
||||
@@ -2026,8 +2041,11 @@ class PmsReservation(models.Model):
|
||||
]
|
||||
)
|
||||
for reservation in reservations:
|
||||
if reservation.checkout_datetime <= fields.Datetime.now():
|
||||
reservations.state = "departure_delayed"
|
||||
if reservation.overnight_room:
|
||||
if reservation.checkout_datetime <= fields.Datetime.now():
|
||||
reservations.state = "departure_delayed"
|
||||
else:
|
||||
reservation.state = "done"
|
||||
|
||||
def preview_reservation(self):
|
||||
self.ensure_one()
|
||||
|
||||
@@ -112,7 +112,10 @@ class PmsReservationLine(models.Model):
|
||||
store=True,
|
||||
compute="_compute_impacts_quota",
|
||||
)
|
||||
|
||||
overnight_room = fields.Boolean(
|
||||
related="reservation_id.overnight_room",
|
||||
store=True,
|
||||
)
|
||||
_sql_constraints = [
|
||||
(
|
||||
"rule_availability",
|
||||
@@ -175,6 +178,8 @@ class PmsReservationLine(models.Model):
|
||||
free_room_select = True if reservation.preferred_room_id else False
|
||||
|
||||
# we get the rooms available for the entire stay
|
||||
# (real_avail if True if the reservation was created with
|
||||
# specific room selected)
|
||||
pms_property = line.pms_property_id
|
||||
pms_property = pms_property.with_context(
|
||||
checkin=reservation.checkin,
|
||||
@@ -184,6 +189,7 @@ class PmsReservationLine(models.Model):
|
||||
else False,
|
||||
current_lines=reservation.reservation_line_ids.ids,
|
||||
pricelist_id=reservation.pricelist_id.id,
|
||||
real_avail=free_room_select,
|
||||
)
|
||||
rooms_available = pms_property.free_room_ids
|
||||
|
||||
|
||||
@@ -86,6 +86,10 @@ class PmsRoomType(models.Model):
|
||||
"Use `-1` for managing no quota.",
|
||||
default=-1,
|
||||
)
|
||||
overnight_room = fields.Boolean(
|
||||
related="class_id.overnight",
|
||||
store=True,
|
||||
)
|
||||
|
||||
def name_get(self):
|
||||
result = []
|
||||
|
||||
@@ -57,6 +57,11 @@ class PmsRoomTypeClass(models.Model):
|
||||
help="Room type class identification code",
|
||||
required=True,
|
||||
)
|
||||
overnight = fields.Boolean(
|
||||
string="Use for overnight stays",
|
||||
help="Set False if if these types of spaces are not used for overnight stays",
|
||||
default=True,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def get_unique_by_property_code(self, pms_property_id, default_code=None):
|
||||
|
||||
@@ -299,6 +299,12 @@ class PmsService(models.Model):
|
||||
day_qty = 1
|
||||
if service.reservation_id and service.product_id:
|
||||
reservation = service.reservation_id
|
||||
# REVIEW: review method dependencies, reservation_line_ids
|
||||
# instead of checkin/checkout
|
||||
if not reservation.checkin or not reservation.checkout:
|
||||
if not service.service_line_ids:
|
||||
service.service_line_ids = False
|
||||
continue
|
||||
product = service.product_id
|
||||
consumed_on = product.consumed_on
|
||||
if product.per_day:
|
||||
|
||||
@@ -29,6 +29,15 @@ class TestPmsReservations(TestPms):
|
||||
}
|
||||
)
|
||||
|
||||
self.room_type_triple = self.env["pms.room.type"].create(
|
||||
{
|
||||
"pms_property_ids": [self.pms_property1.id],
|
||||
"name": "Triple Test",
|
||||
"default_code": "TRP_Test",
|
||||
"class_id": self.room_type_class1.id,
|
||||
}
|
||||
)
|
||||
|
||||
# create rooms
|
||||
self.room1 = self.env["pms.room"].create(
|
||||
{
|
||||
@@ -59,6 +68,16 @@ class TestPmsReservations(TestPms):
|
||||
"extra_beds_allowed": 1,
|
||||
}
|
||||
)
|
||||
|
||||
self.room4 = self.env["pms.room"].create(
|
||||
{
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"name": "Triple 104",
|
||||
"room_type_id": self.room_type_triple.id,
|
||||
"capacity": 3,
|
||||
"extra_beds_allowed": 1,
|
||||
}
|
||||
)
|
||||
self.partner1 = self.env["res.partner"].create(
|
||||
{
|
||||
"firstname": "Jaime",
|
||||
@@ -1645,6 +1664,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkin": fields.date.today(),
|
||||
"checkout": fields.date.today() + datetime.timedelta(days=3),
|
||||
"partner_id": self.partner1.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1678,6 +1698,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkin": fields.date.today() + datetime.timedelta(days=300),
|
||||
"checkout": fields.date.today() + datetime.timedelta(days=305),
|
||||
"partner_id": self.partner1.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
r = reservation.checkin
|
||||
@@ -1695,8 +1716,8 @@ class TestPmsReservations(TestPms):
|
||||
Check available rooms after creating a reservation.
|
||||
-----------
|
||||
Create an availability rule, create a reservation,
|
||||
and then check that the allopwed_room_ids field of the
|
||||
reservation and the room_type_id.room_ids field of the
|
||||
and then check that the allowed_room_ids field filtered by room
|
||||
type of the reservation and the room_type_id.room_ids field of the
|
||||
availability rule match.
|
||||
"""
|
||||
availability_rule = self.env["pms.availability.plan.rule"].create(
|
||||
@@ -1718,8 +1739,10 @@ class TestPmsReservations(TestPms):
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
reservation.allowed_room_ids,
|
||||
availability_rule.room_type_id.room_ids,
|
||||
reservation.allowed_room_ids.filtered(
|
||||
lambda r: r.room_type_id.id == availability_rule.room_type_id.id
|
||||
).ids,
|
||||
availability_rule.room_type_id.room_ids.ids,
|
||||
"Rooms allowed don't match",
|
||||
)
|
||||
|
||||
@@ -1750,6 +1773,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkin": fields.date.today() + datetime.timedelta(days=150),
|
||||
"checkout": fields.date.today() + datetime.timedelta(days=152),
|
||||
"agency_id": agency.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1794,6 +1818,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkin": fields.date.today() + datetime.timedelta(days=150),
|
||||
"checkout": fields.date.today() + datetime.timedelta(days=152),
|
||||
"agency_id": agency.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
@@ -1815,6 +1840,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkin": fields.date.today() + datetime.timedelta(days=150),
|
||||
"checkout": fields.date.today() + datetime.timedelta(days=152),
|
||||
"partner_id": self.partner1.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1873,6 +1899,7 @@ class TestPmsReservations(TestPms):
|
||||
"allowed_checkin": True,
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"adults": 3,
|
||||
"room_type_id": self.room_type_triple.id,
|
||||
}
|
||||
)
|
||||
self.checkin1 = self.env["pms.checkin.partner"].create(
|
||||
@@ -1916,6 +1943,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkout": fields.date.today(),
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"partner_id": self.host1.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -2294,6 +2322,7 @@ class TestPmsReservations(TestPms):
|
||||
"partner_id": self.host1.id,
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"adults": 3,
|
||||
"room_type_id": self.room_type_triple.id,
|
||||
}
|
||||
)
|
||||
self.checkin1 = self.env["pms.checkin.partner"].create(
|
||||
@@ -2351,6 +2380,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkout": "2014-01-17",
|
||||
"partner_id": self.host1.id,
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"room_type_id": self.room_type_triple.id,
|
||||
"adults": 3,
|
||||
}
|
||||
)
|
||||
@@ -2404,6 +2434,7 @@ class TestPmsReservations(TestPms):
|
||||
"partner_id": host.id,
|
||||
"allowed_checkout": True,
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -2435,6 +2466,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkout": "2014-01-17",
|
||||
"pms_property_id": self.pms_property1.id,
|
||||
"folio_id": self.folio1.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
# ACT AND ASSERT
|
||||
@@ -2472,6 +2504,7 @@ class TestPmsReservations(TestPms):
|
||||
"checkin": fields.date.today() + datetime.timedelta(days=150),
|
||||
"checkout": fields.date.today() + datetime.timedelta(days=152),
|
||||
"agency_id": agency.id,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -73,6 +73,116 @@
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="portal_folio_payment" name="Folio Payment">
|
||||
<div
|
||||
class="row"
|
||||
t-if="not tx_ids and folio.state in ('confirm','done') and folio.payment_state in ('not_paid', 'partial') and folio.amount_total"
|
||||
id="portal_pay"
|
||||
>
|
||||
<div class="modal fade" id="pay_with" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Pay with</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div
|
||||
t-if="pms or acquirers"
|
||||
id="payment_method"
|
||||
class="text-left col-md-13"
|
||||
>
|
||||
<t t-call="payment.payment_tokens_list">
|
||||
<t t-set="mode" t-value="'payment'" />
|
||||
<t
|
||||
t-set="partner_id"
|
||||
t-value="folio.partner_id.id if request.env.user._is_public() else request.env.user.partner_id.id"
|
||||
/>
|
||||
<t
|
||||
t-set="success_url"
|
||||
t-value="folio.get_portal_url()"
|
||||
/>
|
||||
<t
|
||||
t-set="error_url"
|
||||
t-value="folio.get_portal_url()"
|
||||
/>
|
||||
<t
|
||||
t-set="access_token"
|
||||
t-value="access_token or ''"
|
||||
/>
|
||||
<t t-set="callback_method" t-value="''" />
|
||||
<t
|
||||
t-set="form_action"
|
||||
t-value="'/folio/pay/' + str(folio.id) + '/s2s_token_tx/'"
|
||||
/>
|
||||
<t
|
||||
t-set="prepare_tx_url"
|
||||
t-value="'/folio/pay/' + str(folio.id) + '/form_tx/'"
|
||||
/>
|
||||
<t t-set="submit_txt">Pay Now</t>
|
||||
<t t-set="icon_class" t-value="'fa-lock'" />
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="portal_folio_page_payment" name="Payment on My Folios">
|
||||
<t
|
||||
t-set="tx_ids"
|
||||
t-value="folio.transaction_ids.filtered(lambda tx: tx.state in ('pending', 'authorized', 'done'))"
|
||||
/>
|
||||
<t
|
||||
t-set="pending_manual_txs"
|
||||
t-value="tx_ids.filtered(lambda tx: tx.state == 'pending' and tx.acquirer_id.provider in ('transfer', 'manual'))"
|
||||
/>
|
||||
<div>
|
||||
<a
|
||||
href="#"
|
||||
t-if="folio.state in ('confirm','done') and folio.payment_state in ('not_paid', 'partial') and folio.amount_total and (pending_manual_txs or not tx_ids)"
|
||||
class="btn btn-primary btn-block mb-2"
|
||||
data-toggle="modal"
|
||||
data-target="#pay_with"
|
||||
>
|
||||
<i class="fa fa-fw fa-arrow-circle-right" /> Pay Now
|
||||
</a>
|
||||
<div
|
||||
t-if="tx_ids and not pending_manual_txs and folio.payment_state not in ('paid', 'in_payment')"
|
||||
class="alert alert-info py-1 mb-2"
|
||||
>
|
||||
<i class="fa fa-fw fa-check-circle" /> Pending
|
||||
</div>
|
||||
<div
|
||||
t-if="folio.payment_state in ('paid', 'in_payment')"
|
||||
class="alert alert-success py-1 mb-2"
|
||||
>
|
||||
<i class="fa fa-fw fa-check-circle" /> Paid
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<t
|
||||
t-set="tx_ids"
|
||||
t-value="folio.transaction_ids.filtered(lambda tx: tx.state in ('authorized', 'done'))"
|
||||
/>
|
||||
<div
|
||||
t-if="not tx_ids and folio.state in('confirm','done') and folio.payment_state in ('not_paid', 'partial') and folio.amount_total"
|
||||
id="portal_pay"
|
||||
>
|
||||
<div t-if="pms or acquirers" id="payment_method">
|
||||
<t t-call="pms.portal_folio_payment" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<template
|
||||
id="folio_portal_template"
|
||||
@@ -94,7 +204,10 @@
|
||||
<ul
|
||||
class="list-group list-group-flush flex-wrap flex-row flex-lg-column"
|
||||
>
|
||||
<li class="list-group-item">
|
||||
<li class="list-group-item flex-grow-1">
|
||||
<div>
|
||||
<div t-call="pms.portal_folio_page_payment" />
|
||||
</div>
|
||||
<div class="o_download_pdf btn-toolbar flex-sm-nowrap">
|
||||
<div class="btn-group mr-1 mb-1">
|
||||
<a
|
||||
|
||||
12
pms/views/payment_transaction_views.xml
Normal file
12
pms/views/payment_transaction_views.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="payment_transaction_inherit_view_form" model="ir.ui.view">
|
||||
<field name="model">payment.transaction</field>
|
||||
<field name="inherit_id" ref="payment.transaction_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='date']" position="before">
|
||||
<field name="folio_ids" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -91,7 +91,11 @@
|
||||
<field name="property_modified_template" />
|
||||
<field name="property_canceled_template" />
|
||||
</group>
|
||||
<group string="Mail Information" colspan="4">
|
||||
<group
|
||||
string="Mail Information"
|
||||
name="mail_information"
|
||||
colspan="4"
|
||||
>
|
||||
<field
|
||||
name="mail_information"
|
||||
string="Aditional Mail Information"
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
/>
|
||||
<field name="name" />
|
||||
<field name="default_code" />
|
||||
<field name="overnight" />
|
||||
</group>
|
||||
</group>
|
||||
<group colspan="2">
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<group name="room_ids_group">
|
||||
<field name="room_ids" widget="many2many_tags" />
|
||||
<field name="total_rooms_count" />
|
||||
<field name="default_max_avail" />
|
||||
<field name="default_quota" />
|
||||
</group>
|
||||
<group name="accounting_group">
|
||||
<field
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
@@ -872,145 +872,161 @@ class AvailabilityWizard(models.TransientModel):
|
||||
|
||||
return new_items
|
||||
|
||||
def continue_massive_changes(self):
|
||||
self.apply_massive_changes()
|
||||
return {
|
||||
"name": _("Massive changes on Pricelist and Availability Plans"),
|
||||
"res_model": "pms.massive.changes.wizard",
|
||||
"type": "ir.actions.act_window",
|
||||
"view_id": self.env.ref("pms.massive_changes_wizard").id,
|
||||
"target": "new",
|
||||
"view_mode": "form",
|
||||
"context": {
|
||||
"default_massive_changes_on": self.massive_changes_on,
|
||||
"default_start_date": self.start_date,
|
||||
"default_end_date": self.end_date,
|
||||
"default_pms_property_ids": [(6, 0, self.pms_property_ids.ids)],
|
||||
"default_pricelist_ids": [(6, 0, self.pricelist_ids.ids)],
|
||||
"default_availability_plan_ids": [
|
||||
(6, 0, self.availability_plan_ids.ids)
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
def save_and_close(self):
|
||||
items = self.apply_massive_changes()
|
||||
if self.massive_changes_on == "pricelist" and not self.pricelist_readonly:
|
||||
action = {
|
||||
"view": self.env.ref("pms.product_pricelist_item_action2").read()[0]
|
||||
}
|
||||
action["view"]["domain"] = [("id", "in", items)]
|
||||
return action["view"]
|
||||
|
||||
if self.massive_changes_on == "availability_plan" and not self.avail_readonly:
|
||||
action = {
|
||||
"view": self.env.ref(
|
||||
"pms.availability_plan_rule_view_tree_action"
|
||||
).read()[0]
|
||||
}
|
||||
action["view"]["domain"] = [("id", "in", items)]
|
||||
return action["view"]
|
||||
|
||||
def apply_massive_changes(self):
|
||||
self.ensure_one()
|
||||
self.pricelist_items_to_overwrite.unlink()
|
||||
week_days_to_apply = (
|
||||
self.apply_on_monday,
|
||||
self.apply_on_tuesday,
|
||||
self.apply_on_wednesday,
|
||||
self.apply_on_thursday,
|
||||
self.apply_on_friday,
|
||||
self.apply_on_saturday,
|
||||
self.apply_on_sunday,
|
||||
)
|
||||
|
||||
for record in self:
|
||||
record.pricelist_items_to_overwrite.unlink()
|
||||
week_days_to_apply = (
|
||||
record.apply_on_monday,
|
||||
record.apply_on_tuesday,
|
||||
record.apply_on_wednesday,
|
||||
record.apply_on_thursday,
|
||||
record.apply_on_friday,
|
||||
record.apply_on_saturday,
|
||||
record.apply_on_sunday,
|
||||
)
|
||||
# dates between start and end (both included)
|
||||
items = []
|
||||
for date in [
|
||||
self.start_date + datetime.timedelta(days=x)
|
||||
for x in range(0, (self.end_date - self.start_date).days + 1)
|
||||
]:
|
||||
|
||||
# dates between start and end (both included)
|
||||
items = []
|
||||
for date in [
|
||||
record.start_date + datetime.timedelta(days=x)
|
||||
for x in range(0, (record.end_date - record.start_date).days + 1)
|
||||
]:
|
||||
if (
|
||||
not self.apply_on_all_week
|
||||
and not week_days_to_apply[date.timetuple()[6]]
|
||||
):
|
||||
continue
|
||||
|
||||
if not self.room_type_ids:
|
||||
room_types = self.env["pms.room.type"].search(
|
||||
[
|
||||
"|",
|
||||
("pms_property_ids", "=", False),
|
||||
("pms_property_ids", "in", self.pms_property_ids.ids),
|
||||
]
|
||||
)
|
||||
else:
|
||||
room_types = self.room_type_ids
|
||||
|
||||
for pms_property in self.pms_property_ids:
|
||||
if (
|
||||
not record.apply_on_all_week
|
||||
and not week_days_to_apply[date.timetuple()[6]]
|
||||
self.massive_changes_on == "pricelist"
|
||||
and self.apply_pricelists_on == "room_types"
|
||||
):
|
||||
continue
|
||||
|
||||
if not record.room_type_ids:
|
||||
room_types = self.env["pms.room.type"].search(
|
||||
[
|
||||
"|",
|
||||
("pms_property_ids", "=", False),
|
||||
("pms_property_ids", "in", record.pms_property_ids.ids),
|
||||
]
|
||||
new_items = self.create_pricelists_items_room_types(
|
||||
room_types,
|
||||
self.pricelist_ids,
|
||||
self.price,
|
||||
self.min_quantity,
|
||||
pms_property,
|
||||
date,
|
||||
self.date_types,
|
||||
)
|
||||
else:
|
||||
room_types = record.room_type_ids
|
||||
items = items + new_items if new_items else items
|
||||
|
||||
for pms_property in record.pms_property_ids:
|
||||
if (
|
||||
record.massive_changes_on == "pricelist"
|
||||
and record.apply_pricelists_on == "room_types"
|
||||
):
|
||||
new_items = self.create_pricelists_items_room_types(
|
||||
room_types,
|
||||
record.pricelist_ids,
|
||||
record.price,
|
||||
record.min_quantity,
|
||||
pms_property,
|
||||
date,
|
||||
record.date_types,
|
||||
)
|
||||
items = items + new_items if new_items else items
|
||||
elif (
|
||||
self.massive_changes_on == "pricelist"
|
||||
and self.apply_pricelists_on == "board_services"
|
||||
):
|
||||
new_items = self.create_pricelists_items_board_services(
|
||||
self.board_service_room_type_ids,
|
||||
self.pricelist_ids,
|
||||
self.board_service,
|
||||
self.price,
|
||||
self.min_quantity,
|
||||
pms_property,
|
||||
self.date_types,
|
||||
date,
|
||||
)
|
||||
items = items + new_items if new_items else items
|
||||
|
||||
elif (
|
||||
record.massive_changes_on == "pricelist"
|
||||
and record.apply_pricelists_on == "board_services"
|
||||
):
|
||||
new_items = self.create_pricelists_items_board_services(
|
||||
record.board_service_room_type_ids,
|
||||
record.pricelist_ids,
|
||||
record.board_service,
|
||||
record.price,
|
||||
record.min_quantity,
|
||||
pms_property,
|
||||
record.date_types,
|
||||
date,
|
||||
)
|
||||
items = items + new_items if new_items else items
|
||||
elif (
|
||||
self.massive_changes_on == "pricelist"
|
||||
and self.apply_pricelists_on == "service"
|
||||
):
|
||||
for pricelist in self.pricelist_ids:
|
||||
if self.service:
|
||||
vals = {
|
||||
"pricelist_id": pricelist.id,
|
||||
"compute_price": "fixed",
|
||||
"applied_on": "0_product_variant",
|
||||
"product_id": self.service.id,
|
||||
"fixed_price": self.price,
|
||||
"min_quantity": self.min_quantity,
|
||||
"pms_property_ids": [pms_property.id],
|
||||
}
|
||||
vals = self.generate_dates_vals(self.date_types, vals, date)
|
||||
|
||||
elif (
|
||||
record.massive_changes_on == "pricelist"
|
||||
and record.apply_pricelists_on == "service"
|
||||
):
|
||||
for pricelist in record.pricelist_ids:
|
||||
if record.service:
|
||||
vals = {
|
||||
"pricelist_id": pricelist.id,
|
||||
"compute_price": "fixed",
|
||||
"applied_on": "0_product_variant",
|
||||
"product_id": record.service.id,
|
||||
"fixed_price": record.price,
|
||||
"min_quantity": record.min_quantity,
|
||||
"pms_property_ids": [pms_property.id],
|
||||
}
|
||||
vals = self.generate_dates_vals(
|
||||
record.date_types, vals, date
|
||||
)
|
||||
pricelist_item = self.env["product.pricelist.item"].create(
|
||||
vals
|
||||
)
|
||||
items.append(pricelist_item.id)
|
||||
elif self.massive_changes_on == "availability_plan":
|
||||
|
||||
pricelist_item = self.env[
|
||||
"product.pricelist.item"
|
||||
].create(vals)
|
||||
items.append(pricelist_item.id)
|
||||
elif record.massive_changes_on == "availability_plan":
|
||||
|
||||
new_items = self.create_availability_plans_rules(
|
||||
room_types,
|
||||
record.availability_plan_ids,
|
||||
record.min_stay,
|
||||
record.apply_min_stay,
|
||||
record.min_stay_arrival,
|
||||
record.apply_min_stay_arrival,
|
||||
record.max_stay,
|
||||
record.apply_max_stay,
|
||||
record.max_stay_arrival,
|
||||
record.apply_max_stay_arrival,
|
||||
record.quota,
|
||||
record.apply_quota,
|
||||
record.max_avail,
|
||||
record.apply_max_avail,
|
||||
record.closed,
|
||||
record.apply_closed,
|
||||
record.closed_arrival,
|
||||
record.apply_closed_arrival,
|
||||
record.closed_departure,
|
||||
record.apply_closed_departure,
|
||||
date,
|
||||
record.rules_to_overwrite,
|
||||
pms_property,
|
||||
)
|
||||
items = items + new_items if new_items else items
|
||||
if (
|
||||
record.massive_changes_on == "pricelist"
|
||||
and not record.pricelist_readonly
|
||||
):
|
||||
action = {
|
||||
"view": self.env.ref("pms.product_pricelist_item_action2").read()[0]
|
||||
}
|
||||
action["view"]["domain"] = [("id", "in", items)]
|
||||
return action["view"]
|
||||
|
||||
if (
|
||||
record.massive_changes_on == "availability_plan"
|
||||
and not record.avail_readonly
|
||||
):
|
||||
action = {
|
||||
"view": self.env.ref(
|
||||
"pms.availability_plan_rule_view_tree_action"
|
||||
).read()[0]
|
||||
}
|
||||
action["view"]["domain"] = [("id", "in", items)]
|
||||
return action["view"]
|
||||
new_items = self.create_availability_plans_rules(
|
||||
room_types,
|
||||
self.availability_plan_ids,
|
||||
self.min_stay,
|
||||
self.apply_min_stay,
|
||||
self.min_stay_arrival,
|
||||
self.apply_min_stay_arrival,
|
||||
self.max_stay,
|
||||
self.apply_max_stay,
|
||||
self.max_stay_arrival,
|
||||
self.apply_max_stay_arrival,
|
||||
self.quota,
|
||||
self.apply_quota,
|
||||
self.max_avail,
|
||||
self.apply_max_avail,
|
||||
self.closed,
|
||||
self.apply_closed,
|
||||
self.closed_arrival,
|
||||
self.apply_closed_arrival,
|
||||
self.closed_departure,
|
||||
self.apply_closed_departure,
|
||||
date,
|
||||
self.rules_to_overwrite,
|
||||
pms_property,
|
||||
)
|
||||
items = items + new_items if new_items else items
|
||||
return items
|
||||
|
||||
@@ -474,8 +474,14 @@
|
||||
</field>
|
||||
<footer>
|
||||
<button
|
||||
name="apply_massive_changes"
|
||||
string="Apply changes"
|
||||
name="save_and_close"
|
||||
string="Apply and close"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
/>
|
||||
<button
|
||||
name="continue_massive_changes"
|
||||
string="Apply and continue"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
/>
|
||||
|
||||
@@ -179,6 +179,7 @@ class ReservationSplitJoinSwapWizard(models.TransientModel):
|
||||
room_type_id=False, # Allows to choose any available room
|
||||
current_lines=record.reservation_id.reservation_line_ids.ids,
|
||||
pricelist_id=record.reservation_id.pricelist_id.id,
|
||||
real_avail=True,
|
||||
)
|
||||
rooms_available = pms_property.free_room_ids
|
||||
|
||||
@@ -224,6 +225,8 @@ class ReservationSplitJoinSwapWizard(models.TransientModel):
|
||||
).date(),
|
||||
current_lines=reservation.reservation_line_ids.ids,
|
||||
pricelist_id=reservation.pricelist_id.id,
|
||||
real_avail=True,
|
||||
class_id=reservation.room_type_id.class_id.id,
|
||||
)
|
||||
rooms_available = pms_property.free_room_ids
|
||||
|
||||
@@ -242,6 +245,7 @@ class ReservationSplitJoinSwapWizard(models.TransientModel):
|
||||
checkout=reservation.checkout,
|
||||
current_lines=reservation.reservation_line_ids.ids,
|
||||
pricelist_id=reservation.pricelist_id.id,
|
||||
real_avail=True,
|
||||
)
|
||||
rooms_available = pms_property.free_room_ids
|
||||
|
||||
@@ -360,6 +364,8 @@ class ReservationLinesToSplit(models.TransientModel):
|
||||
checkout=line.date + datetime.timedelta(days=1),
|
||||
room_type_id=False, # Allows to choose any available room
|
||||
pricelist_id=reservation.pricelist_id.id,
|
||||
real_avail=True,
|
||||
class_id=reservation.room_type_id.class_id.id,
|
||||
)
|
||||
rooms_available = pms_property.free_room_ids
|
||||
rooms_available += line.room_id
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
{
|
||||
"name": "PMS Spanish Adaptation",
|
||||
"version": "14.0.2.1.1",
|
||||
"version": "14.0.2.2.0",
|
||||
"author": "Commit [Sun], Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"application": True,
|
||||
|
||||
@@ -136,6 +136,7 @@ msgid "Detailed message"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms_l10n_es
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_checkin_partner__display_name
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_ine_tourism_type_category__display_name
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_ine_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_log_institution_traveller_report__display_name
|
||||
@@ -218,6 +219,7 @@ msgid "Hotel category in the Ministry of Tourism. Used for INE statistics."
|
||||
msgstr ""
|
||||
|
||||
#. module: pms_l10n_es
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_checkin_partner__id
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_ine_tourism_type_category__id
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_ine_wizard__id
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_log_institution_traveller_report__id
|
||||
@@ -288,6 +290,7 @@ msgid "Institution user"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms_l10n_es
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_checkin_partner____last_update
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_ine_tourism_type_category____last_update
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_ine_wizard____last_update
|
||||
#: model:ir.model.fields,field_description:pms_l10n_es.field_pms_log_institution_traveller_report____last_update
|
||||
@@ -345,6 +348,11 @@ msgstr ""
|
||||
msgid "Mossos_d'esquadra (soon)"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms_l10n_es
|
||||
#: model:ir.model,name:pms_l10n_es.model_pms_checkin_partner
|
||||
msgid "Partner Checkins"
|
||||
msgstr ""
|
||||
|
||||
#. module: pms_l10n_es
|
||||
#: model:ir.model.fields,help:pms_l10n_es.field_pms_property__institution_password
|
||||
msgid "Password provided by institution to send the data."
|
||||
|
||||
@@ -6,3 +6,4 @@ from . import res_country_state
|
||||
from . import pms_ine_tourism_type_category
|
||||
from . import pms_room
|
||||
from . import res_partner
|
||||
from . import pms_checkin_partner
|
||||
|
||||
30
pms_l10n_es/models/pms_checkin_partner.py
Normal file
30
pms_l10n_es/models/pms_checkin_partner.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
CODE_SPAIN = "ES"
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PmsCheckinParnert(models.Model):
|
||||
_inherit = "pms.checkin.partner"
|
||||
|
||||
@api.model
|
||||
def _checkin_mandatory_fields(self, country=False, depends=False):
|
||||
mandatory_fields = super(PmsCheckinParnert, self)._checkin_mandatory_fields(
|
||||
depends
|
||||
)
|
||||
mandatory_fields.extend(
|
||||
[
|
||||
"birthdate_date",
|
||||
"gender",
|
||||
"document_number",
|
||||
"document_type",
|
||||
"document_expedition_date",
|
||||
"nationality_id",
|
||||
]
|
||||
)
|
||||
if depends or (country and country.code == CODE_SPAIN):
|
||||
mandatory_fields.append("state_id")
|
||||
return mandatory_fields
|
||||
@@ -101,11 +101,11 @@ class TravellerReport(models.TransientModel):
|
||||
for line in lines:
|
||||
content += "2"
|
||||
# [P|N|..]
|
||||
if line.document_type.name != "D":
|
||||
if line.document_type.code != "D":
|
||||
content += "||" + line.document_number.upper() + "|"
|
||||
else:
|
||||
content += "|" + line.document_number.upper() + "||"
|
||||
content += line.document_type.name + "|"
|
||||
content += line.document_type.code + "|"
|
||||
content += line.document_expedition_date.strftime("%Y%m%d") + "|"
|
||||
content += line.lastname.upper() + "|"
|
||||
if line.lastname2:
|
||||
|
||||
Reference in New Issue
Block a user