All files / apps/data-refreshments/src/refreshments-execute/sync/quotaConnector dataConnectorQuotaDefinition.ts

100% Statements 96/96
100% Branches 16/16
100% Functions 3/3
100% Lines 96/96

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 971x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x 49x 49x 49x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 3x 3x 3x 3x 3x 1x 1x 3x 3x 3x 3x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 6x 2x 2x 2x 2x 2x 2x 2x 1x  
import { camelCase, set } from 'lodash-es';
 
import { type Variable } from '@amalia/core/models';
import { RefreshmentErrorType } from '@amalia/core/types';
import { RefreshmentTypedError } from '@amalia/data-capture/connectors/library';
import {
  DATA_CONNECTOR_DIRECTORY_MATCHABLE_FIELDS,
  DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_ALL,
  DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_EXISTING,
  type DataConnectorDirectoryMatchableField,
  type DataConnectorObject,
  type DataConnectorObjectField,
} from '@amalia/data-capture/connectors/types';
import { assert } from '@amalia/ext/typescript';
 
export class DataConnectorQuotaDefinition {
  public readonly quotaFields: Record<string, Variable>;
 
  public readonly userFields: DataConnectorDirectoryMatchableField[];
 
  /**
   * Field to use as id for user (one of DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_EXISTING)
   */
  public readonly userIdField: (typeof DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_EXISTING)[number];
 
  public constructor(
    private readonly connectorObject: DataConnectorObject,
    private readonly quotaVariables: Variable[],
  ) {
    const matchedFields = this.getMatchedFields();
    this.quotaFields = matchedFields.quotaFields;
    this.userFields = matchedFields.userFields;
    const userIdField = DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_EXISTING.find((field) =>
      this.userFields.includes(field),
    );
 
    assert(userIdField, 'Cannot find an applicable userIdField');
 
    this.userIdField = userIdField;
  }
 
  public getMatchingField(matchingField?: string): DataConnectorObjectField | undefined {
    assert(this.connectorObject.fields, `Fields not found on ${this.connectorObject.name}`);
    return this.connectorObject.fields.find((field) => field.matchingField === matchingField);
  }
 
  private getMatchedFields(): {
    userFields: DataConnectorDirectoryMatchableField[];
    quotaFields: Record<string, Variable>;
  } {
    assert(this.connectorObject.fields, `Fields not found on ${this.connectorObject.name}`);
 
    const matchedFieldNames = this.connectorObject.fields
      .filter((f) => !!f.matchingField)
      .map((f) => camelCase(f.matchingField));
 
    // If we want to synchronise all users, we need to ensure that mandatory fields are mapped.
    if (!this.connectorObject.synchronizeOnlyToExistantUser) {
      const areMandatoryFieldsMapped = DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_ALL.every((k) =>
        matchedFieldNames.includes(k),
      );
 
      if (!areMandatoryFieldsMapped) {
        throw new RefreshmentTypedError('Some mandatory fields are not mapped', RefreshmentErrorType.CONFIGURATION);
      }
    }
 
    // If we want to synchronise only existing users, we need to ensure that
    // one id field is mapped (one of email, hrisId, externalId).
    if (this.connectorObject.synchronizeOnlyToExistantUser) {
      const isIdFieldMapped = DATA_CONNECTOR_REQUIRED_MATCHING_FIELDS_IF_SYNC_EXISTING.some((k) =>
        matchedFieldNames.includes(k),
      );
 
      if (!isIdFieldMapped) {
        throw new RefreshmentTypedError(
          'Id field is mandatory to sync existing users, and none is mapped',
          RefreshmentErrorType.CONFIGURATION,
        );
      }
    }
 
    const userFields = matchedFieldNames.filter((f) => DATA_CONNECTOR_DIRECTORY_MATCHABLE_FIELDS.includes(f));
    const quotaFields: Record<string, Variable> = {};
    this.quotaVariables
      .filter((v) => matchedFieldNames.includes(v.machineName))
      .forEach((v) => {
        set(quotaFields, v.machineName, v);
      });
 
    return {
      userFields: userFields as DataConnectorDirectoryMatchableField[],
      quotaFields,
    };
  }
}