diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/payment/views | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/payment/views')
| -rw-r--r-- | addons/payment/views/account_invoice_views.xml | 28 | ||||
| -rw-r--r-- | addons/payment/views/account_payment_views.xml | 21 | ||||
| -rw-r--r-- | addons/payment/views/assets.xml | 15 | ||||
| -rw-r--r-- | addons/payment/views/payment_acquirer_onboarding_templates.xml | 92 | ||||
| -rw-r--r-- | addons/payment/views/payment_portal_templates.xml | 169 | ||||
| -rw-r--r-- | addons/payment/views/payment_templates.xml | 186 | ||||
| -rw-r--r-- | addons/payment/views/payment_views.xml | 439 | ||||
| -rw-r--r-- | addons/payment/views/res_partner_views.xml | 29 |
8 files changed, 979 insertions, 0 deletions
diff --git a/addons/payment/views/account_invoice_views.xml b/addons/payment/views/account_invoice_views.xml new file mode 100644 index 00000000..8e57cda0 --- /dev/null +++ b/addons/payment/views/account_invoice_views.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<odoo> + <data> + <record id="account_invoice_view_form_inherit_payment" model="ir.ui.view"> + <field name="name">account.move.view.form.inherit.payment</field> + <field name="model">account.move</field> + <field name="inherit_id" ref="account.view_move_form"/> + <field name="arch" type="xml"> + <!-- + The user must capture/void the authorized transactions before registering a new payment. + --> + <xpath expr="//button[@id='account_invoice_payment_btn']" position="attributes"> + <attribute name="attrs">{'invisible': ['|', '|', '|', ('state', '!=', 'posted'), ('payment_state', 'not in', ('partial', 'not_paid')), ('move_type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt')), ('authorized_transaction_ids', '!=', [])]}</attribute> + </xpath> + <xpath expr="//button[@id='account_invoice_payment_btn']" position="after"> + <field name="authorized_transaction_ids" invisible="1"/> + <button name="payment_action_capture" type="object" + string="Capture Transaction" class="oe_highlight" + attrs="{'invisible': ['|', '|', ('move_type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund')), ('state', '!=', 'posted'), ('authorized_transaction_ids', '=', [])]}"/> + <button name="payment_action_void" type="object" + string="Void Transaction" + confirm="Are you sure you want to void the authorized transaction? This action can't be undone." + attrs="{'invisible': ['|', '|', ('move_type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund')), ('state', '!=', 'posted'), ('authorized_transaction_ids', '=', [])]}"/> + </xpath> + </field> + </record> + </data> +</odoo> diff --git a/addons/payment/views/account_payment_views.xml b/addons/payment/views/account_payment_views.xml new file mode 100644 index 00000000..c6ce4c1a --- /dev/null +++ b/addons/payment/views/account_payment_views.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<odoo> + <data> + <record id="view_account_payment_form_inherit_payment" model="ir.ui.view"> + <field name="name">view.account.payment.form.inherit.payment</field> + <field name="model">account.payment</field> + <field name="inherit_id" ref="account.view_account_payment_form"/> + <field name="arch" type="xml"> + <xpath expr='//group[2]' position="inside"> + <field name="payment_transaction_id" groups="base.group_no_one" attrs="{'invisible': [('payment_method_code', '!=', 'electronic')]}"/> + </xpath> + <field name="payment_method_id" position="after"> + <field name="payment_method_code" invisible="1"/> + <field name="related_partner_ids" invisible="1"/> + <field name="payment_token_id" options="{'no_create': True}" + attrs="{'invisible': [('payment_method_code', '!=', 'electronic')], 'readonly': [('state', '!=', 'draft')]}"/> + </field> + </field> + </record> + </data> +</odoo> diff --git a/addons/payment/views/assets.xml b/addons/payment/views/assets.xml new file mode 100644 index 00000000..a1a2206e --- /dev/null +++ b/addons/payment/views/assets.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <template id="assets_frontend" inherit_id="web.assets_frontend"> + <xpath expr="link[last()]" position="after"> + <link rel="stylesheet" type="text/scss" href="/payment/static/src/scss/portal_payment.scss"/> + <link rel="stylesheet" type="text/scss" href="/payment/static/src/scss/payment_form.scss"/> + </xpath> + <xpath expr="script[last()]" position="after"> + <script type="text/javascript" src="/payment/static/lib/jquery.payment/jquery.payment.js"></script> + <script type="text/javascript" src="/payment/static/src/js/payment_portal.js"></script> + <script type="text/javascript" src="/payment/static/src/js/payment_form.js"></script> + <script type="text/javascript" src="/payment/static/src/js/payment_processing.js"></script> + </xpath> + </template> +</odoo> diff --git a/addons/payment/views/payment_acquirer_onboarding_templates.xml b/addons/payment/views/payment_acquirer_onboarding_templates.xml new file mode 100644 index 00000000..b94d2031 --- /dev/null +++ b/addons/payment/views/payment_acquirer_onboarding_templates.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <!-- onboarding step --> + <template id="onboarding_payment_acquirer_step"> + <t t-call="base.onboarding_step"> + <t t-set="title">Payment Method</t> + <t t-set="description">Choose your default customer payment method.</t> + <t t-set="btn_text">Set payments</t> + <t t-set="done_text">Payment method set!</t> + <t t-set="method" t-value="'action_open_payment_onboarding_payment_acquirer'" /> + <t t-set="model" t-value="'res.company'" /> + <t t-set="state" t-value="state.get('payment_acquirer_onboarding_state')" /> + </t> + </template> + <!--PAYMENT ACQUIRER--> + <record model="ir.ui.view" id="payment_acquirer_onboarding_wizard_form"> + <field name="name">payment.acquirer.onboarding.wizard.form</field> + <field name="model">payment.acquirer.onboarding.wizard</field> + <field name="arch" type="xml"> + <form string="Choose a payment method" class="o_onboarding_payment_acquirer_wizard"> + <div class="container"> + <div class="row align-items-start"> + <div class="col col-4" name="left-column"> + <group> + <field name="payment_method" widget="radio" nolabel="1"/> + </group> + </div> + <div class="col" name="right-column"> + <div attrs="{'invisible': [('payment_method', '!=', 'paypal')]}"> + <group> + <field name="paypal_user_type" widget="radio" nolabel="1"/> + <field name="paypal_email_account" attrs="{'required': [('payment_method', '=', 'paypal')]}" string="Email"/> + <field name="paypal_seller_account" attrs="{'invisible': [('paypal_user_type', '=', 'new_user')], 'required': [('paypal_user_type', '!=', 'new_user'), ('payment_method', '=', 'paypal')]}" /> + <field name="paypal_pdt_token" password="True" attrs="{'invisible': [('paypal_user_type', '=', 'new_user')], 'required': [('paypal_user_type', '!=', 'new_user'), ('payment_method', '=', 'paypal')]}" /> + </group> + <p attrs="{'invisible': [('paypal_user_type', '!=', 'new_user')]}"> + <span>Start selling directly without an account; an email will be sent by Paypal to create your new account and collect your payments.</span> + </p> + <p attrs="{'invisible': [('paypal_user_type', '=', 'new_user')]}"> + <a href="https://www.odoo.com/documentation/14.0/applications/general/payment_acquirers/paypal.html" target="_blank"> + <span class="fa fa-arrow-right"> How to configure your PayPal account</span> + </a> + </p> + </div> + <div attrs="{'invisible': [('payment_method', '!=', 'stripe')]}"> + <group> + <field name="stripe_secret_key" password="True" + attrs="{'required': [('payment_method', '=', 'stripe')]}" /> + <field name="stripe_publishable_key" password="True" + attrs="{'required': [('payment_method', '=', 'stripe')]}" /> + </group> + <p> + <a href="https://dashboard.stripe.com/account/apikeys" target="_blank"> + <span class="fa fa-arrow-right"> Get my Stripe keys</span> + </a> + </p> + </div> + + <div attrs="{'invisible': [('payment_method', '!=', 'other')]}"> + <button type="object" name="action_onboarding_other_payment_acquirer"> + Check here + </button> + to choose another payment method. + </div> + <div attrs="{'invisible': [('payment_method', '!=', 'manual')]}"> + <group> + <field name="manual_name" attrs="{'required': [('payment_method', '=', 'manual')]}"/> + <field name="journal_name" attrs="{'required': [('payment_method', '=', 'manual')]}"/> + <field name="acc_number" attrs="{'required': [('payment_method', '=', 'manual')]}"/> + <field name="manual_post_msg" attrs="{'required': [('payment_method', '=', 'manual')]}"/> + </group> + </div> + </div> + </div> + </div> + <footer> + <button name="add_payment_methods" string="Apply" class="oe_highlight" + type="object" /> + <button special="cancel" string="Cancel" /> + </footer> + </form> + </field> + </record> + <record id="action_open_payment_onboarding_payment_acquirer_wizard" model="ir.actions.act_window"> + <field name="name">Choose a payment method</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">payment.acquirer.onboarding.wizard</field> + <field name="view_mode">form</field> + <field name="view_id" ref="payment.payment_acquirer_onboarding_wizard_form" /> + <field name="target">new</field> + </record> +</odoo> diff --git a/addons/payment/views/payment_portal_templates.xml b/addons/payment/views/payment_portal_templates.xml new file mode 100644 index 00000000..c126368b --- /dev/null +++ b/addons/payment/views/payment_portal_templates.xml @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + <template id="pay_methods" name="Payment Methods"> + <t t-call="portal.frontend_layout"> + <t t-set="additional_title">Payment Methods</t> + <div class="wrap"> + <div class="container"> + <div class="row"> + <div class="col-md-6"> + <ol class="breadcrumb mt8"> + <li class="breadcrumb-item"><a href="/my/home"><i class="fa fa-home" role="img" aria-label="Home" title="Home"/></a></li> + <li class="breadcrumb-item">Payment Methods</li> + </ol> + </div> + </div> + <div class="clearfix"> + <div class="row"> + <div class="col-md-8"> + <h3>Manage Payment Methods</h3> + <t t-call="payment.payment_tokens_list"> + <t t-set="acquirers" t-value="acquirers"/> + <t t-set="mode" t-value="'manage'"/> + </t> + </div> + </div> + </div> + </div> + </div> + </t> + </template> + + <!-- TDE FIXME: was customize_show=True --> + <template id="pay_meth_link" inherit_id="portal.portal_layout"> + <xpath expr="//div[hasclass('o_portal_my_details')]" position="inside"> + <t t-if="request.env['payment.acquirer'].search([('state', 'in', ['enabled', 'test']), ('registration_view_template_id', '!=', False), ('payment_flow', '=', 's2s'), ('company_id', '=', request.env.company.id)])"> + <div class='manage_payment_method mt16'><a href="/my/payment_method">Manage payment methods</a></div> + </t> + </xpath> + </template> + + <template id="pay"> + <t t-call="portal.frontend_layout"> + <t t-set="additional_title">Payment</t> + <div class="wrap"> + <div class="container o_website_payment"> + <h1>Payment</h1> + <div class="row mt32 mb32"> + <div class="col-lg-7"> + <p><b>Reference:</b> <t t-esc="reference"/></p> + <p><b>Amount:</b> <t t-esc="amount" t-options="{'widget': 'monetary', 'display_currency': currency}"/></p> + <t t-call="payment.payment_tokens_list" t-if="reference and amount and currency"> + <t t-set="mode" t-value="'payment'"/> + <t t-set="_overriden_reference" t-value="reference"/> + <t t-set="reference" t-value="quote_plus(reference).replace('+','%20')"/> + <t t-set="prepare_tx_url" t-value="'/website_payment/transaction/v2/' + str(amount) + '/' + str(currency.id) + '/' + reference + (('/' + str(partner_id)) if partner_id else '')"/> + <t t-set="form_action" t-value="'/website_payment/token/v2/' + str(amount) + '/' + str(currency.id) + '/' + reference + (('/' + str(partner_id)) if partner_id else '')"/> + <t t-set="reference" t-value="_overriden_reference"/> + </t> + <div t-if="not acquirers" class="alert alert-danger" role="alert"> + <p>No payment acquirer found.</p> + <p>Please configure a payment acquirer.</p> + </div> + </div> + </div> + </div> + </div> + </t> + </template> + + <template id="confirm"> + <t t-call="portal.frontend_layout"> + <t t-set="additional_title">Payment</t> + <div class="wrap"> + <div class="container o_website_payment"> + <h1>Payment</h1> + <div class="row"> + <div class="col-lg-6"> + <div> + <div t-attf-class="alert alert-#{status}" t-raw="message" role="status"/> + <div class="form-group row"> + <label for="form_partner_name" class="col-md-3 col-form-label">From</label> + <div class="col-md-9"> + <span name="form_partner_name" class="form-control" t-esc="tx.partner_name"/> + </div> + </div> + <div class="form-group row"> + <label for="form_reference" class="col-md-3 col-form-label">Reference</label> + <div class="col-md-9"> + <span name="form_reference" class="form-control" t-esc="tx.reference"/> + </div> + </div> + <div class="form-group row"> + <label for="form_amount" class="col-md-3 col-form-label">Amount</label> + <div class="col-md-9"> + <span name="form_amount" class="form-control" t-esc="tx.amount" t-options="{'widget': 'monetary', 'display_currency': tx.currency_id}"/> + </div> + </div> + + <div t-if="tx.acquirer_id.qr_code"> + <t t-set="qr_code" t-value="tx.acquirer_id.journal_id.bank_account_id.build_qr_code_url(tx.amount, tx.reference, None, tx.currency_id, tx.partner_id)"/> + <div class="card-body" t-if="qr_code"> + <h3>Or scan me with your banking app.</h3> + <img class="border border-dark rounded" t-att-src="qr_code"/> + </div> + </div> + <div class="row"> + <div class="col-md-5 offset-md-3 text-muted"> + <span t-field="tx.acquirer_id.image_128" t-att-title="tx.acquirer_id.name" role="img" t-att-aria-label="tx.acquirer_id.name" t-options='{"widget": "image", "style":"max-width: 60px; display: inline-block"}'/> + <div>Processed by <t t-esc="tx.acquirer_id.name"/>.</div> + </div> + <div class="col-md-4 mt-2 pl-0"> + <a role="button" t-attf-class="btn btn-#{status} float-right" href="/my/home"><i class="fa fa-arrow-circle-right"/> Back to My Account</a> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </t> + </template> + + <template id="payment_confirmation_status"> + <!-- + Inform the portal user about the transaction status. + + To be called with the 'payment_tx_id' value. + --> + <div t-if="payment_tx_id and payment_tx_id.state == 'pending'" class="alert alert-warning alert-dismissable" role="status"> + <button type="button" class="close" data-dismiss="alert" aria-label="Close">×</button> + <span t-if='payment_tx_id.acquirer_id.pending_msg' t-raw="payment_tx_id.acquirer_id.pending_msg"/> + <span t-if='thanks_msg' t-raw="thanks_msg"/> + <div t-if="payment_tx_id.acquirer_id.provider == 'transfer' and reference"> + <b>Communication: </b><span t-esc='reference'/> + </div> + + <div t-if="payment_tx_id.acquirer_id.qr_code and (payment_tx_id.acquirer_id.provider == 'transfer')"> + <t t-set="qr_code" t-value="payment_tx_id.acquirer_id.journal_id.bank_account_id.build_qr_code_url(payment_tx_id.amount,payment_tx_id.reference, None, payment_tx_id.currency_id, payment_tx_id.partner_id)"/> + <div class="card-body" t-if="qr_code"> + <h3>Or scan me with your banking app.</h3> + <img class="border border-dark rounded" t-att-src="qr_code"/> + </div> + </div> + </div> + <div t-if="payment_tx_id and payment_tx_id.state == 'authorized' and payment_tx_id.acquirer_id.authorize_implemented" class="alert alert-success alert-dismissable" role="alert"> + <button type="button" class="close" data-dismiss="alert" title="Dismiss" aria-label="Dismiss">×</button> + <!-- Your payment has been authorized. --> + <span t-if='payment_tx_id.acquirer_id.auth_msg' t-raw="payment_tx_id.acquirer_id.auth_msg"/> + </div> + <div t-if="payment_tx_id and payment_tx_id.state == 'done'" class="alert alert-success alert-dismissable"> + <button type="button" class="close" data-dismiss="alert" title="Dismiss" aria-label="Dismiss">×</button> + <span t-if='payment_tx_id.acquirer_id.done_msg' t-raw="payment_tx_id.acquirer_id.done_msg"/> + <span t-if='thanks_msg' t-raw="thanks_msg"/> + <div t-if="thanks_msg and payment_tx_id.acquirer_id.provider == 'transfer' and reference"> + <b>Communication: </b><span t-esc='reference'/> + </div> + </div> + <div t-if="payment_tx_id and payment_tx_id.state == 'cancel'" class="alert alert-danger alert-dismissable"> + <button type="button" class="close" data-dismiss="alert" title="Dismiss" aria-label="Dismiss">×</button> + <span t-if='payment_tx_id.acquirer_id.cancel_msg' t-raw="payment_tx_id.acquirer_id.cancel_msg"/> + </div> + <div t-if="payment_tx_id and payment_tx_id.state_message"> + <span t-esc="payment_tx_id.state_message"/> + </div> + </template> + + </data> +</odoo> diff --git a/addons/payment/views/payment_templates.xml b/addons/payment/views/payment_templates.xml new file mode 100644 index 00000000..b8de80be --- /dev/null +++ b/addons/payment/views/payment_templates.xml @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <template id="assets_backend" name="Payment Assets Backend" inherit_id="web.assets_backend"> + <xpath expr="." position="inside"> + <link rel="stylesheet" type="text/scss" href="/payment/static/src/scss/payment_acquirer.scss"/> + </xpath> + </template> + + <template id="payment_tokens_list" name="Payment Tokens list"> + <!-- + Variables description: + - 'submit_txt' the text displayed inside the submit button + - 'submit_class' the css classes to style the submit button + - 'icon_class' font awesome class (e.g. 'fa-trash', 'fa-lock') + - 'form_action' the URI to the page that will handle the form values given for server2server + - 'pms' the tokens + - 'checked_pm_id' the payment token that should be checked (for radio buttons) + - 'mode' can take two values, either 'payment' or 'manage'. 'manage' displays the add a new card and delete buttons. 'payment' + display a form that is used to pay and send the information to the form action url. + - 'acquirers' the list of both server2server and form payment acquirers + - 'verify_validity' if we need to verify if the payment method is valid when adding a new one + - 'prepare_tx_url' the url of the route which will handle the creation of a transaction for a form base payment (handles if the transaction is form or form_save) + - 'show_manage_btn' if True, a button is added in the footer to manage payment methods + --> + <form t-if="pms or acquirers" method="post" class="o_payment_form mt-3 clearfix" + t-att-action="form_action if form_action else '#'" + t-att-data-success-url="success_url or ''" + t-att-data-error-url="error_url or ''" + t-att-data-access-token="access_token or ''" + t-att-data-partner-id="partner_id" + t-att-data-callback-method="callback_method or ''" + t-att-data-order-id="order_id or ''" + t-att-data-invoice-id="invoice_id or ''" + t-att-data-mode="mode"> + <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> + <input type="hidden" t-if="prepare_tx_url" name="prepare_tx_url" t-att-value="prepare_tx_url"/> + <input type="hidden" t-if="order_id" name="order_id" t-att-value="order_id"/> + <input type="hidden" t-if="invoice_id" name="invoice_id" t-att-value="invoice_id"/> + <!-- s2s form submission --> + <input type="hidden" t-if="access_token" name="access_token" t-att-value="access_token"/> + <input type="hidden" t-if="success_url" name="success_url" t-att-value="success_url"/> + <input type="hidden" t-if="error_url" name="error_url" t-att-value="error_url"/> + <input type="hidden" t-if="callback_method" name="callback_method" t-att-value="callback_method"/> + + <div class="card"> + <t t-set="acquirers_count" t-value="len(acquirers) if acquirers else 0"/> + <t t-set="pms_count" t-value="len(pms) if pms else 0"/> + <t t-set="MAX_BRAND_LINE" t-value="3"/> + <t t-foreach="acquirers" t-as="acq"> + <div class="card-body o_payment_acquirer_select"> + <label> + <t t-if="acq.payment_flow == 'form'"> + <input type="radio" t-att-data-acquirer-id="acq.id" + t-att-data-form-payment="true" + t-att-data-provider="acq.provider" + t-att-class="'d-none' if (acquirers_count==1 and pms_count==0) else ''" + name="pm_id" t-attf-value="form_{{acq.id}}" + t-att-checked="acquirers_count==1 and pms_count==0 or acquirers[0] == acq"/> + </t> + <t t-else="acq.payment_flow == 's2s'"> + <input type="radio" t-att-data-acquirer-id="acq.id" + t-att-data-s2s-payment="true" + t-att-data-provider="acq.provider" + name="pm_id" t-attf-value="new_{{acq.id}}" + t-att-class="'d-none' if (acquirers_count==1 and pms_count==0) else ''" + t-att-checked="acquirers_count==1 and pms_count==0 or acquirers[0] == acq"/> + </t> + <span class="payment_option_name"> + <t t-esc="acq.display_as or acq.name"/> + <div t-if="acq.state == 'test'" class="badge-pill badge-warning float-right" style="margin-left:5px"> + Test Mode + </div> + </span> + <t t-if="acq_extra_fees and acq_extra_fees.get(acq)"> + <span class="badge badge-pill badge-secondary"> + <t t-esc="acq_extra_fees[acq]" t-options='{"widget": "monetary", "display_currency": acq_extra_fees["currency_id"]}'/> Fee </span> + </t> + <t t-elif="acq.fees_active"> + <small class="text-muted">(Some fees may apply)</small> + </t> + </label> + <ul class="float-right list-inline payment_icon_list"> + <t t-set="i" t-value="0"/> + <t t-foreach="acq.payment_icon_ids" t-as="pm_icon"> + <li t-attf-class="list-inline-item#{'' if (i < MAX_BRAND_LINE) else ' d-none'}"> + <span t-field="pm_icon.image_payment_form" + t-options='{"widget": "image", "alt-field": "name"}'/> + </li> + <li t-if="i==MAX_BRAND_LINE" style="display:block;" class="list-inline-item"> + <span class="float-right more_option text-info"> + <a href="#" class="o_payment_form_pay_icon_more" data-toggle="tooltip" t-att-title="', '.join([opt.name for opt in acq.payment_icon_ids[MAX_BRAND_LINE:]])">and more</a> + </span> + </li> + <t t-set="i" t-value="i+1"/> + </t> + </ul> + <div t-raw="acq.pre_msg" class="text-muted ml-3"/> + </div> + <t t-if="acq.payment_flow == 'form'"> + <div t-attf-id="o_payment_form_acq_{{acq.id}}" + t-attf-class="d-none {{'card-footer' if acq.save_token == 'ask' else ''}}"> + <label t-if="acq.save_token == 'ask'"> + <input type="checkbox" name="o_payment_form_save_token" data-remove-me=""/> + Save my payment data + </label> + <t t-if="acq.save_token == 'always'"> + <input type="checkbox" name="o_payment_form_save_token" checked="'checked'" class="o_hidden" data-remove-me=""/> + </t> + </div> + </t> + <t t-else="acq.payment_flow == 's2s'"> + <div t-attf-id="o_payment_add_token_acq_{{acq.id}}" + t-attf-class="card-footer {{'d-none' if(acquirers_count > 1 and pms_count==0 and acquirers[0]!=acq) else 'd-none' if pms_count >0 else ''}}"> + <div class="clearfix"> + <input type="hidden" t-if="(verify_validity==True or mode == 'manage') and acq.check_validity" name="verify_validity" t-att-value="acq.check_validity"/> + <t t-call="{{acq.sudo().get_s2s_form_xml_id()}}"> + <t t-set="id" t-value="acq.id"/> + <t t-set="partner_id" t-value="partner_id"/> + <t t-if="not return_url" t-set="return_url" t-value="''"/> + </t> + </div> + </div> + </t> + </t> + <t t-foreach="pms" t-as="pm"> + <t t-if="not verify_validity or (pm.acquirer_id.check_validity and pm.verified) or not pm.acquirer_id.check_validity"> + <div class="card-body o_payment_acquirer_select"> + <label> + <input t-if="mode == 'payment'" type="radio" name="pm_id" t-att-value="pm.id" t-att-checked="checked_pm_id == pm.id"/> + <span class="payment_option_name" t-esc="pm.name"/> + <t t-if="pm.verified"> + <i class="fa fa-check text-success" title="This payment method is verified by our system." role="img" aria-label="Ok"></i> + </t> + <t t-else=""> + <i class="fa fa-check text-muted" title="This payment method has not been verified by our system." role="img" aria-label="Not verified"></i> + </t> + </label> + <button t-if="mode == 'manage'" name="delete_pm" t-att-value="pm.id" class="btn btn-primary btn-sm float-right"> + <i class="fa fa-trash"></i> Delete + </button> + </div> + </t> + </t> + </div> + <div t-if='back_button_txt' class="float-left mt-2"> + <a role="button" t-att-href="back_button_link or '#'" t-att-class="back_button_class or 'btn btn-lg btn-secondary'"> + <i t-if="back_button_icon_class" t-attf-class="fa {{back_button_icon_class}}"/> + <t t-esc="back_button_txt"/> + </a> + </div> + <div class="float-right mt-2"> + <button t-if="mode == 'payment'" id="o_payment_form_pay" type="submit" t-att-class="submit_class if submit_class else 'btn btn-primary btn-lg mb8 mt8'" disabled="true"> + <t t-if="submit_txt"> + <i t-if="icon_class and not icon_right" t-attf-class="fa {{icon_class}}"/> + <t t-esc="submit_txt"/> + <i t-if="icon_class and icon_right" t-attf-class="fa {{icon_class}}"/> + </t> + <t t-else=""> + <i class="fa fa-lock"/> Pay + </t> + </button> + <t t-if="show_manage_btn"> + <a class="btn btn-link mb8 mt8" href="/my/payment_method">Manage your payment methods</a> + </t> + <button t-if="mode == 'manage' and list(filter(lambda x: x.payment_flow == 's2s', acquirers))" type="submit" id="o_payment_form_add_pm" class="btn btn-primary btn-lg mb8 mt8"> + <i class="fa fa-plus-circle"/> Add new card + </button> + </div> + </form> + </template> + + <template id="payment_process_page" name="Payment processing page"> + <t t-call="portal.frontend_layout"> + <div class="wrap"> + <div class="container o_website_payment"> + <div class="o_payment_processing"> + <div class="row"> + <div class="o_payment_processing_content col-sm-6 col-sm-offset-3"> + <!-- The content here is generated in JS --> + </div> + </div> + </div> + </div> + </div> + </t> + </template> +</odoo> diff --git a/addons/payment/views/payment_views.xml b/addons/payment/views/payment_views.xml new file mode 100644 index 00000000..9925b8d1 --- /dev/null +++ b/addons/payment/views/payment_views.xml @@ -0,0 +1,439 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + + <record id="acquirer_form" model="ir.ui.view"> + <field name="name">payment.acquirer.form</field> + <field name="model">payment.acquirer</field> + <field name="arch" type="xml"> + <form string="Payment Acquirer"> + <field name="fees_implemented" invisible='1'/> + <field name="token_implemented" invisible='1'/> + <field name="authorize_implemented" invisible="1"/> + <sheet> + <field name="module_id" invisible="1"/> + <field name="module_state" invisible="1"/> + <field name="module_to_buy" invisible="1"/> + <field name="inbound_payment_method_ids" invisible="1"/> + <field name="image_128" widget="image" class="oe_avatar"/> + <widget name="web_ribbon" title="Disabled" bg_color="bg-danger" attrs="{'invisible': [('state', '!=', 'disabled')]}"/> + <widget name="web_ribbon" title="Test Mode" bg_color="bg-warning" attrs="{'invisible': [('state', '!=', 'test')]}"/> + <div class="oe_title"> + <h1><field name="name" placeholder="Name"/></h1> + <div attrs="{'invisible': ['|', ('module_state', '=', 'installed'), ('module_id', '=', False)]}"> + <a attrs="{'invisible': [('module_to_buy', '=', False)]}" href="https://odoo.com/pricing?utm_source=db&utm_medium=module" class="btn btn-info" role="button">Upgrade</a> + <button attrs="{'invisible': [('module_to_buy', '=', True)]}" type="object" class="btn btn-primary" name="button_immediate_install" string="Install"/> + </div> + </div> + <div attrs="{'invisible': ['|', ('module_state', '=', 'installed'), ('module_id', '=', False)]}"> + <div class="o_payment_acquirer_desc"> + <field name="description"/> + </div> + </div> + <group> + <group name="payment_state"> + <field name="provider" groups="base.group_no_one" attrs="{'invisible': [('module_id', '!=', False), ('module_state', '!=', 'installed')]}"/> + <field name="state" widget="radio" attrs="{'invisible': [('module_state', '=', 'uninstalled')]}"/> + <field name="company_id" groups="base.group_multi_company" options='{"no_open":True}'/> + </group> + </group> + <notebook attrs="{'invisible': ['&', ('module_id', '!=', False), ('module_state', '!=', 'installed')]}"> + <page string="Credentials" name="acquirer_credentials" attrs="{'invisible': [('provider', '=', 'manual')]}"> + <group name="acquirer"> + </group> + </page> + <page string="Configuration" name="configuration"> + <group name="acquirer_config"> + <group string="Payment Form" name="payment_form"> + <field name="display_as" placeholder="If not defined, the acquirer name will be used."/> + <field name="payment_icon_ids" widget="many2many_tags"/> + <field name="save_token" widget="radio" attrs="{'invisible': ['|', ('token_implemented', '=', False), ('payment_flow', '=', 's2s')]}"/> + <field name="capture_manually" attrs="{'invisible': [('authorize_implemented', '=', False)]}"/> + <field name="payment_flow" widget="radio" attrs="{'invisible': [('token_implemented', '=', False)]}"/> + <field name="view_template_id" groups="base.group_no_one"/> + <field name="registration_view_template_id" groups="base.group_no_one" attrs="{'invisible': [('payment_flow', '!=', 's2s')]}"/> + <field name="check_validity" attrs="{'invisible': [('payment_flow', '!=', 's2s')]}" groups="base.group_no_one"/> + <field name="qr_code" attrs="{'invisible': [('provider', '!=', 'transfer')]}"/> + </group> + <group string="Availability" name="availability"> + <field name="country_ids" widget="many2many_tags" placeholder="Select countries. Leave empty to use everywhere."/> + </group> + <group string="Payment Followup" name="payment_followup"> + <field name="journal_id" context="{'default_type': 'bank'}" + attrs="{'required': [('state', '!=', 'disabled'), ('provider', 'not in', ['manual', 'transfer'])]}"/> + </group> + </group> + </page> + <page string="Fees" name="fees" attrs="{'invisible': [('fees_implemented', '=', False)]}"> + <group name="payment_fees"> + <field name="fees_active"/> + <field name="fees_dom_fixed" attrs="{'invisible': [('fees_active', '=', False)]}"/> + <field name="fees_dom_var" attrs="{'invisible': [('fees_active', '=', False)]}"/> + <field name="fees_int_fixed" attrs="{'invisible': [('fees_active', '=', False)]}"/> + <field name="fees_int_var" attrs="{'invisible': [('fees_active', '=', False)]}"/> + </group> + </page> + <page string="Messages" + name="messages" + attrs="{'invisible': [('module_id', '=', True), ('module_state', '!=', 'installed')]}"> + <group> + <field name="pre_msg"/> + <field name="auth_msg" attrs="{'invisible': [('authorize_implemented', '=', False)]}"/> + <field name="pending_msg"/> + <field name="done_msg"/> + <field name="cancel_msg"/> + </group> + </page> + </notebook> + </sheet> + </form> + </field> + </record> + + + <!-- Acquirer Kanban View --> + <record id="acquirer_kanban" model="ir.ui.view"> + <field name="name">payment.acquirer.kanban</field> + <field name="model">payment.acquirer</field> + <field name="arch" type="xml"> + <kanban quick_create="false" create="true" class="o_kanban_payment_acquirer o_kanban_dashboard"> + <field name="id"/> + <field name="name"/> + <field name="description"/> + <field name="provider"/> + <field name="module_id"/> + <field name="module_state"/> + <field name="module_to_buy"/> + <field name="color"/> + <templates> + <t t-name="kanban-box"> + <t t-set="installed" t-value="!record.module_id.value || (record.module_id.value && record.module_state.raw_value === 'installed')"/> + <t t-set="to_buy" t-value="record.module_to_buy.raw_value === true"/> + <div t-attf-class="oe_kanban_global_click #{kanban_color(record.color.raw_value)}"> + <div class="o_payment_acquirer_desc"> + <div class="o_kanban_image"> + <img type="open" t-att-src="kanban_image('payment.acquirer', 'image_128', record.id.raw_value)" alt="Acquirer"/> + </div> + <h3 class="mt4"><t t-esc="record.name.value"/></h3> + <t t-if="record.description.raw_value" t-raw="record.description.raw_value"/> + </div> + <div class="o_payment_acquirer_bottom"> + <t t-if="installed"> + <field name="state" widget="label_selection" options="{'classes': {'enabled': 'success', 'test': 'warning', 'disabled' : 'danger'}}"/> + </t> + <button t-if="!installed and !selection_mode and !to_buy" type="object" class="btn btn-secondary float-right" name="button_immediate_install">Install</button> + <t t-if="!installed and to_buy"> + <button href="https://odoo.com/pricing?utm_source=db&utm_medium=module" class="btn btn-info btn-sm float_right">Upgrade</button> + <span class="badge badge-primary oe_inline o_enterprise_label">Enterprise</span> + </t> + <button t-if="installed and record.state.raw_value == 'disabled' and !selection_mode" type="edit" class="btn btn-primary float-right">Activate</button> + <button t-if="installed and record.state.raw_value in ['enabled', 'test'] and !selection_mode" type="edit" class="btn btn-primary float-right">Configure</button> + </div> + </div> + </t> + </templates> + </kanban> + </field> + </record> + + <record id="acquirer_list" model="ir.ui.view"> + <field name="name">payment.acquirer.list</field> + <field name="model">payment.acquirer</field> + <field name="arch" type="xml"> + <tree string="Payment Acquirers"> + <field name="sequence" widget="handle"/> + <field name="name"/> + <field name="provider"/> + <field name="state"/> + <field name="country_ids" widget="many2many_tags" optional="hide"/> + <field name="company_id" groups="base.group_multi_company"/> + </tree> + </field> + </record> + + <record id="acquirer_search" model="ir.ui.view"> + <field name="name">payment.acquirer.search</field> + <field name="model">payment.acquirer</field> + <field name="arch" type="xml"> + <search> + <field name="name" string="Acquirer" filter_domain="['|', ('name','ilike',self), ('description','ilike',self)]"/> + <field name="provider"/> + <filter name="acquirer_installed" string="Installed" domain="[('provider', '!=', 'manual')]"/> + <group expand="0" string="Group By"> + <filter string="Provider" name="provider" domain="[]" context="{'group_by': 'provider'}"/> + <filter string="State" name="state" domain="[]" context="{'group_by': 'state'}"/> + </group> + </search> + </field> + </record> + + <record id="action_payment_acquirer" model="ir.actions.act_window"> + <field name="name">Payment Acquirers</field> + <field name="res_model">payment.acquirer</field> + <field name='view_mode'>kanban,tree,form</field> + <field name="help" type="html"> + <p class="o_view_nocontent_smiling_face"> + Create a new payment acquirer + </p> + </field> + </record> + + <menuitem + action='action_payment_acquirer' + id='payment_acquirer_menu' + parent='account.root_payment_menu' + sequence='10' /> + + <!-- Payment transactions --> + <record id="transaction_form" model="ir.ui.view"> + <field name="name">payment.transaction.form</field> + <field name="model">payment.transaction</field> + <field name="arch" type="xml"> + <form string="Payment Transactions" create="false" edit="false"> + <header> + <button type="object" name="action_capture" states="authorized" string="Capture Transaction" class="oe_highlight"/> + <button type="object" name="action_void" states="authorized" string="Void Transaction" + confirm="Are you sure you want to void the authorized transaction? This action can't be undone."/> + <field name="state" widget="statusbar"/> + </header> + <sheet> + <div class="oe_button_box" name="button_box"> + <button name="action_view_invoices" type="object" + class="oe_stat_button" icon="fa-money" + attrs="{'invisible': [('invoice_ids_nbr', '=', 0)]}"> + <field name="invoice_ids_nbr" widget="statinfo" string="Invoice(s)"/> + </button> + </div> + <group> + <group> + <field name="reference"/> + <field name="payment_id"/> + <label for="amount"/> + <div class="o_row"> + <field name="amount"/> + <field name="currency_id" options="{'no_open': True, 'no_create': True}"/> + </div> + <field name="fees" readonly="1"/> + <label for="partner_id"/> + <div> + <field name="partner_id" context="{'show_address': 1}" options="{'always_reload': True}"/> + <div name="partner_details" class="o_address_format" attrs="{'invisible': [('partner_id', '!=', False)]}"> + <field name="partner_name" placeholder="Name" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_street"/> + <field name="partner_address" placeholder="Address" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_street"/> + <field name="partner_city" placeholder="City" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_city"/> + <field name="partner_zip" placeholder="ZIP" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_zip"/> + <field name="partner_country_id" placeholder="Country" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_country"/> + <field name="partner_lang" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_street"/> + <field name="partner_email" placeholder="E-mail" attrs="{'readonly': [('partner_id', '!=', False)]}" class="o_address_street"/> + </div> + </div> + </group> + <group> + <field name="acquirer_id"/> + <field name="provider" invisible="1"/> + <field name="payment_token_id" options="{'no_create': True}"/> + <field name="acquirer_reference" readonly="1"/> + <field name="date"/> + </group> + </group> + <group string="Message"> + <field name="state_message" nolabel="1"/> + </group> + </sheet> + </form> + </field> + </record> + + <record id="transaction_list" model="ir.ui.view"> + <field name="name">payment.transaction.list</field> + <field name="model">payment.transaction</field> + <field name="arch" type="xml"> + <tree string="Payment Transactions" create="false"> + <field name="reference"/> + <field name="create_date"/> + <field name="acquirer_id"/> + <field name="partner_id"/> + <field name="partner_name"/> + <field name="amount"/> + <field name="fees"/> + <field name="state"/> + </tree> + </field> + </record> + + <record id="transaction_view_kanban" model="ir.ui.view"> + <field name="name">payment.transaction.kanban</field> + <field name="model">payment.transaction</field> + <field name="arch" type="xml"> + <kanban class="o_kanban_mobile" create="false"> + <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="reference"/></strong> + </div> + <div class="col-6"> + <span><field name="partner_name"/></span> + </div> + <div class="col-6"> + <span class="float-right"> + <field name="amount" widget="monetary"/> + <field name="currency_id" invisible="1"/> + </span> + </div> + </div> + </div> + </t> + </templates> + </kanban> + </field> + </record> + + <record id="transaction" model="ir.ui.view"> + <field name="name">payment.transaction.search</field> + <field name="model">payment.transaction</field> + <field name="arch" type="xml"> + <search> + <field name="reference"/> + <field name="acquirer_id"/> + <field name="partner_id"/> + <field name="partner_name"/> + </search> + </field> + </record> + + <record id="action_payment_transaction" model="ir.actions.act_window"> + <field name="name">Payment Transactions</field> + <field name="res_model">payment.transaction</field> + <field name='view_mode'>tree,kanban,form</field> + <field name="help" type="html"> + <p class="o_view_nocontent_smiling_face"> + Create a new payment transaction + </p> + </field> + </record> + + <menuitem + action='action_payment_transaction' + id='payment_transaction_menu' + parent='account.root_payment_menu' + groups="base.group_no_one" + sequence='20' /> + + <!-- Payment Tokens --> + <record model='ir.ui.view' id='payment_token_tree_view'> + <field name='name'>payment.token.tree</field> + <field name='model'>payment.token</field> + <field name='arch' type='xml'> + <tree string='Payment Tokens'> + <field name="name"/> + <field name="active"/> + <field name='partner_id' /> + <field name='acquirer_id' readonly='1'/> + <field name='acquirer_ref' readonly='1'/> + </tree> + </field> + </record> + + <record id='payment_token_view_search' model='ir.ui.view'> + <field name='name'>payment.token.search</field> + <field name='model'>payment.token</field> + <field name='arch' type='xml'> + <search string='Payment Tokens'> + <field name='partner_id'/> + <separator/> + <filter string="Archived" name="inactive" domain="[('active', '=', False)]"/> + </search> + </field> + </record> + + <record id="action_payment_tx_ids" model="ir.actions.act_window"> + <field name="name">Payment Transactions</field> + <field name="res_model">payment.transaction</field> + <field name="view_mode">tree,form</field> + <field name="domain">[('payment_token_id','=', active_id)]</field> + <field name="context">{'create': False}</field> + </record> + + <record model='ir.ui.view' id='payment_token_form_view'> + <field name='name'>payment.token.form</field> + <field name='model'>payment.token</field> + <field name='arch' type='xml'> + <form string='Payment Tokens' create='false' editable='bottom'> + <sheet> + <div class="oe_button_box" name="button_box"> + <button class="oe_stat_button" name="%(action_payment_tx_ids)d" + type="action" icon="fa-money" string="Payments"> + </button> + </div> + <group> + <field name="name"/> + <field name='partner_id' /> + </group> + <group> + <field name="active" widget='boolean_toggle'/> + <field name='acquirer_id'/> + <field name='acquirer_ref'/> + </group> + </sheet> + </form> + </field> + </record> + + <record model='ir.actions.act_window' id='payment_token_action'> + <field name='name'>Saved Payment Data</field> + <field name='res_model'>payment.token</field> + <field name='view_mode'>tree,form</field> + <field name="help" type="html"> + <p class="o_view_nocontent_smiling_face"> + Create a saved payment data + </p> + </field> + </record> + + <menuitem + action='payment_token_action' + id='payment_token_menu' + parent='account.root_payment_menu' + groups='base.group_no_one'/> + + <!-- Payment icons --> + <record model="ir.ui.view" id="payment_icon_form_view"> + <field name="name">payment.icon.form</field> + <field name="model">payment.icon</field> + <field name="arch" type="xml"> + <form string="Payment Icon"> + <sheet> + <field name="image" widget="image" class="oe_avatar"/> + <div class="oe_title"> + <h1><field name="name" placeholder="Name"/></h1> + </div> + <notebook> + <page string="Acquirers list" name="acquirers"> + <field nolabel="1" name="acquirer_ids"/> + </page> + </notebook> + </sheet> + </form> + </field> + </record> + + <record id="action_payment_icon" model="ir.actions.act_window"> + <field name="name">Payment Icons</field> + <field name="res_model">payment.icon</field> + <field name="view_mode">tree,form</field> + <field name="help" type="html"> + <p class="o_view_nocontent_smiling_face"> + Create a payment icon + </p> + </field> + </record> + + <menuitem + action="action_payment_icon" + id="payment_icon_menu" + parent="account.root_payment_menu" + groups="base.group_no_one"/> + </data> +</odoo> diff --git a/addons/payment/views/res_partner_views.xml b/addons/payment/views/res_partner_views.xml new file mode 100644 index 00000000..7657ad09 --- /dev/null +++ b/addons/payment/views/res_partner_views.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<odoo> + <data> + + <!-- Add creditcard to res.partner --> + <record id="view_partners_form_payment_defaultcreditcard" model="ir.ui.view"> + <field name="name">view.res.partner.form.payment.defaultcreditcard</field> + <field name="model">res.partner</field> + <field name="inherit_id" ref="base.view_partner_form"/> + <field name="priority" eval="15"/> + <field name="arch" type="xml"> + <div name="button_box" position="inside"> + <button type="action" class="oe_stat_button" + icon="fa-credit-card" + name="%(payment.payment_token_action)d" + context="{'search_default_partner_id': active_id, 'create': False, 'edit': False}" + attrs="{'invisible': [('payment_token_count', '=', 0)]}"> + <div class="o_form_field o_stat_info"> + <span class="o_stat_value"> + <field name="payment_token_count" widget="statinfo" nolabel="1"/> + </span> + <span class="o_stat_text">Credit Cards</span> + </div> + </button> + </div> + </field> + </record> + </data> +</odoo> |
