[MOV] (website_)payment: move customer portal for payments to payment
Customer portal controller and templates contained in website_payment module are moved to payment. This module now uses the customer portal defined in portal module and most of website_payment code is moved to payment. website_payment now contain code really related to website, such as payment acquirers configuration for website.
This commit is contained in:
@@ -2,3 +2,4 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
from . import controllers
|
||||
@@ -13,7 +13,8 @@
|
||||
'views/payment_views.xml',
|
||||
'views/account_payment_views.xml',
|
||||
'views/payment_templates.xml',
|
||||
'views/payment_assets.xml',
|
||||
'views/payment_portal_templates.xml',
|
||||
'views/assets.xml',
|
||||
'views/res_partner_views.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/payment_security.xml',
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import portal
|
||||
@@ -19,7 +19,7 @@ class WebsitePayment(http.Controller):
|
||||
return_url = request.params.get('redirect', '/my/payment_method')
|
||||
for acquirer in acquirers:
|
||||
acquirer.form = acquirer.sudo()._registration_render(request.env.user.partner_id.id, {'error': {}, 'error_message': [], 'return_url': return_url, 'json': False, 'bootstrap_formatting': True, 'verify_validity': True})
|
||||
return request.render("website_payment.pay_methods", values)
|
||||
return request.render("payment.pay_methods", values)
|
||||
|
||||
@http.route(['/website_payment/delete/'], methods=['POST'], type='http', auth="user", website=True)
|
||||
def delete(self, delete_pm_id=None):
|
||||
@@ -46,7 +46,7 @@ class WebsitePayment(http.Controller):
|
||||
# auto-increment reference with a number suffix if the reference already exists
|
||||
reference = request.env['payment.transaction'].get_next_reference(reference)
|
||||
|
||||
partner_id = user.partner_id.id if user.partner_id.id != request.website.partner_id.id else False
|
||||
partner_id = user.partner_id.id if not user._is_public() else False
|
||||
|
||||
payment_form = acquirer.sudo().render(reference, float(amount), currency.id, values={'return_url': '/website_payment/confirm', 'partner_id': partner_id})
|
||||
values = {
|
||||
@@ -56,11 +56,11 @@ class WebsitePayment(http.Controller):
|
||||
'amount': float(amount),
|
||||
'payment_form': payment_form,
|
||||
}
|
||||
return request.render('website_payment.pay', values)
|
||||
return request.render('payment.pay', values)
|
||||
|
||||
@http.route(['/website_payment/transaction'], type='json', auth="public", website=True)
|
||||
def transaction(self, reference, amount, currency_id, acquirer_id):
|
||||
partner_id = request.env.user.partner_id.id if request.env.user.partner_id != request.website.partner_id else False
|
||||
partner_id = request.env.user.partner_id.id if not request.env.user._is_public() else False
|
||||
values = {
|
||||
'acquirer_id': int(acquirer_id),
|
||||
'reference': reference,
|
||||
@@ -87,7 +87,7 @@ class WebsitePayment(http.Controller):
|
||||
else:
|
||||
status = 'danger'
|
||||
message = tx.acquirer_id.error_msg
|
||||
return request.render('website_payment.confirm', {'tx': tx, 'status': status, 'message': message})
|
||||
return request.render('payment.confirm', {'tx': tx, 'status': status, 'message': message})
|
||||
else:
|
||||
return request.redirect('/my/home')
|
||||
|
||||
+8
-2
@@ -62,12 +62,17 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
|
||||
odoo.define('website_payment.payment_acquirer', function (require) {
|
||||
odoo.define('payment.payment_acquirer', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
var Dialog = require('web.Dialog');
|
||||
var website = require('website.website');
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
if( !$('#payment_tokens_list').length ) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.payment_tokens_list'");
|
||||
}
|
||||
|
||||
var payment_methods = $('#payment_tokens_list');
|
||||
|
||||
@@ -115,3 +120,4 @@ var website = require('website.website');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
odoo.define('payment.website_payment', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
if(!$('.o_website_payment').length) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.o_website_payment'");
|
||||
}
|
||||
|
||||
// When clicking on payment button: create the tx using json then continue to the acquirer
|
||||
var $payment = $(".o_website_payment_form");
|
||||
$payment.on("click", 'button[type="submit"],button[name="submit"]', function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
$(ev.currentTarget).attr('disabled', true);
|
||||
$(ev.currentTarget).prepend('<i class="fa fa-refresh fa-spin"></i> ');
|
||||
var $form = $(ev.currentTarget).parents('form');
|
||||
var data =$("div[class~='o_website_payment_new_payment']").data();
|
||||
ajax.jsonRpc('/website_payment/transaction/', 'call', data).then(function (result) {
|
||||
$form.submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="assets_frontend" inherit_id="web.assets_frontend" name="Payment Tx Assets">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel='stylesheet' href='/payment/static/src/css/portal_payment.css'/>
|
||||
<script type="text/javascript" src="/payment/static/lib/jquery.payment/jquery.payment.js"></script>
|
||||
<script type="text/javascript" src="/payment/static/src/js/payment_transaction.js"></script>
|
||||
<script type="text/javascript" src="/payment/static/src/js/payment_portal.js"></script>
|
||||
<script type="text/javascript" src="/payment/static/src/js/payment_transaction_portal.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="assets_frontend" inherit_id="web.assets_frontend" name="Payment Tx Assets">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/payment/static/src/js/payment_transaction.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="pay_methods" name="Payment Acquirers">
|
||||
<t t-call="portal.frontend_layout">
|
||||
<t t-set="additional_title">Payment Acquirers</t>
|
||||
<div class="wrap">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li>Payment Acquirers</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<h1>Payment Acquirers</h1>
|
||||
<h4 t-if="acquirers">Add a new payment acquirer:</h4>
|
||||
<div t-if="acquirers" class="row">
|
||||
<div class="col-sm-8">
|
||||
<div t-if="error_message" class="alert alert-danger">
|
||||
<t t-foreach="error_message" t-as="err"><t t-esc="err"/><br /></t>
|
||||
</div>
|
||||
<div t-if='len(acquirers)>1'>
|
||||
<label class="control-label" for="pm_acquirer_id">Acquirer</label>
|
||||
<select name="pm_acquirer_id" class="form-control">
|
||||
<t t-foreach="acquirers" t-as="acquirer">
|
||||
<option t-att-value="acquirer.id" t-esc="acquirer.name"/>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<t t-foreach="acquirers" t-as="acquirer">
|
||||
<div t-raw="acquirer.form" t-att-data-acquirer-id="acquirer.id" t-attf-class="acquirer #{'hidden' if acquirer!=acquirers[0] else ''}"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="pms" class="clearfix">
|
||||
<h4>Your payment Methods</h4>
|
||||
<t t-set="show_delete" t-value="True"/>
|
||||
<t t-set="form_action" t-value="'/website_payment/delete/'"/>
|
||||
<div class="col-sm-8">
|
||||
<t t-call="payment.payment_tokens_list"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- TDE FIXME: was customize_show=True -->
|
||||
<template id="pay_meth_link" inherit_id="portal.portal_layout">
|
||||
<xpath expr="//div[@class='o_portal_my_details']" position="inside">
|
||||
<t t-if="request.env['payment.acquirer'].search([('website_published', '=', True), ('registration_view_template_id', '!=', False)])">
|
||||
<div class='manage_payment_method mt16'><a href="/my/payment_method">Manage your payment acquirers</a></div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="pay">
|
||||
<t t-call="portal.frontend_layout">
|
||||
<t t-set="additional_title">Payment</t>
|
||||
<div class="wrap">
|
||||
<div class="container o_website_payment">
|
||||
<h1>Payment</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="oe_structure"></div>
|
||||
<div>
|
||||
<div class="form-horizontal row o_website_payment_new_payment" t-att-data-acquirer_id="acquirer.id" t-att-data-currency_id="currency.id" t-att-data-reference="reference" t-att-data-amount="amount">
|
||||
<div class="form-group">
|
||||
<label for="form_reference" class="col-sm-3 control-label">Reference</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_reference" class="form-control" t-esc="reference"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="form_amount" class="col-sm-3 control-label">Amount</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_amount" class="form-control" t-esc="amount" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-offset-3 text-muted mt16" t-raw="acquirer.pre_msg"/>
|
||||
<div class="col-sm-12 o_website_payment_form" t-raw="payment_form"/>
|
||||
<div class="col-sm-6 col-sm-offset-6 text-muted mt16">
|
||||
<span t-field="acquirer.image_small" t-att-title="acquirer.name" t-options='{"widget": "image", "style":"max-width: 60px; display: inline-block"}'/>
|
||||
<span>Processed by <t t-esc="acquirer.name"/>.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="confirm">
|
||||
<t t-call="portal.frontend_layout">
|
||||
<t t-set="additional_title">Payment</t>
|
||||
<div class="wrap">
|
||||
<div class="container o_website_payment">
|
||||
<h1>Payment</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-horizontal">
|
||||
<div t-attf-class="alert alert-#{status}" t-raw="message"/>
|
||||
<div class="form-group">
|
||||
<label for="form_partner_name" class="col-sm-3 control-label">From</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_partner_name" class="form-control" t-esc="tx.partner_name"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="form_reference" class="col-sm-3 control-label">Reference</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_reference" class="form-control" t-esc="tx.reference"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="form_amount" class="col-sm-3 control-label">Amount</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_amount" class="form-control" t-esc="tx.amount" t-options="{'widget': 'monetary', 'display_currency': tx.currency_id}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<a t-attf-class="btn btn-#{status} pull-right" href="/my/home"><i class="fa fa-arrow-circle-right"/> Back to My Account</a>
|
||||
</div>
|
||||
<div class="col-sm-6 col-sm-offset-6 text-muted mt16">
|
||||
<span t-field="tx.acquirer_id.image_small" t-att-title="tx.acquirer_id.name" t-options='{"widget": "image", "style":"max-width: 60px; display: inline-block"}'/>
|
||||
<span>Processed by <t t-esc="tx.acquirer_id.name"/>.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -2,4 +2,3 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
from . import controllers
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from . import main
|
||||
@@ -1,26 +0,0 @@
|
||||
odoo.define('website_payment.website_payment', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
var website = require('website.website');
|
||||
|
||||
if(!$('.o_website_payment').length) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.o_website_payment'");
|
||||
}
|
||||
|
||||
// When clicking on payment button: create the tx using json then continue to the acquirer
|
||||
var $payment = $(".o_website_payment_form");
|
||||
$payment.on("click", 'button[type="submit"],button[name="submit"]', function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
$(ev.currentTarget).attr('disabled', true);
|
||||
$(ev.currentTarget).prepend('<i class="fa fa-refresh fa-spin"></i> ');
|
||||
var $form = $(ev.currentTarget).parents('form');
|
||||
var data =$("div[class~='o_website_payment_new_payment']").data();
|
||||
console.log(data);
|
||||
ajax.jsonRpc('/website_payment/transaction/', 'call', data).then(function (result) {
|
||||
$form.submit();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,164 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="header_footer_custom_payment" inherit_id="website.footer_default" customize_show="True" active="False" name="Payment Acquirers">
|
||||
<xpath expr="//div[@id='info']" position="inside">
|
||||
<h4 class="payment_method_title">Payment Acquirer</h4>
|
||||
<ul class="payment_method_list list-inline">
|
||||
<t t-foreach="request.website.payment_acquirers()" t-as="acquirer">
|
||||
<li>
|
||||
<span t-field="acquirer.image_small" t-options='{"widget": "image", "alt-field": "name"}' />
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Payment Frontend assets">
|
||||
<xpath expr="." position="inside">
|
||||
|
||||
<link rel='stylesheet' href='/website_payment/static/src/css/website_payment.css'/>
|
||||
<script type="text/javascript" src="/website_payment/static/src/js/payment_acquirer.js"></script>
|
||||
<script type="text/javascript" src="/website_payment/static/lib/jquery.payment/jquery.payment.js"></script>
|
||||
<script type="text/javascript" src="/website_payment/static/src/js/payment_transaction.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="pay_methods" name="Payment Acquirers">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="additional_title">Payment Acquirers</t>
|
||||
<div class="wrap">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li>Payment Acquirers</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<h1>Payment Acquirers</h1>
|
||||
<h4 t-if="acquirers">Add a new payment acquirer:</h4>
|
||||
<div t-if="acquirers" class="row">
|
||||
<div class="col-sm-8">
|
||||
<div t-if="error_message" class="alert alert-danger">
|
||||
<t t-foreach="error_message" t-as="err"><t t-esc="err"/><br /></t>
|
||||
</div>
|
||||
<div t-if='len(acquirers)>1'>
|
||||
<label class="control-label" for="pm_acquirer_id">Acquirer</label>
|
||||
<select name="pm_acquirer_id" class="form-control">
|
||||
<t t-foreach="acquirers" t-as="acquirer">
|
||||
<option t-att-value="acquirer.id" t-esc="acquirer.name"/>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<t t-foreach="acquirers" t-as="acquirer">
|
||||
<div t-raw="acquirer.form" t-att-data-acquirer-id="acquirer.id" t-attf-class="acquirer #{'hidden' if acquirer!=acquirers[0] else ''}"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="pms" class="clearfix">
|
||||
<h4>Your payment Methods</h4>
|
||||
<t t-set="show_delete" t-value="True"/>
|
||||
<t t-set="form_action" t-value="'/website_payment/delete/'"/>
|
||||
<div class="col-sm-8">
|
||||
<t t-call="payment.payment_tokens_list"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="pay_meth_link" inherit_id="portal.portal_layout" customize_show="True">
|
||||
<xpath expr="//div[@class='o_portal_my_details']" position="inside">
|
||||
<t t-if="request.env['payment.acquirer'].search([('website_published', '=', True), ('registration_view_template_id', '!=', False)])">
|
||||
<div class='manage_payment_method mt16'><a href="/my/payment_method">Manage your payment acquirers</a></div>
|
||||
</t>
|
||||
<template id="header_footer_custom_payment" inherit_id="website.footer_default" customize_show="True" active="False" name="Payment Acquirers">
|
||||
<xpath expr="//div[@id='info']" position="inside">
|
||||
<h4 class="payment_method_title">Payment Acquirer</h4>
|
||||
<ul class="payment_method_list list-inline">
|
||||
<t t-foreach="request.website.payment_acquirers()" t-as="acquirer">
|
||||
<li>
|
||||
<span t-field="acquirer.image_small" t-options='{"widget": "image", "alt-field": "name"}' />
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="pay">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="additional_title">Payment</t>
|
||||
<div class="wrap">
|
||||
<div class="container o_website_payment">
|
||||
<h1>Payment</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="oe_structure"></div>
|
||||
<div>
|
||||
<div class="form-horizontal row o_website_payment_new_payment" t-att-data-acquirer_id="acquirer.id" t-att-data-currency_id="currency.id" t-att-data-reference="reference" t-att-data-amount="amount">
|
||||
<div class="form-group">
|
||||
<label for="form_reference" class="col-sm-3 control-label">Reference</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_reference" class="form-control" t-esc="reference"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="form_amount" class="col-sm-3 control-label">Amount</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_amount" class="form-control" t-esc="amount" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-offset-3 text-muted mt16" t-raw="acquirer.pre_msg"/>
|
||||
<div class="col-sm-12 o_website_payment_form" t-raw="payment_form"/>
|
||||
<div class="col-sm-6 col-sm-offset-6 text-muted mt16">
|
||||
<img alt="payment_provider_logo" class="pull-right ml8" t-att-src="website.image_url(acquirer, 'image_small')"/>
|
||||
<span>This transaction will be processed by <t t-esc="acquirer.name"/>.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="confirm">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="additional_title">Payment</t>
|
||||
<div class="wrap">
|
||||
<div class="container o_website_payment">
|
||||
<h1>Payment</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-horizontal">
|
||||
<div t-attf-class="alert alert-#{status}" t-raw="message"/>
|
||||
<div class="form-group">
|
||||
<label for="form_partner_name" class="col-sm-3 control-label">From</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_partner_name" class="form-control" t-esc="tx.partner_name"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="form_reference" class="col-sm-3 control-label">Reference</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_reference" class="form-control" t-esc="tx.reference"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="form_amount" class="col-sm-3 control-label">Amount</label>
|
||||
<div class="col-sm-9">
|
||||
<span name="form_amount" class="form-control" t-esc="tx.amount" t-options="{'widget': 'monetary', 'display_currency': tx.currency_id}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<a t-attf-class="btn btn-#{status} pull-right" href="/my/home"><i class="fa fa-arrow-circle-right"/> Back to My Account</a>
|
||||
</div>
|
||||
<div class="col-sm-6 col-sm-offset-6 text-muted mt16">
|
||||
<img alt="payment_provider_logo" class="pull-right ml8" t-att-src="website.image_url(tx.acquirer_id, 'image_small')"/>
|
||||
<span>Payment processed by <t t-esc="tx.acquirer_id.name"/>.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user