feature/#32-Membership-statistics #48

Merged
jkeffects merged 2 commits from feature/#32-Membership-statistics into develop 2025-01-22 08:06:26 +00:00
10 changed files with 183 additions and 36 deletions
Showing only changes of commit 07d31bfe7d - Show all commits

View file

@ -90,6 +90,19 @@ export async function getMemberById(req: Request, res: Response): Promise<any> {
res.json(MemberFactory.mapToSingle(member));
}
/**
* @description get member statistics by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getMemberStatisticsById(req: Request, res: Response): Promise<any> {
const memberId = parseInt(req.params.id);
let member = await MemberService.getStatisticsById(memberId);
res.json(MemberFactory.mapToMemberStatistic(member));
}
/**
* @description get memberships by member
* @param req {Request} Express req object
@ -103,6 +116,19 @@ export async function getMembershipsByMember(req: Request, res: Response): Promi
res.json(MembershipFactory.mapToBase(memberships));
}
/**
* @description get member statistics by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getMembershipStatisticsById(req: Request, res: Response): Promise<any> {
const memberId = parseInt(req.params.id);
let member = await MembershipService.getStatisticsById(memberId);
res.json(MembershipFactory.mapToMembershipStatistic(member));
}
/**
* @description get membership by member and record
* @param req {Request} Express req object

View file

@ -1,5 +1,6 @@
import { member } from "../../../../entity/club/member/member";
import { MemberViewModel } from "../../../../viewmodel/admin/club/member/member.models";
import { MemberStatisticsViewModel, MemberViewModel } from "../../../../viewmodel/admin/club/member/member.models";
import { memberView } from "../../../../views/memberView";
import CommunicationFactory from "./communication";
import MembershipFactory from "./membership";
@ -40,4 +41,23 @@ export default abstract class MemberFactory {
public static mapToBase(records: Array<member>): Array<MemberViewModel> {
return records.map((r) => this.mapToSingle(r));
}
/**
* @description map view record to MemberMembershipStatisticsViewModel
* @param {memberView} record
* @returns {MemberStatisticsViewModel}
*/
public static mapToMemberStatistic(record: memberView): MemberStatisticsViewModel {
return {
id: record.id,
salutation: record.salutation,
firstname: record.firstname,
lastname: record.lastname,
nameaffix: record.nameaffix,
birthdate: record.birthdate,
todayAge: record.todayAge,
ageThisYear: record.ageThisYear,
exactAge: record.exactAge,
};
}
}

View file

@ -1,5 +1,9 @@
import { membership } from "../../../../entity/club/member/membership";
import { MembershipViewModel } from "../../../../viewmodel/admin/club/member/membership.models";
import {
MembershipStatisticsViewModel,
MembershipViewModel,
} from "../../../../viewmodel/admin/club/member/membership.models";
import { membershipView } from "../../../../views/membershipsView";
export default abstract class MembershipFactory {
/**
@ -26,4 +30,24 @@ export default abstract class MembershipFactory {
public static mapToBase(records: Array<membership>): Array<MembershipViewModel> {
return records.map((r) => this.mapToSingle(r));
}
/**
* @description map view record to MembershipStatisticsViewModel
* @param {membershipView} record
* @returns {MembershipStatisticsViewModel}
*/
public static mapToMembershipStatistic(record: membershipView): MembershipStatisticsViewModel {
return {
durationInDays: record.durationInDays,
durationInYears: record.durationInYears,
status: record.status,
statusId: record.statusId,
memberId: record.memberId,
memberSalutation: record.memberSalutation,
memberFirstname: record.memberFirstname,
memberLastname: record.memberLastname,
memberNameaffix: record.memberNameaffix,
memberBirthdate: record.memberBirthdate,
};
}
}

View file

