#25-cleanup-&-enhancements #26

Merged
jkeffects merged 4 commits from #25-cleanup-&-enhancements into main 2025-01-02 17:37:19 +00:00
17 changed files with 101 additions and 20 deletions
Showing only changes of commit 0d2c7dd7f1 - Show all commits

View file

@ -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 {

View file

@ -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()

View file

@ -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;

View file

@ -8,11 +8,11 @@ import { CreateMembershipCommand, DeleteMembershipCommand, UpdateMembershipComma
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,7 +20,6 @@ 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(member) .getRepository(member)
@ -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) => {

View file

@ -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,

View file

@ -62,6 +62,7 @@ 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 { 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,
@ -134,6 +135,7 @@ const dataSource = new DataSource({
Newsletter1735118780511, Newsletter1735118780511,
NewsletterConfig1735207446910, NewsletterConfig1735207446910,
TemplateMargins1735733514043, TemplateMargins1735733514043,
InternalId1735822722235,
], ],
migrationsRun: true, migrationsRun: true,
migrationsTransactionMode: "each", migrationsTransactionMode: "each",

View file

@ -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[];

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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,

View file

@ -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,

View 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");
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;