All files / libs/payout-definition/plans/views/hub/rule-designer/src/lib/compute use-should-recompute-statement.ts

0% Statements 0/61
0% Branches 0/1
0% Functions 0/1
0% Lines 0/61

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                                                                                                                           
import { useCallback, useMemo } from 'react';

import { isBeingReviewed, type Statement, type StatementForecast } from '@amalia/core/types';
import { dayjs } from '@amalia/ext/dayjs';
import { usePlan, usePlanForecast, usePlanTemplate } from '@amalia/payout-definition/state';

import { useRuleDesignerForecastContext } from '../forecast/RuleDesignerForecast.context';
import { usePlanHubRuleDesignerContext } from '../PlanHubRuleDesigner.context';

export const useShouldRecomputeStatement = () => {
  const { planId } = usePlanHubRuleDesignerContext();
  const { isForecastedView } = useRuleDesignerForecastContext();

  const { data: plan } = usePlan(planId);
  const { data: planTemplate } = usePlanTemplate(planId);
  const { data: planForecast } = usePlanForecast({
    planId: plan?.id,
    planForecastId: plan?.forecastId ?? undefined,
    enabled: isForecastedView,
  });

  // Date used to determine if statements are outdated or not.
  // We use the plan template generated date.
  // In forecast, we use the plan forecast updated date because there is no generation date, and fallback to the plan template generated date.
  const planTemplateGeneratedDate = useMemo(
    () =>
      dayjs.max(
        ...[isForecastedView && planForecast?.updatedAt, planTemplate?.template?.metadata.generatedDate]
          .filter(Boolean)
          .map((date) => dayjs(date)),
      ),
    [isForecastedView, planTemplate?.template?.metadata.generatedDate, planForecast?.updatedAt],
  );

  return useCallback(
    (
      statement:
        | (Pick<Statement, 'lastCalculationDate' | 'workflowComplete' | 'workflowSteps'> & {
            forecast?: Pick<StatementForecast, 'lastCalculationDate'>;
          })
        | undefined,
      isLoading: boolean,
    ): boolean =>
      // Should not recompute if the statement is still loading.
      (!isLoading && !statement) ||
      // Should recompute if there is no statement
      (!!statement &&
        // Should not recompute if validation workflow has been started.
        !isBeingReviewed(statement) &&
        // This should not happen (if you have a statement you should have a plan template for that plan).
        !!planTemplateGeneratedDate &&
        // Should recompute if the statement was computed before the last edit to the plan template.
        // In forecasted mode, the last calculation date is the forecasted last calculation date (fallback to the statement calculation date).
        dayjs(
          isForecastedView
            ? (statement.forecast?.lastCalculationDate ?? statement.lastCalculationDate)
            : statement.lastCalculationDate,
        ).isBefore(planTemplateGeneratedDate)),
    [planTemplateGeneratedDate, isForecastedView],
  );
};