Skip to content

Commit

Permalink
Merge pull request #1152 from Vizzuality/feat/add-api_featureId-to-sc…
Browse files Browse the repository at this point in the history
…enario-features-data

Feat/add api feature id to scenario features data
  • Loading branch information
angelhigueraacid authored Jul 4, 2022
2 parents 9427606 + 755ab10 commit 60db02e
Show file tree
Hide file tree
Showing 28 changed files with 260 additions and 196 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { RemoteFeaturesData } from '../entities/remote-features-data.geo.entity';
import { ScenarioFeaturesData } from '@marxan/features';
import { FeatureTag } from '@marxan/features/domain';
import { GeoFeature } from '../../geo-features/geo-feature.api.entity';
Expand All @@ -19,6 +18,7 @@ type RawRemoteScenarioFeaturesData = Pick<
| 'totalArea'
| 'currentArea'
| 'target2'
| 'apiFeatureId'
>;

export const getValidNonGeoData = (
Expand All @@ -34,6 +34,7 @@ export const getValidNonGeoData = (
currentArea: 12000,
totalArea: 20000,
target2: 0,
apiFeatureId: metaFeatureIdMet,
},
{
id: 'some-another-id',
Expand All @@ -44,22 +45,12 @@ export const getValidNonGeoData = (
currentArea: 4000,
totalArea: 10000,
target2: 0,
apiFeatureId: metaFeatureIdFailed,
},
],
2,
];

export const getValidRemoteFeatureData = (): RemoteFeaturesData[] => [
{
featureId: metaFeatureIdFailed,
id: featureIdFailed,
},
{
featureId: metaFeatureIdMet,
id: featureIdMet,
},
];

