Browse Source

Jun 13: [FIX] Bug Fixed 'all_in_one_dynamic_custom_fields'

pull/254/merge
RisvanaCybro 11 months ago
parent
commit
f70833fe47
  1. 4
      all_in_one_dynamic_custom_fields/README.rst
  2. 19
      all_in_one_dynamic_custom_fields/__init__.py
  3. 32
      all_in_one_dynamic_custom_fields/__manifest__.py
  4. 16
      all_in_one_dynamic_custom_fields/data/widget_data.xml
  5. 4
      all_in_one_dynamic_custom_fields/doc/RELEASE_NOTES.md
  6. 21
      all_in_one_dynamic_custom_fields/models/__init__.py
  7. 37
      all_in_one_dynamic_custom_fields/models/dynamic_field_widgets.py
  8. 221
      all_in_one_dynamic_custom_fields/models/dynamic_fields.py
  9. 37
      all_in_one_dynamic_custom_fields/models/field_widgets.py
  10. 23
      all_in_one_dynamic_custom_fields/models/ir_model_fields.py
  11. 3
      all_in_one_dynamic_custom_fields/security/ir.model.access.csv
  12. 8
      all_in_one_dynamic_custom_fields/security/security.xml
  13. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/1.png
  14. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/10.png
  15. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/2.png
  16. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/3.png
  17. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/4.png
  18. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/5.png
  19. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/7.png
  20. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/8.png
  21. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/9.png
  22. 20
      all_in_one_dynamic_custom_fields/static/description/index.html
  23. 108
      all_in_one_dynamic_custom_fields/views/dynamic_fields.xml
  24. 117
      all_in_one_dynamic_custom_fields/views/dynamic_fields_views.xml

4
all_in_one_dynamic_custom_fields/README.rst

