You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							120 lines
						
					
					
						
							5.1 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							120 lines
						
					
					
						
							5.1 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ############################################################################### | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |
| #    Author: Abhishek E T (Contact : odoo@cybrosys.com) | |
| # | |
| #    This program is under the terms of the Odoo Proprietary License v1.0 | |
| #    (OPL-1) | |
| #    It is forbidden to publish, distribute, sublicense, or sell copies of the | |
| #    Software or modified copies of the Software. | |
| # | |
| #    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| #    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| #    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | |
| #    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | |
| #    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | |
| #    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| #    DEALINGS IN THE SOFTWARE. | |
| # | |
| ############################################################################### | |
| """ | |
| The module helps to remove fields added from Odoo UI or Studio. | |
| """ | |
| import logging | |
| 
 | |
| from odoo import fields, models, _ | |
| from odoo.exceptions import UserError, ValidationError | |
| 
 | |
| _logger = logging.getLogger(__name__) | |
| 
 | |
| 
 | |
| class RemoveStudioField(models.TransientModel): | |
|     """ | |
|     Wizard to select studio fields(x_studio_) and remove them. | |
|     Methods: | |
|         action_remove_studio_field(): | |
|             Delete the selected studio fields. | |
|     """ | |
|     _name = 'remove.studio.field' | |
|     _description = 'Remove Studio Fields' | |
| 
 | |
|     field_ids = fields.Many2many( | |
|         'ir.model.fields', string='Studio Fields', required=True, | |
|         domain="[('name', 'like', 'x_studio_')]", | |
|         help='You can select the fields which are added through Odoo Studio.') | |
| 
 | |
|     def action_remove_studio_field(self): | |
|         """ Search for the selected fields(x_studio_) in views. If any of the | |
|         field is used in any view an error is thrown with the fields and | |
|         corresponding views. If the selected fields are not used in any views, | |
|         remove them. | |
|         Raises: UserError: If any of the selected fields is/are still present | |
|         in any view. | |
|         Raises: UserError: if there is any error while unlinking the fields. | |
|         Returns: | |
|             dict: dictionary to show the success notification. | |
|         """ | |
|         # Makes the given fields clean on all records - remove pending write of | |
|         # this field and pop the pending updates of the fields out from the | |
|         # cache before unlinking the fields | |
|         for record in self.field_ids: | |
|             field = self.pool[record.model]._fields.get(record.name, False) | |
|             if field: | |
|                 self.env.cache.clear_dirty_field(field) | |
|         error_popup_message = '' | |
|         for field in self.field_ids: | |
|             self.env[field.model]._pop_field(field.name) | |
|             domain = [('arch_db', 'like', field.name), | |
|                       ('model', '=', field.model)] | |
|             views = self.env['ir.ui.view'].search(domain) | |
|             field_views = [] | |
|             for view in views: | |
|                 try: | |
|                     view._check_xml() | |
|                 except ValidationError as error: | |
|                     _logger.info(error) | |
|                     field_views.append(view.name) | |
|             if field_views: | |
|                 error_popup_message = '\n'.join( | |
|                     [error_popup_message, _('Field: %s', field.display_name), | |
|                      _('Views: %s') % ', '.join( | |
|                          str(view) for view in field_views) | |
|                      ]) | |
|         # If the fields are present in any views, display them, so that those | |
|         # can be removed from the mentioned views | |
|         if error_popup_message: | |
|             # if Studio module is installed, we will perform a module upgrade | |
|             studio = self.env['ir.module.module'].sudo().search( | |
|                 [('name', '=', 'web_studio')], limit=1) | |
|             if studio and studio.state == 'installed': | |
|                 studio.button_immediate_upgrade() | |
|             raise UserError('\n'.join([ | |
|                 _("Cannot delete the fields that are still present in views:"), | |
|                 error_popup_message | |
|             ])) | |
|         # Set the state of the selected fields as Custom Field(manual) and then | |
|         # unlink those fields | |
|         query = f""" | |
|         UPDATE ir_model_fields set state = 'manual' | |
|             WHERE id in {str(tuple(self.field_ids.ids)).replace(',)', ')')}; | |
|         DELETE FROM ir_model_fields | |
|             WHERE id in {str(tuple(self.field_ids.ids)).replace(',)', ')')}; | |
|         """ | |
|         try: | |
|             self.env.cr.execute(query) | |
|         except Exception as error: | |
|             raise UserError(f'An error occurred! {error}') from error | |
|         return { | |
|             'type': 'ir.actions.client', | |
|             'tag': 'display_notification', | |
|             'params': { | |
|                 'title': _('Success'), | |
|                 'message': _('The selected fields are deleted.'), | |
|                 'sticky': False, | |
|                 'type': 'success', | |
|                 'next': {'type': 'ir.actions.act_window_close'}, | |
|             } | |
|         }
 | |
| 
 |