Compare commits

..

6 Commits

Author SHA1 Message Date
8e6d67428c
chore(release): 1.4.0
All checks were successful
Build release images / build-container (push) Successful in 1m14s
2025-04-28 19:41:55 +02:00
7ffb7523aa
Merge branch 'CreateAnonymousDonation-dedicated-enitity-controller' into dev 2025-04-28 19:41:35 +02:00
f4bf309821
feat(donations): Implement response type to indicate possible missing donor 2025-04-28 19:35:07 +02:00
02b1cb9904
refactor(donations): Make anon prepaid 2025-04-28 19:32:06 +02:00
7697acff82
fix(donations): Move donor over to the types that need it 2025-04-28 19:25:41 +02:00
9875b4f392
wip 2025-04-28 11:04:22 +02:00
8 changed files with 145 additions and 14 deletions

View File

@ -2,8 +2,18 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.4.0](https://git.odit.services/lfk/backend/compare/1.3.12...1.4.0)
- feat(donations): Implement response type to indicate possible missing donor [`f4bf309`](https://git.odit.services/lfk/backend/commit/f4bf309821c140f2bc0ae8b6d96c7458fcc80978)
- wip [`9875b4f`](https://git.odit.services/lfk/backend/commit/9875b4f3926e04b502e7af64c17f54fd3c1d8e3e)
- refactor(donations): Make anon prepaid [`02b1cb9`](https://git.odit.services/lfk/backend/commit/02b1cb9904cc593faeac025ae302a8684f650f5e)
- fix(donations): Move donor over to the types that need it [`7697acf`](https://git.odit.services/lfk/backend/commit/7697acff82b23d0c05dbbd17fee6e70eb1b7061c)
#### [1.3.12](https://git.odit.services/lfk/backend/compare/1.3.11...1.3.12) #### [1.3.12](https://git.odit.services/lfk/backend/compare/1.3.11...1.3.12)
> 28 April 2025
- chore(release): 1.3.12 [`bacfc43`](https://git.odit.services/lfk/backend/commit/bacfc437f97cac6a20c32b79ae2d6391466f78a6)
- refactor: make Donation.donor optional [`2ab6e98`](https://git.odit.services/lfk/backend/commit/2ab6e985e356f0f3d8637d81630d191cc11b8806) - refactor: make Donation.donor optional [`2ab6e98`](https://git.odit.services/lfk/backend/commit/2ab6e985e356f0f3d8637d81630d191cc11b8806)
- refactor(config): improve consola error logs [`ce9b765`](https://git.odit.services/lfk/backend/commit/ce9b765b81b014623e79ce64d8d835f1f86cecf3) - refactor(config): improve consola error logs [`ce9b765`](https://git.odit.services/lfk/backend/commit/ce9b765b81b014623e79ce64d8d835f1f86cecf3)

View File

@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-backend", "name": "@odit/lfk-backend",
"version": "1.3.12", "version": "1.4.0",
"main": "src/app.ts", "main": "src/app.ts",
"repository": "https://git.odit.services/lfk/backend", "repository": "https://git.odit.services/lfk/backend",
"author": { "author": {

View File

@ -4,6 +4,7 @@ import { Repository, getConnectionManager } from 'typeorm';
import { DonationIdsNotMatchingError, DonationNotFoundError } from '../errors/DonationErrors'; import { DonationIdsNotMatchingError, DonationNotFoundError } from '../errors/DonationErrors';
import { DonorNotFoundError } from '../errors/DonorErrors'; import { DonorNotFoundError } from '../errors/DonorErrors';
import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { RunnerNotFoundError } from '../errors/RunnerErrors';
import { CreateAnonymousDonation } from '../models/actions/create/CreateAnonymousDonation';
import { CreateDistanceDonation } from '../models/actions/create/CreateDistanceDonation'; import { CreateDistanceDonation } from '../models/actions/create/CreateDistanceDonation';
import { CreateFixedDonation } from '../models/actions/create/CreateFixedDonation'; import { CreateFixedDonation } from '../models/actions/create/CreateFixedDonation';
import { UpdateDistanceDonation } from '../models/actions/update/UpdateDistanceDonation'; import { UpdateDistanceDonation } from '../models/actions/update/UpdateDistanceDonation';
@ -11,6 +12,7 @@ import { UpdateFixedDonation } from '../models/actions/update/UpdateFixedDonatio
import { DistanceDonation } from '../models/entities/DistanceDonation'; import { DistanceDonation } from '../models/entities/DistanceDonation';
import { Donation } from '../models/entities/Donation'; import { Donation } from '../models/entities/Donation';
import { FixedDonation } from '../models/entities/FixedDonation'; import { FixedDonation } from '../models/entities/FixedDonation';
import { ResponseAnonymousDonation } from '../models/responses/ResponseAnonymousDonation';
import { ResponseDistanceDonation } from '../models/responses/ResponseDistanceDonation'; import { ResponseDistanceDonation } from '../models/responses/ResponseDistanceDonation';
import { ResponseDonation } from '../models/responses/ResponseDonation'; import { ResponseDonation } from '../models/responses/ResponseDonation';
import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseEmpty } from '../models/responses/ResponseEmpty';
@ -35,6 +37,7 @@ export class DonationController {
@Authorized("DONATION:GET") @Authorized("DONATION:GET")
@ResponseSchema(ResponseDonation, { isArray: true }) @ResponseSchema(ResponseDonation, { isArray: true })
@ResponseSchema(ResponseDistanceDonation, { isArray: true }) @ResponseSchema(ResponseDistanceDonation, { isArray: true })
@ResponseSchema(ResponseAnonymousDonation, { isArray: true })
@OpenAPI({ description: 'Lists all donations (fixed or distance based) from all donors. <br> This includes the donations\'s runner\'s distance ran(if distance donation).' }) @OpenAPI({ description: 'Lists all donations (fixed or distance based) from all donors. <br> 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) { async getAll(@QueryParam("page", { required: false }) page: number, @QueryParam("page_size", { required: false }) page_size: number = 100) {
let responseDonations: ResponseDonation[] = new Array<ResponseDonation>(); let responseDonations: ResponseDonation[] = new Array<ResponseDonation>();
@ -56,6 +59,7 @@ export class DonationController {
@Authorized("DONATION:GET") @Authorized("DONATION:GET")
@ResponseSchema(ResponseDonation) @ResponseSchema(ResponseDonation)
@ResponseSchema(ResponseDistanceDonation) @ResponseSchema(ResponseDistanceDonation)
@ResponseSchema(ResponseAnonymousDonation)
@ResponseSchema(DonationNotFoundError, { statusCode: 404 }) @ResponseSchema(DonationNotFoundError, { statusCode: 404 })
@OnUndefined(DonationNotFoundError) @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).' }) @OpenAPI({ description: 'Lists all information about the donation whose id got provided. This includes the donation\'s runner\'s distance ran (if distance donation).' })
@ -76,6 +80,17 @@ export class DonationController {
return (await this.donationRepository.findOne({ id: donation.id }, { relations: ['donor'] })).toResponse(); return (await this.donationRepository.findOne({ id: donation.id }, { relations: ['donor'] })).toResponse();
} }
@Post('/anonymous')
@Authorized("DONATION:CREATE")
@ResponseSchema(ResponseDonation)
@ResponseSchema(DonorNotFoundError, { statusCode: 404 })
@OpenAPI({ description: 'Create a anonymous donation' })
async postAnonymous(@Body({ validate: true }) createDonation: CreateAnonymousDonation) {
let donation = await createDonation.toEntity();
donation = await this.fixedDonationRepository.save(donation);
return (await this.donationRepository.findOne({ id: donation.id })).toResponse();
}
@Post('/distance') @Post('/distance')
@Authorized("DONATION:CREATE") @Authorized("DONATION:CREATE")
@ResponseSchema(ResponseDistanceDonation) @ResponseSchema(ResponseDistanceDonation)

View File

@ -0,0 +1,29 @@
import { IsInt, IsPositive } from 'class-validator';
import { FixedDonation } from '../../entities/FixedDonation';
import { CreateDonation } from './CreateDonation';
/**
* This class is used to create a new FixedDonation entity from a json body (post request).
*/
export class CreateAnonymousDonation extends CreateDonation {
/**
* The donation's amount.
* The unit is your currency's smallest unit (default: euro cent).
*/
@IsInt()
@IsPositive()
amount: number;
/**
* Creates a new FixedDonation entity from this.
*/
public async toEntity(): Promise<FixedDonation> {
let newDonation = new FixedDonation;
newDonation.amount = this.amount;
newDonation.paidAmount = this.amount;
return newDonation;
}
}

View File

@ -10,6 +10,20 @@ import { CreateDonation } from './CreateDonation';
*/ */
export class CreateDistanceDonation extends CreateDonation { export class CreateDistanceDonation extends CreateDonation {
/**
* The donation's associated donor's id.
* This is important to link donations to donors.
*/
@IsInt()
@IsPositive()
donor: number;
/**
* The donation's paid amount in the smalles unit of your currency (default: euro cent).
*/
@IsInt()
paidAmount?: number;
/** /**
* The donation's associated runner's id. * The donation's associated runner's id.
* This is important to link the runner's distance ran to the donation. * This is important to link the runner's distance ran to the donation.

View File

@ -1,4 +1,4 @@
import { IsInt, IsOptional, IsPositive } from 'class-validator'; import { Exclude } from 'class-transformer';
import { getConnection } from 'typeorm'; import { getConnection } from 'typeorm';
import { Donation } from '../../entities/Donation'; import { Donation } from '../../entities/Donation';
import { Donor } from '../../entities/Donor'; import { Donor } from '../../entities/Donor';
@ -7,20 +7,10 @@ import { Donor } from '../../entities/Donor';
* This class is used to create a new Donation entity from a json body (post request). * This class is used to create a new Donation entity from a json body (post request).
*/ */
export abstract class CreateDonation { export abstract class CreateDonation {
/** @Exclude()
* The donation's associated donor's id.
* This is important to link donations to donors.
*/
@IsInt()
@IsPositive()
@IsOptional()
donor: number; donor: number;
/** @Exclude()
* The donation's paid amount in the smalles unit of your currency (default: euro cent).
*/
@IsInt()
@IsOptional()
paidAmount?: number; paidAmount?: number;
/** /**

View File

@ -6,6 +6,21 @@ import { CreateDonation } from './CreateDonation';
* This class is used to create a new FixedDonation entity from a json body (post request). * This class is used to create a new FixedDonation entity from a json body (post request).
*/ */
export class CreateFixedDonation extends CreateDonation { export class CreateFixedDonation extends CreateDonation {
/**
* The donation's associated donor's id.
* This is important to link donations to donors.
*/
@IsInt()
@IsPositive()
donor: number;
/**
* The donation's paid amount in the smalles unit of your currency (default: euro cent).
*/
@IsInt()
paidAmount?: number;
/** /**
* The donation's amount. * The donation's amount.
* The unit is your currency's smallest unit (default: euro cent). * The unit is your currency's smallest unit (default: euro cent).

View File

@ -0,0 +1,58 @@
import { IsInt, IsPositive } from "class-validator";
import { Donation } from '../entities/Donation';
import { DonationStatus } from '../enums/DonationStatus';
import { ResponseObjectType } from '../enums/ResponseObjectType';
import { IResponse } from './IResponse';
/**
* Defines the donation response.
*/
export class ResponseAnonymousDonation implements IResponse {
/**
* The responseType.
* This contains the type of class/entity this response contains.
*/
responseType: ResponseObjectType = ResponseObjectType.DONATION;
/**
* The donation's payment status.
* Provides you with a quick indicator of it's payment status.
*/
status: DonationStatus;
/**
* The donation's id.
*/
@IsInt()
@IsPositive()
id: number;
/**
* The donation's amount in the smalles unit of your currency (default: euro cent).
*/
@IsInt()
amount: number;
/**
* The donation's paid amount in the smalles unit of your currency (default: euro cent).
*/
@IsInt()
paidAmount: number;
/**
* Creates a ResponseDonation object from a scan.
* @param donation The donation the response shall be build for.
*/
public constructor(donation: Donation) {
this.id = donation.id;
this.amount = donation.amount;
this.paidAmount = donation.paidAmount || 0;
if (this.paidAmount < this.amount) {
this.status = DonationStatus.OPEN;
}
else {
this.status = DonationStatus.PAID;
}
}
}