[IMP]pms: added pay button in folio portal

This commit is contained in:
braisab
2021-10-22 21:55:04 +02:00
parent 41f34ca439
commit 23f9f5cb17
3 changed files with 307 additions and 0 deletions

View File

@@ -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,128 @@ 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_invoice_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",

View File

@@ -1955,3 +1955,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

View File

@@ -77,6 +77,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"
@@ -99,6 +209,9 @@
class="list-group list-group-flush flex-wrap flex-row flex-lg-column"
>
<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 flex-grow-1 mr-1 mb-1">
<a