diff --git a/CHANGELOG.md b/CHANGELOG.md index 437d437..10f851b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,33 @@ All notable changes to this project will be documented in this file. Dates are displayed in UTC. +#### [v0.11.0](https://git.odit.services/lfk/backend/compare/v0.10.2...v0.11.0) + +- Fixed spelling [`da266a8`](https://git.odit.services/lfk/backend/commit/da266a8dd68dbb575997ae343624982b690486ec) +- Updated tests [`01ed514`](https://git.odit.services/lfk/backend/commit/01ed51489eb92fff907d46a930ecf0b0eb5cad2b) +- 🧾New changelog file version [CI SKIP] [skip ci] [`520608a`](https://git.odit.services/lfk/backend/commit/520608aef05b21f4daadf55cfc8caddba06b8f01) +- Added payedDonationAmount to donor and responsedonor [`8ae4b85`](https://git.odit.services/lfk/backend/commit/8ae4b8582749332f4fb081eee0c520293347001f) +- Responses now contain the donation status [`34dbaaa`](https://git.odit.services/lfk/backend/commit/34dbaaafe0422234848eabe3f52b26879c9e5a49) +- Marked payedAmount as optional during creation and/or update [`0636616`](https://git.odit.services/lfk/backend/commit/0636616dad5afb41ffe47a857d91ac75b4f2f20a) +- Added payed amount fileld to donation class [`b8fbb72`](https://git.odit.services/lfk/backend/commit/b8fbb72fa0b659c9acc406c72a8a59c2174351b4) +- Added status to tests [`30c6d3d`](https://git.odit.services/lfk/backend/commit/30c6d3d8db9fe37a51e596a73add8b87e8616e54) +- Added payed amount to crealte classes [`71542bc`](https://git.odit.services/lfk/backend/commit/71542bc3887b97c15436d03280e49f7b3f0fcb06) +- Added payed amount to update classes [`9930742`](https://git.odit.services/lfk/backend/commit/99307423c533f8cde847b59a80bffc2ff42c9769) +- Added mssing check to tests [`6c14ed9`](https://git.odit.services/lfk/backend/commit/6c14ed9c89eadc1a10db8c912d8ea2711a518766) +- 📖New license file version [CI SKIP] [skip ci] [`a2f0d81`](https://git.odit.services/lfk/backend/commit/a2f0d814fc782ad440500e7d6ec779b6ab7f0ac6) +- 🚀Bumped version to v0.11.0 [`3558e99`](https://git.odit.services/lfk/backend/commit/3558e9909088647bd4f1f4334f50c07a5ef00214) +- Merge pull request 'Donation payment management feature/193-donation_payments' (#194) from feature/193-donation_payments into dev [`6df5f63`](https://git.odit.services/lfk/backend/commit/6df5f634f3123e04c015889573ccc5674a8bab27) +- Added donation status enum [`b4c31ee`](https://git.odit.services/lfk/backend/commit/b4c31ee9b5b35d6e11b07f50f3d30ca12e0f7728) +- Added payed amount to response class [`d64f470`](https://git.odit.services/lfk/backend/commit/d64f470b608b3f179ec77da0210de51c328ef3f2) +- 🧾New changelog file version [CI SKIP] [skip ci] [`0c61ff4`](https://git.odit.services/lfk/backend/commit/0c61ff457d02f750efa457dd75464187683b037a) +- No longer answering with null, but 0 [`49b174f`](https://git.odit.services/lfk/backend/commit/49b174f29f63e963e600d74b6923a20211d832eb) +- Saved missing file [`8fe3243`](https://git.odit.services/lfk/backend/commit/8fe32436935d7cd6c17eae1e138383d3b714e1ba) + #### [v0.10.2](https://git.odit.services/lfk/backend/compare/v0.10.1...v0.10.2) +> 7 April 2021 + +- Merge pull request 'Release 0.10.2' (#192) from dev into main [`1d82f65`](https://git.odit.services/lfk/backend/commit/1d82f65b0d3a32d10c1a10c991353c18696d58bf) - Added first selfservice test [`057ae0d`](https://git.odit.services/lfk/backend/commit/057ae0d79758cd627d6d128406a0d201b6b7ad9b) - 🧾New changelog file version [CI SKIP] [skip ci] [`b7ad5d3`](https://git.odit.services/lfk/backend/commit/b7ad5d3a31b8b4f5960852d3ac38af133719ebcd) - First try of the laptime sort [`4471e57`](https://git.odit.services/lfk/backend/commit/4471e57438582d55ff846fd69c2cfcc26b40df2a) @@ -22,17 +47,18 @@ All notable changes to this project will be documented in this file. Dates are d - Fixed top-ten bein top 9 [`a6a526d`](https://git.odit.services/lfk/backend/commit/a6a526dc5d8b1613ea34e82e477081349e764aec) - added new ci secret [`5633e85`](https://git.odit.services/lfk/backend/commit/5633e85f41cb69b10fd8a86f57f1bd2f50848f7b) - Added temp console log for test [`22cae39`](https://git.odit.services/lfk/backend/commit/22cae39bd351ca285880e50187ea0d46a7a26437) +- 🧾New changelog file version [CI SKIP] [skip ci] [`610988e`](https://git.odit.services/lfk/backend/commit/610988ec16b8df61cca61cf2252a469d30318d81) - Added temp console log for ci debugging [`4a73eab`](https://git.odit.services/lfk/backend/commit/4a73eab134c3a9f58771be996bc8811b62cf378e) - Temp disabled runners by donations test [`0b07a53`](https://git.odit.services/lfk/backend/commit/0b07a53ed209c6193ead3c4d199545e22333ab32) - Updated default docker-compose [`f8baca5`](https://git.odit.services/lfk/backend/commit/f8baca5ab2c56b906751bc7edd71477456ad91f3) -- Removed all useless console.logs [`95e1eec`](https://git.odit.services/lfk/backend/commit/95e1eec313a79458dd75307a9d0f8319af0d0904) +- 🧾New changelog file version [CI SKIP] [skip ci] [`dd6d799`](https://git.odit.services/lfk/backend/commit/dd6d799c847fc96aec1be8f2667ad371890076fb) - Resolved missing parentgroup relation [`23bd432`](https://git.odit.services/lfk/backend/commit/23bd432c5f33a0863217120d97e2e4ea52a08baf) - Removed console logs for now working tests [`71b33ab`](https://git.odit.services/lfk/backend/commit/71b33ab05b53b62c8b271bd2995c94b2fc212dfd) - Fixed typo in test [`cbcb829`](https://git.odit.services/lfk/backend/commit/cbcb829fbde3a4a5e7f94de5dcf24d854c5fc257) - Ptotential fix for stats failing [`dcdbdd1`](https://git.odit.services/lfk/backend/commit/dcdbdd15acfe6eef4220b7ed66db60d78107d1f9) - 🚀Bumped version to v0.10.2 [`6e236ed`](https://git.odit.services/lfk/backend/commit/6e236ede145e164ee84543fb62404b4776550973) - Merge pull request 'stats/runners/laptime feature/190-runners_laptime' (#191) from feature/190-runners_laptime into dev [`a694ad2`](https://git.odit.services/lfk/backend/commit/a694ad225c68fa23152402acba871c857433cc70) -- 🧾New changelog file version [CI SKIP] [skip ci] [`dd6d799`](https://git.odit.services/lfk/backend/commit/dd6d799c847fc96aec1be8f2667ad371890076fb) +- Removed all useless console.logs [`95e1eec`](https://git.odit.services/lfk/backend/commit/95e1eec313a79458dd75307a9d0f8319af0d0904) - Pinned testing container tag to prod container tag [`10221b9`](https://git.odit.services/lfk/backend/commit/10221b9f2e4493080f3ff095d9772bcfd0ac50eb) - Now resolving all relations for orgs by distance [`4a294b1`](https://git.odit.services/lfk/backend/commit/4a294b1e17c44294274b06748ec8141812c2d217) - Added temp console log [`720774f`](https://git.odit.services/lfk/backend/commit/720774fcf47c38601ab88d5d74cfcd0e47b21acf) diff --git a/licenses.md b/licenses.md index dd80361..d37ec17 100644 --- a/licenses.md +++ b/licenses.md @@ -454,7 +454,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## License Text MIT License -Copyright (c) 2010 - 2020 Brian Carlson +Copyright (c) 2010 - 2021 Brian Carlson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package.json b/package.json index 341ab2c..dffd24d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@odit/lfk-backend", - "version": "0.10.2", + "version": "0.11.0", "main": "src/app.ts", "repository": "https://git.odit.services/lfk/backend", "author": { diff --git a/src/models/actions/create/CreateDistanceDonation.ts b/src/models/actions/create/CreateDistanceDonation.ts index b1ba1dd..133e71b 100644 --- a/src/models/actions/create/CreateDistanceDonation.ts +++ b/src/models/actions/create/CreateDistanceDonation.ts @@ -33,6 +33,7 @@ export class CreateDistanceDonation extends CreateDonation { let newDonation = new DistanceDonation; newDonation.amountPerDistance = this.amountPerDistance; + newDonation.paidAmount = this.paidAmount; newDonation.donor = await this.getDonor(); newDonation.runner = await this.getRunner(); diff --git a/src/models/actions/create/CreateDonation.ts b/src/models/actions/create/CreateDonation.ts index 50d7cd7..e70455e 100644 --- a/src/models/actions/create/CreateDonation.ts +++ b/src/models/actions/create/CreateDonation.ts @@ -1,4 +1,4 @@ -import { IsInt, IsPositive } from 'class-validator'; +import { IsInt, IsOptional, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; import { DonorNotFoundError } from '../../../errors/DonorErrors'; import { Donation } from '../../entities/Donation'; @@ -16,6 +16,13 @@ export abstract class CreateDonation { @IsPositive() donor: number; + /** + * The donation's paid amount in the smalles unit of your currency (default: euro cent). + */ + @IsInt() + @IsOptional() + paidAmount?: number; + /** * Creates a new Donation entity from this. */ diff --git a/src/models/actions/create/CreateFixedDonation.ts b/src/models/actions/create/CreateFixedDonation.ts index 4d73f50..bfdca9f 100644 --- a/src/models/actions/create/CreateFixedDonation.ts +++ b/src/models/actions/create/CreateFixedDonation.ts @@ -21,6 +21,7 @@ export class CreateFixedDonation extends CreateDonation { let newDonation = new FixedDonation; newDonation.amount = this.amount; + newDonation.paidAmount = this.paidAmount; newDonation.donor = await this.getDonor(); return newDonation; diff --git a/src/models/actions/update/UpdateDistanceDonation.ts b/src/models/actions/update/UpdateDistanceDonation.ts index 67407b9..c9a66ce 100644 --- a/src/models/actions/update/UpdateDistanceDonation.ts +++ b/src/models/actions/update/UpdateDistanceDonation.ts @@ -32,6 +32,7 @@ export class UpdateDistanceDonation extends UpdateDonation { */ public async update(donation: DistanceDonation): Promise { donation.amountPerDistance = this.amountPerDistance; + donation.paidAmount = this.paidAmount; donation.donor = await this.getDonor(); donation.runner = await this.getRunner(); diff --git a/src/models/actions/update/UpdateDonation.ts b/src/models/actions/update/UpdateDonation.ts index 569454a..3acf2b9 100644 --- a/src/models/actions/update/UpdateDonation.ts +++ b/src/models/actions/update/UpdateDonation.ts @@ -1,4 +1,4 @@ -import { IsInt, IsPositive } from 'class-validator'; +import { IsInt, IsOptional, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; import { DonorNotFoundError } from '../../../errors/DonorErrors'; import { Donation } from '../../entities/Donation'; @@ -23,6 +23,13 @@ export abstract class UpdateDonation { @IsPositive() donor: number; + /** + * The donation's paid amount in the smalles unit of your currency (default: euro cent). + */ + @IsInt() + @IsOptional() + paidAmount?: number; + /** * Creates a new Donation entity from this. */ diff --git a/src/models/actions/update/UpdateFixedDonation.ts b/src/models/actions/update/UpdateFixedDonation.ts index 5e31068..9e0401f 100644 --- a/src/models/actions/update/UpdateFixedDonation.ts +++ b/src/models/actions/update/UpdateFixedDonation.ts @@ -20,6 +20,7 @@ export class UpdateFixedDonation extends UpdateDonation { */ public async update(donation: FixedDonation): Promise { donation.amount = this.amount; + donation.paidAmount = this.paidAmount; donation.donor = await this.getDonor(); return donation; diff --git a/src/models/entities/Donation.ts b/src/models/entities/Donation.ts index 1dd023d..f693d01 100644 --- a/src/models/entities/Donation.ts +++ b/src/models/entities/Donation.ts @@ -2,7 +2,7 @@ import { IsInt, IsNotEmpty } from "class-validator"; -import { Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; import { ResponseDonation } from '../responses/ResponseDonation'; import { Donor } from './Donor'; @@ -34,6 +34,13 @@ export abstract class Donation { */ public abstract get amount(): number; + /** + * The donation's paid amount in cents (or whatever your currency's smallest unit is.). + * Used to mark donations as paid. + */ + @Column({ nullable: true }) + @IsInt() + paidAmount: number; /** * Turns this entity into it's response class. diff --git a/src/models/entities/Donor.ts b/src/models/entities/Donor.ts index acf5536..4d42769 100644 --- a/src/models/entities/Donor.ts +++ b/src/models/entities/Donor.ts @@ -33,6 +33,15 @@ export class Donor extends Participant { return this.donations.reduce((sum, current) => sum + current.amount, 0); } + /** + * Returns the total paid donations of a donor based on his linked donations. + */ + @IsInt() + public get paidDonationAmount(): number { + if (!this.donations) { return 0; } + return this.donations.reduce((sum, current) => sum + current.paidAmount, 0); + } + /** * Turns this entity into it's response class. */ diff --git a/src/models/enums/DonationStatus.ts b/src/models/enums/DonationStatus.ts new file mode 100644 index 0000000..0f2323f --- /dev/null +++ b/src/models/enums/DonationStatus.ts @@ -0,0 +1,7 @@ +/** + * This enum contains all status a donation can inherit regarding it's payment status. + */ +export enum DonationStatus { + OPEN = 'OPEN', + PAID = 'PAID' +} \ No newline at end of file diff --git a/src/models/responses/ResponseDonation.ts b/src/models/responses/ResponseDonation.ts index e29f11f..e917e96 100644 --- a/src/models/responses/ResponseDonation.ts +++ b/src/models/responses/ResponseDonation.ts @@ -1,5 +1,6 @@ import { IsInt, IsNotEmpty, IsPositive } from "class-validator"; import { Donation } from '../entities/Donation'; +import { DonationStatus } from '../enums/DonationStatus'; import { ResponseObjectType } from '../enums/ResponseObjectType'; import { IResponse } from './IResponse'; import { ResponseDonor } from './ResponseDonor'; @@ -15,6 +16,12 @@ export class ResponseDonation implements IResponse { */ 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. */ @@ -34,6 +41,12 @@ export class ResponseDonation implements IResponse { @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. @@ -42,5 +55,12 @@ export class ResponseDonation implements IResponse { this.id = donation.id; this.donor = donation.donor.toResponse(); this.amount = donation.amount; + this.paidAmount = donation.paidAmount || 0; + if (this.paidAmount < this.amount) { + this.status = DonationStatus.OPEN; + } + else { + this.status = DonationStatus.PAID; + } } } diff --git a/src/models/responses/ResponseDonor.ts b/src/models/responses/ResponseDonor.ts index 2b1e3fc..07f12dc 100644 --- a/src/models/responses/ResponseDonor.ts +++ b/src/models/responses/ResponseDonor.ts @@ -28,6 +28,12 @@ export class ResponseDonor extends ResponseParticipant implements IResponse { @IsInt() donationAmount: number; + /** + * Returns the total paid donations of a donor based on his linked donations. + */ + @IsInt() + paidDonationAmount: number; + /** * Creates a ResponseRunner object from a runner. * @param runner The user the response shall be build for. @@ -36,5 +42,6 @@ export class ResponseDonor extends ResponseParticipant implements IResponse { super(donor); this.receiptNeeded = donor.receiptNeeded; this.donationAmount = donor.donationAmount; + this.paidDonationAmount = donor.paidDonationAmount; } } diff --git a/src/tests/donations/donations_add.spec.ts b/src/tests/donations/donations_add.spec.ts index c851d8d..1f9bfc2 100644 --- a/src/tests/donations/donations_add.spec.ts +++ b/src/tests/donations/donations_add.spec.ts @@ -170,7 +170,7 @@ describe('POST /api/donations/fixed successfully', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json") }); - it('creating a new fixed donation should return 200', async () => { + it('creating a new fixed donation with more params should return 200', async () => { const res = await axios.post(base + '/api/donations/fixed', { "donor": added_donor.id, "amount": 1000 @@ -181,6 +181,25 @@ describe('POST /api/donations/fixed successfully', () => { expect(res.data).toEqual({ "donor": added_donor, "amount": 1000, + "paidAmount": 0, + "status": "OPEN", + "responseType": "DONATION" + }); + }); + it('creating a new fixed donation with all params should return 200', async () => { + const res = await axios.post(base + '/api/donations/fixed', { + "donor": added_donor.id, + "amount": 1000, + "paidAmount": 1000 + }, axios_config); + delete res.data.id; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + expect(res.data).toEqual({ + "donor": added_donor, + "amount": 1000, + "paidAmount": 1000, + "status": "PAID", "responseType": "DONATION" }); }); @@ -219,7 +238,7 @@ describe('POST /api/donations/distance successfully', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json") }); - it('creating a new fixed donation should return 200', async () => { + it('creating a new distance donation with most params should return 200', async () => { const res = await axios.post(base + '/api/donations/distance', { "runner": added_runner.id, "amountPerDistance": 100, @@ -233,6 +252,28 @@ describe('POST /api/donations/distance successfully', () => { "amountPerDistance": 100, "runner": added_runner, "amount": 0, + "paidAmount": 0, + "status": "PAID", + "responseType": "DISTANCEDONATION" + }) + }); + it('creating a new distance donation with all params should return 200', async () => { + const res = await axios.post(base + '/api/donations/distance', { + "runner": added_runner.id, + "amountPerDistance": 100, + "donor": added_donor.id, + "paidAmount": 1000 + }, axios_config); + delete res.data.id; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + expect(res.data).toEqual({ + "donor": added_donor, + "amountPerDistance": 100, + "runner": added_runner, + "amount": 0, + "paidAmount": 1000, + "status": "PAID", "responseType": "DISTANCEDONATION" }) }); diff --git a/src/tests/donations/donations_update.spec.ts b/src/tests/donations/donations_update.spec.ts index 0ac7e86..c7f4fc7 100644 --- a/src/tests/donations/donations_update.spec.ts +++ b/src/tests/donations/donations_update.spec.ts @@ -213,6 +213,17 @@ describe('adding + updating fixed donation valid', () => { expect(res.headers['content-type']).toContain("application/json"); expect(res.data.amount).toEqual(42); }); + it('updating paidAmount should return 200', async () => { + const res = await axios.put(base + '/api/donations/fixed/' + added_donation.id, { + "id": added_donation.id, + "donor": added_donor.id, + "amount": 42, + "paidAmount": 10 + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + expect(res.data.paidAmount).toEqual(10); + }); it('updating donor should return 200', async () => { const res = await axios.put(base + '/api/donations/fixed/' + added_donation.id, { "id": added_donation.id, @@ -317,6 +328,19 @@ describe('adding + updating distance donation valid', () => { expect(res.headers['content-type']).toContain("application/json"); expect(res.data.amountPerDistance).toEqual(69); }); + it('updating paidAmount should return 200', async () => { + const res = await axios.put(base + '/api/donations/distance/' + added_donation.id, { + "id": added_donation.id, + "runner": added_runner.id, + "amountPerDistance": 69, + "donor": added_donor.id, + "paidAmount": 10 + }, axios_config); + delete res.data.donor.donationAmount; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + expect(res.data.paidAmount).toEqual(10); + }); it('updating runner should return 200', async () => { const res = await axios.put(base + '/api/donations/distance/' + added_donation.id, { "id": added_donation.id,