This commit is contained in:
Ernad Husremovic 2025-08-29 17:40:39 +02:00
parent 12c29a983b
commit 95fcc8bd63
189 changed files with 170858 additions and 0 deletions

View file

@ -0,0 +1,18 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
from . import utils
from . import wizards
from odoo import api, SUPERUSER_ID
def setup_provider(cr, registry, code):
env = api.Environment(cr, SUPERUSER_ID, {})
env['payment.provider']._setup_provider(code)
def reset_payment_provider(cr, registry, code):
env = api.Environment(cr, SUPERUSER_ID, {})
env['payment.provider']._remove_provider(code)

View file

@ -0,0 +1,50 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': "Payment Engine",
'version': '2.0',
'category': 'Hidden',
'summary': "The payment engine used by payment provider modules.",
'depends': ['portal'],
'data': [
'data/payment_icon_data.xml',
'data/payment_provider_data.xml',
'data/payment_cron.xml',
'views/payment_portal_templates.xml',
'views/payment_templates.xml',
'views/payment_provider_views.xml',
'views/payment_icon_views.xml',
'views/payment_transaction_views.xml',
'views/payment_token_views.xml', # Depends on `action_payment_transaction_linked_to_token`
'views/res_partner_views.xml',
'security/ir.model.access.csv',
'security/payment_security.xml',
'wizards/payment_link_wizard_views.xml',
'wizards/payment_onboarding_views.xml',
],
'demo': [
'data/payment_demo.xml',
],
'assets': {
'web.assets_frontend': [
'payment/static/src/scss/portal_payment.scss',
'payment/static/src/scss/payment_templates.scss',
'payment/static/src/scss/payment_form.scss',
'payment/static/lib/jquery.payment/jquery.payment.js',
'payment/static/src/js/checkout_form.js',
'payment/static/src/js/express_checkout_form.js',
'payment/static/src/js/manage_form.js',
'payment/static/src/js/payment_form_mixin.js',
'payment/static/src/js/post_processing.js',
'payment/static/src/xml/payment_post_processing.xml',
],
'web.assets_backend': [
'payment/static/src/scss/payment_provider.scss',
],
},
'license': 'LGPL-3',
}

View file

@ -0,0 +1,281 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# According to https://en.wikipedia.org/wiki/ISO_4217#Minor_unit_fractions
CURRENCY_MINOR_UNITS = {
'ADF': 2,
'ADP': 0,
'AED': 2,
'AFA': 2,
'AFN': 2,
'ALL': 2,
'AMD': 2,
'ANG': 2,
'AOA': 2,
'AOK': 0,
'AON': 0,
'AOR': 0,
'ARA': 2,
'ARL': 2,
'ARP': 2,
'ARS': 2,
'ATS': 2,
'AUD': 2,
'AWG': 2,
'AYM': 0,
'AZM': 2,
'AZN': 2,
'BAD': 2,
'BAM': 2,
'BBD': 2,
'BDS': 2,
'BDT': 2,
'BEF': 2,
'BGL': 2,
'BGN': 2,
'BHD': 3,
'BIF': 0,
'BMD': 2,
'BND': 2,
'BOB': 2,
'BOP': 2,
'BOV': 2,
'BRB': 2,
'BRC': 2,
'BRE': 2,
'BRL': 2,
'BRN': 2,
'BRR': 2,
'BSD': 2,
'BTN': 2,
'BWP': 2,
'BYB': 2,
'BYN': 2,
'BYR': 0,
'BZD': 2,
'CAD': 2,
'CDF': 2,
'CHC': 2,
'CHE': 2,
'CHF': 2,
'CHW': 2,
'CLF': 4,
'CLP': 0,
'CNH': 2,
'CNT': 2,
'CNY': 2,
'COP': 2,
'COU': 2,
'CRC': 2,
'CSD': 2,
'CUC': 2,
'CUP': 2,
'CVE': 2,
'CYP': 2,
'CZK': 2,
'DEM': 2,
'DJF': 0,
'DKK': 2,
'DOP': 2,
'DZD': 2,
'ECS': 0,
'ECV': 2,
'EEK': 2,
'EGP': 2,
'ERN': 2,
'ESP': 0,
'ETB': 2,
'EUR': 2,
'FIM': 2,
'FJD': 2,
'FKP': 2,
'FRF': 2,
'GBP': 2,
'GEK': 0,
'GEL': 2,
'GGP': 2,
'GHC': 2,
'GHP': 2,
'GHS': 2,
'GIP': 2,
'GMD': 2,
'GNF': 0,
'GTQ': 2,
'GWP': 2,
'GYD': 2,
'HKD': 2,
'HNL': 2,
'HRD': 2,
'HRK': 2,
'HTG': 2,
'HUF': 2,
'IDR': 2,
'IEP': 2,
'ILR': 2,
'ILS': 2,
'IMP': 2,
'INR': 2,
'IQD': 3,
'IRR': 2,
'ISJ': 2,
'ISK': 0,
'ITL': 0,
'JEP': 2,
'JMD': 2,
'JOD': 3,
'JPY': 0,
'KES': 2,
'KGS': 2,
'KHR': 2,
'KID': 2,
'KMF': 0,
'KPW': 2,
'KRW': 0,
'KWD': 3,
'KYD': 2,
'KZT': 2,
'LAK': 2,
'LBP': 2,
'LKR': 2,
'LRD': 2,
'LSL': 2,
'LTL': 2,
'LTT': 2,
'LUF': 2,
'LVL': 2,
'LVR': 2,
'LYD': 3,
'MAD': 2,
'MAF': 2,
'MCF': 2,
'MDL': 2,
'MGA': 2,
'MGF': 0,
'MKD': 2,
'MMK': 2,
'MNT': 2,
'MOP': 2,
'MRO': 2,
'MRU': 2,
'MTL': 2,
'MUR': 2,
'MVR': 2,
'MWK': 2,
'MXN': 2,
'MXV': 2,
'MYR': 2,
'MZE': 2,
'MZM': 2,
'MZN': 2,
'NAD': 2,
'NGN': 2,
'NIC': 2,
'NIO': 2,
'NIS': 2,
'NLG': 2,
'NOK': 2,
'NPR': 2,
'NTD': 2,
'NZD': 2,
'OMR': 3,
'PAB': 2,
'PEN': 2,
'PES': 2,
'PGK': 2,
'PHP': 2,
'PKR': 2,
'PLN': 2,
'PLZ': 2,
'PRB': 2,
'PTE': 0,
'PYG': 0,
'QAR': 2,
'RHD': 2,
'RMB': 2,
'ROL': 0,
'RON': 2,
'RSD': 2,
'RUB': 2,
'RUR': 2,
'RWF': 0,
'SAR': 2,
'SBD': 2,
'SCR': 2,
'SDD': 2,
'SDG': 2,
'SEK': 2,
'SGD': 2,
'SHP': 2,
'SIT': 2,
'SKK': 2,
'SLE': 2,
'SLL': 2,
'SLS': 2,
'SML': 0,
'SOS': 2,
'SRD': 2,
'SRG': 2,
'SSP': 2,
'STD': 2,
'STG': 2,
'STN': 2,
'SVC': 2,
'SYP': 2,
'SZL': 2,
'THB': 2,
'TJR': 0,
'TJS': 2,
'TMM': 2,
'TMT': 2,
'TND': 3,
'TOP': 2,
'TPE': 0,
'TRL': 0,
'TRY': 2,
'TTD': 2,
'TVD': 2,
'TWD': 2,
'TZS': 2,
'UAH': 2,
'UAK': 2,
'UGX': 0,
'USD': 2,
'USN': 2,
'USS': 2,
'UYI': 0,
'UYN': 2,
'UYU': 2,
'UYW': 4,
'UZS': 2,
'VAL': 0,
'VEB': 2,
'VED': 2,
'VEF': 2,
'VES': 2,
'VND': 0,
'VUV': 0,
'WST': 2,
'XAF': 0,
'XCD': 2,
'XEU': 0,
'XOF': 0,
'XPF': 0,
'YER': 2,
'YUD': 2,
'YUG': 2,
'YUM': 2,
'YUN': 2,
'YUO': 2,
'YUR': 2,
'ZAL': 2,
'ZAR': 2,
'ZMK': 2,
'ZMW': 2,
'ZRN': 2,
'ZRZ': 2,
'ZWB': 2,
'ZWC': 2,
'ZWD': 2,
'ZWL': 2,
'ZWN': 2,
'ZWR': 2
}

View file

@ -0,0 +1,3 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import portal

View file

