[IMP] payment: payment methods improvements
closes odoo/odoo#136525 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
@@ -79,7 +79,7 @@
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//div[@id='invoice_content']//div[hasclass('o_portal_html_view')]" position="before">
|
||||
<div t-if="invoice.transaction_ids and invoice.amount_total and not success and not error" class="o_account_payment_tx_status" t-att-data-invoice-id="invoice.id">
|
||||
<div t-if="invoice.get_portal_last_transaction() and invoice.amount_total and not success and not error" class="o_account_payment_tx_status" t-att-data-invoice-id="invoice.id">
|
||||
<t t-call="payment.transaction_status">
|
||||
<t t-set="tx" t-value="invoice.get_portal_last_transaction()"/>
|
||||
</t>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
'views/portal_templates.xml',
|
||||
|
||||
# Model views.
|
||||
'views/payment_method_views.xml',
|
||||
'views/payment_provider_views.xml', # Depends on `action_payment_method`.
|
||||
'views/payment_provider_views.xml',
|
||||
'views/payment_method_views.xml', # Depends on `action_payment_provider`.
|
||||
'views/payment_transaction_views.xml',
|
||||
'views/payment_token_views.xml', # Depends on `action_payment_transaction_linked_to_token`.
|
||||
'views/res_partner_views.xml',
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</record>
|
||||
|
||||
<record id="payment_method_unknown" model="payment.method">
|
||||
<field name="name">Unknown</field>
|
||||
<field name="name">Payment method</field>
|
||||
<field name="code">unknown</field>
|
||||
<field name="sequence">1000</field>
|
||||
<field name="active">False</field>
|
||||
@@ -3625,6 +3625,27 @@
|
||||
/>
|
||||
</record>
|
||||
|
||||
<record id="payment_method_boleto" model="payment.method">
|
||||
<field name="name">Boleto</field>
|
||||
<field name="code">boleto</field>
|
||||
<field name="sequence">1000</field>
|
||||
<field name="active">False</field>
|
||||
<field name="image" type="base64" file="payment/static/img/cash_app_pay.png"/>
|
||||
<field name="support_tokenization">False</field>
|
||||
<field name="support_express_checkout">False</field>
|
||||
<field name="support_refund"></field>
|
||||
<field name="supported_country_ids"
|
||||
eval="[Command.set([
|
||||
ref('base.br'),
|
||||
])]"
|
||||
/>
|
||||
<field name="supported_currency_ids"
|
||||
eval="[Command.set([
|
||||
ref('base.BRL'),
|
||||
])]"
|
||||
/>
|
||||
</record>
|
||||
|
||||
<!-- === PAYMENT METHOD BRANDS === -->
|
||||
|
||||
<record id="payment_method_visa" model="payment.method">
|
||||
|
||||
@@ -380,6 +380,7 @@
|
||||
ref('payment.payment_method_bancontact'),
|
||||
ref('payment.payment_method_becs_direct_debit'),
|
||||
ref('payment.payment_method_blik'),
|
||||
ref('payment.payment_method_boleto'),
|
||||
ref('payment.payment_method_card'),
|
||||
ref('payment.payment_method_cash_app_pay'),
|
||||
ref('payment.payment_method_clearpay'),
|
||||
|
||||
@@ -53,17 +53,34 @@ class PaymentMethod(models.Model):
|
||||
)
|
||||
|
||||
# Feature support fields.
|
||||
support_tokenization = fields.Boolean(string="Tokenization Supported")
|
||||
support_express_checkout = fields.Boolean(string="Express Checkout Supported")
|
||||
support_tokenization = fields.Boolean(
|
||||
string="Tokenization Supported",
|
||||
help="Tokenization is the process of saving the payment details as a token that can later"
|
||||
" be reused without having to enter the payment details again.",
|
||||
)
|
||||
support_express_checkout = fields.Boolean(
|
||||
string="Express Checkout Supported",
|
||||
help="Express checkout allows customers to pay faster by using a payment method that"
|
||||
" provides all required billing and shipping information, thus allowing to skip the"
|
||||
" checkout process.",
|
||||
)
|
||||
support_refund = fields.Selection(
|
||||
string="Type of Refund Supported",
|
||||
selection=[('full_only', "Full Only"), ('partial', "Partial")],
|
||||
help="Refund is a feature allowing to refund customers directly from the payment in Odoo.",
|
||||
)
|
||||
supported_country_ids = fields.Many2many(
|
||||
string="Supported Countries", comodel_name='res.country'
|
||||
string="Supported Countries",
|
||||
comodel_name='res.country',
|
||||
help="The list of countries in which this payment method can be used (if the provider"
|
||||
" allows it). In other countries, this payment method is not available to customers."
|
||||
)
|
||||
supported_currency_ids = fields.Many2many(
|
||||
string="Supported Currencies", comodel_name='res.currency'
|
||||
string="Supported Currencies",
|
||||
comodel_name='res.currency',
|
||||
help="The list of currencies for that are supported by this payment method (if the provider"
|
||||
" allows it). When paying with another currency, this payment method is not available "
|
||||
"to customers.",
|
||||
)
|
||||
|
||||
#=== COMPUTE METHODS ===#
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
class="d-flex gap-3 align-items-center mt-4 mb-3 fs-6 small text-uppercase
|
||||
fw-bolder"
|
||||
>
|
||||
<span>Saved payment methods</span>
|
||||
<span>Your payment methods</span>
|
||||
<hr class="flex-grow-1 m-0"/>
|
||||
</h4>
|
||||
<!-- === Body === -->
|
||||
@@ -213,7 +213,7 @@
|
||||
</div>
|
||||
<!-- === Provider name (only for desktop and tablet) === -->
|
||||
<div class="col d-none d-md-block">
|
||||
<p t-att-class="'mb-0 small text-600'
|
||||
<p name="o_payment_secured_by_desktop" t-att-class="'mb-0 small text-600'
|
||||
+ (' ms-4 ms-md-0' if allow_token_selection else '')"
|
||||
>
|
||||
<span><i class="fa fa-lock"/> Secured by</span>
|
||||
@@ -239,7 +239,9 @@
|
||||
<t t-call="{{inline_form_xml_id}}"/>
|
||||
</div>
|
||||
<!-- === Provider name (only for mobile) === -->
|
||||
<p class="align-self-end d-block d-md-none mb-0 small text-600">
|
||||
<p name="o_payment_secured_by_mobile"
|
||||
class="align-self-end d-block d-md-none mb-0 small text-600"
|
||||
>
|
||||
<span><i class="fa fa-lock"/> Secured by</span>
|
||||
<span t-out="dict(provider_sudo._fields['code']._description_selection(
|
||||
provider_sudo.env
|
||||
@@ -348,7 +350,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<!-- === Provider name === -->
|
||||
<p class="align-self-end mb-0 ms-auto small text-600">
|
||||
<p name="o_payment_secured_by" class="align-self-end mb-0 ms-auto small text-600">
|
||||
<span><i class="fa fa-lock"/> Secured by</span>
|
||||
<span t-out="dict(provider_sudo._fields['code']._description_selection(
|
||||
provider_sudo.env
|
||||
|
||||
@@ -13,21 +13,72 @@
|
||||
<h1><field name="name" placeholder="Name"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<field name="code" groups="base.group_no_one"/>
|
||||
<field name="code" readonly="id" groups="base.group_no_one"/>
|
||||
<field name="primary_payment_method_id" invisible="is_primary"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
<label for="supported_country_ids"/>
|
||||
<div>
|
||||
<field name="supported_country_ids"
|
||||
class="oe_inline"
|
||||
widget="many2many_tags"
|
||||
readonly="1"
|
||||
/>
|
||||
<span class="oe_inline text-muted" invisible="supported_country_ids">
|
||||
All countries are supported.
|
||||
</span>
|
||||
</div>
|
||||
<label for="supported_currency_ids"/>
|
||||
<div>
|
||||
<field name="supported_currency_ids"
|
||||
class="oe_inline"
|
||||
widget="many2many_tags"
|
||||
readonly="1"
|
||||
/>
|
||||
<span class="oe_inline text-muted" invisible="supported_currency_ids">
|
||||
All currencies are supported.
|
||||
</span>
|
||||
</div>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Brands" name="brands" invisible="not is_primary">
|
||||
<field name="brand_ids"/>
|
||||
</page>
|
||||
<page string="Supported By" name="providers" groups="base.group_no_one">
|
||||
<field name="provider_ids">
|
||||
<tree decoration-muted="state == 'disabled'">
|
||||
<page string="Providers" name="providers">
|
||||
<field name="provider_ids" readonly="1">
|
||||
<tree decoration-muted="state == 'disabled'" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Brands" name="brands" invisible="not is_primary">
|
||||
<field name="brand_ids"/>
|
||||
</page>
|
||||
<page string="Configuration"
|
||||
name="configuration"
|
||||
groups="base.group_no_one"
|
||||
>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<i class="fa fa-exclamation-triangle"/> These properties are set to
|
||||
match the behavior of providers and that of their integration with
|
||||
Odoo regarding this payment method. Any change may result in errors
|
||||
and should be tested on a test database first.
|
||||
</div>
|
||||
<group>
|
||||
<field name="support_tokenization"/>
|
||||
<field name="support_express_checkout"/>
|
||||
<field name="support_refund" />
|
||||
<field name="supported_country_ids"
|
||||
widget="many2many_tags"
|
||||
placeholder="Select countries. Leave empty to allow any."
|
||||
/>
|
||||
<field name="supported_currency_ids"
|
||||
widget="many2many_tags"
|
||||
placeholder="Select currencies. Leave empty to allow any."
|
||||
/>
|
||||
<field name="provider_ids"
|
||||
string="Supported by"
|
||||
widget="many2many_tags"
|
||||
/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
@@ -41,13 +92,38 @@
|
||||
<tree decoration-muted="not active">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="supported_country_ids" optional="hidden" widget="many2many_tags"/>
|
||||
<field name="supported_currency_ids" optional="hidden" widget="many2many_tags"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="payment_method_kanban" model="ir.ui.view">
|
||||
<field name="name">payment.method.kanban</field>
|
||||
<field name="model">payment.method</field>
|
||||
<field name="priority">1</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<strong><field name="name"/></strong>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="float-end">
|
||||
<field name="image" widget="image" class="oe_avatar"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="payment_method_search" model="ir.ui.view">
|
||||
<field name="name">payment.method.search</field>
|
||||
<field name="model">payment.method</field>
|
||||
@@ -62,11 +138,20 @@
|
||||
<field name="name">Payment Methods</field>
|
||||
<field name="res_model">payment.method</field>
|
||||
<field name="view_mode">tree,kanban,form</field>
|
||||
<field name="domain">[('is_primary', '=', True)]</field>
|
||||
<field name="domain">[
|
||||
('is_primary', '=', True),
|
||||
('provider_ids.state', '!=', 'disabled')
|
||||
]
|
||||
</field>
|
||||
<field name="context">{'active_test': False}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a payment method
|
||||
No payment methods found for your payment providers.
|
||||
</p>
|
||||
<p>
|
||||
<a type="action" class="text-primary" name="%(payment.action_payment_provider)d">
|
||||
<i class="oi oi-arrow-right me-1"/> Configure a payment provider
|
||||
</a>
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<group name="provider_config">
|
||||
<group string="Payment Form" name="payment_form">
|
||||
<field name="payment_method_ids"
|
||||
string="Payment Methods"
|
||||
domain="[('is_primary', '=', True)]"
|
||||
readonly="True"
|
||||
widget="many2many_tags"
|
||||
@@ -215,7 +216,15 @@
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="name" string="provider" filter_domain="[('name', 'ilike', self)]"/>
|
||||
<field name="code"/>
|
||||
<field name="payment_method_ids"
|
||||
string="payment method"
|
||||
context="{'active_test': False}"
|
||||
filter_domain="[
|
||||
'|',
|
||||
('payment_method_ids.name', 'ilike', self),
|
||||
('payment_method_ids.code', 'ilike', self),
|
||||
]"
|
||||
/>
|
||||
<filter name="provider_installed" string="Installed" domain="[('module_state', '=', 'installed')]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Provider" name="code" context="{'group_by': 'code'}"/>
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
<!-- Portal breadcrumb -->
|
||||
<t t-call="payment.portal_breadcrumb"/>
|
||||
<!-- Payment methods page -->
|
||||
<div class="row">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-7">
|
||||
<div t-if="not payment_methods_sudo and not tokens_sudo"
|
||||
class="alert alert-warning"
|
||||
@@ -160,6 +160,7 @@
|
||||
<t t-call="portal.frontend_layout">
|
||||
<t t-set="page_title" t-value="'Payment Confirmation'"/>
|
||||
<t t-set="additional_title"><t t-esc="page_title"/></t>
|
||||
<t t-set="show_pm" t-value="tx.payment_method_code != 'unknown'"/>
|
||||
<div class="wrap">
|
||||
<div class="container">
|
||||
<!-- Portal breadcrumb -->
|
||||
@@ -172,7 +173,9 @@
|
||||
<t t-call="payment.transaction_status"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_cc o_cc2 row row-cols-1 row-cols-md-4 mx-0 mb-3 py-2 rounded">
|
||||
<div t-att-class="'o_cc o_cc2 row row-cols-1 mx-0 mb-3 py-2 rounded'
|
||||
+ (' row-cols-md-4' if show_pm else ' row-cols-md-3')"
|
||||
>
|
||||
<t t-call="payment.summary_item">
|
||||
<t t-set="name" t-value="'amount'"/>
|
||||
<t t-set="label">Amount</t>
|
||||
@@ -187,11 +190,13 @@
|
||||
<t t-set="value" t-value="tx.reference"/>
|
||||
<t t-set="include_separator" t-value="True"/>
|
||||
</t>
|
||||
<t t-call="payment.summary_item">
|
||||
<t t-set="name" t-value="'method'"/>
|
||||
<t t-set="label">Payment Method</t>
|
||||
<t t-set="value" t-value="tx.payment_method_id.name"/>
|
||||
<t t-set="include_separator" t-value="True"/>
|
||||
<t t-if="tx.payment_method_code != 'unknown'">
|
||||
<t t-call="payment.summary_item">
|
||||
<t t-set="name" t-value="'method'"/>
|
||||
<t t-set="label">Payment Method</t>
|
||||
<t t-set="value" t-value="tx.payment_method_id.name"/>
|
||||
<t t-set="include_separator" t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-call="payment.summary_item">
|
||||
<t t-set="name" t-value="'provider'"/>
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="payment_custom.token_form" inherit_id="payment.token_form">
|
||||
<xpath expr="//p[@name='o_payment_secured_by_desktop']" position="attributes">
|
||||
<attribute name="t-att-class"/>
|
||||
<attribute name="class">d-none</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//p[@name='o_payment_secured_by_mobile']" position="attributes">
|
||||
<attribute name="class" separator=" " add="d-none"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="payment_custom.payment_method_form" inherit_id="payment.method_form">
|
||||
<xpath expr="//p[@name='o_payment_secured_by']" position="attributes">
|
||||
<attribute name="class" separator=" " add="d-none"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="redirect_form">
|
||||
<form t-att-action="api_url" method="post">
|
||||
<input type="hidden" name="reference" t-att-value="reference"/>
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="payment_demo.token_form" inherit_id="payment.token_form">
|
||||
<xpath expr="//p[@name='o_payment_secured_by_desktop']" position="attributes">
|
||||
<attribute name="t-att-class"/>
|
||||
<attribute name="class">d-none</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//p[@name='o_payment_secured_by_mobile']" position="attributes">
|
||||
<attribute name="class" separator=" " add="d-none"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="payment_demo.payment_method_form" inherit_id="payment.method_form">
|
||||
<xpath expr="//p[@name='o_payment_secured_by']" position="attributes">
|
||||
<attribute name="class" separator=" " add="d-none"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="inline_form">
|
||||
<div t-attf-id="demo-container-{{provider_id}}">
|
||||
<t t-call="payment_demo.payment_details"/>
|
||||
|
||||
@@ -292,7 +292,7 @@
|
||||
If you believe that it is an error, please contact the website administrator.
|
||||
</div>
|
||||
<div t-else="" id="payment_method" class="text-start">
|
||||
<h3 class="mb24">Pay with</h3>
|
||||
<h3>Pay with</h3>
|
||||
<t t-call="payment.form">
|
||||
<!-- Inject the order ID to allow Stripe to check if tokenization is required. -->
|
||||
<t t-set="sale_order_id" t-value="sale_order.id"/>
|
||||
@@ -348,7 +348,7 @@
|
||||
Your order is not in a state to be rejected.
|
||||
</div>
|
||||
|
||||
<t t-if="sale_order.transaction_ids">
|
||||
<t t-if="sale_order.get_portal_last_transaction()">
|
||||
<t t-call="payment.transaction_status">
|
||||
<t t-set="tx" t-value="sale_order.get_portal_last_transaction()"/>
|
||||
</t>
|
||||
@@ -417,7 +417,7 @@
|
||||
<div t-attf-class="#{'card-body' if report_type == 'html' else ''}">
|
||||
<!-- Informations -->
|
||||
<div id="informations">
|
||||
<div t-if="sale_order.transaction_ids and not invoices and sale_order.state in ('sent', 'sale') and portal_confirmation == 'pay' and not success and not error" t-att-data-order-id="sale_order.id">
|
||||
<div t-if="sale_order.get_portal_last_transaction() and not invoices and sale_order.state in ('sent', 'sale') and portal_confirmation == 'pay' and not success and not error" t-att-data-order-id="sale_order.id">
|
||||
<t t-if="sale_order.transaction_ids">
|
||||
<t t-call="payment.transaction_status">
|
||||
<t t-set="tx" t-value="sale_order.get_portal_last_transaction()"/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
|
||||
<record id="payment_provider_onsite" model="payment.provider">
|
||||
<field name="name">Pay in store when picking the product</field>
|
||||
<field name="name">Pay in Store</field>
|
||||
<field name="code">custom</field>
|
||||
<field name="state">enabled</field>
|
||||
<field name="custom_mode">onsite</field>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<record id="onsite_delivery_product" model="product.product">
|
||||
<field name="name">On site picking</field>
|
||||
<field name="description">Pay in store when picking the product</field>
|
||||
<field name="description">Pay in Store</field>
|
||||
<field name="type">service</field>
|
||||
<field name="list_price">0</field>
|
||||
<field name="purchase_ok">false</field>
|
||||
|
||||
@@ -25,7 +25,7 @@ registry.category("web_tour.tours").add('onsite_payment_tour', {
|
||||
wsTourUtils.goToCart({quantity: 2}),
|
||||
wsTourUtils.goToCheckout(),
|
||||
...wsTourUtils.fillAdressForm(),
|
||||
wTourUtils.clickOnElement('"Pay in store when picking the product"', '.o_delivery_carrier_select:contains("Example shipping On Site")'),
|
||||
wTourUtils.clickOnElement('"Pay in Store"', '.o_delivery_carrier_select:contains("Example shipping On Site")'),
|
||||
wTourUtils.clickOnElement('Pay button', 'button[name="o_payment_submit_button"]:visible:not(:disabled)'),
|
||||
{
|
||||
content: "Check if the payment is successful",
|
||||
|
||||
Reference in New Issue
Block a user