This commit is contained in:
gsinghpal
2026-03-20 11:46:41 -04:00
parent 595dccc17d
commit 92369be6e0
71 changed files with 6588 additions and 8 deletions

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_move_form_clover_button" model="ir.ui.view">
<field name="name">account.move.form.clover.button</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="priority">60</field>
<field name="arch" type="xml">
<!-- Clover Refund smart button on invoices -->
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_view_clover_refunds"
type="object"
class="oe_stat_button"
icon="fa-undo"
invisible="clover_refund_count == 0">
<field name="clover_refund_count" widget="statinfo" string="Clover Refunds"/>
</button>
</xpath>
<!-- Collect payment button on invoices -->
<xpath expr="//button[@id='account_invoice_payment_btn']" position="after">
<button name="action_open_clover_payment_wizard"
string="Collect Clover Payment"
type="object"
class="btn-secondary"
icon="fa-credit-card"
invisible="state != 'posted' or payment_state not in ('not_paid', 'partial') or move_type != 'out_invoice' or not clover_provider_enabled"
groups="fusion_clover.group_fusion_clover_user"
data-hotkey="p"/>
</xpath>
<!-- Refund via Clover button on credit notes -->
<xpath expr="//button[@id='account_invoice_payment_btn']" position="after">
<button name="action_open_clover_refund_wizard"
string="Refund via Clover"
type="object"
class="btn-secondary"
icon="fa-undo"
invisible="state != 'posted' or payment_state not in ('not_paid', 'partial') or move_type != 'out_refund' or clover_refunded or not clover_provider_enabled"
groups="fusion_clover.group_fusion_clover_user"
data-hotkey="r"/>
</xpath>
<!-- Resend Receipt button on invoices -->
<xpath expr="//button[@id='account_invoice_payment_btn']" position="after">
<button name="action_resend_clover_receipt"
string="Resend Receipt"
type="object"
class="btn-secondary"
icon="fa-envelope"
invisible="state != 'posted' or move_type != 'out_invoice' or not has_clover_receipt"
groups="fusion_clover.group_fusion_clover_user"/>
</xpath>
<!-- Resend Receipt button on credit notes -->
<xpath expr="//button[@id='account_invoice_payment_btn']" position="after">
<button name="action_resend_clover_receipt"
string="Resend Refund Receipt"
type="object"
class="btn-secondary"
icon="fa-envelope"
invisible="state != 'posted' or move_type != 'out_refund' or not clover_refunded"
groups="fusion_clover.group_fusion_clover_user"/>
</xpath>
<!-- Refunded banner on credit notes -->
<xpath expr="//header" position="before">
<div class="alert alert-info text-center mb-0"
role="status"
invisible="not clover_refunded">
<strong>Refunded via Clover</strong> — This credit note has been
refunded to the customer's card through Clover.
</div>
<field name="clover_refunded" invisible="1"/>
<field name="has_clover_receipt" invisible="1"/>
<field name="clover_provider_enabled" invisible="1"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Terminal form view -->
<record id="clover_terminal_form" model="ir.ui.view">
<field name="name">clover.terminal.form</field>
<field name="model">clover.terminal</field>
<field name="arch" type="xml">
<form string="Clover Terminal">
<header>
<button name="action_refresh_status"
string="Ping Device"
type="object"
class="btn-primary"
icon="fa-wifi"/>
<button name="action_display_welcome"
string="Display Welcome"
type="object"
class="btn-secondary"
icon="fa-tv"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box"/>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger"
invisible="active"/>
<group>
<group string="Device Information">
<field name="name" placeholder="e.g. Front Desk, Back Office"/>
<field name="clover_device_name" readonly="1"
invisible="not clover_device_name"/>
<field name="serial_number"/>
<field name="device_id" readonly="1"/>
<field name="model_name" readonly="1"/>
</group>
<group string="Status">
<field name="provider_id"/>
<field name="status"/>
<field name="last_seen"/>
<field name="active" invisible="1"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- Terminal list view -->
<record id="clover_terminal_list" model="ir.ui.view">
<field name="name">clover.terminal.list</field>
<field name="model">clover.terminal</field>
<field name="arch" type="xml">
<list string="Clover Terminals">
<field name="name"/>
<field name="serial_number"/>
<field name="model_name"/>
<field name="provider_id"/>
<field name="status" decoration-success="status == 'online'"
decoration-danger="status == 'offline'"
decoration-warning="status == 'unknown'"
widget="badge"/>
<field name="last_seen"/>
</list>
</field>
</record>
<!-- Terminal action -->
<record id="action_clover_terminals" model="ir.actions.act_window">
<field name="name">Clover Terminals</field>
<field name="res_model">clover.terminal</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No Clover terminals configured yet.
</p>
<p>
Use the "Sync Terminals" button on the Clover payment provider
to automatically fetch devices from your merchant account,
or add them manually.
</p>
</field>
</record>
<!-- Menu item under Accounting > Configuration -->
<menuitem id="menu_clover_terminals"
name="Clover Terminals"
parent="account.menu_finance_configuration"
action="action_clover_terminals"
sequence="40"
groups="fusion_clover.group_fusion_clover_admin"/>
<!-- Add Sync Terminals button to payment provider form -->
<record id="payment_provider_form_terminal_button" model="ir.ui.view">
<field name="name">payment.provider.form.clover.terminal</field>
<field name="model">payment.provider</field>
<field name="inherit_id" ref="fusion_clover.payment_provider_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_clover_test_connection']" position="after">
<button string="Sync Terminals"
type="object"
name="action_sync_terminals"
class="btn-secondary"
icon="fa-refresh"
invisible="not clover_merchant_id or (not clover_rest_api_token and not clover_api_key)"
colspan="2"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inline payment form template for Clover -->
<template id="inline_form">
<t t-set="inline_form_values"
t-value="provider_sudo._clover_get_inline_form_values(
amount,
currency,
partner_id,
mode == 'validation',
payment_method_sudo=pm_sudo,
)"
/>
<div name="o_clover_payment_container"
class="o_clover_payment_form"
t-att-data-clover-inline-form-values="inline_form_values">
<!-- Terminal toggle -->
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input"
id="clover_use_terminal" name="use_terminal"/>
<label class="form-check-label" for="clover_use_terminal">
<i class="fa fa-credit-card-alt me-1"/>
Pay on Clover Terminal
</label>
</div>
<!-- Terminal select (hidden by default) -->
<div class="mb-3" id="clover_terminal_select_wrapper" style="display:none;">
<label class="form-label" for="clover_terminal_select">Select Terminal</label>
<select class="form-select" id="clover_terminal_select" name="terminal_id">
<option value="">Loading terminals...</option>
</select>
</div>
<!-- Card number input -->
<div class="mb-3">
<label class="form-label" for="clover_card_number">Card Number</label>
<input type="text" class="form-control"
id="clover_card_number"
name="card_number"
placeholder="4111 1111 1111 1111"
maxlength="19"
autocomplete="cc-number"
required="required"/>
</div>
<!-- Expiry and CVV row -->
<div class="row mb-3">
<div class="col-6">
<label class="form-label" for="clover_expiry">Expiry Date</label>
<input type="text" class="form-control"
id="clover_expiry"
name="expiry"
placeholder="MM/YY"
maxlength="5"
autocomplete="cc-exp"
required="required"/>
</div>
<div class="col-6">
<label class="form-label" for="clover_cvv">CVV</label>
<input type="password" class="form-control"
id="clover_cvv"
name="cvv"
placeholder="123"
maxlength="4"
autocomplete="cc-csc"
required="required"/>
</div>
</div>
<!-- Cardholder name -->
<div class="mb-3">
<label class="form-label" for="clover_cardholder">Cardholder Name</label>
<input type="text" class="form-control"
id="clover_cardholder"
name="cardholder_name"
placeholder="John Doe"
autocomplete="cc-name"/>
</div>
<!-- Card type selector -->
<div class="mb-3 o_clover_card_type_section" style="display:none;">
<label class="form-label">Card Type</label>
<div class="d-flex gap-2 flex-wrap">
<div class="form-check">
<input type="radio" class="form-check-input" name="clover_card_type"
id="clover_ct_visa" value="visa"/>
<label class="form-check-label" for="clover_ct_visa">Visa</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" name="clover_card_type"
id="clover_ct_mc" value="mastercard"/>
<label class="form-check-label" for="clover_ct_mc">Mastercard</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" name="clover_card_type"
id="clover_ct_amex" value="amex"/>
<label class="form-check-label" for="clover_ct_amex">Amex</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" name="clover_card_type"
id="clover_ct_other" value="other" checked="checked"/>
<label class="form-check-label" for="clover_ct_other">Other</label>
</div>
</div>
</div>
<!-- Surcharge notice -->
<div class="mb-3 o_clover_surcharge_notice" style="display:none;">
<div class="alert alert-info py-2 mb-0">
<small>
<i class="fa fa-info-circle me-1"/>
<span>A credit card processing fee of </span>
<strong id="clover_surcharge_rate">0.00</strong>
<span>% (<strong id="clover_surcharge_amount">$0.00</strong>) will be added to your total.</span>
</small>
</div>
</div>
</div>
</template>
</odoo>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_provider_form" model="ir.ui.view">
<field name="name">Clover Provider Form</field>
<field name="model">payment.provider</field>
<field name="inherit_id" ref="payment.payment_provider_form"/>
<field name="arch" type="xml">
<group name="provider_credentials" position="inside">
<group invisible="code != 'clover'" name="clover_credentials">
<separator string="Merchant"/>
<field name="clover_merchant_id"
required="code == 'clover' and state != 'disabled'"
placeholder="e.g. 22701620015"/>
<separator string="Ecommerce API Tokens"/>
<field name="clover_api_key"
required="code == 'clover' and state != 'disabled'"
password="True"
placeholder="Private token from Ecommerce API Tokens page"/>
<field name="clover_public_key"
placeholder="Public token from Ecommerce API Tokens page"/>
<separator string="REST API / Terminal"/>
<field name="clover_rest_api_token"
password="True"
placeholder="From Clover Dashboard: Setup > API Tokens"/>
<separator string="OAuth (Optional)"/>
<field name="clover_app_id"
placeholder="App ID (for OAuth flow)"/>
<label for="clover_app_secret"/>
<div class="o_row" col="2">
<field name="clover_app_secret" password="True"/>
</div>
</group>
</group>
<group name="provider_credentials" position="after">
<group string="Clover Actions"
invisible="code != 'clover'" name="clover_actions"
col="4">
<button string="Test Connection"
type="object"
name="action_clover_test_connection"
class="btn-primary"
invisible="not clover_merchant_id or (not clover_api_key and not clover_rest_api_token)"
colspan="2"/>
</group>
<group string="Terminal Settings"
invisible="code != 'clover'" name="clover_terminal_settings">
<field name="clover_default_terminal_id"/>
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_transaction_form_inherit_clover" model="ir.ui.view">
<field name="name">payment.transaction.form.inherit.clover</field>
<field name="model">payment.transaction</field>
<field name="inherit_id" ref="payment.payment_transaction_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='provider_reference']" position="after">
<field name="clover_charge_id"
invisible="provider_code != 'clover'"
readonly="1"/>
<field name="clover_refund_id"
invisible="provider_code != 'clover' or not clover_refund_id"
readonly="1"/>
<field name="clover_order_id"
invisible="provider_code != 'clover' or not clover_order_id"
readonly="1"/>
<field name="clover_voided"
invisible="provider_code != 'clover' or not clover_voided"
readonly="1"/>
<field name="clover_void_date"
invisible="provider_code != 'clover' or not clover_voided"
readonly="1"/>
</xpath>
<!-- Void button on Clover transactions -->
<xpath expr="//header" position="inside">
<button name="action_clover_void"
string="Void Transaction"
type="object"
class="btn-danger"
icon="fa-ban"
invisible="provider_code != 'clover' or state != 'done' or clover_voided"
confirm="Are you sure you want to void this transaction? This cannot be undone."
groups="fusion_clover.group_fusion_clover_admin"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form_fusion_clover" model="ir.ui.view">
<field name="name">res.config.settings.view.form.fusion.clover</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//form" position="inside">
<app data-string="Fusion Clover" string="Fusion Clover" name="fusion_clover"
groups="fusion_clover.group_fusion_clover_admin">
<h2>Credit Card Surcharge</h2>
<div class="row mt-4 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="clover_surcharge_enabled"/>
</div>
<div class="o_setting_right_pane">
<span class="o_form_label">Credit Card Processing Fee</span>
<div class="text-muted">
Automatically add a surcharge line to invoices when collecting payment
via Clover. The fee is calculated as a percentage of the invoice total.
</div>
</div>
</div>
</div>
<div class="row mt-4 o_settings_container"
invisible="not clover_surcharge_enabled">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<span class="o_form_label">Surcharge Rates by Card Type</span>
<div class="text-muted mb-2">
Configure the processing fee percentage for each card brand.
</div>
<div class="mt-2">
<div class="row mb-2">
<label for="clover_surcharge_visa_rate"
class="col-5 col-form-label">Visa</label>
<div class="col-4">
<field name="clover_surcharge_visa_rate" class="o_input"/>
</div>
<div class="col-1 col-form-label">%</div>
</div>
<div class="row mb-2">
<label for="clover_surcharge_mastercard_rate"
class="col-5 col-form-label">Mastercard</label>
<div class="col-4">
<field name="clover_surcharge_mastercard_rate" class="o_input"/>
</div>
<div class="col-1 col-form-label">%</div>
</div>
<div class="row mb-2">
<label for="clover_surcharge_amex_rate"
class="col-5 col-form-label">American Express</label>
<div class="col-4">
<field name="clover_surcharge_amex_rate" class="o_input"/>
</div>
<div class="col-1 col-form-label">%</div>
</div>
<div class="row mb-2">
<label for="clover_surcharge_debit_rate"
class="col-5 col-form-label">Debit</label>
<div class="col-4">
<field name="clover_surcharge_debit_rate" class="o_input"/>
</div>
<div class="col-1 col-form-label">%</div>
</div>
<div class="row mb-2">
<label for="clover_surcharge_other_rate"
class="col-5 col-form-label">Other Cards</label>
<div class="col-4">
<field name="clover_surcharge_other_rate" class="o_input"/>
</div>
<div class="col-1 col-form-label">%</div>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<span class="o_form_label">Surcharge Product</span>
<div class="text-muted mb-2">
The service product used for the processing fee invoice line.
</div>
<div class="mt-2">
<field name="clover_surcharge_product_id"
domain="[('type', '=', 'service')]"/>
</div>
</div>
</div>
</div>
<h2>Quick Links</h2>
<div class="row mt-4 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<span class="o_form_label">Payment Provider</span>
<div class="text-muted mb-2">
Configure your Clover API credentials and merchant ID.
</div>
<div class="mt-2">
<button name="action_open_clover_provider"
type="object"
string="Configure Payment Provider"
class="btn-link"
icon="fa-arrow-right"/>
</div>
</div>
</div>
</div>
</app>
</xpath>
</field>
</record>
<record id="action_fusion_clover_settings" model="ir.actions.act_window">
<field name="name">Fusion Clover Settings</field>
<field name="res_model">res.config.settings</field>
<field name="view_mode">form</field>
<field name="target">current</field>
<field name="context" eval="{'module': 'fusion_clover'}"/>
</record>
</odoo>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_order_form_clover_button" model="ir.ui.view">
<field name="name">sale.order.form.clover.button</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="priority">60</field>
<field name="arch" type="xml">
<xpath expr="//button[@id='create_invoice']" position="after">
<field name="clover_provider_enabled" invisible="1"/>
<button name="action_clover_collect_payment"
string="Collect Payment"
type="object"
class="btn-secondary"
icon="fa-credit-card"
invisible="state not in ('sale', 'done') or not clover_provider_enabled"
groups="fusion_clover.group_fusion_clover_user"
data-hotkey="p"/>
</xpath>
</field>
</record>
</odoo>