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 | import { Injectable } from '@nestjs/common'; import { fromPairs, uniq } from 'lodash-es'; import { DataSource } from 'typeorm'; import { Company, Plan } from '@amalia/core/models'; import { CalculationAnalyze, CalculationRequest } from '@amalia/core/types'; import { DataConnectorsService } from '@amalia/data-capture/connectors/core'; import { getConnectorObjectName } from '@amalia/data-capture/connectors/types'; import { DataRefreshmentsService } from '@amalia/data-capture/imports/core'; import { type AuthenticatedContext } from '@amalia/kernel/auth/types'; import { UserCreatesCalculationUseCase } from './user-creates-calculation.use-case'; export interface AnalyzeCalculationUseCaseArgs { company: Company; authenticatedContext: AuthenticatedContext; createCalculationRequest: CalculationRequest; } @Injectable() export class AnalyzeCalculationUseCase { public constructor( private readonly userCreatesCalculationUseCase: UserCreatesCalculationUseCase, private readonly dataSource: DataSource, private readonly dataRefreshmentsService: DataRefreshmentsService, private readonly dataConnectorsService: DataConnectorsService, ) {} /** * Creates a calculation. * @param company company * @param authenticatedContext * @param createCalculationRequest * @param dryRun */ public async execute({ company, authenticatedContext, createCalculationRequest, }: AnalyzeCalculationUseCaseArgs): Promise<CalculationAnalyze> { const calculation = await this.userCreatesCalculationUseCase.execute({ company, authenticatedContext, createCalculationRequest, dryRun: true, }); // Early return if we haven't found any plans to compute here. if (!calculation) { return { calculation: null, records: {} }; } const planIdsUsedInCalculation = uniq( calculation.descriptor.flatMap((step) => step.batches.flatMap((batch) => batch.planId)), ); if (!planIdsUsedInCalculation.length) { return { calculation, records: {} }; } // Get the list of all custom object definitions used in the plans of that calculation. const customObjectDefinitionMachineNames = await this.dataSource .getRepository(Plan) .createQueryBuilder() .select(`DISTINCT jsonb_object_keys("planTemplate"->'definitions'->'customObjects')`, 'machineName') .where('"companyId" = :companyId', { companyId: company.id }) .andWhere('"id" IN (:...planIds)', { planIds: planIdsUsedInCalculation }) .getRawMany<{ machineName: string }>(); const connectorSources = await this.dataConnectorsService.getConnectorObjectsByCustomObjectDefinitionName( company, customObjectDefinitionMachineNames.map((c) => c.machineName), ); const recordsPairs = ( await Promise.all( customObjectDefinitionMachineNames.map(async ({ machineName }) => { const foundSource = connectorSources[machineName]; // In case the source has been deleted or renamed. if (!foundSource) { return null; } const lastRefresh = await this.dataRefreshmentsService.getLastRefreshment( company, null, getConnectorObjectName(foundSource.source), ); return [ machineName, { source: foundSource.source, lastRefresh, connectorType: foundSource.connector.type, connectorId: foundSource.connector.id, } satisfies CalculationAnalyze['records'][string], ]; }), ) ).filter(Boolean); const records = fromPairs(recordsPairs) as CalculationAnalyze['records']; return { calculation, records }; } } |