@ -0,0 +1,443 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import urllib.parse
import werkzeug
from odoo import _, http
from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.http import request
from odoo.addons.payment import utils as payment_utils
from odoo.addons.payment.controllers.post_processing import PaymentPostProcessing
from odoo.addons.portal.controllers import portal
class PaymentPortal(portal.CustomerPortal):
""" This controller contains the foundations for online payments through the portal.
It allows to complete a full payment flow without the need of going through a document-based
flow made available by another module's controller.
Such controllers should extend this one to gain access to the _create_transaction static method
that implements the creation of a transaction before its processing, or to override specific
routes and change their behavior globally (e.g. make the /pay route handle sale orders).
The following routes are exposed:
- `/payment/pay` allows for arbitrary payments.
- `/my/payment_method` allows the user to create and delete tokens. It's its own `landing_route`
- `/payment/transaction` is the `transaction_route` for the standard payment flow. It creates a
draft transaction, and return the processing values necessary for the completion of the
transaction.
- `/payment/confirmation` is the `landing_route` for the standard payment flow. It displays the
payment confirmation page to the user when the transaction is validated.
"""
@http.route(
'/payment/pay', type='http', methods=['GET'], auth='public', website=True, sitemap=False,
)
def payment_pay(
self, reference=None, amount=None, currency_id=None, partner_id=None, company_id=None,
provider_id=None, access_token=None, **kwargs
):
""" Display the payment form with optional filtering of payment options.
The filtering takes place on the basis of provided parameters, if any. If a parameter is
incorrect or malformed, it is skipped to avoid preventing the user from making the payment.
In addition to the desired filtering, a second one ensures that none of the following
rules is broken:
- Public users are not allowed to save their payment method as a token.
- Payments made by public users should either *not* be made on behalf of a specific
partner or have an access token validating the partner, amount and currency.
We let access rights and security rules do their job for logged in users.
:param str reference: The custom prefix to compute the full reference
:param str amount: The amount to pay
:param str currency_id: The desired currency, as a `res.currency` id
:param str partner_id: The partner making the payment, as a `res.partner` id
:param str company_id: The related company, as a `res.company` id
:param str provider_id: The desired provider, as a `payment.provider` id
:param str access_token: The access token used to authenticate the partner
:param dict kwargs: Optional data passed to helper methods.
:return: The rendered checkout form
:rtype: str
:raise: werkzeug.exceptions.NotFound if the access token is invalid
"""
# Cast numeric parameters as int or float and void them if their str value is malformed
currency_id, provider_id, partner_id, company_id = tuple(map(
self._cast_as_int, (currency_id, provider_id, partner_id, company_id)
))
amount = self._cast_as_float(amount)
# Raise an HTTP 404 if a partner is provided with an invalid access token
if partner_id:
if not payment_utils.check_access_token(access_token, partner_id, amount, currency_id):
raise werkzeug.exceptions.NotFound() # Don't leak information about ids.
user_sudo = request.env.user
logged_in = not user_sudo._is_public()
# If the user is logged in, take their partner rather than the partner set in the params.
# This is something that we want, since security rules are based on the partner, and created
# tokens should not be assigned to the public user. This should have no impact on the
# transaction itself besides making reconciliation possibly more difficult (e.g. The
# transaction and invoice partners are different).
partner_is_different = False
if logged_in:
partner_is_different = partner_id and partner_id != user_sudo.partner_id.id
partner_sudo = user_sudo.partner_id
else:
partner_sudo = request.env['res.partner'].sudo().browse(partner_id).exists()
if not partner_sudo:
return request.redirect(
# Escape special characters to avoid loosing original params when redirected
f'/web/login?redirect={urllib.parse.quote(request.httprequest.full_path)}'
)
# Instantiate transaction values to their default if not set in parameters
reference = reference or payment_utils.singularize_reference_prefix(prefix='tx')
amount = amount or 0.0 # If the amount is invalid, set it to 0 to stop the payment flow
company_id = company_id or partner_sudo.company_id.id or user_sudo.company_id.id
company = request.env['res.company'].sudo().browse(company_id)
currency_id = currency_id or company.currency_id.id
# Make sure that the currency exists and is active
currency = request.env['res.currency'].browse(currency_id).exists()
if not currency or not currency.active:
raise werkzeug.exceptions.NotFound() # The currency must exist and be active.
# Select all providers and tokens that match the constraints
providers_sudo = request.env['payment.provider'].sudo()._get_compatible_providers(
company_id, partner_sudo.id, amount, currency_id=currency.id, **kwargs
) # In sudo mode to read the fields of providers and partner (if not logged in)
if provider_id in providers_sudo.ids: # Only keep the desired provider if it's suitable
providers_sudo = providers_sudo.browse(provider_id)
payment_tokens = request.env['payment.token'].search(
[('provider_id', 'in', providers_sudo.ids), ('partner_id', '=', partner_sudo.id)]
) if logged_in else request.env['payment.token']
# Make sure that the partner's company matches the company passed as parameter.
if not PaymentPortal._can_partner_pay_in_company(partner_sudo, company):
providers_sudo = request.env['payment.provider'].sudo()
payment_tokens = request.env['payment.token']
# Compute the fees taken by providers supporting the feature
fees_by_provider = {
provider_sudo: provider_sudo._compute_fees(amount, currency, partner_sudo.country_id)
for provider_sudo in providers_sudo.filtered('fees_active')
}
# Generate a new access token in case the partner id or the currency id was updated
access_token = payment_utils.generate_access_token(partner_sudo.id, amount, currency.id)
rendering_context = {
'providers': providers_sudo,
'tokens': payment_tokens,
'fees_by_provider': fees_by_provider,
'show_tokenize_input': self._compute_show_tokenize_input_mapping(
providers_sudo, logged_in=logged_in, **kwargs
),
'reference_prefix': reference,
'amount': amount,
'currency': currency,
'partner_id': partner_sudo.id,
'access_token': access_token,
'transaction_route': '/payment/transaction',
'landing_route': '/payment/confirmation',
'res_company': company, # Display the correct logo in a multi-company environment
'partner_is_different': partner_is_different,
**self._get_custom_rendering_context_values(**kwargs),
}
return request.render(self._get_payment_page_template_xmlid(**kwargs), rendering_context)
@staticmethod
def _compute_show_tokenize_input_mapping(providers_sudo, logged_in=False, **kwargs):
""" Determine for each provider whether the tokenization input should be shown or not.
:param recordset providers_sudo: The providers for which to determine whether the
tokenization input should be shown or not, as a sudoed
`payment.provider` recordset.
:param bool logged_in: Whether the user is logged in or not.
:param dict kwargs: The optional data passed to the helper methods.
:return: The mapping of the computed value for each provider id.
:rtype: dict
"""
show_tokenize_input_mapping = {}
for provider_sudo in providers_sudo:
show_tokenize_input = provider_sudo.allow_tokenization \
and not provider_sudo._is_tokenization_required(**kwargs) \
and logged_in
show_tokenize_input_mapping[provider_sudo.id] = show_tokenize_input
return show_tokenize_input_mapping
def _get_payment_page_template_xmlid(self, **kwargs):
return 'payment.pay'
@http.route('/my/payment_method', type='http', methods=['GET'], auth='user', website=True)
def payment_method(self, **kwargs):
""" Display the form to manage payment methods.
:param dict kwargs: Optional data. This parameter is not used here
:return: The rendered manage form
:rtype: str
"""
partner_sudo = request.env.user.partner_id # env.user is always sudoed
providers_sudo = request.env['payment.provider'].sudo()._get_compatible_providers(
request.env.company.id,
partner_sudo.id,
0., # There is no amount to pay with validation transactions.
force_tokenization=True,
is_validation=True,
)
# Get all partner's tokens for which providers are not disabled.
tokens_sudo = request.env['payment.token'].sudo().search([
('partner_id', 'in', [partner_sudo.id, partner_sudo.commercial_partner_id.id]),
('provider_id.state', 'in', ['enabled', 'test']),
])
access_token = payment_utils.generate_access_token(partner_sudo.id, None, None)
rendering_context = {
'providers': providers_sudo,
'tokens': tokens_sudo,
'reference_prefix': payment_utils.singularize_reference_prefix(prefix='V'),
'partner_id': partner_sudo.id,
'access_token': access_token,
'transaction_route': '/payment/transaction',
'landing_route': '/my/payment_method',
**self._get_custom_rendering_context_values(**kwargs),
}
return request.render('payment.payment_methods', rendering_context)
def _get_custom_rendering_context_values(self, **kwargs):
""" Return a dict of additional rendering context values.
:param dict kwargs: Optional data. This parameter is not used here
:return: The dict of additional rendering context values
:rtype: dict
"""
return {}
@http.route('/payment/transaction', type='json', auth='public')
def payment_transaction(self, amount, currency_id, partner_id, access_token, **kwargs):
""" Create a draft transaction and return its processing values.
:param float|None amount: The amount to pay in the given currency.
None if in a payment method validation operation
:param int|None currency_id: The currency of the transaction, as a `res.currency` id.
None if in a payment method validation operation
:param int partner_id: The partner making the payment, as a `res.partner` id
:param str access_token: The access token used to authenticate the partner
:param dict kwargs: Locally unused data passed to `_create_transaction`
:return: The mandatory values for the processing of the transaction
:rtype: dict
:raise: ValidationError if the access token is invalid
"""
# Check the access token against the transaction values
amount = amount and float(amount) # Cast as float in case the JS stripped the '.0'
if not payment_utils.check_access_token(access_token, partner_id, amount, currency_id):
raise ValidationError(_("The access token is invalid."))
kwargs.pop('custom_create_values', None) # Don't allow passing arbitrary create values
tx_sudo = self._create_transaction(
amount=amount, currency_id=currency_id, partner_id=partner_id, **kwargs
)
self._update_landing_route(tx_sudo, access_token) # Add the required parameters to the route
return tx_sudo._get_processing_values()
def _create_transaction(
self, payment_option_id, reference_prefix, amount, currency_id, partner_id, flow,
tokenization_requested, landing_route, is_validation=False,
custom_create_values=None, **kwargs
):
""" Create a draft transaction based on the payment context and return it.
:param int payment_option_id: The payment option handling the transaction, as a
`payment.provider` id or a `payment.token` id
:param str reference_prefix: The custom prefix to compute the full reference
:param float|None amount: The amount to pay in the given currency.
None if in a payment method validation operation
:param int|None currency_id: The currency of the transaction, as a `res.currency` id.
None if in a payment method validation operation
:param int partner_id: The partner making the payment, as a `res.partner` id
:param str flow: The online payment flow of the transaction: 'redirect', 'direct' or 'token'
:param bool tokenization_requested: Whether the user requested that a token is created
:param str landing_route: The route the user is redirected to after the transaction
:param bool is_validation: Whether the operation is a validation
:param dict custom_create_values: Additional create values overwriting the default ones
:param dict kwargs: Locally unused data passed to `_is_tokenization_required` and
`_compute_reference`
:return: The sudoed transaction that was created
:rtype: recordset of `payment.transaction`
:raise: UserError if the flow is invalid
"""
# Prepare create values
if flow in ['redirect', 'direct']: # Direct payment or payment with redirection
provider_sudo = request.env['payment.provider'].sudo().browse(payment_option_id)
token_id = None
tokenize = bool(
# Don't tokenize if the user tried to force it through the browser's developer tools
provider_sudo.allow_tokenization
# Token is only created if required by the flow or requested by the user
and (provider_sudo._is_tokenization_required(**kwargs) or tokenization_requested)
)
elif flow == 'token': # Payment by token
token_sudo = request.env['payment.token'].sudo().browse(payment_option_id)
# Prevent from paying with a token that doesn't belong to the current partner (either
# the current user's partner if logged in, or the partner on behalf of whom the payment
# is being made).
partner_sudo = request.env['res.partner'].sudo().browse(partner_id)
if partner_sudo.commercial_partner_id != token_sudo.partner_id.commercial_partner_id:
raise AccessError(_("You do not have access to this payment token."))
provider_sudo = token_sudo.provider_id
token_id = payment_option_id
tokenize = False
else:
raise UserError(
_("The payment should either be direct, with redirection, or made by a token.")
)
reference = request.env['payment.transaction']._compute_reference(
provider_sudo.code,
prefix=reference_prefix,
**(custom_create_values or {}),
**kwargs
)
if is_validation: # Providers determine the amount and currency in validation operations
amount = provider_sudo._get_validation_amount()
currency_id = provider_sudo._get_validation_currency().id
# Create the transaction
tx_sudo = request.env['payment.transaction'].sudo().create({
'provider_id': provider_sudo.id,
'reference': reference,
'amount': amount,
'currency_id': currency_id,
'partner_id': partner_id,
'token_id': token_id,
'operation': f'online_{flow}' if not is_validation else 'validation',
'tokenize': tokenize,
'landing_route': landing_route,
**(custom_create_values or {}),
}) # In sudo mode to allow writing on callback fields
if flow == 'token':
tx_sudo._send_payment_request() # Payments by token process transactions immediately
else:
tx_sudo._log_sent_message()
# Monitor the transaction to make it available in the portal
PaymentPostProcessing.monitor_transactions(tx_sudo)
return tx_sudo
@staticmethod
def _update_landing_route(tx_sudo, access_token):
""" Add the mandatory parameters to the route and recompute the access token if needed.
The generic landing route requires the tx id and access token to be provided since there is
no document to rely on. The access token is recomputed in case we are dealing with a
validation transaction (provider-specific amount and currency).
:param recordset tx_sudo: The transaction whose landing routes to update, as a
`payment.transaction` record.
:param str access_token: The access token used to authenticate the partner
:return: None
"""
if tx_sudo.operation == 'validation':
access_token = payment_utils.generate_access_token(
tx_sudo.partner_id.id, tx_sudo.amount, tx_sudo.currency_id.id
)
tx_sudo.landing_route = f'{tx_sudo.landing_route}' \
f'?tx_id={tx_sudo.id}&access_token={access_token}'
@http.route('/payment/confirmation', type='http', methods=['GET'], auth='public', website=True)
def payment_confirm(self, tx_id, access_token, **kwargs):
""" Display the payment confirmation page to the user.
:param str tx_id: The transaction to confirm, as a `payment.transaction` id
:param str access_token: The access token used to verify the user
:param dict kwargs: Optional data. This parameter is not used here
:raise: werkzeug.exceptions.NotFound if the access token is invalid
"""
tx_id = self._cast_as_int(tx_id)
if tx_id:
tx_sudo = request.env['payment.transaction'].sudo().browse(tx_id)
# Raise an HTTP 404 if the access token is invalid
if not payment_utils.check_access_token(
access_token, tx_sudo.partner_id.id, tx_sudo.amount, tx_sudo.currency_id.id
):
raise werkzeug.exceptions.NotFound() # Don't leak information about ids.
# Stop monitoring the transaction now that it reached a final state.
PaymentPostProcessing.remove_transactions(tx_sudo)
# Display the payment confirmation page to the user
return request.render('payment.confirm', qcontext={'tx': tx_sudo})
else:
# Display the portal homepage to the user
return request.redirect('/my/home')
@http.route('/payment/archive_token', type='json', auth='user')
def archive_token(self, token_id):
""" Check that a user has write access on a token and archive the token if so.
:param int token_id: The token to archive, as a `payment.token` id
:return: None
"""
partner_sudo = request.env.user.partner_id
token_sudo = request.env['payment.token'].sudo().search([
('id', '=', token_id),
# Check that the user owns the token before letting them archive anything
('partner_id', 'in', [partner_sudo.id, partner_sudo.commercial_partner_id.id])
])
if token_sudo:
token_sudo.active = False
@staticmethod
def _cast_as_int(str_value):
""" Cast a string as an `int` and return it.
If the conversion fails, `None` is returned instead.
:param str str_value: The value to cast as an `int`
:return: The casted value, possibly replaced by None if incompatible
:rtype: int|None
"""
try:
return int(str_value)
except (TypeError, ValueError, OverflowError):
return None
@staticmethod
def _cast_as_float(str_value):
""" Cast a string as a `float` and return it.
If the conversion fails, `None` is returned instead.
:param str str_value: The value to cast as a `float`
:return: The casted value, possibly replaced by None if incompatible
:rtype: float|None
"""
try:
return float(str_value)
except (TypeError, ValueError, OverflowError):
return None
@staticmethod
def _can_partner_pay_in_company(partner, document_company):
""" Return whether the provided partner can pay in the provided company.
The payment is allowed either if the partner's company is not set or if the companies match.
:param recordset partner: The partner on behalf on which the payment is made, as a
`res.partner` record.
:param recordset document_company: The company of the document being paid, as a
`res.company` record.
:return: Whether the payment is allowed.
:rtype: str
"""
return not partner.company_id or partner.company_id == document_company