@ -1,36 +1,38 @@
import express, { Request, Response } from "express";
import {
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,
addAwardToMember,
addCommunicationToMember,
addExecutivePositionToMember,
addMembershipToMember,
addQualificationToMember,
createMember,
createMemberPrintoutList,
deleteAwardOfMember,
deleteCommunicationOfMember,
deleteExecutivePositionOfMember,
deleteMemberById,
deleteMembershipOfMember,
deleteQualificationOfMember,
getAllMembers,
getAwardByMemberAndRecord,
getAwardsByMember,
getCommunicationByMemberAndRecord,
getCommunicationsByMember,
getExecutivePositionByMemberAndRecord,
getExecutivePositionsByMember,
getMemberById,
getMembershipByMemberAndRecord,
getMembershipsByMember,
getMembershipStatisticsById,
getMemberStatisticsById,
getQualificationByMemberAndRecord,
getQualificationsByMember,
updateAwardOfMember,
updateCommunicationOfMember,
updateExecutivePositionOfMember,
updateMemberById,
updateMembershipOfMember,
updateQualificationOfMember,
} from "../../../controller/admin/club/memberController";
import PermissionHelper from "../../../helpers/permissionHelper";
@ -44,14 +46,22 @@ router.get("/:id", async (req: Request, res: Response) => {
await getMemberById(req, res);
});
router.get("/:id/statistics", async (req: Request, res: Response) => {
await getMemberStatisticsById(req, res);
});
router.get("/print/namelist", async (req: Request, res: Response) => {
await createMemberPrintoutList(req, res);
await createMemberPrintoutList(req, res);
});
router.get("/:memberId/memberships", async (req: Request, res: Response) => {
await getMembershipsByMember(req, res);
});
router.get("/:memberId/statistics/memberships", async (req: Request, res: Response) => {
await getMembershipStatisticsById(req, res);
});
router.get("/:memberId/membership/:id", async (req: Request, res: Response) => {
await getMembershipByMemberAndRecord(req, res);
});

View file

@ -2,6 +2,7 @@ import { dataSource } from "../../../data-source";
import { member } from "../../../entity/club/member/member";
import { membership } from "../../../entity/club/member/membership";
import InternalException from "../../../exceptions/internalException";
import { memberView } from "../../../views/memberView";
export default abstract class MemberService {
/**
@ -132,6 +133,25 @@ export default abstract class MemberService {
});
}
/**
* @description get member statistics by id
* @param {number} id
* @returns {Promise<memberView>}
*/
static async getStatisticsById(id: number): Promise<memberView> {
return await dataSource
.getRepository(memberView)
.createQueryBuilder("memberView")
.where("memberView.id = :id", { id: id })
.getOneOrFail()
.then((res) => {
return res;
})
.catch((err) => {
throw new InternalException("memberView not found by id", err);
});
}
/**
* @description get members where membership is setz
* @returns {Promise<member>}

View file

@ -1,6 +1,7 @@
import { dataSource } from "../../../data-source";
import { membership } from "../../../entity/club/member/membership";
import InternalException from "../../../exceptions/internalException";
import { membershipView } from "../../../views/membershipsView";
export default abstract class MembershipService {
/**
@ -45,4 +46,23 @@ export default abstract class MembershipService {
throw new InternalException("member membership not found by id", err);
});
}
/**
* @description get membership statistics by memberId
* @param {number} memberId
* @returns {Promise<membershipView>}
*/
static async getStatisticsById(memberId: number): Promise<membershipView> {
return await dataSource
.getRepository(membershipView)
.createQueryBuilder("membershipView")
.where("membershipView.memberId = :memberId", { memberId: memberId })
.getOneOrFail()
.then((res) => {
return res;
})
.catch((err) => {
throw new InternalException("membershipView not found by id", err);
});
}
}

View file

@ -16,3 +16,15 @@ export interface MemberViewModel {
smsAlarming?: Array<CommunicationViewModel>;
preferredCommunication?: Array<CommunicationViewModel>;
}
export interface MemberStatisticsViewModel {
id: number;
salutation: Salutation;
firstname: string;
lastname: string;
nameaffix: string;
birthdate: Date;
todayAge: number;
ageThisYear: number;
exactAge: string;
}

View file

@ -1,3 +1,5 @@
import { Salutation } from "../../../../enums/salutation";
export interface MembershipViewModel {
id: number;
start: Date;
@ -6,3 +8,16 @@ export interface MembershipViewModel {
status: string;
statusId: number;
}
export interface MembershipStatisticsViewModel {
durationInDays: number;
durationInYears: string;
status: string;
statusId: number;
memberId: number;
memberSalutation: Salutation;
memberFirstname: string;
memberLastname: string;
memberNameaffix: string;
memberBirthdate: Date;
}

View file

@ -43,5 +43,5 @@ export class memberView {
ageThisYear: number;
@ViewColumn()
exactAge: Date;
exactAge: string;
}

View file

@ -30,7 +30,7 @@ export class membershipView {
durationInDays: number;
@ViewColumn()
durationInYears: Date;
durationInYears: string;
@ViewColumn()
status: string;