SettingsHelper

This commit is contained in:
Julian Krauser 2025-04-19 11:26:35 +02:00
parent f850fc2526
commit f32143b7ac
15 changed files with 199 additions and 49 deletions

View file

@ -1,7 +1,7 @@
import "dotenv/config"; import "dotenv/config";
import "reflect-metadata"; import "reflect-metadata";
import { DataSource } from "typeorm"; import { DataSource } from "typeorm";
import { DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME, DB_TYPE, DB_PORT } from "./env.defaults"; import { SettingHelper } from "./helpers/settingsHelper";
import { user } from "./entity/management/user"; import { user } from "./entity/management/user";
import { refresh } from "./entity/refresh"; import { refresh } from "./entity/refresh";
@ -53,12 +53,12 @@ import { NewsletterColumnType1744351418751 } from "./migrations/1744351418751-ne
import { QueryUpdatedAt1744795756230 } from "./migrations/1744795756230-QueryUpdatedAt"; import { QueryUpdatedAt1744795756230 } from "./migrations/1744795756230-QueryUpdatedAt";
const dataSource = new DataSource({ const dataSource = new DataSource({
type: DB_TYPE as any, type: SettingHelper.getEnvSetting("database.type") as any,
host: DB_HOST, host: SettingHelper.getEnvSetting("database.host"),
port: DB_PORT, port: Number(SettingHelper.getEnvSetting("database.port")),
username: DB_USERNAME, username: SettingHelper.getEnvSetting("database.username"),
password: DB_PASSWORD, password: SettingHelper.getEnvSetting("database.password"),
database: DB_NAME, database: SettingHelper.getEnvSetting("database.name"),
synchronize: false, synchronize: false,
logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"], logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"],
bigNumberStrings: false, bigNumberStrings: false,

View file

@ -0,0 +1,13 @@
import { Column, Entity, PrimaryColumn } from "typeorm";
@Entity()
export class user {
@PrimaryColumn({ type: "varchar", length: 255 })
topic: string;
@PrimaryColumn({ type: "varchar", length: 255 })
key: string;
@Column({ type: "varchar", length: 255 })
value: string;
}

View file

@ -2,15 +2,6 @@ import "dotenv/config";
import ms from "ms"; import ms from "ms";
import ip from "ip"; import ip from "ip";
export const DB_TYPE = process.env.DB_TYPE ?? "mysql";
export const DB_HOST = process.env.DB_HOST ?? "";
export const DB_PORT = Number(process.env.DB_PORT ?? 3306);
export const DB_NAME = process.env.DB_NAME ?? "";
export const DB_USERNAME = process.env.DB_USERNAME ?? "";
export const DB_PASSWORD = process.env.DB_PASSWORD ?? "";
export const SERVER_PORT = Number(process.env.SERVER_PORT ?? 5000);
export const JWT_SECRET = process.env.JWT_SECRET ?? "my_jwt_secret_string_ilughfnadiuhgq§$IUZGFVRweiouarbt1oub3h5q4a"; export const JWT_SECRET = process.env.JWT_SECRET ?? "my_jwt_secret_string_ilughfnadiuhgq§$IUZGFVRweiouarbt1oub3h5q4a";
export const JWT_EXPIRATION = (process.env.JWT_EXPIRATION ?? "15m") as ms.StringValue; export const JWT_EXPIRATION = (process.env.JWT_EXPIRATION ?? "15m") as ms.StringValue;
export const REFRESH_EXPIRATION = (process.env.REFRESH_EXPIRATION ?? "1d") as ms.StringValue; export const REFRESH_EXPIRATION = (process.env.REFRESH_EXPIRATION ?? "1d") as ms.StringValue;
@ -27,7 +18,6 @@ export const CLUB_WEBSITE = process.env.CLUB_WEBSITE ?? "";
export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "1"); export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "1");
export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "7"); export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "7");
export const BACKUP_AUTO_RESTORE = process.env.BACKUP_AUTO_RESTORE ?? "true";
export const USE_SECURITY_STRICT_LIMIT = process.env.USE_SECURITY_STRICT_LIMIT ?? "true"; export const USE_SECURITY_STRICT_LIMIT = process.env.USE_SECURITY_STRICT_LIMIT ?? "true";
export const SECURITY_STRICT_LIMIT_WINDOW = (process.env.SECURITY_STRICT_LIMIT_WINDOW ?? "15m") as ms.StringValue; export const SECURITY_STRICT_LIMIT_WINDOW = (process.env.SECURITY_STRICT_LIMIT_WINDOW ?? "15m") as ms.StringValue;
@ -55,18 +45,6 @@ export const TRUST_PROXY = ((): Array<string> | string | boolean | number | null
})(); })();
export function configCheck() { export function configCheck() {
if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres")
throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)");
if ((DB_HOST == "" || typeof DB_HOST != "string") && DB_TYPE != "sqlite")
throw new Error("set valid value to DB_HOST");
if (DB_NAME == "" || typeof DB_NAME != "string") throw new Error("set valid value to DB_NAME");
if ((DB_USERNAME == "" || typeof DB_USERNAME != "string") && DB_TYPE != "sqlite")
throw new Error("set valid value to DB_USERNAME");
if ((DB_PASSWORD == "" || typeof DB_PASSWORD != "string") && DB_TYPE != "sqlite")
throw new Error("set valid value to DB_PASSWORD");
if (isNaN(SERVER_PORT)) throw new Error("set valid numeric value to SERVER_PORT");
if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET"); if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET");
checkMS(JWT_EXPIRATION, "JWT_EXPIRATION"); checkMS(JWT_EXPIRATION, "JWT_EXPIRATION");
checkMS(REFRESH_EXPIRATION, "REFRESH_EXPIRATION"); checkMS(REFRESH_EXPIRATION, "REFRESH_EXPIRATION");
@ -84,8 +62,6 @@ export function configCheck() {
) )
throw new Error("CLUB_WEBSITE is not valid url"); throw new Error("CLUB_WEBSITE is not valid url");
if (BACKUP_AUTO_RESTORE != "true" && BACKUP_AUTO_RESTORE != "false")
throw new Error("set 'true' or 'false' to BACKUP_AUTO_RESTORE");
if (BACKUP_INTERVAL < 1) throw new Error("BACKUP_INTERVAL has to be at least 1"); if (BACKUP_INTERVAL < 1) throw new Error("BACKUP_INTERVAL has to be at least 1");
if (BACKUP_COPIES < 1) throw new Error("BACKUP_COPIES has to be at least 1"); if (BACKUP_COPIES < 1) throw new Error("BACKUP_COPIES has to be at least 1");