@ -1,4 +1,4 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
@ -40,4 +40,4 @@ For support and more information, please visit `Our Website <https://cybrosys.co
Further information
===================
HTML Description: `<static/description/index.html>`__
HTML Description: `<static/description/index.html>`__

19
all_in_one_dynamic_custom_fields/__init__.py

@ -1,23 +1,22 @@
# -*- coding: utf-8 -*-
###################################################################################
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###################################################################################
################################################################################
from . import models

32
all_in_one_dynamic_custom_fields/__manifest__.py

@ -1,44 +1,46 @@
# -*- coding: utf-8 -*-
###################################################################################
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###################################################################################
################################################################################
{
'name': 'All in One Dynamic Fields',
'version': '15.0.1.1.5',
'summary': 'Create Custom Fields As Per Your Need Without Any Coding.',
'description': 'All in One Dynamic Fields, All in One Custom Fields, Dynamic Fields, Custom Fields, Create Fields Dynamically',
'version': '15.0.1.2.6',
'category': 'Extra Tools',
'summary': 'Create Custom Fields As Per Your Need Without Any Coding.',
'description': "The features of module facilitates the addition of fields"
"to any view within a model, allowing users to specify"
"attributes and properties at their preferred "
"location.",
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': "https://www.cybrosys.com",
'license': 'AGPL-3',
'depends': ['base'],
'data': [
'data/widget_data.xml',
'security/security.xml',
'security/ir.model.access.csv',
'views/dynamic_fields.xml',
'views/dynamic_fields_views.xml',
],
'images': ['static/description/banner.png'],
'license': 'AGPL-3',
'installable': True,
'auto_install': False,
'application': False,

16
all_in_one_dynamic_custom_fields/data/widget_data.xml

@ -2,37 +2,37 @@
<odoo>
<data noupdate="1">
<!-- Widget 'image' for 'binary' field -->
<record id="image_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widgets_image" model="dynamic.field.widgets">
<field name="name">image</field>
<field name="description">Image</field>
</record>
<!-- Widget 'many2many_tags' for 'many2many' field -->
<record id="many2many_tag_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widgets_many2many_tags" model="dynamic.field.widgets">
<field name="name">many2many_tags</field>
<field name="description">Many2many Tags</field>
</record>
<!-- Widget 'binary' for 'many2many' field -->
<record id="many2many_binary_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widgets_binary" model="dynamic.field.widgets">
<field name="name">binary</field>
<field name="description">Binary</field>
</record>
<!-- Widget 'radio' for 'selection' field -->
<record id="radio_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widgets_radio" model="dynamic.field.widgets">
<field name="name">radio</field>
<field name="description">Radio</field>
</record>
<!-- Widget 'priority' for 'selection' field -->
<record id="priority_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widgets_priority" model="dynamic.field.widgets">
<field name="name">priority</field>
<field name="description">Priority</field>
</record>
<!-- Widget 'monetory' for 'float' field -->
<record id="monetory_widget" model="dynamic.field.widgets">
<!-- Widget 'monetary' for 'float' field -->
<record id="dynamic_field_widgets_monetary" model="dynamic.field.widgets">
<field name="name">monetary</field>
<field name="description">Monetary</field>
</record>
<!-- Widget 'selection' for 'Many2one' field -->
<record id="selection_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widgets_selection" model="dynamic.field.widgets">
<field name="name">selection</field>
<field name="description">Selection</field>
</record>

4
all_in_one_dynamic_custom_fields/doc/RELEASE_NOTES.md

@ -5,3 +5,7 @@
##### ADD
- Initial commit for All in One Custom Dynamic Fields
#### 13.06.2024
#### Version 15.0.1.2.6
##### UPDATE
- The latest module update includes enhancements to the list view configuration. You can now add the newly created field to the selected list view at the desired position, with the option to enable or disable its visibility by default.

21
all_in_one_dynamic_custom_fields/models/__init__.py

@ -1,25 +1,24 @@
# -*- coding: utf-8 -*-
###################################################################################
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###################################################################################
################################################################################
from . import ir_model_fields
from . import field_widgets
from . import dynamic_field_widgets
from . import dynamic_fields

37
all_in_one_dynamic_custom_fields/models/dynamic_field_widgets.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from odoo import models, fields
class DynamicFieldWidgets(models.Model):
"""We can't filter a selection field dynamically so when we select a
field its widgets also need to change according to the selected field
type, we can't do it by a 'selection' field, need a 'Many2one' field.
"""
_name = 'dynamic.field.widgets'
_rec_name = 'description'
_description = 'Field Widgets'
name = fields.Char(string="Name", help="Name given to the record")
description = fields.Char(string="Description",
help="Description of the record")

221
all_in_one_dynamic_custom_fields/models/dynamic_fields.py

@ -1,30 +1,31 @@
# -*- coding: utf-8 -*-
###################################################################################
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###################################################################################
################################################################################
from xlrd.xlsx import ET
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class DynamicFields(models.Model):
"""model to create dynamic fields to selected model"""
_name = 'dynamic.fields'
_rec_name = 'field_description'
_description = 'Custom Dynamic Fields'
@ -39,49 +40,126 @@ class DynamicFields(models.Model):
field_list.remove(('reference', 'reference'))
return field_list
position_field = fields.Many2one('ir.model.fields', string='Field Name',
required=True,
ondelete='cascade')
position_field_id = fields.Many2one('ir.model.fields',
string='Field Name',
help='Field name',
required=True,
ondelete='cascade')
position = fields.Selection([('before', 'Before'),
('after', 'After')], string='Position',
help='Position of new field to selected field',
required=True)
model_id = fields.Many2one('ir.model', string='Model', required=True,
model_id = fields.Many2one('ir.model', string='Model',
required=True,
index=True, ondelete='cascade',
help="The model this field belongs to")
ref_model_id = fields.Many2one('ir.model', string='Model', index=True)
selection_field = fields.Char(string="Selection Options")
rel_field = fields.Many2one('ir.model.fields', string='Related Field')
ref_model_id = fields.Many2one('ir.model', string='Model',
index=True, help='Reference model')
selection_field = fields.Char(string="Selection Options",
help='Selection values given to the newly '
'created field')
rel_field_id = fields.Many2one('ir.model.fields',
string='Related Field', help='Related field')
field_type = fields.Selection(selection='get_possible_field_types',
string='Field Type', required=True)
ttype = fields.Selection(string="Field Type", related='field_type')
widget = fields.Many2one('dynamic.field.widgets', string='Widget')
groups = fields.Many2many('res.groups', 'employee_dynamic_fields_group_rel',
'field_id', 'group_id')
extra_features = fields.Boolean(string="Show Extra Properties")
string='Field Type',
required=True, help='Field type of the '
'newly created field')
ttype = fields.Selection(string="Field Type", related='field_type',
help='field type')
widget_id = fields.Many2one('dynamic.field.widgets',
string='Widget',
help='widget given to the newly '
'creating field')
groups = fields.Many2many('res.groups',
'employee_dynamic_fields_group_rel',
'field_id', 'group_id',
string='Groups', help="Groups")
is_extra_features = fields.Boolean(string="Show Extra Properties",
help='Enable to give extra features to '
'the newly creating field')
status = fields.Selection([
('draft', 'Draft'),
('form', 'Field Created'),
('tree', 'Added in Tree View'),
], string='Status', index=True, readonly=True, tracking=True,
copy=False, default='draft',
required=True, help='Record Status')
help='Record Status')
form_view_id = fields.Many2one('ir.ui.view', string="Form View ID",
form_view_id = fields.Many2one('ir.ui.view',
string="Form View ID",
help='Form view id of selected model',
required=True)
form_view_inherit_id = fields.Char(string="Form View Inherit Id",
help='External id of selected form view',
related='form_view_id.xml_id')
add_field_in_tree = fields.Boolean(string="Add Field to the Tree View",
default=False)
tree_view_id = fields.Many2one('ir.ui.view', string="Tree View ID")
is_add_field_in_tree = fields.Boolean(string="Add Field to the Tree View",
help='Enable to add field in tree '
'view')
tree_view_id = fields.Many2one('ir.ui.view',
string="Tree View ID",
help='select a tree view id')
tree_view_inherit_id = fields.Char(string="Tree View Inherit Id",
help='External id of selected tree view',
related='tree_view_id.xml_id')
created_form_view_id = fields.Many2one('ir.ui.view',
help='Created from view id',
string='Created Form View')
created_tree_view_id = fields.Many2one('ir.ui.view',
help='Created tree view id',
string='Created Tree View')
tree_field_id = fields.Many2one('ir.model.fields',
sting='Tree Field',
domain="[('id', 'in', "
"tree_field_ids)]",
help='Tree view fields of selected tree '
'view')
tree_field_position = fields.Selection([('before', 'Before'),
('after', 'After')],
string='Tree Field Position',
help='Position of new field to '
'selected field in tree view')
is_field_in_tree = fields.Boolean(string='Field Visible In Tree View',
help='Enable this to enable the toggle '
'view of this field in tree view')
tree_field_ids = fields.Many2many('ir.model.fields',
string='Tree View Fields',
compute='_compute_tree_field_ids',
help='Domain field for tree view fields')
def create_dynamic_fields(self):
@api.depends('tree_view_id')
def _compute_tree_field_ids(self):
"""Compute function to find the tree view fields of selected tree view
in field tree_view_id"""
for rec in self:
if rec.tree_view_id:
field_list = []
if rec.tree_view_id.xml_id:
tree_fields = ET.fromstring(self.env.ref(
rec.tree_view_id.xml_id).arch).findall(".//field")
for field in tree_fields:
field_list.append(field.get('name'))
inherit_id = rec.tree_view_id.inherit_id \
if rec.tree_view_id.inherit_id else False
while inherit_id:
if inherit_id.xml_id:
tree_fields = ET.fromstring(self.env.ref(
inherit_id.xml_id).arch).findall(".//field")
for field in tree_fields:
field_list.append(field.get('name'))
inherit_id = inherit_id.inherit_id \
if inherit_id.inherit_id else False
self.tree_field_ids = self.env['ir.model.fields'].search(
[('model_id', '=', self.model_id.id),
('name', 'in', field_list)])
else:
rec.tree_field_ids = False
def action_create_dynamic_fields(self):
"""Function creates field with given properties to the selected model"""
self.write({'status': 'form'})
if self.field_type == 'monetary' and not self.env[
'ir.model.fields'].sudo().search([
('model', '=', self.model_id.id),
('name', '=', 'currency_id')]):
'ir.model.fields'].sudo().search([('model', '=', self.model_id.id),
('name', '=', 'currency_id')]):
self.env['ir.model.fields'].sudo().create({
'name': 'x_currency_id',
'field_description': 'Currency',
@ -115,18 +193,18 @@ class DynamicFields(models.Model):
'<field name="%s" position="%s">'
'<field name="%s"/>'
'</field>'
'</data>') % (self.position_field.name,
'</data>') % (self.position_field_id.name,
self.position, self.name)
if self.widget:
if self.widget_id:
arch_base = _('<?xml version="1.0"?>'
'<data>'
'<field name="%s" position="%s">'
'<field name="%s" widget="%s"/>'
'</field>'
'</data>') % (self.position_field.name,
'</data>') % (self.position_field_id.name,
self.position, self.name,
self.widget.name)
self.form_view_id = self.env['ir.ui.view'].sudo().create({
self.widget_id.name)
self.created_form_view_id = self.env['ir.ui.view'].sudo().create({
'name': inherit_form_view_name,
'type': 'form',
'model': self.model_id.model,
@ -140,27 +218,30 @@ class DynamicFields(models.Model):
'tag': 'reload',
}
def add_field_to_tree_view(self):
if self.add_field_in_tree:
if self.add_field_in_tree:
def action_add_field_to_tree_view(self):
"""Function adds created field to the tree view"""
if self.is_add_field_in_tree:
if self.is_add_field_in_tree:
inherit_tree_view_name = str(
self.tree_view_id.name) + ".inherit.dynamic.custom" + \
str(self.field_description) + ".field"
tree_view_arch_base = _(
'<?xml version="1.0"?>'
'<data>'
'''<xpath expr="//tree" position="inside">'''
'''<field name="%s" optional="show"/>'''
'''</xpath>'''
'''</data>''') % self.name
self.tree_view_id = self.env['ir.ui.view'].sudo().create({
optional = "show" if self.is_field_in_tree else "hide"
tree_view_arch_base = (_(f'''
<data>
<xpath expr="//field[@name='{self.tree_field_id.name}']" position="{self.tree_field_position}">
<field name="{self.name}" optional="{optional}"/>
</xpath>
</data>'''))
self.created_tree_view_id = self.env['ir.ui.view'].sudo(
).create({
'name': inherit_tree_view_name,
'type': 'tree',
'model': self.model_id.model,
'mode': 'extension',
'inherit_id': self.tree_view_id.id,
'arch_base': tree_view_arch_base,
'active': True})
'active': True
})
self.write({'status': 'tree'})
return {
'type': 'ir.actions.client',
@ -168,52 +249,54 @@ class DynamicFields(models.Model):
}
else:
raise ValidationError(
_('Error! Please select the boolean field Add Field to the Tree View.'))
_('Error! Please select the boolean field Add Field to the '
'Tree View.'))
@api.depends('model_id','add_field_in_tree')
@api.onchange('model_id','add_field_in_tree')
@api.onchange('model_id', 'is_add_field_in_tree')
def set_domain(self):
"""Return the fields that currently present in the form"""
form_view_ids = self.model_id.view_ids.filtered(
lambda l: l.type == 'form' and l.mode == 'primary')
lambda x: x.type == 'form' and x.mode == 'primary')
tree_view_ids = self.model_id.view_ids.filtered(
lambda l: l.type == 'tree' and l.mode == 'primary')
fields = self.env['ir.model.fields'].sudo().search([
lambda x: x.type == 'tree' and x.mode == 'primary')
model_fields = self.env['ir.model.fields'].sudo().search([
('model', '=', self.model_id.model)])
field_list = []
for rec in fields:
for rec in model_fields:
for field in rec:
field_list.append(field.id)
return {'domain': {
'form_view_id': [('id', 'in', form_view_ids.ids)],
'tree_view_id': [('id', 'in', tree_view_ids.ids)],
'position_field': [('id', 'in', field_list)]
'position_field_id': [('id', 'in', field_list)]
}}
@api.depends('field_type')
@api.onchange('field_type')
def onchange_field_type(self):
"""Onchange function of field_type which return domain to widget_id"""
if self.field_type:
if self.field_type == 'binary':
return {'domain': {'widget': [('name', '=', 'image')]}}
return {'domain': {'widget_id': [('name', '=', 'image')]}}
elif self.field_type == 'many2many':
return {'domain': {'widget': [
return {'domain': {'widget_id': [
('name', 'in', ['many2many_tags', 'binary'])]}}
elif self.field_type == 'selection':
return {'domain': {
'widget': [('name', 'in', ['radio', 'priority'])]}}
'widget_id': [('name', 'in', ['radio', 'priority'])]}}
elif self.field_type == 'float':
return {'domain': {'widget': [('name', '=', 'monetary')]}}
return {'domain': {'widget_id': [('name', '=', 'monetary')]}}
elif self.field_type == 'many2one':
return {'domain': {'widget': [('name', '=', 'selection')]}}
return {'domain': {'widget_id': [('name', '=', 'selection')]}}
else:
return {'domain': {'widget': [('id', '=', False)]}}
return {'domain': {'widget': [('id', '=', False)]}}
return {'domain': {'widget_id': [('id', '=', False)]}}
return {'domain': {'widget_id': [('id', '=', False)]}}
def unlink(self):
if self.form_view_id:
self.form_view_id.active = False
if self.tree_view_id:
self.tree_view_id.active = False
"""unlink function override to make the created form and tree view
active false"""
if self.created_form_view_id:
self.created_form_view_id.active = False
if self.created_tree_view_id:
self.created_tree_view_id.active = False
res = super(DynamicFields, self).unlink()
return res

37
all_in_one_dynamic_custom_fields/models/field_widgets.py

@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
###################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
###################################################################################
from odoo import models, fields
class FieldWidgets(models.Model):
"""We can't filter a selection field dynamically
so when we select a field its widgets also need to change according to the selected
field type, we can't do it by a 'selection' field, need a 'Many2one' field.
"""
_name = 'dynamic.field.widgets'
_rec_name = 'description'
_description = 'Field Widgets'
name = fields.Char(string="Name")
description = fields.Char(string="Description")

23
all_in_one_dynamic_custom_fields/models/ir_model_fields.py

@ -1,25 +1,24 @@
# -*- coding: utf-8 -*-
###################################################################################
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###################################################################################
################################################################################
from odoo import models, fields
@ -28,4 +27,6 @@ class IrModelFields(models.Model):
_inherit = 'ir.model.fields'
is_dynamic_field = fields.Boolean(string="Dynamic Field")
is_dynamic_field = fields.Boolean(string="Dynamic Field",
help='weather the field is a '
'dynamically created field')

3
all_in_one_dynamic_custom_fields/security/ir.model.access.csv

@ -1,5 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_all_in_one_dynamic_custom_fields_administrator,dynamic.fields,model_dynamic_fields,all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_administrator,1,1,1,1
access_all_in_one_dynamic_custom_fields_user,dynamic.fields,model_dynamic_fields,all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_user,1,0,0,0
access_dynamic_field_widgets,"dynamic.field.widgets","model_dynamic_field_widgets",,1,1,1,1
access_dynamic_field_widgets,dynamic.field.widgets,model_dynamic_field_widgets,all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_user,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_all_in_one_dynamic_custom_fields_administrator dynamic.fields model_dynamic_fields all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_administrator 1 1 1 1
3 access_all_in_one_dynamic_custom_fields_user dynamic.fields model_dynamic_fields all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_user 1 0 0 0
4 access_dynamic_field_widgets dynamic.field.widgets model_dynamic_field_widgets all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_user 1 1 1 1

8
all_in_one_dynamic_custom_fields/security/security.xml

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<!-- All in one dynamic custom fields module category-->
<record id="module_category_all_in_one_dynamic_custom_fields"
model="ir.module.category">
<field name="name">All in One Custom Dynamic Fields</field>
<field name="description">Helps you handle your All-in-One Custom Dynamic Fields Permissions </field>
<field name="sequence">5</field>
</record>
<!-- All in one dynamic custom fields user group-->
<record id="group_all_in_one_dynamic_custom_fields_user"
model="res.groups">
<field name="name">User</field>
<field name="category_id"
ref="all_in_one_dynamic_custom_fields.module_category_all_in_one_dynamic_custom_fields"/>
</record>
<!-- All in one dynamic custom fields Administrator group-->
<record id="group_all_in_one_dynamic_custom_fields_administrator"
model="res.groups">
<field name="name">Administrator</field>
@ -26,7 +26,5 @@
<field name="users"
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
</record>
</data>
</odoo>

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

BIN
all_in_one_dynamic_custom_fields/static/description/assets/screenshots/9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

20
all_in_one_dynamic_custom_fields/static/description/index.html

@ -265,9 +265,9 @@
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Select the model for which you want to create a custom field.
</p>
<img src="assets/screenshots/dynamic4.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/1.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<img src="assets/screenshots/dynamic5.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/2.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
</div>
@ -279,7 +279,7 @@
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
Choose the field type
</p>
<img src="assets/screenshots/dynamic6.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/3.png" class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
</div>
@ -292,11 +292,11 @@
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
The custom field also we can add to the module List/Tree view.
</p>
<img src="assets/screenshots/dynamic7.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/4.png" class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
<img src="assets/screenshots/dynamic8.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/5.png" class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
<img src="assets/screenshots/dynamic9.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/6.png" class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
</div>
@ -309,9 +309,9 @@
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
A new custom field is created in the sale order form view.
</p>
<img src="assets/screenshots/dynamic3.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/7.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<img src="assets/screenshots/dynamic10.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/8.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
</div>
@ -324,9 +324,9 @@
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
A new custom field is created in the sale order tree view.
</p>
<img src="assets/screenshots/dynamic11.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/9.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
<img src="assets/screenshots/dynamic12.png" class="img-responsive img-thumbnail border" width="100%"
<img src="assets/screenshots/10.png" class="img-responsive img-thumbnail border" width="100%"
height="auto" />
</div>
</div>

108
all_in_one_dynamic_custom_fields/views/dynamic_fields.xml

@ -1,108 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="custom_dynamic_fields_view_tree" model="ir.ui.view">
<field name="name">custom_dynamic_fields_view_tree</field>
<field name="model">dynamic.fields</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="field_description"/>
<field name="model_id"/>
<field name="status"/>
</tree>
</field>
</record>
<record id='custom_dynamic_fields_view_form' model='ir.ui.view'>
<field name="name">custom_dynamic_fields_view_form</field>
<field name="model">dynamic.fields</field>
<field name="arch" type="xml">
<form>
<header>
<button name="create_dynamic_fields" string="Create Field" type="object" class="oe_highlight"
attrs="{'invisible': [('status', 'in', ['form','tree'])]}" groups="all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_administrator"/>
<button name="add_field_to_tree_view" string="Add to Tree View" type="object" class="oe_highlight"
attrs="{'invisible': [('status', 'in', ['draft','tree'])]}" groups="all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_administrator"/>
<field name="status" widget="statusbar"
statusbar_visible="draft,form,tree"/>
</header>
<sheet>
<group>
<group string="Field Info">
<field name="name"/>
<field name="field_description"/>
<field name="state" readonly="1" groups="base.group_no_one"/>
<field name="model_id" options='{"no_open": True, "no_create": True}'/>
<field name="field_type"/>
<field name="selection_field" placeholder="[('blue', 'Blue'),('yellow', 'Yellow')]"
attrs="{'required': [('field_type','in',['selection','reference'])],
'readonly': [('field_type','not in',['selection','reference'])],
'invisible': [('field_type','not in',['selection','reference'])]}"/>
<field name="ref_model_id" options='{"no_open": True, "no_create": True}' attrs="{'required': [('field_type','in',['many2one','many2many'])],
'readonly': [('field_type','not in',['many2one','many2many'])],
'invisible': [('field_type','not in',['many2one','many2many'])]}"/>
<field name="widget" widget="selection"
attrs="{'invisible': [('field_type','not in',['binary', 'many2many', 'selection', 'float', 'many2one'])]}"/>
<field name="required"/>
<field name="form_view_id"/>
<field name="form_view_inherit_id"/>
</group>
<group string="Tree View">
<field name="add_field_in_tree"/>
<field name="tree_view_id" attrs="{'invisible': [('add_field_in_tree', '=', False)],
'required': [('add_field_in_tree', '=', True)]}"/>
<field name="tree_view_inherit_id" attrs="{'invisible': [('add_field_in_tree', '=', False)]}"/>
</group>
<group string="Position">
<field name="position_field" options='{"no_open": True, "no_create": True}'/>
<field name="position"/>
</group>
</group>
<group string="Extra Properties">
<group>
<field name="extra_features"/>
</group>
<group attrs="{'invisible': [('extra_features', '=', False)]}">
<field name="help"/>
</group>
<group attrs="{'invisible': [('extra_features', '=', False)]}">
<field name="readonly"/>
<field name="store"/>
<field name="index"/>
<field name="copied"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id='action_dynamic_custom_fields' model='ir.actions.act_window'>
<field name="name">Custom Dynamic Fields</field>
<field name="res_model">dynamic.fields</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create New Custom Dynamic Field!
</p>
</field>
</record>
<menuitem id="menu_all_in_one_dynamic_custom_fields_root"
name="All in One Custom Dynamic Fields"
groups="group_all_in_one_dynamic_custom_fields_user,group_all_in_one_dynamic_custom_fields_administrator"
web_icon="all_in_one_dynamic_custom_fields,static/description/icon.png"
sequence="01"/>
<menuitem id="menu_create_custom_dynamic_fields"
name="Fields"
parent="menu_all_in_one_dynamic_custom_fields_root"
sequence="1"/>
<menuitem id="menu_create_fields"
name="Create Fields"
parent="menu_create_custom_dynamic_fields"
action="action_dynamic_custom_fields"
groups="group_all_in_one_dynamic_custom_fields_user,group_all_in_one_dynamic_custom_fields_administrator"
sequence="2"/>
</odoo>

117
all_in_one_dynamic_custom_fields/views/dynamic_fields_views.xml

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Dynamic fields view tree -->
<record id="dynamic_fields_view_tree" model="ir.ui.view">
<field name="name">dynamic.fields.view.tree</field>
<field name="model">dynamic.fields</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="field_description"/>
<field name="model_id"/>
<field name="status"/>
</tree>
</field>
</record>
<!-- Dynamic fields view form -->
<record id='dynamic_fields_view_form' model='ir.ui.view'>
<field name="name">dynamic.fields.view.form</field>
<field name="model">dynamic.fields</field>
<field name="arch" type="xml">
<form>
<header>
<button name="action_create_dynamic_fields" string="Create Field" type="object" class="oe_highlight"
attrs="{'invisible': [('status', 'in', ['form','tree'])]}" groups="all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_administrator"/>
<button name="action_add_field_to_tree_view" string="Add to Tree View" type="object" class="oe_highlight"
attrs="{'invisible': [('status', 'in', ['draft','tree'])]}" groups="all_in_one_dynamic_custom_fields.group_all_in_one_dynamic_custom_fields_administrator"/>
<field name="status" widget="statusbar"
statusbar_visible="draft,form,tree"/>
</header>
<sheet>
<group>
<group string="Field Info">
<field name="name" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="field_description" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="state" readonly="1" groups="base.group_no_one"/>
<field name="model_id" options='{"no_open": True, "no_create": True}' attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="field_type" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="selection_field" placeholder="[('blue', 'Blue'),('yellow', 'Yellow')]"
attrs="{'required': [('field_type','in',['selection','reference'])],
'readonly': ['|',('field_type','not in',['selection','reference']), ('status', '!=', 'draft')],
'invisible': [('field_type','not in',['selection','reference'])]}"/>
<field name="ref_model_id" options='{"no_open": True, "no_create": True}' attrs="{'required': [('field_type','in',['many2one','many2many'])],
'readonly': ['|', ('field_type','not in',['many2one','many2many']),('status', '!=', 'draft')],
'invisible': [('field_type','not in',['many2one','many2many'])]}"/>
<field name="widget_id" widget="selection"
attrs="{'invisible': [('field_type','not in',['binary', 'many2many', 'selection', 'float', 'many2one'])],
'readonly': [('status', '!=', 'draft')]}"/>
<field name="required" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="form_view_id" attrs="{'readonly': [('status', '!=', 'draft')]}" options='{"no_open": True, "no_create": True}'/>
<field name="form_view_inherit_id"/>
<field name="tree_field_ids" invisible="1"/>
</group>
<group string="Tree View">
<field name="is_add_field_in_tree" attrs="{'readonly': [('status', 'not in', ['draft', 'form'])]}"/>
<field name="tree_view_id" options='{"no_open": True, "no_create": True}' attrs="{'invisible': [('is_add_field_in_tree', '=', False)],
'required': [('is_add_field_in_tree', '=', True)],'readonly': [('status', 'not in', ['draft', 'form'])]}"/>
<field name="tree_view_inherit_id" attrs="{'invisible': [('is_add_field_in_tree', '=', False)],'readonly': [('status', '!=', 'draft')]}"/>
<field name="tree_field_id" options='{"no_open": True, "no_create": True}' attrs="{'invisible': [('is_add_field_in_tree', '=', False)],
'required': [('is_add_field_in_tree', '=', True)], 'readonly': [('status', 'not in', ['draft', 'form'])]}"/>
<field name="tree_field_position" attrs="{'invisible': [('is_add_field_in_tree', '=', False)],
'required': [('is_add_field_in_tree', '=', True)], 'readonly': [('status', 'not in', ['draft', 'form'])]}"/>
<field name="is_field_in_tree" attrs="{'invisible': [('is_add_field_in_tree', '=', False)],
'required': [('is_add_field_in_tree', '=', True)], 'readonly': [('status', 'not in', ['draft', 'form'])]}"/>
</group>
<group string="Position">
<field name="position_field_id" options='{"no_open": True, "no_create": True}' attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="position" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
</group>
</group>
<group string="Extra Properties">
<group>
<field name="is_extra_features" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
</group>
<group attrs="{'invisible': [('is_extra_features', '=', False)],'readonly': [('status', '!=', 'draft')]}">
<field name="help"/>
</group>
<group attrs="{'invisible': [('is_extra_features', '=', False)],'readonly': [('status', '!=', 'draft')]}">
<field name="readonly" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="store" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="index" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
<field name="copied" attrs="{'readonly': [('status', '!=', 'draft')]}"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- Dynamic fields action-->
<record id='dynamic_fields_action' model='ir.actions.act_window'>
<field name="name">Custom Dynamic Fields</field>
<field name="res_model">dynamic.fields</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create New Custom Dynamic Field!
</p>
</field>
</record>
<!-- All in One Custom Dynamic Fields root menu-->
<menuitem id="menu_all_in_one_dynamic_custom_fields_root"
name="All in One Custom Dynamic Fields"
groups="group_all_in_one_dynamic_custom_fields_user,group_all_in_one_dynamic_custom_fields_administrator"
web_icon="all_in_one_dynamic_custom_fields,static/description/icon.png"
sequence="01"/>
<!-- Create custom dynamic fields menu-->
<menuitem id="menu_create_custom_dynamic_fields"
name="Fields"
parent="menu_all_in_one_dynamic_custom_fields_root"
sequence="1"/>
<!-- Create Fields menu-->
<menuitem id="menu_create_fields"
name="Create Fields"
parent="menu_create_custom_dynamic_fields"
action="dynamic_fields_action"
groups="group_all_in_one_dynamic_custom_fields_user,group_all_in_one_dynamic_custom_fields_administrator"
sequence="2"/>
</odoo>
Loading…
Cancel
Save