Compare commits

..

7 Commits
1.3.4 ... 1.3.7

Author SHA1 Message Date
03e0a29096 chore(release): 1.3.7
All checks were successful
Build release images / build-container (push) Successful in 1m16s
2025-04-08 21:15:59 +02:00
a6afba93e2 feat(stats): Publish runners by kiosk stat 2025-04-08 21:15:41 +02:00
a41758cd9c chore(release): 1.3.6
All checks were successful
Build release images / build-container (push) Successful in 1m32s
2025-04-08 21:06:01 +02:00
d6755ed134 feat(runners): Allow created via being set via api 2025-04-08 21:04:38 +02:00
599c75fc00 fix(participant): Switch to correct type 2025-04-08 21:03:23 +02:00
bb213f001e chore(release): 1.3.5
All checks were successful
Build release images / build-container (push) Successful in 1m16s
2025-04-08 20:01:13 +02:00
5415cd38a7 feat(runners): Generate selfservice urls on runner if requested or create/update/get single 2025-04-08 20:00:27 +02:00
9 changed files with 66 additions and 11 deletions

View File

@@ -2,9 +2,31 @@
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.3.7](https://git.odit.services/lfk/backend/compare/1.3.6...1.3.7)
- feat(stats): Publish runners by kiosk stat [`a6afba9`](https://git.odit.services/lfk/backend/commit/a6afba93e243ca419c282a16cad023d06d864e0e)
#### [1.3.6](https://git.odit.services/lfk/backend/compare/1.3.5...1.3.6)
> 8 April 2025
- chore(release): 1.3.6 [`a41758c`](https://git.odit.services/lfk/backend/commit/a41758cd9c83105c3a4b407744bafe2f0f6fb48a)
- feat(runners): Allow created via being set via api [`d6755ed`](https://git.odit.services/lfk/backend/commit/d6755ed134071df635bc9d5821ceb2396c0f1d22)
- fix(participant): Switch to correct type [`599c75f`](https://git.odit.services/lfk/backend/commit/599c75fc00217eaec3cc87c0de50d059bdde685f)
#### [1.3.5](https://git.odit.services/lfk/backend/compare/1.3.4...1.3.5)
> 8 April 2025
- feat(runners): Generate selfservice urls on runner if requested or create/update/get single [`5415cd3`](https://git.odit.services/lfk/backend/commit/5415cd38a727e76632a01a4d2634a1777df5542c)
- chore(release): 1.3.5 [`bb213f0`](https://git.odit.services/lfk/backend/commit/bb213f001eff2157abf8741128f624f9cc991afe)
#### [1.3.4](https://git.odit.services/lfk/backend/compare/1.3.3...1.3.4) #### [1.3.4](https://git.odit.services/lfk/backend/compare/1.3.3...1.3.4)
> 28 March 2025
- feat: add runnersViaSelfservice to statsControllerGet [`5c5000a`](https://git.odit.services/lfk/backend/commit/5c5000a218b47815e6846ac8b857dcd1995bfa6f) - feat: add runnersViaSelfservice to statsControllerGet [`5c5000a`](https://git.odit.services/lfk/backend/commit/5c5000a218b47815e6846ac8b857dcd1995bfa6f)
- chore(release): 1.3.4 [`175ba52`](https://git.odit.services/lfk/backend/commit/175ba52ffae8e6ba1fdc1603ac2f5eba15602046)
#### [1.3.3](https://git.odit.services/lfk/backend/compare/v1.3.2...1.3.3) #### [1.3.3](https://git.odit.services/lfk/backend/compare/v1.3.2...1.3.3)

View File

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

@@ -30,7 +30,7 @@ export class RunnerController {
@Authorized("RUNNER:GET") @Authorized("RUNNER:GET")
@ResponseSchema(ResponseRunner, { isArray: true }) @ResponseSchema(ResponseRunner, { isArray: true })
@OpenAPI({ description: 'Lists all runners from all teams/orgs. <br> This includes the runner\'s group and distance ran.' }) @OpenAPI({ description: 'Lists all runners from all teams/orgs. <br> This includes the runner\'s group and distance ran.' })
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, @QueryParam("selfservice_links", { required: false }) selfservice_links: boolean = false) {
let responseRunners: ResponseRunner[] = new Array<ResponseRunner>(); let responseRunners: ResponseRunner[] = new Array<ResponseRunner>();
let runners: Array<Runner>; let runners: Array<Runner>;
@@ -41,7 +41,7 @@ export class RunnerController {
} }
runners.forEach(runner => { runners.forEach(runner => {
responseRunners.push(new ResponseRunner(runner)); responseRunners.push(new ResponseRunner(runner, selfservice_links));
}); });
return responseRunners; return responseRunners;
} }
@@ -55,7 +55,7 @@ export class RunnerController {
async getOne(@Param('id') id: number) { async getOne(@Param('id') id: number) {
let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] }) let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] })
if (!runner) { throw new RunnerNotFoundError(); } if (!runner) { throw new RunnerNotFoundError(); }
return new ResponseRunner(runner); return new ResponseRunner(runner, true);
} }
@Get('/:id/scans') @Get('/:id/scans')
@@ -98,7 +98,7 @@ export class RunnerController {
} }
runner = await this.runnerRepository.save(runner) runner = await this.runnerRepository.save(runner)
return new ResponseRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] })); return new ResponseRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] }), true);
} }
@Put('/:id') @Put('/:id')
@@ -119,7 +119,7 @@ export class RunnerController {
} }
await this.runnerRepository.save(await runner.update(oldRunner)); await this.runnerRepository.save(await runner.update(oldRunner));
return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] })); return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] }), true);
} }
@Delete('/:id') @Delete('/:id')

View File

@@ -24,6 +24,7 @@ export class StatsController {
async get() { async get() {
const connection = getConnection(); const connection = getConnection();
const runnersViaSelfservice = await connection.getRepository(Runner).count({ where: { created_via: "selfservice" } }); const runnersViaSelfservice = await connection.getRepository(Runner).count({ where: { created_via: "selfservice" } });
const runnersViaKiosk = await connection.getRepository(Runner).count({ where: { created_via: "kiosk" } });
const runners = await connection.getRepository(Runner).count(); const runners = await connection.getRepository(Runner).count();
const teams = await connection.getRepository(RunnerTeam).count(); const teams = await connection.getRepository(RunnerTeam).count();
const orgs = await connection.getRepository(RunnerOrganization).count(); const orgs = await connection.getRepository(RunnerOrganization).count();
@@ -42,7 +43,7 @@ export class StatsController {
let donations = await connection.getRepository(Donation).find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] }); let donations = await connection.getRepository(Donation).find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] });
const donors = await connection.getRepository(Donor).count(); const donors = await connection.getRepository(Donor).count();
return new ResponseStats(runnersViaSelfservice, runners, teams, orgs, users, scans, donations, distace, donors) return new ResponseStats(runnersViaSelfservice, runners, teams, orgs, users, scans, donations, distace, donors, runnersViaKiosk)
} }
@Get("/runners/distance") @Get("/runners/distance")

View File

@@ -50,4 +50,11 @@ export abstract class CreateParticipant {
@IsOptional() @IsOptional()
@IsObject() @IsObject()
address?: Address; address?: Address;
/**
* how the participant got into the system
*/
@IsOptional()
@IsString()
created_via?: string;
} }

View File

@@ -32,6 +32,9 @@ export class CreateRunner extends CreateParticipant {
newRunner.email = this.email; newRunner.email = this.email;
newRunner.group = await this.getGroup(); newRunner.group = await this.getGroup();
newRunner.address = this.address; newRunner.address = this.address;
if (this.created_via) {
newRunner.created_via = this.created_via;
}
Address.validate(newRunner.address); Address.validate(newRunner.address);
return newRunner; return newRunner;

View File

@@ -80,7 +80,7 @@ export abstract class Participant {
*/ */
@Column({ nullable: true, default: "backend" }) @Column({ nullable: true, default: "backend" })
@IsOptional() @IsOptional()
@IsEmail() @IsString()
created_via?: string; created_via?: string;
/** /**

View File

@@ -1,7 +1,10 @@
import { import {
IsInt, IsInt,
IsObject IsObject,
IsOptional,
IsString
} from "class-validator"; } from "class-validator";
import { JwtCreator } from '../../jwtcreator';
import { Runner } from '../entities/Runner'; import { Runner } from '../entities/Runner';
import { ResponseObjectType } from '../enums/ResponseObjectType'; import { ResponseObjectType } from '../enums/ResponseObjectType';
import { IResponse } from './IResponse'; import { IResponse } from './IResponse';
@@ -30,14 +33,26 @@ export class ResponseRunner extends ResponseParticipant implements IResponse {
@IsObject() @IsObject()
group: ResponseRunnerGroup; group: ResponseRunnerGroup;
/**
* A selfservice link for our new runner.
*/
@IsOptional()
@IsString()
selfserviceLink: string;
/** /**
* 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.
*/ */
public constructor(runner: Runner) { public constructor(runner: Runner, generateSelfServiceLink: boolean = false) {
super(runner); super(runner);
if (!runner.scans) { this.distance = 0 } if (!runner.scans) { this.distance = 0 }
else { this.distance = runner.validScans.reduce((sum, current) => sum + current.distance, 0); } else { this.distance = runner.validScans.reduce((sum, current) => sum + current.distance, 0); }
if (runner.group) { this.group = runner.group.toResponse(); } if (runner.group) { this.group = runner.group.toResponse(); }
if (generateSelfServiceLink) {
const token = JwtCreator.createSelfService(runner);
this.selfserviceLink = `${process.env.SELFSERVICE_URL}/profile/${token}`;
}
} }
} }

View File

@@ -22,6 +22,12 @@ export class ResponseStats implements IResponse {
@IsInt() @IsInt()
runnersViaSelfservice: number; runnersViaSelfservice: number;
/**
* The amount of runners registered via kiosk.
*/
@IsInt()
runnersViaKiosk: number;
/** /**
* The amount of runners registered in the system. * The amount of runners registered in the system.
*/ */
@@ -98,7 +104,7 @@ export class ResponseStats implements IResponse {
* @param scans number of scans - no relations have to be resolved. * @param scans number of scans - no relations have to be resolved.
* @param donations Array containing all donations - the following relations have to be resolved: runner, runner.scans, runner.scans.track * @param donations Array containing all donations - the following relations have to be resolved: runner, runner.scans, runner.scans.track
*/ */
public constructor(runnersViaSelfservice: number, runners: number, teams: number, orgs: number, users: number, scans: number, donations: Donation[], distance: number, donors: number) { public constructor(runnersViaSelfservice: number, runners: number, teams: number, orgs: number, users: number, scans: number, donations: Donation[], distance: number, donors: number, runnersViaKiosk: number) {
this.runnersViaSelfservice = runnersViaSelfservice; this.runnersViaSelfservice = runnersViaSelfservice;
this.total_runners = runners; this.total_runners = runners;
this.total_teams = teams; this.total_teams = teams;
@@ -111,5 +117,6 @@ export class ResponseStats implements IResponse {
this.average_donation = this.total_donation / this.total_donations this.average_donation = this.total_donation / this.total_donations
this.total_donors = donors; this.total_donors = donors;
this.average_distance = this.total_distance / this.total_runners; this.average_distance = this.total_distance / this.total_runners;
this.runnersViaKiosk = runnersViaKiosk;
} }
} }