From 4b15ffac9e3d5a3e9061e77b2f0af6be7d76f163 Mon Sep 17 00:00:00 2001 From: KevSanchez Date: Fri, 5 Aug 2022 10:00:44 +0200 Subject: [PATCH] chore(indicatorrecord): Create all sourcing records refactor 1st prototype --- .../indicator-records.service.ts | 3 +- .../services/impact-calculator.service.ts | 104 ++++++++++++++++-- .../indicator-records.service.spec.ts | 6 +- 3 files changed, 99 insertions(+), 14 deletions(-) diff --git a/api/src/modules/indicator-records/indicator-records.service.ts b/api/src/modules/indicator-records/indicator-records.service.ts index b0e37b3686..85d8ac696d 100644 --- a/api/src/modules/indicator-records/indicator-records.service.ts +++ b/api/src/modules/indicator-records/indicator-records.service.ts @@ -167,7 +167,8 @@ export class IndicatorRecordsService extends AppBaseService< ]; const rawData: SourcingRecordsWithIndicatorRawDataDto[] = - await this.indicatorRecordRepository.getIndicatorRawDataForAllSourcingRecords(); + //await this.indicatorRecordRepository.getIndicatorRawDataForAllSourcingRecords(); + await this.impactCalculatorService.calculateAllSourcingRecords(); const calculatedData2: IndicatorRecordCalculatedValuesDto[] = rawData.map( (sourcingRecordData: SourcingRecordsWithIndicatorRawDataDto) => { diff --git a/api/src/modules/indicator-records/services/impact-calculator.service.ts b/api/src/modules/indicator-records/services/impact-calculator.service.ts index b088e007cb..4c2777a68b 100644 --- a/api/src/modules/indicator-records/services/impact-calculator.service.ts +++ b/api/src/modules/indicator-records/services/impact-calculator.service.ts @@ -1,32 +1,25 @@ import { Connection, - EntityRepository, getConnection, QueryRunner, - Repository, SelectQueryBuilder, } from 'typeorm'; import { Injectable, Logger } from '@nestjs/common'; -import { SaveOptions } from 'typeorm/repository/SaveOptions'; import { MATERIAL_TO_H3_TYPE } from 'modules/materials/material-to-h3.entity'; -import { H3DataService } from 'modules/h3-data/h3-data.service'; import { H3Data } from 'modules/h3-data/h3-data.entity'; import { INDICATOR_TYPES } from 'modules/indicators/indicator.entity'; -import { SourcingRecordsWithIndicatorRawDataDto } from '../../sourcing-records/dto/sourcing-records-with-indicator-raw-data.dto'; +import { SourcingRecordsWithIndicatorRawDataDto } from 'modules/sourcing-records/dto/sourcing-records-with-indicator-raw-data.dto'; @Injectable() export class ImpactCalculatorService { logger: Logger = new Logger(this.constructor.name); - constructor(private readonly h3DataService: H3DataService) {} - async calculateImpact( connection: Connection, queryRunner: QueryRunner, georegionId: string, materialId: string, year: number, - options?: SaveOptions, ): Promise { // MAIN LOGIC @@ -70,9 +63,16 @@ export class ImpactCalculatorService { */ const materialH3s: Map = - await this.h3DataService.getAllMaterialH3sByClosestYear(materialId, year); + await this.getAllMaterialH3sByClosestYear( + connection, + queryRunner, + materialId, + year, + ); const indicatorH3s: Map = - await this.h3DataService.getIndicatorH3sByTypeAndClosestYear( + await this.getIndicatorH3sByTypeAndClosestYear( + connection, + queryRunner, Object.values(INDICATOR_TYPES), year, ); @@ -241,4 +241,88 @@ export class ImpactCalculatorService { return result; } + + getIndicatorH3sByTypeAndClosestYear( + connecttion: Connection, + queryRunner: QueryRunner, + indicatorTypes: INDICATOR_TYPES[], + year: number, + ): Promise> { + return indicatorTypes.reduce( + async ( + previousValue: Promise>, + currentIndicatorType: INDICATOR_TYPES, + ) => { + const queryBuilder: SelectQueryBuilder = connecttion + .createQueryBuilder() + .select(' h3data.*') + .from(H3Data, 'h3data') + .leftJoin( + 'indicator', + 'indicator', + 'h3data.indicatorId = indicator.id', + ) + .where(`indicator.nameCode = '${currentIndicatorType}'`) + .orderBy(`ABS(h3data.year - ${year})`, 'ASC') + .limit(1); + + const map: Map = await previousValue; + + try { + const result: any = await queryRunner.query(queryBuilder.getQuery()); + + if (result.length) { + map.set(currentIndicatorType, result[0]); + } + } catch (err) { + console.error(err); + } + + return map; + }, + Promise.resolve(new Map()), + ); + } + + getAllMaterialH3sByClosestYear( + connecttion: Connection, + queryRunner: QueryRunner, + materialId: string, + year: number, + ): Promise> { + return Object.values(MATERIAL_TO_H3_TYPE).reduce( + async ( + previousValue: Promise>, + currentMaterialToH3Type: MATERIAL_TO_H3_TYPE, + ) => { + const queryBuilder: SelectQueryBuilder = connecttion + .createQueryBuilder() + .select('h3data.*') + .from(H3Data, 'h3data') + .leftJoin( + 'material_to_h3', + 'materialsToH3s', + 'materialsToH3s.h3DataId = h3data.id', + ) + .where(`materialsToH3s.materialId = '${materialId}'`) + .andWhere(`materialsToH3s.type = '${currentMaterialToH3Type}'`) + .orderBy(`ABS(h3data.year - ${year})`, 'ASC') + .limit(1); + + const map: Map = await previousValue; + try { + const result: any = await queryRunner.query(queryBuilder.getQuery()); + + if (result.length) { + map.set(currentMaterialToH3Type, result[0]); + } + } catch (err) { + console.error(err); + } + + return map; + }, + Promise.resolve(new Map()), + ); + } } diff --git a/api/test/integration/indicator-record/indicator-records.service.spec.ts b/api/test/integration/indicator-record/indicator-records.service.spec.ts index 7ca5083c7e..4bce4bea64 100644 --- a/api/test/integration/indicator-record/indicator-records.service.spec.ts +++ b/api/test/integration/indicator-record/indicator-records.service.spec.ts @@ -495,7 +495,7 @@ describe('Indicator Records Service', () => { indicatorPreconditions.carbonEmissions, materialH3DataProducer1, indicatorPreconditions.sourcingRecord1.id, - 29.788819307125873, + 29.788819875776397, 1610, ); await checkCreatedIndicatorRecord( @@ -527,7 +527,7 @@ describe('Indicator Records Service', () => { indicatorPreconditions.carbonEmissions, materialH3DataProducer2, indicatorPreconditions.sourcingRecord2.id, - 14.894409653562937, + 14.894409937888199, 1610, ); await checkCreatedIndicatorRecord( @@ -538,7 +538,7 @@ describe('Indicator Records Service', () => { 0.7700000181794167, 1610, ); - }); + }, 100000000); test("When creating indicators without provided coefficients and the material has H3 data, the raw values for the calculations should be read from the cache if they're already present on the CachedData", async () => { //ARRANGE