mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[IMP] contract_variable_quantity: black, isort, prettier
This commit is contained in:
committed by
Víctor Martínez
parent
fc1955b554
commit
8b7e3b4213
@@ -4,21 +4,20 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Variable quantity in contract recurrent invoicing',
|
||||
'version': '12.0.3.0.0',
|
||||
'category': 'Contract Management',
|
||||
'license': 'AGPL-3',
|
||||
'author': "Tecnativa,"
|
||||
"Odoo Community Association (OCA)",
|
||||
'website': 'https://www.tecnativa.com',
|
||||
'depends': ['contract'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/abstract_contract_line.xml',
|
||||
'views/contract_line_formula.xml',
|
||||
'views/contract_line_views.xml',
|
||||
'views/contract_template.xml',
|
||||
'views/contract.xml',
|
||||
"name": "Variable quantity in contract recurrent invoicing",
|
||||
"version": "12.0.3.0.0",
|
||||
"category": "Contract Management",
|
||||
"license": "AGPL-3",
|
||||
"author": "Tecnativa," "Odoo Community Association (OCA)",
|
||||
"website": "https://www.tecnativa.com",
|
||||
"depends": ["contract"],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"views/abstract_contract_line.xml",
|
||||
"views/contract_line_formula.xml",
|
||||
"views/contract_line_views.xml",
|
||||
"views/contract_template.xml",
|
||||
"views/contract.xml",
|
||||
],
|
||||
'installable': True,
|
||||
"installable": True,
|
||||
}
|
||||
|
||||
@@ -10,23 +10,41 @@ _logger = logging.getLogger(__name__)
|
||||
|
||||
def migrate(cr, version):
|
||||
xmlids_to_rename = [
|
||||
('contract_sale.account_analytic_account_own_salesman',
|
||||
'contract_sale.contract_contract_own_salesman'),
|
||||
('contract_sale.account_analytic_account_see_all',
|
||||
'contract_sale.contract_contract_see_all'),
|
||||
('contract_sale.account_analytic_contract_salesman',
|
||||
'contract_sale.contract_template_salesman'),
|
||||
('contract_sale.account_analytic_contract_sale_manager',
|
||||
'contract_sale.contract_template_sale_manager'),
|
||||
('contract_sale.account_analytic_invoice_line_saleman',
|
||||
'contract_sale.contract_line_saleman'),
|
||||
('contract_sale.account_analytic_invoice_line_manager',
|
||||
'contract_sale.contract_line_manager'),
|
||||
('contract_sale.account_analytic_contract_line_salesman',
|
||||
'contract_sale.contract_template_line_salesman'),
|
||||
('contract_sale.account_analytic_contract_line_manager',
|
||||
'contract_sale.contract_template_line_manager'),
|
||||
('contract_sale.account_analytic_account_contract_salesman',
|
||||
'contract_sale.contract_contract_salesman'),
|
||||
(
|
||||
"contract_sale.account_analytic_account_own_salesman",
|
||||
"contract_sale.contract_contract_own_salesman",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_account_see_all",
|
||||
"contract_sale.contract_contract_see_all",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_contract_salesman",
|
||||
"contract_sale.contract_template_salesman",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_contract_sale_manager",
|
||||
"contract_sale.contract_template_sale_manager",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_invoice_line_saleman",
|
||||
"contract_sale.contract_line_saleman",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_invoice_line_manager",
|
||||
"contract_sale.contract_line_manager",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_contract_line_salesman",
|
||||
"contract_sale.contract_template_line_salesman",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_contract_line_manager",
|
||||
"contract_sale.contract_template_line_manager",
|
||||
),
|
||||
(
|
||||
"contract_sale.account_analytic_account_contract_salesman",
|
||||
"contract_sale.contract_contract_salesman",
|
||||
),
|
||||
]
|
||||
openupgrade.rename_xmlids(cr, xmlids_to_rename)
|
||||
|
||||
@@ -7,15 +7,12 @@ from odoo import fields, models
|
||||
|
||||
|
||||
class ContractAbstractContractLine(models.AbstractModel):
|
||||
_inherit = 'contract.abstract.contract.line'
|
||||
_inherit = "contract.abstract.contract.line"
|
||||
|
||||
qty_type = fields.Selection(
|
||||
selection=[
|
||||
('fixed', 'Fixed quantity'),
|
||||
('variable', 'Variable quantity'),
|
||||
],
|
||||
selection=[("fixed", "Fixed quantity"), ("variable", "Variable quantity")],
|
||||
required=True,
|
||||
default='fixed',
|
||||
default="fixed",
|
||||
string="Qty. type",
|
||||
)
|
||||
qty_formula_id = fields.Many2one(
|
||||
|
||||
@@ -10,6 +10,6 @@ class ContractContract(models.Model):
|
||||
_inherit = "contract.contract"
|
||||
|
||||
skip_zero_qty = fields.Boolean(
|
||||
string='Skip Zero Qty Lines',
|
||||
string="Skip Zero Qty Lines",
|
||||
help="If checked, contract lines with 0 qty don't create invoice line",
|
||||
)
|
||||
|
||||
@@ -9,30 +9,28 @@ from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
|
||||
class AccountAnalyticInvoiceLine(models.Model):
|
||||
_inherit = 'contract.line'
|
||||
_inherit = "contract.line"
|
||||
|
||||
@api.multi
|
||||
def _get_quantity_to_invoice(
|
||||
self, period_first_date, period_last_date, invoice_date
|
||||
):
|
||||
quantity = super(
|
||||
AccountAnalyticInvoiceLine, self
|
||||
)._get_quantity_to_invoice(
|
||||
quantity = super(AccountAnalyticInvoiceLine, self)._get_quantity_to_invoice(
|
||||
period_first_date, period_last_date, invoice_date
|
||||
)
|
||||
if not period_first_date or not period_last_date or not invoice_date:
|
||||
return quantity
|
||||
if self.qty_type == 'variable':
|
||||
if self.qty_type == "variable":
|
||||
eval_context = {
|
||||
'env': self.env,
|
||||
'context': self.env.context,
|
||||
'user': self.env.user,
|
||||
'line': self,
|
||||
'quantity': quantity,
|
||||
'period_first_date': period_first_date,
|
||||
'period_last_date': period_last_date,
|
||||
'invoice_date': invoice_date,
|
||||
'contract': self.contract_id,
|
||||
"env": self.env,
|
||||
"context": self.env.context,
|
||||
"user": self.env.user,
|
||||
"line": self,
|
||||
"quantity": quantity,
|
||||
"period_first_date": period_first_date,
|
||||
"period_last_date": period_last_date,
|
||||
"invoice_date": invoice_date,
|
||||
"contract": self.contract_id,
|
||||
}
|
||||
safe_eval(
|
||||
self.qty_formula_id.code.strip(),
|
||||
@@ -40,7 +38,7 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
mode="exec",
|
||||
nocopy=True,
|
||||
) # nocopy for returning result
|
||||
quantity = eval_context.get('result', 0)
|
||||
quantity = eval_context.get("result", 0)
|
||||
return quantity
|
||||
|
||||
@api.multi
|
||||
@@ -49,13 +47,11 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
invoice_id=invoice_id, invoice_values=invoice_values,
|
||||
)
|
||||
if (
|
||||
'quantity' in vals
|
||||
"quantity" in vals
|
||||
and self.contract_id.skip_zero_qty
|
||||
and float_is_zero(
|
||||
vals['quantity'],
|
||||
self.env['decimal.precision'].precision_get(
|
||||
'Product Unit of Measure'
|
||||
),
|
||||
vals["quantity"],
|
||||
self.env["decimal.precision"].precision_get("Product Unit of Measure"),
|
||||
)
|
||||
):
|
||||
vals = {}
|
||||
|
||||
@@ -3,38 +3,36 @@
|
||||
# Copyright 2018 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, api, fields, models, exceptions
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
|
||||
class ContractLineFormula(models.Model):
|
||||
_name = 'contract.line.qty.formula'
|
||||
_description = 'Contract Line Formula'
|
||||
_name = "contract.line.qty.formula"
|
||||
_description = "Contract Line Formula"
|
||||
|
||||
name = fields.Char(required=True, translate=True)
|
||||
code = fields.Text(required=True, default="result = 0")
|
||||
|
||||
@api.constrains('code')
|
||||
@api.constrains("code")
|
||||
def _check_code(self):
|
||||
eval_context = {
|
||||
'env': self.env,
|
||||
'context': self.env.context,
|
||||
'user': self.env.user,
|
||||
'line': self.env['contract.line'],
|
||||
'contract': self.env['contract.contract'],
|
||||
'invoice': self.env['account.invoice'],
|
||||
'quantity': 0,
|
||||
'period_first_date': False,
|
||||
'period_last_date': False,
|
||||
'invoice_date': False,
|
||||
"env": self.env,
|
||||
"context": self.env.context,
|
||||
"user": self.env.user,
|
||||
"line": self.env["contract.line"],
|
||||
"contract": self.env["contract.contract"],
|
||||
"invoice": self.env["account.invoice"],
|
||||
"quantity": 0,
|
||||
"period_first_date": False,
|
||||
"period_last_date": False,
|
||||
"invoice_date": False,
|
||||
}
|
||||
try:
|
||||
safe_eval(
|
||||
self.code.strip(), eval_context, mode="exec", nocopy=True
|
||||
)
|
||||
safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True)
|
||||
except Exception as e:
|
||||
raise exceptions.ValidationError(
|
||||
_('Error evaluating code.\nDetails: %s') % e
|
||||
_("Error evaluating code.\nDetails: %s") % e
|
||||
)
|
||||
if 'result' not in eval_context:
|
||||
raise exceptions.ValidationError(_('No valid result returned.'))
|
||||
if "result" not in eval_context:
|
||||
raise exceptions.ValidationError(_("No valid result returned."))
|
||||
|
||||
@@ -12,48 +12,46 @@ from odoo import exceptions
|
||||
class TestContractVariableQuantity(odoo.tests.HttpCase):
|
||||
def setUp(self):
|
||||
super(TestContractVariableQuantity, self).setUp()
|
||||
self.partner = self.env['res.partner'].create({'name': 'Test partner'})
|
||||
self.product = self.env['product.product'].create(
|
||||
{'name': 'Test product'}
|
||||
)
|
||||
self.contract = self.env['contract.contract'].create(
|
||||
self.partner = self.env["res.partner"].create({"name": "Test partner"})
|
||||
self.product = self.env["product.product"].create({"name": "Test product"})
|
||||
self.contract = self.env["contract.contract"].create(
|
||||
{
|
||||
'name': 'Test Contract',
|
||||
'partner_id': self.partner.id,
|
||||
'pricelist_id': self.partner.property_product_pricelist.id,
|
||||
"name": "Test Contract",
|
||||
"partner_id": self.partner.id,
|
||||
"pricelist_id": self.partner.property_product_pricelist.id,
|
||||
}
|
||||
)
|
||||
self.formula = self.env['contract.line.qty.formula'].create(
|
||||
self.formula = self.env["contract.line.qty.formula"].create(
|
||||
{
|
||||
'name': 'Test formula',
|
||||
"name": "Test formula",
|
||||
# For testing each of the possible variables
|
||||
'code': 'env["res.users"]\n'
|
||||
"code": 'env["res.users"]\n'
|
||||
'context.get("lang")\n'
|
||||
'user.id\n'
|
||||
'line.qty_type\n'
|
||||
'contract.id\n'
|
||||
'quantity\n'
|
||||
'period_first_date\n'
|
||||
'period_last_date\n'
|
||||
'invoice_date\n'
|
||||
'result = 12',
|
||||
"user.id\n"
|
||||
"line.qty_type\n"
|
||||
"contract.id\n"
|
||||
"quantity\n"
|
||||
"period_first_date\n"
|
||||
"period_last_date\n"
|
||||
"invoice_date\n"
|
||||
"result = 12",
|
||||
}
|
||||
)
|
||||
self.contract_line = self.env['contract.line'].create(
|
||||
self.contract_line = self.env["contract.line"].create(
|
||||
{
|
||||
'contract_id': self.contract.id,
|
||||
'product_id': self.product.id,
|
||||
'name': 'Test',
|
||||
'qty_type': 'variable',
|
||||
'qty_formula_id': self.formula.id,
|
||||
'quantity': 1,
|
||||
'uom_id': self.product.uom_id.id,
|
||||
'price_unit': 100,
|
||||
'discount': 50,
|
||||
'recurring_rule_type': 'monthly',
|
||||
'recurring_interval': 1,
|
||||
'date_start': '2016-02-15',
|
||||
'recurring_next_date': '2016-02-29',
|
||||
"contract_id": self.contract.id,
|
||||
"product_id": self.product.id,
|
||||
"name": "Test",
|
||||
"qty_type": "variable",
|
||||
"qty_formula_id": self.formula.id,
|
||||
"quantity": 1,
|
||||
"uom_id": self.product.uom_id.id,
|
||||
"price_unit": 100,
|
||||
"discount": 50,
|
||||
"recurring_rule_type": "monthly",
|
||||
"recurring_interval": 1,
|
||||
"date_start": "2016-02-15",
|
||||
"recurring_next_date": "2016-02-29",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -71,7 +69,7 @@ class TestContractVariableQuantity(odoo.tests.HttpCase):
|
||||
self.assertEqual(invoice.invoice_line_ids[0].quantity, 12)
|
||||
|
||||
def test_check_skip_zero_qty(self):
|
||||
self.formula.code = 'result=0'
|
||||
self.formula.code = "result=0"
|
||||
self.contract.skip_zero_qty = True
|
||||
invoice = self.contract.recurring_create_invoice()
|
||||
self.assertFalse(invoice.invoice_line_ids)
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record id="contract_abstract_contract_line_form_view"
|
||||
model="ir.ui.view">
|
||||
<record id="contract_abstract_contract_line_form_view" model="ir.ui.view">
|
||||
<field name="name">Abstract Contract Line Form View</field>
|
||||
<field name="model">contract.abstract.contract.line</field>
|
||||
<field name="inherit_id" ref="contract.contract_abstract_contract_line_form_view"/>
|
||||
<field
|
||||
name="inherit_id"
|
||||
ref="contract.contract_abstract_contract_line_form_view"
|
||||
/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//label[@for='quantity']" position="before">
|
||||
<field name="qty_type"/>
|
||||
<field name="qty_type" />
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='quantity']" position="after">
|
||||
<field name="qty_formula_id"
|
||||
<field
|
||||
name="qty_formula_id"
|
||||
attrs="{'required': [('qty_type', '=', 'variable')], 'invisible': [('qty_type', '!=', 'variable')]}"
|
||||
/>
|
||||
</xpath>
|
||||
@@ -22,5 +24,4 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record id="contract_contract_form_view" model="ir.ui.view">
|
||||
<field name="model">contract.contract</field>
|
||||
<field name="inherit_id" ref="contract.contract_contract_form_view"/>
|
||||
<field name="inherit_id" ref="contract.contract_contract_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='code']" position="after">
|
||||
<field name="skip_zero_qty"/>
|
||||
<field name="skip_zero_qty" />
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='contract_line_ids']/tree/field[@name='quantity']" position="before">
|
||||
<field name="qty_type"/>
|
||||
<xpath
|
||||
expr="//field[@name='contract_line_ids']/tree/field[@name='quantity']"
|
||||
position="before"
|
||||
>
|
||||
<field name="qty_type" />
|
||||
<field
|
||||
name="qty_formula_id"
|
||||
attrs="{'invisible': [('qty_type', '!=', 'variable')]}"
|
||||
/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='contract_line_ids']/tree/field[@name='quantity']" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('qty_type', '!=', 'fixed')]}</attribute>
|
||||
<xpath
|
||||
expr="//field[@name='contract_line_ids']/tree/field[@name='quantity']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'invisible': [('qty_type', '!=', 'fixed')]}</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_contract_line_qty_formula_tree" model="ir.ui.view">
|
||||
<field name="model">contract.line.qty.formula</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="name" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_contract_line_qty_formula_form" model="ir.ui.view">
|
||||
<field name="model">contract.line.qty.formula</field>
|
||||
<field name="arch" type="xml">
|
||||
@@ -17,13 +15,17 @@
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="name" placeholder="Name"/>
|
||||
<field name="name" placeholder="Name" />
|
||||
</h1>
|
||||
</div>
|
||||
<group string="Code">
|
||||
<div style="margin-top: 4px;">
|
||||
<field name="code" nolabel="1" widget="ace"
|
||||
options="{'mode': 'python'}"/>
|
||||
<field
|
||||
name="code"
|
||||
nolabel="1"
|
||||
widget="ace"
|
||||
options="{'mode': 'python'}"
|
||||
/>
|
||||
<h3>Help with Python expressions.</h3>
|
||||
<p>You have to insert valid Python code block that
|
||||
stores at some moment a float/integer value of
|
||||
@@ -65,9 +67,7 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_contract_quantity_formula"
|
||||
model="ir.actions.act_window">
|
||||
<record id="action_contract_quantity_formula" model="ir.actions.act_window">
|
||||
<field name="name">Formulas (quantity)</field>
|
||||
<field name="res_model">contract.line.qty.formula</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -78,10 +78,9 @@
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_contract_quantity_formula"
|
||||
<menuitem
|
||||
id="menu_contract_quantity_formula"
|
||||
action="action_contract_quantity_formula"
|
||||
parent="contract.menu_config_contract"
|
||||
/>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2019 Tecnativa - Pedro M. Baeza
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record id="contract_line_tree_view" model="ir.ui.view">
|
||||
<field name="name">contract.line tree view (in contract) - Add variable qty fields</field>
|
||||
<field
|
||||
name="name"
|
||||
>contract.line tree view (in contract) - Add variable qty fields</field>
|
||||
<field name="model">contract.line</field>
|
||||
<field name="inherit_id" ref="contract.contract_line_tree_view"/>
|
||||
<field name="inherit_id" ref="contract.contract_line_tree_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="quantity" position="before">
|
||||
<field name="qty_type"/>
|
||||
<field name="qty_type" />
|
||||
<field
|
||||
name="qty_formula_id"
|
||||
attrs="{'invisible': [('qty_type', '!=', 'variable')]}"
|
||||
/>
|
||||
</field>
|
||||
<field name="quantity" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('qty_type', '!=', 'fixed')]}</attribute>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'invisible': [('qty_type', '!=', 'fixed')]}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record id="contract_template_form_view" model="ir.ui.view">
|
||||
<field name="name">Contract Template Variable Qty</field>
|
||||
<field name="model">contract.template</field>
|
||||
<field name="inherit_id" ref="contract.contract_template_form_view"/>
|
||||
<field name="inherit_id" ref="contract.contract_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='contract_line_ids']//field[@name='quantity']" position="before">
|
||||
<field name="qty_type"/>
|
||||
<xpath
|
||||
expr="//field[@name='contract_line_ids']//field[@name='quantity']"
|
||||
position="before"
|
||||
>
|
||||
<field name="qty_type" />
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='contract_line_ids']//field[@name='quantity']" position="after">
|
||||
<field name="qty_formula_id"
|
||||
<xpath
|
||||
expr="//field[@name='contract_line_ids']//field[@name='quantity']"
|
||||
position="after"
|
||||
>
|
||||
<field
|
||||
name="qty_formula_id"
|
||||
attrs="{'required': [('qty_type', '=', 'variable')], 'invisible': [('qty_type', '!=', 'variable')]}"
|
||||
/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='contract_line_ids']//field[@name='quantity']" position="attributes">
|
||||
<attribute name="attrs">{'required': [('qty_type', '=', 'fixed')], 'invisible': [('qty_type', '!=', 'fixed')]}</attribute>
|
||||
<xpath
|
||||
expr="//field[@name='contract_line_ids']//field[@name='quantity']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'required': [('qty_type', '=', 'fixed')], 'invisible': [('qty_type', '!=', 'fixed')]}</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user