Browse Source

Jun 13: [FIX] Bug Fixed 'all_in_one_dynamic_custom_fields'

pull/331/head
RisvanaCybro 11 months ago
parent
commit
3397a7d05b
  1. 8
      all_in_one_dynamic_custom_fields/__manifest__.py
  2. 16
      all_in_one_dynamic_custom_fields/data/dynamic_field_widgets_data.xml
  3. 5
      all_in_one_dynamic_custom_fields/doc/RELEASE_NOTES.md
  4. 2
      all_in_one_dynamic_custom_fields/models/__init__.py
  5. 2
      all_in_one_dynamic_custom_fields/models/dynamic_field_widgets.py
  6. 118
      all_in_one_dynamic_custom_fields/models/dynamic_fields.py
  7. 2
      all_in_one_dynamic_custom_fields/security/ir.model.access.csv
  8. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/1.png
  9. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/2.png
  10. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/3.png
  11. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/4.png
  12. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/5.png
  13. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/6.png
  14. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/7.png
  15. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/8.png
  16. BIN
      all_in_one_dynamic_custom_fields/static/description/assets/screenshots/9.png
  17. 18
      all_in_one_dynamic_custom_fields/static/description/index.html
  18. 6
      all_in_one_dynamic_custom_fields/views/dynamic_fields_views.xml

8
all_in_one_dynamic_custom_fields/__manifest__.py

