diff --git a/src/server-extension/organization-resolver.ts b/src/server-extension/organization-resolver.ts index 43c8a79..29c2bf1 100644 --- a/src/server-extension/organization-resolver.ts +++ b/src/server-extension/organization-resolver.ts @@ -1,6 +1,11 @@ import { Arg, Query, Resolver } from "type-graphql"; import type { EntityManager } from "typeorm"; -import { VouchCountPerMonth, VouchCountResult } from "./types"; +import { + VouchCountByUser, + VouchCountByUserResult, + VouchCountPerMonth, + VouchCountResult, +} from "./types"; import { isValidDate } from "./helper"; @Resolver() @@ -84,4 +89,75 @@ export class OrganisationResolver { throw new Error(`Failed to fetch vouch count by date: ${error.message}`); } } + + @Query(() => VouchCountByUserResult) + async getOrganisationUserVouchCountBySource( + @Arg("organisationId", () => String) organisationId: string, + @Arg("source", () => String) source: string, + @Arg("fromDate", () => String) fromDate: string, + @Arg("toDate", () => String) toDate: string + ): Promise { + // Validate date format + if (!isValidDate(fromDate) || !isValidDate(toDate)) { + throw new Error( + "Invalid date format. Dates must be in YYYY-MM-DD format." + ); + } + + const from = new Date(fromDate); + const to = new Date(toDate); + if (from > to) { + throw new Error("`fromDate` cannot be later than `toDate`."); + } + + try { + const manager = await this.tx(); + + const query = ` + SELECT + attestor_organisation.attestor_id AS attestor_id, + COUNT(*) AS total_count + FROM + project_attestation + JOIN attestor_organisation + ON project_attestation.attestor_organisation_id = attestor_organisation.id + JOIN project + ON project_attestation.project_id = project.id + WHERE + attestor_organisation.organisation_id = $1 + AND project.source = $2 + AND project_attestation.vouch = true + AND project_attestation.attest_timestamp BETWEEN $3 AND $4 + GROUP BY + attestor_organisation.attestor_id + ORDER BY + total_count DESC; + `; + + const params = [organisationId, source, fromDate, toDate]; + + const result = await manager.query(query, params); + + let totalVouches = 0; + const vouchCountByUser: VouchCountByUser[] = result.map((row: any) => { + const totalCount = Number(row.total_count); + totalVouches += totalCount; + + return { + attestorId: row.attestor_id, + totalCount, + }; + }); + + return { + totalVouches, + vouchCountByUser, + }; + } catch (error: any) { + console.error("Error fetching attestor vouch count by source:", error); + throw new Error( + `Failed to fetch attestor vouch count by source: ${error.message}` + ); + } + } } diff --git a/src/server-extension/types.ts b/src/server-extension/types.ts index ffd72fb..1c76316 100644 --- a/src/server-extension/types.ts +++ b/src/server-extension/types.ts @@ -38,3 +38,21 @@ export class VouchCountPerMonth { @Field() countWithoutComments: number = 0; } + +@ObjectType() +export class VouchCountByUser { + @Field() + attestorId: string = ""; + + @Field(() => Int) + totalCount: number = 0; +} + +@ObjectType() +export class VouchCountByUserResult { + @Field(() => Int) + totalVouches: number = 0; + + @Field(() => [VouchCountByUser]) + vouchCountByUser: VouchCountByUser[] = []; +}