| @ -0,0 +1,50 @@ | |||
| .. image:: https://img.shields.io/badge/license-LGPL--3-green.svg | |||
|     :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html | |||
|     :alt: License: LGPL-3 | |||
| 
 | |||
| Project Dynamic Fields | |||
| ====================== | |||
| This module helps to add any custom field in Project Module. | |||
| 
 | |||
| Configuration | |||
| ============= | |||
| - Need to turn on the option 'Create Project Custom Fields' from the user Configuration | |||
| 
 | |||
| Company | |||
| ------- | |||
| * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | |||
| 
 | |||
| License | |||
| ------- | |||
| General Public License, Version 3 (LGPL v3). | |||
| (http://www.gnu.org/licenses/lgpl-3.0-standalone.html) | |||
| 
 | |||
| Credits | |||
| ------- | |||
| * Developer: | |||
|             (V16)Dhanya Babu, | |||
|             (V17) Gayathri V, | |||
|             (V18) Farook Al Ameen | |||
|   Contact : odoo@cybrosys.com | |||
| 
 | |||
| Contacts | |||
| -------- | |||
| * Mail Contact : odoo@cybrosys.com | |||
| * Website : https://cybrosys.com | |||
| 
 | |||
| Bug Tracker | |||
| ----------- | |||
| Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. | |||
| 
 | |||
| Maintainer | |||
| ========== | |||
| .. image:: https://cybrosys.com/images/logo.png | |||
|    :target: https://cybrosys.com | |||
| 
 | |||
| This module is maintained by Cybrosys Technologies. | |||
| 
 | |||
| For support and more information, please visit `Our Website <https://cybrosys.com/>`__ | |||
| 
 | |||
| Further information | |||
| =================== | |||
| HTML Description: `<static/description/index.html>`__ | |||
| @ -0,0 +1,23 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen (<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from . import models | |||
| from . import wizard | |||
| @ -0,0 +1,48 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen (<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| { | |||
|     'name': 'Project Dynamic Fields', | |||
|     'version': '18.0.1.0.0', | |||
|     'category': 'Project', | |||
|     'summary': "Adding Custom Fields for Project Module", | |||
|     'description': """Adding Custom Fields for Project Module,Odoo18. | |||
|     Easy to track  how many custom fields are created. There is no need of | |||
|      technical knowledge to create custom fields""", | |||
|     'author': 'Cybrosys Techno Solutions', | |||
|     'company': 'Cybrosys Techno Solutions', | |||
|     'maintainer': 'Cybrosys Techno Solutions', | |||
|     'website': 'https://www.cybrosys.com', | |||
|     'depends': ['project'], | |||
|     'data': | |||
|         [ | |||
|             'security/project_dynamic_fields_groups.xml', | |||
|             'security/ir.model.access.csv', | |||
|             'data/project_field_widgets_data.xml', | |||
|             'views/ir_model_fields_views.xml', | |||
|             'wizard/project_dynamic_fields_views.xml', | |||
|         ], | |||
|     'images': ['static/description/banner.gif'], | |||
|     'license': 'LGPL-3', | |||
|     'installable': True, | |||
|     'application': False, | |||
|     'auto_install': False, | |||
| } | |||
| @ -0,0 +1,45 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <data noupdate="1"> | |||
|         <!-- Defines a custom widget for the 'image' field of the project model. --> | |||
|         <record id="project_field_image_widgets" model="project.field.widgets"> | |||
|             <field name="name">image</field> | |||
|             <field name="description">Image</field> | |||
|         </record> | |||
|         <!-- Defines a custom widget for the 'many2many_tags' field of the project model. --> | |||
|         <record id="project_field_many2many_tag_widget" | |||
|                 model="project.field.widgets"> | |||
|             <field name="name">many2many_tags</field> | |||
|             <field name="description">Many2many Tags</field> | |||
|         </record> | |||
|         <!-- Defines a custom widget for the 'binary' field of the project model. --> | |||
|         <record id="project_field_many2many_binary_widget" | |||
|                 model="project.field.widgets"> | |||
|             <field name="name">binary</field> | |||
|             <field name="description">Binary</field> | |||
|         </record> | |||
|         <!-- Defines a custom widget for the 'radio' field of the project model. --> | |||
|         <record id="project_field_radio_widget" model="project.field.widgets"> | |||
|             <field name="name">radio</field> | |||
|             <field name="description">Radio</field> | |||
|         </record> | |||
|         <!-- Defines a custom widget for the 'priority' field of the project model. --> | |||
|         <record id="project_field_priority_widget" | |||
|                 model="project.field.widgets"> | |||
|             <field name="name">priority</field> | |||
|             <field name="description">Priority</field> | |||
|         </record> | |||
|         <!-- Defines a custom widget for the 'monetary' field of the project model. --> | |||
|         <record id="project_field_monetary_widget" | |||
|                 model="project.field.widgets"> | |||
|             <field name="name">monetary</field> | |||
|             <field name="description">Monetary</field> | |||
|         </record> | |||
|         <!-- Defines a custom widget for the 'selection' field of the project model. --> | |||
|         <record id="project_field_selection_widget" | |||
|                 model="project.field.widgets"> | |||
|             <field name="name">selection</field> | |||
|             <field name="description">Selection</field> | |||
|         </record> | |||
|     </data> | |||
| </odoo> | |||
| @ -0,0 +1,7 @@ | |||
| ## Module <project_dynamic_fields> | |||
| 
 | |||
| #### 18.01.2024 | |||
| #### Version 18.0.1.0.0 | |||
| ##### ADD | |||
| 
 | |||
| - Initial Commit For Project Dynamic Fields | |||
| @ -0,0 +1,23 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen (<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from . import project_field_widgets | |||
| from . import ir_model_fields | |||
| @ -0,0 +1,32 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen (<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from odoo import fields, models | |||
| 
 | |||
| 
 | |||
| class IrModelFields(models.Model): | |||
|     """Adding a new field to understand the dynamically created fields.""" | |||
|     _inherit = 'ir.model.fields' | |||
| 
 | |||
|     is_project_dynamic = fields.Boolean(string="Dynamic Field", | |||
|                                         help="Flag to indicate whether this " | |||
|                                              "field is dynamically created or " | |||
|                                              "not.") | |||
| @ -0,0 +1,34 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen (<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from odoo import fields, models | |||
| 
 | |||
| 
 | |||
| class ProjectFieldWidgets(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 = 'project.field.widgets' | |||
|     _rec_name = 'description' | |||
|     _description = 'Project Field Widgets' | |||
| 
 | |||
|     name = fields.Char(string="Name", help="Name ") | |||
|     description = fields.Char(string="Description", help="Description ") | |||
| 
 | 
| @ -0,0 +1,9 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!--    This record represents a user group with permission to create custom fields for projects.--> | |||
|     <!--    Members of this group will be able to add new custom fields to projects,--> | |||
|     <!--    providing additional flexibility and customization options to better meet project management needs.--> | |||
|     <record id="group_add_project_custom_fields" model="res.groups"> | |||
|         <field name="name">Create Project Custom Fields</field> | |||
|     </record> | |||
| </odoo> | |||
| After Width: | Height: | Size: 2.2 KiB | 
| After Width: | Height: | Size: 28 KiB | 
| After Width: | Height: | Size: 628 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 210 KiB | 
| After Width: | Height: | Size: 209 KiB | 
| After Width: | Height: | Size: 109 KiB | 
| After Width: | Height: | Size: 495 B | 
| After Width: | Height: | Size: 1.0 KiB | 
| After Width: | Height: | Size: 624 B | 
| After Width: | Height: | Size: 136 KiB | 
| After Width: | Height: | Size: 214 KiB | 
| After Width: | Height: | Size: 36 KiB | 
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 929 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 3.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 542 B | 
| After Width: | Height: | Size: 576 B | 
| After Width: | Height: | Size: 733 B | 
| After Width: | Height: | Size: 4.3 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 4.0 KiB | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 156 KiB | 
| After Width: | Height: | Size: 2.2 KiB | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 600 B | 
| After Width: | Height: | Size: 673 B | 
| After Width: | Height: | Size: 2.0 KiB | 
| After Width: | Height: | Size: 462 B | 
| After Width: | Height: | Size: 2.1 KiB | 
| After Width: | Height: | Size: 926 B | 
| After Width: | Height: | Size: 9.0 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 7.0 KiB | 
| After Width: | Height: | Size: 878 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 653 B | 
| After Width: | Height: | Size: 800 B | 
| After Width: | Height: | Size: 905 B | 
| After Width: | Height: | Size: 189 KiB | 
| After Width: | Height: | Size: 4.3 KiB | 
| After Width: | Height: | Size: 839 B | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 5.9 KiB | 
| After Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 34 KiB | 
| After Width: | Height: | Size: 26 KiB | 
| After Width: | Height: | Size: 3.8 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 1.9 KiB | 
| After Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 427 B | 
| After Width: | Height: | Size: 627 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 988 B | 
| After Width: | Height: | Size: 3.7 KiB | 
| After Width: | Height: | Size: 5.0 KiB | 
| After Width: | Height: | Size: 875 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 912 KiB | 
| After Width: | Height: | Size: 1.3 MiB | 
| After Width: | Height: | Size: 46 KiB | 
| After Width: | Height: | Size: 44 KiB | 
| After Width: | Height: | Size: 46 KiB | 
| After Width: | Height: | Size: 85 KiB | 
| After Width: | Height: | Size: 142 KiB | 
| After Width: | Height: | Size: 110 KiB | 
| After Width: | Height: | Size: 118 KiB | 
| After Width: | Height: | Size: 106 KiB | 
| After Width: | Height: | Size: 60 KiB | 
| After Width: | Height: | Size: 52 KiB | 
| After Width: | Height: | Size: 71 KiB | 
| After Width: | Height: | Size: 880 KiB | 
| After Width: | Height: | Size: 90 KiB | 
| After Width: | Height: | Size: 11 KiB | 
| @ -0,0 +1,18 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!--    This record defines a custom search view for the 'ir.model.fields' model, | |||
|      allowing users to search for project dynamic fields specifically--> | |||
|     <record id="view_model_fields_search" model="ir.ui.view"> | |||
|         <field name="name">ir.model.fields.view.search.inherit.project.dynamic.fields</field> | |||
|         <field name="model">ir.model.fields</field> | |||
|         <field name="inherit_id" ref="base.view_model_fields_search"/> | |||
|         <field name="arch" type="xml"> | |||
|             <xpath expr="//search/filter[@name='translate']" position="after"> | |||
|                 <separator/> | |||
|                 <filter string="Project Dynamic Fields" | |||
|                         name="project_dynamic_field" | |||
|                         domain="[('is_project_dynamic', '=', True)]"/> | |||
|             </xpath> | |||
|         </field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen(<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from . import project_dynamic_fields | |||
| @ -0,0 +1,190 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Farook Al Ameen (<https://www.cybrosys.com>) | |||
| # | |||
| #    You can modify it under the terms of the GNU LESSER | |||
| #    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |||
| # | |||
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |||
| #    (LGPL v3) along with this program. | |||
| #    If not, see <http://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| import xml.etree.ElementTree as xee | |||
| from odoo import api, fields, models, _ | |||
| 
 | |||
| 
 | |||
| class ProjectDynamicFields(models.TransientModel): | |||
|     """Creating new transient model for the wizard from""" | |||
|     _name = 'project.dynamic.fields' | |||
|     _description = 'Dynamic Fields' | |||
|     _inherit = 'ir.model.fields' | |||
| 
 | |||
|     form_view_id = fields.Many2one('ir.ui.view', string="Form View ID", | |||
|                                    help="Select the view to be used as" | |||
|                                         " the form view for this field.") | |||
| 
 | |||
|     @api.model | |||
|     def get_possible_field_types(self): | |||
|         """Return all available field types other than | |||
|          'One2many' and 'reference' fields.""" | |||
|         field_list = sorted((key, key) for key in fields.MetaField.by_type) | |||
|         field_list.remove(('one2many', 'one2many')) | |||
|         field_list.remove(('reference', 'reference')) | |||
|         field_list.remove(('properties', 'properties')) | |||
|         field_list.remove(('properties_definition', 'properties_definition')) | |||
|         return field_list | |||
| 
 | |||
|     def set_domain(self): | |||
|         """Return the fields that currently present in the form""" | |||
|         view_id = self.env.ref('project.edit_project') | |||
|         view_arch = str(view_id.arch_base) | |||
|         doc = xee.fromstring(view_arch) | |||
|         field_list = [] | |||
|         for tag in doc.findall('.//field'): | |||
|             field_list.append(tag.attrib['name']) | |||
|         model_id = self.env['ir.model'].sudo().search( | |||
|             [('model', '=', 'project.project')]) | |||
|         return [('model_id', '=', model_id.id), ('state', '=', 'base'), | |||
|                 ('name', 'in', field_list)] | |||
| 
 | |||
|     def _set_default(self): | |||
|         """setting the default model""" | |||
|         model_id = self.env['ir.model'].sudo().search( | |||
|             [('model', '=', 'project.project')]) | |||
|         return [('id', '=', model_id.id)] | |||
| 
 | |||
|     def action_create_fields(self): | |||
|         """ Creates a new custom field for the project.project model and adds | |||
|         it to the project form view.""" | |||
|         self.env['ir.model.fields'].sudo().create( | |||
|             {'name': self.name, | |||
|              'field_description': self.field_description, | |||
|              'model_id': self.model_id.id, | |||
|              'ttype': self.field_type, | |||
|              'relation': self.ref_model_id.model, | |||
|              'required': self.required, | |||
|              'index': self.index, | |||
|              'store': self.store, | |||
|              'help': self.help, | |||
|              'readonly': self.readonly, | |||
|              'selection': self.selection_field, | |||
|              'copied': self.copied, | |||
|              'is_project_dynamic': True | |||
|              }) | |||
|         inherit_id = self.env.ref('project.edit_project') | |||
|         arch_base = _('<?xml version="1.0"?>' | |||
|                       '<data>' | |||
|                       '<field name="%s" position="%s">' | |||
|                       '<field name="%s"/>' | |||
|                       '</field>' | |||
|                       '</data>') % ( | |||
|                         self.position_field_id.name, self.position, self.name) | |||
|         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_id.name, self.position, | |||
|                             self.name, | |||
|                             self.widget_id.name) | |||
|         self.form_view_id = self.env['ir.ui.view'].sudo().create( | |||
|             {'name': 'project.dynamic.fields', | |||
|              'type': 'form', | |||
|              'model': 'project.project', | |||
|              'mode': 'extension', | |||
|              'inherit_id': inherit_id.id, | |||
|              'arch_base': arch_base, | |||
|              'active': True}) | |||
|         return { | |||
|             'type': 'ir.actions.client', | |||
|             'tag': 'reload', | |||
|         } | |||
| 
 | |||
|     position_field_id = fields.Many2one('ir.model.fields', string='Field Name', | |||
|                                         domain=set_domain, required=True, | |||
|                                         help="Select the field that will " | |||
|                                              "determine the position of" | |||
|                                              " the custom field.") | |||
|     position = fields.Selection([('before', 'Before'), | |||
|                                  ('after', 'After')], string='Position', | |||
|                                 required=True, help="Position of field") | |||
|     model_id = fields.Many2one('ir.model', string='Model', required=True, | |||
|                                index=True, ondelete='cascade', | |||
|                                help="The model this field belongs to", | |||
|                                domain=_set_default) | |||
|     ref_model_id = fields.Many2one('ir.model', string='Model', index=True, | |||
|                                    help="This field is used to specify the " | |||
|                                         "model that the dynamic field will be " | |||
|                                         "associated with.") | |||
|     selection_field = fields.Char(string="Selection Options", | |||
|                                   help='Enter selection value') | |||
|     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, | |||
|                                   help='The type of field that will be ' | |||
|                                        'created for this dynamic field.' | |||
|                                        'This field is required and must be ' | |||
|                                        'set to one of the possible' | |||
|                                        'field types returned by the ' | |||
|                                        '"get_possible_field_types" method.') | |||
|     ttype = fields.Selection(string="Field Type", related='field_type', | |||
|                              help='The type of field that this dynamic field ' | |||
|                                   'corresponds to.') | |||
|     widget_id = fields.Many2one('project.field.widgets', string='Widget', | |||
|                                 help='Select widget') | |||
|     groups = fields.Many2many('res.groups', | |||
|                                   'project_dynamic_fields_m2m_group_rel', | |||
|                                   'field_ids', 'group_ids', | |||
|                                   help='The security groups that have access to ' | |||
|                                        'this dynamic field.') | |||
|     extra_features = fields.Boolean(string="Show Extra Properties", | |||
|                                     help="A boolean field that determines " | |||
|                                          "whether to display extra properties " | |||
|                                          "for this dynamic field in the user " | |||
|                                          "interface") | |||
| 
 | |||
|     @api.depends('field_type') | |||
|     @api.onchange('field_type') | |||
|     def onchange_field_type(self): | |||
|         if self.field_type: | |||
|             if self.field_type == 'binary': | |||
|                 return {'domain': {'widget': [('name', '=', 'image')]}} | |||
|             elif self.field_type == 'many2many': | |||
|                 return {'domain': { | |||
|                     'widget': [('name', 'in', ['many2many_tags', 'binary'])]}} | |||
|             elif self.field_type == 'selection': | |||
|                 return {'domain': { | |||
|                     'widget': [('name', 'in', ['radio', 'priority'])]}} | |||
|             elif self.field_type == 'float': | |||
|                 return {'domain': {'widget': [('name', '=', 'monetary')]}} | |||
|             elif self.field_type == 'many2one': | |||
|                 return {'domain': {'widget': [('name', '=', 'selection')]}} | |||
|             else: | |||
|                 return {'domain': {'widget': [('id', '=', False)]}} | |||
|         return {'domain': {'widget': [('id', '=', False)]}} | |||
| 
 | |||
|     def unlink(self): | |||
|         """Overrides the default 'unlink' method of the | |||
|         'ProjectDynamicFields' model to perform custom deletion logic.""" | |||
|         if self.form_view_id: | |||
|             self.form_view_id.active = False | |||
|             for field in self: | |||
|                 if field.ttype == 'many2many': | |||
|                     field: [(5, 0, 0)] | |||
|                 else: | |||
|                     query = """delete FROM ir_model_fields WHERE name = %s""" | |||
|                     self.env.cr.execute(query, [field.name]) | |||
|         return super().unlink() | |||
| @ -0,0 +1,112 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!--This is an XML view definition for a form view in Odoo, which allows users to create and manage dynamic fields for a model.   --> | |||
|     <record id='project_dynamic_fields_view_form' model='ir.ui.view'> | |||
|         <field name="name">project.dynamic.fields.view.form</field> | |||
|         <field name="model">project.dynamic.fields</field> | |||
|         <field name="arch" type="xml"> | |||
|             <form string="Dynamic Fields"> | |||
|                 <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')]" | |||
|                                    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}' | |||
|                                    required="field_type in ['many2one','many2many']" | |||
|                                    readonly="field_type not in ['many2one','many2many']" | |||
|                                    invisible="field_type not in ['many2one','many2many']"/> | |||
|                             <field name="widget_id" widget="selection" | |||
|                                    invisible="field_type not in ['binary', 'many2many', 'selection', 'float', 'many2one']"/> | |||
|                             <field name="required"/> | |||
|                         </group> | |||
|                         <group string="Position"> | |||
|                             <field name="position_field_id" | |||
|                                    options='{"no_open": True, "no_create": True}'/> | |||
|                             <field name="position"/> | |||
|                         </group> | |||
|                     </group> | |||
|                     <group string="Extra Properties"> | |||
|                         <group> | |||
|                             <field name="extra_features"/> | |||
|                         </group> | |||
|                         <group invisible="extra_features == False"> | |||
|                             <field name="help"/> | |||
|                         </group> | |||
|                         <group invisible="extra_features == False"> | |||
|                             <field name="readonly"/> | |||
|                             <field name="store"/> | |||
|                             <field name="index"/> | |||
|                             <field name="copied"/> | |||
|                         </group> | |||
|                     </group> | |||
|                 </sheet> | |||
|                 <footer> | |||
|                     <button name="action_create_fields" string="Create" | |||
|                             type="object" class="oe_highlight"/> | |||
|                     <button string="Cancel" class="oe_link" special="cancel"/> | |||
|                 </footer> | |||
|             </form> | |||
|         </field> | |||
|     </record> | |||
|     <!--This XML record defines an action to open a form view for creating custom fields in the project.dynamic.fields model--> | |||
|     <record id='project_dynamic_fields_action_create' | |||
|             model='ir.actions.act_window'> | |||
|         <field name="name">Create Custom Fields</field> | |||
|         <field name="res_model">project.dynamic.fields</field> | |||
|         <field name="view_mode">form</field> | |||
|         <field name="view_id" ref="project_dynamic_fields_view_form"/> | |||
|         <field name="target">new</field> | |||
|     </record> | |||
|     <!--    This is an XML record defining a view for the "project.dynamic.fields" model. The view is a tree view and displays three fields: "name", "field_description", and "ttype". --> | |||
|     <record id='project_dynamic_fields_view_tree' model='ir.ui.view'> | |||
|         <field name="name">project.dynamic.fields.view.list</field> | |||
|         <field name="model">project.dynamic.fields</field> | |||
|         <field name="arch" type="xml"> | |||
|             <list create="false"> | |||
|                 <field name="name"/> | |||
|                 <field name="field_description"/> | |||
|                 <field name="ttype"/> | |||
|             </list> | |||
|         </field> | |||
|     </record> | |||
|     <!--    Delete fields tree view--> | |||
|     <record id="project_dynamic_fields_action_delete" | |||
|             model="ir.actions.act_window"> | |||
|         <field name="name">Delete Custom Fields</field> | |||
|         <field name="res_model">project.dynamic.fields</field> | |||
|         <field name="view_mode">list</field> | |||
|         <field name="view_id" ref="project_dynamic_fields_view_tree"/> | |||
|         <field name="help" type="html"> | |||
|             <p class="o_view_nocontent_smiling_face"> | |||
|                 Delete created custom fields | |||
|             </p> | |||
|         </field> | |||
|     </record> | |||
|     <!-- Menu Item in Project to create fields --> | |||
|     <menuitem | |||
|             id="project_dynamic_fields_menu_create" | |||
|             name="Create Fields" | |||
|             parent="project.menu_project_config" | |||
|             action="project_dynamic_fields.project_dynamic_fields_action_create" | |||
|             groups="project_dynamic_fields.group_add_project_custom_fields" | |||
|             sequence="10"/> | |||
|     <!-- Menu Item in Project to Delete fields --> | |||
|     <menuitem | |||
|             id="project_dynamic_fields_menu_delete" | |||
|             name="Delete Fields" | |||
|             parent="project.menu_project_config" | |||
|             action="project_dynamic_fields.project_dynamic_fields_action_delete" | |||
|             groups="project_dynamic_fields.group_add_project_custom_fields" | |||
|             sequence="12"/> | |||
| </odoo> | |||