@memberjunction/actions-bizapps-lms
Version:
LMS system integration actions for MemberJunction
243 lines (225 loc) • 9.86 kB
text/typescript
import { RegisterClass } from '@memberjunction/global';
import { LearnWorldsBaseAction } from '../learnworlds-base.action';
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
import { BaseAction } from '@memberjunction/actions';
/**
* Action to retrieve all course enrollments for a specific user
*/
(BaseAction, 'GetUserEnrollmentsAction')
export class GetUserEnrollmentsAction extends LearnWorldsBaseAction {
/**
* Get all enrollments for a user
*/
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
const { Params, ContextUser } = params;
this.params = Params; // Set params for base class to use
try {
// Extract and validate parameters
const userId = this.getParamValue(Params, 'UserID');
const status = this.getParamValue(Params, 'Status');
const includeExpired = this.getParamValue(Params, 'IncludeExpired') || false;
const includeCourseDetails = this.getParamValue(Params, 'IncludeCourseDetails') !== false;
const sortBy = this.getParamValue(Params, 'SortBy') || 'enrolled_at';
const sortOrder = this.getParamValue(Params, 'SortOrder') || 'desc';
const maxResults = this.getParamValue(Params, 'MaxResults') || 100;
if (!userId) {
return {
Success: false,
ResultCode: 'VALIDATION_ERROR',
Message: 'UserID is required',
Params
};
}
// Build query parameters
const queryParams: any = {
limit: Math.min(maxResults, 100),
sort: sortBy,
order: sortOrder
};
if (status) {
queryParams.status = status;
}
if (!includeExpired) {
queryParams.hide_expired = true;
}
// Get user enrollments
const enrollmentsData = await this.makeLearnWorldsPaginatedRequest<any>(
`users/${userId}/enrollments`,
queryParams,
ContextUser
);
const enrollments = enrollmentsData || [];
const formattedEnrollments: any[] = [];
// Process each enrollment
for (const enrollment of enrollments) {
const formattedEnrollment: any = {
id: enrollment.id,
courseId: enrollment.course_id,
enrolledAt: enrollment.enrolled_at || enrollment.created_at,
startsAt: enrollment.starts_at,
expiresAt: enrollment.expires_at,
status: enrollment.status || 'active',
progress: {
percentage: enrollment.progress_percentage || 0,
completedUnits: enrollment.completed_units || 0,
totalUnits: enrollment.total_units || 0,
completedLessons: enrollment.completed_lessons || 0,
totalLessons: enrollment.total_lessons || 0,
lastAccessedAt: enrollment.last_accessed_at,
totalTimeSpent: enrollment.total_time_spent || 0,
totalTimeSpentText: this.formatDuration(enrollment.total_time_spent || 0)
},
grade: enrollment.grade,
certificateEligible: enrollment.certificate_eligible || false,
certificateIssuedAt: enrollment.certificate_issued_at,
completedAt: enrollment.completed_at
};
// Get course details if requested
if (includeCourseDetails && enrollment.course_id) {
try {
const course = await this.makeLearnWorldsRequest<any>(
`courses/${enrollment.course_id}`,
'GET',
undefined,
ContextUser
);
formattedEnrollment.course = {
id: course.id,
title: course.title,
description: course.short_description || course.description,
imageUrl: course.image_url,
level: course.level,
duration: course.duration,
durationText: this.formatDuration(course.duration),
instructorName: course.instructor_name,
certificateEnabled: course.certificate_enabled || false
};
} catch (error) {
// Log error but continue processing
console.warn(`Failed to get course details for ${enrollment.course_id}:`, error);
}
}
formattedEnrollments.push(formattedEnrollment);
}
// Calculate summary statistics
const totalEnrollments = formattedEnrollments.length;
const activeEnrollments = formattedEnrollments.filter(e => e.status === 'active').length;
const completedEnrollments = formattedEnrollments.filter(e =>
e.progress.percentage >= 100 || e.completedAt
).length;
const expiredEnrollments = formattedEnrollments.filter(e => e.status === 'expired').length;
const averageProgress = totalEnrollments > 0
? formattedEnrollments.reduce((sum, e) => sum + e.progress.percentage, 0) / totalEnrollments
: 0;
const totalTimeSpent = formattedEnrollments.reduce((sum, e) =>
sum + (e.progress.totalTimeSpent || 0), 0
);
const certificatesEarned = formattedEnrollments.filter(e => e.certificateIssuedAt).length;
// Create summary
const summary = {
userId: userId,
totalEnrollments: totalEnrollments,
activeEnrollments: activeEnrollments,
completedEnrollments: completedEnrollments,
expiredEnrollments: expiredEnrollments,
inProgressEnrollments: activeEnrollments - completedEnrollments,
averageProgressPercentage: Math.round(averageProgress * 100) / 100,
totalTimeSpent: totalTimeSpent,
totalTimeSpentText: this.formatDuration(totalTimeSpent),
certificatesEarned: certificatesEarned,
enrollmentsByStatus: {
active: activeEnrollments,
completed: completedEnrollments,
expired: expiredEnrollments
}
};
// Update output parameters
const outputParams = [...Params];
const enrollmentsParam = outputParams.find(p => p.Name === 'Enrollments');
if (enrollmentsParam) enrollmentsParam.Value = formattedEnrollments;
const totalCountParam = outputParams.find(p => p.Name === 'TotalCount');
if (totalCountParam) totalCountParam.Value = totalEnrollments;
const summaryParam = outputParams.find(p => p.Name === 'Summary');
if (summaryParam) summaryParam.Value = summary;
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Retrieved ${totalEnrollments} enrollments for user`,
Params: outputParams
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return {
Success: false,
ResultCode: 'ERROR',
Message: `Error retrieving enrollments: ${errorMessage}`,
Params
};
}
}
/**
* Define the parameters this action expects
*/
public get Params(): ActionParam[] {
const baseParams = this.getCommonLMSParams();
const specificParams: ActionParam[] = [
{
Name: 'UserID',
Type: 'Input',
Value: null
},
{
Name: 'Status',
Type: 'Input',
Value: null
},
{
Name: 'IncludeExpired',
Type: 'Input',
Value: false
},
{
Name: 'IncludeCourseDetails',
Type: 'Input',
Value: true
},
{
Name: 'SortBy',
Type: 'Input',
Value: 'enrolled_at'
},
{
Name: 'SortOrder',
Type: 'Input',
Value: 'desc'
},
{
Name: 'MaxResults',
Type: 'Input',
Value: 100
},
{
Name: 'Enrollments',
Type: 'Output',
Value: null
},
{
Name: 'TotalCount',
Type: 'Output',
Value: null
},
{
Name: 'Summary',
Type: 'Output',
Value: null
}
];
return [...baseParams, ...specificParams];
}
/**
* Metadata about this action
*/
public get Description(): string {
return 'Retrieves all course enrollments for a specific LearnWorlds user with detailed progress information';
}
}