From 9d9549cdd45f53137c8b86b28e2f051b1eba806b Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:37:17 +0100 Subject: [PATCH 01/27] Added new donor permission target ref #65 --- src/models/enums/PermissionTargets.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/models/enums/PermissionTargets.ts b/src/models/enums/PermissionTargets.ts index 526aaa3..728cf2a 100644 --- a/src/models/enums/PermissionTargets.ts +++ b/src/models/enums/PermissionTargets.ts @@ -9,5 +9,6 @@ export enum PermissionTarget { USER = 'USER', USERGROUP = 'USERGROUP', PERMISSION = 'PERMISSION', - STATSCLIENT = 'STATSCLIENT' + STATSCLIENT = 'STATSCLIENT', + DONOR = 'DONOR' } \ No newline at end of file From 4126d31a5e87aadd33f3c0b7878c71d428721243 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:38:07 +0100 Subject: [PATCH 02/27] Added copy of runnerController with some stuff reanames for donors ref #65 --- src/controllers/DonorController.ts | 106 +++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/controllers/DonorController.ts diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts new file mode 100644 index 0000000..4bd5ab6 --- /dev/null +++ b/src/controllers/DonorController.ts @@ -0,0 +1,106 @@ +import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; +import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; +import { getConnectionManager, Repository } from 'typeorm'; +import { RunnerGroupNeededError, RunnerIdsNotMatchingError, RunnerNotFoundError } from '../errors/RunnerErrors'; +import { RunnerGroupNotFoundError } from '../errors/RunnerGroupErrors'; +import { CreateRunner } from '../models/actions/CreateRunner'; +import { UpdateRunner } from '../models/actions/UpdateRunner'; +import { Donor } from '../models/entities/Donor'; +import { ResponseEmpty } from '../models/responses/ResponseEmpty'; +import { ResponseRunner } from '../models/responses/ResponseRunner'; + +@JsonController('/donors') +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) +export class DonorController { + private donorRepository: Repository; + + /** + * Gets the repository of this controller's model/entity. + */ + constructor() { + this.donorRepository = getConnectionManager().get().getRepository(Donor); + } + + @Get() + @Authorized("DONOR:GET") + @ResponseSchema(ResponseRunner, { isArray: true }) + @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) + async getAll() { + let responseRunners: ResponseRunner[] = new Array(); + const runners = await this.donorRepository.find({ relations: ['scans', 'group'] }); + runners.forEach(runner => { + responseRunners.push(new ResponseRunner(runner)); + }); + return responseRunners; + } + + @Get('/:id') + @Authorized("DONOR:GET") + @ResponseSchema(ResponseRunner) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OnUndefined(RunnerNotFoundError) + @OpenAPI({ description: 'Lists all information about the runner whose id got provided.' }) + async getOne(@Param('id') id: number) { + let runner = await this.donorRepository.findOne({ id: id }, { relations: ['scans', 'group'] }) + if (!runner) { throw new RunnerNotFoundError(); } + return new ResponseRunner(runner); + } + + @Post() + @Authorized("DONOR:CREATE") + @ResponseSchema(ResponseRunner) + @ResponseSchema(RunnerGroupNeededError) + @ResponseSchema(RunnerGroupNotFoundError) + @OpenAPI({ description: 'Create a new runner.
Please remeber to provide the runner\'s group\'s id.' }) + async post(@Body({ validate: true }) createRunner: CreateRunner) { + let runner; + try { + runner = await createRunner.toRunner(); + } catch (error) { + throw error; + } + + runner = await this.donorRepository.save(runner) + return new ResponseRunner(await this.donorRepository.findOne(runner, { relations: ['scans', 'group'] })); + } + + @Put('/:id') + @Authorized("DONOR:UPDATE") + @ResponseSchema(ResponseRunner) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @ResponseSchema(RunnerIdsNotMatchingError, { statusCode: 406 }) + @OpenAPI({ description: "Update the runner whose id you provided.
Please remember that ids can't be changed." }) + async put(@Param('id') id: number, @Body({ validate: true }) runner: UpdateRunner) { + let oldRunner = await this.donorRepository.findOne({ id: id }, { relations: ['group'] }); + + if (!oldRunner) { + throw new RunnerNotFoundError(); + } + + if (oldRunner.id != runner.id) { + throw new RunnerIdsNotMatchingError(); + } + + await this.donorRepository.save(await runner.updateRunner(oldRunner)); + return new ResponseRunner(await this.donorRepository.findOne({ id: id }, { relations: ['scans', 'group'] })); + } + + @Delete('/:id') + @Authorized("DONOR:DELETE") + @ResponseSchema(ResponseRunner) + @ResponseSchema(ResponseEmpty, { statusCode: 204 }) + @OnUndefined(204) + @OpenAPI({ description: 'Delete the runner whose id you provided.
If no runner with this id exists it will just return 204(no content).' }) + async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { + let runner = await this.donorRepository.findOne({ id: id }); + if (!runner) { return null; } + const responseRunner = await this.donorRepository.findOne(runner, { relations: ['scans', 'group'] }); + + if (!runner) { + throw new RunnerNotFoundError(); + } + + await this.donorRepository.delete(runner); + return new ResponseRunner(responseRunner); + } +} From e46cfa0d7789466cf9fef153de7eed0fc10c96bf Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:40:38 +0100 Subject: [PATCH 03/27] Added donor response class ref #65 --- src/models/responses/ResponseDonor.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/models/responses/ResponseDonor.ts diff --git a/src/models/responses/ResponseDonor.ts b/src/models/responses/ResponseDonor.ts new file mode 100644 index 0000000..89fea60 --- /dev/null +++ b/src/models/responses/ResponseDonor.ts @@ -0,0 +1,26 @@ +import { + IsBoolean +} from "class-validator"; +import { Donor } from '../entities/Donor'; +import { ResponseParticipant } from './ResponseParticipant'; + +/** + * Defines the donor response. +*/ +export class ResponseDonor extends ResponseParticipant { + + /** + * Does this donor need a receipt? + */ + @IsBoolean() + receiptNeeded: boolean; + + /** + * Creates a ResponseRunner object from a runner. + * @param runner The user the response shall be build for. + */ + public constructor(donor: Donor) { + super(donor); + this.receiptNeeded = donor.receiptNeeded; + } +} From 3df1db4ad8fa26deaaf7fe64af94c8893303d9c3 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:42:55 +0100 Subject: [PATCH 04/27] Added the base logic for donor getters ref #65 --- src/controllers/DonorController.ts | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 4bd5ab6..3f8a30b 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -6,8 +6,8 @@ import { RunnerGroupNotFoundError } from '../errors/RunnerGroupErrors'; import { CreateRunner } from '../models/actions/CreateRunner'; import { UpdateRunner } from '../models/actions/UpdateRunner'; import { Donor } from '../models/entities/Donor'; +import { ResponseDonor } from '../models/responses/ResponseDonor'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; -import { ResponseRunner } from '../models/responses/ResponseRunner'; @JsonController('/donors') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @@ -23,32 +23,32 @@ export class DonorController { @Get() @Authorized("DONOR:GET") - @ResponseSchema(ResponseRunner, { isArray: true }) + @ResponseSchema(ResponseDonor, { isArray: true }) @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) async getAll() { - let responseRunners: ResponseRunner[] = new Array(); - const runners = await this.donorRepository.find({ relations: ['scans', 'group'] }); - runners.forEach(runner => { - responseRunners.push(new ResponseRunner(runner)); + let responseDonors: ResponseDonor[] = new Array(); + const donors = await this.donorRepository.find(); + donors.forEach(donor => { + responseDonors.push(new ResponseDonor(donor)); }); - return responseRunners; + return responseDonors; } @Get('/:id') @Authorized("DONOR:GET") - @ResponseSchema(ResponseRunner) + @ResponseSchema(ResponseDonor) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(RunnerNotFoundError) @OpenAPI({ description: 'Lists all information about the runner whose id got provided.' }) async getOne(@Param('id') id: number) { - let runner = await this.donorRepository.findOne({ id: id }, { relations: ['scans', 'group'] }) - if (!runner) { throw new RunnerNotFoundError(); } - return new ResponseRunner(runner); + let donor = await this.donorRepository.findOne({ id: id }) + if (!donor) { throw new RunnerNotFoundError(); } + return new ResponseDonor(donor); } @Post() @Authorized("DONOR:CREATE") - @ResponseSchema(ResponseRunner) + @ResponseSchema(ResponseDonor) @ResponseSchema(RunnerGroupNeededError) @ResponseSchema(RunnerGroupNotFoundError) @OpenAPI({ description: 'Create a new runner.
Please remeber to provide the runner\'s group\'s id.' }) @@ -61,12 +61,12 @@ export class DonorController { } runner = await this.donorRepository.save(runner) - return new ResponseRunner(await this.donorRepository.findOne(runner, { relations: ['scans', 'group'] })); + return new ResponseDonor(await this.donorRepository.findOne(runner, { relations: ['scans', 'group'] })); } @Put('/:id') @Authorized("DONOR:UPDATE") - @ResponseSchema(ResponseRunner) + @ResponseSchema(ResponseDonor) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the runner whose id you provided.
Please remember that ids can't be changed." }) @@ -82,12 +82,12 @@ export class DonorController { } await this.donorRepository.save(await runner.updateRunner(oldRunner)); - return new ResponseRunner(await this.donorRepository.findOne({ id: id }, { relations: ['scans', 'group'] })); + return new ResponseDonor(await this.donorRepository.findOne({ id: id }, { relations: ['scans', 'group'] })); } @Delete('/:id') @Authorized("DONOR:DELETE") - @ResponseSchema(ResponseRunner) + @ResponseSchema(ResponseDonor) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) @OpenAPI({ description: 'Delete the runner whose id you provided.
If no runner with this id exists it will just return 204(no content).' }) @@ -101,6 +101,6 @@ export class DonorController { } await this.donorRepository.delete(runner); - return new ResponseRunner(responseRunner); + return new ResponseDonor(responseRunner); } } From 61a17b198f13a3c4b57d4811f74a531688e95045 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:45:01 +0100 Subject: [PATCH 05/27] Implemented basic donor deletion ref #65 --- src/controllers/DonorController.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 3f8a30b..5438daa 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -92,15 +92,17 @@ export class DonorController { @OnUndefined(204) @OpenAPI({ description: 'Delete the runner whose id you provided.
If no runner with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { - let runner = await this.donorRepository.findOne({ id: id }); - if (!runner) { return null; } - const responseRunner = await this.donorRepository.findOne(runner, { relations: ['scans', 'group'] }); + let donor = await this.donorRepository.findOne({ id: id }); + if (!donor) { return null; } + const responseDonor = await this.donorRepository.findOne(donor); - if (!runner) { + if (!donor) { throw new RunnerNotFoundError(); } - await this.donorRepository.delete(runner); - return new ResponseDonor(responseRunner); + //TODO: DELETE DONATIONS AND WARN FOR FORCE + + await this.donorRepository.delete(donor); + return new ResponseDonor(responseDonor); } } From a83fedc9b8cefb25105149aa82988c8aa263a0bb Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:47:06 +0100 Subject: [PATCH 06/27] Added first donor-specific errors ref #65 --- src/controllers/DonorController.ts | 20 +++++++++----------- src/errors/DonorErrors.ts | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 src/errors/DonorErrors.ts diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 5438daa..6b8fc7b 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -1,8 +1,8 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; -import { RunnerGroupNeededError, RunnerIdsNotMatchingError, RunnerNotFoundError } from '../errors/RunnerErrors'; -import { RunnerGroupNotFoundError } from '../errors/RunnerGroupErrors'; +import { DonorIdsNotMatchingError, DonorNotFoundError } from '../errors/DonorErrors'; +import { RunnerIdsNotMatchingError } from '../errors/RunnerErrors'; import { CreateRunner } from '../models/actions/CreateRunner'; import { UpdateRunner } from '../models/actions/UpdateRunner'; import { Donor } from '../models/entities/Donor'; @@ -37,20 +37,18 @@ export class DonorController { @Get('/:id') @Authorized("DONOR:GET") @ResponseSchema(ResponseDonor) - @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OnUndefined(RunnerNotFoundError) + @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) + @OnUndefined(DonorNotFoundError) @OpenAPI({ description: 'Lists all information about the runner whose id got provided.' }) async getOne(@Param('id') id: number) { let donor = await this.donorRepository.findOne({ id: id }) - if (!donor) { throw new RunnerNotFoundError(); } + if (!donor) { throw new DonorNotFoundError(); } return new ResponseDonor(donor); } @Post() @Authorized("DONOR:CREATE") @ResponseSchema(ResponseDonor) - @ResponseSchema(RunnerGroupNeededError) - @ResponseSchema(RunnerGroupNotFoundError) @OpenAPI({ description: 'Create a new runner.
Please remeber to provide the runner\'s group\'s id.' }) async post(@Body({ validate: true }) createRunner: CreateRunner) { let runner; @@ -67,14 +65,14 @@ export class DonorController { @Put('/:id') @Authorized("DONOR:UPDATE") @ResponseSchema(ResponseDonor) - @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @ResponseSchema(RunnerIdsNotMatchingError, { statusCode: 406 }) + @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) + @ResponseSchema(DonorIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the runner whose id you provided.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) runner: UpdateRunner) { let oldRunner = await this.donorRepository.findOne({ id: id }, { relations: ['group'] }); if (!oldRunner) { - throw new RunnerNotFoundError(); + throw new DonorNotFoundError(); } if (oldRunner.id != runner.id) { @@ -97,7 +95,7 @@ export class DonorController { const responseDonor = await this.donorRepository.findOne(donor); if (!donor) { - throw new RunnerNotFoundError(); + throw new DonorNotFoundError(); } //TODO: DELETE DONATIONS AND WARN FOR FORCE diff --git a/src/errors/DonorErrors.ts b/src/errors/DonorErrors.ts new file mode 100644 index 0000000..94a844a --- /dev/null +++ b/src/errors/DonorErrors.ts @@ -0,0 +1,25 @@ +import { IsString } from 'class-validator'; +import { NotAcceptableError, NotFoundError } from 'routing-controllers'; + +/** + * Error to throw when a donor couldn't be found. + */ +export class DonorNotFoundError extends NotFoundError { + @IsString() + name = "DonorNotFoundError" + + @IsString() + message = "Donor not found!" +} + +/** + * Error to throw when two donors' ids don't match. + * Usually occurs when a user tries to change a donor's id. + */ +export class DonorIdsNotMatchingError extends NotAcceptableError { + @IsString() + name = "DonorIdsNotMatchingError" + + @IsString() + message = "The ids don't match! \n And if you wanted to change a donor's id: This isn't allowed!" +} \ No newline at end of file From 557608e3181ec3b2c6a6cde3a6405509356e97d0 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:51:33 +0100 Subject: [PATCH 07/27] Added everything for basic donor creation ref #65 --- src/controllers/DonorController.ts | 12 +++++------ src/models/actions/CreateDonor.ts | 33 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 src/models/actions/CreateDonor.ts diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 6b8fc7b..308825a 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -3,7 +3,7 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { DonorIdsNotMatchingError, DonorNotFoundError } from '../errors/DonorErrors'; import { RunnerIdsNotMatchingError } from '../errors/RunnerErrors'; -import { CreateRunner } from '../models/actions/CreateRunner'; +import { CreateDonor } from '../models/actions/CreateDonor'; import { UpdateRunner } from '../models/actions/UpdateRunner'; import { Donor } from '../models/entities/Donor'; import { ResponseDonor } from '../models/responses/ResponseDonor'; @@ -50,16 +50,16 @@ export class DonorController { @Authorized("DONOR:CREATE") @ResponseSchema(ResponseDonor) @OpenAPI({ description: 'Create a new runner.
Please remeber to provide the runner\'s group\'s id.' }) - async post(@Body({ validate: true }) createRunner: CreateRunner) { - let runner; + async post(@Body({ validate: true }) createRunner: CreateDonor) { + let donor; try { - runner = await createRunner.toRunner(); + donor = await createRunner.toDonor(); } catch (error) { throw error; } - runner = await this.donorRepository.save(runner) - return new ResponseDonor(await this.donorRepository.findOne(runner, { relations: ['scans', 'group'] })); + donor = await this.donorRepository.save(donor) + return new ResponseDonor(await this.donorRepository.findOne(donor)); } @Put('/:id') diff --git a/src/models/actions/CreateDonor.ts b/src/models/actions/CreateDonor.ts new file mode 100644 index 0000000..8520f5a --- /dev/null +++ b/src/models/actions/CreateDonor.ts @@ -0,0 +1,33 @@ +import { IsBoolean, IsOptional } from 'class-validator'; +import { Donor } from '../entities/Donor'; +import { CreateParticipant } from './CreateParticipant'; + +/** + * This classed is used to create a new Donor entity from a json body (post request). + */ +export class CreateDonor extends CreateParticipant { + + /** + * Does this donor need a receipt? + */ + @IsBoolean() + @IsOptional() + receiptNeeded: boolean = false; + + /** + * Creates a new Donor entity from this. + */ + public async toDonor(): Promise { + let newDonor: Donor = new Donor(); + + newDonor.firstname = this.firstname; + newDonor.middlename = this.middlename; + newDonor.lastname = this.lastname; + newDonor.phone = this.phone; + newDonor.email = this.email; + newDonor.receiptNeeded = this.receiptNeeded; + newDonor.address = await this.getAddress(); + + return newDonor; + } +} \ No newline at end of file From ab67e5f4aaa6deeb79af1ebbf2aaff0675ce58e9 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 16:55:27 +0100 Subject: [PATCH 08/27] Added basic runner updateing ref #65 --- src/controllers/DonorController.ts | 17 ++++++------- src/models/actions/CreateDonor.ts | 2 +- src/models/actions/UpdateDonor.ts | 39 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 src/models/actions/UpdateDonor.ts diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 308825a..399421f 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -2,9 +2,8 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { DonorIdsNotMatchingError, DonorNotFoundError } from '../errors/DonorErrors'; -import { RunnerIdsNotMatchingError } from '../errors/RunnerErrors'; import { CreateDonor } from '../models/actions/CreateDonor'; -import { UpdateRunner } from '../models/actions/UpdateRunner'; +import { UpdateDonor } from '../models/actions/UpdateDonor'; import { Donor } from '../models/entities/Donor'; import { ResponseDonor } from '../models/responses/ResponseDonor'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; @@ -68,19 +67,19 @@ export class DonorController { @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) @ResponseSchema(DonorIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the runner whose id you provided.
Please remember that ids can't be changed." }) - async put(@Param('id') id: number, @Body({ validate: true }) runner: UpdateRunner) { - let oldRunner = await this.donorRepository.findOne({ id: id }, { relations: ['group'] }); + async put(@Param('id') id: number, @Body({ validate: true }) donor: UpdateDonor) { + let oldDonor = await this.donorRepository.findOne({ id: id }); - if (!oldRunner) { + if (!oldDonor) { throw new DonorNotFoundError(); } - if (oldRunner.id != runner.id) { - throw new RunnerIdsNotMatchingError(); + if (oldDonor.id != donor.id) { + throw new DonorIdsNotMatchingError(); } - await this.donorRepository.save(await runner.updateRunner(oldRunner)); - return new ResponseDonor(await this.donorRepository.findOne({ id: id }, { relations: ['scans', 'group'] })); + await this.donorRepository.save(await donor.updateDonor(oldDonor)); + return new ResponseDonor(await this.donorRepository.findOne({ id: id })); } @Delete('/:id') diff --git a/src/models/actions/CreateDonor.ts b/src/models/actions/CreateDonor.ts index 8520f5a..ec7c983 100644 --- a/src/models/actions/CreateDonor.ts +++ b/src/models/actions/CreateDonor.ts @@ -12,7 +12,7 @@ export class CreateDonor extends CreateParticipant { */ @IsBoolean() @IsOptional() - receiptNeeded: boolean = false; + receiptNeeded?: boolean = false; /** * Creates a new Donor entity from this. diff --git a/src/models/actions/UpdateDonor.ts b/src/models/actions/UpdateDonor.ts new file mode 100644 index 0000000..9ace6f9 --- /dev/null +++ b/src/models/actions/UpdateDonor.ts @@ -0,0 +1,39 @@ +import { IsBoolean, IsInt, IsOptional } from 'class-validator'; +import { Donor } from '../entities/Donor'; +import { CreateParticipant } from './CreateParticipant'; + +/** + * This class is used to update a Donor entity (via put request). + */ +export class UpdateDonor extends CreateParticipant { + + /** + * The updated donor's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). + */ + @IsInt() + id: number; + + /** + * Does the updated donor need a receipt? + */ + @IsBoolean() + @IsOptional() + receiptNeeded?: boolean; + + + /** + * Updates a provided Donor entity based on this. + */ + public async updateDonor(donor: Donor): Promise { + donor.firstname = this.firstname; + donor.middlename = this.middlename; + donor.lastname = this.lastname; + donor.phone = this.phone; + donor.email = this.email; + donor.receiptNeeded = this.receiptNeeded; + donor.address = await this.getAddress(); + + return donor; + } +} \ No newline at end of file From c9ba69792f326b70d68ee1529d513f0fc122d375 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 17:07:17 +0100 Subject: [PATCH 09/27] Extended todo w/ issue link ref #65 --- src/controllers/DonorController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 399421f..54a5ba4 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -97,7 +97,7 @@ export class DonorController { throw new DonorNotFoundError(); } - //TODO: DELETE DONATIONS AND WARN FOR FORCE + //TODO: DELETE DONATIONS AND WARN FOR FORCE (https://git.odit.services/lfk/backend/issues/66) await this.donorRepository.delete(donor); return new ResponseDonor(responseDonor); From 1dc438beb25e81671980fa7a5704879169053985 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 18:12:18 +0100 Subject: [PATCH 10/27] Mitigated circular dependency (to be fixed) ref #65 --- src/models/actions/CreateRunnerOrganisation.ts | 2 +- src/models/actions/UpdateRunnerOrganisation.ts | 2 +- src/models/entities/Address.ts | 11 +++++------ src/models/entities/Donation.ts | 6 +++--- src/models/entities/Donor.ts | 10 +++++++++- src/models/entities/Participant.ts | 10 +--------- src/models/entities/RunnerOrganisation.ts | 17 ++++++++--------- .../responses/ResponseRunnerOrganisation.ts | 2 +- 8 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/models/actions/CreateRunnerOrganisation.ts b/src/models/actions/CreateRunnerOrganisation.ts index 017675e..a0733de 100644 --- a/src/models/actions/CreateRunnerOrganisation.ts +++ b/src/models/actions/CreateRunnerOrganisation.ts @@ -41,7 +41,7 @@ export class CreateRunnerOrganisation extends CreateRunnerGroup { newRunnerOrganisation.name = this.name; newRunnerOrganisation.contact = await this.getContact(); - newRunnerOrganisation.address = await this.getAddress(); + // newRunnerOrganisation.address = await this.getAddress(); return newRunnerOrganisation; } diff --git a/src/models/actions/UpdateRunnerOrganisation.ts b/src/models/actions/UpdateRunnerOrganisation.ts index 3a5b1fb..9a2cafa 100644 --- a/src/models/actions/UpdateRunnerOrganisation.ts +++ b/src/models/actions/UpdateRunnerOrganisation.ts @@ -45,7 +45,7 @@ export class UpdateRunnerOrganisation extends CreateRunnerGroup { organisation.name = this.name; organisation.contact = await this.getContact(); - organisation.address = await this.getAddress(); + // organisation.address = await this.getAddress(); return organisation; } diff --git a/src/models/entities/Address.ts b/src/models/entities/Address.ts index 99d69ce..bd3cd32 100644 --- a/src/models/entities/Address.ts +++ b/src/models/entities/Address.ts @@ -8,7 +8,6 @@ import { import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { config } from '../../config'; import { Participant } from "./Participant"; -import { RunnerOrganisation } from "./RunnerOrganisation"; /** * Defines the Address entity. @@ -82,9 +81,9 @@ export class Address { @OneToMany(() => Participant, participant => participant.address, { nullable: true }) participants: Participant[]; - /** - * Used to link the address to runner groups. - */ - @OneToMany(() => RunnerOrganisation, group => group.address, { nullable: true }) - groups: RunnerOrganisation[]; + // /** + // * Used to link the address to runner groups. + // */ + // @OneToMany(() => RunnerOrganisation, group => group.address, { nullable: true }) + // groups: RunnerOrganisation[]; } diff --git a/src/models/entities/Donation.ts b/src/models/entities/Donation.ts index 3ddc272..eea23b5 100644 --- a/src/models/entities/Donation.ts +++ b/src/models/entities/Donation.ts @@ -3,7 +3,7 @@ import { IsNotEmpty } from "class-validator"; import { Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; -import { Participant } from "./Participant"; +import { Donor } from './Donor'; /** * Defines the Donation entity. @@ -24,8 +24,8 @@ export abstract class Donation { * The donations's donor. */ @IsNotEmpty() - @ManyToOne(() => Participant, donor => donor.donations) - donor: Participant; + @ManyToOne(() => Donor, donor => donor.donations) + donor: Donor; /** * The donation's amount in cents (or whatever your currency's smallest unit is.). diff --git a/src/models/entities/Donor.ts b/src/models/entities/Donor.ts index c0f914e..188ed09 100644 --- a/src/models/entities/Donor.ts +++ b/src/models/entities/Donor.ts @@ -1,5 +1,6 @@ import { IsBoolean } from "class-validator"; -import { ChildEntity, Column } from "typeorm"; +import { ChildEntity, Column, OneToMany } from "typeorm"; +import { Donation } from './Donation'; import { Participant } from "./Participant"; /** @@ -14,4 +15,11 @@ export class Donor extends Participant { @Column() @IsBoolean() receiptNeeded: boolean = false; + + /** + * Used to link the participant as the donor of a donation. + * Attention: Only runner's can be associated as a distanceDonations distance source. + */ + @OneToMany(() => Donation, donation => donation.donor, { nullable: true }) + donations: Donation[]; } \ No newline at end of file diff --git a/src/models/entities/Participant.ts b/src/models/entities/Participant.ts index e2e2263..19af17e 100644 --- a/src/models/entities/Participant.ts +++ b/src/models/entities/Participant.ts @@ -7,10 +7,9 @@ import { IsString } from "class-validator"; -import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; import { config } from '../../config'; import { Address } from "./Address"; -import { Donation } from "./Donation"; /** * Defines the Participant entity. @@ -74,11 +73,4 @@ export abstract class Participant { @IsOptional() @IsEmail() email?: string; - - /** - * Used to link the participant as the donor of a donation. - * Attention: Only runner's can be associated as a distanceDonations distance source. - */ - @OneToMany(() => Donation, donation => donation.donor, { nullable: true }) - donations: Donation[]; } \ No newline at end of file diff --git a/src/models/entities/RunnerOrganisation.ts b/src/models/entities/RunnerOrganisation.ts index 877784b..7110b09 100644 --- a/src/models/entities/RunnerOrganisation.ts +++ b/src/models/entities/RunnerOrganisation.ts @@ -1,6 +1,5 @@ -import { IsInt, IsOptional } from "class-validator"; -import { ChildEntity, ManyToOne, OneToMany } from "typeorm"; -import { Address } from "./Address"; +import { IsInt } from "class-validator"; +import { ChildEntity, OneToMany } from "typeorm"; import { Runner } from './Runner'; import { RunnerGroup } from "./RunnerGroup"; import { RunnerTeam } from "./RunnerTeam"; @@ -12,12 +11,12 @@ import { RunnerTeam } from "./RunnerTeam"; @ChildEntity() export class RunnerOrganisation extends RunnerGroup { - /** - * The organisations's address. - */ - @IsOptional() - @ManyToOne(() => Address, address => address.groups, { nullable: true }) - address?: Address; + // /** + // * The organisations's address. + // */ + // @IsOptional() + // @ManyToOne(() => Address, address => address.groups, { nullable: true }) + // address?: Address; /** * The organisation's teams. diff --git a/src/models/responses/ResponseRunnerOrganisation.ts b/src/models/responses/ResponseRunnerOrganisation.ts index edc1ff0..8e31a71 100644 --- a/src/models/responses/ResponseRunnerOrganisation.ts +++ b/src/models/responses/ResponseRunnerOrganisation.ts @@ -32,7 +32,7 @@ export class ResponseRunnerOrganisation extends ResponseRunnerGroup { */ public constructor(org: RunnerOrganisation) { super(org); - this.address = org.address; + // this.address = org.address; this.teams = org.teams; } } From 53548ba7a698bef27560adb18aca07e4a587c155 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 18:19:40 +0100 Subject: [PATCH 11/27] Fixed not null constraint ref #56 --- src/models/entities/Runner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/entities/Runner.ts b/src/models/entities/Runner.ts index 1c509d6..5c51c11 100644 --- a/src/models/entities/Runner.ts +++ b/src/models/entities/Runner.ts @@ -18,7 +18,7 @@ export class Runner extends Participant { * Can be a runner team or organisation. */ @IsNotEmpty() - @ManyToOne(() => RunnerGroup, group => group.runners, { nullable: false }) + @ManyToOne(() => RunnerGroup, group => group.runners) group: RunnerGroup; /** From 52cdd41ec869318d75aead3043b3541487916b5a Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 18:19:40 +0100 Subject: [PATCH 12/27] Fixed not null constraint ref #65 --- src/models/entities/Runner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/entities/Runner.ts b/src/models/entities/Runner.ts index 1c509d6..5c51c11 100644 --- a/src/models/entities/Runner.ts +++ b/src/models/entities/Runner.ts @@ -18,7 +18,7 @@ export class Runner extends Participant { * Can be a runner team or organisation. */ @IsNotEmpty() - @ManyToOne(() => RunnerGroup, group => group.runners, { nullable: false }) + @ManyToOne(() => RunnerGroup, group => group.runners) group: RunnerGroup; /** From 335d4e24daeccf06b559c077e26469c5d6c8a91c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 18:28:22 +0100 Subject: [PATCH 13/27] Added address check for donors that want a receipt ref #65 --- src/errors/DonorErrors.ts | 11 +++++++++++ src/models/actions/CreateDonor.ts | 7 ++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/errors/DonorErrors.ts b/src/errors/DonorErrors.ts index 94a844a..0cd534e 100644 --- a/src/errors/DonorErrors.ts +++ b/src/errors/DonorErrors.ts @@ -22,4 +22,15 @@ export class DonorIdsNotMatchingError extends NotAcceptableError { @IsString() message = "The ids don't match! \n And if you wanted to change a donor's id: This isn't allowed!" +} + +/** + * Error to throw when a donor needs a receipt, but no address is associated with them. + */ +export class DonorReceiptAddressNeededError extends NotAcceptableError { + @IsString() + name = "DonorReceiptAddressNeededError" + + @IsString() + message = "An address is needed to create a receipt for a donor. \n You didn't provide one." } \ No newline at end of file diff --git a/src/models/actions/CreateDonor.ts b/src/models/actions/CreateDonor.ts index ec7c983..bf4e206 100644 --- a/src/models/actions/CreateDonor.ts +++ b/src/models/actions/CreateDonor.ts @@ -1,4 +1,5 @@ import { IsBoolean, IsOptional } from 'class-validator'; +import { DonorReceiptAddressNeededError } from '../../errors/DonorErrors'; import { Donor } from '../entities/Donor'; import { CreateParticipant } from './CreateParticipant'; @@ -25,8 +26,12 @@ export class CreateDonor extends CreateParticipant { newDonor.lastname = this.lastname; newDonor.phone = this.phone; newDonor.email = this.email; - newDonor.receiptNeeded = this.receiptNeeded; newDonor.address = await this.getAddress(); + newDonor.receiptNeeded = this.receiptNeeded; + + if (this.receiptNeeded == true && this.email == "" && this.address == null) { + throw new DonorReceiptAddressNeededError() + } return newDonor; } From 2594a607dc4315a8fdfe42c8b961b6c3a30b4428 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 18:30:03 +0100 Subject: [PATCH 14/27] Added address check for donors that want a receipt on update ref #65 --- src/models/actions/CreateDonor.ts | 2 +- src/models/actions/UpdateDonor.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/models/actions/CreateDonor.ts b/src/models/actions/CreateDonor.ts index bf4e206..25a631c 100644 --- a/src/models/actions/CreateDonor.ts +++ b/src/models/actions/CreateDonor.ts @@ -29,7 +29,7 @@ export class CreateDonor extends CreateParticipant { newDonor.address = await this.getAddress(); newDonor.receiptNeeded = this.receiptNeeded; - if (this.receiptNeeded == true && this.email == "" && this.address == null) { + if (this.receiptNeeded == true && this.address == null) { throw new DonorReceiptAddressNeededError() } diff --git a/src/models/actions/UpdateDonor.ts b/src/models/actions/UpdateDonor.ts index 9ace6f9..b7139c8 100644 --- a/src/models/actions/UpdateDonor.ts +++ b/src/models/actions/UpdateDonor.ts @@ -1,4 +1,5 @@ import { IsBoolean, IsInt, IsOptional } from 'class-validator'; +import { DonorReceiptAddressNeededError } from '../../errors/DonorErrors'; import { Donor } from '../entities/Donor'; import { CreateParticipant } from './CreateParticipant'; @@ -34,6 +35,10 @@ export class UpdateDonor extends CreateParticipant { donor.receiptNeeded = this.receiptNeeded; donor.address = await this.getAddress(); + if (this.receiptNeeded == true && this.address == null) { + throw new DonorReceiptAddressNeededError() + } + return donor; } } \ No newline at end of file From 599296c4e3736bf9aadbc32067cd2ff8c39f0f17 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:01:55 +0100 Subject: [PATCH 15/27] Removed addresses from tests until the circular dependencies are solved ref #65 --- src/controllers/RunnerOrganisationController.ts | 10 +++++----- src/tests/runnerOrgs/org_add.spec.ts | 4 ++-- src/tests/runnerOrgs/org_delete.spec.ts | 4 ++-- src/tests/runnerOrgs/org_update.spec.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index e10d415..be25805 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -29,7 +29,7 @@ export class RunnerOrganisationController { @OpenAPI({ description: 'Lists all organisations.
This includes their address, contact and teams (if existing/associated).' }) async getAll() { let responseTeams: ResponseRunnerOrganisation[] = new Array(); - const runners = await this.runnerOrganisationRepository.find({ relations: ['address', 'contact', 'teams'] }); + const runners = await this.runnerOrganisationRepository.find({ relations: [/*'address',*/ 'contact', 'teams'] }); runners.forEach(runner => { responseTeams.push(new ResponseRunnerOrganisation(runner)); }); @@ -43,7 +43,7 @@ export class RunnerOrganisationController { @OnUndefined(RunnerOrganisationNotFoundError) @OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' }) async getOne(@Param('id') id: number) { - let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['address', 'contact', 'teams'] }); + let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: [/*'address',*/ 'contact', 'teams'] }); if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); } return new ResponseRunnerOrganisation(runnerOrg); } @@ -62,7 +62,7 @@ export class RunnerOrganisationController { runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation); - return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['address', 'contact', 'teams'] })); + return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: [/*'address',*/ 'contact', 'teams'] })); } @Put('/:id') @@ -84,7 +84,7 @@ export class RunnerOrganisationController { await this.runnerOrganisationRepository.save(await updateOrganisation.updateRunnerOrganisation(oldRunnerOrganisation)); - return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['address', 'contact', 'teams'] })); + return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: [/*'address',*/ 'contact', 'teams'] })); } @Delete('/:id') @@ -98,7 +98,7 @@ export class RunnerOrganisationController { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let organisation = await this.runnerOrganisationRepository.findOne({ id: id }); if (!organisation) { return null; } - let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['address', 'contact', 'runners', 'teams'] }); + let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: [/*'address',*/ 'contact', 'runners', 'teams'] }); if (!force) { if (runnerOrganisation.teams.length != 0) { diff --git a/src/tests/runnerOrgs/org_add.spec.ts b/src/tests/runnerOrgs/org_add.spec.ts index 6ee0606..62aa067 100644 --- a/src/tests/runnerOrgs/org_add.spec.ts +++ b/src/tests/runnerOrgs/org_add.spec.ts @@ -56,7 +56,7 @@ describe('adding + getting from all orgs', () => { expect(added_org).toEqual({ "name": "test123", "contact": null, - "address": null, + // "address": null, "teams": [] }) }); @@ -83,7 +83,7 @@ describe('adding + getting explicitly', () => { expect(added_org2).toEqual({ "name": "test123", "contact": null, - "address": null, + // "address": null, "teams": [] }) }); diff --git a/src/tests/runnerOrgs/org_delete.spec.ts b/src/tests/runnerOrgs/org_delete.spec.ts index 08891f8..9598704 100644 --- a/src/tests/runnerOrgs/org_delete.spec.ts +++ b/src/tests/runnerOrgs/org_delete.spec.ts @@ -44,7 +44,7 @@ describe('adding + deletion (successfull)', () => { expect(added_org2).toEqual({ "name": "test123", "contact": null, - "address": null, + // "address": null, "teams": [] }); }); @@ -121,7 +121,7 @@ describe('adding + deletion with teams still existing (with force)', () => { expect(added_org2).toEqual({ "name": "test123", "contact": null, - "address": null + // "address": null }); }); it('check if org really was deleted', async () => { diff --git a/src/tests/runnerOrgs/org_update.spec.ts b/src/tests/runnerOrgs/org_update.spec.ts index e6a1055..a410521 100644 --- a/src/tests/runnerOrgs/org_update.spec.ts +++ b/src/tests/runnerOrgs/org_update.spec.ts @@ -32,7 +32,7 @@ describe('adding + updating name', () => { "id": added_org_id, "name": "testlelele", "contact": null, - "address": null, + // "address": null, }, axios_config); expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") @@ -42,7 +42,7 @@ describe('adding + updating name', () => { expect(added_org2).toEqual({ "name": "testlelele", "contact": null, - "address": null, + // "address": null, "teams": [] }) }); @@ -65,7 +65,7 @@ describe('adding + try updating id (should return 406)', () => { "id": added_org_id + 1, "name": "testlelele", "contact": null, - "address": null, + // "address": null, }, axios_config); expect(res2.status).toEqual(406); expect(res2.headers['content-type']).toContain("application/json") From 82a0e194cbac2b9191e1361909dbcb979865bda3 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:02:16 +0100 Subject: [PATCH 16/27] Updated track tests for paralellism ref #65 --- src/tests/tracks.spec.ts | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/tests/tracks.spec.ts b/src/tests/tracks.spec.ts index 4646878..81e4850 100644 --- a/src/tests/tracks.spec.ts +++ b/src/tests/tracks.spec.ts @@ -72,30 +72,26 @@ describe('adding + getting tracks', () => { }); // --------------- describe('adding + getting + updating', () => { - let added_track_id + let added_track; it('correct distance input should return 200', async () => { const res = await axios.post(base + '/api/tracks', { "name": "string", "distance": 1500 }, axios_config); expect(res.status).toEqual(200); - expect(res.headers['content-type']).toContain("application/json") + expect(res.headers['content-type']).toContain("application/json"); + added_track = res.data; }); it('get should return 200', async () => { - const res1 = await axios.get(base + '/api/tracks', axios_config); + const res1 = await axios.get(base + '/api/tracks/' + added_track.id, axios_config); expect(res1.status).toEqual(200); expect(res1.headers['content-type']).toContain("application/json") - let added_track = res1.data[res1.data.length - 1] - added_track_id = added_track.id - delete added_track.id - expect(added_track).toEqual({ - "name": "string", - "distance": 1500 - }) + const compareTrack = res1.data; + expect(compareTrack).toEqual(added_track) }) it('get should return 200', async () => { - const res2 = await axios.put(base + '/api/tracks/' + added_track_id, { - "id": added_track_id, + const res2 = await axios.put(base + '/api/tracks/' + added_track.id, { + "id": added_track.id, "name": "apitrack", "distance": 5100 }, axios_config); @@ -103,10 +99,10 @@ describe('adding + getting + updating', () => { expect(res2.headers['content-type']).toContain("application/json") }) it('get should return 200', async () => { - const res3 = await axios.get(base + '/api/tracks', axios_config); + const res3 = await axios.get(base + '/api/tracks/' + added_track.id, axios_config); expect(res3.status).toEqual(200); expect(res3.headers['content-type']).toContain("application/json") - let added_track2 = res3.data[res3.data.length - 1] + let added_track2 = res3.data; delete added_track2.id expect(added_track2).toEqual({ "name": "apitrack", From b337ab424d2a350d662910445fcbdb1a5e35c070 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:02:31 +0100 Subject: [PATCH 17/27] Added donor get tests ref #65 --- src/tests/donors/donor_get.spec.ts | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/tests/donors/donor_get.spec.ts diff --git a/src/tests/donors/donor_get.spec.ts b/src/tests/donors/donor_get.spec.ts new file mode 100644 index 0000000..fd9d17d --- /dev/null +++ b/src/tests/donors/donor_get.spec.ts @@ -0,0 +1,57 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('GET /api/donors', () => { + it('basic get should return 200', async () => { + const res = await axios.get(base + '/api/donors', axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('GET /api/donors/0', () => { + it('basic get should return 404', async () => { + const res = await axios.get(base + '/api/donors/0', axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('GET /api/donors after adding', () => { + let added_donor; + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('explicit get should return 200', async () => { + const res3 = await axios.get(base + '/api/donors/' + added_donor.id, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + let gotten_donor = res3.data + expect(gotten_donor).toEqual(added_donor); + }); + it('get from all runners should return 200', async () => { + const res4 = await axios.get(base + '/api/donors/', axios_config); + expect(res4.status).toEqual(200); + expect(res4.headers['content-type']).toContain("application/json") + let gotten_donors = res4.data + expect(gotten_donors).toContainEqual(added_donor); + }); +}); \ No newline at end of file From e4c1930dd1ac1c95ca0449d81dd2251f570729a5 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:10:23 +0100 Subject: [PATCH 18/27] Added donor post (add) tests ref #65 --- src/tests/donors/donor_add.spec.ts | 84 ++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/tests/donors/donor_add.spec.ts diff --git a/src/tests/donors/donor_add.spec.ts b/src/tests/donors/donor_add.spec.ts new file mode 100644 index 0000000..f7ee4c8 --- /dev/null +++ b/src/tests/donors/donor_add.spec.ts @@ -0,0 +1,84 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +// --------------- +describe('POST /api/donors with errors', () => { + it('creating a new donor without any parameters should return 400', async () => { + const res1 = await axios.post(base + '/api/donors', null, axios_config); + expect(res1.status).toEqual(400); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new donor without a last name should return 400', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "middlename": "middle" + }, axios_config); + expect(res2.status).toEqual(400); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new donor with a invalid address should return 404', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "middlename": "middle", + "lastname": "last", + "address": 0 + }, axios_config); + expect(res2.status).toEqual(404); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new donor with a invalid phone number should return 400', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "middlename": "middle", + "lastname": "last", + "phone": "123" + }, axios_config); + expect(res2.status).toEqual(400); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new donor with a invalid mail address should return 400', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "string", + "middlename": "string", + "lastname": "string", + "phone": null, + "email": "123", + }, axios_config); + expect(res2.status).toEqual(400); + expect(res2.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('POST /api/donors working', () => { + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new donor with all non-relationship optional params should return 200', async () => { + const res3 = await axios.post(base + '/api/donors', { + "firstname": "first", + "middlename": "middle", + "lastname": "last", + "receiptNeeded": false + }, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); \ No newline at end of file From f9e314bf9f2c0a23e585f5a093b1b46a92af54cd Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:12:02 +0100 Subject: [PATCH 19/27] Added donor add test for address needed error ref #65 --- src/tests/donors/donor_add.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/tests/donors/donor_add.spec.ts b/src/tests/donors/donor_add.spec.ts index f7ee4c8..8022184 100644 --- a/src/tests/donors/donor_add.spec.ts +++ b/src/tests/donors/donor_add.spec.ts @@ -60,6 +60,16 @@ describe('POST /api/donors with errors', () => { expect(res2.status).toEqual(400); expect(res2.headers['content-type']).toContain("application/json") }); + it('creating a new donor without an address but with receiptNeeded=true 406', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "string", + "middlename": "string", + "lastname": "string", + "receiptNeeded": true + }, axios_config); + expect(res2.status).toEqual(406); + expect(res2.headers['content-type']).toContain("application/json") + }); }); // --------------- describe('POST /api/donors working', () => { From 17c82ff4098dc42a99fae445fc298471b295cb0a Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:13:59 +0100 Subject: [PATCH 20/27] Added donor delete tests ref #65 --- src/tests/donors/donor_delete.spec.ts | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/tests/donors/donor_delete.spec.ts diff --git a/src/tests/donors/donor_delete.spec.ts b/src/tests/donors/donor_delete.spec.ts new file mode 100644 index 0000000..63e10fe --- /dev/null +++ b/src/tests/donors/donor_delete.spec.ts @@ -0,0 +1,47 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('adding + deletion (non-existant)', () => { + it('delete', async () => { + const res2 = await axios.delete(base + '/api/donors/0', axios_config); + expect(res2.status).toEqual(204); + }); +}); +// --------------- +describe('add+delete', () => { + let added_donor; + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('delete donor', async () => { + const res3 = await axios.delete(base + '/api/donors/' + added_donor.id, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + let deleted_runner = res3.data + expect(deleted_runner).toEqual(added_donor); + }); + it('check if donor really was deleted', async () => { + const res4 = await axios.get(base + '/api/donors/' + added_donor.id, axios_config); + expect(res4.status).toEqual(404); + expect(res4.headers['content-type']).toContain("application/json") + }); +}); \ No newline at end of file From deb13674b255fde6f367e09bf624ac084a5f44de Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:25:58 +0100 Subject: [PATCH 21/27] Added donor put (update) tests ref #65 --- src/tests/donors/donor_update.spec.ts | 75 +++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/tests/donors/donor_update.spec.ts diff --git a/src/tests/donors/donor_update.spec.ts b/src/tests/donors/donor_update.spec.ts new file mode 100644 index 0000000..26f6eb6 --- /dev/null +++ b/src/tests/donors/donor_update.spec.ts @@ -0,0 +1,75 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('Update donor name after adding', () => { + let added_donor; + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('valid update should return 200', async () => { + let donor_copy = added_donor + donor_copy.firstname = "second" + const res3 = await axios.put(base + '/api/donors/' + added_donor.id, donor_copy, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + let updated_donor = res3.data + expect(updated_donor).toEqual(donor_copy); + }); +}); +// --------------- +describe('Update donor id after adding(should fail)', () => { + let added_donor; + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('invalid update should return 406', async () => { + added_donor.id++; + const res3 = await axios.put(base + '/api/donors/' + (added_donor.id - 1), added_donor, axios_config); + expect(res3.status).toEqual(406); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('Update donor without address but receiptNeeded=true should fail', () => { + let added_donor; + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last", + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('invalid update should return 406', async () => { + added_donor.receiptNeeded = true; + const res3 = await axios.put(base + '/api/donors/' + added_donor.id, added_donor, axios_config); + expect(res3.status).toEqual(406); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); \ No newline at end of file From 9b5d16ae92045580a748c820d0af64950cf2fdfd Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:39:02 +0100 Subject: [PATCH 22/27] Added todo relateing to the bugfix issue ref #65 #68 --- src/models/entities/Address.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/entities/Address.ts b/src/models/entities/Address.ts index bd3cd32..afa10da 100644 --- a/src/models/entities/Address.ts +++ b/src/models/entities/Address.ts @@ -81,6 +81,7 @@ export class Address { @OneToMany(() => Participant, participant => participant.address, { nullable: true }) participants: Participant[]; + //TODO: #68 // /** // * Used to link the address to runner groups. // */ From 2c47436259260a3e1d340ae64e69da1496a685ec Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:56:04 +0100 Subject: [PATCH 23/27] Implemented a possible bugfix ref #68 --- src/models/entities/Address.ts | 13 +++---------- src/models/entities/GroupContact.ts | 5 +++-- src/models/entities/IAddressUser.ts | 11 +++++++++++ src/models/entities/Participant.ts | 5 +++-- src/models/entities/RunnerOrganisation.ts | 20 +++++++++++--------- 5 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 src/models/entities/IAddressUser.ts diff --git a/src/models/entities/Address.ts b/src/models/entities/Address.ts index afa10da..561808f 100644 --- a/src/models/entities/Address.ts +++ b/src/models/entities/Address.ts @@ -7,7 +7,7 @@ import { } from "class-validator"; import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { config } from '../../config'; -import { Participant } from "./Participant"; +import { IAddressUser } from './IAddressUser'; /** * Defines the Address entity. @@ -78,13 +78,6 @@ export class Address { /** * Used to link the address to participants. */ - @OneToMany(() => Participant, participant => participant.address, { nullable: true }) - participants: Participant[]; - - //TODO: #68 - // /** - // * Used to link the address to runner groups. - // */ - // @OneToMany(() => RunnerOrganisation, group => group.address, { nullable: true }) - // groups: RunnerOrganisation[]; + @OneToMany(() => IAddressUser, addressUser => addressUser.address, { nullable: true }) + addressUsers: IAddressUser[]; } diff --git a/src/models/entities/GroupContact.ts b/src/models/entities/GroupContact.ts index f524863..4dbcc5e 100644 --- a/src/models/entities/GroupContact.ts +++ b/src/models/entities/GroupContact.ts @@ -10,6 +10,7 @@ import { import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { config } from '../../config'; import { Address } from "./Address"; +import { IAddressUser } from './IAddressUser'; import { RunnerGroup } from "./RunnerGroup"; /** @@ -17,7 +18,7 @@ import { RunnerGroup } from "./RunnerGroup"; * Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups. */ @Entity() -export class GroupContact { +export class GroupContact implements IAddressUser { /** * Autogenerated unique id (primary key). */ @@ -54,7 +55,7 @@ export class GroupContact { * This is a address object to prevent any formatting differences. */ @IsOptional() - @ManyToOne(() => Address, address => address.participants, { nullable: true }) + @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) address?: Address; /** diff --git a/src/models/entities/IAddressUser.ts b/src/models/entities/IAddressUser.ts new file mode 100644 index 0000000..425f4e3 --- /dev/null +++ b/src/models/entities/IAddressUser.ts @@ -0,0 +1,11 @@ +import { Entity, ManyToOne, PrimaryColumn } from 'typeorm'; +import { Address } from './Address'; + +@Entity() +export abstract class IAddressUser { + @PrimaryColumn() + id: number; + + @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) + address?: Address +} diff --git a/src/models/entities/Participant.ts b/src/models/entities/Participant.ts index 19af17e..de13b5f 100644 --- a/src/models/entities/Participant.ts +++ b/src/models/entities/Participant.ts @@ -10,6 +10,7 @@ import { import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; import { config } from '../../config'; import { Address } from "./Address"; +import { IAddressUser } from './IAddressUser'; /** * Defines the Participant entity. @@ -17,7 +18,7 @@ import { Address } from "./Address"; */ @Entity() @TableInheritance({ column: { name: "type", type: "varchar" } }) -export abstract class Participant { +export abstract class Participant implements IAddressUser { /** * Autogenerated unique id (primary key). */ @@ -53,7 +54,7 @@ export abstract class Participant { * The participant's address. * This is a address object to prevent any formatting differences. */ - @ManyToOne(() => Address, address => address.participants, { nullable: true }) + @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) address?: Address; /** diff --git a/src/models/entities/RunnerOrganisation.ts b/src/models/entities/RunnerOrganisation.ts index 7110b09..f0f8c78 100644 --- a/src/models/entities/RunnerOrganisation.ts +++ b/src/models/entities/RunnerOrganisation.ts @@ -1,5 +1,7 @@ -import { IsInt } from "class-validator"; -import { ChildEntity, OneToMany } from "typeorm"; +import { IsInt, IsOptional } from "class-validator"; +import { ChildEntity, ManyToOne, OneToMany } from "typeorm"; +import { Address } from './Address'; +import { IAddressUser } from './IAddressUser'; import { Runner } from './Runner'; import { RunnerGroup } from "./RunnerGroup"; import { RunnerTeam } from "./RunnerTeam"; @@ -9,14 +11,14 @@ import { RunnerTeam } from "./RunnerTeam"; * This usually is a school, club or company. */ @ChildEntity() -export class RunnerOrganisation extends RunnerGroup { +export class RunnerOrganisation extends RunnerGroup implements IAddressUser { - // /** - // * The organisations's address. - // */ - // @IsOptional() - // @ManyToOne(() => Address, address => address.groups, { nullable: true }) - // address?: Address; + /** + * The organisations's address. + */ + @IsOptional() + @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) + address?: Address; /** * The organisation's teams. From 9c4e54fc6e738194475c956895a229b18b51a3f4 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:57:33 +0100 Subject: [PATCH 24/27] Added comments to the bugfix --- src/models/entities/IAddressUser.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/models/entities/IAddressUser.ts b/src/models/entities/IAddressUser.ts index 425f4e3..56ee840 100644 --- a/src/models/entities/IAddressUser.ts +++ b/src/models/entities/IAddressUser.ts @@ -1,6 +1,10 @@ import { Entity, ManyToOne, PrimaryColumn } from 'typeorm'; import { Address } from './Address'; +/** + * The interface(-ish) all entities using addresses have to implement. + * This is a abstract class, because apparently typeorm can't really work with interfaces :/ + */ @Entity() export abstract class IAddressUser { @PrimaryColumn() From 56c6a7efb057da6a43081be803ae2b15402eb2fd Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 19:57:55 +0100 Subject: [PATCH 25/27] Revert "Removed addresses from tests until the circular dependencies are solved" This reverts commit 599296c4e3736bf9aadbc32067cd2ff8c39f0f17. --- src/controllers/RunnerOrganisationController.ts | 10 +++++----- src/tests/runnerOrgs/org_add.spec.ts | 4 ++-- src/tests/runnerOrgs/org_delete.spec.ts | 4 ++-- src/tests/runnerOrgs/org_update.spec.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index be25805..e10d415 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -29,7 +29,7 @@ export class RunnerOrganisationController { @OpenAPI({ description: 'Lists all organisations.
This includes their address, contact and teams (if existing/associated).' }) async getAll() { let responseTeams: ResponseRunnerOrganisation[] = new Array(); - const runners = await this.runnerOrganisationRepository.find({ relations: [/*'address',*/ 'contact', 'teams'] }); + const runners = await this.runnerOrganisationRepository.find({ relations: ['address', 'contact', 'teams'] }); runners.forEach(runner => { responseTeams.push(new ResponseRunnerOrganisation(runner)); }); @@ -43,7 +43,7 @@ export class RunnerOrganisationController { @OnUndefined(RunnerOrganisationNotFoundError) @OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' }) async getOne(@Param('id') id: number) { - let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: [/*'address',*/ 'contact', 'teams'] }); + let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['address', 'contact', 'teams'] }); if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); } return new ResponseRunnerOrganisation(runnerOrg); } @@ -62,7 +62,7 @@ export class RunnerOrganisationController { runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation); - return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: [/*'address',*/ 'contact', 'teams'] })); + return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['address', 'contact', 'teams'] })); } @Put('/:id') @@ -84,7 +84,7 @@ export class RunnerOrganisationController { await this.runnerOrganisationRepository.save(await updateOrganisation.updateRunnerOrganisation(oldRunnerOrganisation)); - return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: [/*'address',*/ 'contact', 'teams'] })); + return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['address', 'contact', 'teams'] })); } @Delete('/:id') @@ -98,7 +98,7 @@ export class RunnerOrganisationController { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let organisation = await this.runnerOrganisationRepository.findOne({ id: id }); if (!organisation) { return null; } - let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: [/*'address',*/ 'contact', 'runners', 'teams'] }); + let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['address', 'contact', 'runners', 'teams'] }); if (!force) { if (runnerOrganisation.teams.length != 0) { diff --git a/src/tests/runnerOrgs/org_add.spec.ts b/src/tests/runnerOrgs/org_add.spec.ts index 62aa067..6ee0606 100644 --- a/src/tests/runnerOrgs/org_add.spec.ts +++ b/src/tests/runnerOrgs/org_add.spec.ts @@ -56,7 +56,7 @@ describe('adding + getting from all orgs', () => { expect(added_org).toEqual({ "name": "test123", "contact": null, - // "address": null, + "address": null, "teams": [] }) }); @@ -83,7 +83,7 @@ describe('adding + getting explicitly', () => { expect(added_org2).toEqual({ "name": "test123", "contact": null, - // "address": null, + "address": null, "teams": [] }) }); diff --git a/src/tests/runnerOrgs/org_delete.spec.ts b/src/tests/runnerOrgs/org_delete.spec.ts index 9598704..08891f8 100644 --- a/src/tests/runnerOrgs/org_delete.spec.ts +++ b/src/tests/runnerOrgs/org_delete.spec.ts @@ -44,7 +44,7 @@ describe('adding + deletion (successfull)', () => { expect(added_org2).toEqual({ "name": "test123", "contact": null, - // "address": null, + "address": null, "teams": [] }); }); @@ -121,7 +121,7 @@ describe('adding + deletion with teams still existing (with force)', () => { expect(added_org2).toEqual({ "name": "test123", "contact": null, - // "address": null + "address": null }); }); it('check if org really was deleted', async () => { diff --git a/src/tests/runnerOrgs/org_update.spec.ts b/src/tests/runnerOrgs/org_update.spec.ts index a410521..e6a1055 100644 --- a/src/tests/runnerOrgs/org_update.spec.ts +++ b/src/tests/runnerOrgs/org_update.spec.ts @@ -32,7 +32,7 @@ describe('adding + updating name', () => { "id": added_org_id, "name": "testlelele", "contact": null, - // "address": null, + "address": null, }, axios_config); expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") @@ -42,7 +42,7 @@ describe('adding + updating name', () => { expect(added_org2).toEqual({ "name": "testlelele", "contact": null, - // "address": null, + "address": null, "teams": [] }) }); @@ -65,7 +65,7 @@ describe('adding + try updating id (should return 406)', () => { "id": added_org_id + 1, "name": "testlelele", "contact": null, - // "address": null, + "address": null, }, axios_config); expect(res2.status).toEqual(406); expect(res2.headers['content-type']).toContain("application/json") From 1e2de7656e36405b9b15d4e0a7004e8b14e61c85 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 20:03:02 +0100 Subject: [PATCH 26/27] Reenabled addresses in org responses ref #68 --- src/models/responses/ResponseRunnerOrganisation.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/models/responses/ResponseRunnerOrganisation.ts b/src/models/responses/ResponseRunnerOrganisation.ts index 8e31a71..69ccaf1 100644 --- a/src/models/responses/ResponseRunnerOrganisation.ts +++ b/src/models/responses/ResponseRunnerOrganisation.ts @@ -1,7 +1,8 @@ import { IsArray, - IsNotEmpty, - IsObject + + IsObject, + IsOptional } from "class-validator"; import { Address } from '../entities/Address'; import { RunnerOrganisation } from '../entities/RunnerOrganisation'; @@ -17,7 +18,7 @@ export class ResponseRunnerOrganisation extends ResponseRunnerGroup { * The runnerOrganisation's address. */ @IsObject() - @IsNotEmpty() + @IsOptional() address?: Address; /** @@ -32,7 +33,7 @@ export class ResponseRunnerOrganisation extends ResponseRunnerGroup { */ public constructor(org: RunnerOrganisation) { super(org); - // this.address = org.address; + this.address = org.address; this.teams = org.teams; } } From 97e8470b0d9c2d6e87fb951236769eb4274e2ab9 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 2 Jan 2021 21:53:21 +0100 Subject: [PATCH 27/27] Change requested by @philipp ref #70 --- src/models/entities/IAddressUser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/entities/IAddressUser.ts b/src/models/entities/IAddressUser.ts index 56ee840..3a7762a 100644 --- a/src/models/entities/IAddressUser.ts +++ b/src/models/entities/IAddressUser.ts @@ -2,7 +2,7 @@ import { Entity, ManyToOne, PrimaryColumn } from 'typeorm'; import { Address } from './Address'; /** - * The interface(-ish) all entities using addresses have to implement. + * The interface(tm) all entities using addresses have to implement. * This is a abstract class, because apparently typeorm can't really work with interfaces :/ */ @Entity()