@ -21,13 +21,13 @@
################################################################################
{
'name': 'All in One Dynamic Fields',
'version': '17.0.1.0.0',
'version': '17.0.1.1.1',
'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.",
"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',

16
all_in_one_dynamic_custom_fields/data/dynamic_field_widgets_data.xml

@ -2,43 +2,43 @@
<odoo>
<data noupdate="1">
<!-- Widget 'image' for 'binary' field -->
<record id="image_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widget_image" model="dynamic.field.widgets">
<field name="name">image</field>
<field name="data_type">binary</field>
<field name="description">Image</field>
</record>
<!-- Widget 'many2many_tags' for 'many 2 many' field -->
<record id="many2many_tag_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widget_many2many_tags" model="dynamic.field.widgets">
<field name="name">many2many_tags</field>
<field name="data_type">many2many</field>
<field name="description">Many2many Tags</field>
</record>
<!-- Widget 'binary' for 'many 2 many' field -->
<record id="many2many_binary_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widget_binary" model="dynamic.field.widgets">
<field name="name">binary</field>
<field name="data_type">many2many</field>
<field name="description">Binary</field>
</record>
<!-- Widget 'radio' for 'selection' field -->
<record id="radio_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widget_radio" model="dynamic.field.widgets">
<field name="name">radio</field>
<field name="data_type">selection</field>
<field name="description">Radio</field>
</record>
<!-- Widget 'priority' for 'selection' field -->
<record id="priority_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widget_priority" model="dynamic.field.widgets">
<field name="name">priority</field>
<field name="data_type">selection</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_widget_monetary" model="dynamic.field.widgets">
<field name="name">monetary</field>
<field name="data_type">float</field>
<field name="description">Monetary</field>
</record>
<!-- Widget 'selection' for 'Many_2_one' field -->
<record id="selection_widget" model="dynamic.field.widgets">
<record id="dynamic_field_widget_selection" model="dynamic.field.widgets">
<field name="name">selection</field>
<field name="data_type">many2one</field>
<field name="description">Selection</field>

5
all_in_one_dynamic_custom_fields/doc/RELEASE_NOTES.md

@ -5,3 +5,8 @@
##### ADD
- Initial commit for All in One Custom Dynamic Fields
#### 13.06.2024
#### Version 17.0.1.1.1
##### 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.

2
all_in_one_dynamic_custom_fields/models/__init__.py

@ -20,5 +20,5 @@
#
################################################################################
from . import dynamic_fields
from . import field_widgets
from . import dynamic_field_widgets
from . import ir_model_fields

2
all_in_one_dynamic_custom_fields/models/field_widgets.py → all_in_one_dynamic_custom_fields/models/dynamic_field_widgets.py

@ -22,7 +22,7 @@
from odoo import fields, models
class FieldWidgets(models.Model):
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,

118
all_in_one_dynamic_custom_fields/models/dynamic_fields.py

@ -19,6 +19,8 @@
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from xlrd.xlsx import ET
from odoo import api, fields, models, _
@ -65,7 +67,7 @@ class DynamicFields(models.Model):
required=True, help="Position of new field")
model_id = fields.Many2one(comodel_name='ir.model', string='Model',
required=True,
index=True, ondelete='cascade',
index=True,
help="The model this field belongs to")
ref_model_id = fields.Many2one(comodel_name='ir.model', string='Relational '
'Model',
@ -76,16 +78,20 @@ class DynamicFields(models.Model):
field_type = fields.Selection(selection='get_possible_field_types',
string='Field Type', required=True,
help="Data type of new field")
tree_field_ids = fields.Many2many('ir.model.fields',
'tree_field_ids',
compute='_compute_tree_field_ids')
ttype = fields.Selection(string="Field Type", related='field_type',
help="Field type of field")
widget = fields.Many2one(comodel_name='dynamic.field.widgets',
string='Widget', help="Widgets for field",
domain=lambda self: "[('data_type', '=', "
"field_type)]")
widget_id = fields.Many2one(comodel_name='dynamic.field.widgets',
string='Widget', help="Widgets for field",
domain=lambda self: "[('data_type', '=', "
"field_type)]")
groups = fields.Many2many('res.groups',
'employee_dynamic_fields_group_rel',
'field_id', 'group_id',
help="Groups of field")
'dynamic_fields_group_rel',
'dynamic_field_id',
'dynamic_group_id',
help="Groups of field")
extra_features = fields.Boolean(string="Show Extra Properties",
help="Enable to add extra features")
status = fields.Selection(selection=[('draft', 'Draft'), ('form',
@ -93,7 +99,7 @@ class DynamicFields(models.Model):
string='Status',
index=True, readonly=True, tracking=True,
copy=False, default='draft',
required=True, help='State for record')
help='State for record')
form_view_ids = fields.Many2many(comodel_name='ir.ui.view',
string="Form View IDs",
help="Stores form view ids")
@ -112,26 +118,78 @@ class DynamicFields(models.Model):
help="Form view inherit id(adds"
" by selecting form view id)")
add_field_in_tree = fields.Boolean(string="Add Field to the Tree View",
default=False,
help="Enable to add field in tree view")
tree_view_id = fields.Many2one(comodel_name='ir.ui.view',
string="Tree View ID",
help="Tree view id of the model",
domain=lambda self: "[('id', 'in', "
"tree_view_ids)]")
tree_view_inherit_id = fields.Char(string="Tree View Inherit Id",
tree_view_inherit_id = fields.Char(string="External Id",
related='tree_view_id.xml_id',
help="Tree view inherit id(adds"
" by selecting tree view id)")
tree_field_id = fields.Many2one('ir.model.fields',
string='Tree Field',
help='Position for new field',
domain="[('id', 'in', tree_field_ids)]")
tree_field_position = fields.Selection(selection=[('before', 'Before'),
('after', 'After')],
string='Tree Position',
help="Position of new field in "
"tree view")
is_visible_in_tree_view = fields.Boolean(string='Visible In List View',
help="Enable to make the field "
"visible in selected list "
"view of the model")
created_tree_view_id = fields.Many2one('ir.ui.view',
string='Created Tree view',
help='This is the currently '
'created tree view')
created_form_view_id = fields.Many2one('ir.ui.view',
string='Created form view',
help='Created form view id for the '
'dynamic field')
@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:
fields = ET.fromstring(self.env.ref(
rec.tree_view_id.xml_id).arch).findall(".//field")
for field in 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:
fields = ET.fromstring(self.env.ref(
inherit_id.xml_id).arch).findall(".//field")
for field in 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
@api.onchange('add_field_in_tree')
def _onchange_add_field_in_tree(self):
"""Function to clear values of tree_view_id and tree_field_id"""
if not self.add_field_in_tree:
self.tree_view_id = False
self.tree_field_id = False
def action_create_dynamic_field(self):
"""Function to create dynamic field to a particular model, data type,
properties and etc"""
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',
@ -139,6 +197,7 @@ class DynamicFields(models.Model):
'ttype': 'many2one',
'relation': 'res.currency',
'is_dynamic_field': True
})
self.env['ir.model.fields'].sudo().create({
'name': self.name,
@ -156,8 +215,8 @@ class DynamicFields(models.Model):
'is_dynamic_field': True
})
inherit_form_view_name = str(
self.form_view_id.name) + ".inherit.dynamic.custom." + str(self.
field_description) + ".field"
self.form_view_id.name) + ".inherit.dynamic.custom." + str(
self.field_description) + ".field"
xml_id = self.form_view_id.xml_id
inherit_id = self.env.ref(xml_id)
arch_base = _('<?xml version="1.0"?>'
@ -167,7 +226,7 @@ class DynamicFields(models.Model):
'</field>'
'</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">'
@ -175,8 +234,8 @@ class DynamicFields(models.Model):
'</field>'
'</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,
@ -194,22 +253,23 @@ class DynamicFields(models.Model):
def action_create_to_tree_view(self):
"""Function to add field to tree view"""
if self.add_field_in_tree:
optional = "show" if self.is_visible_in_tree_view 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>'''))
inherit_tree_view_name = str(
self.tree_view_id.name) + ".inherit.dynamic.custom" + \
str(self.field_description) + ".field"
self.tree_view_id = self.env['ir.ui.view'].sudo().create({
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': _(
'<?xml version="1.0"?>'
'<data>'
'''<xpath expr="//tree" position="inside">'''
'''<field name="%s" optional="show"/>'''
'''</xpath>'''
'''</data>''') % self.name,
'arch_base': tree_view_arch_base,
'active': True})
return {
'type': 'ir.actions.client',
@ -219,8 +279,8 @@ class DynamicFields(models.Model):
def unlink(self):
"""Super unlink function"""
if self.form_view_id:
self.form_view_id.active = False
self.created_form_view_id.active = False
if self.tree_view_id:
self.tree_view_id.active = False
self.created_tree_view_id.active = False
res = super(DynamicFields, self).unlink()
return res

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

@ -1,4 +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,base.group_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 base.group_user 1 1 1 1

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

18
all_in_one_dynamic_custom_fields/static/description/index.html

@ -222,7 +222,7 @@
height="auto">
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img4.png"
<img src="assets/screenshots/1.png"
class="img-responsive" width="100%"
height="auto">
</div>
@ -240,12 +240,12 @@
create a custom field.</p>
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img5.png"
<img src="assets/screenshots/2.png"
class="img-responsive" width="100%"
height="auto">
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img6.png"
<img src="assets/screenshots/3.png"
class="img-responsive" width="100%"
height="auto">
</div>
@ -262,7 +262,7 @@
Choose the field type.</p>
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img7.png"
<img src="assets/screenshots/4.png"
class="img-responsive" width="100%"
height="auto">
</div>
@ -281,17 +281,17 @@
module List/Tree view.</p>
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img8.png"
<img src="assets/screenshots/5.png"
class="img-responsive" width="100%"
height="auto">
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img9.png"
<img src="assets/screenshots/6.png"
class="img-responsive" width="100%"
height="auto">
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img10.png"
<img src="assets/screenshots/7.png"
class="img-responsive" width="100%"
height="auto">
</div>
@ -309,7 +309,7 @@
order form view.</p>
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img11.png"
<img src="assets/screenshots/8.png"
class="img-responsive" width="100%"
height="auto">
</div>
@ -327,7 +327,7 @@
order tree view.</p>
</div>
<div class="row justify-content-center p-3 w-100 m-0">
<img src="assets/screenshots/img12.png"
<img src="assets/screenshots/9.png"
class="img-responsive" width="100%"
height="auto">
</div>

6
all_in_one_dynamic_custom_fields/views/dynamic_fields_views.xml

@ -51,7 +51,7 @@
required="field_type in ('many2one','many2many')"
readonly="field_type not in ('many2one','many2many') or status != 'draft'"
invisible="field_type not in ('many2one','many2many')"/>
<field name="widget" widget="selection"
<field name="widget_id" widget="selection"
invisible="field_type not in ('binary','many2many', 'selection', 'float', 'many2one')"
readonly="status != 'draft'"/>
<field name="required"
@ -74,6 +74,10 @@
readonly="status != 'draft'"/>
<field name="tree_view_inherit_id"
invisible="not add_field_in_tree"/>
<field name="tree_field_ids" invisible="1"/>
<field name="tree_field_id" required="add_field_in_tree" invisible="not add_field_in_tree"/>
<field name="tree_field_position" required="add_field_in_tree" invisible="not add_field_in_tree"/>
<field name="is_visible_in_tree_view" required="add_field_in_tree" invisible="not add_field_in_tree"/>
</group>
<group string="Position">
<field name="position_field_id"

Loading…
Cancel
Save