From 0d2c7dd7f173eac21a5b21217f8ebf84b5732cda Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Thu, 2 Jan 2025 17:08:53 +0100 Subject: [PATCH] internal Id to member --- src/command/memberCommand.ts | 2 + src/command/memberCommandHandler.ts | 2 + src/command/membershipCommand.ts | 2 - src/command/membershipCommandHandler.ts | 23 +++++------ src/controller/admin/memberController.ts | 8 ++-- src/data-source.ts | 2 + src/entity/member.ts | 3 ++ src/entity/memberAwards.ts | 6 +++ src/entity/memberExecutivePositions.ts | 6 +++ src/entity/memberQualifications.ts | 6 +++ src/entity/membership.ts | 9 +++++ src/factory/admin/member.ts | 1 + src/factory/admin/membership.ts | 1 - src/migrations/1735822722235-internalId.ts | 47 ++++++++++++++++++++++ src/service/membershipService.ts | 1 + src/viewmodel/admin/member.models.ts | 1 + src/viewmodel/admin/membership.models.ts | 1 - 17 files changed, 101 insertions(+), 20 deletions(-) create mode 100644 src/migrations/1735822722235-internalId.ts diff --git a/src/command/memberCommand.ts b/src/command/memberCommand.ts index 3dc61d3..a40de21 100644 --- a/src/command/memberCommand.ts +++ b/src/command/memberCommand.ts @@ -6,6 +6,7 @@ export interface CreateMemberCommand { lastname: string; nameaffix: string; birthdate: Date; + internalId?: string; } export interface UpdateMemberCommand { @@ -15,6 +16,7 @@ export interface UpdateMemberCommand { lastname: string; nameaffix: string; birthdate: Date; + internalId?: string; } export interface UpdateMemberNewsletterCommand { diff --git a/src/command/memberCommandHandler.ts b/src/command/memberCommandHandler.ts index 4c396cf..767a01f 100644 --- a/src/command/memberCommandHandler.ts +++ b/src/command/memberCommandHandler.ts @@ -27,6 +27,7 @@ export default abstract class MemberCommandHandler { lastname: createMember.lastname, nameaffix: createMember.nameaffix, birthdate: createMember.birthdate, + internalId: createMember.internalId, }) .execute() .then((result) => { @@ -53,6 +54,7 @@ export default abstract class MemberCommandHandler { lastname: updateMember.lastname, nameaffix: updateMember.nameaffix, birthdate: updateMember.birthdate, + internalId: updateMember.internalId, }) .where("id = :id", { id: updateMember.id }) .execute() diff --git a/src/command/membershipCommand.ts b/src/command/membershipCommand.ts index fcf429d..9e9ca25 100644 --- a/src/command/membershipCommand.ts +++ b/src/command/membershipCommand.ts @@ -1,5 +1,4 @@ export interface CreateMembershipCommand { - internalId?: string; start: Date; memberId: number; statusId: number; @@ -7,7 +6,6 @@ export interface CreateMembershipCommand { export interface UpdateMembershipCommand { id: number; - internalId?: string; start: Date; end?: Date; terminationReason?: string; diff --git a/src/command/membershipCommandHandler.ts b/src/command/membershipCommandHandler.ts index b38366a..35a5262 100644 --- a/src/command/membershipCommandHandler.ts +++ b/src/command/membershipCommandHandler.ts @@ -8,11 +8,11 @@ import { CreateMembershipCommand, DeleteMembershipCommand, UpdateMembershipComma export default abstract class MembershipCommandHandler { /** * @description create membership - * @param CreateMembershipCommand + * @param {CreateMembershipCommand} createMembership * @returns {Promise} */ static async create(createMembership: CreateMembershipCommand): Promise { - let insertid = -1; + let insertId = -1; return await dataSource .transaction(async (manager) => { await manager @@ -20,7 +20,6 @@ export default abstract class MembershipCommandHandler { .insert() .into(membership) .values({ - internalId: createMembership.internalId, start: createMembership.start, member: await dataSource .getRepository(member) @@ -35,7 +34,7 @@ export default abstract class MembershipCommandHandler { }) .execute() .then((result) => { - insertid = result.identifiers[0].id; + insertId = result.identifiers[0].id; }); await manager @@ -43,14 +42,15 @@ export default abstract class MembershipCommandHandler { .update(membership) .set({ end: createMembership.start, + terminationReason: "beendet durch neuen Eintrag.", }) .where("end IS NULL") .andWhere("memberId = :memberId", { memberId: createMembership.memberId }) - .andWhere("id <> :id", { id: insertid }) + .andWhere("id <> :id", { id: insertId }) .execute(); }) .then(() => { - return insertid; + return insertId; }) .catch((err) => { throw new InternalException("Failed creating membership", err); @@ -59,7 +59,7 @@ export default abstract class MembershipCommandHandler { /** * @description update membership - * @param UpdateMembershipCommand + * @param {UpdateMembershipCommand} updateMembership * @returns {Promise} */ static async update(updateMembership: UpdateMembershipCommand): Promise { @@ -67,7 +67,6 @@ export default abstract class MembershipCommandHandler { .createQueryBuilder() .update(membership) .set({ - internalId: updateMembership.internalId, start: updateMembership.start, end: updateMembership.end, terminationReason: updateMembership.terminationReason, @@ -88,16 +87,16 @@ export default abstract class MembershipCommandHandler { /** * @description delete membership - * @param DeleteMembershipCommand + * @param {DeleteMembershipCommand} deleteMembership * @returns {Promise} */ - static async delete(deletMembership: DeleteMembershipCommand): Promise { + static async delete(deleteMembership: DeleteMembershipCommand): Promise { return await dataSource .createQueryBuilder() .delete() .from(membership) - .where("id = :id", { id: deletMembership.id }) - .andWhere("memberId = :memberId", { memberId: deletMembership.memberId }) + .where("id = :id", { id: deleteMembership.id }) + .andWhere("memberId = :memberId", { memberId: deleteMembership.memberId }) .execute() .then(() => {}) .catch((err) => { diff --git a/src/controller/admin/memberController.ts b/src/controller/admin/memberController.ts index 6644568..8728311 100644 --- a/src/controller/admin/memberController.ts +++ b/src/controller/admin/memberController.ts @@ -228,6 +228,7 @@ export async function createMember(req: Request, res: Response): Promise { const lastname = req.body.lastname; const nameaffix = req.body.nameaffix; const birthdate = req.body.birthdate; + const internalId = req.body.internalId; let createMember: CreateMemberCommand = { salutation, @@ -235,6 +236,7 @@ export async function createMember(req: Request, res: Response): Promise { lastname, nameaffix, birthdate, + internalId, }; let memberId = await MemberCommandHandler.create(createMember); @@ -249,12 +251,10 @@ export async function createMember(req: Request, res: Response): Promise { */ export async function addMembershipToMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); - const internalId = req.body.internalId; const start = req.body.start; const statusId = req.body.statusId; let createMembership: CreateMembershipCommand = { - internalId, start, memberId, statusId, @@ -394,6 +394,7 @@ export async function updateMemberById(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); - const internalId = req.body.internalId; const start = req.body.start; const end = req.body.end || null; const terminationReason = req.body.terminationReason; @@ -425,7 +426,6 @@ export async function updateMembershipOfMember(req: Request, res: Response): Pro let updateMembership: UpdateMembershipCommand = { id: recordId, - internalId, start, end, terminationReason, diff --git a/src/data-source.ts b/src/data-source.ts index f4ea044..75f6f5b 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -62,6 +62,7 @@ import { Newsletter1735118780511 } from "./migrations/1735118780511-newsletter"; import { newsletterConfig } from "./entity/newsletterConfig"; import { NewsletterConfig1735207446910 } from "./migrations/1735207446910-newsletterConfig"; import { TemplateMargins1735733514043 } from "./migrations/1735733514043-templateMargins"; +import { InternalId1735822722235 } from "./migrations/1735822722235-internalId"; const dataSource = new DataSource({ type: DB_TYPE as any, @@ -134,6 +135,7 @@ const dataSource = new DataSource({ Newsletter1735118780511, NewsletterConfig1735207446910, TemplateMargins1735733514043, + InternalId1735822722235, ], migrationsRun: true, migrationsTransactionMode: "each", diff --git a/src/entity/member.ts b/src/entity/member.ts index de7f612..6fef6cf 100644 --- a/src/entity/member.ts +++ b/src/entity/member.ts @@ -39,6 +39,9 @@ export class member { @Column({ type: "date" }) birthdate: Date; + @Column({ type: "varchar", length: 255, unique: true, nullable: true }) + internalId?: string; + @OneToMany(() => communication, (communications) => communications.member) communications: communication[]; diff --git a/src/entity/memberAwards.ts b/src/entity/memberAwards.ts index 47ea86a..e25420e 100644 --- a/src/entity/memberAwards.ts +++ b/src/entity/memberAwards.ts @@ -16,6 +16,12 @@ export class memberAwards { @Column({ type: "date" }) date: Date; + @Column() + memberId: number; + + @Column() + awardId: number; + @ManyToOne(() => member, (member) => member.awards, { nullable: false, onDelete: "CASCADE", diff --git a/src/entity/memberExecutivePositions.ts b/src/entity/memberExecutivePositions.ts index 0f68729..fea07e9 100644 --- a/src/entity/memberExecutivePositions.ts +++ b/src/entity/memberExecutivePositions.ts @@ -16,6 +16,12 @@ export class memberExecutivePositions { @Column({ type: "date", nullable: true }) end?: Date; + @Column() + memberId: number; + + @Column() + executivePositionId: number; + @ManyToOne(() => member, (member) => member.awards, { nullable: false, onDelete: "CASCADE", diff --git a/src/entity/memberQualifications.ts b/src/entity/memberQualifications.ts index c2d4026..bbc67e9 100644 --- a/src/entity/memberQualifications.ts +++ b/src/entity/memberQualifications.ts @@ -19,6 +19,12 @@ export class memberQualifications { @Column({ type: "varchar", length: 255, nullable: true }) terminationReason?: string; + @Column() + memberId: number; + + @Column() + qualificationId: number; + @ManyToOne(() => member, (member) => member.awards, { nullable: false, onDelete: "CASCADE", diff --git a/src/entity/membership.ts b/src/entity/membership.ts index dd8d1ac..51801cb 100644 --- a/src/entity/membership.ts +++ b/src/entity/membership.ts @@ -7,6 +7,9 @@ export class membership { @PrimaryColumn({ generated: "increment", type: "int" }) id: number; + /** + * @deprecated + */ @Column({ type: "varchar", length: 255, unique: true, nullable: true }) internalId?: string; @@ -19,6 +22,12 @@ export class membership { @Column({ type: "varchar", length: 255, nullable: true }) terminationReason?: string; + @Column() + memberId: number; + + @Column() + statusId: number; + @ManyToOne(() => member, (member) => member.memberships, { nullable: false, onDelete: "CASCADE", diff --git a/src/factory/admin/member.ts b/src/factory/admin/member.ts index 44ddc70..01419e8 100644 --- a/src/factory/admin/member.ts +++ b/src/factory/admin/member.ts @@ -17,6 +17,7 @@ export default abstract class MemberFactory { lastname: record?.lastname, nameaffix: record?.nameaffix, birthdate: record?.birthdate, + internalId: record.internalId, firstMembershipEntry: record?.firstMembershipEntry ? MembershipFactory.mapToSingle(record.firstMembershipEntry) : null, diff --git a/src/factory/admin/membership.ts b/src/factory/admin/membership.ts index ba54a08..2a711c4 100644 --- a/src/factory/admin/membership.ts +++ b/src/factory/admin/membership.ts @@ -10,7 +10,6 @@ export default abstract class MembershipFactory { public static mapToSingle(record: membership): MembershipViewModel { return { id: record.id, - internalId: record.internalId, start: record.start, end: record.end, terminationReason: record.terminationReason, diff --git a/src/migrations/1735822722235-internalId.ts b/src/migrations/1735822722235-internalId.ts new file mode 100644 index 0000000..9dccc0f --- /dev/null +++ b/src/migrations/1735822722235-internalId.ts @@ -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 { + 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 }>((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 { + await queryRunner.dropColumn("member", "internalId"); + } +} diff --git a/src/service/membershipService.ts b/src/service/membershipService.ts index caa4273..96805cc 100644 --- a/src/service/membershipService.ts +++ b/src/service/membershipService.ts @@ -14,6 +14,7 @@ export default abstract class MembershipService { .createQueryBuilder("membership") .leftJoinAndSelect("membership.status", "membershipStatus") .where("membership.memberId = :memberId", { memberId: memberId }) + .orderBy("membership.start", "DESC") .getMany() .then((res) => { return res; diff --git a/src/viewmodel/admin/member.models.ts b/src/viewmodel/admin/member.models.ts index c005d9d..76f1a9a 100644 --- a/src/viewmodel/admin/member.models.ts +++ b/src/viewmodel/admin/member.models.ts @@ -9,6 +9,7 @@ export interface MemberViewModel { lastname: string; nameaffix: string; birthdate: Date; + internalId?: string; firstMembershipEntry?: MembershipViewModel; lastMembershipEntry?: MembershipViewModel; sendNewsletter?: CommunicationViewModel; diff --git a/src/viewmodel/admin/membership.models.ts b/src/viewmodel/admin/membership.models.ts index 396be33..59e2aba 100644 --- a/src/viewmodel/admin/membership.models.ts +++ b/src/viewmodel/admin/membership.models.ts @@ -1,6 +1,5 @@ export interface MembershipViewModel { id: number; - internalId?: string; start: Date; end?: Date; terminationReason?: string;