View file

@ -0,0 +1,139 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from datetime import timedelta
import psycopg2
from odoo import fields, http
from odoo.http import request
_logger = logging.getLogger(__name__)
class PaymentPostProcessing(http.Controller):
"""
This controller is responsible for the monitoring and finalization of the post-processing of
transactions.
It exposes the route `/payment/status`: All payment flows must go through this route at some
point to allow the user checking on the transactions' status, and to trigger the finalization of
their post-processing.
"""
MONITORED_TX_IDS_KEY = '__payment_monitored_tx_ids__'
@http.route('/payment/status', type='http', auth='public', website=True, sitemap=False)
def display_status(self, **kwargs):
""" Display the payment status page.
:param dict kwargs: Optional data. This parameter is not used here
:return: The rendered status page
:rtype: str
"""
return request.render('payment.payment_status')
@http.route('/payment/status/poll', type='json', auth='public')
def poll_status(self, **_kwargs):
""" Fetch the transactions to display on the status page and finalize their post-processing.
:return: The post-processing values of the transactions
:rtype: dict
"""
# Retrieve recent user's transactions from the session
limit_date = fields.Datetime.now() - timedelta(days=1)
monitored_txs = request.env['payment.transaction'].sudo().search([
('id', 'in', self.get_monitored_transaction_ids()),
('last_state_change', '>=', limit_date)
])
if not monitored_txs: # The transaction was not correctly created
return {
'success': False,
'error': 'no_tx_found',
}
# Build the list of display values with the display message and post-processing values
display_values_list = []
for tx in monitored_txs:
display_message = None
if tx.state == 'pending':
display_message = tx.provider_id.pending_msg
elif tx.state == 'done':
display_message = tx.provider_id.done_msg
elif tx.state == 'cancel':
display_message = tx.provider_id.cancel_msg
display_values_list.append({
'display_message': display_message,
**tx._get_post_processing_values(),
})
# Stop monitoring already post-processed transactions
post_processed_txs = monitored_txs.filtered('is_post_processed')
self.remove_transactions(post_processed_txs)
# Finalize post-processing of transactions before displaying them to the user
txs_to_post_process = (monitored_txs - post_processed_txs).filtered(
lambda t: t.state == 'done'
)
success, error = True, None
try:
txs_to_post_process._finalize_post_processing()
except psycopg2.OperationalError: # A collision of accounting sequences occurred
request.env.cr.rollback() # Rollback and try later
success = False
error = 'tx_process_retry'
except Exception as e:
request.env.cr.rollback()
success = False
error = str(e)
_logger.exception(
"encountered an error while post-processing transactions with ids %s:\n%s",
', '.join([str(tx_id) for tx_id in txs_to_post_process.ids]), e
)
return {
'success': success,
'error': error,
'display_values_list': display_values_list,
}
@classmethod
def monitor_transactions(cls, transactions):
""" Add the ids of the provided transactions to the list of monitored transaction ids.
:param recordset transactions: The transactions to monitor, as a `payment.transaction`
recordset
:return: None
"""
if transactions:
monitored_tx_ids = request.session.get(cls.MONITORED_TX_IDS_KEY, [])
request.session[cls.MONITORED_TX_IDS_KEY] = list(
set(monitored_tx_ids).union(transactions.ids)
)
@classmethod
def get_monitored_transaction_ids(cls):
""" Return the ids of transactions being monitored.
Only the ids and not the recordset itself is returned to allow the caller browsing the
recordset with sudo privileges, and using the ids in a custom query.
:return: The ids of transactions being monitored
:rtype: list
"""
return request.session.get(cls.MONITORED_TX_IDS_KEY, [])
@classmethod
def remove_transactions(cls, transactions):
""" Remove the ids of the provided transactions from the list of monitored transaction ids.
:param recordset transactions: The transactions to remove, as a `payment.transaction`
recordset
:return: None
"""
if transactions:
monitored_tx_ids = request.session.get(cls.MONITORED_TX_IDS_KEY, [])
request.session[cls.MONITORED_TX_IDS_KEY] = [
tx_id for tx_id in monitored_tx_ids if tx_id not in transactions.ids
]

View file

