[IMP] point_of_sale, pos_adyen, pos_mercury: payment terminal per method

For now when you are using payment terminals in the point of sale, you
have different way to configure payment temrminals, for the IOT, you
have to select the payment terminal in the pos config, and for adyen and
ventiv you have to configure them in the payment method.

So we've modified it to always configure payment terminal on payment
mehthod, and not on the pos config anymore, with iot you'll be able to
select the specific device you want to use, even if it is not on the iot
box set on the pos config.

closes odoo/odoo#35665

Task-id: 2042382
Signed-off-by: pimodoo <pimodoo@users.noreply.github.com>
This commit is contained in:
Joseph Caburnay
2019-09-09 14:08:51 +00:00
committed by Pierre Masereel
parent 7c6c76d021
commit d6543adc05
13 changed files with 88 additions and 51 deletions
@@ -19,6 +19,9 @@ class PosPaymentMethod(models.Model):
_description = "Point of Sale Payment Methods"
_order = "id asc"
def _get_payment_terminal_selection(self):
return []
name = fields.Char(string="Payment Method", required=True)
receivable_account_id = fields.Many2one('account.account',
string='Intermediary Account',
@@ -40,19 +43,25 @@ class PosPaymentMethod(models.Model):
open_session_ids = fields.Many2many('pos.session', string='Pos Sessions', compute='_compute_open_session_ids', help='Open PoS sessions that are using this payment method.')
config_ids = fields.Many2many('pos.config', string='Point of Sale Configurations')
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company)
use_payment_terminal = fields.Selection([], 'Use a Payment Terminal', help='Record payments with a terminal on this journal.')
use_payment_terminal = fields.Selection(selection=lambda self: self._get_payment_terminal_selection(), string='Use a Payment Terminal', help='Record payments with a terminal on this journal.')
hide_use_payment_terminal = fields.Boolean(compute='_compute_hide_use_payment_terminal', help='Technical field which is used to '
'hide use_payment_terminal when no payment interfaces are installed.')
@api.depends('is_cash_count')
def _compute_hide_use_payment_terminal(self):
no_terminals = not bool(self._fields['use_payment_terminal'].selection)
no_terminals = not bool(self._fields['use_payment_terminal'].selection(self))
for payment_method in self:
payment_method.hide_use_payment_terminal = no_terminals
payment_method.hide_use_payment_terminal = no_terminals or payment_method.is_cash_count
@api.onchange('use_payment_terminal')
def _onchange_use_payment_terminal(self):
"""Used by inheriting model to unset the value of the field related to the unselected payment terminal."""
pass
@api.depends('config_ids')
def _compute_open_session_ids(self):
for payment_method in self:
self.open_session_ids = self.env['pos.session'].search([('config_id', 'in', payment_method.config_ids.ids), ('state', '!=', 'closed')])
payment_method.open_session_ids = self.env['pos.session'].search([('config_id', 'in', payment_method.config_ids.ids), ('state', '!=', 'closed')])
@api.onchange('is_cash_count')
def _onchange_is_cash_count(self):
@@ -7,4 +7,5 @@ class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
sale_tax_id = fields.Many2one('account.tax', string="Default Sale Tax", related='company_id.account_sale_tax_id', readonly=False)
module_pos_mercury = fields.Boolean(string="Integrated Card Payments", help="The transactions are processed by Vantiv. Set your Vantiv credentials on the related payment journal.")
module_pos_mercury = fields.Boolean(string="Vantiv Payment Terminal", help="The transactions are processed by Vantiv. Set your Vantiv credentials on the related payment method.")
module_pos_adyen = fields.Boolean(string="Adyen Payment Terminal", help="The transactions are processed by Adyen. Set your Adyen credentials on the related payment method.")
@@ -17,10 +17,10 @@
<field name="is_cash_count" />
<field name="cash_journal_id" attrs="{'invisible': [('is_cash_count', '=', False)], 'required': [('is_cash_count', '=', True)]}" />
<field name="split_transactions" groups="base.group_no_one" />
<field name="use_payment_terminal" attrs="{'invisible': ['|', ('is_cash_count', '=', True), ('hide_use_payment_terminal', '=', True)]}"/>
<field name="company_id" readonly="1" groups="base.group_multi_company" />
</group>
<group>
<field name="use_payment_terminal" attrs="{'invisible': [('hide_use_payment_terminal', '=', True)]}" widget="radio" />
</group>
</group>
</sheet>
@@ -33,10 +33,12 @@
<field name="model">pos.payment.method</field>
<field name="arch" type="xml">
<tree string="Payment Methods">
<field name="hide_use_payment_terminal" invisible="1"/>
<field name="name" />
<field name="receivable_account_id" groups="account.group_account_user"/>
<field name="is_cash_count" />
<field name="split_transactions" groups="base.group_no_one" />
<field name="use_payment_terminal" attrs="{'invisible': [('hide_use_payment_terminal', '=', True)]}" />
<field name="company_id" groups="base.group_multi_company" />
</tree>
</field>
@@ -66,24 +66,34 @@
</div>
</div>
</div>
<h2>Payments</h2>
<div class="row mt16 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box" title="The transactions are processed by Vantiv. Set your Vantiv credentials on the related payment journal.">
<h2>Payment Terminals</h2>
<div class="row mt16 o_settings_container" id="o_settings_use_payment_terminals">
<div class="col-12 col-lg-6 o_setting_box" title="The transactions are processed by Vantiv. Set your Vantiv credentials on the related payment method.">
<div class="o_setting_left_pane">
<field name="module_pos_mercury"/>
</div>
<div class="o_setting_right_pane">
<label for="module_pos_mercury" string="Credit Card Reader"/>
<label for="module_pos_mercury" string="Vantiv (US &amp; Canada)"/>
<div class="text-muted">
Accept payments with a credit card reader
Accept payments with a Vantiv payment terminal
</div>
<div class="content-group" attrs="{'invisible': [('module_pos_mercury', '=', False)]}">
<div class="mt16" id="btn_use_pos_mercury">
<button string="Save" type="object" name="execute" class="oe_highlight"/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" title="The transactions are processed by Adyen. Set your Adyen credentials on the related payment method.">
<div class="o_setting_left_pane">
<field name="module_pos_adyen"/>
</div>
<div class="o_setting_right_pane">
<label for="module_pos_adyen" string="Adyen"/>
<div class="text-muted">
Accept payments with an Adyen payment terminal
</div>
</div>
</div>
</div>
</div>
</xpath>
+10 -1
View File
@@ -15,7 +15,9 @@ _logger = logging.getLogger(__name__)
class PosPaymentMethod(models.Model):
_inherit = 'pos.payment.method'
use_payment_terminal = fields.Selection(selection_add=[('adyen', 'Adyen')])
def _get_payment_terminal_selection(self):
return super(PosPaymentMethod, self)._get_payment_terminal_selection() + [('adyen', 'Adyen')]
adyen_api_key = fields.Char(string="Adyen API key", help='Used when connecting to Adyen: https://docs.adyen.com/user-management/how-to-get-the-api-key/#description', copy=False)
adyen_terminal_identifier = fields.Char(help='[Terminal model]-[Serial number], for example: P400Plus-123456789', copy=False)
adyen_test_mode = fields.Boolean(help='Run transactions in the test environment.')
@@ -116,3 +118,10 @@ class PosPaymentMethod(models.Model):
return True
return req.json()
@api.onchange('use_payment_terminal')
def _onchange_use_payment_terminal(self):
super(PosPaymentMethod, self)._onchange_use_payment_terminal()
if self.use_payment_terminal != 'adyen':
self.adyen_api_key = False
self.adyen_terminal_identifier = False
@@ -5,14 +5,12 @@
<field name="model">pos.payment.method</field>
<field name="inherit_id" ref="point_of_sale.pos_payment_method_view_form"/>
<field name="arch" type="xml">
<group name="Payment methods" position="inside">
<group>
<field name="adyen_api_key"
attrs="{'invisible': [('use_payment_terminal', '!=', 'adyen')], 'required': [('use_payment_terminal', '=', 'adyen')]}"/>
<field name="adyen_terminal_identifier" attrs="{'invisible': [('use_payment_terminal', '!=', 'adyen')], 'required': [('use_payment_terminal', '=', 'adyen')]}"/>
<field name="adyen_test_mode" attrs="{'invisible': [('use_payment_terminal', '!=', 'adyen')]}"/>
</group>
</group>
<xpath expr="//field[@name='use_payment_terminal']" position="after">
<field name="adyen_api_key"
attrs="{'invisible': [('use_payment_terminal', '!=', 'adyen')], 'required': [('use_payment_terminal', '=', 'adyen')]}"/>
<field name="adyen_terminal_identifier" attrs="{'invisible': [('use_payment_terminal', '!=', 'adyen')], 'required': [('use_payment_terminal', '=', 'adyen')]}"/>
<field name="adyen_test_mode" attrs="{'invisible': [('use_payment_terminal', '!=', 'adyen')]}"/>
</xpath>
</field>
</record>
</odoo>
+3 -3
View File
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Mercury Payment Services',
'name': 'Vantiv Payment Services',
'version': '1.0',
'category': 'Point of Sale',
'sequence': 6,
@@ -12,8 +12,8 @@ Allow credit card POS payments
==============================
This module allows customers to pay for their orders with credit
cards. The transactions are processed by Mercury (developed by Wells
Fargo Bank). A Mercury merchant account is necessary. It allows the
cards. The transactions are processed by Vantiv (developed by Wells
Fargo Bank). A Vantiv merchant account is necessary. It allows the
following:
* Fast payment by just swiping a credit card while on the payment screen
+2 -2
View File
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
<odoo>
<data>
<!-- Mercury Production Test Account (e2e + token) -->
<!-- Vantiv Production Test Account (e2e + token) -->
<!-- This is a test account for testing with test cards and cannot be used in a live environment -->
<record id="pos_mercury_configuration" model="pos_mercury.configuration">
<field name="name">Mercury Demo</field>
<field name="name">Vantiv Demo</field>
<field name="merchant_id">755847002</field>
<field name="merchant_pwd">xyz</field>
</record>
+14 -6
View File
@@ -19,9 +19,9 @@ class BarcodeRule(models.Model):
class PosMercuryConfiguration(models.Model):
_name = 'pos_mercury.configuration'
_description = 'Point of Sale Mercury Configuration'
_description = 'Point of Sale Vantiv Configuration'
name = fields.Char(required=True, help='Name of this Mercury configuration')
name = fields.Char(required=True, help='Name of this Vantiv configuration')
merchant_id = fields.Char(string='Merchant ID', required=True, help='ID of the merchant to authenticate him on the payment provider server')
merchant_pwd = fields.Char(string='Merchant Password', required=True, help='Password of the merchant to authenticate him on the payment provider server')
@@ -33,9 +33,9 @@ class PoSPayment(models.Model):
mercury_prefixed_card_number = fields.Char(string='Card Number Prefix', compute='_compute_prefixed_card_number', help='The card number used for the payment.')
mercury_card_brand = fields.Char(string='Card Brand', help='The brand of the payment card (e.g. Visa, AMEX, ...)')
mercury_card_owner_name = fields.Char(string='Card Owner Name', help='The name of the card owner')
mercury_ref_no = fields.Char(string='Mercury reference number', help='Payment reference number from Mercury Pay')
mercury_record_no = fields.Char(string='Mercury record number', help='Payment record number from Mercury Pay')
mercury_invoice_no = fields.Char(string='Mercury invoice number', help='Invoice number from Mercury Pay')
mercury_ref_no = fields.Char(string='Vantiv reference number', help='Payment reference number from Vantiv Pay')
mercury_record_no = fields.Char(string='Vantiv record number', help='Payment record number from Vantiv Pay')
mercury_invoice_no = fields.Char(string='Vantiv invoice number', help='Invoice number from Vantiv Pay')
def _compute_prefixed_card_number(self):
for line in self:
@@ -48,8 +48,16 @@ class PoSPayment(models.Model):
class PoSPaymentMethod(models.Model):
_inherit = 'pos.payment.method'
pos_mercury_config_id = fields.Many2one('pos_mercury.configuration', string='Mercury Credentials', help='The configuration of Mercury used for this journal')
pos_mercury_config_id = fields.Many2one('pos_mercury.configuration', string='Vantiv Credentials', help='The configuration of Vantiv used for this journal')
def _get_payment_terminal_selection(self):
return super(PoSPaymentMethod, self)._get_payment_terminal_selection() + [('mercury', 'Vantiv')]
@api.onchange('use_payment_terminal')
def _onchange_use_payment_terminal(self):
super(PoSPaymentMethod, self)._onchange_use_payment_terminal()
if self.use_payment_terminal != 'mercury':
self.pos_mercury_config_id = False
class PosOrder(models.Model):
_inherit = "pos.order"
@@ -14,7 +14,7 @@ from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, misc
class MercuryTransaction(models.Model):
_name = 'pos_mercury.mercury_transaction'
_description = 'Point of Sale Mercury Transaction'
_description = 'Point of Sale Vantiv Transaction'
def _get_pos_session(self):
pos_session = self.env['pos.session'].search([('state', '=', 'opened'), ('user_id', '=', self.env.uid)], limit=1)
@@ -31,7 +31,7 @@ class MercuryTransaction(models.Model):
if payment_method and payment_method.pos_mercury_config_id:
return payment_method.pos_mercury_config_id
else:
raise UserError(_("No Mercury configuration associated with the payment method."))
raise UserError(_("No Vantiv configuration associated with the payment method."))
def _setup_request(self, data):
# todo: in master make the client include the pos.session id and use that
@@ -112,7 +112,7 @@ class MercuryTransaction(models.Model):
response = self._do_request('pos_mercury.mercury_return', data)
return response
# One time (the ones we use) Mercury tokens are required to be
# One time (the ones we use) Vantiv tokens are required to be
# deleted after 6 months
@api.model
def cleanup_old_tokens(self):
@@ -255,10 +255,10 @@ ScreenWidget.include({
// On Payment screen, allow online payments
PaymentScreenWidget.include({
// How long we wait for the odoo server to deliver the response of
// a Mercury transaction
// a Vantiv transaction
server_timeout_in_ms: 95000,
// How many Mercury transactions we send without receiving a
// How many Vantiv transactions we send without receiving a
// response
server_retries: 3,
@@ -313,7 +313,7 @@ PaymentScreenWidget.include({
message = "Error " + response.error + ": " + lookUpCodeTransaction["TimeoutError"][response.error] + "<br/>" + response.message;
} else {
if (can_connect_to_server) {
message = _t("No response from Mercury (Mercury down?)");
message = _t("No response from Vantiv (Vantiv down?)");
} else {
message = _t("No response from server (connected to network?)");
}
@@ -393,7 +393,7 @@ PaymentScreenWidget.include({
timeout: self.server_timeout_in_ms,
})
.then(function (data) {
// if not receiving a response from Mercury, we should retry
// if not receiving a response from Vantiv, we should retry
if (data === "timeout") {
self.retry_mercury_transaction(def, null, retry_nr, true, self.credit_code_transaction, [parsed_result, def, retry_nr + 1]);
return;
@@ -401,7 +401,7 @@ PaymentScreenWidget.include({
if (data === "not setup") {
def.resolve({
message: _t("Please setup your Mercury merchant account.")
message: _t("Please setup your Vantiv merchant account.")
});
return;
}
@@ -24,7 +24,7 @@
<EncryptedFormat>MagneSafe</EncryptedFormat>
</Account>
<Amount>
<Purchase><t t-esc='"%.2f" % purchase'/></Purchase> <!-- format required by Mercury -->
<Purchase><t t-esc='"%.2f" % purchase'/></Purchase> <!-- format required by Vantiv -->
</Amount>
</Transaction>
</TStream>
@@ -38,7 +38,7 @@
<RecordNo><t t-esc='record_no'/></RecordNo>
<Memo><t t-esc='memo'/></Memo>
<Amount>
<Purchase><t t-esc='"%.2f" % authorize'/></Purchase> <!-- format required by Mercury -->
<Purchase><t t-esc='"%.2f" % authorize'/></Purchase> <!-- format required by Vantiv -->
</Amount>
<TranInfo>
<AuthCode><t t-esc='auth_code'/></AuthCode>
@@ -2,7 +2,7 @@
<odoo>
<data>
<record id="view_pos_mercury_configuration_form" model="ir.ui.view" >
<field name="name">Mercury Configurations</field>
<field name="name">Vantiv Configurations</field>
<field name="model">pos_mercury.configuration</field>
<field name="arch" type="xml">
<form string="Card Reader">
@@ -13,8 +13,8 @@
</div>
<div>
<p>
<i>Mercury Configurations</i> define what Mercury account will be used when
processing credit card transactions in the Point Of Sale. Setting up a Mercury
<i>Vantiv Configurations</i> define what Vantiv account will be used when
processing credit card transactions in the Point Of Sale. Setting up a Vantiv
configuration will enable you to allow payments with various credit cards
(eg. Visa, MasterCard, Discovery, American Express, ...). After setting up this
configuration you should associate it with a Point Of Sale payment method.
@@ -22,7 +22,7 @@
We currently support the MagTek Dynamag card reader device. It can be connected
directly to the Point Of Sale device or it can be connected to the IoTBox.
</p><p>
Using the Mercury integration in the Point Of Sale is easy: just press the
Using the Vantiv integration in the Point Of Sale is easy: just press the
associated payment method. After that the amount can be adjusted (eg. for cashback)
just like on any other payment line. Whenever the payment line is set up, a card
can be swiped through the card reader device.
@@ -31,7 +31,7 @@
(without having pressed anything else) will charge the full amount of the order to
the card.
</p><p>
If you don't already have a Mercury account, contact Mercury at +1 (800) 846-4472
If you don't already have a Vantiv account, contact Vantiv at +1 (800) 846-4472
to create one.
</p>
</div>
@@ -45,7 +45,7 @@
</record>
<record id="view_pos_mercury_configuration_tree" model="ir.ui.view">
<field name="name">Mercury Configurations</field>
<field name="name">Vantiv Configurations</field>
<field name="model">pos_mercury.configuration</field>
<field name="arch" type="xml">
<tree string="Card Reader">
@@ -56,7 +56,7 @@
</record>
<record id="action_configuration_form" model="ir.actions.act_window">
<field name="name">Mercury Configurations</field>
<field name="name">Vantiv Configurations</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos_mercury.configuration</field>
<field name="view_mode">tree,kanban,form</field>
@@ -72,8 +72,8 @@
<field name="model">pos.payment.method</field>
<field name="inherit_id" ref="point_of_sale.pos_payment_method_view_form"></field>
<field name="arch" type="xml">
<xpath expr="//field[@name='company_id']" position="after">
<field name="pos_mercury_config_id" attrs="{'invisible': [('is_cash_count', '=', True)]}"/>
<xpath expr="//field[@name='use_payment_terminal']" position="after">
<field name="pos_mercury_config_id" attrs="{'invisible': [('use_payment_terminal', '!=', 'mercury')], 'required': [('use_payment_terminal', '=', 'mercury')]}"/>
</xpath>
</field>
</record>