@ -0,0 +1,53 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
||||
|
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
Employee Dynamic Fields |
||||
|
======================= |
||||
|
Ability To Add Custom Fields in Employee From User Level,Create/Delete Employee |
||||
|
Custom Fields. |
||||
|
|
||||
|
Configuration |
||||
|
============ |
||||
|
- Install our custom addon |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPLv3) |
||||
|
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developers: |
||||
|
(V14) Minhaj T, |
||||
|
(V15) Musthafa C, |
||||
|
(V16) Viswanth K, |
||||
|
(V17) Sruthi Pavithran, |
||||
|
(V18) Nivedhya T |
||||
|
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,24 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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 . import models |
||||
|
from . import wizards |
@ -0,0 +1,46 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
{ |
||||
|
'name': 'Employee Dynamic Fields', |
||||
|
'version': '18.0.1.0.0', |
||||
|
'category': 'Extra Tools', |
||||
|
'summary': """Ability To Add Custom Fields in Employee From User Level""", |
||||
|
'description': """ Dynamic Fields module helps with easy creation of custom |
||||
|
fields in employee without any coding""", |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'website': "https://www.cybrosys.com", |
||||
|
'depends': ['hr'], |
||||
|
'data': [ |
||||
|
'security/employee_dynamic_fields_groups.xml', |
||||
|
'security/ir.model.access.csv', |
||||
|
'data/employee_field_widgets_data.xml', |
||||
|
'views/ir_model_fields_views.xml', |
||||
|
'wizards/employee_dynamic_fields_views.xml' |
||||
|
], |
||||
|
'images': ['static/description/banner.jpg'], |
||||
|
'license': 'AGPL-3', |
||||
|
'installable': True, |
||||
|
'auto_install': False, |
||||
|
'application': False, |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- Create data for various widgets--> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Widget 'image' for 'binary' field --> |
||||
|
<record id="employee_field_widgets_image" model="employee.field.widgets"> |
||||
|
<field name="name">image</field> |
||||
|
<field name="description">Image</field> |
||||
|
</record> |
||||
|
<!-- Widget 'many2many_tags' for 'many2many' field --> |
||||
|
<record id="employee_field_widgets_many2many_tags" model="employee.field.widgets"> |
||||
|
<field name="name">many2many_tags</field> |
||||
|
<field name="description">Many2many Tags</field> |
||||
|
</record> |
||||
|
<!-- Widget 'binary' for 'many2many' field --> |
||||
|
<record id="employee_field_widgets_binary" model="employee.field.widgets"> |
||||
|
<field name="name">binary</field> |
||||
|
<field name="description">Binary</field> |
||||
|
</record> |
||||
|
<!-- Widget 'radio' for 'selection' field --> |
||||
|
<record id="employee_field_widgets_radio" model="employee.field.widgets"> |
||||
|
<field name="name">radio</field> |
||||
|
<field name="description">Radio</field> |
||||
|
</record> |
||||
|
<!-- Widget 'priority' for 'selection' field --> |
||||
|
<record id="employee_field_widgets_priority" model="employee.field.widgets"> |
||||
|
<field name="name">priority</field> |
||||
|
<field name="description">Priority</field> |
||||
|
</record> |
||||
|
<!-- Widget 'monetary' for 'float' field --> |
||||
|
<record id="employee_field_widgets_monetory" model="employee.field.widgets"> |
||||
|
<field name="name">monetary</field> |
||||
|
<field name="description">Monetary</field> |
||||
|
</record> |
||||
|
<!-- Widget 'selection' for 'Many2one' field --> |
||||
|
<record id="employee_field_widgets_selection" model="employee.field.widgets"> |
||||
|
<field name="name">selection</field> |
||||
|
<field name="description">Selection</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,6 @@ |
|||||
|
## Module <employee_dynamic_fields> |
||||
|
|
||||
|
#### 04.10.2025 |
||||
|
#### Version 18.0.1.0.0 |
||||
|
##### ADD |
||||
|
- Initial Commit for Employee Dynamic Fields |
@ -0,0 +1,24 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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 . import employee_field_widgets |
||||
|
from . import hr_employee |
||||
|
from . import ir_model_fields |
@ -0,0 +1,37 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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 fields, models |
||||
|
|
||||
|
|
||||
|
class EmployeeFieldWidgets(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 = 'employee.field.widgets' |
||||
|
_rec_name = 'description' |
||||
|
_description = 'Field Widgets' |
||||
|
|
||||
|
name = fields.Char(string="Name", help="Name of the field widget") |
||||
|
description = fields.Char(string="Description", |
||||
|
help="Description of the filed widget") |
@ -0,0 +1,32 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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 fields, models |
||||
|
|
||||
|
|
||||
|
class HrEmployee(models.Model): |
||||
|
"""Inherit the hr.employee model for adding fields""" |
||||
|
_description = 'Employee' |
||||
|
_inherit = 'hr.employee' |
||||
|
|
||||
|
x_currency_id = fields.Many2one('res.currency', |
||||
|
help="Choose currency", |
||||
|
string='Currency') |
@ -0,0 +1,30 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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 fields, models |
||||
|
|
||||
|
|
||||
|
class IrModelFields(models.Model): |
||||
|
"""Adding a new field to understand the dynamically created fields.""" |
||||
|
_inherit = 'ir.model.fields' |
||||
|
|
||||
|
is_employee_dynamic = fields.Boolean(string="Dynamic Field", |
||||
|
help="Is the field is dynamic or not") |
@ -0,0 +1,8 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- Create group for custom fields --> |
||||
|
<record id="employee_dynamic_fields_group_add_employee_custom_fields" |
||||
|
model="res.groups"> |
||||
|
<field name="name">Create Employee 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: 319 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: 47 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 821 KiB |
After Width: | Height: | Size: 530 KiB |
After Width: | Height: | Size: 193 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 880 KiB |
After Width: | Height: | Size: 721 KiB |
After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,19 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- Create search view for dynamic fields--> |
||||
|
<record id="view_model_fields_search" model="ir.ui.view"> |
||||
|
<field name="name"> |
||||
|
ir.model.fields.search.inherit.employee.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="Employee Dynamic Fields" |
||||
|
name="employee_dynamic_field" |
||||
|
domain="[('is_employee_dynamic', '=', True)]"/> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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 . import employee_dynamic_fields |
@ -0,0 +1,226 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2025-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/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
import xml.etree.ElementTree as xee |
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class EmployeeDynamicFields(models.TransientModel): |
||||
|
""" |
||||
|
Model for creating dynamic fields and adding necessary fields |
||||
|
""" |
||||
|
_name = 'employee.dynamic.fields' |
||||
|
_description = 'Dynamic Fields' |
||||
|
_inherit = 'ir.model.fields' |
||||
|
|
||||
|
form_view_id = fields.Many2one('ir.ui.view', |
||||
|
string="Form View ID", |
||||
|
help="View ID of the form") |
||||
|
|
||||
|
@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')) |
||||
|
return field_list |
||||
|
|
||||
|
def set_domain(self): |
||||
|
"""Return the fields that currently present in the form""" |
||||
|
view_id = self.env.ref('hr.view_employee_form') |
||||
|
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', '=', 'hr.employee')]) |
||||
|
return [('model_id', '=', model_id.id), ('state', '=', 'base'), |
||||
|
('name', 'in', field_list)] |
||||
|
|
||||
|
def _set_default(self): |
||||
|
""" |
||||
|
This method is used to set a default filter in a domain expression |
||||
|
for the 'hr.employee' model. It retrieves the ID of the |
||||
|
'hr.employee' model using a search query and sets it as a default |
||||
|
filter in the domain expression. |
||||
|
""" |
||||
|
model_id = self.env['ir.model'].sudo().search( |
||||
|
[('model', '=', 'hr.employee')]) |
||||
|
return [('id', '=', model_id.id)] |
||||
|
|
||||
|
def action_create_fields(self): |
||||
|
""" |
||||
|
This method is used to create custom fields for the 'hr.employee' |
||||
|
model and extend the employee form view.It creates a new field in |
||||
|
the 'ir.model.fields' table, extends the 'hr.view_employee_form' |
||||
|
view. |
||||
|
""" |
||||
|
self.created_menu_id = 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_employee_dynamic': True |
||||
|
}]) |
||||
|
inherit_id = self.env.ref('hr.view_employee_form') |
||||
|
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.name) |
||||
|
|
||||
|
self.form_view_id = self.env['ir.ui.view'].sudo().create( |
||||
|
[{'name': 'employee.dynamic.fields', |
||||
|
'type': 'form', |
||||
|
'model': 'hr.employee', |
||||
|
'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, |
||||
|
ondelete='cascade', |
||||
|
help="Position of the field") |
||||
|
position = fields.Selection([('before', 'Before'), |
||||
|
('after', 'After')], string='Position', |
||||
|
required=True, help='Position after or before existing 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='Reference model') |
||||
|
selection_field = fields.Char(string="Selection Options", help='Selection 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, help="Type of the field") |
||||
|
ttype = fields.Selection(string="Field Type", related='field_type', |
||||
|
help="Specifies the type of the field") |
||||
|
widget_id = fields.Many2one('employee.field.widgets', |
||||
|
string='Widget', help="Widget of the field") |
||||
|
# Already existing field |
||||
|
groups = fields.Many2many('res.groups', |
||||
|
'fields_group_rel', |
||||
|
'id_field', 'id_group', |
||||
|
string='Groups', help="User groups") |
||||
|
extra_features = fields.Boolean(string="Show Extra Properties", |
||||
|
help="Add extra features for the field") |
||||
|
created_menu_id = fields.Many2one('ir.model.fields', string='Created Menu', |
||||
|
help="Menu created using the dynamic " |
||||
|
"field creation option") |
||||
|
menu_state = fields.Selection([('active', 'Active'), |
||||
|
('inactive', 'Inactive')], string='State', |
||||
|
help="State of the created menu", |
||||
|
default='active') |
||||
|
|
||||
|
def action_deactivate_menu(self): |
||||
|
"""Method action_deactivate_menu to deactivate the created menu and the |
||||
|
created view""" |
||||
|
if self.form_view_id: |
||||
|
self.form_view_id.active = False |
||||
|
self.menu_state = 'inactive' |
||||
|
return { |
||||
|
'type': 'ir.actions.client', |
||||
|
'tag': 'reload', |
||||
|
} |
||||
|
|
||||
|
def action_activate_menu(self): |
||||
|
"""Method action_activate_menu to activate the created menu and the |
||||
|
created view""" |
||||
|
if self.form_view_id: |
||||
|
self.form_view_id.active = True |
||||
|
self.menu_state = 'active' |
||||
|
return { |
||||
|
'type': 'ir.actions.client', |
||||
|
'tag': 'reload', |
||||
|
} |
||||
|
|
||||
|
@api.depends('field_type') |
||||
|
@api.onchange('field_type') |
||||
|
def onchange_field_type(self): |
||||
|
""" |
||||
|
This method is triggered when the 'field_type' attribute is changed |
||||
|
in a form. It provides a domain for the 'widget' attribute based on |
||||
|
the selected field type. |
||||
|
""" |
||||
|
if self.field_type: |
||||
|
if self.field_type == 'binary': |
||||
|
return {'domain': {'widget_id': [('name', '=', 'image')]}} |
||||
|
elif self.field_type == 'many2many': |
||||
|
return {'domain': { |
||||
|
'widget_id': [ |
||||
|
('name', 'in', ['many2many_tags', 'binary'])]}} |
||||
|
elif self.field_type == 'selection': |
||||
|
return {'domain': { |
||||
|
'widget_id': [('name', 'in', ['radio', 'priority'])]}} |
||||
|
elif self.field_type == 'float': |
||||
|
return {'domain': {'widget_id': [('name', '=', 'monetary')]}} |
||||
|
elif self.field_type == 'many2one': |
||||
|
return {'domain': {'widget_id': [('name', '=', 'selection')]}} |
||||
|
else: |
||||
|
return {'domain': {'widget_id': [('id', '=', False)]}} |
||||
|
return {'domain': {'widget_id': [('id', '=', False)]}} |
||||
|
|
||||
|
def unlink(self): |
||||
|
""" |
||||
|
This method is used to delete dynamic fields associated with |
||||
|
an instance of 'EmployeeDynamicFields' and deactivate the related |
||||
|
form view. |
||||
|
""" |
||||
|
if self.menu_state == 'active': |
||||
|
raise ValidationError(_("You cannot delete a menu that is active")) |
||||
|
if self.form_view_id: |
||||
|
self.form_view_id.unlink() |
||||
|
self.created_menu_id.unlink() |
||||
|
return super(EmployeeDynamicFields, self).unlink() |
@ -0,0 +1,118 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- Wizard view for creating new fields --> |
||||
|
<record id='employee_dynamic_fields_view_form' model='ir.ui.view'> |
||||
|
<field name="name">employee.dynamic.fields.view.form</field> |
||||
|
<field name="model">employee.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 Fields" |
||||
|
type="object" class="oe_highlight"/> |
||||
|
<button string="Cancel" class="oe_link" special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<!--Tree view of the model employee dynamic fields--> |
||||
|
<record id='employee_dynamic_fields_view_tree' model='ir.ui.view'> |
||||
|
<field name="name">employee.dynamic.fields.view.tree</field> |
||||
|
<field name="model">employee.dynamic.fields</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<list create="false"> |
||||
|
<field name="name"/> |
||||
|
<field name="field_description"/> |
||||
|
<field name="ttype"/> |
||||
|
<field name="menu_state" |
||||
|
decoration-success="menu_state == 'active'" |
||||
|
decoration-danger="menu_state == 'inactive'" |
||||
|
widget="badge"/> |
||||
|
<button name="action_deactivate_menu" string="Deactivate" |
||||
|
type="object" |
||||
|
invisible="menu_state == 'inactive'"/> |
||||
|
<button name="action_activate_menu" string="Activate" |
||||
|
type="object" |
||||
|
invisible="menu_state == 'active'"/> |
||||
|
</list> |
||||
|
</field> |
||||
|
</record> |
||||
|
<!--Employee dynamic fields action--> |
||||
|
<record id='employee_dynamic_fields_action' model='ir.actions.act_window'> |
||||
|
<field name="name">Create Custom Fields</field> |
||||
|
<field name="res_model">employee.dynamic.fields</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="employee_dynamic_fields_view_form"/> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
<!--Employee dynamic fields delete action--> |
||||
|
<record id="employee_dynamic_fields_action_delete" |
||||
|
model="ir.actions.act_window"> |
||||
|
<field name="name">Delete Fields</field> |
||||
|
<field name="res_model">employee.dynamic.fields</field> |
||||
|
<field name="view_mode">list</field> |
||||
|
<field name="view_id" ref="employee_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 Employee to create fields --> |
||||
|
<menuitem id="employee_dynamic_fields_menu" |
||||
|
name="Create Fields" |
||||
|
parent="hr.menu_hr_employee_payroll" |
||||
|
action="employee_dynamic_fields.employee_dynamic_fields_action" |
||||
|
groups="employee_dynamic_fields.employee_dynamic_fields_group_add_employee_custom_fields" |
||||
|
sequence="10"/> |
||||
|
<menuitem id="employee_dynamic_fields_menu_delete" |
||||
|
name="Delete Fields" |
||||
|
parent="hr.menu_hr_employee_payroll" |
||||
|
action="employee_dynamic_fields_action_delete" |
||||
|
groups="employee_dynamic_fields.employee_dynamic_fields_group_add_employee_custom_fields" |
||||
|
sequence="12"/> |
||||
|
</odoo> |