@ -0,0 +1,4 @@
-- disable generic payment provider
UPDATE payment_provider
SET state = 'disabled'
WHERE state NOT IN ('test', 'disabled');

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.cron" id="cron_post_process_payment_tx">
<field name="name">payment: post-process transactions</field>
<field name="model_id" ref="payment.model_payment_transaction" />
<field name="state">code</field>
<field name="code">model._cron_finalize_post_processing()</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
</record>
</odoo>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- Enable the EUR currency since it's the currency of the company. -->
<function model="res.currency" name="action_unarchive" eval="[[ref('base.EUR')]]"/>
</odoo>

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_icon_cc_visa" model="payment.icon">
<field name="sequence">10</field>
<field name="name">VISA</field>
<field name="image" type="base64" file="payment/static/img/visa.png"/>
</record>
<record id="payment_icon_cc_mastercard" model="payment.icon">
<field name="sequence">20</field>
<field name="name">MasterCard</field>
<field name="image" type="base64" file="payment/static/img/mastercard.png"/>
</record>
<record id="payment_icon_cc_american_express" model="payment.icon">
<field name="sequence">30</field>
<field name="name">American Express</field>
<field name="image" type="base64" file="payment/static/img/american_express.png"/>
</record>
<record id="payment_icon_cc_discover" model="payment.icon">
<field name="sequence">40</field>
<field name="name">Discover</field>
<field name="image" type="base64" file="payment/static/img/discover.png"/>
</record>
<record id="payment_icon_cc_diners_club_intl" model="payment.icon">
<field name="sequence">50</field>
<field name="name">Diners Club International</field>
<field name="image" type="base64" file="payment/static/img/diners_club_intl.png"/>
</record>
<record id="payment_icon_paypal" model="payment.icon">
<field name="sequence">60</field>
<field name="name">Paypal</field>
<field name="image" type="base64" file="payment/static/img/paypal.png"/>
</record>
<record id="payment_icon_cc_rupay" model="payment.icon">
<field name="sequence">65</field>
<field name="name">Rupay</field>
<field name="image" type="base64" file="payment/static/img/rupay.png"/>
</record>
<record id="payment_icon_apple_pay" model="payment.icon">
<field name="sequence">70</field>
<field name="name">Apple Pay</field>
<field name="image" type="base64" file="payment/static/img/applepay.png"/>
</record>
<record id="payment_icon_cc_jcb" model="payment.icon">
<field name="sequence">80</field>
<field name="name">JCB</field>
<field name="image" type="base64" file="payment/static/img/jcb.png"/>
</record>
<record id="payment_icon_cc_maestro" model="payment.icon">
<field name="sequence">90</field>
<field name="name">Maestro</field>
<field name="image" type="base64" file="payment/static/img/maestro.png"/>
</record>
<record id="payment_icon_cc_cirrus" model="payment.icon">
<field name="sequence">100</field>
<field name="name">Cirrus</field>
<field name="image" type="base64" file="payment/static/img/cirrus.png"/>
</record>
<record id="payment_icon_cc_unionpay" model="payment.icon">
<field name="sequence">110</field>
<field name="name">UnionPay</field>
<field name="image" type="base64" file="payment/static/img/unionpay.png"/>
</record>
<record id="payment_icon_cc_bancontact" model="payment.icon">
<field name="sequence">120</field>
<field name="name">Bancontact</field>
<field name="image" type="base64" file="payment/static/img/bancontact.png"/>
</record>
<record id="payment_icon_cc_western_union" model="payment.icon">
<field name="sequence">130</field>
<field name="name">Western Union</field>
<field name="image" type="base64" file="payment/static/img/western_union.png"/>
</record>
<record id="payment_icon_sepa" model="payment.icon">
<field name="sequence">140</field>
<field name="name">SEPA Direct Debit</field>
<field name="image" type="base64" file="payment/static/img/sepa.png"/>
</record>
<record id="payment_icon_cc_ideal" model="payment.icon">
<field name="sequence">150</field>
<field name="name">iDEAL</field>
<field name="image" type="base64" file="payment/static/img/ideal.png"/>
</record>
<record id="payment_icon_cc_webmoney" model="payment.icon">
<field name="sequence">160</field>
<field name="name">WebMoney</field>
<field name="image" type="base64" file="payment/static/img/webmoney.png"/>
</record>
<record id="payment_icon_cc_giropay" model="payment.icon">
<field name="sequence">170</field>
<field name="name">Giropay</field>
<field name="image" type="base64" file="payment/static/img/giropay.png"/>
</record>
<record id="payment_icon_cc_eps" model="payment.icon">
<field name="sequence">180</field>
<field name="name">EPS</field>
<field name="image" type="base64" file="payment/static/img/eps.png"/>
</record>
<record id="payment_icon_cc_p24" model="payment.icon">
<field name="sequence">190</field>
<field name="name">P24</field>
<field name="image" type="base64" file="payment/static/img/p24.png"/>
</record>
<record id="payment_icon_cc_codensa_easy_credit" model="payment.icon">
<field name="sequence">200</field>
<field name="name">Codensa Easy Credit</field>
<field name="image" type="base64" file="payment/static/img/codensa_easy_credit.png"/>
</record>
<record id="payment_icon_kbc" model="payment.icon">
<field name="sequence">210</field>
<field name="name">KBC</field>
<field name="image" type="base64" file="payment/static/img/kbc.png"/>
</record>
<record id="payment_icon_mpesa" model="payment.icon">
<field name="sequence">220</field>
<field name="name">M-Pesa</field>
<field name="image" type="base64" file="payment/static/img/m-pesa.png"/>
</record>
<record id="payment_icon_airtel_money" model="payment.icon">
<field name="sequence">230</field>
<field name="name">Airtel Money</field>
<field name="image" type="base64" file="payment/static/img/airtel-money.png"/>
</record>
<record id="payment_icon_mtn_mobile_money" model="payment.icon">
<field name="sequence">240</field>
<field name="name">MTN Mobile Money</field>
<field name="image" type="base64" file="payment/static/img/mtn-mobile-money.png"/>
</record>
<record id="payment_icon_barter_by_flutterwave" model="payment.icon">
<field name="sequence">250</field>
<field name="name">Barter by Flutterwave</field>
<field name="image" type="base64" file="payment/static/img/barter-by-flutterwave.png"/>
</record>
<record id="payment_icon_sadad" model="payment.icon">
<field name="sequence">260</field>
<field name="name">Sadad</field>
<field name="image" type="base64" file="payment/static/img/sadad.png"/>
</record>
<record id="payment_icon_mada" model="payment.icon">
<field name="sequence">270</field>
<field name="name">Mada</field>
<field name="image" type="base64" file="payment/static/img/mada.png"/>
</record>
<record id="payment_icon_bbva_bancomer" model="payment.icon">
<field name="sequence">280</field>
<field name="name">BBVA Bancomer</field>
<field name="image" type="base64" file="payment/static/img/bbva-bancomer.png"/>
</record>
<record id="payment_icon_citibanamex" model="payment.icon">
<field name="sequence">280</field>
<field name="name">CitiBanamex</field>
<field name="image" type="base64" file="payment/static/img/citibanamex.png"/>
</record>
</odoo>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<!-- Simplified payment provider data - removed external payment modules dependencies -->
</odoo>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,758 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * payment
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Odoo 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-08-18 14:07+0000\n"
"PO-Revision-Date: 2015-09-08 06:27+0000\n"
"Last-Translator: Martin Trigaux\n"
"Language-Team: Spanish (Panama) (http://www.transifex.com/odoo/odoo-9/"
"language/es_PA/)\n"
"Language: es_PA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_callback_eval
msgid ""
" Will be safe_eval with `self` being the current transaction. i."
"e.:\n"
" self.env['my.model'].payment_validated(self)"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_adyen
msgid "-This installs the module payment_adyen."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_authorize
msgid "-This installs the module payment_authorize."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_buckaroo
msgid "-This installs the module payment_buckaroo."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_ogone
msgid "-This installs the module payment_ogone."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_paypal
msgid "-This installs the module payment_paypal."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_sips
msgid "-This installs the module payment_sips."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_transfer
msgid "-This installs the module payment_transfer."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_html_3ds
msgid "3D Secure HTML"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"<span class=\"text-danger\">Test</span>\n"
" <span class=\"o_stat_text\">Environment</"
"span>"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"<span class=\"text-success\">Production</span>\n"
" <span class=\"o_stat_text\">Environment</"
"span>"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_acquirer_id
msgid "Acquirer"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_acquirer_id
msgid "Acquirer Account"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_acquirer_ref
msgid "Acquirer Ref."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_acquirer_reference
msgid "Acquirer Reference"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_active
msgid "Active"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_active
msgid "Add Extra Fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_address
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Address"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_adyen
msgid "Adyen"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_amount
#: model:ir.model.fields,help:payment.field_payment_transaction_amount
msgid "Amount"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "At payment no acquirer confirmation needed"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "At payment with acquirer confirmation"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_authorize
msgid "Authorize.Net"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_buckaroo
msgid "Buckaroo"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_cancel_msg
msgid "Cancel Message"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Canceled"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_city
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "City"
msgstr "Ciudad"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_company_id
msgid "Company"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Configuration"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.payment_acquirer_installation
msgid "Configure payment acquiring methods"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_res_partner_payment_method_count
msgid "Count Payment Method"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_country_id
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Country"
msgstr "País"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_create_uid
#: model:ir.model.fields,field_description:payment.field_payment_method_create_uid
#: model:ir.model.fields,field_description:payment.field_payment_transaction_create_uid
msgid "Created by"
msgstr "Creado por"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_create_date
#: model:ir.model.fields,field_description:payment.field_payment_method_create_date
msgid "Created on"
msgstr "Creado en"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_create_date
msgid "Creation Date"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Credentials"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.view_partners_form_payment_defaultcreditcard
msgid "Credit card(s)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_currency_id
msgid "Currency"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Customer Details"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_sequence
msgid "Determine the display order"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_display_name
#: model:ir.model.fields,field_description:payment.field_payment_method_display_name
#: model:ir.model.fields,field_description:payment.field_payment_transaction_display_name
msgid "Display Name"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Done"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_done_msg
msgid "Done Message"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Draft"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "E-mail"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_email
msgid "Email"
msgstr "Correo electrónico"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_environment
msgid "Environment"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Error"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_error_msg
msgid "Error Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_fees
msgid "Fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_fees
msgid "Fees amount; set by the system because depends on the acquirer"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_state_message
msgid "Field used to store error and/or validation messages for information"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_dom_fixed
msgid "Fixed domestic fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_int_fixed
msgid "Fixed international fees"
msgstr ""
#. module: payment
#: selection:payment.transaction,type:0
msgid "Form"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_view_template_id
msgid "Form Button Template"
msgstr ""
#. module: payment
#: selection:payment.transaction,type:0
msgid "Form with credentials storage"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_search
msgid "Group By"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_pre_msg
msgid "Help Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_id
#: model:ir.model.fields,field_description:payment.field_payment_method_id
#: model:ir.model.fields,field_description:payment.field_payment_transaction_id
msgid "ID"
msgstr "ID"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image
msgid "Image"
msgstr "Imagen"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_reference
msgid "Internal reference of the TX"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_lang
msgid "Language"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer___last_update
#: model:ir.model.fields,field_description:payment.field_payment_method___last_update
#: model:ir.model.fields,field_description:payment.field_payment_transaction___last_update
msgid "Last Modified on"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_write_uid
#: model:ir.model.fields,field_description:payment.field_payment_method_write_uid
#: model:ir.model.fields,field_description:payment.field_payment_transaction_write_uid
msgid "Last Updated by"
msgstr "Última actualización de"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_write_date
#: model:ir.model.fields,field_description:payment.field_payment_method_write_date
#: model:ir.model.fields,field_description:payment.field_payment_transaction_write_date
msgid "Last Updated on"
msgstr "Última actualización en"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_website_published
msgid "Make this payment acquirer available (Customer invoices, etc.)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image_medium
msgid "Medium-sized image"
msgstr "Imagen mediana"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image_medium
msgid ""
"Medium-sized image of this provider. It is automatically resized as a "
"128x128px image, with aspect ratio preserved. Use this field in form views "
"or some kanban views."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_state_message
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_post_msg
msgid "Message displayed after having done the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_pre_msg
msgid "Message displayed to explain and help the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_error_msg
msgid "Message displayed, if error is occur during the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_cancel_msg
msgid "Message displayed, if order is cancel during the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_done_msg
msgid ""
"Message displayed, if order is done successfully after having done the "
"payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_pending_msg
msgid ""
"Message displayed, if order is in pending state after having done the "
"payment process."
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Messages"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_name
#: model:ir.model.fields,field_description:payment.field_payment_method_name
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Name"
msgstr "Nombre"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_method_name
msgid "Name of the payment method"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "No automatic confirmation"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_ogone
msgid "Ogone"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_auto_confirm
msgid "Order Confirmation"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_res_partner
#: model:ir.model.fields,field_description:payment.field_payment_method_partner_id
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_id
msgid "Partner"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_name
msgid "Partner Name"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_acquirer
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Payment Acquirer"
msgstr "Método de pago"
#. module: payment
#: model:ir.actions.act_window,name:payment.action_payment_acquirer
#: model:ir.ui.menu,name:payment.payment_acquirer_menu
#: model_terms:ir.ui.view,arch_db:payment.acquirer_list
msgid "Payment Acquirers"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_payment_method_id
msgid "Payment Method"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_res_partner_payment_method_ids
#: model_terms:ir.ui.view,arch_db:payment.payment_method_form_view
#: model_terms:ir.ui.view,arch_db:payment.payment_method_tree_view
#: model_terms:ir.ui.view,arch_db:payment.payment_method_view_search
msgid "Payment Methods"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_transaction
msgid "Payment Transaction"
msgstr "Transacción de pago"
#. module: payment
#: model:ir.actions.act_window,name:payment.action_payment_transaction
#: model:ir.actions.act_window,name:payment.action_payment_tx_ids
#: model:ir.actions.act_window,name:payment.payment_transaction_action_child
#: model:ir.model.fields,field_description:payment.field_payment_method_payment_ids
#: model:ir.ui.menu,name:payment.payment_transaction_menu
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
#: model_terms:ir.ui.view,arch_db:payment.transaction_list
msgid "Payment Transactions"
msgstr ""
#. module: payment
#: model:ir.ui.menu,name:payment.root_payment_menu
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
#: model_terms:ir.ui.view,arch_db:payment.payment_method_form_view
msgid "Payments"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_paypal
msgid "Paypal"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Pending"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_pending_msg
msgid "Pending Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_phone
msgid "Phone"
msgstr "Teléfono"
#. module: payment
#: selection:payment.acquirer,environment:0
msgid "Production"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_provider
#: model_terms:ir.ui.view,arch_db:payment.acquirer_search
msgid "Provider"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_reference
msgid "Reference"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_acquirer_reference
msgid "Reference of the TX as stored in the acquirer database"
msgstr ""
#. module: payment
#: constraint:payment.acquirer:0
msgid "Required fields not filled"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_callback_eval
msgid "S2S Callback"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_registration_view_template_id
msgid "S2S Form Template"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.payment_method_action
#: model:ir.ui.menu,name:payment.payment_method_menu
msgid "Saved Payment Data"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_sequence
msgid "Sequence"
msgstr "Secuencia"
#. module: payment
#: selection:payment.transaction,type:0
msgid "Server To Server"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_sips
msgid "Sips"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image_small
msgid "Small-sized image"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image_small
msgid ""
"Small-sized image of this provider. It is automatically resized as a 64x64px "
"image, with aspect ratio preserved. Use this field anywhere a small image is "
"required."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_state
msgid "Status"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_registration_view_template_id
msgid "Template for method registration"
msgstr ""
#. module: payment
#: selection:payment.acquirer,environment:0
msgid "Test"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_post_msg
msgid "Thanks Message"
msgstr ""
#. module: payment
#: constraint:payment.transaction:0
msgid "The payment transaction reference must be unique!"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image
msgid ""
"This field holds the image used for this provider, limited to 1024x1024px"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"This template renders the acquirer button with all necessary values.\n"
" It is be rendered with qWeb with "
"the following evaluation context:"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_type
msgid "Type"
msgstr "Tipo"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_date_validate
msgid "Validation Date"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_dom_var
msgid "Variable domestic fees (in percents)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_int_var
msgid "Variable international fees (in percents)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_website_published
msgid "Visible in Portal / Website"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_transfer
msgid "Wire Transfer"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "ZIP"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_zip
msgid "Zip"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_account_config_settings
msgid "account.config.settings"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "acquirer: payment.acquirer browse record"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "amount: the transaction amount, a float"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "context: the current context dictionary"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "currency: the transaction currency browse record"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "partner: the buyer partner browse record, not necessarily set"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"partner_values: specific values about the buyer, for example coming from a "
"shipping form"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_method
msgid "payment.method"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "reference: the transaction reference number"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "tx_url: transaction URL to post the form"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "tx_values: transaction values"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "user: current user browse record"
msgstr ""

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,758 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * payment
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Odoo 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-08-18 14:07+0000\n"
"PO-Revision-Date: 2015-11-18 13:41+0000\n"
"Last-Translator: Martin Trigaux\n"
"Language-Team: French (Belgium) (http://www.transifex.com/odoo/odoo-9/"
"language/fr_BE/)\n"
"Language: fr_BE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_callback_eval
msgid ""
" Will be safe_eval with `self` being the current transaction. i."
"e.:\n"
" self.env['my.model'].payment_validated(self)"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_adyen
msgid "-This installs the module payment_adyen."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_authorize
msgid "-This installs the module payment_authorize."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_buckaroo
msgid "-This installs the module payment_buckaroo."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_ogone
msgid "-This installs the module payment_ogone."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_paypal
msgid "-This installs the module payment_paypal."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_sips
msgid "-This installs the module payment_sips."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_transfer
msgid "-This installs the module payment_transfer."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_html_3ds
msgid "3D Secure HTML"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"<span class=\"text-danger\">Test</span>\n"
" <span class=\"o_stat_text\">Environment</"
"span>"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"<span class=\"text-success\">Production</span>\n"
" <span class=\"o_stat_text\">Environment</"
"span>"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_acquirer_id
msgid "Acquirer"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_acquirer_id
msgid "Acquirer Account"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_acquirer_ref
msgid "Acquirer Ref."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_acquirer_reference
msgid "Acquirer Reference"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_active
msgid "Active"
msgstr "Actif"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_active
msgid "Add Extra Fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_address
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Address"
msgstr "Adresse"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_adyen
msgid "Adyen"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_amount
#: model:ir.model.fields,help:payment.field_payment_transaction_amount
msgid "Amount"
msgstr "Montant"
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "At payment no acquirer confirmation needed"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "At payment with acquirer confirmation"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_authorize
msgid "Authorize.Net"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_buckaroo
msgid "Buckaroo"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_cancel_msg
msgid "Cancel Message"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Canceled"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_city
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "City"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_company_id
msgid "Company"
msgstr "Société"
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Configuration"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.payment_acquirer_installation
msgid "Configure payment acquiring methods"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_res_partner_payment_method_count
msgid "Count Payment Method"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_country_id
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Country"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_create_uid
#: model:ir.model.fields,field_description:payment.field_payment_method_create_uid
#: model:ir.model.fields,field_description:payment.field_payment_transaction_create_uid
msgid "Created by"
msgstr "Créé par"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_create_date
#: model:ir.model.fields,field_description:payment.field_payment_method_create_date
msgid "Created on"
msgstr "Créé le"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_create_date
msgid "Creation Date"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Credentials"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.view_partners_form_payment_defaultcreditcard
msgid "Credit card(s)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_currency_id
msgid "Currency"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Customer Details"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_sequence
msgid "Determine the display order"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_display_name
#: model:ir.model.fields,field_description:payment.field_payment_method_display_name
#: model:ir.model.fields,field_description:payment.field_payment_transaction_display_name
msgid "Display Name"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Done"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_done_msg
msgid "Done Message"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Draft"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "E-mail"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_email
msgid "Email"
msgstr "Email"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_environment
msgid "Environment"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Error"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_error_msg
msgid "Error Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_fees
msgid "Fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_fees
msgid "Fees amount; set by the system because depends on the acquirer"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_state_message
msgid "Field used to store error and/or validation messages for information"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_dom_fixed
msgid "Fixed domestic fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_int_fixed
msgid "Fixed international fees"
msgstr ""
#. module: payment
#: selection:payment.transaction,type:0
msgid "Form"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_view_template_id
msgid "Form Button Template"
msgstr ""
#. module: payment
#: selection:payment.transaction,type:0
msgid "Form with credentials storage"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_search
msgid "Group By"
msgstr "Grouper par"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_pre_msg
msgid "Help Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_id
#: model:ir.model.fields,field_description:payment.field_payment_method_id
#: model:ir.model.fields,field_description:payment.field_payment_transaction_id
msgid "ID"
msgstr "ID"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image
msgid "Image"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_reference
msgid "Internal reference of the TX"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_lang
msgid "Language"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer___last_update
#: model:ir.model.fields,field_description:payment.field_payment_method___last_update
#: model:ir.model.fields,field_description:payment.field_payment_transaction___last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_write_uid
#: model:ir.model.fields,field_description:payment.field_payment_method_write_uid
#: model:ir.model.fields,field_description:payment.field_payment_transaction_write_uid
msgid "Last Updated by"
msgstr "Derniere fois mis à jour par"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_write_date
#: model:ir.model.fields,field_description:payment.field_payment_method_write_date
#: model:ir.model.fields,field_description:payment.field_payment_transaction_write_date
msgid "Last Updated on"
msgstr "Dernière mis à jour le"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_website_published
msgid "Make this payment acquirer available (Customer invoices, etc.)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image_medium
msgid "Medium-sized image"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image_medium
msgid ""
"Medium-sized image of this provider. It is automatically resized as a "
"128x128px image, with aspect ratio preserved. Use this field in form views "
"or some kanban views."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_state_message
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Message"
msgstr "Message"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_post_msg
msgid "Message displayed after having done the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_pre_msg
msgid "Message displayed to explain and help the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_error_msg
msgid "Message displayed, if error is occur during the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_cancel_msg
msgid "Message displayed, if order is cancel during the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_done_msg
msgid ""
"Message displayed, if order is done successfully after having done the "
"payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_pending_msg
msgid ""
"Message displayed, if order is in pending state after having done the "
"payment process."
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Messages"
msgstr "Messages"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_name
#: model:ir.model.fields,field_description:payment.field_payment_method_name
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Name"
msgstr "Nom"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_method_name
msgid "Name of the payment method"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "No automatic confirmation"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_ogone
msgid "Ogone"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_auto_confirm
msgid "Order Confirmation"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_res_partner
#: model:ir.model.fields,field_description:payment.field_payment_method_partner_id
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_id
msgid "Partner"
msgstr "Partenaire"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_name
msgid "Partner Name"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_acquirer
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Payment Acquirer"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.action_payment_acquirer
#: model:ir.ui.menu,name:payment.payment_acquirer_menu
#: model_terms:ir.ui.view,arch_db:payment.acquirer_list
msgid "Payment Acquirers"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_payment_method_id
msgid "Payment Method"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_res_partner_payment_method_ids
#: model_terms:ir.ui.view,arch_db:payment.payment_method_form_view
#: model_terms:ir.ui.view,arch_db:payment.payment_method_tree_view
#: model_terms:ir.ui.view,arch_db:payment.payment_method_view_search
msgid "Payment Methods"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_transaction
msgid "Payment Transaction"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.action_payment_transaction
#: model:ir.actions.act_window,name:payment.action_payment_tx_ids
#: model:ir.actions.act_window,name:payment.payment_transaction_action_child
#: model:ir.model.fields,field_description:payment.field_payment_method_payment_ids
#: model:ir.ui.menu,name:payment.payment_transaction_menu
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
#: model_terms:ir.ui.view,arch_db:payment.transaction_list
msgid "Payment Transactions"
msgstr ""
#. module: payment
#: model:ir.ui.menu,name:payment.root_payment_menu
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
#: model_terms:ir.ui.view,arch_db:payment.payment_method_form_view
msgid "Payments"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_paypal
msgid "Paypal"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Pending"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_pending_msg
msgid "Pending Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_phone
msgid "Phone"
msgstr ""
#. module: payment
#: selection:payment.acquirer,environment:0
msgid "Production"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_provider
#: model_terms:ir.ui.view,arch_db:payment.acquirer_search
msgid "Provider"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_reference
msgid "Reference"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_acquirer_reference
msgid "Reference of the TX as stored in the acquirer database"
msgstr ""
#. module: payment
#: constraint:payment.acquirer:0
msgid "Required fields not filled"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_callback_eval
msgid "S2S Callback"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_registration_view_template_id
msgid "S2S Form Template"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.payment_method_action
#: model:ir.ui.menu,name:payment.payment_method_menu
msgid "Saved Payment Data"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_sequence
msgid "Sequence"
msgstr "Séquence"
#. module: payment
#: selection:payment.transaction,type:0
msgid "Server To Server"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_sips
msgid "Sips"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image_small
msgid "Small-sized image"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image_small
msgid ""
"Small-sized image of this provider. It is automatically resized as a 64x64px "
"image, with aspect ratio preserved. Use this field anywhere a small image is "
"required."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_state
msgid "Status"
msgstr "Statut"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_registration_view_template_id
msgid "Template for method registration"
msgstr ""
#. module: payment
#: selection:payment.acquirer,environment:0
msgid "Test"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_post_msg
msgid "Thanks Message"
msgstr ""
#. module: payment
#: constraint:payment.transaction:0
msgid "The payment transaction reference must be unique!"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image
msgid ""
"This field holds the image used for this provider, limited to 1024x1024px"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"This template renders the acquirer button with all necessary values.\n"
" It is be rendered with qWeb with "
"the following evaluation context:"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_type
msgid "Type"
msgstr "Type"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_date_validate
msgid "Validation Date"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_dom_var
msgid "Variable domestic fees (in percents)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_int_var
msgid "Variable international fees (in percents)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_website_published
msgid "Visible in Portal / Website"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_transfer
msgid "Wire Transfer"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "ZIP"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_zip
msgid "Zip"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_account_config_settings
msgid "account.config.settings"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "acquirer: payment.acquirer browse record"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "amount: the transaction amount, a float"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "context: the current context dictionary"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "currency: the transaction currency browse record"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "partner: the buyer partner browse record, not necessarily set"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"partner_values: specific values about the buyer, for example coming from a "
"shipping form"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_method
msgid "payment.method"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "reference: the transaction reference number"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "tx_url: transaction URL to post the form"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "tx_values: transaction values"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "user: current user browse record"
msgstr ""

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,760 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * payment
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Odoo 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-08-18 14:07+0000\n"
"PO-Revision-Date: 2015-09-08 06:27+0000\n"
"Last-Translator: Martin Trigaux\n"
"Language-Team: Kazakh (http://www.transifex.com/odoo/odoo-9/language/kk/)\n"
"Language: kk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=1; plural=0;\n"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_callback_eval
msgid ""
" Will be safe_eval with `self` being the current transaction. i."
"e.:\n"
" self.env['my.model'].payment_validated(self)"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_adyen
msgid "-This installs the module payment_adyen."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_authorize
msgid "-This installs the module payment_authorize."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_buckaroo
msgid "-This installs the module payment_buckaroo."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_ogone
msgid "-This installs the module payment_ogone."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_paypal
msgid "-This installs the module payment_paypal."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_sips
msgid "-This installs the module payment_sips."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_account_config_settings_module_payment_transfer
msgid "-This installs the module payment_transfer."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_html_3ds
msgid "3D Secure HTML"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"<span class=\"text-danger\">Test</span>\n"
" <span class=\"o_stat_text\">Environment</"
"span>"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"<span class=\"text-success\">Production</span>\n"
" <span class=\"o_stat_text\">Environment</"
"span>"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_acquirer_id
msgid "Acquirer"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_acquirer_id
msgid "Acquirer Account"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_acquirer_ref
msgid "Acquirer Ref."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_acquirer_reference
msgid "Acquirer Reference"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_method_active
msgid "Active"
msgstr "Белсенді"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_active
msgid "Add Extra Fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_address
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Address"
msgstr "Адресі"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_adyen
msgid "Adyen"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_amount
#: model:ir.model.fields,help:payment.field_payment_transaction_amount
msgid "Amount"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "At payment no acquirer confirmation needed"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "At payment with acquirer confirmation"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_authorize
msgid "Authorize.Net"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_buckaroo
msgid "Buckaroo"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_cancel_msg
msgid "Cancel Message"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Canceled"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_city
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "City"
msgstr "Қала"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_company_id
msgid "Company"
msgstr "Компания"
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Configuration"
msgstr "Баптау"
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.payment_acquirer_installation
msgid "Configure payment acquiring methods"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_res_partner_payment_method_count
msgid "Count Payment Method"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_country_id
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Country"
msgstr "Кантри"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_create_uid
#: model:ir.model.fields,field_description:payment.field_payment_method_create_uid
#: model:ir.model.fields,field_description:payment.field_payment_transaction_create_uid
msgid "Created by"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_create_date
#: model:ir.model.fields,field_description:payment.field_payment_method_create_date
msgid "Created on"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_create_date
msgid "Creation Date"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Credentials"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.view_partners_form_payment_defaultcreditcard
msgid "Credit card(s)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_currency_id
msgid "Currency"
msgstr "Ақша"
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Customer Details"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_sequence
msgid "Determine the display order"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_display_name
#: model:ir.model.fields,field_description:payment.field_payment_method_display_name
#: model:ir.model.fields,field_description:payment.field_payment_transaction_display_name
msgid "Display Name"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Done"
msgstr "Бітті"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_done_msg
msgid "Done Message"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Draft"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "E-mail"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_email
msgid "Email"
msgstr "Эл.поштасы"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_environment
msgid "Environment"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Error"
msgstr "Қате"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_error_msg
msgid "Error Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_fees
msgid "Fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_fees
msgid "Fees amount; set by the system because depends on the acquirer"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_state_message
msgid "Field used to store error and/or validation messages for information"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_dom_fixed
msgid "Fixed domestic fees"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_int_fixed
msgid "Fixed international fees"
msgstr ""
#. module: payment
#: selection:payment.transaction,type:0
msgid "Form"
msgstr "Пішін"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_view_template_id
msgid "Form Button Template"
msgstr ""
#. module: payment
#: selection:payment.transaction,type:0
msgid "Form with credentials storage"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_search
msgid "Group By"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_pre_msg
msgid "Help Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_id
#: model:ir.model.fields,field_description:payment.field_payment_method_id
#: model:ir.model.fields,field_description:payment.field_payment_transaction_id
msgid "ID"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image
msgid "Image"
msgstr "Сурет"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_reference
msgid "Internal reference of the TX"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_lang
msgid "Language"
msgstr "Тіл"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer___last_update
#: model:ir.model.fields,field_description:payment.field_payment_method___last_update
#: model:ir.model.fields,field_description:payment.field_payment_transaction___last_update
msgid "Last Modified on"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_write_uid
#: model:ir.model.fields,field_description:payment.field_payment_method_write_uid
#: model:ir.model.fields,field_description:payment.field_payment_transaction_write_uid
msgid "Last Updated by"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_write_date
#: model:ir.model.fields,field_description:payment.field_payment_method_write_date
#: model:ir.model.fields,field_description:payment.field_payment_transaction_write_date
msgid "Last Updated on"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_website_published
msgid "Make this payment acquirer available (Customer invoices, etc.)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image_medium
msgid "Medium-sized image"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image_medium
msgid ""
"Medium-sized image of this provider. It is automatically resized as a "
"128x128px image, with aspect ratio preserved. Use this field in form views "
"or some kanban views."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_state_message
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Message"
msgstr "Хат"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_post_msg
msgid "Message displayed after having done the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_pre_msg
msgid "Message displayed to explain and help the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_error_msg
msgid "Message displayed, if error is occur during the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_cancel_msg
msgid "Message displayed, if order is cancel during the payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_done_msg
msgid ""
"Message displayed, if order is done successfully after having done the "
"payment process."
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_pending_msg
msgid ""
"Message displayed, if order is in pending state after having done the "
"payment process."
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Messages"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_name
#: model:ir.model.fields,field_description:payment.field_payment_method_name
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "Name"
msgstr "Атауы"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_method_name
msgid "Name of the payment method"
msgstr ""
#. module: payment
#: selection:payment.acquirer,auto_confirm:0
msgid "No automatic confirmation"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_ogone
msgid "Ogone"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_auto_confirm
msgid "Order Confirmation"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_res_partner
#: model:ir.model.fields,field_description:payment.field_payment_method_partner_id
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_id
msgid "Partner"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_name
msgid "Partner Name"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_acquirer
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "Payment Acquirer"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.action_payment_acquirer
#: model:ir.ui.menu,name:payment.payment_acquirer_menu
#: model_terms:ir.ui.view,arch_db:payment.acquirer_list
msgid "Payment Acquirers"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_payment_method_id
msgid "Payment Method"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_res_partner_payment_method_ids
#: model_terms:ir.ui.view,arch_db:payment.payment_method_form_view
#: model_terms:ir.ui.view,arch_db:payment.payment_method_tree_view
#: model_terms:ir.ui.view,arch_db:payment.payment_method_view_search
msgid "Payment Methods"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_transaction
msgid "Payment Transaction"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.action_payment_transaction
#: model:ir.actions.act_window,name:payment.action_payment_tx_ids
#: model:ir.actions.act_window,name:payment.payment_transaction_action_child
#: model:ir.model.fields,field_description:payment.field_payment_method_payment_ids
#: model:ir.ui.menu,name:payment.payment_transaction_menu
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
#: model_terms:ir.ui.view,arch_db:payment.transaction_list
msgid "Payment Transactions"
msgstr ""
#. module: payment
#: model:ir.ui.menu,name:payment.root_payment_menu
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
#: model_terms:ir.ui.view,arch_db:payment.payment_method_form_view
msgid "Payments"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_paypal
msgid "Paypal"
msgstr ""
#. module: payment
#: selection:payment.transaction,state:0
msgid "Pending"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_pending_msg
msgid "Pending Message"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_phone
msgid "Phone"
msgstr "Телефондау"
#. module: payment
#: selection:payment.acquirer,environment:0
msgid "Production"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_provider
#: model_terms:ir.ui.view,arch_db:payment.acquirer_search
msgid "Provider"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_reference
msgid "Reference"
msgstr "Сілтеме"
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_transaction_acquirer_reference
msgid "Reference of the TX as stored in the acquirer database"
msgstr ""
#. module: payment
#: constraint:payment.acquirer:0
msgid "Required fields not filled"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_callback_eval
msgid "S2S Callback"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_registration_view_template_id
msgid "S2S Form Template"
msgstr ""
#. module: payment
#: model:ir.actions.act_window,name:payment.payment_method_action
#: model:ir.ui.menu,name:payment.payment_method_menu
msgid "Saved Payment Data"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_sequence
msgid "Sequence"
msgstr "Тізбек"
#. module: payment
#: selection:payment.transaction,type:0
msgid "Server To Server"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_sips
msgid "Sips"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_image_small
msgid "Small-sized image"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image_small
msgid ""
"Small-sized image of this provider. It is automatically resized as a 64x64px "
"image, with aspect ratio preserved. Use this field anywhere a small image is "
"required."
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_state
msgid "Status"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_registration_view_template_id
msgid "Template for method registration"
msgstr ""
#. module: payment
#: selection:payment.acquirer,environment:0
msgid "Test"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_post_msg
msgid "Thanks Message"
msgstr ""
#. module: payment
#: constraint:payment.transaction:0
msgid "The payment transaction reference must be unique!"
msgstr ""
#. module: payment
#: model:ir.model.fields,help:payment.field_payment_acquirer_image
msgid ""
"This field holds the image used for this provider, limited to 1024x1024px"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"This template renders the acquirer button with all necessary values.\n"
" It is be rendered with qWeb with "
"the following evaluation context:"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_type
msgid "Type"
msgstr "Түрі"
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_date_validate
msgid "Validation Date"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_dom_var
msgid "Variable domestic fees (in percents)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_fees_int_var
msgid "Variable international fees (in percents)"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_acquirer_website_published
msgid "Visible in Portal / Website"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_account_config_settings_module_payment_transfer
msgid "Wire Transfer"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.transaction_form
msgid "ZIP"
msgstr ""
#. module: payment
#: model:ir.model.fields,field_description:payment.field_payment_transaction_partner_zip
msgid "Zip"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_account_config_settings
msgid "account.config.settings"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "acquirer: payment.acquirer browse record"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "amount: the transaction amount, a float"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "context: the current context dictionary"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "currency: the transaction currency browse record"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "partner: the buyer partner browse record, not necessarily set"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid ""
"partner_values: specific values about the buyer, for example coming from a "
"shipping form"
msgstr ""
#. module: payment
#: model:ir.model,name:payment.model_payment_method
msgid "payment.method"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "reference: the transaction reference number"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "tx_url: transaction URL to post the form"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "tx_values: transaction values"
msgstr ""
#. module: payment
#: model_terms:ir.ui.view,arch_db:payment.acquirer_form
msgid "user: current user browse record"
msgstr ""
#~ msgid "unknown"
#~ msgstr "беймәлім"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import ir_http
from . import payment_provider
from . import payment_icon
from . import payment_token
from . import payment_transaction
from . import res_company
from . import res_partner

