update newsletter syncing commands and controller

This commit is contained in:
Julian Krauser 2024-12-26 12:34:31 +01:00
parent 4180da5749
commit 6dcd650cad
9 changed files with 16 additions and 49 deletions

View file

@ -1,9 +1,4 @@
export interface SynchronizeNewsletterRecipientsCommand { export interface SynchronizeNewsletterRecipientsCommand {
newsletterId: number; newsletterId: number;
recipients: Array<NewsletterRecipientCommand>; recipients: Array<number>;
}
export interface NewsletterRecipientCommand {
memberId: number;
addedManually: boolean;
} }

View file

@ -2,7 +2,7 @@ import { DeleteResult, EntityManager, InsertResult, UpdateResult } from "typeorm
import { dataSource } from "../data-source"; import { dataSource } from "../data-source";
import InternalException from "../exceptions/internalException"; import InternalException from "../exceptions/internalException";
import NewsletterRecipientsService from "../service/newsletterRecipientsService"; import NewsletterRecipientsService from "../service/newsletterRecipientsService";
import { NewsletterRecipientCommand, SynchronizeNewsletterRecipientsCommand } from "./newsletterRecipientsCommand"; import { SynchronizeNewsletterRecipientsCommand } from "./newsletterRecipientsCommand";
import { newsletterRecipients } from "../entity/newsletterRecipients"; import { newsletterRecipients } from "../entity/newsletterRecipients";
export default abstract class NewsletterRecipientsCommandHandler { export default abstract class NewsletterRecipientsCommandHandler {
@ -12,18 +12,17 @@ export default abstract class NewsletterRecipientsCommandHandler {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async sync(syncNewsletterRecipients: SynchronizeNewsletterRecipientsCommand): Promise<void> { static async sync(syncNewsletterRecipients: SynchronizeNewsletterRecipientsCommand): Promise<void> {
let currentRecipients = await NewsletterRecipientsService.getAll(syncNewsletterRecipients.newsletterId); let currentRecipients = (await NewsletterRecipientsService.getAll(syncNewsletterRecipients.newsletterId)).map(
(r) => r.memberId
);
return await dataSource.manager return await dataSource.manager
.transaction(async (manager) => { .transaction(async (manager) => {
let newRecipients = syncNewsletterRecipients.recipients.filter( let newRecipients = syncNewsletterRecipients.recipients.filter(
(r) => !currentRecipients.map((np) => np.memberId).includes(r.memberId) (r) => !currentRecipients.map((np) => np).includes(r)
); );
let removeRecipients = currentRecipients.filter( let removeRecipients = currentRecipients.filter(
(r) => !syncNewsletterRecipients.recipients.map((np) => np.memberId).includes(r.memberId) (r) => !syncNewsletterRecipients.recipients.map((np) => np).includes(r)
);
let keptRecipients = currentRecipients.filter((r) =>
syncNewsletterRecipients.recipients.map((np) => np.memberId).includes(r.memberId)
); );
if (newRecipients.length != 0) { if (newRecipients.length != 0) {
@ -33,10 +32,6 @@ export default abstract class NewsletterRecipientsCommandHandler {
if (removeRecipients.length != 0) { if (removeRecipients.length != 0) {
await this.syncPresenceRemove(manager, syncNewsletterRecipients.newsletterId, removeRecipients); await this.syncPresenceRemove(manager, syncNewsletterRecipients.newsletterId, removeRecipients);
} }
for (const recipient of keptRecipients) {
await this.syncPresenceUpdate(manager, syncNewsletterRecipients.newsletterId, recipient);
}
}) })
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
@ -47,47 +42,31 @@ export default abstract class NewsletterRecipientsCommandHandler {
private static async syncPresenceAdd( private static async syncPresenceAdd(
manager: EntityManager, manager: EntityManager,
newsletterId: number, newsletterId: number,
recipients: Array<NewsletterRecipientCommand> recipients: Array<number>
): Promise<InsertResult> { ): Promise<InsertResult> {
return await manager return await manager
.createQueryBuilder() .createQueryBuilder()
.insert() .insert()
.into(newsletterRecipients) .into(newsletterRecipients)
.values( .values(
recipients.map((d) => ({ recipients.map((r) => ({
...d, memberId: r,
newsletterId: newsletterId, newsletterId: newsletterId,
})) }))
) )
.execute(); .execute();
} }
private static async syncPresenceUpdate(
manager: EntityManager,
newsletterId: number,
recipient: NewsletterRecipientCommand
): Promise<UpdateResult> {
return await manager
.createQueryBuilder()
.update(newsletterRecipients)
.set({
addedManually: recipient.addedManually,
})
.where("memberId = :memberId", { memberId: recipient.memberId })
.andWhere("newsletterId = :newsletterId", { newsletterId })
.execute();
}
private static async syncPresenceRemove( private static async syncPresenceRemove(
manager: EntityManager, manager: EntityManager,
newsletterId: number, newsletterId: number,
recipients: Array<NewsletterRecipientCommand> recipients: Array<number>
): Promise<DeleteResult> { ): Promise<DeleteResult> {
return await manager return await manager
.createQueryBuilder() .createQueryBuilder()
.delete() .delete()
.from(newsletterRecipients) .from(newsletterRecipients)
.where("memberId IN (:...ids)", { ids: recipients.map((d) => d.memberId) }) .where("memberId IN (:...ids)", { ids: recipients })
.andWhere("newsletterId = :newsletterId", { newsletterId }) .andWhere("newsletterId = :newsletterId", { newsletterId })
.execute(); .execute();
} }

View file

@ -215,14 +215,11 @@ export async function synchronizeNewsletterDatesById(req: Request, res: Response
*/ */
export async function synchronizeNewsletterRecipientsById(req: Request, res: Response): Promise<any> { export async function synchronizeNewsletterRecipientsById(req: Request, res: Response): Promise<any> {
let newsletterId = parseInt(req.params.newsletterId); let newsletterId = parseInt(req.params.newsletterId);
let recipients = req.body.recipients as Array<NewsletterRecipientsViewModel>; let recipients = req.body.recipients as Array<number>;
let syncRecipients: SynchronizeNewsletterRecipientsCommand = { let syncRecipients: SynchronizeNewsletterRecipientsCommand = {
newsletterId, newsletterId,
recipients: recipients.map((r) => ({ recipients: recipients,
memberId: r.memberId,
addedManually: r.addedManually,
})),
}; };
await NewsletterRecipientsCommandHandler.sync(syncRecipients); await NewsletterRecipientsCommandHandler.sync(syncRecipients);

View file

@ -10,9 +10,6 @@ export class newsletterRecipients {
@PrimaryColumn({ type: "int" }) @PrimaryColumn({ type: "int" })
memberId: number; memberId: number;
@Column({ type: "boolean", default: false })
addedManually: boolean;
@ManyToOne(() => newsletter, (newsletter) => newsletter.recipients, { @ManyToOne(() => newsletter, (newsletter) => newsletter.recipients, {
nullable: false, nullable: false,
onDelete: "CASCADE", onDelete: "CASCADE",

View file

@ -17,6 +17,7 @@ export default abstract class NewsletterFactory {
newsletterText: record.newsletterText, newsletterText: record.newsletterText,
newsletterSignatur: record.newsletterSignatur, newsletterSignatur: record.newsletterSignatur,
isSent: record.isSent, isSent: record.isSent,
recipientsByQueryId: record?.recipientsByQuery ? record.recipientsByQuery.id : null,
recipientsByQuery: record?.recipientsByQuery ? QueryStoreFactory.mapToSingle(record.recipientsByQuery) : null, recipientsByQuery: record?.recipientsByQuery ? QueryStoreFactory.mapToSingle(record.recipientsByQuery) : null,
}; };
} }

View file

@ -12,7 +12,6 @@ export default abstract class NewsletterRecipientsFactory {
return { return {
newsletterId: record.newsletterId, newsletterId: record.newsletterId,
memberId: record.memberId, memberId: record.memberId,
addedManually: record.addedManually,
member: MemberFactory.mapToSingle(record.member), member: MemberFactory.mapToSingle(record.member),
}; };
} }

View file

@ -26,7 +26,6 @@ export class Newsletter1735118780511 implements MigrationInterface {
columns: [ columns: [
{ name: "newsletterId", type: variableType_int, isPrimary: true }, { name: "newsletterId", type: variableType_int, isPrimary: true },
{ name: "memberId", type: variableType_int, isPrimary: true }, { name: "memberId", type: variableType_int, isPrimary: true },
{ name: "addedManually", type: "tinyint", default: "0" },
], ],
}), }),
true true

View file

@ -8,5 +8,6 @@ export interface NewsletterViewModel {
newsletterText: string; newsletterText: string;
newsletterSignatur: string; newsletterSignatur: string;
isSent: boolean; isSent: boolean;
recipientsByQueryId?: number;
recipientsByQuery?: QueryStoreViewModel; recipientsByQuery?: QueryStoreViewModel;
} }

View file

@ -3,6 +3,5 @@ import { MemberViewModel } from "./member.models";
export interface NewsletterRecipientsViewModel { export interface NewsletterRecipientsViewModel {
newsletterId: number; newsletterId: number;
memberId: number; memberId: number;
addedManually: boolean;
member: MemberViewModel; member: MemberViewModel;
} }