File

apps/recallassess/recallassess-api/src/api/client/participant/participant-activity.service.ts

Description

Service to track and update participant last activity timestamps This keeps Participant.last_login field updated based on various actions

Extends

CLBaseService

Index

Properties
Methods

Methods

Async getInactiveParticipants
getInactiveParticipants(companyId: number, inactiveDays: number)

Get participants who haven't been active for a specified number of days Useful for sending inactivity alerts

Parameters :
Name Type Optional Description
companyId number No
  • Company ID to filter by
inactiveDays number No
  • Number of days of inactivity
Returns : Promise<number[]>

Array of inactive participant IDs

Private Async logActivity
logActivity(participantId: number, activityType: ParticipantActivityType, metadata: Record<string | unknown> | undefined, timestamp: Date)

Future enhancement: Log activity to a separate ActivityLog table This would enable analytics, reporting, and audit trails

Parameters :
Name Type Optional Description
participantId number No
  • Participant ID
activityType ParticipantActivityType No
  • Type of activity
metadata Record<string | unknown> | undefined No
  • Additional activity data
timestamp Date No
  • Activity timestamp
Returns : Promise<void>
Async updateLastActivity
updateLastActivity(participantId: number, activityType: ParticipantActivityType | string, metadata?: Record<string | unknown>)

Update participant's last_login timestamp This is the primary method to call when a participant performs any action

Parameters :
Name Type Optional Description
participantId number No
  • Participant ID
activityType ParticipantActivityType | string No
  • Type of activity being performed (string or enum)
metadata Record<string | unknown> Yes
  • Optional metadata about the activity (for future logging/analytics)
Returns : Promise<void>
Async updateLastActivityBulk
updateLastActivityBulk(participantIds: number[])

Bulk update last activity for multiple participants Useful for batch operations or session refresh

Parameters :
Name Type Optional Description
participantIds number[] No
  • Array of participant IDs
Returns : Promise<void>
Async updateLastActivityOnLogin
updateLastActivityOnLogin(participantId: number, ipAddress?: string, userAgent?: string)

Update last activity on login Special handler for login events

Parameters :
Name Type Optional Description
participantId number No
  • Participant ID
ipAddress string Yes
  • Optional IP address for security tracking
userAgent string Yes
  • Optional user agent string
Returns : Promise<void>
Protected buildCompanyWhere
buildCompanyWhere(companyId: number, additionalWhere?: Record)
Inherited from CLBaseService
Defined in CLBaseService:82

Build base WHERE clause with company scope Ensures all queries are scoped to the user's company

Parameters :
Name Type Optional Description
companyId number No
  • Company ID to scope queries to
additionalWhere Record<string | any> Yes
  • Additional where conditions to merge
Returns : Record<string, any>

Complete where clause object

Protected buildSearchWhere
buildSearchWhere(searchFields: string[], searchQuery?: string)
Inherited from CLBaseService
Defined in CLBaseService:64

Build a WHERE clause for search functionality Creates OR conditions for multiple fields

Parameters :
Name Type Optional Description
searchFields string[] No
  • Array of field names to search in
searchQuery string Yes
  • Search query string
Returns : [] | undefined

Array of search conditions or undefined if no query

Protected Async findByIdWithCompanyScope
findByIdWithCompanyScope(entityName: string, entityId: number, companyId: number)
Inherited from CLBaseService
Defined in CLBaseService:111

Find entity by ID with company scope verification Common pattern: get entity and ensure it belongs to the company

Parameters :
Name Type Optional Description
entityName string No
  • Prisma model name
entityId number No
  • Entity ID
companyId number No
  • Company ID to verify ownership
Returns : Promise<any | null>

Entity if found and belongs to company, null otherwise

Protected getRepo
getRepo(repoName: string)
Inherited from CLBaseService
Defined in CLBaseService:96

Get a Prisma repository (table) dynamically Useful for generic operations across different entities

Parameters :
Name Type Optional Description
repoName string No
  • The name of the Prisma repository (table)
Returns : any

The Prisma repository instance

Protected toDto
toDto(entity: any, dtoClass: unknown)
Inherited from CLBaseService
Defined in CLBaseService:20
Type parameters :
  • TDto

Transform database entity to DTO using class-transformer

Parameters :
Name Type Optional Description
entity any No
  • Raw database entity
dtoClass unknown No
  • DTO class constructor
Returns : TDto

Transformed DTO instance

Protected toDtoArray
toDtoArray(entities: any[], dtoClass: unknown)
Inherited from CLBaseService
Defined in CLBaseService:30
Type parameters :
  • TDto

Transform array of database entities to DTOs

Parameters :
Name Type Optional Description
entities any[] No
  • Array of raw database entities
dtoClass unknown No
  • DTO class constructor
Returns : TDto[]

Array of transformed DTO instances

Protected Async verifyCompanyOwnership
verifyCompanyOwnership(entityName: string, entityId: number, companyId: number)
Inherited from CLBaseService
Defined in CLBaseService:42

Verify that an entity belongs to a specific company Common security check to prevent cross-company data access

Parameters :
Name Type Optional Description
entityName string No
  • Prisma model name (e.g., 'participant', 'participantGroup')
entityId number No
  • Entity ID to check
companyId number No
  • Company ID to verify ownership
Returns : Promise<boolean>

True if entity belongs to company, false otherwise

Properties

