Compare commits

...

74 Commits

Author SHA1 Message Date
f19f2808d8 Merge pull request 'Release 0.11.1' (#196) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #196
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-04-22 18:21:16 +00:00
3b9cd2e1bb 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-04-22 17:59:02 +00:00
95320ca1bc 🚀Bumped version to v0.11.1
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is passing
2021-04-22 19:57:31 +02:00
f2d127fc98 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-04-22 17:53:09 +00:00
eb526fb57f Added fix for the appended 2
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-22 19:52:32 +02:00
348fe52c42 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 17:42:09 +00:00
eef0fa6952 Merge branch 'dev' of git.odit.services:lfk/backend into dev
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-22 19:41:21 +02:00
8a82e059b7 Now prefixing runnercards with 2 2021-04-22 19:41:18 +02:00
2229cdf20d 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-14 17:05:15 +00:00
3220b194d4 Merge pull request 'Release 0.11.0' (#195) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #195
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-04-14 17:04:29 +00:00
278c4a6a41 🧾New changelog file version [CI SKIP] [skip ci]
Some checks failed
continuous-integration/drone/pr Build is failing
2021-04-14 16:59:20 +00:00
ec50ac31c4 Merge branch 'dev' of git.odit.services:lfk/backend into dev
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2021-04-14 18:58:24 +02:00
a2f0d814fc 📖New license file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-04-14 16:58:11 +00:00
6468b35708 Merge branch 'dev' of git.odit.services:lfk/backend into dev 2021-04-14 18:57:45 +02:00
3558e99090 🚀Bumped version to v0.11.0 2021-04-14 18:57:26 +02:00
520608aef0 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-14 16:57:03 +00:00
6df5f634f3 Merge pull request 'Donation payment management feature/193-donation_payments' (#194) from feature/193-donation_payments into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #194
2021-04-14 16:56:22 +00:00
da266a8dd6 Fixed spelling
All checks were successful
continuous-integration/drone/pr Build is passing
ref #193
2021-04-14 18:54:02 +02:00
8ae4b85827 Added payedDonationAmount to donor and responsedonor
All checks were successful
continuous-integration/drone/pr Build is passing
ref #193
2021-04-14 18:49:44 +02:00
8fe3243693 Saved missing file
All checks were successful
continuous-integration/drone/pr Build is passing
ref #193
2021-04-14 18:47:10 +02:00
49b174f29f No longer answering with null, but 0
Some checks failed
continuous-integration/drone/pr Build is failing
ref #193
2021-04-14 18:42:38 +02:00
30c6d3d8db Added status to tests
Some checks reported errors
continuous-integration/drone/pr Build was killed
ref #193
2021-04-14 18:41:20 +02:00
6c14ed9c89 Added mssing check to tests
ref #193
2021-04-14 18:36:59 +02:00
01ed51489e Updated tests
Some checks failed
continuous-integration/drone/pr Build is failing
ref #193
2021-04-14 18:34:15 +02:00
0636616dad Marked payedAmount as optional during creation and/or update
ref #193
2021-04-14 18:29:40 +02:00
34dbaaafe0 Responses now contain the donation status
ref #193
2021-04-14 18:28:08 +02:00
b4c31ee9b5 Added donation status enum
ref #193
2021-04-14 18:25:42 +02:00
99307423c5 Added payed amount to update classes
ref #193
2021-04-14 18:19:26 +02:00
71542bc388 Added payed amount to crealte classes
ref #193
2021-04-14 18:17:26 +02:00
d64f470b60 Added payed amount to response class
ref #193
2021-04-14 18:15:37 +02:00
b8fbb72fa0 Added payed amount fileld to donation class
ref #193
2021-04-14 18:12:45 +02:00
0c61ff457d 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-07 17:28:37 +00:00
1d82f65b0d Merge pull request 'Release 0.10.2' (#192) from dev into main
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
Reviewed-on: #192
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-04-07 17:27:47 +00:00
610988ec16 🧾New changelog file version [CI SKIP] [skip ci]
All checks were successful
continuous-integration/drone/pr Build is passing
2021-04-07 17:20:21 +00:00
6e236ede14 🚀Bumped version to v0.10.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-07 19:18:21 +02:00
b7ad5d3a31 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-07 17:17:14 +00:00
a694ad225c Merge pull request 'stats/runners/laptime feature/190-runners_laptime' (#191) from feature/190-runners_laptime into dev
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #191
2021-04-07 17:16:33 +00:00
5633e85f41 added new ci secret
All checks were successful
continuous-integration/drone/pr Build is passing
ref #190
2021-04-07 18:13:00 +02:00
95e1eec313 Removed all useless console.logs
All checks were successful
continuous-integration/drone/pr Build is passing
ref #190
2021-04-07 16:41:10 +02:00
377d5dadb2 Potential fix for all remaining errors
All checks were successful
continuous-integration/drone/pr Build is passing
ref #190
2021-04-07 16:38:20 +02:00
4a294b1e17 Now resolving all relations for orgs by distance
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-07 16:34:09 +02:00
720774fcf4 Added temp console log
ref #190
2021-04-07 16:31:36 +02:00
dcdbdd15ac Ptotential fix for stats failing
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-07 16:28:48 +02:00
132b48cf2a Removed console log for passing tests
ref #190
2021-04-07 16:26:12 +02:00
23bd432c5f Resolved missing parentgroup relation
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-07 16:23:13 +02:00
71b33ab05b Removed console logs for now working tests
ref #190
2021-04-07 16:21:01 +02:00
87f444c30d At least one fewer test should fail now
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-07 16:17:37 +02:00
4a73eab134 Added temp console log for ci debugging
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-07 16:10:36 +02:00
f8baca5ab2 Updated default docker-compose
ref #190
2021-04-07 16:10:22 +02:00
10221b9f2e Pinned testing container tag to prod container tag
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-07 16:06:06 +02:00
1d8c8c8e9c Removed console log
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 10:45:06 +02:00
4603a84f16 Reverted temp bugfix
ref #190
2021-04-06 10:43:54 +02:00
2cd8f3f7f3 Merge branch 'feature/190-runners_laptime' of git.odit.services:lfk/backend into feature/190-runners_laptime
Some checks failed
continuous-integration/drone/pr Build is failing
2021-04-06 10:15:35 +02:00
107eeeae7f Merge branch 'feature/190-runners_laptime' of git.odit.services:lfk/backend into feature/190-runners_laptime 2021-04-06 10:15:32 +02:00
b8767b8bd4 Merge branch 'feature/190-runners_laptime' of git.odit.services:lfk/backend into feature/190-runners_laptime
Some checks failed
continuous-integration/drone/pr Build is failing
2021-04-06 10:08:00 +02:00
bf686e89e0 Temp test logging workaround
ref #190
2021-04-06 10:07:59 +02:00
6163f0a90b Temp test logging workaround
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 10:05:05 +02:00
8f0f795a70 Tried workaround for no availdable stats
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:34:12 +02:00
22cae39bd3 Added temp console log for test
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:29:23 +02:00
0b07a53ed2 Temp disabled runners by donations test
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:27:22 +02:00
d4a02e7db2 Added orgs by donations stats tests
ref #190
2021-04-06 09:26:19 +02:00
b9a7dc84f0 Added teams stats endpoint tests
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:21:23 +02:00
7111068361 Added runners stats tests
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:20:09 +02:00
63964fbf2c Removed test for content type
All checks were successful
continuous-integration/drone/pr Build is passing
ref #190
2021-04-06 09:14:45 +02:00
cbcb829fbd Fixed typo in test
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:12:03 +02:00
057ae0d797 Added first selfservice test
Some checks failed
continuous-integration/drone/pr Build is failing
ref #190
2021-04-06 09:09:01 +02:00
257f320ee3 Now resolving all missing relations
ref #190
2021-04-06 09:02:07 +02:00
7b15c2d88b Fixed sorting
ref #190
2021-04-06 08:58:22 +02:00
988f17a795 Fixed sorting algo
ref #190
2021-04-06 08:56:34 +02:00
4471e57438 First try of the laptime sort
ref #190
2021-04-06 08:44:14 +02:00
51daf969cf Added min laptime to StatsRunner
ref #190
2021-04-06 08:14:02 +02:00
cb71fcd13b Added basic laptime endpoint
ref #190
2021-04-06 08:13:43 +02:00
a6a526dc5d Fixed top-ten bein top 9
ref #190
2021-04-05 17:47:51 +02:00
dd6d799c84 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-03 16:25:14 +00:00
26 changed files with 443 additions and 36 deletions

View File

@@ -19,10 +19,17 @@ get:
path: odit-git-bot path: odit-git-bot
name: sshkey name: sshkey
---
kind: secret
name: ci_token
get:
path: odit-ci-bot
name: apikey
--- ---
kind: pipeline kind: pipeline
type: kubernetes type: kubernetes
name: tests:node_latest name: tests:node_14.15.1-alpine3.12
clone: clone:
disable: true disable: true
steps: steps:
@@ -32,7 +39,7 @@ steps:
- git clone $DRONE_REMOTE_URL . - git clone $DRONE_REMOTE_URL .
- git checkout $DRONE_SOURCE_BRANCH - git checkout $DRONE_SOURCE_BRANCH
- name: run tests - name: run tests
image: node:latest image: node:14.15.1-alpine3.12
commands: commands:
- yarn - yarn
- yarn test:ci - yarn test:ci
@@ -176,13 +183,13 @@ steps:
settings: settings:
urls: https://ci.odit.services/api/repos/lfk/lfk-client-node/builds?SOURCE_TAG=${DRONE_TAG} urls: https://ci.odit.services/api/repos/lfk/lfk-client-node/builds?SOURCE_TAG=${DRONE_TAG}
bearer: bearer:
from_secret: BOT_DRONE_KEY from_secret: ci_token
- name: trigger js lib build - name: trigger js lib build
image: idcooldi/drone-webhook image: idcooldi/drone-webhook
settings: settings:
urls: https://ci.odit.services/api/repos/lfk/lfk-client-js/builds?SOURCE_TAG=${DRONE_TAG} urls: https://ci.odit.services/api/repos/lfk/lfk-client-js/builds?SOURCE_TAG=${DRONE_TAG}
bearer: bearer:
from_secret: BOT_DRONE_KEY from_secret: ci_token
trigger: trigger:
event: event:
- tag - tag

View File

@@ -2,17 +2,100 @@
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.
#### [v0.11.1](https://git.odit.services/lfk/backend/compare/v0.11.0...v0.11.1)
- 🧾New changelog file version [CI SKIP] [skip ci] [`2229cdf`](https://git.odit.services/lfk/backend/commit/2229cdf20db1a98f9f76a99fa9d3f463cdf6d804)
- 🧾New changelog file version [CI SKIP] [skip ci] [`348fe52`](https://git.odit.services/lfk/backend/commit/348fe52c42cfa32239b703041820f725e147154e)
- Now prefixing runnercards with 2 [`8a82e05`](https://git.odit.services/lfk/backend/commit/8a82e059b74ceabf43c9cbfe9c9b89ef6ce15a28)
- Added fix for the appended 2 [`eb526fb`](https://git.odit.services/lfk/backend/commit/eb526fb57faf631fd6e84af99af738ab1b3481c7)
- 🚀Bumped version to v0.11.1 [`95320ca`](https://git.odit.services/lfk/backend/commit/95320ca1bccc2886553accea6a428aadffda0a27)
- 🧾New changelog file version [CI SKIP] [skip ci] [`f2d127f`](https://git.odit.services/lfk/backend/commit/f2d127fc98d75ce658424624abd382c087737ca0)
#### [v0.11.0](https://git.odit.services/lfk/backend/compare/v0.10.2...v0.11.0)
> 14 April 2021
- Merge pull request 'Release 0.11.0' (#195) from dev into main [`3220b19`](https://git.odit.services/lfk/backend/commit/3220b194d4c704835d6d106ec4d9d54a17a38b62)
- 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)
- 🧾New changelog file version [CI SKIP] [skip ci] [`278c4a6`](https://git.odit.services/lfk/backend/commit/278c4a6a415434487a92ff66f8114bb2547aac48)
- 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 response class [`d64f470`](https://git.odit.services/lfk/backend/commit/d64f470b608b3f179ec77da0210de51c328ef3f2)
- 📖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 payed amount to crealte classes [`71542bc`](https://git.odit.services/lfk/backend/commit/71542bc3887b97c15436d03280e49f7b3f0fcb06)
- Added donation status enum [`b4c31ee`](https://git.odit.services/lfk/backend/commit/b4c31ee9b5b35d6e11b07f50f3d30ca12e0f7728)
- Added payed amount to update classes [`9930742`](https://git.odit.services/lfk/backend/commit/99307423c533f8cde847b59a80bffc2ff42c9769)
- 🧾New changelog file version [CI SKIP] [skip ci] [`0c61ff4`](https://git.odit.services/lfk/backend/commit/0c61ff457d02f750efa457dd75464187683b037a)
- Added mssing check to tests [`6c14ed9`](https://git.odit.services/lfk/backend/commit/6c14ed9c89eadc1a10db8c912d8ea2711a518766)
- 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)
- Potential fix for all remaining errors [`377d5da`](https://git.odit.services/lfk/backend/commit/377d5dadb2a14cb2d70e0b2dc77026f51b3fb51c)
- At least one fewer test should fail now [`87f444c`](https://git.odit.services/lfk/backend/commit/87f444c30d69d65a9f918c63631a859a389eeee3)
- Tried workaround for no availdable stats [`8f0f795`](https://git.odit.services/lfk/backend/commit/8f0f795a709db216396998b68b8bbd64ff4d44ff)
- Reverted temp bugfix [`4603a84`](https://git.odit.services/lfk/backend/commit/4603a84f16fb53a14d1792447100f5b470969dd0)
- Fixed sorting algo [`988f17a`](https://git.odit.services/lfk/backend/commit/988f17a795bb2d867e9d1d8e78051dff1a14ec30)
- Added runners stats tests [`7111068`](https://git.odit.services/lfk/backend/commit/7111068361e00cc1308664a3ae650a56e28c015c)
- Added basic laptime endpoint [`cb71fcd`](https://git.odit.services/lfk/backend/commit/cb71fcd13bc61e6214e2fd7b70e72094749463d3)
- Added orgs by donations stats tests [`d4a02e7`](https://git.odit.services/lfk/backend/commit/d4a02e7db2ff4976be21605e31aac2f3c82a49c0)
- Added teams stats endpoint tests [`b9a7dc8`](https://git.odit.services/lfk/backend/commit/b9a7dc84f05441445453193974b2a793b5197fa5)
- Now resolving all missing relations [`257f320`](https://git.odit.services/lfk/backend/commit/257f320ee3bf6429c4314c64023520366f9f730b)
- Added min laptime to StatsRunner [`51daf96`](https://git.odit.services/lfk/backend/commit/51daf969cf74792b2c2f2f16ce4359d9fca47bc8)
- Fixed sorting [`7b15c2d`](https://git.odit.services/lfk/backend/commit/7b15c2d88b14e7279aad97b0c950202ddb5acaaa)
- 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)
- 🧾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)
- 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)
- Removed console log for passing tests [`132b48c`](https://git.odit.services/lfk/backend/commit/132b48cf2a9e990a5e830c744ed8244bd25e8b3a)
- Removed console log [`1d8c8c8`](https://git.odit.services/lfk/backend/commit/1d8c8c8e9cefa58449f7abb2481d9396fe37ba20)
- Temp test logging workaround [`bf686e8`](https://git.odit.services/lfk/backend/commit/bf686e89e02998ccc80c838ef890c736c252634c)
- Temp test logging workaround [`6163f0a`](https://git.odit.services/lfk/backend/commit/6163f0a90b3721d3a1488f89cbb39ddff7152241)
- Removed test for content type [`63964fb`](https://git.odit.services/lfk/backend/commit/63964fbf2c41d9b90f995f056e9db65ab07d54a8)
#### [v0.10.1](https://git.odit.services/lfk/backend/compare/v0.10.0...v0.10.1) #### [v0.10.1](https://git.odit.services/lfk/backend/compare/v0.10.0...v0.10.1)
> 3 April 2021
- Merge pull request 'Release 0.10.1' (#189) from dev into main [`e89e07d`](https://git.odit.services/lfk/backend/commit/e89e07d0fc99f14148b01204fb8ed39e2da77e38)
- 🧾New changelog file version [CI SKIP] [skip ci] [`69afd4d`](https://git.odit.services/lfk/backend/commit/69afd4d5877401eb46df430f43a7feb273abda1e) - 🧾New changelog file version [CI SKIP] [skip ci] [`69afd4d`](https://git.odit.services/lfk/backend/commit/69afd4d5877401eb46df430f43a7feb273abda1e)
- 🚀Bumped version to v0.10.1 [`24d152f`](https://git.odit.services/lfk/backend/commit/24d152fdc8fe17fffa2f2a718d7145ba8a91d79c) - 🚀Bumped version to v0.10.1 [`24d152f`](https://git.odit.services/lfk/backend/commit/24d152fdc8fe17fffa2f2a718d7145ba8a91d79c)
- New class: ResponseSelfServiceDonor [`d70c5b1`](https://git.odit.services/lfk/backend/commit/d70c5b1bbc9f02782f8755b6929e2d3458e10221)
- 🧾New changelog file version [CI SKIP] [skip ci] [`4279e43`](https://git.odit.services/lfk/backend/commit/4279e4374304887e8db40eab77763b20bbce91a1) - 🧾New changelog file version [CI SKIP] [skip ci] [`4279e43`](https://git.odit.services/lfk/backend/commit/4279e4374304887e8db40eab77763b20bbce91a1)
- Removed duplicate openapi statement [`4834a66`](https://git.odit.services/lfk/backend/commit/4834a6698b0958602421c1478a95fec7edda910b) - Removed duplicate openapi statement [`4834a66`](https://git.odit.services/lfk/backend/commit/4834a6698b0958602421c1478a95fec7edda910b)
- Merge pull request 'Selfservice donations reformatting feature/187-selfservice_donation' (#188) from feature/187-selfservice_donation into dev [`d837654`](https://git.odit.services/lfk/backend/commit/d837654617f7de5d055ffb06c65e2cd52f65c604)
- New class: ResponseSelfServiceDonor [`d70c5b1`](https://git.odit.services/lfk/backend/commit/d70c5b1bbc9f02782f8755b6929e2d3458e10221)
- Switched selfservice donation.donor from string to object [`0767943`](https://git.odit.services/lfk/backend/commit/0767943721b6964d542f580c541e744f86444ac6) - Switched selfservice donation.donor from string to object [`0767943`](https://git.odit.services/lfk/backend/commit/0767943721b6964d542f580c541e744f86444ac6)
- Adjusted runner property names [`ca87774`](https://git.odit.services/lfk/backend/commit/ca87774767807a2c4bc869b0de95cc73832a8405) - Adjusted runner property names [`ca87774`](https://git.odit.services/lfk/backend/commit/ca87774767807a2c4bc869b0de95cc73832a8405)
- 🧾New changelog file version [CI SKIP] [skip ci] [`71e3d0e`](https://git.odit.services/lfk/backend/commit/71e3d0efe2cbde47aea0f26cb5a8b5cd3312707d) - 🧾New changelog file version [CI SKIP] [skip ci] [`71e3d0e`](https://git.odit.services/lfk/backend/commit/71e3d0efe2cbde47aea0f26cb5a8b5cd3312707d)
- 🧾New changelog file version [CI SKIP] [skip ci] [`c28843c`](https://git.odit.services/lfk/backend/commit/c28843c405dc4fd06a10f0fb85814acede15a769)
- Merge pull request 'Selfservice donations reformatting feature/187-selfservice_donation' (#188) from feature/187-selfservice_donation into dev [`d837654`](https://git.odit.services/lfk/backend/commit/d837654617f7de5d055ffb06c65e2cd52f65c604)
- Added new responsetype for new class [`f693f2c`](https://git.odit.services/lfk/backend/commit/f693f2cde9a04147155aea4de5d52e1d19d722ca) - Added new responsetype for new class [`f693f2c`](https://git.odit.services/lfk/backend/commit/f693f2cde9a04147155aea4de5d52e1d19d722ca)
#### [v0.10.0](https://git.odit.services/lfk/backend/compare/v0.9.2...v0.10.0) #### [v0.10.0](https://git.odit.services/lfk/backend/compare/v0.9.2...v0.10.0)

View File

@@ -11,8 +11,12 @@ services:
DB_PORT: bla DB_PORT: bla
DB_USER: bla DB_USER: bla
DB_PASSWORD: bla DB_PASSWORD: bla
DB_NAME: dev.sqlite DB_NAME: ./db.sqlite
NODE_ENV: production NODE_ENV: production
POSTALCODE_COUNTRYCODE: DE
SEED_TEST_DATA: "false"
MAILER_URL: https://dev.lauf-fuer-kaya.de/mailer
MAILER_KEY: asdasd
# APP_PORT: 4010 # APP_PORT: 4010
# DB_TYPE: postgres # DB_TYPE: postgres
# DB_HOST: backend_db # DB_HOST: backend_db

View File

@@ -454,7 +454,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## License Text ## License Text
MIT License 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-backend", "name": "@odit/lfk-backend",
"version": "0.10.1", "version": "0.11.1",
"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

@@ -1,4 +1,4 @@
import { Get, JsonController, UseBefore } from 'routing-controllers'; import { Get, JsonController, QueryParam, UseBefore } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { getConnection } from 'typeorm'; import { getConnection } from 'typeorm';
import StatsAuth from '../middlewares/StatsAuth'; import StatsAuth from '../middlewares/StatsAuth';
@@ -7,6 +7,7 @@ import { Runner } from '../models/entities/Runner';
import { RunnerOrganization } from '../models/entities/RunnerOrganization'; import { RunnerOrganization } from '../models/entities/RunnerOrganization';
import { RunnerTeam } from '../models/entities/RunnerTeam'; import { RunnerTeam } from '../models/entities/RunnerTeam';
import { Scan } from '../models/entities/Scan'; import { Scan } from '../models/entities/Scan';
import { TrackScan } from '../models/entities/TrackScan';
import { User } from '../models/entities/User'; import { User } from '../models/entities/User';
import { ResponseStats } from '../models/responses/ResponseStats'; import { ResponseStats } from '../models/responses/ResponseStats';
import { ResponseStatsOrgnisation } from '../models/responses/ResponseStatsOrganization'; import { ResponseStatsOrgnisation } from '../models/responses/ResponseStatsOrganization';
@@ -36,7 +37,10 @@ export class StatsController {
@OpenAPI({ description: "Returns the top ten runners by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten runners by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopRunnersByDistance() { async getTopRunnersByDistance() {
let runners = await getConnection().getRepository(Runner).find({ relations: ['scans', 'group', 'distanceDonations', 'scans.track'] }); let runners = await getConnection().getRepository(Runner).find({ relations: ['scans', 'group', 'distanceDonations', 'scans.track'] });
let topRunners = runners.sort((runner1, runner2) => runner1.distance - runner2.distance).slice(0, 9); if (!runners || runners.length == 0) {
return [];
}
let topRunners = runners.sort((runner1, runner2) => runner2.distance - runner1.distance).slice(0, 10);
let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>(); let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>();
topRunners.forEach(runner => { topRunners.forEach(runner => {
responseRunners.push(new ResponseStatsRunner(runner)); responseRunners.push(new ResponseStatsRunner(runner));
@@ -49,8 +53,11 @@ export class StatsController {
@ResponseSchema(ResponseStatsRunner, { isArray: true }) @ResponseSchema(ResponseStatsRunner, { isArray: true })
@OpenAPI({ description: "Returns the top ten runners by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten runners by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopRunnersByDonations() { async getTopRunnersByDonations() {
let runners = await getConnection().getRepository(Runner).find({ relations: ['scans', 'group', 'distanceDonations', 'scans.track'] }); let runners = await getConnection().getRepository(Runner).find({ relations: ['group', 'distanceDonations', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] });
let topRunners = runners.sort((runner1, runner2) => runner1.distanceDonationAmount - runner2.distanceDonationAmount).slice(0, 9); if (!runners || runners.length == 0) {
return [];
}
let topRunners = runners.sort((runner1, runner2) => runner2.distanceDonationAmount - runner1.distanceDonationAmount).slice(0, 10);
let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>(); let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>();
topRunners.forEach(runner => { topRunners.forEach(runner => {
responseRunners.push(new ResponseStatsRunner(runner)); responseRunners.push(new ResponseStatsRunner(runner));
@@ -58,6 +65,34 @@ export class StatsController {
return responseRunners; return responseRunners;
} }
@Get("/runners/laptime")
@UseBefore(StatsAuth)
@ResponseSchema(ResponseStatsRunner, { isArray: true })
@OpenAPI({ description: "Returns the top ten runners by fastest laptime on your selected track (track by id).", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopRunnersByLaptime(@QueryParam("track") track: number) {
let scans = await getConnection().getRepository(TrackScan).find({ relations: ['track', 'runner', 'runner.group', 'runner.scans', 'runner.scans.track', 'runner.distanceDonations'] });
if (!scans || scans.length == 0) {
return [];
}
scans = scans.filter((s) => { return s.track.id == track && s.valid == true && s.lapTime != 0 }).sort((scan1, scan2) => scan1.lapTime - scan2.lapTime);
let topScans = new Array<TrackScan>();
let knownRunners = new Array<number>();
for (let i = 0; i < scans.length && topScans.length < 10; i++) {
const element = scans[i];
if (!knownRunners.includes(element.runner.id)) {
topScans.push(element);
knownRunners.push(element.runner.id);
}
}
let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>();
topScans.forEach(scan => {
responseRunners.push(new ResponseStatsRunner(scan.runner, scan.lapTime));
});
return responseRunners;
}
@Get("/scans") @Get("/scans")
@UseBefore(StatsAuth) @UseBefore(StatsAuth)
@ResponseSchema(ResponseStatsRunner, { isArray: true }) @ResponseSchema(ResponseStatsRunner, { isArray: true })
@@ -71,8 +106,11 @@ export class StatsController {
@ResponseSchema(ResponseStatsTeam, { isArray: true }) @ResponseSchema(ResponseStatsTeam, { isArray: true })
@OpenAPI({ description: "Returns the top ten teams by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten teams by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopTeamsByDistance() { async getTopTeamsByDistance() {
let teams = await getConnection().getRepository(RunnerTeam).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track'] }); let teams = await getConnection().getRepository(RunnerTeam).find({ relations: ['parentGroup', 'runners', 'runners.scans', 'runners.scans.track'] });
let topTeams = teams.sort((team1, team2) => team1.distance - team2.distance).slice(0, 9); if (!teams || teams.length == 0) {
return [];
}
let topTeams = teams.sort((team1, team2) => team2.distance - team1.distance).slice(0, 10);
let responseTeams: ResponseStatsTeam[] = new Array<ResponseStatsTeam>(); let responseTeams: ResponseStatsTeam[] = new Array<ResponseStatsTeam>();
topTeams.forEach(team => { topTeams.forEach(team => {
responseTeams.push(new ResponseStatsTeam(team)); responseTeams.push(new ResponseStatsTeam(team));
@@ -85,8 +123,11 @@ export class StatsController {
@ResponseSchema(ResponseStatsTeam, { isArray: true }) @ResponseSchema(ResponseStatsTeam, { isArray: true })
@OpenAPI({ description: "Returns the top ten teams by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten teams by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopTeamsByDonations() { async getTopTeamsByDonations() {
let teams = await getConnection().getRepository(RunnerTeam).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track'] }); let teams = await getConnection().getRepository(RunnerTeam).find({ relations: ['parentGroup', 'runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track'] });
let topTeams = teams.sort((team1, team2) => team1.distanceDonationAmount - team2.distanceDonationAmount).slice(0, 9); if (!teams || teams.length == 0) {
return [];
}
let topTeams = teams.sort((team1, team2) => team2.distanceDonationAmount - team1.distanceDonationAmount).slice(0, 10);
let responseTeams: ResponseStatsTeam[] = new Array<ResponseStatsTeam>(); let responseTeams: ResponseStatsTeam[] = new Array<ResponseStatsTeam>();
topTeams.forEach(team => { topTeams.forEach(team => {
responseTeams.push(new ResponseStatsTeam(team)); responseTeams.push(new ResponseStatsTeam(team));
@@ -100,7 +141,10 @@ export class StatsController {
@OpenAPI({ description: "Returns the top ten organizations by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten organizations by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopOrgsByDistance() { async getTopOrgsByDistance() {
let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] }); let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] });
let topOrgs = orgs.sort((org1, org2) => org1.distance - org2.distance).slice(0, 9); if (!orgs || orgs.length == 0) {
return [];
}
let topOrgs = orgs.sort((org1, org2) => org2.distance - org1.distance).slice(0, 10);
let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>(); let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>();
topOrgs.forEach(org => { topOrgs.forEach(org => {
responseOrgs.push(new ResponseStatsOrgnisation(org)); responseOrgs.push(new ResponseStatsOrgnisation(org));
@@ -113,8 +157,11 @@ export class StatsController {
@ResponseSchema(ResponseStatsOrgnisation, { isArray: true }) @ResponseSchema(ResponseStatsOrgnisation, { isArray: true })
@OpenAPI({ description: "Returns the top ten organizations by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @OpenAPI({ description: "Returns the top ten organizations by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
async getTopOrgsByDonations() { async getTopOrgsByDonations() {
let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] }); let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.distanceDonations', 'runners.distanceDonations.runner', 'runners.distanceDonations.runner.scans', 'runners.distanceDonations.runner.scans.track', 'teams', 'teams.runners', 'teams.runners.distanceDonations', 'teams.runners.distanceDonations.runner', 'teams.runners.distanceDonations.runner.scans', 'teams.runners.distanceDonations.runner.scans.track'] });
let topOrgs = orgs.sort((org1, org2) => org1.distanceDonationAmount - org2.distanceDonationAmount).slice(0, 9); if (!orgs || orgs.length == 0) {
return [];
}
let topOrgs = orgs.sort((org1, org2) => org2.distanceDonationAmount - org1.distanceDonationAmount).slice(0, 10);
let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>(); let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>();
topOrgs.forEach(org => { topOrgs.forEach(org => {
responseOrgs.push(new ResponseStatsOrgnisation(org)); responseOrgs.push(new ResponseStatsOrgnisation(org));

View File

@@ -33,6 +33,7 @@ export class CreateDistanceDonation extends CreateDonation {
let newDonation = new DistanceDonation; let newDonation = new DistanceDonation;
newDonation.amountPerDistance = this.amountPerDistance; newDonation.amountPerDistance = this.amountPerDistance;
newDonation.paidAmount = this.paidAmount;
newDonation.donor = await this.getDonor(); newDonation.donor = await this.getDonor();
newDonation.runner = await this.getRunner(); newDonation.runner = await this.getRunner();

View File

@@ -1,4 +1,4 @@
import { IsInt, IsPositive } from 'class-validator'; import { IsInt, IsOptional, IsPositive } from 'class-validator';
import { getConnection } from 'typeorm'; import { getConnection } from 'typeorm';
import { DonorNotFoundError } from '../../../errors/DonorErrors'; import { DonorNotFoundError } from '../../../errors/DonorErrors';
import { Donation } from '../../entities/Donation'; import { Donation } from '../../entities/Donation';
@@ -16,6 +16,13 @@ export abstract class CreateDonation {
@IsPositive() @IsPositive()
donor: number; 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. * Creates a new Donation entity from this.
*/ */

View File

@@ -21,6 +21,7 @@ export class CreateFixedDonation extends CreateDonation {
let newDonation = new FixedDonation; let newDonation = new FixedDonation;
newDonation.amount = this.amount; newDonation.amount = this.amount;
newDonation.paidAmount = this.paidAmount;
newDonation.donor = await this.getDonor(); newDonation.donor = await this.getDonor();
return newDonation; return newDonation;

View File

@@ -57,7 +57,8 @@ export class CreateTrackScan {
* @returns The runnerCard whom's id you provided. * @returns The runnerCard whom's id you provided.
*/ */
public async getCard(): Promise<RunnerCard> { public async getCard(): Promise<RunnerCard> {
const track = await getConnection().getRepository(RunnerCard).findOne({ id: this.card }, { relations: ["runner"] }); const id = this.card % 200000000000;
const track = await getConnection().getRepository(RunnerCard).findOne({ id: id }, { relations: ["runner"] });
if (!track) { if (!track) {
throw new RunnerCardNotFoundError(); throw new RunnerCardNotFoundError();
} }

View File

@@ -32,6 +32,7 @@ export class UpdateDistanceDonation extends UpdateDonation {
*/ */
public async update(donation: DistanceDonation): Promise<DistanceDonation> { public async update(donation: DistanceDonation): Promise<DistanceDonation> {
donation.amountPerDistance = this.amountPerDistance; donation.amountPerDistance = this.amountPerDistance;
donation.paidAmount = this.paidAmount;
donation.donor = await this.getDonor(); donation.donor = await this.getDonor();
donation.runner = await this.getRunner(); donation.runner = await this.getRunner();

View File

@@ -1,4 +1,4 @@
import { IsInt, IsPositive } from 'class-validator'; import { IsInt, IsOptional, IsPositive } from 'class-validator';
import { getConnection } from 'typeorm'; import { getConnection } from 'typeorm';
import { DonorNotFoundError } from '../../../errors/DonorErrors'; import { DonorNotFoundError } from '../../../errors/DonorErrors';
import { Donation } from '../../entities/Donation'; import { Donation } from '../../entities/Donation';
@@ -23,6 +23,13 @@ export abstract class UpdateDonation {
@IsPositive() @IsPositive()
donor: number; 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. * Creates a new Donation entity from this.
*/ */

View File

@@ -20,6 +20,7 @@ export class UpdateFixedDonation extends UpdateDonation {
*/ */
public async update(donation: FixedDonation): Promise<FixedDonation> { public async update(donation: FixedDonation): Promise<FixedDonation> {
donation.amount = this.amount; donation.amount = this.amount;
donation.paidAmount = this.paidAmount;
donation.donor = await this.getDonor(); donation.donor = await this.getDonor();
return donation; return donation;

View File

@@ -2,7 +2,7 @@ import {
IsInt, IsInt,
IsNotEmpty IsNotEmpty
} from "class-validator"; } from "class-validator";
import { Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm";
import { ResponseDonation } from '../responses/ResponseDonation'; import { ResponseDonation } from '../responses/ResponseDonation';
import { Donor } from './Donor'; import { Donor } from './Donor';
@@ -34,6 +34,13 @@ export abstract class Donation {
*/ */
public abstract get amount(): number; 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. * Turns this entity into it's response class.

View File

@@ -33,6 +33,15 @@ export class Donor extends Participant {
return this.donations.reduce((sum, current) => sum + current.amount, 0); 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. * Turns this entity into it's response class.
*/ */

View File

@@ -67,10 +67,11 @@ export class RunnerCard {
private get paddedId(): string { private get paddedId(): string {
let id: string = this.id.toString(); let id: string = this.id.toString();
if (id.length > 12) { if (id.length > 11) {
throw new RunnerCardIdOutOfRangeError(); throw new RunnerCardIdOutOfRangeError();
} }
while (id.length < 12) { id = '0' + id; } while (id.length < 11) { id = '0' + id; }
id = '2' + id;
return id; return id;
} }

View File

@@ -51,6 +51,9 @@ export abstract class RunnerGroup {
*/ */
@IsInt() @IsInt()
public get distance(): number { public get distance(): number {
if (!this.runners || this.runners.length == 0) {
return 0;
}
return this.runners.reduce((sum, current) => sum + current.distance, 0); return this.runners.reduce((sum, current) => sum + current.distance, 0);
} }

View File

@@ -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'
}

View File

@@ -1,5 +1,6 @@
import { IsInt, IsNotEmpty, IsPositive } from "class-validator"; import { IsInt, IsNotEmpty, IsPositive } from "class-validator";
import { Donation } from '../entities/Donation'; import { Donation } from '../entities/Donation';
import { DonationStatus } from '../enums/DonationStatus';
import { ResponseObjectType } from '../enums/ResponseObjectType'; import { ResponseObjectType } from '../enums/ResponseObjectType';
import { IResponse } from './IResponse'; import { IResponse } from './IResponse';
import { ResponseDonor } from './ResponseDonor'; import { ResponseDonor } from './ResponseDonor';
@@ -15,6 +16,12 @@ export class ResponseDonation implements IResponse {
*/ */
responseType: ResponseObjectType = ResponseObjectType.DONATION; 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. * The donation's id.
*/ */
@@ -34,6 +41,12 @@ export class ResponseDonation implements IResponse {
@IsInt() @IsInt()
amount: number; 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. * Creates a ResponseDonation object from a scan.
* @param donation The donation the response shall be build for. * @param donation The donation the response shall be build for.
@@ -42,5 +55,12 @@ export class ResponseDonation implements IResponse {
this.id = donation.id; this.id = donation.id;
this.donor = donation.donor.toResponse(); this.donor = donation.donor.toResponse();
this.amount = donation.amount; this.amount = donation.amount;
this.paidAmount = donation.paidAmount || 0;
if (this.paidAmount < this.amount) {
this.status = DonationStatus.OPEN;
}
else {
this.status = DonationStatus.PAID;
}
} }
} }

View File

@@ -28,6 +28,12 @@ export class ResponseDonor extends ResponseParticipant implements IResponse {
@IsInt() @IsInt()
donationAmount: number; 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. * Creates a ResponseRunner object from a runner.
* @param runner The user the response shall be build for. * @param runner The user the response shall be build for.
@@ -36,5 +42,6 @@ export class ResponseDonor extends ResponseParticipant implements IResponse {
super(donor); super(donor);
this.receiptNeeded = donor.receiptNeeded; this.receiptNeeded = donor.receiptNeeded;
this.donationAmount = donor.donationAmount; this.donationAmount = donor.donationAmount;
this.paidDonationAmount = donor.paidDonationAmount;
} }
} }

View File

@@ -49,7 +49,15 @@ export class ResponseStatsOrgnisation implements IResponse {
public constructor(org: RunnerOrganization) { public constructor(org: RunnerOrganization) {
this.name = org.name; this.name = org.name;
this.id = org.id; this.id = org.id;
this.distance = org.distance; try {
this.donationAmount = org.distanceDonationAmount; this.distance = org.distance;
} catch {
this.distance = -1;
}
try {
this.donationAmount = org.distanceDonationAmount;
} catch {
this.donationAmount = -1;
}
} }
} }

View File

@@ -1,6 +1,7 @@
import { import {
IsInt, IsInt,
IsObject, IsObject,
IsOptional,
IsString IsString
} from "class-validator"; } from "class-validator";
import { Runner } from '../entities/Runner'; import { Runner } from '../entities/Runner';
@@ -55,6 +56,13 @@ export class ResponseStatsRunner implements IResponse {
@IsInt() @IsInt()
donationAmount: number; donationAmount: number;
/**
* The runner's fastest laptime in seconds.
*/
@IsInt()
@IsOptional()
minLaptime?: number;
/** /**
* The runner's group. * The runner's group.
*/ */
@@ -65,13 +73,28 @@ export class ResponseStatsRunner implements IResponse {
* Creates a new runner stats response from a runner * Creates a new runner stats response from a runner
* @param runner The runner whoes response shall be generated - the following relations have to be resolved: scans, group, distanceDonations, scans.track * @param runner The runner whoes response shall be generated - the following relations have to be resolved: scans, group, distanceDonations, scans.track
*/ */
public constructor(runner: Runner) { public constructor(runner: Runner, laptime?: number) {
this.id = runner.id; this.id = runner.id;
this.firstname = runner.firstname; this.firstname = runner.firstname;
this.middlename = runner.middlename; if (runner.firstname) {
this.middlename = runner.middlename;
}
this.lastname = runner.lastname; this.lastname = runner.lastname;
this.distance = runner.distance; try {
this.donationAmount = runner.distanceDonationAmount; this.distance = runner.distance;
}
catch {
this.distance = -1;
}
try {
this.donationAmount = runner.distanceDonationAmount;
}
catch {
this.donationAmount = -1;
}
if (laptime) {
this.minLaptime = laptime;
}
this.group = runner.group.toResponse(); this.group = runner.group.toResponse();
} }
} }

View File

@@ -57,7 +57,15 @@ export class ResponseStatsTeam implements IResponse {
this.name = team.name; this.name = team.name;
this.id = team.id; this.id = team.id;
this.parent = team.parentGroup.toResponse(); this.parent = team.parentGroup.toResponse();
this.distance = team.distance; try {
this.donationAmount = team.distanceDonationAmount; this.distance = team.distance;
} catch {
this.distance = -1;
}
try {
this.donationAmount = team.distanceDonationAmount;
} catch {
this.donationAmount = -1;
}
} }
} }

View File

@@ -170,7 +170,7 @@ describe('POST /api/donations/fixed successfully', () => {
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") 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', { const res = await axios.post(base + '/api/donations/fixed', {
"donor": added_donor.id, "donor": added_donor.id,
"amount": 1000 "amount": 1000
@@ -181,6 +181,25 @@ describe('POST /api/donations/fixed successfully', () => {
expect(res.data).toEqual({ expect(res.data).toEqual({
"donor": added_donor, "donor": added_donor,
"amount": 1000, "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" "responseType": "DONATION"
}); });
}); });
@@ -219,7 +238,7 @@ describe('POST /api/donations/distance successfully', () => {
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") 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', { const res = await axios.post(base + '/api/donations/distance', {
"runner": added_runner.id, "runner": added_runner.id,
"amountPerDistance": 100, "amountPerDistance": 100,
@@ -233,6 +252,28 @@ describe('POST /api/donations/distance successfully', () => {
"amountPerDistance": 100, "amountPerDistance": 100,
"runner": added_runner, "runner": added_runner,
"amount": 0, "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" "responseType": "DISTANCEDONATION"
}) })
}); });

View File

@@ -213,6 +213,17 @@ describe('adding + updating fixed donation valid', () => {
expect(res.headers['content-type']).toContain("application/json"); expect(res.headers['content-type']).toContain("application/json");
expect(res.data.amount).toEqual(42); 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 () => { it('updating donor should return 200', async () => {
const res = await axios.put(base + '/api/donations/fixed/' + added_donation.id, { const res = await axios.put(base + '/api/donations/fixed/' + added_donation.id, {
"id": 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.headers['content-type']).toContain("application/json");
expect(res.data.amountPerDistance).toEqual(69); 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 () => { it('updating runner should return 200', async () => {
const res = await axios.put(base + '/api/donations/distance/' + added_donation.id, { const res = await axios.put(base + '/api/donations/distance/' + added_donation.id, {
"id": added_donation.id, "id": added_donation.id,

View File

@@ -0,0 +1,89 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let axios_config_full;
let axios_config_stats;
beforeAll(async () => {
jest.setTimeout(20000);
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
let access_token = res.data["access_token"];
axios_config_full = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
const res2 = await axios.post(base + '/api/statsclients', { username: "demo", password: "demo" }, axios_config_full);
access_token = res2.data["key"];
axios_config_stats = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
describe('GET /api/stats/runners/distance w/o auth should return 200', () => {
it('get with invalid token should return 401', async () => {
const res = await axios.get(base + '/api/stats/runners/distance', {
headers: { "authorization": "Bearer 123123123123123123" },
validateStatus: undefined
});
expect(res.status).toEqual(401);
});
});
// ---------------
describe('GET /api/stats should return 200', () => {
it('get w/o auth should return 200', async () => {
const res = await axios.get(base + '/api/stats', { validateStatus: undefined });
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('get w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('GET /api/stats/runners/* should return 200', () => {
it('get by distance w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/runners/distance', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('get by donations w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/runners/donations', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('get by laptime w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/runners/laptime', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('GET /api/stats/teams/* should return 200', () => {
it('get by distance w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/teams/distance', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('get by donations w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/teams/donations', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});
// ---------------
describe('GET /api/stats/organizations/* should return 200', () => {
it('get by distance w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/organizations/distance', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('get by donations w/ auth should return 200', async () => {
const res = await axios.get(base + '/api/stats/organizations/donations', axios_config_stats);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
});