Intermediate: Merge pull request '#25-cleanup-&-enhancements' (#26) from #25-cleanup-&-enhancements into main
Reviewed-on: Ehrenamt/member-administration-server#26
This commit is contained in:
commit
9afb205da5
31 changed files with 188 additions and 50 deletions
|
@ -17,3 +17,4 @@ MAIL_PORT = mail_portnumber
|
||||||
MAIL_SECURE (true|false) // true for port 465, fals for other ports
|
MAIL_SECURE (true|false) // true for port 465, fals for other ports
|
||||||
|
|
||||||
CLUB_NAME = clubname
|
CLUB_NAME = clubname
|
||||||
|
CLUB_WEBSITE = https://my-club-website-url
|
|
@ -37,6 +37,7 @@ services:
|
||||||
- MAIL_PORT=<port>
|
- MAIL_PORT=<port>
|
||||||
- MAIL_SECURE=<boolean>
|
- MAIL_SECURE=<boolean>
|
||||||
- CLUB_NAME=<tobemodified>
|
- CLUB_NAME=<tobemodified>
|
||||||
|
- CLUB_WEBSITE=<tobemodified>
|
||||||
volumes:
|
volumes:
|
||||||
- <volume|local path>:/app/export
|
- <volume|local path>:/app/export
|
||||||
networks:
|
networks:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
import { award } from "../entity/award";
|
import { award } from "../entity/award";
|
||||||
|
import { member } from "../entity/member";
|
||||||
import { memberAwards } from "../entity/memberAwards";
|
import { memberAwards } from "../entity/memberAwards";
|
||||||
import { user } from "../entity/user";
|
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import { CreateMemberAwardCommand, DeleteMemberAwardCommand, UpdateMemberAwardCommand } from "./memberAwardCommand";
|
import { CreateMemberAwardCommand, DeleteMemberAwardCommand, UpdateMemberAwardCommand } from "./memberAwardCommand";
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ export default abstract class MemberAwardCommandHandler {
|
||||||
note: createMemberAward.note,
|
note: createMemberAward.note,
|
||||||
date: createMemberAward.date,
|
date: createMemberAward.date,
|
||||||
member: await dataSource
|
member: await dataSource
|
||||||
.getRepository(user)
|
.getRepository(member)
|
||||||
.createQueryBuilder("user")
|
.createQueryBuilder("member")
|
||||||
.where("id = :id", { id: createMemberAward.memberId })
|
.where("id = :id", { id: createMemberAward.memberId })
|
||||||
.getOneOrFail(),
|
.getOneOrFail(),
|
||||||
award: await dataSource
|
award: await dataSource
|
||||||
|
|
|
@ -6,6 +6,7 @@ export interface CreateMemberCommand {
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
birthdate: Date;
|
birthdate: Date;
|
||||||
|
internalId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateMemberCommand {
|
export interface UpdateMemberCommand {
|
||||||
|
@ -15,6 +16,7 @@ export interface UpdateMemberCommand {
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
birthdate: Date;
|
birthdate: Date;
|
||||||
|
internalId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateMemberNewsletterCommand {
|
export interface UpdateMemberNewsletterCommand {
|
||||||
|
|
|
@ -27,6 +27,7 @@ export default abstract class MemberCommandHandler {
|
||||||
lastname: createMember.lastname,
|
lastname: createMember.lastname,
|
||||||
nameaffix: createMember.nameaffix,
|
nameaffix: createMember.nameaffix,
|
||||||
birthdate: createMember.birthdate,
|
birthdate: createMember.birthdate,
|
||||||
|
internalId: createMember.internalId,
|
||||||
})
|
})
|
||||||
.execute()
|
.execute()
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
@ -53,6 +54,7 @@ export default abstract class MemberCommandHandler {
|
||||||
lastname: updateMember.lastname,
|
lastname: updateMember.lastname,
|
||||||
nameaffix: updateMember.nameaffix,
|
nameaffix: updateMember.nameaffix,
|
||||||
birthdate: updateMember.birthdate,
|
birthdate: updateMember.birthdate,
|
||||||
|
internalId: updateMember.internalId,
|
||||||
})
|
})
|
||||||
.where("id = :id", { id: updateMember.id })
|
.where("id = :id", { id: updateMember.id })
|
||||||
.execute()
|
.execute()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
import { executivePosition } from "../entity/executivePosition";
|
import { executivePosition } from "../entity/executivePosition";
|
||||||
|
import { member } from "../entity/member";
|
||||||
import { memberExecutivePositions } from "../entity/memberExecutivePositions";
|
import { memberExecutivePositions } from "../entity/memberExecutivePositions";
|
||||||
import { user } from "../entity/user";
|
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import {
|
import {
|
||||||
CreateMemberExecutivePositionCommand,
|
CreateMemberExecutivePositionCommand,
|
||||||
|
@ -25,8 +25,8 @@ export default abstract class MemberExecutivePositionCommandHandler {
|
||||||
start: createMemberExecutivePosition.start,
|
start: createMemberExecutivePosition.start,
|
||||||
end: createMemberExecutivePosition.end,
|
end: createMemberExecutivePosition.end,
|
||||||
member: await dataSource
|
member: await dataSource
|
||||||
.getRepository(user)
|
.getRepository(member)
|
||||||
.createQueryBuilder("user")
|
.createQueryBuilder("member")
|
||||||
.where("id = :id", { id: createMemberExecutivePosition.memberId })
|
.where("id = :id", { id: createMemberExecutivePosition.memberId })
|
||||||
.getOneOrFail(),
|
.getOneOrFail(),
|
||||||
executivePosition: await dataSource
|
executivePosition: await dataSource
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
import { qualification } from "../entity/qualification";
|
import { qualification } from "../entity/qualification";
|
||||||
import { memberQualifications } from "../entity/memberQualifications";
|
import { memberQualifications } from "../entity/memberQualifications";
|
||||||
import { user } from "../entity/user";
|
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import {
|
import {
|
||||||
CreateMemberQualificationCommand,
|
CreateMemberQualificationCommand,
|
||||||
DeleteMemberQualificationCommand,
|
DeleteMemberQualificationCommand,
|
||||||
UpdateMemberQualificationCommand,
|
UpdateMemberQualificationCommand,
|
||||||
} from "./memberQualificationCommand";
|
} from "./memberQualificationCommand";
|
||||||
|
import { member } from "../entity/member";
|
||||||
|
|
||||||
export default abstract class MemberQualificationCommandHandler {
|
export default abstract class MemberQualificationCommandHandler {
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +24,8 @@ export default abstract class MemberQualificationCommandHandler {
|
||||||
note: createMemberQualification.note,
|
note: createMemberQualification.note,
|
||||||
start: createMemberQualification.start,
|
start: createMemberQualification.start,
|
||||||
member: await dataSource
|
member: await dataSource
|
||||||
.getRepository(user)
|
.getRepository(member)
|
||||||
.createQueryBuilder("user")
|
.createQueryBuilder("member")
|
||||||
.where("id = :id", { id: createMemberQualification.memberId })
|
.where("id = :id", { id: createMemberQualification.memberId })
|
||||||
.getOneOrFail(),
|
.getOneOrFail(),
|
||||||
qualification: await dataSource
|
qualification: await dataSource
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export interface CreateMembershipCommand {
|
export interface CreateMembershipCommand {
|
||||||
internalId?: string;
|
|
||||||
start: Date;
|
start: Date;
|
||||||
memberId: number;
|
memberId: number;
|
||||||
statusId: number;
|
statusId: number;
|
||||||
|
@ -7,7 +6,6 @@ export interface CreateMembershipCommand {
|
||||||
|
|
||||||
export interface UpdateMembershipCommand {
|
export interface UpdateMembershipCommand {
|
||||||
id: number;
|
id: number;
|
||||||
internalId?: string;
|
|
||||||
start: Date;
|
start: Date;
|
||||||
end?: Date;
|
end?: Date;
|
||||||
terminationReason?: string;
|
terminationReason?: string;
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { dataSource } from "../data-source";
|
import { dataSource } from "../data-source";
|
||||||
|
import { member } from "../entity/member";
|
||||||
import { membership } from "../entity/membership";
|
import { membership } from "../entity/membership";
|
||||||
import { membershipStatus } from "../entity/membershipStatus";
|
import { membershipStatus } from "../entity/membershipStatus";
|
||||||
import { user } from "../entity/user";
|
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import { CreateMembershipCommand, DeleteMembershipCommand, UpdateMembershipCommand } from "./membershipCommand";
|
import { CreateMembershipCommand, DeleteMembershipCommand, UpdateMembershipCommand } from "./membershipCommand";
|
||||||
|
|
||||||
export default abstract class MembershipCommandHandler {
|
export default abstract class MembershipCommandHandler {
|
||||||
/**
|
/**
|
||||||
* @description create membership
|
* @description create membership
|
||||||
* @param CreateMembershipCommand
|
* @param {CreateMembershipCommand} createMembership
|
||||||
* @returns {Promise<number>}
|
* @returns {Promise<number>}
|
||||||
*/
|
*/
|
||||||
static async create(createMembership: CreateMembershipCommand): Promise<number> {
|
static async create(createMembership: CreateMembershipCommand): Promise<number> {
|
||||||
let insertid = -1;
|
let insertId = -1;
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.transaction(async (manager) => {
|
.transaction(async (manager) => {
|
||||||
await manager
|
await manager
|
||||||
|
@ -20,11 +20,10 @@ export default abstract class MembershipCommandHandler {
|
||||||
.insert()
|
.insert()
|
||||||
.into(membership)
|
.into(membership)
|
||||||
.values({
|
.values({
|
||||||
internalId: createMembership.internalId,
|
|
||||||
start: createMembership.start,
|
start: createMembership.start,
|
||||||
member: await dataSource
|
member: await dataSource
|
||||||
.getRepository(user)
|
.getRepository(member)
|
||||||
.createQueryBuilder("user")
|
.createQueryBuilder("member")
|
||||||
.where("id = :id", { id: createMembership.memberId })
|
.where("id = :id", { id: createMembership.memberId })
|
||||||
.getOneOrFail(),
|
.getOneOrFail(),
|
||||||
status: await dataSource
|
status: await dataSource
|
||||||
|
@ -35,7 +34,7 @@ export default abstract class MembershipCommandHandler {
|
||||||
})
|
})
|
||||||
.execute()
|
.execute()
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
insertid = result.identifiers[0].id;
|
insertId = result.identifiers[0].id;
|
||||||
});
|
});
|
||||||
|
|
||||||
await manager
|
await manager
|
||||||
|
@ -43,14 +42,15 @@ export default abstract class MembershipCommandHandler {
|
||||||
.update(membership)
|
.update(membership)
|
||||||
.set({
|
.set({
|
||||||
end: createMembership.start,
|
end: createMembership.start,
|
||||||
|
terminationReason: "beendet durch neuen Eintrag.",
|
||||||
})
|
})
|
||||||
.where("end IS NULL")
|
.where("end IS NULL")
|
||||||
.andWhere("memberId = :memberId", { memberId: createMembership.memberId })
|
.andWhere("memberId = :memberId", { memberId: createMembership.memberId })
|
||||||
.andWhere("id <> :id", { id: insertid })
|
.andWhere("id <> :id", { id: insertId })
|
||||||
.execute();
|
.execute();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return insertid;
|
return insertId;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw new InternalException("Failed creating membership", err);
|
throw new InternalException("Failed creating membership", err);
|
||||||
|
@ -59,7 +59,7 @@ export default abstract class MembershipCommandHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description update membership
|
* @description update membership
|
||||||
* @param UpdateMembershipCommand
|
* @param {UpdateMembershipCommand} updateMembership
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
static async update(updateMembership: UpdateMembershipCommand): Promise<void> {
|
static async update(updateMembership: UpdateMembershipCommand): Promise<void> {
|
||||||
|
@ -67,7 +67,6 @@ export default abstract class MembershipCommandHandler {
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.update(membership)
|
.update(membership)
|
||||||
.set({
|
.set({
|
||||||
internalId: updateMembership.internalId,
|
|
||||||
start: updateMembership.start,
|
start: updateMembership.start,
|
||||||
end: updateMembership.end,
|
end: updateMembership.end,
|
||||||
terminationReason: updateMembership.terminationReason,
|
terminationReason: updateMembership.terminationReason,
|
||||||
|
@ -88,16 +87,16 @@ export default abstract class MembershipCommandHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description delete membership
|
* @description delete membership
|
||||||
* @param DeleteMembershipCommand
|
* @param {DeleteMembershipCommand} deleteMembership
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
static async delete(deletMembership: DeleteMembershipCommand): Promise<void> {
|
static async delete(deleteMembership: DeleteMembershipCommand): Promise<void> {
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.delete()
|
.delete()
|
||||||
.from(membership)
|
.from(membership)
|
||||||
.where("id = :id", { id: deletMembership.id })
|
.where("id = :id", { id: deleteMembership.id })
|
||||||
.andWhere("memberId = :memberId", { memberId: deletMembership.memberId })
|
.andWhere("memberId = :memberId", { memberId: deleteMembership.memberId })
|
||||||
.execute()
|
.execute()
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|
|
@ -3,4 +3,6 @@ export interface UpdateTemplateUsageCommand {
|
||||||
headerId: number | null;
|
headerId: number | null;
|
||||||
bodyId: number | null;
|
bodyId: number | null;
|
||||||
footerId: number | null;
|
footerId: number | null;
|
||||||
|
headerHeight: number | null;
|
||||||
|
footerHeight: number | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ export default abstract class TemplateUsageCommandHandler {
|
||||||
headerId: updateTemplateUsage.headerId,
|
headerId: updateTemplateUsage.headerId,
|
||||||
bodyId: updateTemplateUsage.bodyId,
|
bodyId: updateTemplateUsage.bodyId,
|
||||||
footerId: updateTemplateUsage.footerId,
|
footerId: updateTemplateUsage.footerId,
|
||||||
|
headerHeight: updateTemplateUsage.headerHeight,
|
||||||
|
footerHeight: updateTemplateUsage.footerHeight,
|
||||||
})
|
})
|
||||||
.where("scope = :scope", { scope: updateTemplateUsage.scope })
|
.where("scope = :scope", { scope: updateTemplateUsage.scope })
|
||||||
.execute()
|
.execute()
|
||||||
|
|
|
@ -228,6 +228,7 @@ export async function createMember(req: Request, res: Response): Promise<any> {
|
||||||
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;
|
||||||
|
|
||||||
let createMember: CreateMemberCommand = {
|
let createMember: CreateMemberCommand = {
|
||||||
salutation,
|
salutation,
|
||||||
|
@ -235,6 +236,7 @@ export async function createMember(req: Request, res: Response): Promise<any> {
|
||||||
lastname,
|
lastname,
|
||||||
nameaffix,
|
nameaffix,
|
||||||
birthdate,
|
birthdate,
|
||||||
|
internalId,
|
||||||
};
|
};
|
||||||
let memberId = await MemberCommandHandler.create(createMember);
|
let memberId = await MemberCommandHandler.create(createMember);
|
||||||
|
|
||||||
|
@ -249,12 +251,10 @@ export async function createMember(req: Request, res: Response): Promise<any> {
|
||||||
*/
|
*/
|
||||||
export async function addMembershipToMember(req: Request, res: Response): Promise<any> {
|
export async function addMembershipToMember(req: Request, res: Response): Promise<any> {
|
||||||
const memberId = parseInt(req.params.memberId);
|
const memberId = parseInt(req.params.memberId);
|
||||||
const internalId = req.body.internalId;
|
|
||||||
const start = req.body.start;
|
const start = req.body.start;
|
||||||
const statusId = req.body.statusId;
|
const statusId = req.body.statusId;
|
||||||
|
|
||||||
let createMembership: CreateMembershipCommand = {
|
let createMembership: CreateMembershipCommand = {
|
||||||
internalId,
|
|
||||||
start,
|
start,
|
||||||
memberId,
|
memberId,
|
||||||
statusId,
|
statusId,
|
||||||
|
@ -394,6 +394,7 @@ export async function updateMemberById(req: Request, res: Response): Promise<any
|
||||||
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;
|
||||||
|
|
||||||
let updateMember: UpdateMemberCommand = {
|
let updateMember: UpdateMemberCommand = {
|
||||||
id: memberId,
|
id: memberId,
|
||||||
|
@ -402,6 +403,7 @@ export async function updateMemberById(req: Request, res: Response): Promise<any
|
||||||
lastname,
|
lastname,
|
||||||
nameaffix,
|
nameaffix,
|
||||||
birthdate,
|
birthdate,
|
||||||
|
internalId,
|
||||||
};
|
};
|
||||||
await MemberCommandHandler.update(updateMember);
|
await MemberCommandHandler.update(updateMember);
|
||||||
|
|
||||||
|
@ -417,7 +419,6 @@ export async function updateMemberById(req: Request, res: Response): Promise<any
|
||||||
export async function updateMembershipOfMember(req: Request, res: Response): Promise<any> {
|
export async function updateMembershipOfMember(req: Request, res: Response): Promise<any> {
|
||||||
const memberId = parseInt(req.params.memberId);
|
const memberId = parseInt(req.params.memberId);
|
||||||
const recordId = parseInt(req.params.recordId);
|
const recordId = parseInt(req.params.recordId);
|
||||||
const internalId = req.body.internalId;
|
|
||||||
const start = req.body.start;
|
const start = req.body.start;
|
||||||
const end = req.body.end || null;
|
const end = req.body.end || null;
|
||||||
const terminationReason = req.body.terminationReason;
|
const terminationReason = req.body.terminationReason;
|
||||||
|
@ -425,7 +426,6 @@ export async function updateMembershipOfMember(req: Request, res: Response): Pro
|
||||||
|
|
||||||
let updateMembership: UpdateMembershipCommand = {
|
let updateMembership: UpdateMembershipCommand = {
|
||||||
id: recordId,
|
id: recordId,
|
||||||
internalId,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
terminationReason,
|
terminationReason,
|
||||||
|
|
|
@ -78,12 +78,16 @@ export async function updateTemplateUsage(req: Request, res: Response): Promise<
|
||||||
const headerId = req.body.headerId ?? null;
|
const headerId = req.body.headerId ?? null;
|
||||||
const bodyId = req.body.bodyId ?? null;
|
const bodyId = req.body.bodyId ?? null;
|
||||||
const footerId = req.body.footerId ?? null;
|
const footerId = req.body.footerId ?? null;
|
||||||
|
const headerHeight = req.body.headerHeight ?? null;
|
||||||
|
const footerHeight = req.body.footerHeight ?? null;
|
||||||
|
|
||||||
let updateTemplateUsage: UpdateTemplateUsageCommand = {
|
let updateTemplateUsage: UpdateTemplateUsageCommand = {
|
||||||
scope: scope,
|
scope: scope,
|
||||||
headerId: headerId,
|
headerId: headerId,
|
||||||
bodyId: bodyId,
|
bodyId: bodyId,
|
||||||
footerId: footerId,
|
footerId: footerId,
|
||||||
|
headerHeight: headerHeight,
|
||||||
|
footerHeight: footerHeight,
|
||||||
};
|
};
|
||||||
await TemplateUsageCommandHandler.update(updateTemplateUsage);
|
await TemplateUsageCommandHandler.update(updateTemplateUsage);
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,8 @@ import { newsletterRecipients } from "./entity/newsletterRecipients";
|
||||||
import { Newsletter1735118780511 } from "./migrations/1735118780511-newsletter";
|
import { Newsletter1735118780511 } from "./migrations/1735118780511-newsletter";
|
||||||
import { newsletterConfig } from "./entity/newsletterConfig";
|
import { newsletterConfig } from "./entity/newsletterConfig";
|
||||||
import { NewsletterConfig1735207446910 } from "./migrations/1735207446910-newsletterConfig";
|
import { NewsletterConfig1735207446910 } from "./migrations/1735207446910-newsletterConfig";
|
||||||
|
import { TemplateMargins1735733514043 } from "./migrations/1735733514043-templateMargins";
|
||||||
|
import { InternalId1735822722235 } from "./migrations/1735822722235-internalId";
|
||||||
|
|
||||||
const dataSource = new DataSource({
|
const dataSource = new DataSource({
|
||||||
type: DB_TYPE as any,
|
type: DB_TYPE as any,
|
||||||
|
@ -132,6 +134,8 @@ const dataSource = new DataSource({
|
||||||
TemplateUsage1734949173739,
|
TemplateUsage1734949173739,
|
||||||
Newsletter1735118780511,
|
Newsletter1735118780511,
|
||||||
NewsletterConfig1735207446910,
|
NewsletterConfig1735207446910,
|
||||||
|
TemplateMargins1735733514043,
|
||||||
|
InternalId1735822722235,
|
||||||
],
|
],
|
||||||
migrationsRun: true,
|
migrationsRun: true,
|
||||||
migrationsTransactionMode: "each",
|
migrationsTransactionMode: "each",
|
||||||
|
|
|
@ -39,6 +39,9 @@ export class member {
|
||||||
@Column({ type: "date" })
|
@Column({ type: "date" })
|
||||||
birthdate: Date;
|
birthdate: Date;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 255, unique: true, nullable: true })
|
||||||
|
internalId?: string;
|
||||||
|
|
||||||
@OneToMany(() => communication, (communications) => communications.member)
|
@OneToMany(() => communication, (communications) => communications.member)
|
||||||
communications: communication[];
|
communications: communication[];
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,12 @@ export class memberAwards {
|
||||||
@Column({ type: "date" })
|
@Column({ type: "date" })
|
||||||
date: Date;
|
date: Date;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
memberId: number;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
awardId: number;
|
||||||
|
|
||||||
@ManyToOne(() => member, (member) => member.awards, {
|
@ManyToOne(() => member, (member) => member.awards, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
|
|
|
@ -16,6 +16,12 @@ export class memberExecutivePositions {
|
||||||
@Column({ type: "date", nullable: true })
|
@Column({ type: "date", nullable: true })
|
||||||
end?: Date;
|
end?: Date;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
memberId: number;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
executivePositionId: number;
|
||||||
|
|
||||||
@ManyToOne(() => member, (member) => member.awards, {
|
@ManyToOne(() => member, (member) => member.awards, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
|
|
|
@ -19,6 +19,12 @@ export class memberQualifications {
|
||||||
@Column({ type: "varchar", length: 255, nullable: true })
|
@Column({ type: "varchar", length: 255, nullable: true })
|
||||||
terminationReason?: string;
|
terminationReason?: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
memberId: number;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
qualificationId: number;
|
||||||
|
|
||||||
@ManyToOne(() => member, (member) => member.awards, {
|
@ManyToOne(() => member, (member) => member.awards, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
|
|
|
@ -7,6 +7,9 @@ export class membership {
|
||||||
@PrimaryColumn({ generated: "increment", type: "int" })
|
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
@Column({ type: "varchar", length: 255, unique: true, nullable: true })
|
@Column({ type: "varchar", length: 255, unique: true, nullable: true })
|
||||||
internalId?: string;
|
internalId?: string;
|
||||||
|
|
||||||
|
@ -19,6 +22,12 @@ export class membership {
|
||||||
@Column({ type: "varchar", length: 255, nullable: true })
|
@Column({ type: "varchar", length: 255, nullable: true })
|
||||||
terminationReason?: string;
|
terminationReason?: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
memberId: number;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
statusId: number;
|
||||||
|
|
||||||
@ManyToOne(() => member, (member) => member.memberships, {
|
@ManyToOne(() => member, (member) => member.memberships, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
|
|
|
@ -7,15 +7,21 @@ export class templateUsage {
|
||||||
@PrimaryColumn({ type: "varchar", length: 255 })
|
@PrimaryColumn({ type: "varchar", length: 255 })
|
||||||
scope: PermissionModule;
|
scope: PermissionModule;
|
||||||
|
|
||||||
@Column({ type: "number", nullable: true })
|
@Column({ type: "int", nullable: true })
|
||||||
headerId: number | null;
|
headerId: number | null;
|
||||||
|
|
||||||
@Column({ type: "number", nullable: true })
|
@Column({ type: "int", nullable: true })
|
||||||
bodyId: number | null;
|
bodyId: number | null;
|
||||||
|
|
||||||
@Column({ type: "number", nullable: true })
|
@Column({ type: "int", nullable: true })
|
||||||
footerId: number | null;
|
footerId: number | null;
|
||||||
|
|
||||||
|
@Column({ type: "int", nullable: true })
|
||||||
|
headerHeight: number | null;
|
||||||
|
|
||||||
|
@Column({ type: "int", nullable: true })
|
||||||
|
footerHeight: number | null;
|
||||||
|
|
||||||
@ManyToOne(() => template, {
|
@ManyToOne(() => template, {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
onDelete: "RESTRICT",
|
onDelete: "RESTRICT",
|
||||||
|
|
|
@ -17,6 +17,7 @@ export default abstract class MemberFactory {
|
||||||
lastname: record?.lastname,
|
lastname: record?.lastname,
|
||||||
nameaffix: record?.nameaffix,
|
nameaffix: record?.nameaffix,
|
||||||
birthdate: record?.birthdate,
|
birthdate: record?.birthdate,
|
||||||
|
internalId: record.internalId,
|
||||||
firstMembershipEntry: record?.firstMembershipEntry
|
firstMembershipEntry: record?.firstMembershipEntry
|
||||||
? MembershipFactory.mapToSingle(record.firstMembershipEntry)
|
? MembershipFactory.mapToSingle(record.firstMembershipEntry)
|
||||||
: null,
|
: null,
|
||||||
|
|
|
@ -10,7 +10,6 @@ export default abstract class MembershipFactory {
|
||||||
public static mapToSingle(record: membership): MembershipViewModel {
|
public static mapToSingle(record: membership): MembershipViewModel {
|
||||||
return {
|
return {
|
||||||
id: record.id,
|
id: record.id,
|
||||||
internalId: record.internalId,
|
|
||||||
start: record.start,
|
start: record.start,
|
||||||
end: record.end,
|
end: record.end,
|
||||||
terminationReason: record.terminationReason,
|
terminationReason: record.terminationReason,
|
||||||
|
|
|
@ -13,6 +13,8 @@ export default abstract class TemplateUsageFactory {
|
||||||
header: record.header ? { id: record.header.id, template: record.header.template } : null,
|
header: record.header ? { id: record.header.id, template: record.header.template } : null,
|
||||||
body: record.body ? { id: record.body.id, template: record.body.template } : null,
|
body: record.body ? { id: record.body.id, template: record.body.template } : null,
|
||||||
footer: record.footer ? { id: record.footer.id, template: record.footer.template } : null,
|
footer: record.footer ? { id: record.footer.id, template: record.footer.template } : null,
|
||||||
|
headerHeight: record.headerHeight,
|
||||||
|
footerHeight: record.footerHeight,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ export abstract class PdfExport {
|
||||||
filename = null,
|
filename = null,
|
||||||
data = {},
|
data = {},
|
||||||
saveToDisk = true,
|
saveToDisk = true,
|
||||||
margins = { top: "15mm", bottom: "15mm" },
|
|
||||||
folder = "",
|
folder = "",
|
||||||
}: {
|
}: {
|
||||||
template: PermissionModule;
|
template: PermissionModule;
|
||||||
|
@ -19,12 +18,11 @@ export abstract class PdfExport {
|
||||||
filename?: string;
|
filename?: string;
|
||||||
data?: any;
|
data?: any;
|
||||||
saveToDisk?: boolean;
|
saveToDisk?: boolean;
|
||||||
margins?: { top: string; bottom: string };
|
|
||||||
folder?: string;
|
folder?: string;
|
||||||
}) {
|
}) {
|
||||||
if (folder != "") FileSystemHelper.createFolder(folder);
|
if (folder != "") FileSystemHelper.createFolder(folder);
|
||||||
|
|
||||||
const { header, footer, body } = await TemplateHelper.renderFileForModule({
|
const { header, footer, body, headerMargin, footerMargin } = await TemplateHelper.renderFileForModule({
|
||||||
module: template,
|
module: template,
|
||||||
headerData: data,
|
headerData: data,
|
||||||
bodyData: data,
|
bodyData: data,
|
||||||
|
@ -46,8 +44,8 @@ export abstract class PdfExport {
|
||||||
format: "A4",
|
format: "A4",
|
||||||
printBackground: false,
|
printBackground: false,
|
||||||
margin: {
|
margin: {
|
||||||
top: margins.top,
|
top: (headerMargin ?? 15) + "mm",
|
||||||
bottom: margins.bottom,
|
bottom: (footerMargin ?? 15) + "mm",
|
||||||
left: "10mm",
|
left: "10mm",
|
||||||
right: "10mm",
|
right: "10mm",
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import TemplateService from "../service/templateService";
|
import TemplateService from "../service/templateService";
|
||||||
import { PermissionModule } from "../type/permissionTypes";
|
import { PermissionModule } from "../type/permissionTypes";
|
||||||
import TemplateUsageService from "../service/templateUsageService";
|
import TemplateUsageService from "../service/templateUsageService";
|
||||||
import Handlebars from "handlebars";
|
import Handlebars, { template } from "handlebars";
|
||||||
import { FileSystemHelper } from "./fileSystemHelper";
|
import { FileSystemHelper } from "./fileSystemHelper";
|
||||||
|
|
||||||
export abstract class TemplateHelper {
|
export abstract class TemplateHelper {
|
||||||
|
@ -39,27 +39,27 @@ export abstract class TemplateHelper {
|
||||||
headerData?: any;
|
headerData?: any;
|
||||||
bodyData?: any;
|
bodyData?: any;
|
||||||
footerData?: any;
|
footerData?: any;
|
||||||
}): Promise<{ header: string; body: string; footer: string; margins?: { top: string; bottom: string } }> {
|
}): Promise<{ header: string; body: string; footer: string; headerMargin?: number; footerMargin?: number }> {
|
||||||
const moduleTemplates = await TemplateUsageService.getByScope(module);
|
const moduleTemplate = await TemplateUsageService.getByScope(module);
|
||||||
|
|
||||||
let header = `<h1 style="font-size:10px; text-align:center; width:100%;">${title}</h1>`;
|
let header = `<h1 style="font-size:10px; text-align:center; width:100%;">${title}</h1>`;
|
||||||
let footer = "";
|
let footer = "";
|
||||||
let body = "";
|
let body = "";
|
||||||
|
|
||||||
if (moduleTemplates.headerId) {
|
if (moduleTemplate.headerId) {
|
||||||
header = await this.getTemplateFromStore(moduleTemplates.headerId);
|
header = await this.getTemplateFromStore(moduleTemplate.headerId);
|
||||||
header = this.applyDataToTemplate(header, { title, ...headerData });
|
header = this.applyDataToTemplate(header, { title, ...headerData });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleTemplates.footerId) {
|
if (moduleTemplate.footerId) {
|
||||||
footer = await this.getTemplateFromStore(moduleTemplates.footerId);
|
footer = await this.getTemplateFromStore(moduleTemplate.footerId);
|
||||||
} else {
|
} else {
|
||||||
footer = this.getTemplateFromFile(module + ".footer");
|
footer = this.getTemplateFromFile(module + ".footer");
|
||||||
}
|
}
|
||||||
footer = this.applyDataToTemplate(footer, footerData);
|
footer = this.applyDataToTemplate(footer, footerData);
|
||||||
|
|
||||||
if (moduleTemplates.bodyId) {
|
if (moduleTemplate.bodyId) {
|
||||||
body = await this.getTemplateFromStore(moduleTemplates.bodyId);
|
body = await this.getTemplateFromStore(moduleTemplate.bodyId);
|
||||||
} else {
|
} else {
|
||||||
body = this.getTemplateFromFile(module + ".body");
|
body = this.getTemplateFromFile(module + ".body");
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ export abstract class TemplateHelper {
|
||||||
header,
|
header,
|
||||||
footer,
|
footer,
|
||||||
body,
|
body,
|
||||||
|
headerMargin: moduleTemplate.headerHeight,
|
||||||
|
footerMargin: moduleTemplate.footerHeight,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
35
src/migrations/1735733514043-templateMargins.ts
Normal file
35
src/migrations/1735733514043-templateMargins.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { MigrationInterface, QueryRunner, TableColumn } from "typeorm";
|
||||||
|
import { DB_TYPE } from "../env.defaults";
|
||||||
|
|
||||||
|
export class TemplateMargins1735733514043 implements MigrationInterface {
|
||||||
|
name = "TemplateMargins1735733514043";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const variableType_int = DB_TYPE == "mysql" ? "int" : "integer";
|
||||||
|
|
||||||
|
await queryRunner.addColumn(
|
||||||
|
"template_usage",
|
||||||
|
new TableColumn({
|
||||||
|
name: "headerHeight",
|
||||||
|
type: variableType_int,
|
||||||
|
default: null,
|
||||||
|
isNullable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.addColumn(
|
||||||
|
"template_usage",
|
||||||
|
new TableColumn({
|
||||||
|
name: "footerHeight",
|
||||||
|
type: variableType_int,
|
||||||
|
default: null,
|
||||||
|
isNullable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.dropColumn("template_usage", "footerHeight");
|
||||||
|
await queryRunner.dropColumn("template_usage", "headerHeight");
|
||||||
|
}
|
||||||
|
}
|
47
src/migrations/1735822722235-internalId.ts
Normal file
47
src/migrations/1735822722235-internalId.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { MigrationInterface, QueryRunner, TableColumn } from "typeorm";
|
||||||
|
import { membership } from "../entity/membership";
|
||||||
|
import { member } from "../entity/member";
|
||||||
|
|
||||||
|
export class InternalId1735822722235 implements MigrationInterface {
|
||||||
|
name = "InternalId1735822722235";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.addColumn(
|
||||||
|
"member",
|
||||||
|
new TableColumn({
|
||||||
|
name: "internalId",
|
||||||
|
type: "varchar",
|
||||||
|
length: "255",
|
||||||
|
default: null,
|
||||||
|
isNullable: true,
|
||||||
|
isUnique: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
let memberships = await queryRunner.manager.getRepository(membership).find();
|
||||||
|
console.log(memberships);
|
||||||
|
let internalIds = memberships.reduce<{ [key: number]: Array<string> }>((acc, cur) => {
|
||||||
|
let memberId = cur.memberId;
|
||||||
|
let setIds = acc[memberId] ?? [];
|
||||||
|
if (cur?.internalId) {
|
||||||
|
setIds.push(cur.internalId);
|
||||||
|
}
|
||||||
|
acc[memberId] = setIds;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
console.log(internalIds);
|
||||||
|
for (const [id, value] of Object.entries(internalIds)) {
|
||||||
|
const ids = value.filter((v) => v != null).join(", ");
|
||||||
|
if (ids) {
|
||||||
|
let m = await queryRunner.manager.getRepository(member).findOneByOrFail({ id: parseInt(id) });
|
||||||
|
m.internalId = ids;
|
||||||
|
await queryRunner.manager.getRepository(member).save(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.dropColumn("member", "internalId");
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ export default abstract class MembershipService {
|
||||||
.createQueryBuilder("membership")
|
.createQueryBuilder("membership")
|
||||||
.leftJoinAndSelect("membership.status", "membershipStatus")
|
.leftJoinAndSelect("membership.status", "membershipStatus")
|
||||||
.where("membership.memberId = :memberId", { memberId: memberId })
|
.where("membership.memberId = :memberId", { memberId: memberId })
|
||||||
|
.orderBy("membership.start", "DESC")
|
||||||
.getMany()
|
.getMany()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -9,6 +9,7 @@ export interface MemberViewModel {
|
||||||
lastname: string;
|
lastname: string;
|
||||||
nameaffix: string;
|
nameaffix: string;
|
||||||
birthdate: Date;
|
birthdate: Date;
|
||||||
|
internalId?: string;
|
||||||
firstMembershipEntry?: MembershipViewModel;
|
firstMembershipEntry?: MembershipViewModel;
|
||||||
lastMembershipEntry?: MembershipViewModel;
|
lastMembershipEntry?: MembershipViewModel;
|
||||||
sendNewsletter?: CommunicationViewModel;
|
sendNewsletter?: CommunicationViewModel;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
export interface MembershipViewModel {
|
export interface MembershipViewModel {
|
||||||
id: number;
|
id: number;
|
||||||
internalId?: string;
|
|
||||||
start: Date;
|
start: Date;
|
||||||
end?: Date;
|
end?: Date;
|
||||||
terminationReason?: string;
|
terminationReason?: string;
|
||||||
|
|
|
@ -5,4 +5,6 @@ export interface TemplateUsageViewModel {
|
||||||
header: { id: number; template: string } | null;
|
header: { id: number; template: string } | null;
|
||||||
body: { id: number; template: string } | null;
|
body: { id: number; template: string } | null;
|
||||||
footer: { id: number; template: string } | null;
|
footer: { id: number; template: string } | null;
|
||||||
|
headerHeight: number | null;
|
||||||
|
footerHeight: number | null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue