From 5d3f8ea46a72154f70d4d5044fc86f6b9a8801e8 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 5 Jan 2025 13:43:03 +0100 Subject: [PATCH] #30 Attendance list with all members --- src/controller/admin/memberController.ts | 29 +++++++++ .../admin/templateUsageController.ts | 4 +- src/data-source.ts | 2 + src/demodata/member.list.data.ts | 13 ++++ src/entity/templateUsage.ts | 2 +- src/helpers/demoDataHelper.ts | 5 +- src/helpers/pdfExport.ts | 2 +- src/helpers/templateHelper.ts | 2 +- src/migrations/1736079005086-memberlist.ts | 26 ++++++++ src/routes/admin/member.ts | 65 ++++++++++--------- src/service/memberService.ts | 23 ++++++- src/templates/member.list.body.template.html | 46 +++++++++++++ .../member.list.footer.template.html | 3 + src/viewmodel/admin/templateUsage.models.ts | 2 +- 14 files changed, 185 insertions(+), 39 deletions(-) create mode 100644 src/demodata/member.list.data.ts create mode 100644 src/migrations/1736079005086-memberlist.ts create mode 100644 src/templates/member.list.body.template.html create mode 100644 src/templates/member.list.footer.template.html diff --git a/src/controller/admin/memberController.ts b/src/controller/admin/memberController.ts index 9aa6446..ac48217 100644 --- a/src/controller/admin/memberController.ts +++ b/src/controller/admin/memberController.ts @@ -48,6 +48,8 @@ import { UpdateCommunicationCommand, } from "../../command/communicationCommand"; import CommunicationCommandHandler from "../../command/communicationCommandHandler"; +import {PdfExport} from "../../helpers/pdfExport"; +import {PermissionModule} from "../../type/permissionTypes"; /** * @description get all members @@ -218,6 +220,33 @@ export async function getCommunicationByMemberAndRecord(req: Request, res: Respo res.json(CommunicationFactory.mapToSingle(communication)); } +/** + * @description create member printout list + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function createMemberPrintoutList(req: Request, res: Response): Promise { + let members = await MemberService.getByRunningMembership() + + let pdf = await PdfExport.renderFile({ + title: "Mitgliederliste", + template: "member.list", + saveToDisk: false, + data: { + member: members + }, + }); + + let pdfbuffer = Buffer.from(pdf); + + res.setHeader("Content-Type", "application/pdf"); + res.setHeader("Content-Length", pdfbuffer.byteLength); + res.setHeader("Content-Disposition", "inline; filename=preview.pdf"); + + res.send(pdfbuffer); +} + /** * @description create member * @param req {Request} Express req object diff --git a/src/controller/admin/templateUsageController.ts b/src/controller/admin/templateUsageController.ts index 0a75af3..a00c525 100644 --- a/src/controller/admin/templateUsageController.ts +++ b/src/controller/admin/templateUsageController.ts @@ -21,8 +21,8 @@ export async function getAllTemplateUsages(req: Request, res: Response): Promise if (!req.isOwner) { templateUsages = templateUsages.filter((tu) => { return ( - PermissionHelper.can(req.permissions, "update", "settings", tu.scope) || - PermissionHelper.can(req.permissions, "update", "club", tu.scope) + PermissionHelper.can(req.permissions, "update", "settings", tu.scope.split(".")[0] as PermissionModule) || + PermissionHelper.can(req.permissions, "update", "club", tu.scope.split(".")[0] as PermissionModule) ); }); } diff --git a/src/data-source.ts b/src/data-source.ts index 770fe2a..fb699c9 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -65,6 +65,7 @@ import { TemplateMargins1735733514043 } from "./migrations/1735733514043-templat import { InternalId1735822722235 } from "./migrations/1735822722235-internalId"; import { PostalCode1735927918979 } from "./migrations/1735927918979-postalCode"; import { ProtocolAbsent1736072179716 } from "./migrations/1736072179716-protocolAbsent"; +import {Memberlist1736079005086} from "./migrations/1736079005086-memberlist"; const dataSource = new DataSource({ type: DB_TYPE as any, @@ -140,6 +141,7 @@ const dataSource = new DataSource({ InternalId1735822722235, PostalCode1735927918979, ProtocolAbsent1736072179716, + Memberlist1736079005086 ], migrationsRun: true, migrationsTransactionMode: "each", diff --git a/src/demodata/member.list.data.ts b/src/demodata/member.list.data.ts new file mode 100644 index 0000000..3df0f88 --- /dev/null +++ b/src/demodata/member.list.data.ts @@ -0,0 +1,13 @@ +import { member } from "../entity/member"; +import { protocolAgenda } from "../entity/protocolAgenda"; +import { protocolDecision } from "../entity/protocolDecision"; +import { protocolVoting } from "../entity/protocolVoting"; + +export const memberlistDemoData: { member: Array> } = { + member: [ + { + firstname: "Julian", + lastname: "Krauser", + }, + ] +} diff --git a/src/entity/templateUsage.ts b/src/entity/templateUsage.ts index 00f41bf..0e0338e 100644 --- a/src/entity/templateUsage.ts +++ b/src/entity/templateUsage.ts @@ -5,7 +5,7 @@ import { PermissionModule } from "../type/permissionTypes"; @Entity() export class templateUsage { @PrimaryColumn({ type: "varchar", length: 255 }) - scope: PermissionModule; + scope: `${PermissionModule}`|`${PermissionModule}.${string}`; @Column({ type: "int", nullable: true }) headerId: number | null; diff --git a/src/helpers/demoDataHelper.ts b/src/helpers/demoDataHelper.ts index e02e5b5..3187ca1 100644 --- a/src/helpers/demoDataHelper.ts +++ b/src/helpers/demoDataHelper.ts @@ -1,14 +1,17 @@ import { newsletterDemoData } from "../demodata/newsletter.data"; import { protocolDemoData } from "../demodata/protocol.data"; import { PermissionModule } from "../type/permissionTypes"; +import {memberlistDemoData} from "../demodata/member.list.data"; export abstract class DemoDataHelper { - static getData(scope: PermissionModule) { + static getData(scope: `${PermissionModule}`|`${PermissionModule}.${string}`) { switch (scope) { case "protocol": return protocolDemoData; case "newsletter": return newsletterDemoData; + case "member.list": + return memberlistDemoData; default: return {}; } diff --git a/src/helpers/pdfExport.ts b/src/helpers/pdfExport.ts index ee1af97..00a65a8 100644 --- a/src/helpers/pdfExport.ts +++ b/src/helpers/pdfExport.ts @@ -13,7 +13,7 @@ export abstract class PdfExport { saveToDisk = true, folder = "", }: { - template: PermissionModule; + template: `${PermissionModule}`|`${PermissionModule}.${string}`; title?: string; filename?: string; data?: any; diff --git a/src/helpers/templateHelper.ts b/src/helpers/templateHelper.ts index eb681b6..aa9f42a 100644 --- a/src/helpers/templateHelper.ts +++ b/src/helpers/templateHelper.ts @@ -34,7 +34,7 @@ export abstract class TemplateHelper { bodyData = {}, footerData = {}, }: { - module: PermissionModule; + module: `${PermissionModule}`|`${PermissionModule}.${string}`; title?: string; headerData?: any; bodyData?: any; diff --git a/src/migrations/1736079005086-memberlist.ts b/src/migrations/1736079005086-memberlist.ts new file mode 100644 index 0000000..331099b --- /dev/null +++ b/src/migrations/1736079005086-memberlist.ts @@ -0,0 +1,26 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; +import { templateUsage } from "../entity/templateUsage"; +import {PermissionModule} from "../type/permissionTypes"; + +export class Memberlist1736079005086 implements MigrationInterface { + name = "Memberlist1736079005086"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.manager + .createQueryBuilder() + .insert() + .into(templateUsage) + .values({ scope: "member.list" }) + .orIgnore() + .execute(); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.manager + .createQueryBuilder() + .delete() + .from(templateUsage) + .where({ scope: "member.list" }) + .execute(); + } +} diff --git a/src/routes/admin/member.ts b/src/routes/admin/member.ts index bd45549..4752242 100644 --- a/src/routes/admin/member.ts +++ b/src/routes/admin/member.ts @@ -1,35 +1,36 @@ import express, { Request, Response } from "express"; import { - addAwardToMember, - addCommunicationToMember, - addExecutivePositionToMember, - addMembershipToMember, - addQualificationToMember, - createMember, - deleteAwardOfMember, - deleteCommunicationOfMember, - deleteExecutivePositionOfMember, - deleteMemberById, - deleteMembershipOfMember, - deleteQualificationOfMember, - getAllMembers, - getAwardByMemberAndRecord, - getAwardsByMember, - getCommunicationByMemberAndRecord, - getCommunicationsByMember, - getExecutivePositionByMemberAndRecord, - getExecutivePositionsByMember, - getMemberById, - getMembershipByMemberAndRecord, - getMembershipsByMember, - getQualificationByMemberAndRecord, - getQualificationsByMember, - updateAwardOfMember, - updateCommunicationOfMember, - updateExecutivePositionOfMember, - updateMemberById, - updateMembershipOfMember, - updateQualificationOfMember, + addAwardToMember, + addCommunicationToMember, + addExecutivePositionToMember, + addMembershipToMember, + addQualificationToMember, + createMember, + createMemberPrintoutList, + deleteAwardOfMember, + deleteCommunicationOfMember, + deleteExecutivePositionOfMember, + deleteMemberById, + deleteMembershipOfMember, + deleteQualificationOfMember, + getAllMembers, + getAwardByMemberAndRecord, + getAwardsByMember, + getCommunicationByMemberAndRecord, + getCommunicationsByMember, + getExecutivePositionByMemberAndRecord, + getExecutivePositionsByMember, + getMemberById, + getMembershipByMemberAndRecord, + getMembershipsByMember, + getQualificationByMemberAndRecord, + getQualificationsByMember, + updateAwardOfMember, + updateCommunicationOfMember, + updateExecutivePositionOfMember, + updateMemberById, + updateMembershipOfMember, + updateQualificationOfMember, } from "../../controller/admin/memberController"; import PermissionHelper from "../../helpers/permissionHelper"; @@ -43,6 +44,10 @@ router.get("/:id", async (req: Request, res: Response) => { await getMemberById(req, res); }); +router.get("/print/namelist", async (req: Request, res: Response) => { + await createMemberPrintoutList(req, res); +}); + router.get("/:memberId/memberships", async (req: Request, res: Response) => { await getMembershipsByMember(req, res); }); diff --git a/src/service/memberService.ts b/src/service/memberService.ts index 531c4b6..e3ae0c1 100644 --- a/src/service/memberService.ts +++ b/src/service/memberService.ts @@ -9,7 +9,7 @@ export default abstract class MemberService { * @returns {Promise<[Array, number]>} */ static async getAll(offset: number = 0, count: number = 25, search: string = ""): Promise<[Array, number]> { - let query = await dataSource + let query = dataSource .getRepository(member) .createQueryBuilder("member") .leftJoinAndMapOne( @@ -54,7 +54,7 @@ export default abstract class MemberService { }); } - return query + return await query .offset(offset) .limit(count) .orderBy("member.lastname") @@ -114,6 +114,25 @@ export default abstract class MemberService { }); } + /** + * @description get members where membership is setz + * @returns {Promise} + */ + static async getByRunningMembership(): Promise> { + return await dataSource + .getRepository(member) + .createQueryBuilder("member") + .leftJoinAndSelect("member.memberships", "membership") + .where("membership.end IS NULL") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new InternalException("member not found by id", err); + }); + } + /** * @description get newsletter by member by id * @param {number} id diff --git a/src/templates/member.list.body.template.html b/src/templates/member.list.body.template.html new file mode 100644 index 0000000..9cb0396 --- /dev/null +++ b/src/templates/member.list.body.template.html @@ -0,0 +1,46 @@ + + + + + Mitgliederliste + + +

Mitgliederliste

+
+ + + {{#each member}} + + + + + {{/each}} +
{{this.firstname}} {{this.lastname}} {{this.nameaffix}}
+ + + diff --git a/src/templates/member.list.footer.template.html b/src/templates/member.list.footer.template.html new file mode 100644 index 0000000..7a3190b --- /dev/null +++ b/src/templates/member.list.footer.template.html @@ -0,0 +1,3 @@ +
+ Seite von +
diff --git a/src/viewmodel/admin/templateUsage.models.ts b/src/viewmodel/admin/templateUsage.models.ts index 8783eac..0f42c91 100644 --- a/src/viewmodel/admin/templateUsage.models.ts +++ b/src/viewmodel/admin/templateUsage.models.ts @@ -1,7 +1,7 @@ import { PermissionModule } from "../../type/permissionTypes"; export interface TemplateUsageViewModel { - scope: PermissionModule; + scope: `${PermissionModule}`|`${PermissionModule}.${string}`; header: { id: number; template: string } | null; body: { id: number; template: string } | null; footer: { id: number; template: string } | null;