diff --git a/src/command/communicationCommand.ts b/src/command/communicationCommand.ts index 1dfffd6..6700110 100644 --- a/src/command/communicationCommand.ts +++ b/src/command/communicationCommand.ts @@ -1,5 +1,6 @@ export interface CreateCommunicationCommand { preferred: boolean; + isSMSAlarming: boolean; mobile: string; email: string; city: string; @@ -13,6 +14,7 @@ export interface CreateCommunicationCommand { export interface UpdateCommunicationCommand { id: number; preferred: boolean; + isSMSAlarming: boolean; mobile: string; email: string; city: string; diff --git a/src/command/communicationCommandHandler.ts b/src/command/communicationCommandHandler.ts index 4f2f801..c13bec6 100644 --- a/src/command/communicationCommandHandler.ts +++ b/src/command/communicationCommandHandler.ts @@ -22,6 +22,7 @@ export default abstract class CommunicationCommandHandler { .into(communication) .values({ preferred: createCommunication.preferred, + isSMSAlarming: createCommunication.isSMSAlarming, mobile: createCommunication.mobile, email: createCommunication.email, city: createCommunication.city, @@ -59,6 +60,7 @@ export default abstract class CommunicationCommandHandler { .update(communication) .set({ preferred: updateCommunication.preferred, + isSMSAlarming: updateCommunication.isSMSAlarming, mobile: updateCommunication.mobile, email: updateCommunication.email, city: updateCommunication.city, diff --git a/src/command/memberCommandHandler.ts b/src/command/memberCommandHandler.ts index b37d89f..4c396cf 100644 --- a/src/command/memberCommandHandler.ts +++ b/src/command/memberCommandHandler.ts @@ -68,7 +68,6 @@ export default abstract class MemberCommandHandler { * @returns {Promise} */ static async updateNewsletter(updateMember: UpdateMemberNewsletterCommand): Promise { - console.log(updateMember); return await dataSource .createQueryBuilder() .update(member) @@ -88,6 +87,26 @@ export default abstract class MemberCommandHandler { }); } + /** + * @description update member newsletter to unset + * @param memberId string + * @returns {Promise} + */ + static async unsetNewsletter(memberId: number): Promise { + return await dataSource + .createQueryBuilder() + .update(member) + .set({ + sendNewsletter: null, + }) + .where("id = :id", { id: memberId }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed updating member", err); + }); + } + /** * @description delete member * @param DeleteMemberCommand diff --git a/src/controller/admin/memberController.ts b/src/controller/admin/memberController.ts index 0fc309e..6644568 100644 --- a/src/controller/admin/memberController.ts +++ b/src/controller/admin/memberController.ts @@ -346,6 +346,7 @@ 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 isSMSAlarming = req.body.isSMSAlarming; const mobile = req.body.mobile; const email = req.body.email; const city = req.body.city; @@ -357,6 +358,7 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro let createCommunication: CreateCommunicationCommand = { preferred, + isSMSAlarming, mobile, email, city, @@ -528,6 +530,7 @@ export async function updateCommunicationOfMember(req: Request, res: Response): const memberId = parseInt(req.params.memberId); const recordId = parseInt(req.params.recordId); const preferred = req.body.preferred; + const isSMSAlarming = req.body.isSMSAlarming; const mobile = req.body.mobile; const email = req.body.email; const city = req.body.city; @@ -540,6 +543,7 @@ export async function updateCommunicationOfMember(req: Request, res: Response): let updateCommunication: UpdateCommunicationCommand = { id: recordId, preferred, + isSMSAlarming, mobile, email, city, @@ -550,12 +554,16 @@ export async function updateCommunicationOfMember(req: Request, res: Response): }; await CommunicationCommandHandler.update(updateCommunication); + let currentUserNewsletterMain = await MemberService.getNewsletterById(memberId); + if (isNewsletterMain) { let updateNewsletter: UpdateMemberNewsletterCommand = { id: memberId, communicationId: recordId, }; await MemberCommandHandler.updateNewsletter(updateNewsletter); + } else if (currentUserNewsletterMain.sendNewsletter.id == recordId) { + await MemberCommandHandler.unsetNewsletter(memberId); } res.sendStatus(204); diff --git a/src/data-source.ts b/src/data-source.ts index 39a56c7..c7fec9f 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -42,6 +42,7 @@ import { calendarType } from "./entity/calendarType"; import { Calendar1729947763295 } from "./migrations/1729947763295-calendar"; import { reset } from "./entity/reset"; import { ResetToken1732358596823 } from "./migrations/1732358596823-resetToken"; +import { SMSAlarming1732696919191 } from "./migrations/1732696919191-SMSAlarming"; const dataSource = new DataSource({ type: DB_TYPE as any, @@ -94,6 +95,7 @@ const dataSource = new DataSource({ Protocol1729347911107, Calendar1729947763295, ResetToken1732358596823, + SMSAlarming1732696919191, ], migrationsRun: true, migrationsTransactionMode: "each", diff --git a/src/entity/communication.ts b/src/entity/communication.ts index dbf3983..be006c1 100644 --- a/src/entity/communication.ts +++ b/src/entity/communication.ts @@ -10,6 +10,9 @@ export class communication { @Column({ type: "boolean", default: false }) preferred: boolean; + @Column({ type: "boolean", default: false }) + isSMSAlarming: boolean; + @Column({ type: "varchar", length: 255, nullable: true }) mobile: string; diff --git a/src/entity/member.ts b/src/entity/member.ts index d2be9b0..7bb0d78 100644 --- a/src/entity/member.ts +++ b/src/entity/member.ts @@ -65,4 +65,5 @@ export class member { firstMembershipEntry?: membership; lastMembershipEntry?: membership; preferredCommunication?: Array; + smsAlarming?: Array; } diff --git a/src/factory/admin/communication.ts b/src/factory/admin/communication.ts index 1333515..6fe454e 100644 --- a/src/factory/admin/communication.ts +++ b/src/factory/admin/communication.ts @@ -20,6 +20,7 @@ export default abstract class CommunicationFactory { streetNumberAddition: record.streetNumberAddition, type: CommunicationTypeFactory.mapToSingle(record.type), isNewsletterMain: isMain ? isMain : record?.member?.sendNewsletter?.id == record.id, + isSMSAlarming: record.isSMSAlarming, }; } diff --git a/src/factory/admin/member.ts b/src/factory/admin/member.ts index 0745d10..44ddc70 100644 --- a/src/factory/admin/member.ts +++ b/src/factory/admin/member.ts @@ -27,6 +27,7 @@ export default abstract class MemberFactory { preferredCommunication: record?.preferredCommunication ? CommunicationFactory.mapToBase(record.preferredCommunication) : null, + smsAlarming: record?.smsAlarming ? CommunicationFactory.mapToBase(record.smsAlarming) : null, }; } diff --git a/src/migrations/1732696919191-SMSAlarming.ts b/src/migrations/1732696919191-SMSAlarming.ts new file mode 100644 index 0000000..2ef756e --- /dev/null +++ b/src/migrations/1732696919191-SMSAlarming.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; + +export class SMSAlarming1732696919191 implements MigrationInterface { + name = "SMSAlarming1732696919191"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.addColumn( + "communication", + new TableColumn({ + name: "isSMSAlarming", + type: "tinyint", + default: 0, + isNullable: false, + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn("communication", "isSMSAlarming"); + } +} diff --git a/src/service/communicationService.ts b/src/service/communicationService.ts index de86e49..03073fa 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", "preferred", "type", "member"].includes(c)); + return columns.filter((c) => !["id", "preferred", "isSMSAlarming", "type", "member"].includes(c)); } } diff --git a/src/service/memberService.ts b/src/service/memberService.ts index ae9e2d4..633497d 100644 --- a/src/service/memberService.ts +++ b/src/service/memberService.ts @@ -35,6 +35,8 @@ export default abstract class MemberService { "preferredCommunication.preferred = 1" ) .leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred") + .leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1") + .leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming") .offset(offset) .limit(count) .orderBy("member.lastname") @@ -52,7 +54,7 @@ export default abstract class MemberService { /** * @description get member by id * @param {number} id - * @returns {Promise>} + * @returns {Promise} */ static async getById(id: number): Promise { return await dataSource @@ -80,6 +82,9 @@ export default abstract class MemberService { "preferredCommunication", "preferredCommunication.preferred = 1" ) + + .leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1") + .leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming") .leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred") .where("member.id = :id", { id: id }) .getOneOrFail() @@ -90,4 +95,24 @@ export default abstract class MemberService { throw new InternalException("member not found by id", err); }); } + + /** + * @description get newsletter by member by id + * @param {number} id + * @returns {Promise} + */ + static async getNewsletterById(id: number): Promise { + return await dataSource + .getRepository(member) + .createQueryBuilder("member") + .leftJoinAndSelect("member.sendNewsletter", "sendNewsletter") + .where("member.id = :id", { id: id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new InternalException("member not found by id", err); + }); + } } diff --git a/src/viewmodel/admin/communication.models.ts b/src/viewmodel/admin/communication.models.ts index 50e9ac5..64295f8 100644 --- a/src/viewmodel/admin/communication.models.ts +++ b/src/viewmodel/admin/communication.models.ts @@ -11,4 +11,5 @@ export interface CommunicationViewModel { streetNumberAddition: string; type: CommunicationTypeViewModel; isNewsletterMain: boolean; + isSMSAlarming: boolean; } diff --git a/src/viewmodel/admin/member.models.ts b/src/viewmodel/admin/member.models.ts index 5772ff5..c005d9d 100644 --- a/src/viewmodel/admin/member.models.ts +++ b/src/viewmodel/admin/member.models.ts @@ -12,5 +12,6 @@ export interface MemberViewModel { firstMembershipEntry?: MembershipViewModel; lastMembershipEntry?: MembershipViewModel; sendNewsletter?: CommunicationViewModel; + smsAlarming?: Array; preferredCommunication?: Array; }