From 2b67dd2c2142e63c6ad13a485f1e1eea075687ec Mon Sep 17 00:00:00 2001 From: andrea rota Date: Wed, 20 Mar 2024 12:30:10 +0000 Subject: [PATCH] (re)cast numbers-as-strings to actual JS numbers --- .../scenario-features-gap-data.service.ts | 15 ++++++++++++++- .../scenario-features-output-gap-data.service.ts | 15 ++++++++++++++- .../src/modules/scenarios/scenarios.controller.ts | 3 --- .../src/scenario-features-gap-data.geo.entity.ts | 3 +++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/api/apps/api/src/modules/scenarios-features/scenario-features-gap-data.service.ts b/api/apps/api/src/modules/scenarios-features/scenario-features-gap-data.service.ts index 96eaf426f0..daf9e6ba75 100644 --- a/api/apps/api/src/modules/scenarios-features/scenario-features-gap-data.service.ts +++ b/api/apps/api/src/modules/scenarios-features/scenario-features-gap-data.service.ts @@ -17,6 +17,7 @@ import { ScenarioAccessControl } from '@marxan-api/modules/access-control/scenar import { assertDefined } from '@marxan/utils'; import { forbiddenError } from '@marxan-api/modules/access-control'; import { Either, left, right } from 'fp-ts/lib/Either'; +import { plainToClass } from 'class-transformer'; @Injectable() export class ScenarioFeaturesGapDataService extends AppBaseService< @@ -59,7 +60,19 @@ export class ScenarioFeaturesGapDataService extends AppBaseService< ) { return left(forbiddenError); } - return right(await super.findAllPaginated(fetchSpecification, info)); + /** + * @debt Explicitly applying transforms (via `plainToClass()`) here: it + * would be best to do this at AppBaseService level, but that would + * currently open a rabbit hole due to the use of generics. + */ + const { data, metadata } = await this.findAllPaginated( + fetchSpecification, + info, + ); + return right({ + data: plainToClass(ScenarioFeaturesGapData, data), + metadata, + }); } async setFilters( diff --git a/api/apps/api/src/modules/scenarios-features/scenario-features-output-gap-data.service.ts b/api/apps/api/src/modules/scenarios-features/scenario-features-output-gap-data.service.ts index 547bf69279..b945f35602 100644 --- a/api/apps/api/src/modules/scenarios-features/scenario-features-output-gap-data.service.ts +++ b/api/apps/api/src/modules/scenarios-features/scenario-features-output-gap-data.service.ts @@ -18,6 +18,7 @@ import { forbiddenError } from '@marxan-api/modules/access-control'; import { assertDefined } from '@marxan/utils'; import { Either, left, right } from 'fp-ts/lib/Either'; import { ScenarioAccessControl } from '@marxan-api/modules/access-control/scenarios-acl/scenario-access-control'; +import { plainToClass } from 'class-transformer'; const scenarioFeaturesOutputGapDataFilterKeyNames = ['runId'] as const; type ScenarioFeaturesOutputGapDataFilterKeys = keyof Pick< @@ -73,7 +74,19 @@ export class ScenarioFeaturesOutputGapDataService extends AppBaseService< ) { return left(forbiddenError); } - return right(await super.findAllPaginated(fetchSpecification, info)); + /** + * @debt Explicitly applying transforms (via `plainToClass()`) here: it + * would be best to do this at AppBaseService level, but that would + * currently open a rabbit hole due to the use of generics. + */ + const { data, metadata } = await this.findAllPaginated( + fetchSpecification, + info, + ); + return right({ + data: plainToClass(ScenarioFeaturesOutputGapData, data), + metadata, + }); } async setFilters( diff --git a/api/apps/api/src/modules/scenarios/scenarios.controller.ts b/api/apps/api/src/modules/scenarios/scenarios.controller.ts index d237ae6441..45fdb61277 100644 --- a/api/apps/api/src/modules/scenarios/scenarios.controller.ts +++ b/api/apps/api/src/modules/scenarios/scenarios.controller.ts @@ -86,7 +86,6 @@ import { GeometryKind, } from '@marxan-api/decorators/file-interceptors.decorator'; import { ProtectedAreaDto } from '@marxan-api/modules/scenarios/dto/protected-area.dto'; -import { UploadShapefileDto } from '@marxan-api/modules/scenarios/dto/upload.shapefile.dto'; import { ProtectedAreasChangeDto } from '@marxan-api/modules/scenarios/dto/protected-area-change.dto'; import { StartScenarioBlmCalibrationDto } from '@marxan-api/modules/scenarios/dto/start-scenario-blm-calibration.dto'; import { BlmCalibrationRunResultDto } from './dto/scenario-blm-calibration-results.dto'; @@ -108,8 +107,6 @@ import { RequestScenarioCloneResponseDto } from './dto/scenario-clone.dto'; import { ensureShapefileHasRequiredFiles } from '@marxan-api/utils/file-uploads.utils'; import { WebshotPdfReportConfig } from '@marxan/webshot/webshot.dto'; import { ClearLockStatusParams } from '@marxan-api/modules/scenarios/dto/clear-lock-status-param.dto'; -import { CostRangeDto } from '@marxan-api/modules/scenarios/dto/cost-range.dto'; -import { plainToClass } from 'class-transformer'; import { ProjectsService } from '@marxan-api/modules/projects/projects.service'; import { CostSurfaceService } from '@marxan-api/modules/cost-surface/cost-surface.service'; diff --git a/api/libs/features/src/scenario-features-gap-data.geo.entity.ts b/api/libs/features/src/scenario-features-gap-data.geo.entity.ts index 0266bbb7bc..397286f2a0 100644 --- a/api/libs/features/src/scenario-features-gap-data.geo.entity.ts +++ b/api/libs/features/src/scenario-features-gap-data.geo.entity.ts @@ -1,4 +1,5 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; import { Column, ViewEntity } from 'typeorm'; @ViewEntity('scenario_features_gap_data') @@ -23,6 +24,7 @@ export class ScenarioFeaturesGapData { // explicitly set type, otherwise TypeORM (v10, at least) will cast to integer // TypeORM will still represent the value as string though (https://github.com/typeorm/typeorm/issues/873#issuecomment-328912050) @Column({ name: 'met', type: 'double precision' }) + @Transform(parseFloat) met!: number; @ApiProperty() @@ -33,6 +35,7 @@ export class ScenarioFeaturesGapData { // explicitly set type, otherwise TypeORM (v10, at least) will cast to integer // TypeORM will still represent the value as string though (https://github.com/typeorm/typeorm/issues/873#issuecomment-328912050) @Column({ name: 'coverage_target', type: 'double precision' }) + @Transform(parseFloat) coverageTarget!: number; @ApiProperty()