|
|
@@ -275,16 +275,22 @@ class CrmLead(models.Model):
|
|
|
|
|
|
_logger.info(f"🔍 Checking for existing folder '{folder_name}' in parent {parent_folder_id}")
|
|
|
|
|
|
- folder_id = drive_service.create_or_get_folder(parent_folder_id, folder_name)
|
|
|
-
|
|
|
- # Check if it was reused or created
|
|
|
+ # First check if folder already exists
|
|
|
existing_folders = drive_service.find_folders_by_name(parent_folder_id, f'^{folder_name}$')
|
|
|
was_reused = len(existing_folders) > 0
|
|
|
|
|
|
if was_reused:
|
|
|
+ folder_id = existing_folders[0]['id']
|
|
|
_logger.info(f"🔄 REUSING existing folder '{folder_name}' (ID: {folder_id})")
|
|
|
else:
|
|
|
- _logger.info(f"📁 CREATED new folder '{folder_name}' (ID: {folder_id})")
|
|
|
+ # Create new folder
|
|
|
+ result = drive_service.create_folder(folder_name, parent_folder_id)
|
|
|
+ if result.get('success'):
|
|
|
+ folder_id = result.get('folder_id')
|
|
|
+ _logger.info(f"📁 CREATED new folder '{folder_name}' (ID: {folder_id})")
|
|
|
+ else:
|
|
|
+ error_msg = result.get('error', 'Unknown error')
|
|
|
+ raise UserError(_('Failed to create Google Drive folder "%s": %s') % (folder_name, error_msg))
|
|
|
|
|
|
return folder_id, was_reused
|
|
|
|
|
|
@@ -440,55 +446,100 @@ class CrmLead(models.Model):
|
|
|
)
|
|
|
|
|
|
def _rename_entire_folder_structure(self, old_components=None, new_components=None):
|
|
|
- """Unified method to rename folder structure"""
|
|
|
+ """Unified method to rename folder structure with robust error handling"""
|
|
|
if not self.google_drive_folder_id:
|
|
|
return
|
|
|
|
|
|
- # Get current structure if needed
|
|
|
- if old_components is None and new_components is not None:
|
|
|
- current_structure = self._analyze_crm_folder_structure(self.google_drive_folder_id)
|
|
|
- if not current_structure:
|
|
|
- raise UserError(_('Could not analyze current folder structure'))
|
|
|
+ try:
|
|
|
+ drive_service = self.env['google.drive.service']
|
|
|
|
|
|
- old_components = {
|
|
|
- 'primary_name': current_structure.get('primary_folder', {}).get('name', ''),
|
|
|
- 'year': current_structure.get('year_folder', {}).get('name', ''),
|
|
|
- 'opportunity_name': current_structure.get('opportunity_folder', {}).get('name', '')
|
|
|
- }
|
|
|
-
|
|
|
- # Get new components if needed
|
|
|
- if new_components is None and old_components is not None:
|
|
|
- new_components = self._get_folder_name_components()
|
|
|
-
|
|
|
- drive_service = self.env['google.drive.service']
|
|
|
- current_folder_id = self.google_drive_folder_id
|
|
|
-
|
|
|
- # Navigate up to find primary folder
|
|
|
- primary_folder_id = self._find_primary_folder_id_crm(current_folder_id)
|
|
|
- if not primary_folder_id:
|
|
|
- raise UserError(_('Cannot find primary folder in the structure'))
|
|
|
-
|
|
|
- # Rename folders if needed
|
|
|
- if old_components['primary_name'] != new_components['primary_name']:
|
|
|
- result = drive_service.rename_folder(primary_folder_id, new_components['primary_name'])
|
|
|
- if not result.get('success'):
|
|
|
- raise UserError(_('Failed to rename primary folder: %s') % result.get('error', 'Unknown error'))
|
|
|
-
|
|
|
- if old_components['year'] != new_components['year']:
|
|
|
- year_folder_id = self._find_year_folder_id_crm(primary_folder_id, old_components['year'])
|
|
|
- if year_folder_id:
|
|
|
- result = drive_service.rename_folder(year_folder_id, new_components['year'])
|
|
|
- if not result.get('success'):
|
|
|
- raise UserError(_('Failed to rename year folder: %s') % result.get('error', 'Unknown error'))
|
|
|
-
|
|
|
- if old_components['opportunity_name'] != new_components['opportunity_name']:
|
|
|
- result = drive_service.rename_folder(current_folder_id, new_components['opportunity_name'])
|
|
|
- if not result.get('success'):
|
|
|
- raise UserError(_('Failed to rename opportunity folder: %s') % result.get('error', 'Unknown error'))
|
|
|
+ _logger.info(f"🔄 Starting folder structure rename for opportunity {self.id}")
|
|
|
+
|
|
|
+ # First validate that the current folder exists
|
|
|
+ validation = drive_service.validate_folder_id(self.google_drive_folder_id)
|
|
|
+ if not validation.get('valid'):
|
|
|
+ _logger.warning(f"Cannot rename folder {self.google_drive_folder_id}: folder not found or not accessible")
|
|
|
+ raise UserError(_('Cannot rename folder: folder not found or not accessible'))
|
|
|
+
|
|
|
+ # Get current structure if needed
|
|
|
+ if old_components is None and new_components is not None:
|
|
|
+ current_structure = self._analyze_crm_folder_structure(self.google_drive_folder_id)
|
|
|
+ if not current_structure:
|
|
|
+ raise UserError(_('Could not analyze current folder structure'))
|
|
|
+
|
|
|
+ old_components = {
|
|
|
+ 'primary_name': current_structure.get('primary_folder', {}).get('name', ''),
|
|
|
+ 'year': current_structure.get('year_folder', {}).get('name', ''),
|
|
|
+ 'opportunity_name': current_structure.get('opportunity_folder', {}).get('name', '')
|
|
|
+ }
|
|
|
+
|
|
|
+ # Get new components if needed
|
|
|
+ if new_components is None and old_components is not None:
|
|
|
+ new_components = self._get_folder_name_components()
|
|
|
+
|
|
|
+ current_folder_id = self.google_drive_folder_id
|
|
|
+
|
|
|
+ # SOLUCIÓN ROBUSTA: En lugar de buscar el primary folder, vamos a recrear la estructura
|
|
|
+ # Esto evita problemas con folders que ya no existen
|
|
|
+ _logger.info(f"🔄 Using robust approach: recreating folder structure")
|
|
|
+
|
|
|
+ # Get company root folder
|
|
|
+ company_root_folder_id = self._get_company_root_folder_id()
|
|
|
+ if not company_root_folder_id:
|
|
|
+ raise UserError(_('Company root folder not configured'))
|
|
|
+
|
|
|
+ # Create new structure with new components
|
|
|
+ _logger.info(f"🔄 Creating new folder structure with components: {new_components}")
|
|
|
+
|
|
|
+ # Create primary folder
|
|
|
+ new_primary_folder_id, was_reused = self._create_or_get_folder_crm(company_root_folder_id, new_components['primary_name'])
|
|
|
+ _logger.info(f"✅ Primary folder created/found: {new_primary_folder_id}")
|
|
|
+
|
|
|
+ # Create year folder
|
|
|
+ new_year_folder_id, was_reused = self._create_or_get_folder_crm(new_primary_folder_id, new_components['year'])
|
|
|
+ _logger.info(f"✅ Year folder created/found: {new_year_folder_id}")
|
|
|
+
|
|
|
+ # Validate current opportunity folder exists before moving
|
|
|
+ _logger.info(f"🔍 Validating current opportunity folder: {current_folder_id}")
|
|
|
+ current_validation = drive_service.validate_folder_id(current_folder_id)
|
|
|
+ if not current_validation.get('valid'):
|
|
|
+ _logger.warning(f"⚠️ Current opportunity folder {current_folder_id} is not accessible: {current_validation.get('error')}")
|
|
|
+ # If folder doesn't exist, we need to create a new one
|
|
|
+ _logger.info(f"🔄 Creating new opportunity folder in the correct structure")
|
|
|
+
|
|
|
+ # Create new opportunity folder with correct name
|
|
|
+ new_opportunity_folder_id, was_reused = self._create_or_get_folder_crm(new_year_folder_id, new_components['opportunity_name'])
|
|
|
+
|
|
|
+ # Update the stored folder ID to the new folder
|
|
|
+ self.with_context(skip_google_drive_update=True).write({
|
|
|
+ 'google_drive_folder_id': new_opportunity_folder_id,
|
|
|
+ 'google_drive_folder_name': self._build_structure_string(new_components)
|
|
|
+ })
|
|
|
+
|
|
|
+ _logger.info(f"✅ Created new opportunity folder: {new_opportunity_folder_id}")
|
|
|
+ return
|
|
|
+
|
|
|
+ # Move current opportunity folder to new structure
|
|
|
+ _logger.info(f"🔄 Moving opportunity folder from old structure to new structure")
|
|
|
+ move_result = drive_service.move_folder(current_folder_id, new_year_folder_id)
|
|
|
+
|
|
|
+ if not move_result.get('success'):
|
|
|
+ _logger.error(f"❌ Failed to move opportunity folder: {move_result.get('error')}")
|
|
|
+ raise UserError(_('Failed to move opportunity folder: %s') % move_result.get('error', 'Unknown error'))
|
|
|
|
|
|
+ _logger.info(f"✅ Successfully moved opportunity folder to new structure")
|
|
|
+
|
|
|
+ # Update the stored folder information
|
|
|
+ new_structure = self._build_structure_string(new_components)
|
|
|
self.with_context(skip_google_drive_update=True).write({
|
|
|
- 'google_drive_folder_name': new_components['opportunity_name']
|
|
|
+ 'google_drive_folder_name': new_structure
|
|
|
})
|
|
|
+
|
|
|
+ _logger.info(f"✅ Folder structure rename completed successfully")
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ _logger.error(f"Error renaming folder structure: {str(e)}")
|
|
|
+ raise
|
|
|
|
|
|
def _move_folder_to_new_company(self, new_company_id):
|
|
|
"""Move only this opportunity's folder to new company"""
|
|
|
@@ -499,15 +550,25 @@ class CrmLead(models.Model):
|
|
|
new_root_folder_id = new_company.google_drive_crm_folder_id
|
|
|
|
|
|
if not new_root_folder_id:
|
|
|
- self.message_post(
|
|
|
+ self.message_post(
|
|
|
body=_("⚠️ No se puede mover: Nueva empresa no tiene Google Drive configurado."),
|
|
|
- message_type='comment'
|
|
|
- )
|
|
|
- return
|
|
|
+ message_type='comment'
|
|
|
+ )
|
|
|
+ return
|
|
|
|
|
|
try:
|
|
|
drive_service = self.env['google.drive.service']
|
|
|
|
|
|
+ # First validate that the current folder exists
|
|
|
+ validation = drive_service.validate_folder_id(self.google_drive_folder_id)
|
|
|
+ if not validation.get('valid'):
|
|
|
+ _logger.warning(f"Cannot move folder {self.google_drive_folder_id}: folder not found or not accessible")
|
|
|
+ self.message_post(
|
|
|
+ body=_("⚠️ No se puede mover: La carpeta actual no existe o no es accesible."),
|
|
|
+ message_type='comment'
|
|
|
+ )
|
|
|
+ return
|
|
|
+
|
|
|
# Get current opportunity folder components
|
|
|
current_components = self._get_folder_name_components()
|
|
|
|
|
|
@@ -533,7 +594,11 @@ class CrmLead(models.Model):
|
|
|
|
|
|
except Exception as e:
|
|
|
_logger.error(f"Error moviendo folder: {str(e)}")
|
|
|
- raise
|
|
|
+ # Don't raise the exception, just log it and continue
|
|
|
+ self.message_post(
|
|
|
+ body=_("⚠️ Error moviendo carpeta: %s") % str(e),
|
|
|
+ message_type='comment'
|
|
|
+ )
|
|
|
|
|
|
# ============================================================================
|
|
|
# MÉTODOS ESPECÍFICOS DE CRM
|
|
|
@@ -543,20 +608,43 @@ class CrmLead(models.Model):
|
|
|
"""Find the primary folder (company/contact level) in the hierarchy"""
|
|
|
try:
|
|
|
drive_service = self.env['google.drive.service']
|
|
|
+
|
|
|
+ _logger.info(f"🔍 Finding primary folder starting from: {start_folder_id}")
|
|
|
+
|
|
|
+ # First validate the start folder exists
|
|
|
+ validation = drive_service.validate_folder_id(start_folder_id)
|
|
|
+ if not validation.get('valid'):
|
|
|
+ _logger.error(f"❌ Start folder {start_folder_id} is not valid: {validation.get('error')}")
|
|
|
+ return None
|
|
|
+
|
|
|
hierarchy = drive_service.navigate_folder_hierarchy(start_folder_id, max_levels=5)
|
|
|
+ _logger.info(f"📁 Hierarchy found: {len(hierarchy)} levels")
|
|
|
|
|
|
for folder_info in hierarchy:
|
|
|
folder_name = folder_info.get('name', '')
|
|
|
level = folder_info.get('level', 0)
|
|
|
+ folder_id = folder_info.get('id', '')
|
|
|
+
|
|
|
+ _logger.info(f"📂 Level {level}: {folder_name} (ID: {folder_id})")
|
|
|
|
|
|
if level == 0:
|
|
|
continue
|
|
|
|
|
|
if not folder_name.isdigit() and folder_name not in ['Meets', 'Archivos cliente']:
|
|
|
- year_folders = drive_service.find_folders_by_name(folder_info['id'], r'^\d{4}$')
|
|
|
+ # Validate this folder exists before checking its children
|
|
|
+ folder_validation = drive_service.validate_folder_id(folder_id)
|
|
|
+ if not folder_validation.get('valid'):
|
|
|
+ _logger.warning(f"⚠️ Folder {folder_id} ({folder_name}) is not accessible, skipping")
|
|
|
+ continue
|
|
|
+
|
|
|
+ year_folders = drive_service.find_folders_by_name(folder_id, r'^\d{4}$')
|
|
|
if year_folders:
|
|
|
- return folder_info['id']
|
|
|
+ _logger.info(f"✅ Found primary folder: {folder_name} (ID: {folder_id})")
|
|
|
+ return folder_id
|
|
|
+ else:
|
|
|
+ _logger.info(f"ℹ️ Folder {folder_name} has no year folders, not primary")
|
|
|
|
|
|
+ _logger.warning(f"❌ No primary folder found in hierarchy")
|
|
|
return None
|
|
|
except Exception as e:
|
|
|
_logger.error(f"Error finding primary folder (CRM): {str(e)}")
|
|
|
@@ -766,13 +854,26 @@ class CrmLead(models.Model):
|
|
|
raise UserError(_('No Google Drive folder exists for this opportunity.'))
|
|
|
|
|
|
try:
|
|
|
+ # Add detailed diagnostic information
|
|
|
+ _logger.info(f"🔍 Analyzing folder structure for opportunity {self.id} (ID: {self.name})")
|
|
|
+ _logger.info(f"📁 Current folder ID: {self.google_drive_folder_id}")
|
|
|
+
|
|
|
expected_components = self._get_folder_name_components()
|
|
|
+ _logger.info(f"📋 Expected components: {expected_components}")
|
|
|
+
|
|
|
+ # Test folder validation first
|
|
|
+ drive_service = self.env['google.drive.service']
|
|
|
+ validation = drive_service.validate_folder_id(self.google_drive_folder_id)
|
|
|
+ _logger.info(f"✅ Folder validation result: {validation}")
|
|
|
+
|
|
|
current_structure = self._analyze_crm_folder_structure(self.google_drive_folder_id)
|
|
|
+ _logger.info(f"📊 Current structure analysis: {current_structure}")
|
|
|
|
|
|
if not current_structure:
|
|
|
# Provide a more helpful error message
|
|
|
error_msg = f"<strong>❌ Cannot Analyze Folder Structure</strong><br/><br/>"
|
|
|
error_msg += f"<strong>Folder ID:</strong> {self.google_drive_folder_id}<br/>"
|
|
|
+ error_msg += f"<strong>Validation Result:</strong> {validation}<br/>"
|
|
|
error_msg += f"<strong>Possible Issues:</strong><br/>"
|
|
|
error_msg += f"• Folder may not exist or be accessible<br/>"
|
|
|
error_msg += f"• Insufficient permissions to access the folder<br/>"
|