sms alarming flag #19

Merged
jkeffects merged 1 commit from #18-mark-member-phone-as-sms-alarming into main 2024-11-27 09:08:18 +00:00
14 changed files with 90 additions and 3 deletions

View file

@ -1,5 +1,6 @@
export interface CreateCommunicationCommand { export interface CreateCommunicationCommand {
preferred: boolean; preferred: boolean;
isSMSAlarming: boolean;
mobile: string; mobile: string;
email: string; email: string;
city: string; city: string;
@ -13,6 +14,7 @@ export interface CreateCommunicationCommand {
export interface UpdateCommunicationCommand { export interface UpdateCommunicationCommand {
id: number; id: number;
preferred: boolean; preferred: boolean;
isSMSAlarming: boolean;
mobile: string; mobile: string;
email: string; email: string;
city: string; city: string;

View file

@ -22,6 +22,7 @@ export default abstract class CommunicationCommandHandler {
.into(communication) .into(communication)
.values({ .values({
preferred: createCommunication.preferred, preferred: createCommunication.preferred,
isSMSAlarming: createCommunication.isSMSAlarming,
mobile: createCommunication.mobile, mobile: createCommunication.mobile,
email: createCommunication.email, email: createCommunication.email,
city: createCommunication.city, city: createCommunication.city,
@ -59,6 +60,7 @@ export default abstract class CommunicationCommandHandler {
.update(communication) .update(communication)
.set({ .set({
preferred: updateCommunication.preferred, preferred: updateCommunication.preferred,
isSMSAlarming: updateCommunication.isSMSAlarming,
mobile: updateCommunication.mobile, mobile: updateCommunication.mobile,
email: updateCommunication.email, email: updateCommunication.email,
city: updateCommunication.city, city: updateCommunication.city,

View file

@ -68,7 +68,6 @@ export default abstract class MemberCommandHandler {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async updateNewsletter(updateMember: UpdateMemberNewsletterCommand): Promise<void> { static async updateNewsletter(updateMember: UpdateMemberNewsletterCommand): Promise<void> {
console.log(updateMember);
return await dataSource return await dataSource
.createQueryBuilder() .createQueryBuilder()
.update(member) .update(member)
@ -88,6 +87,26 @@ export default abstract class MemberCommandHandler {
}); });
} }
/**
* @description update member newsletter to unset
* @param memberId string
* @returns {Promise<void>}
*/
static async unsetNewsletter(memberId: number): Promise<void> {
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 * @description delete member
* @param DeleteMemberCommand * @param DeleteMemberCommand

View file

@ -346,6 +346,7 @@ export async function addExecutivePositionToMember(req: Request, res: Response):
export async function addCommunicationToMember(req: Request, res: Response): Promise<any> { export async function addCommunicationToMember(req: Request, res: Response): Promise<any> {
const memberId = parseInt(req.params.memberId); const memberId = parseInt(req.params.memberId);
const preferred = req.body.preferred; const preferred = req.body.preferred;
const isSMSAlarming = req.body.isSMSAlarming;
const mobile = req.body.mobile; const mobile = req.body.mobile;
const email = req.body.email; const email = req.body.email;
const city = req.body.city; const city = req.body.city;
@ -357,6 +358,7 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro
let createCommunication: CreateCommunicationCommand = { let createCommunication: CreateCommunicationCommand = {
preferred, preferred,
isSMSAlarming,
mobile, mobile,
email, email,
city, city,
@ -528,6 +530,7 @@ export async function updateCommunicationOfMember(req: Request, res: Response):
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 preferred = req.body.preferred; const preferred = req.body.preferred;
const isSMSAlarming = req.body.isSMSAlarming;
const mobile = req.body.mobile; const mobile = req.body.mobile;
const email = req.body.email; const email = req.body.email;
const city = req.body.city; const city = req.body.city;
@ -540,6 +543,7 @@ export async function updateCommunicationOfMember(req: Request, res: Response):
let updateCommunication: UpdateCommunicationCommand = { let updateCommunication: UpdateCommunicationCommand = {
id: recordId, id: recordId,
preferred, preferred,
isSMSAlarming,
mobile, mobile,
email, email,
city, city,
@ -550,12 +554,16 @@ export async function updateCommunicationOfMember(req: Request, res: Response):
}; };
await CommunicationCommandHandler.update(updateCommunication); await CommunicationCommandHandler.update(updateCommunication);
let currentUserNewsletterMain = await MemberService.getNewsletterById(memberId);
if (isNewsletterMain) { if (isNewsletterMain) {
let updateNewsletter: UpdateMemberNewsletterCommand = { let updateNewsletter: UpdateMemberNewsletterCommand = {
id: memberId, id: memberId,
communicationId: recordId, communicationId: recordId,
}; };
await MemberCommandHandler.updateNewsletter(updateNewsletter); await MemberCommandHandler.updateNewsletter(updateNewsletter);
} else if (currentUserNewsletterMain.sendNewsletter.id == recordId) {
await MemberCommandHandler.unsetNewsletter(memberId);
} }
res.sendStatus(204); res.sendStatus(204);

View file

@ -42,6 +42,7 @@ import { calendarType } from "./entity/calendarType";
import { Calendar1729947763295 } from "./migrations/1729947763295-calendar"; import { Calendar1729947763295 } from "./migrations/1729947763295-calendar";
import { reset } from "./entity/reset"; import { reset } from "./entity/reset";
import { ResetToken1732358596823 } from "./migrations/1732358596823-resetToken"; import { ResetToken1732358596823 } from "./migrations/1732358596823-resetToken";
import { SMSAlarming1732696919191 } from "./migrations/1732696919191-SMSAlarming";
const dataSource = new DataSource({ const dataSource = new DataSource({
type: DB_TYPE as any, type: DB_TYPE as any,
@ -94,6 +95,7 @@ const dataSource = new DataSource({
Protocol1729347911107, Protocol1729347911107,
Calendar1729947763295, Calendar1729947763295,
ResetToken1732358596823, ResetToken1732358596823,
SMSAlarming1732696919191,
], ],
migrationsRun: true, migrationsRun: true,
migrationsTransactionMode: "each", migrationsTransactionMode: "each",

View file

@ -10,6 +10,9 @@ export class communication {
@Column({ type: "boolean", default: false }) @Column({ type: "boolean", default: false })
preferred: boolean; preferred: boolean;
@Column({ type: "boolean", default: false })
isSMSAlarming: boolean;
@Column({ type: "varchar", length: 255, nullable: true }) @Column({ type: "varchar", length: 255, nullable: true })
mobile: string; mobile: string;

View file

@ -65,4 +65,5 @@ export class member {
firstMembershipEntry?: membership; firstMembershipEntry?: membership;
lastMembershipEntry?: membership; lastMembershipEntry?: membership;
preferredCommunication?: Array<communication>; preferredCommunication?: Array<communication>;
smsAlarming?: Array<communication>;
} }

View file

@ -20,6 +20,7 @@ export default abstract class CommunicationFactory {
streetNumberAddition: record.streetNumberAddition, streetNumberAddition: record.streetNumberAddition,
type: CommunicationTypeFactory.mapToSingle(record.type), type: CommunicationTypeFactory.mapToSingle(record.type),
isNewsletterMain: isMain ? isMain : record?.member?.sendNewsletter?.id == record.id, isNewsletterMain: isMain ? isMain : record?.member?.sendNewsletter?.id == record.id,
isSMSAlarming: record.isSMSAlarming,
}; };
} }

View file

@ -27,6 +27,7 @@ export default abstract class MemberFactory {
preferredCommunication: record?.preferredCommunication preferredCommunication: record?.preferredCommunication
? CommunicationFactory.mapToBase(record.preferredCommunication) ? CommunicationFactory.mapToBase(record.preferredCommunication)
: null, : null,
smsAlarming: record?.smsAlarming ? CommunicationFactory.mapToBase(record.smsAlarming) : null,
}; };
} }

View file

@ -0,0 +1,21 @@
import { MigrationInterface, QueryRunner, TableColumn } from "typeorm";
export class SMSAlarming1732696919191 implements MigrationInterface {
name = "SMSAlarming1732696919191";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.addColumn(
"communication",
new TableColumn({
name: "isSMSAlarming",
type: "tinyint",
default: 0,
isNullable: false,
})
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropColumn("communication", "isSMSAlarming");
}
}

View file

@ -56,6 +56,6 @@ export default abstract class CommunicationService {
static getAvailableColumnsForCommunication(): Array<string> { static getAvailableColumnsForCommunication(): Array<string> {
let metadata = dataSource.getMetadata(communication); let metadata = dataSource.getMetadata(communication);
let columns = metadata.columns.map((c) => c.propertyName); 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));
} }
} }

View file

@ -35,6 +35,8 @@ export default abstract class MemberService {
"preferredCommunication.preferred = 1" "preferredCommunication.preferred = 1"
) )
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred") .leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
.offset(offset) .offset(offset)
.limit(count) .limit(count)
.orderBy("member.lastname") .orderBy("member.lastname")
@ -52,7 +54,7 @@ export default abstract class MemberService {
/** /**
* @description get member by id * @description get member by id
* @param {number} id * @param {number} id
* @returns {Promise<Array<member>>} * @returns {Promise<member>}
*/ */
static async getById(id: number): Promise<member> { static async getById(id: number): Promise<member> {
return await dataSource return await dataSource
@ -80,6 +82,9 @@ export default abstract class MemberService {
"preferredCommunication", "preferredCommunication",
"preferredCommunication.preferred = 1" "preferredCommunication.preferred = 1"
) )
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred") .leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
.where("member.id = :id", { id: id }) .where("member.id = :id", { id: id })
.getOneOrFail() .getOneOrFail()
@ -90,4 +95,24 @@ export default abstract class MemberService {
throw new InternalException("member not found by id", err); throw new InternalException("member not found by id", err);
}); });
} }
/**
* @description get newsletter by member by id
* @param {number} id
* @returns {Promise<member>}
*/
static async getNewsletterById(id: number): Promise<member> {
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);
});
}
} }

View file

@ -11,4 +11,5 @@ export interface CommunicationViewModel {
streetNumberAddition: string; streetNumberAddition: string;
type: CommunicationTypeViewModel; type: CommunicationTypeViewModel;
isNewsletterMain: boolean; isNewsletterMain: boolean;
isSMSAlarming: boolean;
} }

View file

@ -12,5 +12,6 @@ export interface MemberViewModel {
firstMembershipEntry?: MembershipViewModel; firstMembershipEntry?: MembershipViewModel;
lastMembershipEntry?: MembershipViewModel; lastMembershipEntry?: MembershipViewModel;
sendNewsletter?: CommunicationViewModel; sendNewsletter?: CommunicationViewModel;
smsAlarming?: Array<CommunicationViewModel>;
preferredCommunication?: Array<CommunicationViewModel>; preferredCommunication?: Array<CommunicationViewModel>;
} }