View file

@ -1,8 +1,8 @@
import { DB_TYPE } from "../../../../env.defaults"; import { SettingHelper } from "../../../../helpers/settingsHelper";
export default abstract class DateMappingHelper { export default abstract class DateMappingHelper {
static mapDate(entry: any) { static mapDate(entry: any) {
switch (DB_TYPE) { switch (SettingHelper.getEnvSetting("database.type")) {
case "postgres": case "postgres":
return `${entry?.years ?? 0} years ${entry?.months ?? 0} months ${entry?.days ?? 0} days`; return `${entry?.years ?? 0} years ${entry?.months ?? 0} months ${entry?.days ?? 0} days`;
case "mysql": case "mysql":

View file

@ -0,0 +1,57 @@
import ms from "ms";
import { EnvSettingString, envSettingsType, SettingString, settingsType } from "../type/settingTypes";
export abstract class SettingHelper {
private static settings: { [key in SettingString]?: string } = {};
private static envSettings: { [key in EnvSettingString]?: string } = {};
public static getSetting(key: SettingString): string | number | boolean | ms.StringValue {
let settingType = settingsType[key];
return this.settings[key] ?? settingType.default ?? "";
}
public static getEnvSetting(key: EnvSettingString): string {
let settingType = envSettingsType[key];
return this.envSettings[key] ?? settingType.default ?? "";
}
public static async configure() {}
public static async configurEnv() {
this.envSettings = {
"database.type": process.env.DB_TYPE,
"database.host": process.env.DB_HOST,
"database.port": process.env.DB_PORT,
"database.name": process.env.DB_NAME,
"database.username": process.env.DB_USERNAME,
"database.password": process.env.DB_PASSWORD,
};
this.checkEnvSettings();
}
private static checkEnvSettings() {
if (!["mysql", "sqlite", "postgres"].includes(this.envSettings["database.type"]))
throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)");
if (this.checkIfEmptyOrNotString(this.envSettings["database.name"]))
throw new Error("set valid value to DB_NAME (name of database or filepath for sqlite)");
if (
this.checkIfEmptyOrNotString(this.envSettings["database.host"]) &&
this.envSettings["database.type"] != "sqlite"
)
throw new Error("set valid value to DB_HOST");
if (
this.checkIfEmptyOrNotString(this.envSettings["database.username"]) &&
this.envSettings["database.type"] != "sqlite"
)
throw new Error("set valid value to DB_USERNAME");
if (
this.checkIfEmptyOrNotString(this.envSettings["database.password"]) &&
this.envSettings["database.type"] != "sqlite"
)
throw new Error("set valid value to DB_PASSWORD");
}
private static checkIfEmptyOrNotString(val: any) {
return typeof val != "string" || val == "";
}
}

View file

@ -1,8 +1,10 @@
import "dotenv/config"; import "dotenv/config";
import "./handlebars.config"; import "./handlebars.config";
import express from "express"; import express from "express";
import { SettingHelper } from "./helpers/settingsHelper";
import { BACKUP_AUTO_RESTORE, configCheck, SERVER_PORT } from "./env.defaults"; SettingHelper.configurEnv();
import { configCheck } from "./env.defaults";
configCheck(); configCheck();
import { PermissionObject } from "./type/permissionTypes"; import { PermissionObject } from "./type/permissionTypes";
@ -22,18 +24,21 @@ declare global {
import { dataSource } from "./data-source"; import { dataSource } from "./data-source";
import BackupHelper from "./helpers/backupHelper"; import BackupHelper from "./helpers/backupHelper";
dataSource.initialize().then(async () => { dataSource.initialize().then(async () => {
if ((BACKUP_AUTO_RESTORE as "true" | "false") == "true" && (await dataSource.createQueryRunner().hasTable("user"))) { if (await dataSource.createQueryRunner().hasTable("user")) {
await BackupHelper.autoRestoreBackup().catch((err) => { await BackupHelper.autoRestoreBackup().catch((err) => {
console.log(`${new Date().toISOString()}: failed auto-restoring database`, err); console.log(`${new Date().toISOString()}: failed auto-restoring database`, err);
}); });
} }
SettingHelper.configure();
}); });
const app = express(); const app = express();
import router from "./routes/index"; import router from "./routes/index";
router(app); router(app);
app.listen(process.env.NODE_ENV ? SERVER_PORT : 5000, () => { app.listen(process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000, () => {
console.log(`${new Date().toISOString()}: listening on port ${process.env.NODE_ENV ? SERVER_PORT : 5000}`); console.log(
`${new Date().toISOString()}: listening on port ${process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000}`
);
}); });
import schedule from "node-schedule"; import schedule from "node-schedule";

View file

@ -2,13 +2,16 @@ import { MigrationInterface, QueryRunner, Table } from "typeorm";
import BackupHelper from "../helpers/backupHelper"; import BackupHelper from "../helpers/backupHelper";
import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "./ormHelper"; import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "./ormHelper";
import InternalException from "../exceptions/internalException"; import InternalException from "../exceptions/internalException";
import { DB_TYPE } from "../env.defaults"; import { SettingHelper } from "../helpers/settingsHelper";
export class BackupAndResetDatabase1738166124200 implements MigrationInterface { export class BackupAndResetDatabase1738166124200 implements MigrationInterface {
name = "BackupAndResetDatabase1738166124200"; name = "BackupAndResetDatabase1738166124200";
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {
let query = DB_TYPE == "postgres" ? "SELECT name FROM migrations" : "SELECT `name` FROM `migrations`"; let query =
SettingHelper.getEnvSetting("database.type") == "postgres"
? "SELECT name FROM migrations"
: "SELECT `name` FROM `migrations`";
let migrations = await queryRunner.query(query); let migrations = await queryRunner.query(query);
if ( if (
(await queryRunner.hasTable("user")) && (await queryRunner.hasTable("user")) &&

View file

@ -54,7 +54,7 @@ import {
newsletter_recipients_table, newsletter_recipients_table,
newsletter_table, newsletter_table,
} from "./baseSchemaTables/newsletter"; } from "./baseSchemaTables/newsletter";
import { DB_TYPE } from "../env.defaults"; import { SettingHelper } from "../helpers/settingsHelper";
export class CreateSchema1738166167472 implements MigrationInterface { export class CreateSchema1738166167472 implements MigrationInterface {
name = "CreateSchema1738166167472"; name = "CreateSchema1738166167472";
@ -84,6 +84,7 @@ export class CreateSchema1738166167472 implements MigrationInterface {
await queryRunner.createTable(member_executive_positions_table, true, true, true); await queryRunner.createTable(member_executive_positions_table, true, true, true);
await queryRunner.createTable(member_qualifications_table, true, true, true); await queryRunner.createTable(member_qualifications_table, true, true, true);
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
if (DB_TYPE == "postgres") await queryRunner.createView(member_view_postgres, true); if (DB_TYPE == "postgres") await queryRunner.createView(member_view_postgres, true);
else if (DB_TYPE == "mysql") await queryRunner.createView(member_view_mysql, true); else if (DB_TYPE == "mysql") await queryRunner.createView(member_view_mysql, true);
else if (DB_TYPE == "sqlite") await queryRunner.createView(member_view_sqlite, true); else if (DB_TYPE == "sqlite") await queryRunner.createView(member_view_sqlite, true);

View file

@ -1,3 +1,5 @@
import { SettingHelper } from "../helpers/settingsHelper";
export type ORMType = "int" | "bigint" | "boolean" | "date" | "datetime" | "time" | "text" | "varchar" | "uuid"; export type ORMType = "int" | "bigint" | "boolean" | "date" | "datetime" | "time" | "text" | "varchar" | "uuid";
export type ORMDefault = "currentTimestamp" | "string" | "boolean" | "number" | "null"; export type ORMDefault = "currentTimestamp" | "string" | "boolean" | "number" | "null";
export type ColumnConfig = { export type ColumnConfig = {
@ -13,7 +15,7 @@ export type Primary = {
}; };
export function getTypeByORM(type: ORMType, nullable: boolean = false, length: number = 255): ColumnConfig { export function getTypeByORM(type: ORMType, nullable: boolean = false, length: number = 255): ColumnConfig {
const dbType = process.env.DB_TYPE; const dbType = SettingHelper.getEnvSetting("database.type");
const typeMap: Record<string, Record<ORMType, string>> = { const typeMap: Record<string, Record<ORMType, string>> = {
mysql: { mysql: {
@ -63,7 +65,7 @@ export function getTypeByORM(type: ORMType, nullable: boolean = false, length: n
} }
export function getDefaultByORM<T = string | null>(type: ORMDefault, data?: string | number | boolean): T { export function getDefaultByORM<T = string | null>(type: ORMDefault, data?: string | number | boolean): T {
const dbType = process.env.DB_TYPE; const dbType = SettingHelper.getEnvSetting("database.type");
const typeMap: Record<string, Record<ORMDefault, string | null>> = { const typeMap: Record<string, Record<ORMDefault, string | null>> = {
mysql: { mysql: {

View file

@ -5,7 +5,7 @@ import { membership } from "../../../entity/club/member/membership";
import DatabaseActionException from "../../../exceptions/databaseActionException"; import DatabaseActionException from "../../../exceptions/databaseActionException";
import InternalException from "../../../exceptions/internalException"; import InternalException from "../../../exceptions/internalException";
import { memberView } from "../../../views/memberView"; import { memberView } from "../../../views/memberView";
import { DB_TYPE } from "../../../env.defaults"; import { SettingHelper } from "../../../helpers/settingsHelper";
export default abstract class MemberService { export default abstract class MemberService {
/** /**
@ -169,7 +169,7 @@ export default abstract class MemberService {
"member.firstMembershipEntry", "member.firstMembershipEntry",
"member.memberships", "member.memberships",
"membership_first", "membership_first",
DB_TYPE == "postgres" SettingHelper.getEnvSetting("database.type") == "postgres"
? 'membership_first.memberId = member.id AND membership_first.start = (SELECT MIN("m_first"."start") FROM "membership" "m_first" WHERE "m_first"."memberId" = "member"."id")' ? 'membership_first.memberId = member.id AND membership_first.start = (SELECT MIN("m_first"."start") FROM "membership" "m_first" WHERE "m_first"."memberId" = "member"."id")'
: "membership_first.memberId = member.id AND membership_first.start = (SELECT MIN(m_first.start) FROM membership m_first WHERE m_first.memberId = member.id)" : "membership_first.memberId = member.id AND membership_first.start = (SELECT MIN(m_first.start) FROM membership m_first WHERE m_first.memberId = member.id)"
) )
@ -177,7 +177,7 @@ export default abstract class MemberService {
"member.lastMembershipEntry", "member.lastMembershipEntry",
"member.memberships", "member.memberships",
"membership_last", "membership_last",
DB_TYPE == "postgres" SettingHelper.getEnvSetting("database.type") == "postgres"
? 'membership_last.memberId = member.id AND membership_last.start = (SELECT MAX("m_last"."start") FROM "membership" "m_last" WHERE "m_last"."memberId" = "member"."id")' ? 'membership_last.memberId = member.id AND membership_last.start = (SELECT MAX("m_last"."start") FROM "membership" "m_last" WHERE "m_last"."memberId" = "member"."id")'
: "membership_last.memberId = member.id AND membership_last.start = (SELECT MAX(m_last.start) FROM membership m_last WHERE m_last.memberId = member.id)" : "membership_last.memberId = member.id AND membership_last.start = (SELECT MAX(m_last.start) FROM membership m_last WHERE m_last.memberId = member.id)"
) )

89
src/type/settingTypes.ts Normal file
View file

@ -0,0 +1,89 @@
import ms from "ms";
import { StringHelper } from "../helpers/stringHelper";
export type SettingTopic = "club" | "app" | "session" | "mail" | "backup" | "security";
export type SettingString =
| "club.name"
| "club.imprint"
| "club.privacy"
| "club.website"
| "app.custom_login_message"
| "app.show_link_to_calendar"
| "session.jwt_secret"
| "session.jwt_expiration"
| "session.refresh_expiration"
| "session.pwa_refresh_expiration"
| "mail.username"
| "mail.password"
| "mail.host"
| "mail.port"
| "mail.secure"
| "backup.interval"
| "backup.copies"
| "security.strict_limit"
| "security.strict_limit_window"
| "security.strict_limit_request_count"
| "security.limit"
| "security.limit_window"
| "security.limit_request_count"
| "security.trust_proxy";
export type SettingTypeAtom = "longstring" | "string" | "ms" | "number" | "boolean" | "url";
export type SettingType = SettingTypeAtom | `${SettingTypeAtom}/crypt` | `${SettingTypeAtom}/rand`;
export const settingsType: {
[key in SettingString]: {
type: SettingType | SettingType[];
default?: string | number | boolean | ms.StringValue;
optional?: boolean;
};
} = {
"club.name": { type: "string", default: "FF Admin" },
"club.imprint": { type: "url", optional: true },
"club.privacy": { type: "url", optional: true },
"club.website": { type: "url", optional: true },
"app.custom_login_message": { type: "string", optional: true },
"app.show_link_to_calendar": { type: "boolean", default: true },
"session.jwt_secret": { type: "longstring/rand", default: StringHelper.random(64) },
"session.jwt_expiration": { type: "ms", default: "15m" },
"session.refresh_expiration": { type: "ms", default: "1d" },
"session.pwa_refresh_expiration": { type: "ms", default: "5d" },
"mail.username": { type: "string", optional: false },
"mail.password": { type: "string/crypt", optional: false },
"mail.host": { type: "url", optional: false },
"mail.port": { type: "number", default: 587 },
"mail.secure": { type: "boolean", default: false },
"backup.interval": { type: "number", default: 1 },
"backup.copies": { type: "number", default: 7 },
"security.strict_limit": { type: "boolean", default: true },
"security.strict_limit_window": { type: "ms", default: "15m" },
"security.strict_limit_request_count": { type: "number", default: 15 },
"security.limit": { type: "boolean", default: true },
"security.limit_window": { type: "ms", default: "1m" },
"security.limit_request_count": { type: "number", default: 500 },
"security.trust_proxy": { type: ["boolean", "number"], optional: true },
};
/** ENV Settings */
export type EnvSettingString =
| "database.type"
| "database.host"
| "database.port"
| "database.name"
| "database.username"
| "database.password";
export const envSettingsType: {
[key in EnvSettingString]: {
type: SettingType | SettingType[];
default?: string;
};
} = {
"database.type": { type: "string", default: "postgres" },
"database.host": { type: "string" },
"database.port": { type: "string", default: "5432" },
"database.name": { type: "string" },
"database.username": { type: "string" },
"database.password": { type: "string" },
};

View file

@ -1,10 +1,11 @@
import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { DataSource, ViewColumn, ViewEntity } from "typeorm";
import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions"; import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions";
import { DB_TYPE } from "../env.defaults"; import { SettingHelper } from "../helpers/settingsHelper";
let durationInDays: string; let durationInDays: string;
let durationInYears: string; let durationInYears: string;
let exactDuration: string; let exactDuration: string;
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
if (DB_TYPE == "postgres") { if (DB_TYPE == "postgres") {
durationInDays = `SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start")`; durationInDays = `SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start")`;
durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")))`; durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")))`;

View file

@ -1,10 +1,11 @@
import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { DataSource, ViewColumn, ViewEntity } from "typeorm";
import { memberQualifications } from "../entity/club/member/memberQualifications"; import { memberQualifications } from "../entity/club/member/memberQualifications";
import { DB_TYPE } from "../env.defaults"; import { SettingHelper } from "../helpers/settingsHelper";
let durationInDays: string; let durationInDays: string;
let durationInYears: string; let durationInYears: string;
let exactDuration: string; let exactDuration: string;
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
if (DB_TYPE == "postgres") { if (DB_TYPE == "postgres") {
durationInDays = `SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") `; durationInDays = `SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") `;
durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")))`; durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")))`;

View file

@ -1,10 +1,11 @@
import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { DataSource, ViewColumn, ViewEntity } from "typeorm";
import { member } from "../entity/club/member/member"; import { member } from "../entity/club/member/member";
import { DB_TYPE } from "../env.defaults"; import { SettingHelper } from "../helpers/settingsHelper";
let todayAge: string; let todayAge: string;
let ageThisYear: string; let ageThisYear: string;
let exactAge: string; let exactAge: string;
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
if (DB_TYPE == "postgres") { if (DB_TYPE == "postgres") {
todayAge = `DATE_PART('year', AGE(CURRENT_DATE, member.birthdate))`; todayAge = `DATE_PART('year', AGE(CURRENT_DATE, member.birthdate))`;
ageThisYear = `EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate)`; ageThisYear = `EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate)`;

View file

@ -1,10 +1,11 @@
import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { DataSource, ViewColumn, ViewEntity } from "typeorm";
import { membership } from "../entity/club/member/membership"; import { membership } from "../entity/club/member/membership";
import { DB_TYPE } from "../env.defaults"; import { SettingHelper } from "../helpers/settingsHelper";
let durationInDays: string; let durationInDays: string;
let durationInYears: string; let durationInYears: string;
let exactDuration: string; let exactDuration: string;
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
if (DB_TYPE == "postgres") { if (DB_TYPE == "postgres") {
durationInDays = `SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") `; durationInDays = `SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") `;
durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")))`; durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")))`;