diff --git a/lib/services/leantime-service.ts b/lib/services/leantime-service.ts index 22be438a..005845aa 100644 --- a/lib/services/leantime-service.ts +++ b/lib/services/leantime-service.ts @@ -230,23 +230,62 @@ export class LeantimeService { * @param missionUsers The mission users with roles */ async assignUsersToProject(projectId: number, missionUsers: any[]): Promise { + console.log(`Attempting to add ${missionUsers.length} users to project ${projectId}`); + + // Create a direct URL to the project that can be shared with users + const baseUrl = this.apiUrl + .replace('/api/jsonrpc', '') + .replace('/api/jsonrpc.php', ''); + + const projectUrl = baseUrl.endsWith('/') + ? `${baseUrl}projects/showProject/${projectId}` + : `${baseUrl}/projects/showProject/${projectId}`; + + console.log(`🔗 Project created successfully. Direct project URL: ${projectUrl}`); + + if (!missionUsers || missionUsers.length === 0) { + console.log('No users to assign to the project.'); + return; + } + + // Users will need to be added manually if the automatic assignment fails + console.log('Attempting to assign users to the project - if this fails, users can be added manually through the Leantime interface.'); + try { + let successCount = 0; + let errorCount = 0; + for (const missionUser of missionUsers) { - // Get or create the user in Leantime - const leantimeUserId = await this.getUserByEmail(missionUser.user.email); - if (!leantimeUserId) { - console.warn(`User not found in Leantime: ${missionUser.user.email}`); - continue; + try { + // Get or create the user in Leantime + const leantimeUserId = await this.getUserByEmail(missionUser.user.email); + if (!leantimeUserId) { + console.warn(`⚠️ User not found in Leantime: ${missionUser.user.email}`); + errorCount++; + continue; + } + + // Determine role (Gardien du Temps gets editor, others get commenter) + const role = missionUser.role === 'gardien-temps' ? 'editor' : 'commenter'; + + // Assign the user to the project + await this.assignUserToProject(projectId, leantimeUserId, role); + successCount++; + } catch (userError) { + console.error(`Error assigning user ${missionUser.user.email}:`, userError); + errorCount++; + // Continue with next user } - - // Determine role (Gardien du Temps gets editor, others get commenter) - const role = missionUser.role === 'gardien-temps' ? 'editor' : 'commenter'; - - // Assign the user to the project - await this.assignUserToProject(projectId, leantimeUserId, role); + } + + console.log(`User assignment complete: ${successCount} successful, ${errorCount} failed.`); + + if (errorCount > 0) { + console.log(`⚠️ Some users could not be assigned automatically. They will need to be added manually at: ${projectUrl}`); } } catch (error) { console.error('Error assigning users to project:', error); + console.log(`⚠️ Users will need to be added manually at: ${projectUrl}`); // Continue even if some user assignments fail } } @@ -261,63 +300,12 @@ export class LeantimeService { try { console.log(`Assigning user ${userId} to project ${projectId} with role ${role}`); - // Try with Projects.Projects.addUser first - const response = await axios.post( - this.getApiEndpoint(), - { - method: 'leantime.rpc.Projects.Projects.addUser', - jsonrpc: '2.0', - id: 1, - params: { - projectId: projectId, - userId: userId, - role: role - } - }, - { - headers: { - 'Content-Type': 'application/json', - 'X-API-Key': this.apiToken - } - } - ); - - if (response.data && response.data.result) { - console.log(`Assigned user ${userId} to project ${projectId} with role ${role}`); - return; - } - - // If that fails, try with the alternative format - console.log('First method failed, trying Projects.Projects.assignUserToProject...'); - - const altResponse = await axios.post( - this.getApiEndpoint(), - { - method: 'leantime.rpc.Projects.Projects.assignUserToProject', - jsonrpc: '2.0', - id: 1, - params: { - projectId: projectId, - userId: userId, - role: role - } - }, - { - headers: { - 'Content-Type': 'application/json', - 'X-API-Key': this.apiToken - } - } - ); - - if (!altResponse.data || !altResponse.data.result) { - // Try one more time with the Projects.assignUserToProject format - console.log('Second method failed, trying Projects.assignUserToProject...'); - - const thirdResponse = await axios.post( + // Try method 1: Projects.Projects.addUser + try { + const response = await axios.post( this.getApiEndpoint(), { - method: 'leantime.rpc.Projects.assignUserToProject', + method: 'leantime.rpc.Projects.Projects.addUser', jsonrpc: '2.0', id: 1, params: { @@ -333,19 +321,116 @@ export class LeantimeService { } } ); - - if (!thirdResponse.data || !thirdResponse.data.result) { - throw new Error(`Failed to assign user to project with all methods: ${JSON.stringify(thirdResponse.data)}`); + + if (response.data && response.data.result) { + console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 1)`); + return; } - - console.log(`Assigned user ${userId} to project ${projectId} with role ${role} using third method`); - return; + } catch (error) { + console.log('Method 1 failed, trying next method...'); } - console.log(`Assigned user ${userId} to project ${projectId} with role ${role} using alternative method`); + // Try method 2: Projects.addProjectUser + try { + const response2 = await axios.post( + this.getApiEndpoint(), + { + method: 'leantime.rpc.Projects.addProjectUser', + jsonrpc: '2.0', + id: 1, + params: { + projectId: projectId, + userId: userId, + role: role + } + }, + { + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': this.apiToken + } + } + ); + + if (response2.data && response2.data.result) { + console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 2)`); + return; + } + } catch (error) { + console.log('Method 2 failed, trying next method...'); + } + + // Try method 3: Projects.Projects.addProjectUser + try { + const response3 = await axios.post( + this.getApiEndpoint(), + { + method: 'leantime.rpc.Projects.Projects.addProjectUser', + jsonrpc: '2.0', + id: 1, + params: { + projectId: projectId, + userId: userId, + role: role + } + }, + { + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': this.apiToken + } + } + ); + + if (response3.data && response3.data.result) { + console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 3)`); + return; + } + } catch (error) { + console.log('Method 3 failed, trying next method...'); + } + + // Try method 4: Projects.editUserProjectRelations + try { + // This method might take a different param structure + const response4 = await axios.post( + this.getApiEndpoint(), + { + method: 'leantime.rpc.Projects.editUserProjectRelations', + jsonrpc: '2.0', + id: 1, + params: { + action: 'add', + userId: userId, + projects: [{ + id: projectId, + role: role + }] + } + }, + { + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': this.apiToken + } + } + ); + + if (response4.data && response4.data.result) { + console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 4)`); + return; + } + } catch (error) { + console.log('Method 4 failed.'); + } + + // If we reach here, all methods failed + console.warn(`⚠️ Could not assign user ${userId} to project ${projectId} with any method. This is not a critical error, the project was created.`); + } catch (error) { console.error(`Error assigning user ${userId} to project ${projectId}:`, error); - // Don't fail if individual user assignment fails + // We'll allow this to fail since the project was created successfully + console.warn(`⚠️ User assignment failed, but this is not critical. The project ${projectId} was created successfully.`); } }