All files / referral referral.service.ts

100% Statements 41/41
100% Branches 14/14
100% Functions 10/10
100% Lines 39/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146          18x 18x 18x 18x   18x         18x           18x   34x 34x 34x 34x 34x 34x                           7x 7x   7x 6x   6x 5x 4x         1x     1x     1x                     13x   13x 12x       1x                     14x   14x 13x           1x                     4x       4x   4x 3x   3x   1x                   2x                     1x      
/**
 * Referral service.
 * @packageDocumentation
 */
 
import { Injectable, Inject, forwardRef } from '@nestjs/common';
import { DBService } from '../db/db.service';
import { ResourceService } from '../resource/resource.service';
import { UserService } from '../user/user.service';
import { NBReferral } from './referral.interface';
import { ServiceException } from '../service.exception';
 
/**
 * Referral table name.
 */
export const referralTableName = 'NB_REFERRAL';
 
/**
 * Referral table service.
 */
@Injectable()
export class ReferralService {
  constructor(
    @Inject(forwardRef(() => DBService))
    private readonly dbService: DBService,
    @Inject(forwardRef(() => ResourceService))
    private readonly resourceService: ResourceService,
    @Inject(forwardRef(() => UserService))
    private readonly userService: UserService,
  ) {}
 
  /**
   * Refer a user.
   *
   * @param userID The user's ID.
   * @param newUserID The new user's ID.
   * @returns The new referral record.
   */
  public async referUser(
    userID: string,
    newUserID: string,
  ): Promise<NBReferral> {
    const userExists = await this.userService.userExists(userID);
    const newUserExists = await this.userService.userExists(newUserID);
 
    if (userExists && newUserExists) {
      const referral = await this.getReferral(newUserID);
 
      if (!referral) {
        if (userID !== newUserID) {
          return this.dbService.create<NBReferral>(referralTableName, {
            userID,
            newUserID,
          });
        } else {
          throw new ServiceException('Users cannot refer themselves');
        }
      } else {
        throw new ServiceException('A user has already referred');
      }
    } else {
      throw new ServiceException('User does not exist');
    }
  }
 
  /**
   * Get the referral record for a user, or undefined if they did not refer someone.
   *
   * @param newUserID The new user's ID.
   * @returns The referral record.
   */
  public async getReferral(newUserID: string): Promise<NBReferral | undefined> {
    const newUserExists = await this.userService.userExists(newUserID);
 
    if (newUserExists) {
      return this.dbService.getByFields<NBReferral>(referralTableName, {
        newUserID,
      });
    } else {
      throw new ServiceException('User does not exist');
    }
  }
 
  /**
   * Get all referral records associated with a user.
   *
   * @param userID The user's ID.
   * @returns All referral records associated with the user.
   */
  public async getReferrals(userID: string): Promise<NBReferral[]> {
    const userExists = await this.userService.userExists(userID);
 
    if (userExists) {
      return this.dbService.listByFields<NBReferral>(
        referralTableName,
        { userID },
        { fieldName: 'referTime', sortOrder: 'ASC' },
      );
    } else {
      throw new ServiceException('User does not exist');
    }
  }
 
  /**
   * Determine whether or not a user has reached the referral threshold.
   *
   * @param userID The user's ID.
   * @returns Whether or not the user has reached the referral threshold.
   */
  public async reachedReferralThreshold(userID: string): Promise<boolean> {
    const referralThreshold = await this.resourceService.getResource<number>(
      'REFERRAL_THRESHOLD',
    );
 
    const userExists = await this.userService.userExists(userID);
 
    if (userExists) {
      const referrals = await this.getReferrals(userID);
 
      return referrals.length >= referralThreshold;
    } else {
      throw new ServiceException('User does not exist');
    }
  }
 
  /**
   * Delete a user's referral record.
   *
   * @param newUserID The new user's ID.
   */
  public async deleteReferral(newUserID: string): Promise<void> {
    await this.dbService.deleteByFields(referralTableName, {
      newUserID,
    });
  }
 
  /**
   * Delete all referral records associated with a user.
   *
   * @param userID The user's ID.
   */
  public async deleteUserReferrals(userID: string): Promise<void> {
    await this.dbService.deleteByFields(referralTableName, { userID });
  }
}