Name

sn_entitlement.SubscriptionService

Description

No description available

Script

/**
* Functions that calculate the derived values for subscriptions (e.g. unallocated users, unallocated groups, stats, etc)
*/
var SubscriptionService = Class.create();
SubscriptionService.prototype = {
  /**
   * @param {bool} oobRolesOnly A boolean flag that filters the roles to out-of-box roles when true.
   */
  initialize: function(oobRolesOnly = false) {
      this._oobRolesOnly = oobRolesOnly;

      this._logSourceName = `sn_entitlement.${this.type}`;

      this._userDao = new sn_entitlement.UserDao();
      this._userGroupDao = new sn_entitlement.UserGroupDao();
      this._contextFactory = new sn_entitlement.UnallocatedEntityCalculation_ContextFactory(oobRolesOnly);
  },

  /**
   * Retrieves an array of objects containing all of the unallocated users for each active subscription
   *
   * @returns {stream} A stream of objects that contain the unallocated users per subscription
   */
  getUnallocatedUserCalculationsByAllSubscriptions: function() {
      // Note: For performance reasons, it is better to calculate the global set of unallocated users
      //    and then determine which subscriptions they are unallocated for than calling the 
      //    getUnallocatedUsersBySubscriptionId(subscriptionId) as it has to calculate the unallocation
      //    data for all users on each call.

      const subscriptionContext = this._contextFactory.createSubscriptionContext();

      const userIds = this._getUserIdsThatHaveARoleThatRequiresASubscription();
      gs.info(`${this._logSourceName}: Calculating unallocated status for ${userIds.length} users`);

      return global.Stream.fromArray(userIds)
          .map(userId => this._contextFactory.createUserContext(userId, subscriptionContext))
          .map(userContext => new sn_entitlement.UnallocatedEntityCalculation(subscriptionContext, userContext))
          .map(calculation => calculation.calculateUnallocatedData())
          .filter(calculation => this._hasAnAllocatedOrUnallocatedSubscriptionReference(calculation));
  },

  /**
   * Retrieves an array of unallocated user objects for the provided subscriptionId
   *
   * @param {guid} subscriptionId The subscription_entitlement.sys_id value to identify unallocated users for.
   * @returns {stream} A stream of UnallocatedUser objects for the unallocated users of this subscription
   */
  getUnallocatedUserCalculationsBySubscriptionId: function(subscriptionId) {
      if (!subscriptionId || subscriptionId.trim().length === 0)
          return [];

      // Note: Since the calculation for unallocated users per subscription or globally is the same
      //    all that needs to be done in this function is get the super-set of unallocated users
      //    and filter down to the set that are unallocated for the required subscription
      return this.getUnallocatedUserCalculationsByAllSubscriptions()
          .filter(data => data.unallocated_subscription_ids.indexOf(subscriptionId) > -1);
  },

  /**
   * Retrieves an unallocated user calculation object for the provided userId
   * This function will return an object for any valid user whether it is unallocated or not.
   *
   * @param {guid} userId The sys_user.sys_id value to identify the user by.
   * @returns {object} An unallocated user calculation object for the user. Null if the user doesn't exist.
   */
  getUnallocatedUserCalculationByUserId: function(userId) {
      if (!this._userDao.getUserIdIsActive(userId))
          return null;

      const subscriptionContext = this._contextFactory.createSubscriptionContext();
      const userContext = this._contextFactory.createUserContext(userId);
      const calculation = new sn_entitlement.UnallocatedEntityCalculation(subscriptionContext, userContext);
      return calculation.calculateUnallocatedData();
  },

  /**
   * Retrieves an array of objects containing all of the unallocated groups for each active subscription
   *
   * @returns {stream} A stream of objects that contain the unallocated groups per subscription
   */
  getUnallocatedGroupCalculationsByAllSubscriptions: function() {
      const subscriptionContext = this._contextFactory.createSubscriptionContext();

      const groupIds = this._getGroupIdsThatHaveARoleThatRequiresASubscription();
      gs.info(`${this._logSourceName}: Calculating unallocated status for ${groupIds.length} groups`);

      return global.Stream.fromArray(groupIds)
          .map(groupId => this._contextFactory.createGroupContext(groupId, subscriptionContext))
          .map(groupContext => new sn_entitlement.UnallocatedEntityCalculation(subscriptionContext, groupContext))
          .map(calculation => calculation.calculateUnallocatedData())
          .filter(calculation => this._hasAnAllocatedOrUnallocatedSubscriptionReference(calculation));
  },

  /**
   * Retrieves an array of unallocated group objects for the provided subscriptionId
   *
   * @param {guid} subscriptionId The subscription_entitlement.sys_id value to identify unallocated users for.
   * @returns {stream} A stream of UnallocatedUser objects for the unallocated users of this subscription
   */
  getUnallocatedGroupCalculationsBySubscriptionId: function(subscriptionId) {
      if (!subscriptionId || subscriptionId.trim().length === 0)
          return [];

      return this.getUnallocatedGroupCalculationsByAllSubscriptions()
          .filter(data => data.unallocated_subscription_ids.indexOf(subscriptionId) > -1);
  },

  /**
   * Retrieves an unallocated group calculation object for the provided groupId
   * This function will return an object for any valid group whether it is unallocated or not.
   *
   * @param {guid} groupId The sys_user_group.sys_id value to identify the group by.
   * @returns {object} An unallocated group calculation object for the group. Null if the group doesn't exist.
   */
  getUnallocatedGroupCalculationByGroupId: function(groupId) {
      if (!this._userGroupDao.getGroupIdIsActive(groupId))
          return null;

      const subscriptionContext = this._contextFactory.createSubscriptionContext();
      const groupContext = this._contextFactory.createGroupContext(groupId);
      const calculation = new sn_entitlement.UnallocatedEntityCalculation(subscriptionContext, groupContext);
      return calculation.calculateUnallocatedData();
  },

  /**
   * Retrieves the number of users the subscription service will process when calling getUnallocatedUserCalculationsByAllSubscriptions()
   */
  getUserCountByNeedsToBeProcessed: function() {
      return this._getUserIdsThatHaveARoleThatRequiresASubscription().length;
  },

  /**
   * Retrieves the number of groups the subscription service will process when calling getUnallocatedGroupCalculationsByAllSubscriptions()
   */
  getGroupCountByNeedsToBeProcessed: function() {
      return this._getGroupIdsThatHaveARoleThatRequiresASubscription().length;
  },

  /**
   * Determines if the calculation results in at least one allocated or unallocated subscription.
   * In normal scenarios, it is expected that unallocated calculations will always result in at least
   * one subscription mapping (either allocated or unallocated) since a licensable role requires a subscription
   * however, with the special cases of UU and Module behavior, we may process a user that has 100% of
   * their licensable roles fulfilled by UU and/or Module and thus not produce a subscription relationship.
   * These users/groups should be ignored.
   */
  _hasAnAllocatedOrUnallocatedSubscriptionReference: function(entityAllocationData) {
      return entityAllocationData &&
          (entityAllocationData.allocated_subscription_ids && entityAllocationData.allocated_subscription_ids.length > 0 ||
              entityAllocationData.unallocated_subscription_ids && entityAllocationData.unallocated_subscription_ids.length > 0);
  },

  /**
   * Retrieves an array of user ids (sys_user.sys_id) that have at least one role that requires
   * a subscription.
   *
   * @returns {array} An array of sys_user.sys_id values
   */
  _getUserIdsThatHaveARoleThatRequiresASubscription: function() {
      const roleIdsThatRequireASubscription = this._contextFactory
          .createSubscriptionContext()
          .getRoleIdsByRequiresASubscription();

      gs.info(`${this._logSourceName}: ${roleIdsThatRequireASubscription.length} metered roleIds detected`);

      return this._userDao.getUserIdsByActiveAndHasRole(roleIdsThatRequireASubscription);
  },

  /**
   * Retrieves an array of group ids (sys_user_group.sys_id) that have at least one role that requires a subscription
   *
   * @returns {array} An array of sys_user_role.sys_id values
   */
  _getGroupIdsThatHaveARoleThatRequiresASubscription: function() {
      const roleIdsThatRequireASubscription = this._contextFactory
          .createSubscriptionContext()
          .getRoleIdsByRequiresASubscription();

      gs.info(`${this._logSourceName}: ${roleIdsThatRequireASubscription.length} metered roleIds detected`);

      return this._userGroupDao.getGroupIdsByActiveAndHasRole(roleIdsThatRequireASubscription);
  },

  type: 'SubscriptionService'
};

Sys ID

34c54f39ff18e110468365d7d3b8fee5

Offical Documentation

Official Docs: