Merge branch 'dev' into feature/104-contacts
This commit is contained in:
@@ -1,90 +1,93 @@
|
||||
import {
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsPostalCode,
|
||||
IsString
|
||||
} from "class-validator";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { config } from '../../config';
|
||||
import { IAddressUser } from './IAddressUser';
|
||||
|
||||
/**
|
||||
* Defines the Address entity.
|
||||
* Implemented this way to prevent any formatting differences.
|
||||
*/
|
||||
@Entity()
|
||||
export class Address {
|
||||
/**
|
||||
* Autogenerated unique id (primary key).
|
||||
*/
|
||||
@PrimaryGeneratedColumn()
|
||||
@IsInt()
|
||||
id: number;
|
||||
|
||||
/**
|
||||
* The address's description.
|
||||
* Optional and mostly for UX.
|
||||
*/
|
||||
@Column({ nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
description?: string;
|
||||
|
||||
/**
|
||||
* The address's first line.
|
||||
* Containing the street and house number.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
address1: string;
|
||||
|
||||
/**
|
||||
* The address's second line.
|
||||
* Containing optional information.
|
||||
*/
|
||||
@Column({ nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
address2?: string;
|
||||
|
||||
/**
|
||||
* The address's postal code.
|
||||
* This will get checked against the postal code syntax for the configured country.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@IsPostalCode(config.postalcode_validation_countrycode)
|
||||
postalcode: string;
|
||||
|
||||
/**
|
||||
* The address's city.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
city: string;
|
||||
|
||||
/**
|
||||
* The address's country.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
country: string;
|
||||
|
||||
/**
|
||||
* Used to link the address to participants.
|
||||
*/
|
||||
@OneToMany(() => IAddressUser, addressUser => addressUser.address, { nullable: true })
|
||||
addressUsers: IAddressUser[];
|
||||
|
||||
/**
|
||||
* Turns this entity into it's response class.
|
||||
*/
|
||||
public toResponse() {
|
||||
return new Error("NotImplemented");
|
||||
}
|
||||
}
|
||||
import {
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsPostalCode,
|
||||
IsString
|
||||
} from "class-validator";
|
||||
import { Column } from "typeorm";
|
||||
import ValidatorJS from 'validator';
|
||||
import { config } from '../../config';
|
||||
import { AddressCityEmptyError, AddressCountryEmptyError, AddressFirstLineEmptyError, AddressPostalCodeEmptyError, AddressPostalCodeInvalidError } from '../../errors/AddressErrors';
|
||||
|
||||
/**
|
||||
* Defines the Address class.
|
||||
* Implemented this way to prevent any formatting differences.
|
||||
*/
|
||||
export class Address {
|
||||
/**
|
||||
* The address's first line.
|
||||
* Containing the street and house number.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
address1: string;
|
||||
|
||||
/**
|
||||
* The address's second line.
|
||||
* Containing optional information.
|
||||
*/
|
||||
@Column({ nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
address2?: string;
|
||||
|
||||
/**
|
||||
* The address's postal code.
|
||||
* This will get checked against the postal code syntax for the configured country.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@IsPostalCode(config.postalcode_validation_countrycode)
|
||||
postalcode: string;
|
||||
|
||||
/**
|
||||
* The address's city.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
city: string;
|
||||
|
||||
/**
|
||||
* The address's country.
|
||||
*/
|
||||
@Column()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
country: string;
|
||||
|
||||
public reset() {
|
||||
this.address1 = null;
|
||||
this.address2 = null;
|
||||
this.city = null;
|
||||
this.country = null;
|
||||
this.postalcode = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a valid address
|
||||
*/
|
||||
public static isValidAddress(address: Address): Boolean {
|
||||
if (address == null) { return false; }
|
||||
if (address.address1 == null || address.city == null || address.country == null || address.postalcode == null) { return false; }
|
||||
if (ValidatorJS.isPostalCode(address.postalcode, config.postalcode_validation_countrycode) == false) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function validates addresses.
|
||||
* This is a workaround for non-existant class validation for embedded entities.
|
||||
* @param address The address that shall get validated.
|
||||
*/
|
||||
public static validate(address: Address) {
|
||||
if (address == null) { return; }
|
||||
if (address.address1 == null && address.city == null && address.country == null && address.postalcode == null) { return; }
|
||||
if (address.address1 == null) { throw new AddressFirstLineEmptyError(); }
|
||||
if (address.postalcode == null) { throw new AddressPostalCodeEmptyError(); }
|
||||
if (address.city == null) { throw new AddressCityEmptyError(); }
|
||||
if (address.country == null) { throw new AddressCountryEmptyError(); }
|
||||
if (ValidatorJS.isPostalCode(address.postalcode.toString(), config.postalcode_validation_countrycode) == false) { throw new AddressPostalCodeInvalidError(); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,10 @@ import {
|
||||
|
||||
IsString
|
||||
} from "class-validator";
|
||||
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { config } from '../../config';
|
||||
import { ResponseGroupContact } from '../responses/ResponseGroupContact';
|
||||
import { Address } from "./Address";
|
||||
import { IAddressUser } from './IAddressUser';
|
||||
import { RunnerGroup } from "./RunnerGroup";
|
||||
|
||||
/**
|
||||
@@ -19,7 +18,7 @@ import { RunnerGroup } from "./RunnerGroup";
|
||||
* Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups.
|
||||
*/
|
||||
@Entity()
|
||||
export class GroupContact implements IAddressUser {
|
||||
export class GroupContact {
|
||||
/**
|
||||
* Autogenerated unique id (primary key).
|
||||
*/
|
||||
@@ -56,7 +55,7 @@ export class GroupContact implements IAddressUser {
|
||||
* This is a address object to prevent any formatting differences.
|
||||
*/
|
||||
@IsOptional()
|
||||
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true })
|
||||
@Column(type => Address)
|
||||
address?: Address;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Entity, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||
import { Address } from './Address';
|
||||
|
||||
/**
|
||||
* The interface(tm) all entities using addresses have to implement.
|
||||
* This is a abstract class, because apparently typeorm can't really work with interfaces :/
|
||||
*/
|
||||
@Entity()
|
||||
export abstract class IAddressUser {
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true })
|
||||
address?: Address
|
||||
|
||||
/**
|
||||
* Turns this entity into it's response class.
|
||||
*/
|
||||
public abstract toResponse();
|
||||
}
|
||||
@@ -7,11 +7,10 @@ import {
|
||||
|
||||
IsString
|
||||
} from "class-validator";
|
||||
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm";
|
||||
import { Column, Entity, PrimaryGeneratedColumn, TableInheritance } from "typeorm";
|
||||
import { config } from '../../config';
|
||||
import { ResponseParticipant } from '../responses/ResponseParticipant';
|
||||
import { Address } from "./Address";
|
||||
import { IAddressUser } from './IAddressUser';
|
||||
|
||||
/**
|
||||
* Defines the Participant entity.
|
||||
@@ -19,7 +18,7 @@ import { IAddressUser } from './IAddressUser';
|
||||
*/
|
||||
@Entity()
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export abstract class Participant implements IAddressUser {
|
||||
export abstract class Participant {
|
||||
/**
|
||||
* Autogenerated unique id (primary key).
|
||||
*/
|
||||
@@ -55,7 +54,7 @@ export abstract class Participant implements IAddressUser {
|
||||
* The participant's address.
|
||||
* This is a address object to prevent any formatting differences.
|
||||
*/
|
||||
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true })
|
||||
@Column(type => Address)
|
||||
address?: Address;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,65 +1,64 @@
|
||||
import { IsInt, IsOptional } from "class-validator";
|
||||
import { ChildEntity, ManyToOne, OneToMany } from "typeorm";
|
||||
import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation';
|
||||
import { Address } from './Address';
|
||||
import { IAddressUser } from './IAddressUser';
|
||||
import { Runner } from './Runner';
|
||||
import { RunnerGroup } from "./RunnerGroup";
|
||||
import { RunnerTeam } from "./RunnerTeam";
|
||||
|
||||
/**
|
||||
* Defines the RunnerOrganisation entity.
|
||||
* This usually is a school, club or company.
|
||||
*/
|
||||
@ChildEntity()
|
||||
export class RunnerOrganisation extends RunnerGroup implements IAddressUser {
|
||||
|
||||
/**
|
||||
* The organisations's address.
|
||||
*/
|
||||
@IsOptional()
|
||||
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true })
|
||||
address?: Address;
|
||||
|
||||
/**
|
||||
* The organisation's teams.
|
||||
* Used to link teams to a organisation.
|
||||
*/
|
||||
@OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true })
|
||||
teams: RunnerTeam[];
|
||||
|
||||
/**
|
||||
* Returns all runners associated with this organisation (directly or indirectly via teams).
|
||||
*/
|
||||
public get allRunners(): Runner[] {
|
||||
let returnRunners: Runner[] = new Array<Runner>();
|
||||
returnRunners.push(...this.runners);
|
||||
for (let team of this.teams) {
|
||||
returnRunners.push(...team.runners)
|
||||
}
|
||||
return returnRunners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total distance ran by this group's runners based on all their valid scans.
|
||||
*/
|
||||
@IsInt()
|
||||
public get distance(): number {
|
||||
return this.allRunners.reduce((sum, current) => sum + current.distance, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total donations a runner has collected based on his linked donations and distance ran.
|
||||
*/
|
||||
@IsInt()
|
||||
public get distanceDonationAmount(): number {
|
||||
return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this entity into it's response class.
|
||||
*/
|
||||
public toResponse(): ResponseRunnerOrganisation {
|
||||
return new ResponseRunnerOrganisation(this);
|
||||
}
|
||||
import { IsInt, IsOptional } from "class-validator";
|
||||
import { ChildEntity, Column, OneToMany } from "typeorm";
|
||||
import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation';
|
||||
import { Address } from './Address';
|
||||
import { Runner } from './Runner';
|
||||
import { RunnerGroup } from "./RunnerGroup";
|
||||
import { RunnerTeam } from "./RunnerTeam";
|
||||
|
||||
/**
|
||||
* Defines the RunnerOrganisation entity.
|
||||
* This usually is a school, club or company.
|
||||
*/
|
||||
@ChildEntity()
|
||||
export class RunnerOrganisation extends RunnerGroup {
|
||||
|
||||
/**
|
||||
* The organisations's address.
|
||||
*/
|
||||
@IsOptional()
|
||||
@Column(type => Address)
|
||||
address?: Address;
|
||||
|
||||
/**
|
||||
* The organisation's teams.
|
||||
* Used to link teams to a organisation.
|
||||
*/
|
||||
@OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true })
|
||||
teams: RunnerTeam[];
|
||||
|
||||
/**
|
||||
* Returns all runners associated with this organisation (directly or indirectly via teams).
|
||||
*/
|
||||
public get allRunners(): Runner[] {
|
||||
let returnRunners: Runner[] = new Array<Runner>();
|
||||
returnRunners.push(...this.runners);
|
||||
for (let team of this.teams) {
|
||||
returnRunners.push(...team.runners)
|
||||
}
|
||||
return returnRunners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total distance ran by this group's runners based on all their valid scans.
|
||||
*/
|
||||
@IsInt()
|
||||
public get distance(): number {
|
||||
return this.allRunners.reduce((sum, current) => sum + current.distance, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total donations a runner has collected based on his linked donations and distance ran.
|
||||
*/
|
||||
@IsInt()
|
||||
public get distanceDonationAmount(): number {
|
||||
return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this entity into it's response class.
|
||||
*/
|
||||
public toResponse(): ResponseRunnerOrganisation {
|
||||
return new ResponseRunnerOrganisation(this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user