Skip to content

Commit

Permalink
Update endpoint for getting project cost surface min and max values
Browse files Browse the repository at this point in the history
  • Loading branch information
yulia-bel committed Sep 27, 2023
1 parent 1a68104 commit 35d97f5
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 6 deletions.
35 changes: 35 additions & 0 deletions api/apps/api/src/modules/cost-surface/cost-surface.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { projectNotEditable } from '@marxan-api/modules/projects/projects.servic
import { UploadCostSurfaceShapefileDto } from '@marxan-api/modules/cost-surface/dto/upload-cost-surface-shapefile.dto';
import { UpdateCostSurfaceDto } from '@marxan-api/modules/cost-surface/dto/update-cost-surface.dto';
import { CostSurfaceCalculationPort } from '@marxan-api/modules/cost-surface/ports/project/cost-surface-calculation.port';
import { forbiddenError } from '@marxan-api/modules/access-control';

export const costSurfaceNotEditableWithinProject = Symbol(
`cost surface not editable within project`,
Expand All @@ -20,6 +21,11 @@ export const costSurfaceNameAlreadyExistsForProject = Symbol(
`cost surface already exists for project`,
);

export interface CostRange {
min: number;
max: number;
}

@Injectable()
export class CostSurfaceService {
constructor(
Expand Down Expand Up @@ -118,4 +124,33 @@ export class CostSurfaceService {

return right(costSurface);
}

async getCostSurfaceRange(
costSurfaceId: string,
projectId: string,
userId: string,
): Promise<
Either<
typeof costSurfaceNotFoundForProject | typeof projectNotEditable,
CostRange
>
> {
if (
!(await this.projectAclService.canEditCostSurfaceInProject(
userId,
projectId,
))
) {
return left(projectNotEditable);
}
const costRange = await this.costSurfaceRepository.findOne({
select: ['min', 'max'],
where: { id: costSurfaceId, projectId },
});
if (costRange) {
return right({ min: costRange.min, max: costRange.max });
} else {
return left(costSurfaceNotFoundForProject);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Body,
Controller,
ForbiddenException,
forwardRef,
Get,
Inject,
Expand Down Expand Up @@ -131,23 +132,35 @@ export class ProjectCostSurfaceController {

@ImplementsAcl()
@UseGuards(JwtAuthGuard)
@ApiParam({
name: 'costSurfaceId',
description: 'The id of the Cost Surface to be updated',
})
@ApiParam({
name: 'projectId',
description: 'The id of the Project that the Cost Surface is associated to',
})
@Get(`:projectId/cost-surface/:costSurfaceId/cost-range`)
@ApiOkResponse({ type: CostRangeDto })
async getCostRange(
@Param('projectId') scenarioId: string,
@Param('projectId') projectId: string,
@Param('costSurfaceId') costSurfaceId: string,
@Req() req: RequestWithAuthenticatedUser,
): Promise<CostRangeDto> {
const result = await this.scenarioService.getCostRange(
scenarioId,
const result = await this.costSurfaceService.getCostSurfaceRange(
costSurfaceId,
projectId,
req.user.id,
);

if (isLeft(result)) {
throw mapAclDomainToHttpError(result.left, {
scenarioId,
projectId,
costSurfaceId,
userId: req.user.id,
resourceType: scenarioResource.name.plural,
});
}

return plainToClass<CostRangeDto, CostRangeDto>(CostRangeDto, result.right);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class SelectionGetService {

return [
...categories.map((category) => ({
name: 'IUCN '+ category,
name: 'IUCN ' + category,
id: category,
isCustom: false,
})),
Expand Down
25 changes: 25 additions & 0 deletions api/apps/api/test/project/project-cost-surface.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ describe('Cost Surface', () => {
beforeEach(async () => {
fixtures = await getProjectCostSurfaceFixtures();
});

afterEach(async () => {
await fixtures.cleanup();
});

describe('Default Cost Surface', () => {
it(`should create a default Cost Surface`, async () => {
const { projectId } = await fixtures.WhenCreatingAProject(
Expand Down Expand Up @@ -134,4 +139,24 @@ describe('Cost Surface', () => {
await fixtures.ThenCostSurfaceAPIEntityWasNotUpdated(costSurface2);
});
});

describe('Get Cost Surface Range', () => {
it(`should return the range of the cost surface`, async () => {
// ARRANGE
const projectId = await fixtures.GivenProject('someProject');
const costSurface = await fixtures.GivenCostSurfaceMetadataForProject(
projectId,
'costSurfaceName',
);

// ACT
const response = await fixtures.WhenGettingCostSurfaceRange(
costSurface.id,
projectId,
);

// ASSERT
await fixtures.ThenCostSurfaceRangeWasReturned(response);
});
});
});
17 changes: 17 additions & 0 deletions api/apps/api/test/project/project-cost-surface.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ export const getProjectCostSurfaceFixtures = async () => {
.send({ name: costSurfaceName });
},

WhenGettingCostSurfaceRange: async (
costSurfaceId: string,
projectId: string,
) => {
return request(app.getHttpServer())
.get(
`/api/v1/projects/${projectId}/cost-surface/${costSurfaceId}/cost-range`,
)
.set('Authorization', `Bearer ${token}`)
.send();
},

ThenCostSurfaceAPIEntityWasProperlySaved: async (name: string) => {
const savedCostSurface = await costSurfaceRepo.findOne({
where: { name },
Expand Down Expand Up @@ -230,5 +242,10 @@ export const getProjectCostSurfaceFixtures = async () => {

expect(costSurface).toBeDefined();
},

ThenCostSurfaceRangeWasReturned: async (response: any) => {
expect(response.status).toBe(HttpStatus.OK);
expect(response.body).toEqual({ min: 0, max: 0 });
},
};
};

0 comments on commit 35d97f5

Please sign in to comment.