From 48c54961ecc3f45a1532cefd2fd03ffa9d840abd Mon Sep 17 00:00:00 2001 From: Alexander Petkov Date: Thu, 7 Dec 2023 13:15:20 +0200 Subject: [PATCH] src/donations: Fix wrong unique donors count Currently when we count unique donors we group them by billing_name, which gives us the total number of unique donors. The number of total donors is then added, to the total amount of donations made by the first user in the returned query. This results in overestimating the actually count of unique donors. Changed the query to plain SQL, as prisma doesn't yet support counting by distinct properties, and counting is relatively faster to process, than grouping or searching Changed the query to count by distinct billing_email property, rather than billing_name, as email is the "more unique" property of the two. --- apps/api/src/donations/donations.service.ts | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/apps/api/src/donations/donations.service.ts b/apps/api/src/donations/donations.service.ts index 2b6795aad..ed5609543 100644 --- a/apps/api/src/donations/donations.service.ts +++ b/apps/api/src/donations/donations.service.ts @@ -770,22 +770,14 @@ export class DonationsService { } async getDonorsCount() { - const donorsCount = await this.prisma.donation.groupBy({ - by: ['billingName'], - where: { status: DonationStatus.succeeded }, - _count: { - _all: true, - }, - orderBy: { billingName: { sort: 'asc', nulls: 'first' } }, - }) - - // get count of the donations with billingName == null - const anonymousDonations = donorsCount[0]._count._all + const donorsCount = await this.prisma.$queryRaw<{ + count: number + }>`SELECT COUNT (*) FROM (SELECT DISTINCT billing_email FROM donations WHERE status::text=${DonationStatus.succeeded}) AS unique_donors` - const totalCount = donorsCount.length - 1 + anonymousDonations + //Return result is BigInt which can't be serialized. Convert result to string first. + const uniqueDonors = donorsCount[0].count.toString() - // substract one because we don't want to include anonymousDonation again - return { count: totalCount } + return { count: Number(uniqueDonors) } } /**