All files / libs/payout-calculation/compute-engine/core-engine/src/engine/release PlanTemplateRelease.ts

98.26% Statements 113/115
33.33% Branches 3/9
100% Functions 1/1
98.26% Lines 113/115

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 1161x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x     11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 1x  
import { ItemsGenerators } from '@amalia/amalia-lang/formula/parsing';
import { VariableType } from '@amalia/amalia-lang/tokens/types';
import { ConfigurationError } from '@amalia/core/types';
import { assert } from '@amalia/ext/typescript';
import { PlanTemplate } from '@amalia/payout-calculation/compute-engine/core-plan-template';
import { DatasetType } from '@amalia/payout-calculation/types';
 
/**
 * For release, we cannot do the PlanTemplate on a plan because we're not in the context of a plan.
 */
export class PlanTemplateRelease extends PlanTemplate {
  public async buildForReleaseCondition(ruleId: string) {
    // Get the definition of the hnr rule.
    const ruleDefinition = await this.statementCalculationCache.fetchRuleById(ruleId);
 
    assert(ruleDefinition, new ConfigurationError(`Cannot find rule ${ruleId} to release payments`));
 
    assert(
      ruleDefinition.releaseConditionVariableId,
      new ConfigurationError(`No release condition variable set for rule ${ruleDefinition.machineName}`),
    );
 
    // Get the definition of the release condition and the current custom object.
    const releaseConditionDefinition = this.statementCalculationCache
      .getDefinitions()
      .getVariableById(ruleDefinition.releaseConditionVariableId);
    assert(
      releaseConditionDefinition &&
        releaseConditionDefinition.type === VariableType.object &&
        releaseConditionDefinition.objectId,
      new ConfigurationError(
        `Release variable of rule ${ruleDefinition.name} cannot be found, has a wrong type, or is not linked to an object.`,
      ),
    );
 
    this.addVariableDefinition(releaseConditionDefinition);
 
    const customObjectDefinition = this.statementCalculationCache
      .getDefinitions()
      .getCustomObjectDefinitionById(releaseConditionDefinition.objectId);
 
    assert(
      customObjectDefinition && customObjectDefinition.id === ruleDefinition.filter?.object?.id,
      new ConfigurationError(
        `Hold and release: ${releaseConditionDefinition.machineName} is not on the same object than the filter of rule ${ruleDefinition.name}`,
      ),
    );
 
    this.addCustomObjectDefinition(customObjectDefinition);
 
    // Create the parent dataset.
    const dataset = ItemsGenerators.generateFilterDataset(
      {
        type: DatasetType.filter,
        filterMachineName: `dummy-filter-for-rule-${ruleId}`,
        customObjectDefinition,
      },
      [],
    );
 
    // Register it into the plan template.
    this.saveDataset(dataset);
 
    // If set, gather payment date and forecast date definitions.
    const paymentDateDefinition = ruleDefinition.configuration?.paymentDateFieldId
      ? this.statementCalculationCache.getDefinitions().getVariableById(ruleDefinition.configuration.paymentDateFieldId)
      : null;
 
    const forecastPaymentDateDefinition = ruleDefinition.configuration?.forecastPaymentDateFieldId
      ? this.statementCalculationCache
          .getDefinitions()
          .getVariableById(ruleDefinition.configuration.forecastPaymentDateFieldId)
      : null;
 
    // Store their config in the plan template to avoid redoing the same job later.
    this.holdAndReleaseFields = {
      releaseCondition: releaseConditionDefinition.machineName,
      paymentDate: paymentDateDefinition?.machineName,
      forecastPaymentDate: forecastPaymentDateDefinition?.machineName,
    };
 
    // Take those variables and start fetching their dependencies.
    const variablesToAnalyze = [
      releaseConditionDefinition.machineName,
      paymentDateDefinition?.machineName,
      forecastPaymentDateDefinition?.machineName,
    ].filter(Boolean);
 
    for (const variableToAnalyze of variablesToAnalyze) {
      // Create the ComputedVariable for the variable.
      const computedVariableToAnalyze = ItemsGenerators.generateObjectVariable(
        variableToAnalyze,
        customObjectDefinition.machineName,
        [],
        dataset.id,
        PlanTemplate.ROOT_RELATION_LEVEL,
      );
 
      // Push it into the dataset.
      this.saveComputedItemInDataset(dataset.id, computedVariableToAnalyze);
 
      // Then fetch its dependencies.
      await this.findDependenciesOfComputedItem(
        computedVariableToAnalyze,
        dataset.id,
        customObjectDefinition,
        PlanTemplate.ROOT_RELATION_LEVEL,
      );
    }
 
    // Partial post-build.
    this.buildDefinitions();
    this.buildParentsGraph();
  }
}