export const getValidGeoFeature = (): GeoFeature[] => {
const entity1 = new GeoFeature();
entity1.id = metaFeatureIdMet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ test(`returns full query with all parameters`, async () => {
expect(fixPrettierQuirk(query.query)).toEqual(`
with inserted_sfp as (
insert into scenario_features_preparation as sfp (feature_class_id,
api_feature_id,
scenario_id,
specification_id,
fpf,
Expand All @@ -51,6 +52,7 @@ test(`returns full query with all parameters`, async () => {
current_pa,
hash)
select fd.id,
fd.feature_id,
$1,
$2,
$3,
Expand Down Expand Up @@ -137,6 +139,7 @@ test(`returns full query with no wdpa`, async () => {
`
with inserted_sfp as (
insert into scenario_features_preparation as sfp (feature_class_id,
api_feature_id,
scenario_id,
specification_id,
fpf,
Expand All @@ -146,6 +149,7 @@ test(`returns full query with no wdpa`, async () => {
current_pa,
hash)
select fd.id,
fd.feature_id,
$1,
$2,
$3,
Expand Down Expand Up @@ -239,6 +243,7 @@ test(`returns full query with no planning area location`, async () => {
`
with inserted_sfp as (
insert into scenario_features_preparation as sfp (feature_class_id,
api_feature_id,
scenario_id,
specification_id,
fpf,
Expand All @@ -248,6 +253,7 @@ test(`returns full query with no planning area location`, async () => {
current_pa,
hash)
select fd.id,
fd.feature_id,
$1,
$2,
$3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class CopyQuery {
const query = `
with inserted_sfp as (
insert into scenario_features_preparation as sfp (feature_class_id,
api_feature_id,
scenario_id,
specification_id,
fpf,
Expand All @@ -60,6 +61,7 @@ export class CopyQuery {
current_pa,
hash)
select fd.id,
fd.feature_id,
${fields.scenarioId},
${fields.specificationId},
${fields.fpf},
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class MoveDataFromPreparationHandler
`
insert into scenario_features_data as sfd (id,
feature_class_id,
api_feature_id,
scenario_id,
total_area,
current_pa,
Expand All @@ -45,6 +46,7 @@ export class MoveDataFromPreparationHandler
specification_id)
select id,
feature_class_id,
api_feature_id,
scenario_id,
total_area,
current_pa,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,25 +134,19 @@ export class ScenarioFeaturesGapDataService extends AppBaseService<

/**
* (pseudo)FKs across dbs:
* (geo)scenario_feature_data.featureClassId -> (geo)feature_data.id
* (geo)feature_data.feature_id -> (api)feature.id
* (geo)scenario_feature_data.api_feature_id -> (api)feature.id
*/
const featureRelations: Record<string, string> = {};
const featureMetadata = await this.features.find({
where: {
id: In(featureIds),
},
});

featureMetadata.forEach((fd) => {
featureRelations[fd.id] = fd.id;
});

return [
scenarioFeaturesData
.map((sfd) => {
const relatedFeature = featureMetadata.find(
(f) => f.id === featureRelations[sfd.featureId],
(f) => f.id === sfd.featureId,
);

if (!relatedFeature) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,19 @@ export class ScenarioFeaturesOutputGapDataService extends AppBaseService<

/**
* (pseudo)FKs across dbs:
* (geo)scenario_feature_data.featureClassId -> (geo)feature_data.id
* (geo)feature_data.feature_id -> (api)feature.id
* (geo)scenario_feature_data.api_feature_id -> (api)feature.id
*/
const featureRelations: Record<string, string> = {};
const featureMetadata = await this.features.find({
where: {
id: In(featureIds),
},
});

featureMetadata.forEach((fd) => {
featureRelations[fd.id] = fd.id;
});

return [
scenarioFeaturesData
.map((sfd) => {
const relatedFeature = featureMetadata.find(
(f) => f.id === featureRelations[sfd.featureId],
(f) => f.id === sfd.featureId,
);

if (!relatedFeature) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { DbConnections } from '@marxan-api/ormconfig.connections';
import { ProjectsModule } from '@marxan-api/modules/projects/projects.module';
import { CqrsModule } from '@nestjs/cqrs';
import { ApiEventsModule } from '../api-events/api-events.module';
import { RemoteFeaturesData } from './entities/remote-features-data.geo.entity';
import { CreateFeaturesSaga } from './create-features.saga';
import { CreateFeaturesHandler } from './create-features.handler';
import { CopyDataProvider, CopyOperation, CopyQuery } from './copy';
Expand All @@ -39,7 +38,6 @@ import { AccessControlModule } from '@marxan-api/modules/access-control';
ScenarioFeaturesData,
ScenarioFeaturesGapData,
ScenarioFeaturesOutputGapData,
RemoteFeaturesData,
],
DbConnections.geoprocessingDB,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,29 @@ import { ScenarioFeaturesData } from '@marxan/features';
import { Test } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { fakeQueryBuilder } from '../../utils/__mocks__/fake-query-builder';
import { RemoteFeaturesData } from './entities/remote-features-data.geo.entity';
import { GeoFeature } from '../geo-features/geo-feature.api.entity';
import {
getValidGeoFeature,
getValidNonGeoData,
getValidRemoteFeatureData,
} from './__mocks__/scenario-features.view-data';
import { DbConnections } from '@marxan-api/ormconfig.connections';

let sut: ScenarioFeaturesService;
let geoFeatureRepoMock: jest.Mocked<Repository<GeoFeature>>;
let geoRemoteFeaturesRepoMock: jest.Mocked<Repository<RemoteFeaturesData>>;

let fakeResultResolver: jest.Mock;

beforeAll(async () => {
fakeResultResolver = jest.fn();
const geoFeatureToken = getRepositoryToken(GeoFeature);
const geoRemoteScenarioFeaturesRepoToken = getRepositoryToken(
const geoScenarioFeaturesRepoToken = getRepositoryToken(
ScenarioFeaturesData,
DbConnections.geoprocessingDB,
);
const geoRemoteFeaturesRepoToken = getRepositoryToken(
RemoteFeaturesData,
DbConnections.geoprocessingDB,
);
const sandbox = await Test.createTestingModule({
providers: [
{
provide: geoRemoteScenarioFeaturesRepoToken,
provide: geoScenarioFeaturesRepoToken,
useValue: {
metadata: {
name: 'required-by-base-service-for-logging',
Expand All @@ -47,19 +40,12 @@ beforeAll(async () => {
find: jest.fn(),
},
},
{
provide: geoRemoteFeaturesRepoToken,
useValue: {
find: jest.fn(),
},
},
ScenarioFeaturesService,
],
}).compile();

sut = sandbox.get(ScenarioFeaturesService);
geoFeatureRepoMock = sandbox.get(geoFeatureToken);
geoRemoteFeaturesRepoMock = sandbox.get(geoRemoteFeaturesRepoToken);
});

describe(`when looking for a scenario's features`, () => {
Expand All @@ -69,9 +55,6 @@ describe(`when looking for a scenario's features`, () => {
// Asset
fakeResultResolver.mockResolvedValue(getValidNonGeoData(scenarioId));
geoFeatureRepoMock.find.mockResolvedValueOnce(getValidGeoFeature());
geoRemoteFeaturesRepoMock.find.mockResolvedValueOnce(
getValidRemoteFeatureData(),
);
// Act
result = await sut.findAll({
filter: {
Expand All @@ -85,6 +68,7 @@ describe(`when looking for a scenario's features`, () => {
Array [
Array [
Object {
"apiFeatureId": "meta-feature-uuid-1-criteria-met",
"coverageTarget": 50,
"coverageTargetArea": 10000,
"currentArea": 12000,
Expand All @@ -103,6 +87,7 @@ describe(`when looking for a scenario's features`, () => {
"totalArea": 20000,
},
Object {
"apiFeatureId": "meta-feature-uuid-1-criteria-failed",
"coverageTarget": 50,
"coverageTargetArea": 5000,
"currentArea": 4000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {

import { GeoFeature } from '../geo-features/geo-feature.api.entity';
import { ScenarioFeaturesData } from '@marxan/features';
import { RemoteFeaturesData } from './entities/remote-features-data.geo.entity';
import { UserSearchCriteria } from './search-criteria';
import { AppConfig } from '../../utils/config.utils';
import { DbConnections } from '@marxan-api/ormconfig.connections';
Expand All @@ -24,8 +23,6 @@ export class ScenarioFeaturesService extends AppBaseService<
constructor(
@InjectRepository(GeoFeature)
private readonly features: Repository<GeoFeature>,
@InjectRepository(RemoteFeaturesData, DbConnections.geoprocessingDB)
private readonly remoteFeature: Repository<RemoteFeaturesData>,
@InjectRepository(ScenarioFeaturesData, DbConnections.geoprocessingDB)
private readonly remoteScenarioFeatures: Repository<ScenarioFeaturesData>,
) {
Expand All @@ -52,28 +49,12 @@ export class ScenarioFeaturesService extends AppBaseService<
entitiesAndCount: [any[], number],
): Promise<[any[], number]> {
const scenarioFeaturesData = entitiesAndCount[0] as ScenarioFeaturesData[];
const featuresDataIds = scenarioFeaturesData.map(
(rsfd) => rsfd.featureDataId,
);

if (featuresDataIds.length === 0) {
if (scenarioFeaturesData.length === 0) {
return entitiesAndCount;
}
/**
* (geo)scenario_feature_data.featureClassId -> feature_data.id --feature_data.feature_id -> (api)feature.id
*/
const featureRelations: Record<string, string> = {};
const featureData = await this.remoteFeature.find({
where: {
id: In(featuresDataIds),
},
});

featureData.forEach((fd) => {
featureRelations[fd.id] = fd.featureId;
});

const featureIds = featureData.map((fd) => fd.featureId);
const featureIds = scenarioFeaturesData.map((sfd) => sfd.apiFeatureId);
const features = await this.features.find({
where: {
id: In(featureIds),
Expand All @@ -84,7 +65,7 @@ export class ScenarioFeaturesService extends AppBaseService<
scenarioFeaturesData
.map((sfd) => {
const relatedFeature = features.find(
(f) => f.id === featureRelations[sfd.featureDataId],
(f) => f.id === sfd.apiFeatureId,
);

if (!relatedFeature) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ export class SpecDatService {
with grouped_feature as (
select min(sfd.feature_id) as min_feature_id
from public.scenario_features_data as sfd
inner join features_data fd on fd.id = sfd.feature_class_id
where sfd.scenario_id = $1
group by fd.feature_id
group by sfd.api_feature_id
)
select
feature_id as "featureId",
Expand All @@ -50,7 +49,7 @@ export class SpecDatService {
sepnum as "sepNum",
metadata
from grouped_feature
left join scenario_features_data as sfd on feature_id = grouped_feature.min_feature_id
left join scenario_features_data as sfd on feature_id = grouped_feature.min_feature_id AND sfd.scenario_id = $1
order by feature_id
`,
[scenarioId],
Expand Down
Loading

0 comments on commit 60db02e

Please sign in to comment.