import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { Repository, getConnectionManager } from 'typeorm'; import { DonationIdsNotMatchingError, DonationNotFoundError } from '../errors/DonationErrors'; import { DonorNotFoundError } from '../errors/DonorErrors'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { CreateDistanceDonation } from '../models/actions/create/CreateDistanceDonation'; import { CreateFixedDonation } from '../models/actions/create/CreateFixedDonation'; import { UpdateDistanceDonation } from '../models/actions/update/UpdateDistanceDonation'; import { UpdateFixedDonation } from '../models/actions/update/UpdateFixedDonation'; import { DistanceDonation } from '../models/entities/DistanceDonation'; import { Donation } from '../models/entities/Donation'; import { FixedDonation } from '../models/entities/FixedDonation'; import { ResponseDistanceDonation } from '../models/responses/ResponseDistanceDonation'; import { ResponseDonation } from '../models/responses/ResponseDonation'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; @JsonController('/donations') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class DonationController { private donationRepository: Repository; private distanceDonationRepository: Repository; private fixedDonationRepository: Repository; /** * Gets the repository of this controller's model/entity. */ constructor() { this.donationRepository = getConnectionManager().get().getRepository(Donation); this.distanceDonationRepository = getConnectionManager().get().getRepository(DistanceDonation); this.fixedDonationRepository = getConnectionManager().get().getRepository(FixedDonation); } @Get() @Authorized("DONATION:GET") @ResponseSchema(ResponseDonation, { isArray: true }) @ResponseSchema(ResponseDistanceDonation, { isArray: true }) @OpenAPI({ description: 'Lists all donations (fixed or distance based) from all donors.
This includes the donations\'s runner\'s distance ran(if distance donation).' }) async getAll(@QueryParam("page", { required: false }) page: number, @QueryParam("page_size", { required: false }) page_size: number = 100) { let responseDonations: ResponseDonation[] = new Array(); let donations: Array; if (page != undefined) { donations = await this.donationRepository.find({ relations: ['runner', 'donor', 'runner.scans', 'runner.scans.track'], skip: page * page_size, take: page_size }); } else { donations = await this.donationRepository.find({ relations: ['runner', 'donor', 'runner.scans', 'runner.scans.track'] }); } donations.forEach(donation => { responseDonations.push(donation.toResponse()); }); return responseDonations; } @Get('/:id') @Authorized("DONATION:GET") @ResponseSchema(ResponseDonation) @ResponseSchema(ResponseDistanceDonation) @ResponseSchema(DonationNotFoundError, { statusCode: 404 }) @OnUndefined(DonationNotFoundError) @OpenAPI({ description: 'Lists all information about the donation whose id got provided. This includes the donation\'s runner\'s distance ran (if distance donation).' }) async getOne(@Param('id') id: number) { let donation = await this.donationRepository.findOne({ id: id }, { relations: ['runner', 'donor', 'runner.scans', 'runner.scans.track'] }) if (!donation) { throw new DonationNotFoundError(); } return donation.toResponse(); } @Post('/fixed') @Authorized("DONATION:CREATE") @ResponseSchema(ResponseDonation) @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) @OpenAPI({ description: 'Create a fixed donation (not distance donation - use /donations/distance instead).
Please rmemember to provide the donation\'s donors\'s id and amount.' }) async postFixed(@Body({ validate: true }) createDonation: CreateFixedDonation) { let donation = await createDonation.toEntity(); donation = await this.fixedDonationRepository.save(donation); return (await this.donationRepository.findOne({ id: donation.id }, { relations: ['donor'] })).toResponse(); } @Post('/distance') @Authorized("DONATION:CREATE") @ResponseSchema(ResponseDistanceDonation) @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OpenAPI({ description: 'Create a distance donation (not fixed donation - use /donations/fixed instead).
Please rmemember to provide the donation\'s donors\'s and runner\s ids and amount per distance (kilometer).' }) async postDistance(@Body({ validate: true }) createDonation: CreateDistanceDonation) { let donation = await createDonation.toEntity(); donation = await this.distanceDonationRepository.save(donation); return (await this.distanceDonationRepository.findOne({ id: donation.id }, { relations: ['runner', 'donor', 'runner.scans', 'runner.scans.track'] })).toResponse(); } @Put('/fixed/:id') @Authorized("DONATION:UPDATE") @ResponseSchema(ResponseDonation) @ResponseSchema(DonationNotFoundError, { statusCode: 404 }) @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @ResponseSchema(DonationIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the fixed donation (not distance donation - use /donations/distance instead) whose id you provided.
Please remember that ids can't be changed and amounts must be positive." }) async putFixed(@Param('id') id: number, @Body({ validate: true }) donation: UpdateFixedDonation) { let oldDonation = await this.fixedDonationRepository.findOne({ id: id }); if (!oldDonation) { throw new DonationNotFoundError(); } if (oldDonation.id != donation.id) { throw new DonationIdsNotMatchingError(); } await this.fixedDonationRepository.save(await donation.update(oldDonation)); return (await this.donationRepository.findOne({ id: donation.id }, { relations: ['donor'] })).toResponse(); } @Put('/distance/:id') @Authorized("DONATION:UPDATE") @ResponseSchema(ResponseDonation) @ResponseSchema(DonationNotFoundError, { statusCode: 404 }) @ResponseSchema(DonorNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @ResponseSchema(DonationIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the distance donation (not fixed donation - use /donations/fixed instead) whose id you provided.
Please remember that ids can't be changed and amountPerDistance must be positive." }) async putDistance(@Param('id') id: number, @Body({ validate: true }) donation: UpdateDistanceDonation) { let oldDonation = await this.distanceDonationRepository.findOne({ id: id }); if (!oldDonation) { throw new DonationNotFoundError(); } if (oldDonation.id != donation.id) { throw new DonationIdsNotMatchingError(); } await this.distanceDonationRepository.save(await donation.update(oldDonation)); return (await this.distanceDonationRepository.findOne({ id: donation.id }, { relations: ['runner', 'donor', 'runner.scans', 'runner.scans.track'] })).toResponse(); } @Delete('/:id') @Authorized("DONATION:DELETE") @ResponseSchema(ResponseDonation) @ResponseSchema(ResponseDistanceDonation) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) @OpenAPI({ description: 'Delete the donation whose id you provided.
If no donation with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let donation = await this.donationRepository.findOne({ id: id }); if (!donation) { return null; } const responseScan = await this.donationRepository.findOne({ id: donation.id }, { relations: ['runner', 'donor', 'runner.scans', 'runner.scans.track'] }); await this.donationRepository.delete(donation); return responseScan.toResponse(); } }