Merge pull request 'patches v1.2.1' (#54) from develop into main
Reviewed-on: #54
This commit is contained in:
commit
3165eb789f
35 changed files with 891 additions and 272 deletions
|
@ -20,13 +20,13 @@ Um den Container hochzufahren, erstellen Sie eine `docker-compose.yml` Datei mit
|
||||||
version: "3"
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
ff-ff-admin-server:
|
ff-admin-server:
|
||||||
image: docker.registry.jk-effects.cloud/ehrenamt/ff-admin/server:latest
|
image: docker.registry.jk-effects.cloud/ehrenamt/ff-admin/server:latest
|
||||||
container_name: ff_member_administration_server
|
container_name: ff_member_administration_server
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- DB_TYPE=<mysql|sqlite> # default ist auf mysql gesetzt
|
- DB_TYPE=<mysql|sqlite> # default ist auf mysql gesetzt
|
||||||
- DB_HOST=ffm-db
|
- DB_HOST=ff-db
|
||||||
- DB_PORT=<number> # default ist auf 3306 gesetzt
|
- DB_PORT=<number> # default ist auf 3306 gesetzt
|
||||||
- DB_NAME=ffadmin
|
- DB_NAME=ffadmin
|
||||||
- DB_USERNAME=administration_backend
|
- DB_USERNAME=administration_backend
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { Salutation } from "../../../enums/salutation";
|
|
||||||
|
|
||||||
export interface CreateMemberCommand {
|
export interface CreateMemberCommand {
|
||||||
salutation: Salutation;
|
salutationId: number;
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
|
@ -11,7 +9,7 @@ export interface CreateMemberCommand {
|
||||||
|
|
||||||
export interface UpdateMemberCommand {
|
export interface UpdateMemberCommand {
|
||||||
id: number;
|
id: number;
|
||||||
salutation: Salutation;
|
salutationId: number;
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
|
|
|
@ -21,7 +21,7 @@ export default abstract class MemberCommandHandler {
|
||||||
.insert()
|
.insert()
|
||||||
.into(member)
|
.into(member)
|
||||||
.values({
|
.values({
|
||||||
salutation: createMember.salutation,
|
salutationId: createMember.salutationId,
|
||||||
firstname: createMember.firstname,
|
firstname: createMember.firstname,
|
||||||
lastname: createMember.lastname,
|
lastname: createMember.lastname,
|
||||||
nameaffix: createMember.nameaffix,
|
nameaffix: createMember.nameaffix,
|
||||||
|
@ -50,7 +50,7 @@ export default abstract class MemberCommandHandler {
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.update(member)
|
.update(member)
|
||||||
.set({
|
.set({
|
||||||
salutation: updateMember.salutation,
|
salutationId: updateMember.salutationId,
|
||||||
firstname: updateMember.firstname,
|
firstname: updateMember.firstname,
|
||||||
lastname: updateMember.lastname,
|
lastname: updateMember.lastname,
|
||||||
nameaffix: updateMember.nameaffix,
|
nameaffix: updateMember.nameaffix,
|
||||||
|
|
12
src/command/settings/salutation/salutationCommand.ts
Normal file
12
src/command/settings/salutation/salutationCommand.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export interface CreateSalutationCommand {
|
||||||
|
salutation: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateSalutationCommand {
|
||||||
|
id: number;
|
||||||
|
salutation: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteSalutationCommand {
|
||||||
|
id: number;
|
||||||
|
}
|
69
src/command/settings/salutation/salutationCommandHandler.ts
Normal file
69
src/command/settings/salutation/salutationCommandHandler.ts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { dataSource } from "../../../data-source";
|
||||||
|
import { salutation } from "../../../entity/settings/salutation";
|
||||||
|
import InternalException from "../../../exceptions/internalException";
|
||||||
|
import { CreateSalutationCommand, DeleteSalutationCommand, UpdateSalutationCommand } from "./salutationCommand";
|
||||||
|
|
||||||
|
export default abstract class SalutationCommandHandler {
|
||||||
|
/**
|
||||||
|
* @description create salutation
|
||||||
|
* @param {CreateSalutationCommand} createSalutation
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
static async create(createSalutation: CreateSalutationCommand): Promise<number> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(salutation)
|
||||||
|
.values({
|
||||||
|
salutation: createSalutation.salutation,
|
||||||
|
})
|
||||||
|
.execute()
|
||||||
|
.then((result) => {
|
||||||
|
return result.identifiers[0].id;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("Failed creating salutation", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description update salutation
|
||||||
|
* @param {UpdateSalutationCommand} updateSalutation
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
static async update(updateSalutation: UpdateSalutationCommand): Promise<void> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update(salutation)
|
||||||
|
.set({
|
||||||
|
salutation: updateSalutation.salutation,
|
||||||
|
})
|
||||||
|
.where("id = :id", { id: updateSalutation.id })
|
||||||
|
.execute()
|
||||||
|
.then(() => {})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("Failed updating salutation", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description delete salutation
|
||||||
|
* @param {DeleteSalutationCommand} deleteSalutation
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
static async delete(deleteSalutation: DeleteSalutationCommand): Promise<void> {
|
||||||
|
return await dataSource
|
||||||
|
.createQueryBuilder()
|
||||||
|
.delete()
|
||||||
|
.from(salutation)
|
||||||
|
.where("id = :id", { id: deleteSalutation.id })
|
||||||
|
.execute()
|
||||||
|
.then(() => {})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException(
|
||||||
|
`Failed deleting salutation ${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -285,15 +285,15 @@ export async function createMemberPrintoutList(req: Request, res: Response): Pro
|
||||||
* @returns {Promise<*>}
|
* @returns {Promise<*>}
|
||||||
*/
|
*/
|
||||||
export async function createMember(req: Request, res: Response): Promise<any> {
|
export async function createMember(req: Request, res: Response): Promise<any> {
|
||||||
const salutation = req.body.salutation;
|
const salutationId = parseInt(req.body.salutationId);
|
||||||
const firstname = req.body.firstname;
|
const firstname = req.body.firstname;
|
||||||
const lastname = req.body.lastname;
|
const lastname = req.body.lastname;
|
||||||
const nameaffix = req.body.nameaffix;
|
const nameaffix = req.body.nameaffix;
|
||||||
const birthdate = req.body.birthdate;
|
const birthdate = req.body.birthdate;
|
||||||
const internalId = req.body.internalId;
|
const internalId = req.body.internalId || null;
|
||||||
|
|
||||||
let createMember: CreateMemberCommand = {
|
let createMember: CreateMemberCommand = {
|
||||||
salutation,
|
salutationId,
|
||||||
firstname,
|
firstname,
|
||||||
lastname,
|
lastname,
|
||||||
nameaffix,
|
nameaffix,
|
||||||
|
@ -453,7 +453,7 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro
|
||||||
*/
|
*/
|
||||||
export async function updateMemberById(req: Request, res: Response): Promise<any> {
|
export async function updateMemberById(req: Request, res: Response): Promise<any> {
|
||||||
const memberId = parseInt(req.params.id);
|
const memberId = parseInt(req.params.id);
|
||||||
const salutation = req.body.salutation;
|
const salutationId = parseInt(req.body.salutationId);
|
||||||
const firstname = req.body.firstname;
|
const firstname = req.body.firstname;
|
||||||
const lastname = req.body.lastname;
|
const lastname = req.body.lastname;
|
||||||
const nameaffix = req.body.nameaffix;
|
const nameaffix = req.body.nameaffix;
|
||||||
|
@ -462,7 +462,7 @@ export async function updateMemberById(req: Request, res: Response): Promise<any
|
||||||
|
|
||||||
let updateMember: UpdateMemberCommand = {
|
let updateMember: UpdateMemberCommand = {
|
||||||
id: memberId,
|
id: memberId,
|
||||||
salutation,
|
salutationId,
|
||||||
firstname,
|
firstname,
|
||||||
lastname,
|
lastname,
|
||||||
nameaffix,
|
nameaffix,
|
||||||
|
|
|
@ -21,7 +21,6 @@ import UserService from "../../../service/user/userService";
|
||||||
import { TemplateHelper } from "../../../helpers/templateHelper";
|
import { TemplateHelper } from "../../../helpers/templateHelper";
|
||||||
import MailHelper from "../../../helpers/mailHelper";
|
import MailHelper from "../../../helpers/mailHelper";
|
||||||
import { NewsletterEventType, NewsletterHelper } from "../../../helpers/newsletterHelper";
|
import { NewsletterEventType, NewsletterHelper } from "../../../helpers/newsletterHelper";
|
||||||
import { Salutation } from "../../../enums/salutation";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description get all newsletters
|
* @description get all newsletters
|
||||||
|
@ -142,7 +141,7 @@ export async function createNewsletterPrintoutPreviewById(req: Request, res: Res
|
||||||
data.recipient = {
|
data.recipient = {
|
||||||
firstname: recipient.firstname,
|
firstname: recipient.firstname,
|
||||||
lastname: recipient.lastname,
|
lastname: recipient.lastname,
|
||||||
salutation: Salutation.none,
|
salutation: "Anrede",
|
||||||
nameaffix: "",
|
nameaffix: "",
|
||||||
street: "Straße",
|
street: "Straße",
|
||||||
streetNumber: "Hausnummer",
|
streetNumber: "Hausnummer",
|
||||||
|
@ -248,7 +247,7 @@ export async function createNewsletterMailPreviewById(req: Request, res: Respons
|
||||||
data.recipient = {
|
data.recipient = {
|
||||||
firstname: recipient.firstname,
|
firstname: recipient.firstname,
|
||||||
lastname: recipient.lastname,
|
lastname: recipient.lastname,
|
||||||
salutation: Salutation.none,
|
salutation: "Anrede",
|
||||||
nameaffix: "",
|
nameaffix: "",
|
||||||
street: "Straße",
|
street: "Straße",
|
||||||
streetNumber: "Hausnummer",
|
streetNumber: "Hausnummer",
|
||||||
|
|
87
src/controller/admin/settings/salutationController.ts
Normal file
87
src/controller/admin/settings/salutationController.ts
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import SalutationService from "../../../service/settings/salutationService";
|
||||||
|
import SalutationFactory from "../../../factory/admin/settings/salutation";
|
||||||
|
import {
|
||||||
|
CreateSalutationCommand,
|
||||||
|
DeleteSalutationCommand,
|
||||||
|
UpdateSalutationCommand,
|
||||||
|
} from "../../../command/settings/salutation/salutationCommand";
|
||||||
|
import SalutationCommandHandler from "../../../command/settings/salutation/salutationCommandHandler";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description get all salutations
|
||||||
|
* @param req {Request} Express req object
|
||||||
|
* @param res {Response} Express res object
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getAllSalutations(req: Request, res: Response): Promise<any> {
|
||||||
|
let salutations = await SalutationService.getAll();
|
||||||
|
|
||||||
|
res.json(SalutationFactory.mapToBase(salutations));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description get salutation by id
|
||||||
|
* @param req {Request} Express req object
|
||||||
|
* @param res {Response} Express res object
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function getSalutationById(req: Request, res: Response): Promise<any> {
|
||||||
|
const id = parseInt(req.params.id);
|
||||||
|
let salutation = await SalutationService.getById(id);
|
||||||
|
|
||||||
|
res.json(SalutationFactory.mapToSingle(salutation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description create new salutation
|
||||||
|
* @param req {Request} Express req object
|
||||||
|
* @param res {Response} Express res object
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function createSalutation(req: Request, res: Response): Promise<any> {
|
||||||
|
const salutation = req.body.salutation;
|
||||||
|
|
||||||
|
let createSalutation: CreateSalutationCommand = {
|
||||||
|
salutation: salutation,
|
||||||
|
};
|
||||||
|
await SalutationCommandHandler.create(createSalutation);
|
||||||
|
|
||||||
|
res.sendStatus(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description update salutation
|
||||||
|
* @param req {Request} Express req object
|
||||||
|
* @param res {Response} Express res object
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function updateSalutation(req: Request, res: Response): Promise<any> {
|
||||||
|
const id = parseInt(req.params.id);
|
||||||
|
const salutation = req.body.salutation;
|
||||||
|
|
||||||
|
let updateSalutation: UpdateSalutationCommand = {
|
||||||
|
id: id,
|
||||||
|
salutation: salutation,
|
||||||
|
};
|
||||||
|
await SalutationCommandHandler.update(updateSalutation);
|
||||||
|
|
||||||
|
res.sendStatus(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description delete salutation
|
||||||
|
* @param req {Request} Express req object
|
||||||
|
* @param res {Response} Express res object
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
export async function deleteSalutation(req: Request, res: Response): Promise<any> {
|
||||||
|
const id = parseInt(req.params.id);
|
||||||
|
|
||||||
|
let deleteSalutation: DeleteSalutationCommand = {
|
||||||
|
id: id,
|
||||||
|
};
|
||||||
|
await SalutationCommandHandler.delete(deleteSalutation);
|
||||||
|
|
||||||
|
res.sendStatus(204);
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import MailHelper from "../../../helpers/mailHelper";
|
||||||
import { CLUB_NAME } from "../../../env.defaults";
|
import { CLUB_NAME } from "../../../env.defaults";
|
||||||
import { UpdateUserPermissionsCommand } from "../../../command/user/user/userPermissionCommand";
|
import { UpdateUserPermissionsCommand } from "../../../command/user/user/userPermissionCommand";
|
||||||
import UserPermissionCommandHandler from "../../../command/user/user/userPermissionCommandHandler";
|
import UserPermissionCommandHandler from "../../../command/user/user/userPermissionCommandHandler";
|
||||||
|
import BadRequestException from "../../../exceptions/badRequestException";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description get All users
|
* @description get All users
|
||||||
|
@ -137,7 +138,11 @@ export async function updateUserRoles(req: Request, res: Response): Promise<any>
|
||||||
export async function deleteUser(req: Request, res: Response): Promise<any> {
|
export async function deleteUser(req: Request, res: Response): Promise<any> {
|
||||||
const id = parseInt(req.params.id);
|
const id = parseInt(req.params.id);
|
||||||
|
|
||||||
let user = await UserService.getById(id);
|
let { mail, isOwner } = await UserService.getById(id);
|
||||||
|
|
||||||
|
if (isOwner) {
|
||||||
|
throw new BadRequestException("Owner cannot be deleted");
|
||||||
|
}
|
||||||
|
|
||||||
let deleteUser: DeleteUserCommand = {
|
let deleteUser: DeleteUserCommand = {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -147,7 +152,7 @@ export async function deleteUser(req: Request, res: Response): Promise<any> {
|
||||||
try {
|
try {
|
||||||
// sendmail
|
// sendmail
|
||||||
await MailHelper.sendMail(
|
await MailHelper.sendMail(
|
||||||
user.mail,
|
mail,
|
||||||
`Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`,
|
`Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`,
|
||||||
`Ihr Nutzerkonto des Adminportals wurde erfolgreich gelöscht.`
|
`Ihr Nutzerkonto des Adminportals wurde erfolgreich gelöscht.`
|
||||||
);
|
);
|
||||||
|
|
|
@ -71,6 +71,9 @@ import { ProtocolPresenceExcuse1737287798828 } from "./migrations/1737287798828-
|
||||||
import { webapi } from "./entity/user/webapi";
|
import { webapi } from "./entity/user/webapi";
|
||||||
import { webapiPermission } from "./entity/user/webapi_permission";
|
import { webapiPermission } from "./entity/user/webapi_permission";
|
||||||
import { AddWebapiTokens1737453096674 } from "./migrations/1737453096674-addwebapiTokens";
|
import { AddWebapiTokens1737453096674 } from "./migrations/1737453096674-addwebapiTokens";
|
||||||
|
import { salutation } from "./entity/settings/salutation";
|
||||||
|
import { SalutationAsTable1737796878058 } from "./migrations/1737796878058-salutationAsTable";
|
||||||
|
import { UpdateViews1737800468938 } from "./migrations/1737800468938-updateViews";
|
||||||
|
|
||||||
const dataSource = new DataSource({
|
const dataSource = new DataSource({
|
||||||
type: DB_TYPE as any,
|
type: DB_TYPE as any,
|
||||||
|
@ -96,6 +99,7 @@ const dataSource = new DataSource({
|
||||||
executivePosition,
|
executivePosition,
|
||||||
membershipStatus,
|
membershipStatus,
|
||||||
qualification,
|
qualification,
|
||||||
|
salutation,
|
||||||
member,
|
member,
|
||||||
memberAwards,
|
memberAwards,
|
||||||
memberExecutivePositions,
|
memberExecutivePositions,
|
||||||
|
@ -152,6 +156,8 @@ const dataSource = new DataSource({
|
||||||
FinishInternalIdTransfer1736505324488,
|
FinishInternalIdTransfer1736505324488,
|
||||||
ProtocolPresenceExcuse1737287798828,
|
ProtocolPresenceExcuse1737287798828,
|
||||||
AddWebapiTokens1737453096674,
|
AddWebapiTokens1737453096674,
|
||||||
|
SalutationAsTable1737796878058,
|
||||||
|
UpdateViews1737800468938,
|
||||||
],
|
],
|
||||||
migrationsRun: true,
|
migrationsRun: true,
|
||||||
migrationsTransactionMode: "each",
|
migrationsTransactionMode: "each",
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { calendar } from "../entity/club/calendar";
|
import { calendar } from "../entity/club/calendar";
|
||||||
import { member } from "../entity/club/member/member";
|
import { member } from "../entity/club/member/member";
|
||||||
import { Salutation } from "../enums/salutation";
|
|
||||||
|
|
||||||
export const newsletterDemoData: {
|
export const newsletterDemoData: {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -18,7 +17,9 @@ export const newsletterDemoData: {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
recipient: Partial<member & { street: string; streetNumber: string; streetNumberAdd: string }>;
|
recipient: Partial<
|
||||||
|
Omit<member, "salutation"> & { salutation: string; street: string; streetNumber: string; streetNumberAdd: string }
|
||||||
|
>;
|
||||||
} = {
|
} = {
|
||||||
title: "Beispiel Newsletter Daten",
|
title: "Beispiel Newsletter Daten",
|
||||||
description: "Zusammenfassung der Demodaten.",
|
description: "Zusammenfassung der Demodaten.",
|
||||||
|
@ -63,7 +64,7 @@ export const newsletterDemoData: {
|
||||||
recipient: {
|
recipient: {
|
||||||
firstname: "Julian",
|
firstname: "Julian",
|
||||||
lastname: "Krauser",
|
lastname: "Krauser",
|
||||||
salutation: Salutation.sir,
|
salutation: "Herr",
|
||||||
nameaffix: "",
|
nameaffix: "",
|
||||||
street: "Straße",
|
street: "Straße",
|
||||||
streetNumber: "Hausnummer",
|
streetNumber: "Hausnummer",
|
||||||
|
|
|
@ -1,32 +1,16 @@
|
||||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryColumn } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryColumn } from "typeorm";
|
||||||
import { Salutation } from "../../../enums/salutation";
|
|
||||||
import { membership } from "./membership";
|
import { membership } from "./membership";
|
||||||
import { memberAwards } from "./memberAwards";
|
import { memberAwards } from "./memberAwards";
|
||||||
import { memberQualifications } from "./memberQualifications";
|
import { memberQualifications } from "./memberQualifications";
|
||||||
import { memberExecutivePositions } from "./memberExecutivePositions";
|
import { memberExecutivePositions } from "./memberExecutivePositions";
|
||||||
import { communication } from "./communication";
|
import { communication } from "./communication";
|
||||||
import { CommunicationViewModel } from "../../../viewmodel/admin/club/member/communication.models";
|
import { salutation } from "../../settings/salutation";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class member {
|
export class member {
|
||||||
@PrimaryColumn({ generated: "increment", type: "int" })
|
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@Column({
|
|
||||||
type: "varchar",
|
|
||||||
length: "255",
|
|
||||||
default: Salutation.none.toString(),
|
|
||||||
transformer: {
|
|
||||||
to(value: Salutation) {
|
|
||||||
return value.toString();
|
|
||||||
},
|
|
||||||
from(value: string) {
|
|
||||||
return Salutation[value as keyof typeof Salutation];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
salutation: Salutation;
|
|
||||||
|
|
||||||
@Column({ type: "varchar", length: 255 })
|
@Column({ type: "varchar", length: 255 })
|
||||||
firstname: string;
|
firstname: string;
|
||||||
|
|
||||||
|
@ -42,6 +26,9 @@ export class member {
|
||||||
@Column({ type: "varchar", length: 255, unique: true, nullable: true })
|
@Column({ type: "varchar", length: 255, unique: true, nullable: true })
|
||||||
internalId?: string;
|
internalId?: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
salutationId: number;
|
||||||
|
|
||||||
@OneToMany(() => communication, (communications) => communications.member)
|
@OneToMany(() => communication, (communications) => communications.member)
|
||||||
communications: communication[];
|
communications: communication[];
|
||||||
|
|
||||||
|
@ -53,6 +40,9 @@ export class member {
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
sendNewsletter?: communication;
|
sendNewsletter?: communication;
|
||||||
|
|
||||||
|
@ManyToOne(() => salutation, (salutation) => salutation.members)
|
||||||
|
salutation: salutation;
|
||||||
|
|
||||||
@OneToMany(() => membership, (membership) => membership.member)
|
@OneToMany(() => membership, (membership) => membership.member)
|
||||||
memberships: membership[];
|
memberships: membership[];
|
||||||
|
|
||||||
|
|
15
src/entity/settings/salutation.ts
Normal file
15
src/entity/settings/salutation.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Column, Entity, OneToMany, PrimaryColumn } from "typeorm";
|
||||||
|
import { memberAwards } from "../club/member/memberAwards";
|
||||||
|
import { member } from "../club/member/member";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class salutation {
|
||||||
|
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255, unique: true })
|
||||||
|
salutation: string;
|
||||||
|
|
||||||
|
@OneToMany(() => member, (member) => member.salutation)
|
||||||
|
members: member[];
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
export enum Salutation {
|
|
||||||
sir = "sir",
|
|
||||||
madam = "madam",
|
|
||||||
other = "other",
|
|
||||||
none = "none",
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { member } from "../../../../entity/club/member/member";
|
import { member } from "../../../../entity/club/member/member";
|
||||||
import { MemberStatisticsViewModel, MemberViewModel } from "../../../../viewmodel/admin/club/member/member.models";
|
import { MemberStatisticsViewModel, MemberViewModel } from "../../../../viewmodel/admin/club/member/member.models";
|
||||||
import { memberView } from "../../../../views/memberView";
|
import { memberView } from "../../../../views/memberView";
|
||||||
|
import SalutationFactory from "../../settings/salutation";
|
||||||
import CommunicationFactory from "./communication";
|
import CommunicationFactory from "./communication";
|
||||||
import MembershipFactory from "./membership";
|
import MembershipFactory from "./membership";
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ export default abstract class MemberFactory {
|
||||||
public static mapToSingle(record: member): MemberViewModel {
|
public static mapToSingle(record: member): MemberViewModel {
|
||||||
return {
|
return {
|
||||||
id: record?.id,
|
id: record?.id,
|
||||||
salutation: record?.salutation,
|
salutation: SalutationFactory.mapToSingle(record?.salutation),
|
||||||
firstname: record?.firstname,
|
firstname: record?.firstname,
|
||||||
lastname: record?.lastname,
|
lastname: record?.lastname,
|
||||||
nameaffix: record?.nameaffix,
|
nameaffix: record?.nameaffix,
|
||||||
|
|
25
src/factory/admin/settings/salutation.ts
Normal file
25
src/factory/admin/settings/salutation.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { salutation } from "../../../entity/settings/salutation";
|
||||||
|
import { SalutationViewModel } from "../../../viewmodel/admin/settings/salutation.models";
|
||||||
|
|
||||||
|
export default abstract class SalutationFactory {
|
||||||
|
/**
|
||||||
|
* @description map record to salutation
|
||||||
|
* @param {salutation} record
|
||||||
|
* @returns {SalutationViewModel}
|
||||||
|
*/
|
||||||
|
public static mapToSingle(record: salutation): SalutationViewModel {
|
||||||
|
return {
|
||||||
|
id: record.id,
|
||||||
|
salutation: record.salutation,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description map records to salutation
|
||||||
|
* @param {Array<salutation>} records
|
||||||
|
* @returns {Array<SalutationViewModel>}
|
||||||
|
*/
|
||||||
|
public static mapToBase(records: Array<salutation>): Array<SalutationViewModel> {
|
||||||
|
return records.map((r) => this.mapToSingle(r));
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ export default abstract class DynamicQueryBuilder {
|
||||||
"executivePosition",
|
"executivePosition",
|
||||||
"membershipStatus",
|
"membershipStatus",
|
||||||
"qualification",
|
"qualification",
|
||||||
|
"salutation",
|
||||||
"member",
|
"member",
|
||||||
"memberAwards",
|
"memberAwards",
|
||||||
"memberExecutivePositions",
|
"memberExecutivePositions",
|
||||||
|
|
|
@ -100,7 +100,7 @@ export abstract class NewsletterHelper {
|
||||||
recipient: {
|
recipient: {
|
||||||
firstname: recipient.firstname,
|
firstname: recipient.firstname,
|
||||||
lastname: recipient.lastname,
|
lastname: recipient.lastname,
|
||||||
salutation: recipient.salutation,
|
salutation: recipient.salutation.salutation,
|
||||||
nameaffix: recipient.nameaffix,
|
nameaffix: recipient.nameaffix,
|
||||||
...(showAdress
|
...(showAdress
|
||||||
? {
|
? {
|
||||||
|
|
|
@ -8,105 +8,105 @@ export class MemberDataViews1734520998539 implements MigrationInterface {
|
||||||
name = "MemberDataViews1734520998539";
|
name = "MemberDataViews1734520998539";
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.createView(
|
// await queryRunner.createView(
|
||||||
new View({
|
// new View({
|
||||||
name: "member_view",
|
// name: "member_view",
|
||||||
expression: (datasource: DataSource) =>
|
// expression: (datasource: DataSource) =>
|
||||||
datasource
|
// datasource
|
||||||
.getRepository(member)
|
// .getRepository(member)
|
||||||
.createQueryBuilder("member")
|
// .createQueryBuilder("member")
|
||||||
.select("member.id", "id")
|
// .select("member.id", "id")
|
||||||
.addSelect("member.salutation", "salutation")
|
// .addSelect("member.salutation", "salutation")
|
||||||
.addSelect("member.firstname", "firstname")
|
// .addSelect("member.firstname", "firstname")
|
||||||
.addSelect("member.lastname", "lastname")
|
// .addSelect("member.lastname", "lastname")
|
||||||
.addSelect("member.nameaffix", "nameaffix")
|
// .addSelect("member.nameaffix", "nameaffix")
|
||||||
.addSelect("member.birthdate", "birthdate")
|
// .addSelect("member.birthdate", "birthdate")
|
||||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
// .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
// .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||||
}),
|
// }),
|
||||||
true
|
// true
|
||||||
);
|
// );
|
||||||
await queryRunner.createView(
|
// await queryRunner.createView(
|
||||||
new View({
|
// new View({
|
||||||
name: "member_executive_positions_view",
|
// name: "member_executive_positions_view",
|
||||||
expression: (datasource: DataSource) =>
|
// expression: (datasource: DataSource) =>
|
||||||
datasource
|
// datasource
|
||||||
.getRepository(memberExecutivePositions)
|
// .getRepository(memberExecutivePositions)
|
||||||
.createQueryBuilder("memberExecutivePositions")
|
// .createQueryBuilder("memberExecutivePositions")
|
||||||
.select("executivePosition.id", "positionId")
|
// .select("executivePosition.id", "positionId")
|
||||||
.addSelect("executivePosition.position", "position")
|
// .addSelect("executivePosition.position", "position")
|
||||||
.addSelect("member.id", "memberId")
|
// .addSelect("member.id", "memberId")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
// .addSelect("member.salutation", "memberSalutation")
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
// .addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
// .addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
// .addSelect("member.birthdate", "memberBirthdate")
|
||||||
.addSelect(
|
// .addSelect(
|
||||||
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
// "SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||||
"durationInDays"
|
// "durationInDays"
|
||||||
)
|
// )
|
||||||
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
// .leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||||
.leftJoin("memberExecutivePositions.member", "member")
|
// .leftJoin("memberExecutivePositions.member", "member")
|
||||||
.groupBy("executivePosition.id"),
|
// .groupBy("executivePosition.id"),
|
||||||
}),
|
// }),
|
||||||
true
|
// true
|
||||||
);
|
// );
|
||||||
await queryRunner.createView(
|
// await queryRunner.createView(
|
||||||
new View({
|
// new View({
|
||||||
name: "member_qualifications_view",
|
// name: "member_qualifications_view",
|
||||||
expression: (datasource: DataSource) =>
|
// expression: (datasource: DataSource) =>
|
||||||
datasource
|
// datasource
|
||||||
.getRepository(memberQualifications)
|
// .getRepository(memberQualifications)
|
||||||
.createQueryBuilder("memberQualifications")
|
// .createQueryBuilder("memberQualifications")
|
||||||
.select("qualification.id", "qualificationId")
|
// .select("qualification.id", "qualificationId")
|
||||||
.addSelect("qualification.qualification", "qualification")
|
// .addSelect("qualification.qualification", "qualification")
|
||||||
.addSelect("member.id", "memberId")
|
// .addSelect("member.id", "memberId")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
// .addSelect("member.salutation", "memberSalutation")
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
// .addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
// .addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
// .addSelect("member.birthdate", "memberBirthdate")
|
||||||
.addSelect(
|
// .addSelect(
|
||||||
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
// "SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||||
"durationInDays"
|
// "durationInDays"
|
||||||
)
|
// )
|
||||||
.leftJoin("memberQualifications.qualification", "qualification")
|
// .leftJoin("memberQualifications.qualification", "qualification")
|
||||||
.leftJoin("memberQualifications.member", "member")
|
// .leftJoin("memberQualifications.member", "member")
|
||||||
.groupBy("qualification.id"),
|
// .groupBy("qualification.id"),
|
||||||
}),
|
// }),
|
||||||
true
|
// true
|
||||||
);
|
// );
|
||||||
await queryRunner.createView(
|
// await queryRunner.createView(
|
||||||
new View({
|
// new View({
|
||||||
name: "membership_view",
|
// name: "membership_view",
|
||||||
expression: (datasource: DataSource) =>
|
// expression: (datasource: DataSource) =>
|
||||||
datasource
|
// datasource
|
||||||
.getRepository(membership)
|
// .getRepository(membership)
|
||||||
.createQueryBuilder("membership")
|
// .createQueryBuilder("membership")
|
||||||
.select("status.id", "statusId")
|
// .select("status.id", "statusId")
|
||||||
.addSelect("status.status", "status")
|
// .addSelect("status.status", "status")
|
||||||
.addSelect("member.id", "memberId")
|
// .addSelect("member.id", "memberId")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
// .addSelect("member.salutation", "memberSalutation")
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
// .addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
// .addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
// .addSelect("member.birthdate", "memberBirthdate")
|
||||||
.addSelect(
|
// .addSelect(
|
||||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
// "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||||
"durationInDays"
|
// "durationInDays"
|
||||||
)
|
// )
|
||||||
.leftJoin("membership.status", "status")
|
// .leftJoin("membership.status", "status")
|
||||||
.leftJoin("membership.member", "member")
|
// .leftJoin("membership.member", "member")
|
||||||
.groupBy("status.id"),
|
// .groupBy("status.id"),
|
||||||
}),
|
// }),
|
||||||
true
|
// true
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.dropView("membership_view");
|
// await queryRunner.dropView("membership_view");
|
||||||
await queryRunner.dropView("member_qualifications_view");
|
// await queryRunner.dropView("member_qualifications_view");
|
||||||
await queryRunner.dropView("member_executive_positions_view");
|
// await queryRunner.dropView("member_executive_positions_view");
|
||||||
await queryRunner.dropView("member_view");
|
// await queryRunner.dropView("member_view");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,106 +8,104 @@ export class ExtendViewValues1736084198860 implements MigrationInterface {
|
||||||
name = "ExtendViewValues1736084198860";
|
name = "ExtendViewValues1736084198860";
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.dropView("membership_view");
|
// await queryRunner.dropView("membership_view");
|
||||||
await queryRunner.dropView("member_view");
|
// await queryRunner.dropView("member_view");
|
||||||
|
// await queryRunner.createView(
|
||||||
await queryRunner.createView(
|
// new View({
|
||||||
new View({
|
// name: "member_view",
|
||||||
name: "member_view",
|
// expression: (datasource: DataSource) =>
|
||||||
expression: (datasource: DataSource) =>
|
// datasource
|
||||||
datasource
|
// .getRepository(member)
|
||||||
.getRepository(member)
|
// .createQueryBuilder("member")
|
||||||
.createQueryBuilder("member")
|
// .select("member.id", "id")
|
||||||
.select("member.id", "id")
|
// .addSelect("member.salutation", "salutation")
|
||||||
.addSelect("member.salutation", "salutation")
|
// .addSelect("member.firstname", "firstname")
|
||||||
.addSelect("member.firstname", "firstname")
|
// .addSelect("member.lastname", "lastname")
|
||||||
.addSelect("member.lastname", "lastname")
|
// .addSelect("member.nameaffix", "nameaffix")
|
||||||
.addSelect("member.nameaffix", "nameaffix")
|
// .addSelect("member.birthdate", "birthdate")
|
||||||
.addSelect("member.birthdate", "birthdate")
|
// .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
// .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
// .addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
// }),
|
||||||
}),
|
// true
|
||||||
true
|
// );
|
||||||
);
|
// await queryRunner.createView(
|
||||||
await queryRunner.createView(
|
// new View({
|
||||||
new View({
|
// name: "membership_view",
|
||||||
name: "membership_view",
|
// expression: (datasource: DataSource) =>
|
||||||
expression: (datasource: DataSource) =>
|
// datasource
|
||||||
datasource
|
// .getRepository(membership)
|
||||||
.getRepository(membership)
|
// .createQueryBuilder("membership")
|
||||||
.createQueryBuilder("membership")
|
// .select("status.id", "statusId")
|
||||||
.select("status.id", "statusId")
|
// .addSelect("status.status", "status")
|
||||||
.addSelect("status.status", "status")
|
// .addSelect("member.id", "memberId")
|
||||||
.addSelect("member.id", "memberId")
|
// .addSelect("member.salutation", "memberSalutation")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
// .addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
// .addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
// .addSelect("member.birthdate", "memberBirthdate")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
// .addSelect(
|
||||||
.addSelect(
|
// "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
// "durationInDays"
|
||||||
"durationInDays"
|
// )
|
||||||
)
|
// .addSelect(
|
||||||
.addSelect(
|
// "CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
// "durationInYears"
|
||||||
"durationInYears"
|
// )
|
||||||
)
|
// .leftJoin("membership.status", "status")
|
||||||
.leftJoin("membership.status", "status")
|
// .leftJoin("membership.member", "member")
|
||||||
.leftJoin("membership.member", "member")
|
// .groupBy("status.id")
|
||||||
.groupBy("status.id")
|
// .addGroupBy("member.id"),
|
||||||
.addGroupBy("member.id"),
|
// }),
|
||||||
}),
|
// true
|
||||||
true
|
// );
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.dropView("membership_view");
|
// await queryRunner.dropView("membership_view");
|
||||||
await queryRunner.dropView("member_view");
|
// await queryRunner.dropView("member_view");
|
||||||
|
// await queryRunner.createView(
|
||||||
await queryRunner.createView(
|
// new View({
|
||||||
new View({
|
// name: "member_view",
|
||||||
name: "member_view",
|
// expression: (datasource: DataSource) =>
|
||||||
expression: (datasource: DataSource) =>
|
// datasource
|
||||||
datasource
|
// .getRepository(member)
|
||||||
.getRepository(member)
|
// .createQueryBuilder("member")
|
||||||
.createQueryBuilder("member")
|
// .select("member.id", "id")
|
||||||
.select("member.id", "id")
|
// .addSelect("member.salutation", "salutation")
|
||||||
.addSelect("member.salutation", "salutation")
|
// .addSelect("member.firstname", "firstname")
|
||||||
.addSelect("member.firstname", "firstname")
|
// .addSelect("member.lastname", "lastname")
|
||||||
.addSelect("member.lastname", "lastname")
|
// .addSelect("member.nameaffix", "nameaffix")
|
||||||
.addSelect("member.nameaffix", "nameaffix")
|
// .addSelect("member.birthdate", "birthdate")
|
||||||
.addSelect("member.birthdate", "birthdate")
|
// .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
// .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
// }),
|
||||||
}),
|
// true
|
||||||
true
|
// );
|
||||||
);
|
// await queryRunner.createView(
|
||||||
await queryRunner.createView(
|
// new View({
|
||||||
new View({
|
// name: "membership_view",
|
||||||
name: "membership_view",
|
// expression: (datasource: DataSource) =>
|
||||||
expression: (datasource: DataSource) =>
|
// datasource
|
||||||
datasource
|
// .getRepository(membership)
|
||||||
.getRepository(membership)
|
// .createQueryBuilder("membership")
|
||||||
.createQueryBuilder("membership")
|
// .select("status.id", "statusId")
|
||||||
.select("status.id", "statusId")
|
// .addSelect("status.status", "status")
|
||||||
.addSelect("status.status", "status")
|
// .addSelect("member.id", "memberId")
|
||||||
.addSelect("member.id", "memberId")
|
// .addSelect("member.salutation", "memberSalutation")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
// .addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
// .addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
// .addSelect("member.birthdate", "memberBirthdate")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
// .addSelect(
|
||||||
.addSelect(
|
// "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
// "durationInDays"
|
||||||
"durationInDays"
|
// )
|
||||||
)
|
// .leftJoin("membership.status", "status")
|
||||||
.leftJoin("membership.status", "status")
|
// .leftJoin("membership.member", "member")
|
||||||
.leftJoin("membership.member", "member")
|
// .groupBy("status.id"),
|
||||||
.groupBy("status.id"),
|
// }),
|
||||||
}),
|
// true
|
||||||
true
|
// );
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
91
src/migrations/1737796878058-salutationAsTable.ts
Normal file
91
src/migrations/1737796878058-salutationAsTable.ts
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from "typeorm";
|
||||||
|
import { DB_TYPE } from "../env.defaults";
|
||||||
|
import { member } from "../entity/club/member/member";
|
||||||
|
import { salutation } from "../entity/settings/salutation";
|
||||||
|
|
||||||
|
export class SalutationAsTable1737796878058 implements MigrationInterface {
|
||||||
|
name = "SalutationAsTable1737796878058";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const variableType_int = DB_TYPE == "mysql" ? "int" : "integer";
|
||||||
|
|
||||||
|
await queryRunner.createTable(
|
||||||
|
new Table({
|
||||||
|
name: "salutation",
|
||||||
|
columns: [
|
||||||
|
{ name: "id", type: variableType_int, isPrimary: true, isGenerated: true, generationStrategy: "increment" },
|
||||||
|
{ name: "salutation", type: "varchar", length: "255", isUnique: true, isNullable: false },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// ! has to be sql. Else the column would be dropped and created - resulting in data loss.
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`member\` CHANGE \`salutation\` \`salutationId\` varchar(255) NOT NULL DEFAULT ''`
|
||||||
|
);
|
||||||
|
|
||||||
|
// ! has to be sql. Else no data is returned.
|
||||||
|
const existing_salutations = await queryRunner.query(
|
||||||
|
"SELECT DISTINCT salutationId FROM `member` `member` GROUP BY salutationId"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let s of existing_salutations.map((s: any) => s.salutationId) as Array<string>) {
|
||||||
|
await queryRunner.manager.getRepository(salutation).save({ salutation: s });
|
||||||
|
}
|
||||||
|
|
||||||
|
const salutations = await queryRunner.manager.getRepository(salutation).find();
|
||||||
|
|
||||||
|
for (let salutation of salutations) {
|
||||||
|
await queryRunner.manager
|
||||||
|
.getRepository(member)
|
||||||
|
.createQueryBuilder("member")
|
||||||
|
.update({ salutationId: salutation.id })
|
||||||
|
.where({ salutationId: salutation.salutation })
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`member\` CHANGE \`salutationId\` \`salutationId\` ${variableType_int} NOT NULL`
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.createForeignKey(
|
||||||
|
"member",
|
||||||
|
new TableForeignKey({
|
||||||
|
columnNames: ["salutationId"],
|
||||||
|
referencedColumnNames: ["id"],
|
||||||
|
referencedTableName: "salutation",
|
||||||
|
onDelete: "RESTRICT",
|
||||||
|
onUpdate: "RESTRICT",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const table = await queryRunner.getTable("member");
|
||||||
|
const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("salutationId") !== -1);
|
||||||
|
await queryRunner.dropForeignKey("member", foreignKey);
|
||||||
|
|
||||||
|
// ! has to be sql. Else the column would be dropped and created - resulting in data loss.
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`member\` CHANGE \`salutationId\` \`salutationId\` varchar(255) NOT NULL DEFAULT ''`
|
||||||
|
);
|
||||||
|
|
||||||
|
const salutations = await queryRunner.manager.getRepository(salutation).find();
|
||||||
|
|
||||||
|
for (let salutation of salutations) {
|
||||||
|
await queryRunner.manager
|
||||||
|
.getRepository(member)
|
||||||
|
.createQueryBuilder("member")
|
||||||
|
.update({ salutationId: salutation.salutation as unknown as number })
|
||||||
|
.where({ salutationId: salutation.id })
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE \`member\` CHANGE \`salutationId\` \`salutation\` varchar(255) NOT NULL DEFAULT 'none'`
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.dropTable("webapi");
|
||||||
|
}
|
||||||
|
}
|
229
src/migrations/1737800468938-updateViews.ts
Normal file
229
src/migrations/1737800468938-updateViews.ts
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
import { DataSource, MigrationInterface, QueryRunner, View } from "typeorm";
|
||||||
|
import { member } from "../entity/club/member/member";
|
||||||
|
import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions";
|
||||||
|
import { memberQualifications } from "../entity/club/member/memberQualifications";
|
||||||
|
import { membership } from "../entity/club/member/membership";
|
||||||
|
|
||||||
|
export class UpdateViews1737800468938 implements MigrationInterface {
|
||||||
|
name = "UpdateViews1737800468938";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
// await queryRunner.dropView("membership_view");
|
||||||
|
// await queryRunner.dropView("member_executive_positions_view");
|
||||||
|
// await queryRunner.dropView("member_qualifications_view");
|
||||||
|
// await queryRunner.dropView("member_view");
|
||||||
|
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "member_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(member)
|
||||||
|
.createQueryBuilder("member")
|
||||||
|
.select("member.id", "id")
|
||||||
|
.addSelect("member.firstname", "firstname")
|
||||||
|
.addSelect("member.lastname", "lastname")
|
||||||
|
.addSelect("member.nameaffix", "nameaffix")
|
||||||
|
.addSelect("member.birthdate", "birthdate")
|
||||||
|
.addSelect("salutation.salutation", "salutation")
|
||||||
|
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||||
|
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||||
|
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge")
|
||||||
|
.leftJoin("member.salutation", "salutation"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "member_executive_positions_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(memberExecutivePositions)
|
||||||
|
.createQueryBuilder("memberExecutivePositions")
|
||||||
|
.select("executivePosition.id", "positionId")
|
||||||
|
.addSelect("executivePosition.position", "position")
|
||||||
|
.addSelect("member.id", "memberId")
|
||||||
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
|
.addSelect("member.lastname", "memberLastname")
|
||||||
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect("salutation.salutation", "memberSalutation")
|
||||||
|
.addSelect(
|
||||||
|
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||||
|
"durationInDays"
|
||||||
|
)
|
||||||
|
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||||
|
.leftJoin("memberExecutivePositions.member", "member")
|
||||||
|
.leftJoin("member.salutation", "salutation")
|
||||||
|
.groupBy("executivePosition.id")
|
||||||
|
.addGroupBy("member.id"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "member_qualifications_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(memberQualifications)
|
||||||
|
.createQueryBuilder("memberQualifications")
|
||||||
|
.select("qualification.id", "qualificationId")
|
||||||
|
.addSelect("qualification.qualification", "qualification")
|
||||||
|
.addSelect("member.id", "memberId")
|
||||||
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
|
.addSelect("member.lastname", "memberLastname")
|
||||||
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect("salutation.salutation", "memberSalutation")
|
||||||
|
.addSelect(
|
||||||
|
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||||
|
"durationInDays"
|
||||||
|
)
|
||||||
|
.leftJoin("memberQualifications.qualification", "qualification")
|
||||||
|
.leftJoin("memberQualifications.member", "member")
|
||||||
|
.leftJoin("member.salutation", "salutation")
|
||||||
|
.groupBy("qualification.id")
|
||||||
|
.addGroupBy("member.id"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "membership_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(membership)
|
||||||
|
.createQueryBuilder("membership")
|
||||||
|
.select("status.id", "statusId")
|
||||||
|
.addSelect("status.status", "status")
|
||||||
|
.addSelect("member.id", "memberId")
|
||||||
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
|
.addSelect("member.lastname", "memberLastname")
|
||||||
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect("salutation.salutation", "memberSalutation")
|
||||||
|
.addSelect(
|
||||||
|
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||||
|
"durationInDays"
|
||||||
|
)
|
||||||
|
.addSelect(
|
||||||
|
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||||
|
"durationInYears"
|
||||||
|
)
|
||||||
|
.leftJoin("membership.status", "status")
|
||||||
|
.leftJoin("membership.member", "member")
|
||||||
|
.leftJoin("member.salutation", "salutation")
|
||||||
|
.groupBy("status.id")
|
||||||
|
.addGroupBy("member.id"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.dropView("membership_view");
|
||||||
|
await queryRunner.dropView("member_executive_positions_view");
|
||||||
|
await queryRunner.dropView("member_qualifications_view");
|
||||||
|
await queryRunner.dropView("member_view");
|
||||||
|
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "member_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(member)
|
||||||
|
.createQueryBuilder("member")
|
||||||
|
.select("member.id", "id")
|
||||||
|
.addSelect("member.salutation", "salutation")
|
||||||
|
.addSelect("member.firstname", "firstname")
|
||||||
|
.addSelect("member.lastname", "lastname")
|
||||||
|
.addSelect("member.nameaffix", "nameaffix")
|
||||||
|
.addSelect("member.birthdate", "birthdate")
|
||||||
|
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||||
|
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||||
|
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "member_executive_positions_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(memberExecutivePositions)
|
||||||
|
.createQueryBuilder("memberExecutivePositions")
|
||||||
|
.select("executivePosition.id", "positionId")
|
||||||
|
.addSelect("executivePosition.position", "position")
|
||||||
|
.addSelect("member.id", "memberId")
|
||||||
|
.addSelect("member.salutation", "memberSalutation")
|
||||||
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
|
.addSelect("member.lastname", "memberLastname")
|
||||||
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect(
|
||||||
|
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||||
|
"durationInDays"
|
||||||
|
)
|
||||||
|
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||||
|
.leftJoin("memberExecutivePositions.member", "member")
|
||||||
|
.groupBy("executivePosition.id"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "member_qualifications_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(memberQualifications)
|
||||||
|
.createQueryBuilder("memberQualifications")
|
||||||
|
.select("qualification.id", "qualificationId")
|
||||||
|
.addSelect("qualification.qualification", "qualification")
|
||||||
|
.addSelect("member.id", "memberId")
|
||||||
|
.addSelect("member.salutation", "memberSalutation")
|
||||||
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
|
.addSelect("member.lastname", "memberLastname")
|
||||||
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect(
|
||||||
|
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||||
|
"durationInDays"
|
||||||
|
)
|
||||||
|
.leftJoin("memberQualifications.qualification", "qualification")
|
||||||
|
.leftJoin("memberQualifications.member", "member")
|
||||||
|
.groupBy("qualification.id"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await queryRunner.createView(
|
||||||
|
new View({
|
||||||
|
name: "membership_view",
|
||||||
|
expression: (datasource: DataSource) =>
|
||||||
|
datasource
|
||||||
|
.getRepository(membership)
|
||||||
|
.createQueryBuilder("membership")
|
||||||
|
.select("status.id", "statusId")
|
||||||
|
.addSelect("status.status", "status")
|
||||||
|
.addSelect("member.id", "memberId")
|
||||||
|
.addSelect("member.salutation", "memberSalutation")
|
||||||
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
|
.addSelect("member.lastname", "memberLastname")
|
||||||
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect(
|
||||||
|
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||||
|
"durationInDays"
|
||||||
|
)
|
||||||
|
.addSelect(
|
||||||
|
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||||
|
"durationInYears"
|
||||||
|
)
|
||||||
|
.leftJoin("membership.status", "status")
|
||||||
|
.leftJoin("membership.member", "member")
|
||||||
|
.groupBy("status.id")
|
||||||
|
.addGroupBy("member.id"),
|
||||||
|
}),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import communicationType from "./settings/communicationType";
|
||||||
import executivePosition from "./settings/executivePosition";
|
import executivePosition from "./settings/executivePosition";
|
||||||
import membershipStatus from "./settings/membershipStatus";
|
import membershipStatus from "./settings/membershipStatus";
|
||||||
import qualification from "./settings/qualification";
|
import qualification from "./settings/qualification";
|
||||||
|
import salutation from "./settings/salutation";
|
||||||
import calendarType from "./settings/calendarType";
|
import calendarType from "./settings/calendarType";
|
||||||
import queryStore from "./settings/queryStore";
|
import queryStore from "./settings/queryStore";
|
||||||
import template from "./settings/template";
|
import template from "./settings/template";
|
||||||
|
@ -43,6 +44,7 @@ router.use(
|
||||||
membershipStatus
|
membershipStatus
|
||||||
);
|
);
|
||||||
router.use("/qualification", PermissionHelper.passCheckMiddleware("read", "settings", "qualification"), qualification);
|
router.use("/qualification", PermissionHelper.passCheckMiddleware("read", "settings", "qualification"), qualification);
|
||||||
|
router.use("/salutation", PermissionHelper.passCheckMiddleware("read", "settings", "salutation"), salutation);
|
||||||
router.use("/calendartype", PermissionHelper.passCheckMiddleware("read", "settings", "calendar_type"), calendarType);
|
router.use("/calendartype", PermissionHelper.passCheckMiddleware("read", "settings", "calendar_type"), calendarType);
|
||||||
router.use("/querystore", PermissionHelper.passCheckMiddleware("read", "settings", "query_store"), queryStore);
|
router.use("/querystore", PermissionHelper.passCheckMiddleware("read", "settings", "query_store"), queryStore);
|
||||||
router.use("/template", PermissionHelper.passCheckMiddleware("read", "settings", "template"), template);
|
router.use("/template", PermissionHelper.passCheckMiddleware("read", "settings", "template"), template);
|
||||||
|
|
45
src/routes/admin/settings/salutation.ts
Normal file
45
src/routes/admin/settings/salutation.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import express, { Request, Response } from "express";
|
||||||
|
import {
|
||||||
|
createSalutation,
|
||||||
|
deleteSalutation,
|
||||||
|
getAllSalutations,
|
||||||
|
getSalutationById,
|
||||||
|
updateSalutation,
|
||||||
|
} from "../../../controller/admin/settings/salutationController";
|
||||||
|
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||||
|
|
||||||
|
var router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
|
router.get("/", async (req: Request, res: Response) => {
|
||||||
|
await getAllSalutations(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/:id", async (req: Request, res: Response) => {
|
||||||
|
await getSalutationById(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
"/",
|
||||||
|
PermissionHelper.passCheckMiddleware("create", "settings", "salutation"),
|
||||||
|
async (req: Request, res: Response) => {
|
||||||
|
await createSalutation(req, res);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
router.patch(
|
||||||
|
"/:id",
|
||||||
|
PermissionHelper.passCheckMiddleware("update", "settings", "salutation"),
|
||||||
|
async (req: Request, res: Response) => {
|
||||||
|
await updateSalutation(req, res);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
router.delete(
|
||||||
|
"/:id",
|
||||||
|
PermissionHelper.passCheckMiddleware("delete", "settings", "salutation"),
|
||||||
|
async (req: Request, res: Response) => {
|
||||||
|
await deleteSalutation(req, res);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default router;
|
|
@ -14,10 +14,11 @@ import auth from "./auth";
|
||||||
import admin from "./admin/index";
|
import admin from "./admin/index";
|
||||||
import user from "./user";
|
import user from "./user";
|
||||||
import detectPWA from "../middleware/detectPWA";
|
import detectPWA from "../middleware/detectPWA";
|
||||||
import api from "./webapi";
|
import webapi from "./webapi";
|
||||||
import authenticateAPI from "../middleware/authenticateAPI";
|
import authenticateAPI from "../middleware/authenticateAPI";
|
||||||
import server from "./server";
|
import server from "./server";
|
||||||
import PermissionHelper from "../helpers/permissionHelper";
|
import PermissionHelper from "../helpers/permissionHelper";
|
||||||
|
import preventWebapiAccess from "../middleware/preventWebApiAccess";
|
||||||
|
|
||||||
export default (app: Express) => {
|
export default (app: Express) => {
|
||||||
app.set("query parser", "extended");
|
app.set("query parser", "extended");
|
||||||
|
@ -32,14 +33,14 @@ export default (app: Express) => {
|
||||||
|
|
||||||
app.use(detectPWA);
|
app.use(detectPWA);
|
||||||
app.use("/api/public", publicAvailable);
|
app.use("/api/public", publicAvailable);
|
||||||
app.use("/api/setup", allowSetup, setup);
|
app.use("/api/setup", preventWebapiAccess, allowSetup, setup);
|
||||||
app.use("/api/reset", reset);
|
app.use("/api/reset", preventWebapiAccess, reset);
|
||||||
app.use("/api/invite", invite);
|
app.use("/api/invite", preventWebapiAccess, invite);
|
||||||
app.use("/api/auth", auth);
|
app.use("/api/auth", preventWebapiAccess, auth);
|
||||||
app.use("/api/webapi", authenticateAPI, api);
|
app.use("/api/webapi", authenticateAPI, webapi);
|
||||||
app.use(authenticate);
|
app.use(authenticate);
|
||||||
app.use("/api/admin", admin);
|
app.use("/api/admin", admin);
|
||||||
app.use("/api/user", user);
|
app.use("/api/user", preventWebapiAccess, user);
|
||||||
app.use("/api/server", PermissionHelper.isAdminMiddleware(), server);
|
app.use("/api/server", preventWebapiAccess, PermissionHelper.isAdminMiddleware(), server);
|
||||||
app.use(errorHandler);
|
app.use(errorHandler);
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,7 +49,8 @@ export default abstract class MemberService {
|
||||||
)
|
)
|
||||||
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
||||||
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
||||||
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming");
|
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
|
||||||
|
.leftJoinAndSelect("member.salutation", "salutation");
|
||||||
|
|
||||||
if (search != "") {
|
if (search != "") {
|
||||||
search.split(" ").forEach((term, index) => {
|
search.split(" ").forEach((term, index) => {
|
||||||
|
@ -68,7 +69,7 @@ export default abstract class MemberService {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ids.length != 0) {
|
if (ids.length != 0) {
|
||||||
query = query.where({ id: ids });
|
query = query.where("member.id IN (:...ids)", { ids: ids });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noLimit) {
|
if (!noLimit) {
|
||||||
|
@ -123,6 +124,7 @@ export default abstract class MemberService {
|
||||||
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
||||||
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
|
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
|
||||||
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
||||||
|
.leftJoinAndSelect("member.salutation", "salutation")
|
||||||
.where("member.id = :id", { id: id })
|
.where("member.id = :id", { id: id })
|
||||||
.getOneOrFail()
|
.getOneOrFail()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
|
41
src/service/settings/salutationService.ts
Normal file
41
src/service/settings/salutationService.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { dataSource } from "../../data-source";
|
||||||
|
import { salutation } from "../../entity/settings/salutation";
|
||||||
|
import InternalException from "../../exceptions/internalException";
|
||||||
|
|
||||||
|
export default abstract class SalutationService {
|
||||||
|
/**
|
||||||
|
* @description get all salutations
|
||||||
|
* @returns {Promise<Array<salutation>>}
|
||||||
|
*/
|
||||||
|
static async getAll(): Promise<Array<salutation>> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(salutation)
|
||||||
|
.createQueryBuilder("salutation")
|
||||||
|
.orderBy("salutation", "ASC")
|
||||||
|
.getMany()
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("salutations not found", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description get salutation by id
|
||||||
|
* @returns {Promise<salutation>}
|
||||||
|
*/
|
||||||
|
static async getById(id: number): Promise<salutation> {
|
||||||
|
return await dataSource
|
||||||
|
.getRepository(salutation)
|
||||||
|
.createQueryBuilder("salutation")
|
||||||
|
.where("salutation.id = :id", { id: id })
|
||||||
|
.getOneOrFail()
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new InternalException("salutation not found by id", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ export type PermissionModule =
|
||||||
| "executive_position"
|
| "executive_position"
|
||||||
| "communication_type"
|
| "communication_type"
|
||||||
| "membership_status"
|
| "membership_status"
|
||||||
|
| "salutation"
|
||||||
| "calendar_type"
|
| "calendar_type"
|
||||||
| "user"
|
| "user"
|
||||||
| "role"
|
| "role"
|
||||||
|
@ -53,6 +54,7 @@ export const permissionModules: Array<PermissionModule> = [
|
||||||
"executive_position",
|
"executive_position",
|
||||||
"communication_type",
|
"communication_type",
|
||||||
"membership_status",
|
"membership_status",
|
||||||
|
"salutation",
|
||||||
"calendar_type",
|
"calendar_type",
|
||||||
"user",
|
"user",
|
||||||
"role",
|
"role",
|
||||||
|
@ -71,6 +73,7 @@ export const sectionsAndModules: SectionsAndModulesObject = {
|
||||||
"executive_position",
|
"executive_position",
|
||||||
"communication_type",
|
"communication_type",
|
||||||
"membership_status",
|
"membership_status",
|
||||||
|
"salutation",
|
||||||
"calendar_type",
|
"calendar_type",
|
||||||
"query_store",
|
"query_store",
|
||||||
"template",
|
"template",
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Salutation } from "../../../../enums/salutation";
|
import { SalutationViewModel } from "../../settings/salutation.models";
|
||||||
import { CommunicationViewModel } from "./communication.models";
|
import { CommunicationViewModel } from "./communication.models";
|
||||||
import { MembershipViewModel } from "./membership.models";
|
import { MembershipViewModel } from "./membership.models";
|
||||||
|
|
||||||
export interface MemberViewModel {
|
export interface MemberViewModel {
|
||||||
id: number;
|
id: number;
|
||||||
salutation: Salutation;
|
salutation: SalutationViewModel;
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
|
@ -19,7 +19,7 @@ export interface MemberViewModel {
|
||||||
|
|
||||||
export interface MemberStatisticsViewModel {
|
export interface MemberStatisticsViewModel {
|
||||||
id: number;
|
id: number;
|
||||||
salutation: Salutation;
|
salutation: string;
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { Salutation } from "../../../../enums/salutation";
|
|
||||||
|
|
||||||
export interface MembershipViewModel {
|
export interface MembershipViewModel {
|
||||||
id: number;
|
id: number;
|
||||||
start: Date;
|
start: Date;
|
||||||
|
@ -15,7 +13,7 @@ export interface MembershipStatisticsViewModel {
|
||||||
status: string;
|
status: string;
|
||||||
statusId: number;
|
statusId: number;
|
||||||
memberId: number;
|
memberId: number;
|
||||||
memberSalutation: Salutation;
|
memberSalutation: string;
|
||||||
memberFirstname: string;
|
memberFirstname: string;
|
||||||
memberLastname: string;
|
memberLastname: string;
|
||||||
memberNameaffix: string;
|
memberNameaffix: string;
|
||||||
|
|
4
src/viewmodel/admin/settings/salutation.models.ts
Normal file
4
src/viewmodel/admin/settings/salutation.models.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export interface SalutationViewModel {
|
||||||
|
id: number;
|
||||||
|
salutation: string;
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
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 { Salutation } from "../enums/salutation";
|
|
||||||
|
|
||||||
@ViewEntity({
|
@ViewEntity({
|
||||||
expression: (datasource: DataSource) =>
|
expression: (datasource: DataSource) =>
|
||||||
|
@ -10,18 +9,20 @@ import { Salutation } from "../enums/salutation";
|
||||||
.select("executivePosition.id", "positionId")
|
.select("executivePosition.id", "positionId")
|
||||||
.addSelect("executivePosition.position", "position")
|
.addSelect("executivePosition.position", "position")
|
||||||
.addSelect("member.id", "memberId")
|
.addSelect("member.id", "memberId")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
.addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect("salutation.salutation", "memberSalutation")
|
||||||
.addSelect(
|
.addSelect(
|
||||||
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||||
"durationInDays"
|
"durationInDays"
|
||||||
)
|
)
|
||||||
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||||
.leftJoin("memberExecutivePositions.member", "member")
|
.leftJoin("memberExecutivePositions.member", "member")
|
||||||
.groupBy("executivePosition.id"),
|
.leftJoin("member.salutation", "salutation")
|
||||||
|
.groupBy("executivePosition.id")
|
||||||
|
.addGroupBy("member.id"),
|
||||||
})
|
})
|
||||||
export class memberExecutivePositionsView {
|
export class memberExecutivePositionsView {
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
|
@ -37,7 +38,7 @@ export class memberExecutivePositionsView {
|
||||||
memberId: number;
|
memberId: number;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
memberSalutation: Salutation;
|
memberSalutation: string;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
memberFirstname: string;
|
memberFirstname: string;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
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 { Salutation } from "../enums/salutation";
|
|
||||||
|
|
||||||
@ViewEntity({
|
@ViewEntity({
|
||||||
expression: (datasource: DataSource) =>
|
expression: (datasource: DataSource) =>
|
||||||
|
@ -10,18 +9,20 @@ import { Salutation } from "../enums/salutation";
|
||||||
.select("qualification.id", "qualificationId")
|
.select("qualification.id", "qualificationId")
|
||||||
.addSelect("qualification.qualification", "qualification")
|
.addSelect("qualification.qualification", "qualification")
|
||||||
.addSelect("member.id", "memberId")
|
.addSelect("member.id", "memberId")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
.addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect("salutation.salutation", "memberSalutation")
|
||||||
.addSelect(
|
.addSelect(
|
||||||
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||||
"durationInDays"
|
"durationInDays"
|
||||||
)
|
)
|
||||||
.leftJoin("memberQualifications.qualification", "qualification")
|
.leftJoin("memberQualifications.qualification", "qualification")
|
||||||
.leftJoin("memberQualifications.member", "member")
|
.leftJoin("memberQualifications.member", "member")
|
||||||
.groupBy("qualification.id"),
|
.leftJoin("member.salutation", "salutation")
|
||||||
|
.groupBy("qualification.id")
|
||||||
|
.addGroupBy("member.id"),
|
||||||
})
|
})
|
||||||
export class memberQualificationsView {
|
export class memberQualificationsView {
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
|
@ -37,7 +38,7 @@ export class memberQualificationsView {
|
||||||
memberId: number;
|
memberId: number;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
memberSalutation: Salutation;
|
memberSalutation: string;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
memberFirstname: string;
|
memberFirstname: string;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
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 { Salutation } from "../enums/salutation";
|
|
||||||
|
|
||||||
@ViewEntity({
|
@ViewEntity({
|
||||||
expression: (datasource: DataSource) =>
|
expression: (datasource: DataSource) =>
|
||||||
|
@ -8,21 +7,22 @@ import { Salutation } from "../enums/salutation";
|
||||||
.getRepository(member)
|
.getRepository(member)
|
||||||
.createQueryBuilder("member")
|
.createQueryBuilder("member")
|
||||||
.select("member.id", "id")
|
.select("member.id", "id")
|
||||||
.addSelect("member.salutation", "salutation")
|
|
||||||
.addSelect("member.firstname", "firstname")
|
.addSelect("member.firstname", "firstname")
|
||||||
.addSelect("member.lastname", "lastname")
|
.addSelect("member.lastname", "lastname")
|
||||||
.addSelect("member.nameaffix", "nameaffix")
|
.addSelect("member.nameaffix", "nameaffix")
|
||||||
.addSelect("member.birthdate", "birthdate")
|
.addSelect("member.birthdate", "birthdate")
|
||||||
|
.addSelect("salutation.salutation", "salutation")
|
||||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge")
|
||||||
|
.leftJoin("member.salutation", "salutation"),
|
||||||
})
|
})
|
||||||
export class memberView {
|
export class memberView {
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
salutation: Salutation;
|
salutation: string;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
firstname: string;
|
firstname: string;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
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 { Salutation } from "../enums/salutation";
|
|
||||||
|
|
||||||
@ViewEntity({
|
@ViewEntity({
|
||||||
expression: (datasource: DataSource) =>
|
expression: (datasource: DataSource) =>
|
||||||
|
@ -10,11 +9,11 @@ import { Salutation } from "../enums/salutation";
|
||||||
.select("status.id", "statusId")
|
.select("status.id", "statusId")
|
||||||
.addSelect("status.status", "status")
|
.addSelect("status.status", "status")
|
||||||
.addSelect("member.id", "memberId")
|
.addSelect("member.id", "memberId")
|
||||||
.addSelect("member.salutation", "memberSalutation")
|
|
||||||
.addSelect("member.firstname", "memberFirstname")
|
.addSelect("member.firstname", "memberFirstname")
|
||||||
.addSelect("member.lastname", "memberLastname")
|
.addSelect("member.lastname", "memberLastname")
|
||||||
.addSelect("member.nameaffix", "memberNameaffix")
|
.addSelect("member.nameaffix", "memberNameaffix")
|
||||||
.addSelect("member.birthdate", "memberBirthdate")
|
.addSelect("member.birthdate", "memberBirthdate")
|
||||||
|
.addSelect("salutation.salutation", "memberSalutation")
|
||||||
.addSelect("SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))", "durationInDays")
|
.addSelect("SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))", "durationInDays")
|
||||||
.addSelect(
|
.addSelect(
|
||||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||||
|
@ -22,6 +21,7 @@ import { Salutation } from "../enums/salutation";
|
||||||
)
|
)
|
||||||
.leftJoin("membership.status", "status")
|
.leftJoin("membership.status", "status")
|
||||||
.leftJoin("membership.member", "member")
|
.leftJoin("membership.member", "member")
|
||||||
|
.leftJoin("member.salutation", "salutation")
|
||||||
.groupBy("status.id")
|
.groupBy("status.id")
|
||||||
.addGroupBy("member.id"),
|
.addGroupBy("member.id"),
|
||||||
})
|
})
|
||||||
|
@ -42,7 +42,7 @@ export class membershipView {
|
||||||
memberId: number;
|
memberId: number;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
memberSalutation: Salutation;
|
memberSalutation: string;
|
||||||
|
|
||||||
@ViewColumn()
|
@ViewColumn()
|
||||||
memberFirstname: string;
|
memberFirstname: string;
|
||||||
|
|
Loading…
Reference in a new issue