Protected Readonly prisma
Type : BNestPrismaService
Decorators :
@Inject()
Inherited from CLBaseService
Defined in CLBaseService:12
import { CLBaseService } from "@api/shared/services";
import { Injectable } from "@nestjs/common";

/**
 * Enum for different types of participant activities
 * Used to track when participants perform various actions in the system
 */
export enum ParticipantActivityType {
  // Invitation & Onboarding
  INVITATION_ACCEPTED = "invitation_accepted",
  ACCOUNT_ACTIVATED = "account_activated",
  PASSWORD_SET = "password_set",

  // E-Learning Activities
  COURSE_STARTED = "course_started",
  COURSE_MODULE_STARTED = "course_module_started",
  COURSE_MODULE_PAGE_VIEWED = "course_module_page_viewed",
  COURSE_MODULE_COMPLETED = "course_module_completed",
  COURSE_COMPLETED = "course_completed",

  // Assessment Activities
  PRE_BAT_STARTED = "pre_bat_started",
  PRE_BAT_QUESTION_ANSWERED = "pre_bat_question_answered",
  PRE_BAT_COMPLETED = "pre_bat_completed",
  POST_BAT_STARTED = "post_bat_started",
  POST_BAT_QUESTION_ANSWERED = "post_bat_question_answered",
  POST_BAT_COMPLETED = "post_bat_completed",

  // Knowledge Review Activities
  KNOWLEDGE_REVIEW_STARTED = "knowledge_review_started",
  KNOWLEDGE_REVIEW_ANSWERED = "knowledge_review_answered",
  KNOWLEDGE_REVIEW_COMPLETED = "knowledge_review_completed",

  // Report Activities
  REPORT_VIEWED = "report_viewed",
  REPORT_DOWNLOADED = "report_downloaded",

  // Profile & Settings
  PROFILE_UPDATED = "profile_updated",
  SETTINGS_UPDATED = "settings_updated",

  // Authentication
  LOGIN = "login",
  LOGOUT = "logout",

  // General Activity
  SESSION_ACTIVE = "session_active", // For periodic pings to show user is active
}

/**
 * Service to track and update participant last activity timestamps
 * This keeps Participant.last_login field updated based on various actions
 */
@Injectable()
export class CLParticipantActivityService extends CLBaseService {
  /**
   * Update participant's last_login timestamp
   * This is the primary method to call when a participant performs any action
   *
   * @param participantId - Participant ID
   * @param activityType - Type of activity being performed (string or enum)
   * @param metadata - Optional metadata about the activity (for future logging/analytics)
   */
  async updateLastActivity(
    participantId: number,
    activityType: ParticipantActivityType | string,
    metadata?: Record<string, unknown>,
  ): Promise<void> {
    const now = new Date();

    // Update the participant's last_login field
    await this.prisma.client.participant.update({
      where: { id: participantId },
      data: {
        last_login: now,
      },
    });

    // TODO: Future enhancement - Log activity to ActivityLog table for analytics
    // await this.logActivity(participantId, activityType, metadata, now);
  }

  /**
   * Bulk update last activity for multiple participants
   * Useful for batch operations or session refresh
   *
   * @param participantIds - Array of participant IDs
   */
  async updateLastActivityBulk(participantIds: number[]): Promise<void> {
    const now = new Date();

    await this.prisma.client.participant.updateMany({
      where: {
        id: {
          in: participantIds,
        },
      },
      data: {
        last_login: now,
      },
    });
  }

  /**
   * Get participants who haven't been active for a specified number of days
   * Useful for sending inactivity alerts
   *
   * @param companyId - Company ID to filter by
   * @param inactiveDays - Number of days of inactivity
   * @returns Array of inactive participant IDs
   */
  async getInactiveParticipants(companyId: number, inactiveDays: number): Promise<number[]> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - inactiveDays);

    const inactiveParticipants = await this.prisma.client.participant.findMany({
      where: {
        company_id: companyId,
        is_active: true,
        last_login: {
          lt: cutoffDate,
        },
      },
      select: {
        id: true,
      },
    });

    return inactiveParticipants.map((p) => p.id);
  }

  /**
   * Update last activity on login
   * Special handler for login events
   *
   * @param participantId - Participant ID
   * @param ipAddress - Optional IP address for security tracking
   * @param userAgent - Optional user agent string
   */
  async updateLastActivityOnLogin(participantId: number, ipAddress?: string, userAgent?: string): Promise<void> {
    await this.updateLastActivity(participantId, ParticipantActivityType.LOGIN, {
      ip_address: ipAddress,
      user_agent: userAgent,
    });
  }

  /**
   * Future enhancement: Log activity to a separate ActivityLog table
   * This would enable analytics, reporting, and audit trails
   *
   * @param participantId - Participant ID
   * @param activityType - Type of activity
   * @param metadata - Additional activity data
   * @param timestamp - Activity timestamp
   */
  private async logActivity(
    participantId: number,
    activityType: ParticipantActivityType,
    metadata: Record<string, unknown> | undefined,
    timestamp: Date,
  ): Promise<void> {
    // TODO: Implement when ActivityLog table is created
    // await this.prisma.client.activityLog.create({
    //   data: {
    //     participant_id: participantId,
    //     activity_type: activityType,
    //     metadata: metadata ? JSON.stringify(metadata) : null,
    //     created_at: timestamp,
    //   },
    // });
  }
}

results matching ""

    No results matching ""