From 58d863e5e055a5392cdc1e4f34b24a7270b1ecff Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 27 Sep 2024 14:55:34 +0200 Subject: [PATCH] member related data commands --- src/command/communicationCommand.ts | 28 ++ src/command/communicationCommandHandler.ts | 96 ++++++ src/command/memberAwardCommand.ts | 21 ++ src/command/memberAwardCommandHandler.ts | 89 +++++ src/command/memberCommand.ts | 5 + src/command/memberCommandHandler.ts | 35 +- src/command/memberExecutivePositionCommand.ts | 21 ++ .../memberExecutivePositionCommandHandler.ts | 93 ++++++ src/command/memberQualificationCommand.ts | 21 ++ .../memberQualificationCommandHandler.ts | 93 ++++++ src/command/membershipCommand.ts | 21 ++ src/command/membershipCommandHandler.ts | 107 ++++++ src/controller/admin/memberController.ts | 305 +++++++++++++++++- src/data-source.ts | 2 + src/entity/communication.ts | 12 +- src/factory/admin/memberAward.ts | 1 + src/factory/admin/memberExecutivePosition.ts | 1 + src/factory/admin/memberQualification.ts | 1 + src/factory/admin/membership.ts | 1 + .../1727439800630-communicationFields.ts | 140 ++++++++ src/routes/admin/member.ts | 25 ++ src/service/communicationService.ts | 2 +- src/viewmodel/admin/memberAward.models.ts | 1 + .../admin/memberExecutivePosition.models.ts | 1 + .../admin/memberQualification.models.ts | 1 + src/viewmodel/admin/membership.models.ts | 1 + 26 files changed, 1115 insertions(+), 9 deletions(-) create mode 100644 src/command/communicationCommand.ts create mode 100644 src/command/communicationCommandHandler.ts create mode 100644 src/command/memberAwardCommand.ts create mode 100644 src/command/memberAwardCommandHandler.ts create mode 100644 src/command/memberExecutivePositionCommand.ts create mode 100644 src/command/memberExecutivePositionCommandHandler.ts create mode 100644 src/command/memberQualificationCommand.ts create mode 100644 src/command/memberQualificationCommandHandler.ts create mode 100644 src/command/membershipCommand.ts create mode 100644 src/command/membershipCommandHandler.ts create mode 100644 src/migrations/1727439800630-communicationFields.ts diff --git a/src/command/communicationCommand.ts b/src/command/communicationCommand.ts new file mode 100644 index 0000000..1dfffd6 --- /dev/null +++ b/src/command/communicationCommand.ts @@ -0,0 +1,28 @@ +export interface CreateCommunicationCommand { + preferred: boolean; + mobile: string; + email: string; + city: string; + street: string; + streetNumber: number; + streetNumberAddition: string; + memberId: number; + typeId: number; +} + +export interface UpdateCommunicationCommand { + id: number; + preferred: boolean; + mobile: string; + email: string; + city: string; + street: string; + streetNumber: number; + streetNumberAddition: string; + memberId: number; +} + +export interface DeleteCommunicationCommand { + id: number; + memberId: number; +} diff --git a/src/command/communicationCommandHandler.ts b/src/command/communicationCommandHandler.ts new file mode 100644 index 0000000..4f2f801 --- /dev/null +++ b/src/command/communicationCommandHandler.ts @@ -0,0 +1,96 @@ +import { dataSource } from "../data-source"; +import { communication } from "../entity/communication"; +import { communicationType } from "../entity/communicationType"; +import { user } from "../entity/user"; +import InternalException from "../exceptions/internalException"; +import { + CreateCommunicationCommand, + DeleteCommunicationCommand, + UpdateCommunicationCommand, +} from "./communicationCommand"; + +export default abstract class CommunicationCommandHandler { + /** + * @description create communication + * @param CreateCommunicationCommand + * @returns {Promise} + */ + static async create(createCommunication: CreateCommunicationCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(communication) + .values({ + preferred: createCommunication.preferred, + mobile: createCommunication.mobile, + email: createCommunication.email, + city: createCommunication.city, + street: createCommunication.street, + streetNumber: createCommunication.streetNumber, + streetNumberAddition: createCommunication.streetNumberAddition, + member: await dataSource + .getRepository(user) + .createQueryBuilder("user") + .where("id = :id", { id: createCommunication.memberId }) + .getOneOrFail(), + type: await dataSource + .getRepository(communicationType) + .createQueryBuilder("communication") + .where("id = :id", { id: createCommunication.typeId }) + .getOneOrFail(), + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new InternalException("Failed creating communication", err); + }); + } + + /** + * @description update communication + * @param UpdateCommunicationCommand + * @returns {Promise} + */ + static async update(updateCommunication: UpdateCommunicationCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(communication) + .set({ + preferred: updateCommunication.preferred, + mobile: updateCommunication.mobile, + email: updateCommunication.email, + city: updateCommunication.city, + street: updateCommunication.street, + streetNumber: updateCommunication.streetNumber, + streetNumberAddition: updateCommunication.streetNumberAddition, + }) + .where("id = :id", { id: updateCommunication.id }) + .andWhere("memberId = :memberId", { memberId: updateCommunication.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating communication", err); + }); + } + + /** + * @description delete communication + * @param DeleteCommunicationCommand + * @returns {Promise} + */ + static async delete(deletCommunication: DeleteCommunicationCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(communication) + .where("id = :id", { id: deletCommunication.id }) + .andWhere("memberId = :memberId", { memberId: deletCommunication.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed deleting communication", err); + }); + } +} diff --git a/src/command/memberAwardCommand.ts b/src/command/memberAwardCommand.ts new file mode 100644 index 0000000..b9c2458 --- /dev/null +++ b/src/command/memberAwardCommand.ts @@ -0,0 +1,21 @@ +export interface CreateMemberAwardCommand { + given: boolean; + note?: string; + date: Date; + memberId: number; + awardId: number; +} + +export interface UpdateMemberAwardCommand { + id: number; + given: boolean; + note?: string; + date: Date; + memberId: number; + awardId: number; +} + +export interface DeleteMemberAwardCommand { + id: number; + memberId: number; +} diff --git a/src/command/memberAwardCommandHandler.ts b/src/command/memberAwardCommandHandler.ts new file mode 100644 index 0000000..05b2d0d --- /dev/null +++ b/src/command/memberAwardCommandHandler.ts @@ -0,0 +1,89 @@ +import { dataSource } from "../data-source"; +import { award } from "../entity/award"; +import { memberAwards } from "../entity/memberAwards"; +import { user } from "../entity/user"; +import InternalException from "../exceptions/internalException"; +import { CreateMemberAwardCommand, DeleteMemberAwardCommand, UpdateMemberAwardCommand } from "./memberAwardCommand"; + +export default abstract class MemberAwardCommandHandler { + /** + * @description create memberAward + * @param CreateMemberAwardCommand + * @returns {Promise} + */ + static async create(createMemberAward: CreateMemberAwardCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(memberAwards) + .values({ + given: createMemberAward.given, + note: createMemberAward.note, + date: createMemberAward.date, + member: await dataSource + .getRepository(user) + .createQueryBuilder("user") + .where("id = :id", { id: createMemberAward.memberId }) + .getOneOrFail(), + award: await dataSource + .getRepository(award) + .createQueryBuilder("award") + .where("id = :id", { id: createMemberAward.awardId }) + .getOneOrFail(), + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new InternalException("Failed creating memberAward", err); + }); + } + + /** + * @description update memberAward + * @param UpdateMemberAwardCommand + * @returns {Promise} + */ + static async update(updateMemberAward: UpdateMemberAwardCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(memberAwards) + .set({ + given: updateMemberAward.given, + note: updateMemberAward.note, + date: updateMemberAward.date, + award: await dataSource + .getRepository(award) + .createQueryBuilder("award") + .where("id = :id", { id: updateMemberAward.awardId }) + .getOneOrFail(), + }) + .where("id = :id", { id: updateMemberAward.id }) + .andWhere("memberId = :memberId", { memberId: updateMemberAward.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating memberAward", err); + }); + } + + /** + * @description delete memberAward + * @param DeleteMemberAwardCommand + * @returns {Promise} + */ + static async delete(deletMemberAward: DeleteMemberAwardCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(memberAwards) + .where("id = :id", { id: deletMemberAward.id }) + .andWhere("memberId = :memberId", { memberId: deletMemberAward.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed deleting memberAward", err); + }); + } +} diff --git a/src/command/memberCommand.ts b/src/command/memberCommand.ts index 0d76460..3dc61d3 100644 --- a/src/command/memberCommand.ts +++ b/src/command/memberCommand.ts @@ -17,6 +17,11 @@ export interface UpdateMemberCommand { birthdate: Date; } +export interface UpdateMemberNewsletterCommand { + id: number; + communicationId: number; +} + export interface DeleteMemberCommand { id: number; } diff --git a/src/command/memberCommandHandler.ts b/src/command/memberCommandHandler.ts index 28fc79e..b37d89f 100644 --- a/src/command/memberCommandHandler.ts +++ b/src/command/memberCommandHandler.ts @@ -1,7 +1,14 @@ import { dataSource } from "../data-source"; +import { communication } from "../entity/communication"; import { member } from "../entity/member"; import InternalException from "../exceptions/internalException"; -import { CreateMemberCommand, DeleteMemberCommand, UpdateMemberCommand } from "./memberCommand"; +import CommunicationService from "../service/communicationService"; +import { + CreateMemberCommand, + DeleteMemberCommand, + UpdateMemberCommand, + UpdateMemberNewsletterCommand, +} from "./memberCommand"; export default abstract class MemberCommandHandler { /** @@ -55,6 +62,32 @@ export default abstract class MemberCommandHandler { }); } + /** + * @description update member newsletter + * @param UpdateMemberCommand + * @returns {Promise} + */ + static async updateNewsletter(updateMember: UpdateMemberNewsletterCommand): Promise { + console.log(updateMember); + return await dataSource + .createQueryBuilder() + .update(member) + .set({ + sendNewsletter: await dataSource + .getRepository(communication) + .createQueryBuilder("communication") + .where("id = :id", { id: updateMember.communicationId }) + .andWhere("memberId = :memberId", { memberId: updateMember.id }) + .getOneOrFail(), + }) + .where("id = :id", { id: updateMember.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating member", err); + }); + } + /** * @description delete member * @param DeleteMemberCommand diff --git a/src/command/memberExecutivePositionCommand.ts b/src/command/memberExecutivePositionCommand.ts new file mode 100644 index 0000000..2fd2578 --- /dev/null +++ b/src/command/memberExecutivePositionCommand.ts @@ -0,0 +1,21 @@ +export interface CreateMemberExecutivePositionCommand { + note?: string; + start: Date; + end?: Date; + memberId: number; + executivePositionId: number; +} + +export interface UpdateMemberExecutivePositionCommand { + id: number; + note?: string; + start: Date; + end?: Date; + memberId: number; + executivePositionId: number; +} + +export interface DeleteMemberExecutivePositionCommand { + id: number; + memberId: number; +} diff --git a/src/command/memberExecutivePositionCommandHandler.ts b/src/command/memberExecutivePositionCommandHandler.ts new file mode 100644 index 0000000..a9a1762 --- /dev/null +++ b/src/command/memberExecutivePositionCommandHandler.ts @@ -0,0 +1,93 @@ +import { dataSource } from "../data-source"; +import { executivePosition } from "../entity/executivePosition"; +import { memberExecutivePositions } from "../entity/memberExecutivePositions"; +import { user } from "../entity/user"; +import InternalException from "../exceptions/internalException"; +import { + CreateMemberExecutivePositionCommand, + DeleteMemberExecutivePositionCommand, + UpdateMemberExecutivePositionCommand, +} from "./memberExecutivePositionCommand"; + +export default abstract class MemberExecutivePositionCommandHandler { + /** + * @description create memberExecutivePosition + * @param CreateMemberExecutivePositionCommand + * @returns {Promise} + */ + static async create(createMemberExecutivePosition: CreateMemberExecutivePositionCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(memberExecutivePositions) + .values({ + note: createMemberExecutivePosition.note, + start: createMemberExecutivePosition.start, + end: createMemberExecutivePosition.end, + member: await dataSource + .getRepository(user) + .createQueryBuilder("user") + .where("id = :id", { id: createMemberExecutivePosition.memberId }) + .getOneOrFail(), + executivePosition: await dataSource + .getRepository(executivePosition) + .createQueryBuilder("executivePosition") + .where("id = :id", { id: createMemberExecutivePosition.executivePositionId }) + .getOneOrFail(), + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new InternalException("Failed creating memberExecutivePosition", err); + }); + } + + /** + * @description update memberExecutivePosition + * @param UpdateMemberExecutivePositionCommand + * @returns {Promise} + */ + static async update(updateMemberExecutivePosition: UpdateMemberExecutivePositionCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(memberExecutivePositions) + .set({ + note: updateMemberExecutivePosition.note, + start: updateMemberExecutivePosition.start, + end: updateMemberExecutivePosition.end, + executivePosition: await dataSource + .getRepository(executivePosition) + .createQueryBuilder("executivePosition") + .where("id = :id", { id: updateMemberExecutivePosition.executivePositionId }) + .getOneOrFail(), + }) + .where("id = :id", { id: updateMemberExecutivePosition.id }) + .andWhere("memberId = :memberId", { memberId: updateMemberExecutivePosition.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating memberExecutivePosition", err); + }); + } + + /** + * @description delete memberExecutivePosition + * @param DeleteMemberExecutivePositionCommand + * @returns {Promise} + */ + static async delete(deletMemberExecutivePosition: DeleteMemberExecutivePositionCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(memberExecutivePositions) + .where("id = :id", { id: deletMemberExecutivePosition.id }) + .andWhere("memberId = :memberId", { memberId: deletMemberExecutivePosition.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed deleting memberExecutivePosition", err); + }); + } +} diff --git a/src/command/memberQualificationCommand.ts b/src/command/memberQualificationCommand.ts new file mode 100644 index 0000000..8c6cb04 --- /dev/null +++ b/src/command/memberQualificationCommand.ts @@ -0,0 +1,21 @@ +export interface CreateMemberQualificationCommand { + note?: string; + start: Date; + memberId: number; + qualificationId: number; +} + +export interface UpdateMemberQualificationCommand { + id: number; + note?: string; + start: Date; + end?: Date; + terminationReason?: string; + memberId: number; + qualificationId: number; +} + +export interface DeleteMemberQualificationCommand { + id: number; + memberId: number; +} diff --git a/src/command/memberQualificationCommandHandler.ts b/src/command/memberQualificationCommandHandler.ts new file mode 100644 index 0000000..2963638 --- /dev/null +++ b/src/command/memberQualificationCommandHandler.ts @@ -0,0 +1,93 @@ +import { dataSource } from "../data-source"; +import { qualification } from "../entity/qualification"; +import { memberQualifications } from "../entity/memberQualifications"; +import { user } from "../entity/user"; +import InternalException from "../exceptions/internalException"; +import { + CreateMemberQualificationCommand, + DeleteMemberQualificationCommand, + UpdateMemberQualificationCommand, +} from "./memberQualificationCommand"; + +export default abstract class MemberQualificationCommandHandler { + /** + * @description create memberQualification + * @param CreateMemberQualificationCommand + * @returns {Promise} + */ + static async create(createMemberQualification: CreateMemberQualificationCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(memberQualifications) + .values({ + note: createMemberQualification.note, + start: createMemberQualification.start, + member: await dataSource + .getRepository(user) + .createQueryBuilder("user") + .where("id = :id", { id: createMemberQualification.memberId }) + .getOneOrFail(), + qualification: await dataSource + .getRepository(qualification) + .createQueryBuilder("qualification") + .where("id = :id", { id: createMemberQualification.qualificationId }) + .getOneOrFail(), + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new InternalException("Failed creating memberQualification", err); + }); + } + + /** + * @description update memberQualification + * @param UpdateMemberQualificationCommand + * @returns {Promise} + */ + static async update(updateMemberQualification: UpdateMemberQualificationCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(memberQualifications) + .set({ + note: updateMemberQualification.note, + start: updateMemberQualification.start, + end: updateMemberQualification.end, + terminationReason: updateMemberQualification.terminationReason, + qualification: await dataSource + .getRepository(qualification) + .createQueryBuilder("qualification") + .where("id = :id", { id: updateMemberQualification.qualificationId }) + .getOneOrFail(), + }) + .where("id = :id", { id: updateMemberQualification.id }) + .andWhere("memberId = :memberId", { memberId: updateMemberQualification.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating memberQualification", err); + }); + } + + /** + * @description delete memberQualification + * @param DeleteMemberQualificationCommand + * @returns {Promise} + */ + static async delete(deletMemberQualification: DeleteMemberQualificationCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(memberQualifications) + .where("id = :id", { id: deletMemberQualification.id }) + .andWhere("memberId = :memberId", { memberId: deletMemberQualification.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed deleting memberQualification", err); + }); + } +} diff --git a/src/command/membershipCommand.ts b/src/command/membershipCommand.ts new file mode 100644 index 0000000..fcf429d --- /dev/null +++ b/src/command/membershipCommand.ts @@ -0,0 +1,21 @@ +export interface CreateMembershipCommand { + internalId?: string; + start: Date; + memberId: number; + statusId: number; +} + +export interface UpdateMembershipCommand { + id: number; + internalId?: string; + start: Date; + end?: Date; + terminationReason?: string; + memberId: number; + statusId: number; +} + +export interface DeleteMembershipCommand { + id: number; + memberId: number; +} diff --git a/src/command/membershipCommandHandler.ts b/src/command/membershipCommandHandler.ts new file mode 100644 index 0000000..204b0d8 --- /dev/null +++ b/src/command/membershipCommandHandler.ts @@ -0,0 +1,107 @@ +import { dataSource } from "../data-source"; +import { membership } from "../entity/membership"; +import { membershipStatus } from "../entity/membershipStatus"; +import { user } from "../entity/user"; +import InternalException from "../exceptions/internalException"; +import { CreateMembershipCommand, DeleteMembershipCommand, UpdateMembershipCommand } from "./membershipCommand"; + +export default abstract class MembershipCommandHandler { + /** + * @description create membership + * @param CreateMembershipCommand + * @returns {Promise} + */ + static async create(createMembership: CreateMembershipCommand): Promise { + let insertid = -1; + return await dataSource + .transaction(async (manager) => { + await manager + .createQueryBuilder() + .insert() + .into(membership) + .values({ + internalId: createMembership.internalId, + start: createMembership.start, + member: await dataSource + .getRepository(user) + .createQueryBuilder("user") + .where("id = :id", { id: createMembership.memberId }) + .getOneOrFail(), + status: await dataSource + .getRepository(membershipStatus) + .createQueryBuilder("membershipStatus") + .where("id = :id", { id: createMembership.statusId }) + .getOneOrFail(), + }) + .execute() + .then((result) => { + insertid = result.identifiers[0].id; + }); + + await manager + .createQueryBuilder() + .update(membership) + .set({ + end: createMembership.start, + }) + .where("end IS NULL") + .andWhere("memberId = :memberId", { memberId: createMembership.memberId }) + .andWhere("id <> :id", { id: insertid }) + .execute(); + }) + .then(() => { + return insertid; + }) + .catch((err) => { + throw new InternalException("Failed creating membership", err); + }); + } + + /** + * @description update membership + * @param UpdateMembershipCommand + * @returns {Promise} + */ + static async update(updateMembership: UpdateMembershipCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(membership) + .set({ + internalId: updateMembership.internalId, + start: updateMembership.start, + end: updateMembership.end, + terminationReason: updateMembership.terminationReason, + status: await dataSource + .getRepository(membershipStatus) + .createQueryBuilder("membershipStatus") + .where("id = :id", { id: updateMembership.statusId }) + .getOneOrFail(), + }) + .where("id = :id", { id: updateMembership.id }) + .andWhere("memberId = :memberId", { memberId: updateMembership.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating membership", err); + }); + } + + /** + * @description delete membership + * @param DeleteMembershipCommand + * @returns {Promise} + */ + static async delete(deletMembership: DeleteMembershipCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(membership) + .where("id = :id", { id: deletMembership.id }) + .andWhere("memberId = :memberId", { memberId: deletMembership.memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed deleting membership", err); + }); + } +} diff --git a/src/controller/admin/memberController.ts b/src/controller/admin/memberController.ts index 155790b..0fc309e 100644 --- a/src/controller/admin/memberController.ts +++ b/src/controller/admin/memberController.ts @@ -11,8 +11,43 @@ import MemberExecutivePositionService from "../../service/memberExecutivePositio import MemberExecutivePositionFactory from "../../factory/admin/memberExecutivePosition"; import CommunicationService from "../../service/communicationService"; import CommunicationFactory from "../../factory/admin/communication"; -import { CreateMemberCommand, DeleteMemberCommand, UpdateMemberCommand } from "../../command/memberCommand"; +import { + CreateMemberCommand, + DeleteMemberCommand, + UpdateMemberCommand, + UpdateMemberNewsletterCommand, +} from "../../command/memberCommand"; import MemberCommandHandler from "../../command/memberCommandHandler"; +import { + CreateMembershipCommand, + DeleteMembershipCommand, + UpdateMembershipCommand, +} from "../../command/membershipCommand"; +import MembershipCommandHandler from "../../command/membershipCommandHandler"; +import { + CreateMemberAwardCommand, + DeleteMemberAwardCommand, + UpdateMemberAwardCommand, +} from "../../command/memberAwardCommand"; +import MemberAwardCommandHandler from "../../command/memberAwardCommandHandler"; +import { + CreateMemberExecutivePositionCommand, + DeleteMemberExecutivePositionCommand, + UpdateMemberExecutivePositionCommand, +} from "../../command/memberExecutivePositionCommand"; +import MemberExecutivePositionCommandHandler from "../../command/memberExecutivePositionCommandHandler"; +import { + CreateMemberQualificationCommand, + DeleteMemberQualificationCommand, + UpdateMemberQualificationCommand, +} from "../../command/memberQualificationCommand"; +import MemberQualificationCommandHandler from "../../command/memberQualificationCommandHandler"; +import { + CreateCommunicationCommand, + DeleteCommunicationCommand, + UpdateCommunicationCommand, +} from "../../command/communicationCommand"; +import CommunicationCommandHandler from "../../command/communicationCommandHandler"; /** * @description get all members @@ -59,6 +94,20 @@ export async function getMembershipsByMember(req: Request, res: Response): Promi res.json(MembershipFactory.mapToBase(memberships)); } +/** + * @description get membership by member and record + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getMembershipByMemberAndRecord(req: Request, res: Response): Promise { + const memberId = parseInt(req.params.memberId); + const recordId = parseInt(req.params.id); + let membership = await MembershipService.getById(memberId, recordId); + + res.json(MembershipFactory.mapToSingle(membership)); +} + /** * @description get awards by member * @param req {Request} Express req object @@ -72,6 +121,20 @@ export async function getAwardsByMember(req: Request, res: Response): Promise} + */ +export async function getAwardByMemberAndRecord(req: Request, res: Response): Promise { + const memberId = parseInt(req.params.memberId); + const recordId = parseInt(req.params.id); + let award = await MemberAwardService.getById(memberId, recordId); + + res.json(MemberAwardFactory.mapToSingle(award)); +} + /** * @description get qualifications by member * @param req {Request} Express req object @@ -85,6 +148,20 @@ export async function getQualificationsByMember(req: Request, res: Response): Pr res.json(MemberQualificationFactory.mapToBase(qualifications)); } +/** + * @description get qualification by member and record + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getQualificationByMemberAndRecord(req: Request, res: Response): Promise { + const memberId = parseInt(req.params.memberId); + const recordId = parseInt(req.params.id); + let qualification = await MemberQualificationService.getById(memberId, recordId); + + res.json(MemberQualificationFactory.mapToSingle(qualification)); +} + /** * @description get executive positions by member * @param req {Request} Express req object @@ -98,6 +175,20 @@ export async function getExecutivePositionsByMember(req: Request, res: Response) res.json(MemberExecutivePositionFactory.mapToBase(positions)); } +/** + * @description get executive position by member and record + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getExecutivePositionByMemberAndRecord(req: Request, res: Response): Promise { + const memberId = parseInt(req.params.memberId); + const recordId = parseInt(req.params.id); + let position = await MemberExecutivePositionService.getById(memberId, recordId); + + res.json(MemberExecutivePositionFactory.mapToSingle(position)); +} + /** * @description get communications by member * @param req {Request} Express req object @@ -111,6 +202,20 @@ export async function getCommunicationsByMember(req: Request, res: Response): Pr res.json(CommunicationFactory.mapToBase(communications)); } +/** + * @description get communication by member and record + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getCommunicationByMemberAndRecord(req: Request, res: Response): Promise { + const memberId = parseInt(req.params.memberId); + const recordId = parseInt(req.params.id); + let communication = await CommunicationService.getById(memberId, recordId); + + res.json(CommunicationFactory.mapToSingle(communication)); +} + /** * @description create member * @param req {Request} Express req object @@ -144,6 +249,17 @@ 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, + }; + await MembershipCommandHandler.create(createMembership); res.sendStatus(204); } @@ -156,6 +272,19 @@ export async function addMembershipToMember(req: Request, res: Response): Promis */ export async function addAwardToMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); + const given = req.body.given; + const note = req.body.note; + const date = req.body.date; + const awardId = req.body.awardId; + + let createMemberAward: CreateMemberAwardCommand = { + given, + note, + date, + memberId, + awardId, + }; + await MemberAwardCommandHandler.create(createMemberAward); res.sendStatus(204); } @@ -168,6 +297,17 @@ export async function addAwardToMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); + const note = req.body.note; + const start = req.body.start; + const qualificationId = req.body.qualificationId; + + let createMemberQualification: CreateMemberQualificationCommand = { + note, + start, + memberId, + qualificationId, + }; + await MemberQualificationCommandHandler.create(createMemberQualification); res.sendStatus(204); } @@ -180,6 +320,19 @@ export async function addQualificationToMember(req: Request, res: Response): Pro */ export async function addExecutivePositionToMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); + const note = req.body.note; + const start = req.body.start; + const end = req.body.end || null; + const executivePositionId = req.body.executivePositionId; + + let createMemberExecutivePosition: CreateMemberExecutivePositionCommand = { + note, + start, + end, + memberId, + executivePositionId, + }; + await MemberExecutivePositionCommandHandler.create(createMemberExecutivePosition); res.sendStatus(204); } @@ -192,6 +345,36 @@ export async function addExecutivePositionToMember(req: Request, res: Response): */ export async function addCommunicationToMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); + const preferred = req.body.preferred; + const mobile = req.body.mobile; + const email = req.body.email; + const city = req.body.city; + const street = req.body.street; + const streetNumber = req.body.streetNumber; + const streetNumberAddition = req.body.streetNumberAddition; + const typeId = req.body.typeId; + const isNewsletterMain = req.body.isNewsletterMain; + + let createCommunication: CreateCommunicationCommand = { + preferred, + mobile, + email, + city, + street, + streetNumber, + streetNumberAddition, + memberId, + typeId, + }; + let id = await CommunicationCommandHandler.create(createCommunication); + + if (isNewsletterMain) { + let updateNewsletter: UpdateMemberNewsletterCommand = { + id: memberId, + communicationId: id, + }; + await MemberCommandHandler.updateNewsletter(updateNewsletter); + } res.sendStatus(204); } @@ -232,6 +415,22 @@ 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; + const statusId = req.body.statusId; + + let updateMembership: UpdateMembershipCommand = { + id: recordId, + internalId, + start, + end, + terminationReason, + memberId, + statusId, + }; + await MembershipCommandHandler.update(updateMembership); res.sendStatus(204); } @@ -245,6 +444,20 @@ export async function updateMembershipOfMember(req: Request, res: Response): Pro export async function updateAwardOfMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + const given = req.body.given; + const note = req.body.note; + const date = req.body.date; + const awardId = req.body.awardId; + + let updateMemberAward: UpdateMemberAwardCommand = { + id: recordId, + given, + note, + date, + memberId, + awardId, + }; + await MemberAwardCommandHandler.update(updateMemberAward); res.sendStatus(204); } @@ -258,6 +471,22 @@ export async function updateAwardOfMember(req: Request, res: Response): Promise< export async function updateQualificationOfMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + const note = req.body.note; + const start = req.body.start; + const end = req.body.end || null; + const terminationReason = req.body.terminationReason; + const qualificationId = req.body.qualificationId; + + let updateMemberQualification: UpdateMemberQualificationCommand = { + id: recordId, + note, + start, + end, + terminationReason, + memberId, + qualificationId, + }; + await MemberQualificationCommandHandler.update(updateMemberQualification); res.sendStatus(204); } @@ -271,6 +500,20 @@ export async function updateQualificationOfMember(req: Request, res: Response): export async function updateExecutivePositionOfMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + const note = req.body.note; + const start = req.body.start; + const end = req.body.end || null; + const executivePositionId = req.body.executivePositionId; + + let updateMemberExecutivePosition: UpdateMemberExecutivePositionCommand = { + id: recordId, + note, + start, + end, + memberId, + executivePositionId, + }; + await MemberExecutivePositionCommandHandler.update(updateMemberExecutivePosition); res.sendStatus(204); } @@ -284,6 +527,36 @@ export async function updateExecutivePositionOfMember(req: Request, res: Respons export async function updateCommunicationOfMember(req: Request, res: Response): Promise { const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + const preferred = req.body.preferred; + const mobile = req.body.mobile; + const email = req.body.email; + const city = req.body.city; + const street = req.body.street; + const streetNumber = req.body.streetNumber; + const streetNumberAddition = req.body.streetNumberAddition; + const typeId = req.body.typeId; + const isNewsletterMain = req.body.isNewsletterMain; + + let updateCommunication: UpdateCommunicationCommand = { + id: recordId, + preferred, + mobile, + email, + city, + street, + streetNumber, + streetNumberAddition, + memberId, + }; + await CommunicationCommandHandler.update(updateCommunication); + + if (isNewsletterMain) { + let updateNewsletter: UpdateMemberNewsletterCommand = { + id: memberId, + communicationId: recordId, + }; + await MemberCommandHandler.updateNewsletter(updateNewsletter); + } res.sendStatus(204); } @@ -315,6 +588,12 @@ export async function deleteMembershipOfMember(req: Request, res: Response): Pro const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + let deleteMembership: DeleteMembershipCommand = { + id: recordId, + memberId, + }; + await MembershipCommandHandler.delete(deleteMembership); + res.sendStatus(204); } @@ -328,6 +607,12 @@ export async function deleteAwardOfMember(req: Request, res: Response): Promise< const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + let deleteMemberAward: DeleteMemberAwardCommand = { + id: recordId, + memberId, + }; + await MemberAwardCommandHandler.delete(deleteMemberAward); + res.sendStatus(204); } @@ -341,6 +626,12 @@ export async function deleteQualificationOfMember(req: Request, res: Response): const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + let deleteMemberQualification: DeleteMemberQualificationCommand = { + id: recordId, + memberId, + }; + await MemberQualificationCommandHandler.delete(deleteMemberQualification); + res.sendStatus(204); } @@ -354,6 +645,12 @@ export async function deleteExecutivePositionOfMember(req: Request, res: Respons const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + let deleteMemberExecutivePosition: DeleteMemberExecutivePositionCommand = { + id: recordId, + memberId, + }; + await MemberExecutivePositionCommandHandler.delete(deleteMemberExecutivePosition); + res.sendStatus(204); } @@ -367,5 +664,11 @@ export async function deleteCommunicationOfMember(req: Request, res: Response): const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); + let deleteCommunication: DeleteCommunicationCommand = { + id: recordId, + memberId, + }; + await CommunicationCommandHandler.delete(deleteCommunication); + res.sendStatus(204); } diff --git a/src/data-source.ts b/src/data-source.ts index 21c23a2..a78ab3c 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -28,6 +28,7 @@ import { memberExecutivePositions } from "./entity/memberExecutivePositions"; import { memberQualifications } from "./entity/memberQualifications"; import { membership } from "./entity/membership"; import { Memberdata1726301836849 } from "./migrations/1726301836849-memberdata"; +import { CommunicationFields1727439800630 } from "./migrations/1727439800630-communicationFields"; const dataSource = new DataSource({ type: DB_TYPE as any, @@ -66,6 +67,7 @@ const dataSource = new DataSource({ RolePermission1724771491085, MemberBaseData1725435669492, Memberdata1726301836849, + CommunicationFields1727439800630, ], migrationsRun: true, migrationsTransactionMode: "each", diff --git a/src/entity/communication.ts b/src/entity/communication.ts index 02c060f..dbf3983 100644 --- a/src/entity/communication.ts +++ b/src/entity/communication.ts @@ -10,22 +10,22 @@ export class communication { @Column({ type: "boolean", default: false }) preferred: boolean; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, nullable: true }) mobile: string; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, nullable: true }) email: string; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, nullable: true }) city: string; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, nullable: true }) street: string; - @Column({ type: "integer" }) + @Column({ type: "integer", nullable: true }) streetNumber: number; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, nullable: true }) streetNumberAddition: string; @ManyToOne(() => communicationType, (communicationType) => communicationType.communications, { diff --git a/src/factory/admin/memberAward.ts b/src/factory/admin/memberAward.ts index c323429..756eaf3 100644 --- a/src/factory/admin/memberAward.ts +++ b/src/factory/admin/memberAward.ts @@ -14,6 +14,7 @@ export default abstract class MemberAwardFactory { note: record.note, date: record.date, award: record.award.award, + awardId: record.award.id, }; } diff --git a/src/factory/admin/memberExecutivePosition.ts b/src/factory/admin/memberExecutivePosition.ts index b4605f6..71655e5 100644 --- a/src/factory/admin/memberExecutivePosition.ts +++ b/src/factory/admin/memberExecutivePosition.ts @@ -14,6 +14,7 @@ export default abstract class MemberExecutivePositionFactory { start: record.start, end: record.end, executivePosition: record.executivePosition.position, + executivePositionId: record.executivePosition.id, }; } diff --git a/src/factory/admin/memberQualification.ts b/src/factory/admin/memberQualification.ts index 290b2bb..917f78f 100644 --- a/src/factory/admin/memberQualification.ts +++ b/src/factory/admin/memberQualification.ts @@ -15,6 +15,7 @@ export default abstract class MemberQualificationFactory { end: record.end, terminationReason: record.terminationReason, qualification: record.qualification.qualification, + qualificationId: record.qualification.id, }; } diff --git a/src/factory/admin/membership.ts b/src/factory/admin/membership.ts index 8c7c819..ba54a08 100644 --- a/src/factory/admin/membership.ts +++ b/src/factory/admin/membership.ts @@ -15,6 +15,7 @@ export default abstract class MembershipFactory { end: record.end, terminationReason: record.terminationReason, status: record.status.status, + statusId: record.status.id, }; } diff --git a/src/migrations/1727439800630-communicationFields.ts b/src/migrations/1727439800630-communicationFields.ts new file mode 100644 index 0000000..8901579 --- /dev/null +++ b/src/migrations/1727439800630-communicationFields.ts @@ -0,0 +1,140 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; +import { TableColumn } from "typeorm"; + +export class CommunicationFields1727439800630 implements MigrationInterface { + name = "CommunicationFields1727439800630"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.changeColumn( + "communication", + "mobile", + new TableColumn({ + name: "mobile", + type: "varchar", + length: "255", + isNullable: true, + }) + ); + + await queryRunner.changeColumn( + "communication", + "email", + new TableColumn({ + name: "email", + type: "varchar", + length: "255", + isNullable: true, + }) + ); + + await queryRunner.changeColumn( + "communication", + "city", + new TableColumn({ + name: "city", + type: "varchar", + length: "255", + isNullable: true, + }) + ); + + await queryRunner.changeColumn( + "communication", + "street", + new TableColumn({ + name: "street", + type: "varchar", + length: "255", + isNullable: true, + }) + ); + + await queryRunner.changeColumn( + "communication", + "streetNumber", + new TableColumn({ + name: "streetNumber", + type: "int", + isNullable: true, + }) + ); + + await queryRunner.changeColumn( + "communication", + "streetNumberAddition", + new TableColumn({ + name: "streetNumberAddition", + type: "varchar", + length: "255", + isNullable: true, + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.changeColumn( + "communication", + "mobile", + new TableColumn({ + name: "mobile", + type: "varchar", + length: "255", + isNullable: false, + }) + ); + + await queryRunner.changeColumn( + "communication", + "email", + new TableColumn({ + name: "email", + type: "varchar", + length: "255", + isNullable: false, + }) + ); + + await queryRunner.changeColumn( + "communication", + "city", + new TableColumn({ + name: "city", + type: "varchar", + length: "255", + isNullable: false, + }) + ); + + await queryRunner.changeColumn( + "communication", + "street", + new TableColumn({ + name: "street", + type: "varchar", + length: "255", + isNullable: false, + }) + ); + + await queryRunner.changeColumn( + "communication", + "streetNumber", + new TableColumn({ + name: "streetNumber", + type: "int", + isNullable: false, + }) + ); + + await queryRunner.changeColumn( + "communication", + "streetNumberAddition", + new TableColumn({ + name: "streetNumberAddition", + type: "varchar", + length: "255", + isNullable: false, + }) + ); + } +} diff --git a/src/routes/admin/member.ts b/src/routes/admin/member.ts index 2f8c04e..bd45549 100644 --- a/src/routes/admin/member.ts +++ b/src/routes/admin/member.ts @@ -13,11 +13,16 @@ import { deleteMembershipOfMember, deleteQualificationOfMember, getAllMembers, + getAwardByMemberAndRecord, getAwardsByMember, + getCommunicationByMemberAndRecord, getCommunicationsByMember, + getExecutivePositionByMemberAndRecord, getExecutivePositionsByMember, getMemberById, + getMembershipByMemberAndRecord, getMembershipsByMember, + getQualificationByMemberAndRecord, getQualificationsByMember, updateAwardOfMember, updateCommunicationOfMember, @@ -42,22 +47,42 @@ router.get("/:memberId/memberships", async (req: Request, res: Response) => { await getMembershipsByMember(req, res); }); +router.get("/:memberId/membership/:id", async (req: Request, res: Response) => { + await getMembershipByMemberAndRecord(req, res); +}); + router.get("/:memberId/awards", async (req: Request, res: Response) => { await getAwardsByMember(req, res); }); +router.get("/:memberId/award/:id", async (req: Request, res: Response) => { + await getAwardByMemberAndRecord(req, res); +}); + router.get("/:memberId/qualifications", async (req: Request, res: Response) => { await getQualificationsByMember(req, res); }); +router.get("/:memberId/qualification/:id", async (req: Request, res: Response) => { + await getQualificationByMemberAndRecord(req, res); +}); + router.get("/:memberId/positions", async (req: Request, res: Response) => { await getExecutivePositionsByMember(req, res); }); +router.get("/:memberId/position/:id", async (req: Request, res: Response) => { + await getExecutivePositionByMemberAndRecord(req, res); +}); + router.get("/:memberId/communications", async (req: Request, res: Response) => { await getCommunicationsByMember(req, res); }); +router.get("/:memberId/communication/:id", async (req: Request, res: Response) => { + await getCommunicationByMemberAndRecord(req, res); +}); + router.post( "/", PermissionHelper.passCheckMiddleware("create", "club", "member"), diff --git a/src/service/communicationService.ts b/src/service/communicationService.ts index 5cb9a16..de86e49 100644 --- a/src/service/communicationService.ts +++ b/src/service/communicationService.ts @@ -56,6 +56,6 @@ export default abstract class CommunicationService { static getAvailableColumnsForCommunication(): Array { let metadata = dataSource.getMetadata(communication); let columns = metadata.columns.map((c) => c.propertyName); - return columns.filter((c) => !["id", "preffered", "type", "member"].includes(c)); + return columns.filter((c) => !["id", "preferred", "type", "member"].includes(c)); } } diff --git a/src/viewmodel/admin/memberAward.models.ts b/src/viewmodel/admin/memberAward.models.ts index fc8f447..12fe5ed 100644 --- a/src/viewmodel/admin/memberAward.models.ts +++ b/src/viewmodel/admin/memberAward.models.ts @@ -4,4 +4,5 @@ export interface MemberAwardViewModel { note?: string; date: Date; award: string; + awardId: number; } diff --git a/src/viewmodel/admin/memberExecutivePosition.models.ts b/src/viewmodel/admin/memberExecutivePosition.models.ts index 6830216..e87801f 100644 --- a/src/viewmodel/admin/memberExecutivePosition.models.ts +++ b/src/viewmodel/admin/memberExecutivePosition.models.ts @@ -4,4 +4,5 @@ export interface MemberExecutivePositionViewModel { start: Date; end?: Date; executivePosition: string; + executivePositionId: number; } diff --git a/src/viewmodel/admin/memberQualification.models.ts b/src/viewmodel/admin/memberQualification.models.ts index 53c7bca..4327155 100644 --- a/src/viewmodel/admin/memberQualification.models.ts +++ b/src/viewmodel/admin/memberQualification.models.ts @@ -5,4 +5,5 @@ export interface MemberQualificationViewModel { end?: Date; terminationReason?: string; qualification: string; + qualificationId: number; } diff --git a/src/viewmodel/admin/membership.models.ts b/src/viewmodel/admin/membership.models.ts index d8a5305..396be33 100644 --- a/src/viewmodel/admin/membership.models.ts +++ b/src/viewmodel/admin/membership.models.ts @@ -5,4 +5,5 @@ export interface MembershipViewModel { end?: Date; terminationReason?: string; status: string; + statusId: number; }