View file

@ -0,0 +1,12 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class IrHttp(models.AbstractModel):
_inherit = 'ir.http'
@classmethod
def _get_translation_frontend_modules_name(cls):
mods = super(IrHttp, cls)._get_translation_frontend_modules_name()
return mods + ['payment']

View file

@ -0,0 +1,21 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class PaymentIcon(models.Model):
_name = 'payment.icon'
_description = 'Payment Icon'
_order = 'sequence, name'
name = fields.Char(string="Name")
provider_ids = fields.Many2many(
string="Providers", comodel_name='payment.provider',
help="The list of providers supporting this payment icon")
image = fields.Image(
string="Image", max_width=64, max_height=64,
help="This field holds the image used for this payment icon, limited to 64x64 px")
image_payment_form = fields.Image(
string="Image displayed on the payment form", related='image', store=True, max_width=45,
max_height=30)
sequence = fields.Integer('Sequence', default=1)

View file

@ -0,0 +1,623 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from psycopg2 import sql
from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo.osv import expression
_logger = logging.getLogger(__name__)
class PaymentProvider(models.Model):
_name = 'payment.provider'
_description = 'Payment Provider'
_order = 'module_state, state desc, sequence, name'
def _valid_field_parameter(self, field, name):
return name == 'required_if_provider' or super()._valid_field_parameter(field, name)
# Configuration fields
name = fields.Char(string="Name", required=True, translate=True)
sequence = fields.Integer(string="Sequence", help="Define the display order")
code = fields.Selection(
string="Code",
help="The technical code of this payment provider.",
selection=[('none', "No Provider Set")],
default='none',
required=True,
)
state = fields.Selection(
string="State",
help="In test mode, a fake payment is processed through a test payment interface.\n"
"This mode is advised when setting up the provider.",
selection=[('disabled', "Disabled"), ('enabled', "Enabled"), ('test', "Test Mode")],
default='disabled', required=True, copy=False)
is_published = fields.Boolean(
string="Published",
help="Whether the provider is visible on the website or not. Tokens remain functional but "
"are only visible on manage forms.",
)
company_id = fields.Many2one( # Indexed to speed-up ORM searches (from ir_rule or others)
string="Company", comodel_name='res.company', default=lambda self: self.env.company.id,
required=True, index=True)
main_currency_id = fields.Many2one(
related='company_id.currency_id',
help="The main currency of the company, used to display monetary fields.",
)
payment_icon_ids = fields.Many2many(
string="Supported Payment Icons", comodel_name='payment.icon')
allow_tokenization = fields.Boolean(
string="Allow Saving Payment Methods",
help="This controls whether customers can save their payment methods as payment tokens.\n"
"A payment token is an anonymous link to the payment method details saved in the\n"
"provider's database, allowing the customer to reuse it for a next purchase.")
capture_manually = fields.Boolean(
string="Capture Amount Manually",
help="Capture the amount from Odoo, when the delivery is completed.\n"
"Use this if you want to charge your customers cards only when\n"
"you are sure you can ship the goods to them.")
allow_express_checkout = fields.Boolean(
string="Allow Express Checkout",
help="This controls whether customers can use express payment methods. Express checkout "
"enables customers to pay with Google Pay and Apple Pay from which address "
"information is collected at payment.",
)
redirect_form_view_id = fields.Many2one(
string="Redirect Form Template", comodel_name='ir.ui.view',
help="The template rendering a form submitted to redirect the user when making a payment",
domain=[('type', '=', 'qweb')],
ondelete='restrict',
)
inline_form_view_id = fields.Many2one(
string="Inline Form Template", comodel_name='ir.ui.view',
help="The template rendering the inline payment form when making a direct payment",
domain=[('type', '=', 'qweb')],
ondelete='restrict',
)
token_inline_form_view_id = fields.Many2one(
string="Token Inline Form Template",
comodel_name='ir.ui.view',
help="The template rendering the inline payment form when making a payment by token.",
domain=[('type', '=', 'qweb')],
ondelete='restrict',
)
express_checkout_form_view_id = fields.Many2one(
string="Express Checkout Form Template",
comodel_name='ir.ui.view',
help="The template rendering the express payment methods' form.",
domain=[('type', '=', 'qweb')],
ondelete='restrict',
)
# Availability fields
available_country_ids = fields.Many2many(
string="Countries",
comodel_name='res.country',
help="The countries in which this payment provider is available. Leave blank to make it "
"available in all countries.",
relation='payment_country_rel',
column1='payment_id',
column2='country_id',
)
maximum_amount = fields.Monetary(
string="Maximum Amount",
help="The maximum payment amount that this payment provider is available for. Leave blank "
"to make it available for any payment amount.",
currency_field='main_currency_id',
)
# Fees fields
fees_active = fields.Boolean(string="Add Extra Fees")
fees_dom_fixed = fields.Float(string="Fixed domestic fees")
fees_dom_var = fields.Float(string="Variable domestic fees (in percents)")
fees_int_fixed = fields.Float(string="Fixed international fees")
fees_int_var = fields.Float(string="Variable international fees (in percents)")
# Message fields
display_as = fields.Char(
string="Displayed as", help="Description of the provider for customers",
translate=True)
pre_msg = fields.Html(
string="Help Message", help="The message displayed to explain and help the payment process",
translate=True)
pending_msg = fields.Html(
string="Pending Message",
help="The message displayed if the order pending after the payment process",
default=lambda self: _(
"Your payment has been successfully processed but is waiting for approval."
), translate=True)
auth_msg = fields.Html(
string="Authorize Message", help="The message displayed if payment is authorized",
default=lambda self: _("Your payment has been authorized."), translate=True)
done_msg = fields.Html(
string="Done Message",
help="The message displayed if the order is successfully done after the payment process",
default=lambda self: _("Your payment has been successfully processed. Thank you!"),
translate=True)
cancel_msg = fields.Html(
string="Canceled Message",
help="The message displayed if the order is canceled during the payment process",
default=lambda self: _("Your payment has been cancelled."), translate=True)
# Feature support fields
support_tokenization = fields.Boolean(
string="Tokenization Supported", compute='_compute_feature_support_fields'
)
support_manual_capture = fields.Boolean(
string="Manual Capture Supported", compute='_compute_feature_support_fields'
)
support_express_checkout = fields.Boolean(
string="Express Checkout Supported", compute='_compute_feature_support_fields'
)
support_refund = fields.Selection(
string="Type of Refund Supported",
selection=[('full_only', "Full Only"), ('partial', "Partial")],
compute='_compute_feature_support_fields',
)
support_fees = fields.Boolean(
string="Fees Supported", compute='_compute_feature_support_fields'
)
# Kanban view fields
image_128 = fields.Image(string="Image", max_width=128, max_height=128)
color = fields.Integer(
string="Color", help="The color of the card in kanban view", compute='_compute_color',
store=True)
# Module-related fields
module_id = fields.Many2one(string="Corresponding Module", comodel_name='ir.module.module')
module_state = fields.Selection(
string="Installation State", related='module_id.state', store=True) # Stored for sorting.
module_to_buy = fields.Boolean(string="Odoo Enterprise Module", related='module_id.to_buy')
# View configuration fields
show_credentials_page = fields.Boolean(compute='_compute_view_configuration_fields')
show_allow_tokenization = fields.Boolean(compute='_compute_view_configuration_fields')
show_allow_express_checkout = fields.Boolean(compute='_compute_view_configuration_fields')
show_payment_icon_ids = fields.Boolean(compute='_compute_view_configuration_fields')
show_pre_msg = fields.Boolean(compute='_compute_view_configuration_fields')
show_pending_msg = fields.Boolean(compute='_compute_view_configuration_fields')
show_auth_msg = fields.Boolean(compute='_compute_view_configuration_fields')
show_done_msg = fields.Boolean(compute='_compute_view_configuration_fields')
show_cancel_msg = fields.Boolean(compute='_compute_view_configuration_fields')
#=== COMPUTE METHODS ===#
@api.depends('state', 'module_state')
def _compute_color(self):
""" Update the color of the kanban card based on the state of the provider.
:return: None
"""
for provider in self:
if provider.module_id and not provider.module_state == 'installed':
provider.color = 4 # blue
elif provider.state == 'disabled':
provider.color = 3 # yellow
elif provider.state == 'test':
provider.color = 2 # orange
elif provider.state == 'enabled':
provider.color = 7 # green
@api.depends('code')
def _compute_view_configuration_fields(self):
""" Compute the view configuration fields based on the provider.
View configuration fields are used to hide specific elements (notebook pages, fields, etc.)
from the form view of payment providers. These fields are set to `True` by default and are
as follows:
- `show_credentials_page`: Whether the "Credentials" notebook page should be shown.
- `show_allow_tokenization`: Whether the `allow_tokenization` field should be shown.
- `show_allow_express_checkout`: Whether the `allow_express_checkout` field should be shown.
- `show_payment_icon_ids`: Whether the `payment_icon_ids` field should be shown.
- `show_pre_msg`: Whether the `pre_msg` field should be shown.
- `show_pending_msg`: Whether the `pending_msg` field should be shown.
- `show_auth_msg`: Whether the `auth_msg` field should be shown.
- `show_done_msg`: Whether the `done_msg` field should be shown.
- `show_cancel_msg`: Whether the `cancel_msg` field should be shown.
For a provider to hide specific elements of the form view, it must override this method and
set the related view configuration fields to `False` on the appropriate `payment.provider`
records.
:return: None
"""
self.update({
'show_credentials_page': True,
'show_allow_tokenization': True,
'show_allow_express_checkout': True,
'show_payment_icon_ids': True,
'show_pre_msg': True,
'show_pending_msg': True,
'show_auth_msg': True,
'show_done_msg': True,
'show_cancel_msg': True,
})
def _compute_feature_support_fields(self):
""" Compute the feature support fields based on the provider.
Feature support fields are used to specify which additional features are supported by a
given provider. These fields are as follows:
- `support_express_checkout`: Whether the "express checkout" feature is supported. `False`
by default.
- `support_fees`: Whether the "extra fees" feature is supported. `False` by default.
- `support_manual_capture`: Whether the "manual capture" feature is supported. `False` by
default.
- `support_refund`: Which type of the "refunds" feature is supported: `None`,
`'full_only'`, or `'partial'`. `None` by default.
- `support_tokenization`: Whether the "tokenization feature" is supported. `False` by
default.
For a provider to specify that it supports additional features, it must override this method
and set the related feature support fields to the desired value on the appropriate
`payment.provider` records.
:return: None
"""
self.update(dict.fromkeys((
'support_express_checkout',
'support_fees',
'support_manual_capture',
'support_refund',
'support_tokenization',
), None))
#=== ONCHANGE METHODS ===#
@api.onchange('state')
def _onchange_state_switch_is_published(self):
""" Automatically publish or unpublish the provider depending on its state.
:return: None
"""
self.is_published = self.state == 'enabled'
@api.onchange('state')
def _onchange_state_warn_before_disabling_tokens(self):
""" Display a warning about the consequences of disabling a provider.
Let the user know that tokens related to a provider get archived if it is disabled or if its
state is changed from 'test' to 'enabled', and vice versa.
:return: A client action with the warning message, if any.
:rtype: dict
"""
if self._origin.state in ('test', 'enabled') and self._origin.state != self.state:
related_tokens = self.env['payment.token'].search(
[('provider_id', '=', self._origin.id)]
)
if related_tokens:
return {
'warning': {
'title': _("Warning"),
'message': _(
"This action will also archive %s tokens that are registered with this "
"provider. Archiving tokens is irreversible.", len(related_tokens)
)
}
}
#=== CONSTRAINT METHODS ===#
@api.constrains('fees_dom_var', 'fees_int_var')
def _check_fee_var_within_boundaries(self):
""" Check that variable fees are within realistic boundaries.
Variable fee values should always be positive and below 100% to respectively avoid negative
and infinite (division by zero) fee amounts.
:return None
"""
for provider in self:
if any(not 0 <= fee < 100 for fee in (provider.fees_dom_var, provider.fees_int_var)):
raise ValidationError(_("Variable fees must always be positive and below 100%."))
#=== CRUD METHODS ===#
@api.model_create_multi
def create(self, values_list):
providers = super().create(values_list)
providers._check_required_if_provider()
return providers
def write(self, values):
# Handle provider disabling.
if 'state' in values:
state_changed_providers = self.filtered(
lambda p: p.state not in ('disabled', values['state'])
) # Don't handle providers being enabled or whose state is not updated.
state_changed_providers._handle_state_change()
result = super().write(values)
self._check_required_if_provider()
return result
def _check_required_if_provider(self):
""" Check that provider-specific required fields have been filled.
The fields that have the `required_if_provider='<provider_code>'` attribute are made
required for all `payment.provider` records with the `code` field equal to `<provider_code>`
and with the `state` field equal to `'enabled'` or `'test'`.
Provider-specific views should make the form fields required under the same conditions.
:return: None
:raise ValidationError: If a provider-specific required field is empty.
"""
field_names = []
enabled_providers = self.filtered(lambda p: p.state in ['enabled', 'test'])
for field_name, field in self._fields.items():
required_for_provider_code = getattr(field, 'required_if_provider', None)
if required_for_provider_code and any(
required_for_provider_code == provider.code and not provider[field_name]
for provider in enabled_providers
):
ir_field = self.env['ir.model.fields']._get(self._name, field_name)
field_names.append(ir_field.field_description)
if field_names:
raise ValidationError(
_("The following fields must be filled: %s", ", ".join(field_names))
)
def _handle_state_change(self):
""" Archive all the payment tokens linked to the providers.
:return: None
"""
self.env['payment.token'].search([('provider_id', 'in', self.ids)]).write({'active': False})
@api.ondelete(at_uninstall=False)
def _unlink_except_master_data(self):
""" Prevent the deletion of the payment provider if it has an xmlid. """
external_ids = self.get_external_id()
for provider in self:
external_id = external_ids[provider.id]
if external_id and not external_id.startswith('__export__'):
raise UserError(_(
"You cannot delete the payment provider %s; disable it or uninstall it"
" instead.", provider.name
))
#=== ACTION METHODS ===#
def button_immediate_install(self):
""" Install the module and reload the page.
Note: `self.ensure_one()`
:return: The action to reload the page.
:rtype: dict
"""
if self.module_id and self.module_state != 'installed':
self.module_id.button_immediate_install()
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
def action_toggle_is_published(self):
""" Toggle the field `is_published`.
:return: None
:raise UserError: If the provider is disabled.
"""
if self.state != 'disabled':
self.is_published = not self.is_published
else:
raise UserError(_("You cannot publish a disabled provider."))
#=== BUSINESS METHODS ===#
@api.model
def _get_compatible_providers(
self, company_id, partner_id, amount, currency_id=None, force_tokenization=False,
is_express_checkout=False, is_validation=False, **kwargs
):
""" Select and return the providers matching the criteria.
The criteria are that providers must not be disabled, be in the company that is provided,
and support the country of the partner if it exists. The criteria can be further refined
by providing the keyword arguments.
:param int company_id: The company to which providers must belong, as a `res.company` id.
:param int partner_id: The partner making the payment, as a `res.partner` id.
:param float amount: The amount to pay. `0` for validation transactions.
:param int currency_id: The payment currency, if known beforehand, as a `res.currency` id.
:param bool force_tokenization: Whether only providers allowing tokenization can be matched.
:param bool is_express_checkout: Whether the payment is made through express checkout.
:param bool is_validation: Whether the operation is a validation.
:param dict kwargs: Optional data. This parameter is not used here.
:return: The compatible providers.
:rtype: recordset of `payment.provider`
"""
# Compute the base domain for compatible providers.
domain = ['&', ('state', 'in', ['enabled', 'test']), ('company_id', '=', company_id)]
# Handle the is_published state.
if not self.env.user._is_internal():
domain = expression.AND([domain, [('is_published', '=', True)]])
# Handle partner country.
partner = self.env['res.partner'].browse(partner_id)
if partner.country_id: # The partner country must either not be set or be supported.
domain = expression.AND([
domain, [
'|',
('available_country_ids', '=', False),
('available_country_ids', 'in', [partner.country_id.id]),
]
])
# Handle the maximum amount.
currency = self.env['res.currency'].browse(currency_id).exists()
if not is_validation and currency: # The currency is required to convert the amount.
company = self.env['res.company'].browse(company_id).exists()
date = fields.Date.context_today(self)
converted_amount = currency._convert(amount, company.currency_id, company, date)
domain = expression.AND([
domain, [
'|', '|',
('maximum_amount', '>=', converted_amount),
('maximum_amount', '=', False),
('maximum_amount', '=', 0.),
]
])
# Handle tokenization support requirements.
if force_tokenization or self._is_tokenization_required(**kwargs):
domain = expression.AND([domain, [('allow_tokenization', '=', True)]])
# Handle express checkout.
if is_express_checkout:
domain = expression.AND([domain, [('allow_express_checkout', '=', True)]])
compatible_providers = self.env['payment.provider'].search(domain)
return compatible_providers
def _is_tokenization_required(self, **kwargs):
""" Return whether tokenizing the transaction is required given its context.
For a module to make the tokenization required based on the transaction context, it must
override this method and return whether it is required.
:param dict kwargs: The transaction context. This parameter is not used here.
:return: Whether tokenizing the transaction is required.
:rtype: bool
"""
return False
def _should_build_inline_form(self, is_validation=False):
""" Return whether the inline payment form should be instantiated.
For a provider to handle both direct payments and payments with redirection, it must
override this method and return whether the inline payment form should be instantiated (i.e.
if the payment should be direct) based on the operation (online payment or validation).
:param bool is_validation: Whether the operation is a validation.
:return: Whether the inline form should be instantiated.
:rtype: bool
"""
return True
def _compute_fees(self, amount, currency, country):
""" Compute the transaction fees.
The computation is based on the fields `fees_dom_fixed`, `fees_dom_var`, `fees_int_fixed`
and `fees_int_var`, and is performed with the formula
:code:`fees = (amount * variable / 100.0 + fixed) / (1 - variable / 100.0)` where the values
of `fixed` and `variable` are taken from either the domestic (`dom`) or international
(`int`) fields, depending on whether the country matches the company's country.
For a provider to base the computation on different variables, or to use a different
formula, it must override this method and return the resulting fees.
:param float amount: The amount to pay for the transaction.
:param recordset currency: The currency of the transaction, as a `res.currency` record.
:param recordset country: The customer country, as a `res.country` record.
:return: The computed fees.
:rtype: float
"""
self.ensure_one()
fees = 0.0
if self.fees_active:
if country == self.company_id.country_id:
fixed = self.fees_dom_fixed
variable = self.fees_dom_var
else:
fixed = self.fees_int_fixed
variable = self.fees_int_var
fees = (amount * variable / 100.0 + fixed) / (1 - variable / 100.0)
return fees
def _get_validation_amount(self):
""" Return the amount to use for validation operations.
For a provider to support tokenization, it must override this method and return the
validation amount. If it is `0`, it is not necessary to create the override.
Note: `self.ensure_one()`
:return: The validation amount.
:rtype: float
"""
self.ensure_one()
return 0.0
def _get_validation_currency(self):
""" Return the currency to use for validation operations.
For a provider to support tokenization, it must override this method and return the
validation currency. If the validation amount is `0`, it is not necessary to create the
override.
Note: `self.ensure_one()`
:return: The validation currency.
:rtype: recordset of `res.currency`
"""
self.ensure_one()
return self.company_id.currency_id
def _get_redirect_form_view(self, is_validation=False):
""" Return the view of the template used to render the redirect form.
For a provider to return a different view depending on whether the operation is a
validation, it must override this method and return the appropriate view.
Note: `self.ensure_one()`
:param bool is_validation: Whether the operation is a validation.
:return: The view of the redirect form template.
:rtype: record of `ir.ui.view`
"""
self.ensure_one()
return self.redirect_form_view_id
@api.model
def _setup_provider(self, provider_code):
""" Perform module-specific setup steps for the provider.
This method is called after the module of a provider is installed, with its code passed as
`provider_code`.
:param str provider_code: The code of the provider to setup.
:return: None
"""
return
@api.model
def _remove_provider(self, provider_code):
""" Remove the module-specific data of the given provider.
:param str provider_code: The code of the provider whose data to remove.
:return: None
"""
providers = self.search([('code', '=', provider_code)])
providers.write(self._get_removal_values())
def _get_removal_values(self):
""" Return the values to update a provider with when its module is uninstalled.
For a module to specify additional removal values, it must override this method and complete
the generic values with its specific values.
:return: The removal values to update the removed provider with.
:rtype: dict
"""
return {
'code': 'none',
'state': 'disabled',
'is_published': False,
'redirect_form_view_id': None,
'inline_form_view_id': None,
'token_inline_form_view_id': None,
'express_checkout_form_view_id': None,
}

View file

@ -0,0 +1,147 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class PaymentToken(models.Model):
_name = 'payment.token'
_order = 'partner_id, id desc'
_description = 'Payment Token'
provider_id = fields.Many2one(string="Provider", comodel_name='payment.provider', required=True)
provider_code = fields.Selection(related='provider_id.code')
payment_details = fields.Char(
string="Payment Details", help="The clear part of the payment method's payment details.",
)
partner_id = fields.Many2one(string="Partner", comodel_name='res.partner', required=True)
company_id = fields.Many2one( # Indexed to speed-up ORM searches (from ir_rule or others)
related='provider_id.company_id', store=True, index=True)
provider_ref = fields.Char(
string="Provider Reference", help="The provider reference of the token of the transaction",
required=True) # This is not the same thing as the provider reference of the transaction.
transaction_ids = fields.One2many(
string="Payment Transactions", comodel_name='payment.transaction', inverse_name='token_id')
verified = fields.Boolean(string="Verified")
active = fields.Boolean(string="Active", default=True)
#=== CRUD METHODS ===#
@api.model_create_multi
def create(self, values_list):
for values in values_list:
if 'provider_id' in values:
provider = self.env['payment.provider'].browse(values['provider_id'])
# Include provider-specific create values
values.update(self._get_specific_create_values(provider.code, values))
else:
pass # Let psycopg warn about the missing required field.
return super().create(values_list)
@api.model
def _get_specific_create_values(self, provider_code, values):
""" Complete the values of the `create` method with provider-specific values.
For a provider to add its own create values, it must overwrite this method and return a
dict of values. Provider-specific values take precedence over those of the dict of generic
create values.
:param str provider_code: The code of the provider managing the token.
:param dict values: The original create values.
:return: The dict of provider-specific create values.
:rtype: dict
"""
return dict()
def write(self, values):
""" Prevent unarchiving tokens and handle their archiving.
:return: The result of the call to the parent method.
:rtype: bool
:raise UserError: If at least one token is being unarchived.
"""
if 'active' in values:
if values['active']:
if any(not token.active for token in self):
raise UserError(_("A token cannot be unarchived once it has been archived."))
else:
# Call the handlers in sudo mode because this method might have been called by RPC.
self.filtered('active').sudo()._handle_archiving()
return super().write(values)
def _handle_archiving(self):
""" Handle the archiving of tokens.
For a module to perform additional operations when a token is archived, it must override
this method.
:return: None
"""
return
def name_get(self):
return [(token.id, token._build_display_name()) for token in self]
#=== BUSINESS METHODS ===#
def _build_display_name(self, *args, max_length=34, should_pad=True, **kwargs):
""" Build a token name of the desired maximum length with the format `•••• 1234`.
The payment details are padded on the left with up to four padding characters. The padding
is only added if there is enough room for it. If not, it is either reduced or not added at
all. If there is not enough room for the payment details either, they are trimmed from the
left.
For a module to customize the display name of a token, it must override this method and
return the customized display name.
Note: `self.ensure_one()`
:param list args: The arguments passed by QWeb when calling this method.
:param int max_length: The desired maximum length of the token name. The default is `34` to
fit the largest IBANs.
:param bool should_pad: Whether the token should be padded.
:param dict kwargs: Optional data used in overrides of this method.
:return: The padded token name.
:rtype: str
"""
self.ensure_one()
padding_length = max_length - len(self.payment_details or '')
if not self.payment_details:
create_date_str = self.create_date.strftime('%Y/%m/%d')
display_name = _("Payment details saved on %(date)s", date=create_date_str)
elif padding_length >= 2: # Enough room for padding.
padding = '' * min(padding_length - 1, 4) + ' ' if should_pad else ''
display_name = ''.join([padding, self.payment_details])
elif padding_length > 0: # Not enough room for padding.
display_name = self.payment_details
else: # Not enough room for neither padding nor the payment details.
display_name = self.payment_details[-max_length:] if max_length > 0 else ''
return display_name
def get_linked_records_info(self):
""" Return a list of information about records linked to the current token.
For a module to implement payments and link documents to a token, it must override this
method and add information about linked document records to the returned list.
The information must be structured as a dict with the following keys:
- `description`: The description of the record's model (e.g. "Subscription").
- `id`: The id of the record.
- `name`: The name of the record.
- `url`: The url to access the record.
Note: `self.ensure_one()`
:return: The list of information about the linked document records.
:rtype: list
"""
self.ensure_one()
return []

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,72 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
payment_provider_onboarding_state = fields.Selection(
string="State of the onboarding payment provider step",
selection=[('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")],
default='not_done')
payment_onboarding_payment_method = fields.Selection(
string="Selected onboarding payment method",
selection=[
('paypal', "PayPal"),
('stripe', "Stripe"),
('manual', "Manual"),
('other', "Other"),
])
def _run_payment_onboarding_step(self, menu_id):
""" Install the suggested payment modules and configure the providers.
It's checked that the current company has a Chart of Account.
:param int menu_id: The menu from which the user started the onboarding step, as an
`ir.ui.menu` id
:return: The action returned by `action_stripe_connect_account`
:rtype: dict
"""
self.env.company.get_chart_of_accounts_or_fail()
self._install_modules(['payment_stripe', 'account_payment'])
# Create a new env including the freshly installed module(s)
new_env = api.Environment(self.env.cr, self.env.uid, self.env.context)
# Configure Stripe
default_journal = new_env['account.journal'].search(
[('type', '=', 'bank'), ('company_id', '=', new_env.company.id)], limit=1
)
stripe_provider = new_env['payment.provider'].search(
[('company_id', '=', self.env.company.id), ('code', '=', 'stripe')], limit=1
)
if not stripe_provider:
base_provider = self.env.ref('payment.payment_provider_stripe')
# Use sudo to access payment provider record that can be in different company.
stripe_provider = base_provider.sudo().with_context(
stripe_connect_onboarding=True,
).copy(default={'company_id': self.env.company.id})
stripe_provider.journal_id = stripe_provider.journal_id or default_journal
return stripe_provider.action_stripe_connect_account(menu_id=menu_id)
def _install_modules(self, module_names):
modules_sudo = self.env['ir.module.module'].sudo().search([('name', 'in', module_names)])
STATES = ['installed', 'to install', 'to upgrade']
modules_sudo.filtered(lambda m: m.state not in STATES).button_immediate_install()
def _mark_payment_onboarding_step_as_done(self):
""" Mark the payment onboarding step as done.
:return: None
"""
self.set_onboarding_step_done('payment_provider_onboarding_state')
def get_account_invoice_onboarding_steps_states_names(self):
""" Override of account. """
steps = super().get_account_invoice_onboarding_steps_states_names()
return steps + ['payment_provider_onboarding_state']

View file

@ -0,0 +1,22 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
payment_token_ids = fields.One2many(
string="Payment Tokens", comodel_name='payment.token', inverse_name='partner_id')
payment_token_count = fields.Integer(
string="Payment Token Count", compute='_compute_payment_token_count')
@api.depends('payment_token_ids')
def _compute_payment_token_count(self):
payments_data = self.env['payment.token']._read_group(
[('partner_id', 'in', self.ids)], ['partner_id'], ['partner_id']
)
partners_data = {payment_data['partner_id'][0]: payment_data['partner_id_count']
for payment_data in payments_data}
for partner in self:
partner.payment_token_count = partners_data.get(partner.id, 0)

Some files were not shown because too many files have changed in this diff Show more