From 47890fbd4816b46a68a624442b1ceb490be86746 Mon Sep 17 00:00:00 2001 From: Leo Kewitz Date: Thu, 14 Nov 2024 09:38:02 +0100 Subject: [PATCH 1/3] refact: fetch balance in host currency --- src/server/controllers/hosted-collectives.ts | 22 ++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/server/controllers/hosted-collectives.ts b/src/server/controllers/hosted-collectives.ts index a5b39d22..8eea11d3 100644 --- a/src/server/controllers/hosted-collectives.ts +++ b/src/server/controllers/hosted-collectives.ts @@ -60,11 +60,24 @@ type Fields = | 'contributionMonthlyAverageCount' | 'contributionMonthlyAverageTotal' | 'spentTotalMonthlyAverage' - | 'receivedTotalMonthlyAverage'; +const hostQuery = gqlV2` + query HostedCollectives( + $hostSlug: String! + ) { + host(slug: $hostSlug) { + id + legacyId + slug + name + currency + } + } +`; export const hostedCollectivesQuery = gqlV2` query HostedCollectives( $hostSlug: String! + $hostCurrency: Currency! $limit: Int! $offset: Int! $sort: OrderByInput @@ -122,7 +135,7 @@ export const hostedCollectivesQuery = gqlV2` unhostedAt(host: { slug: $hostSlug }) stats { id - balance { + balance(currency: $hostCurrency) { value currency } @@ -340,6 +353,10 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } const hostSlug = req.params.slug; assert(hostSlug, 'Please provide a slug'); + const hostResult = await graphqlRequest(hostQuery, { hostSlug }, { version: 'v2', headers }); + const host = hostResult.host; + assert(host, 'Could not find Host'); + const fields = (get(req.query, 'fields', '') as string) .split(',') .map(trim) @@ -347,6 +364,7 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } const variables = { hostSlug, + hostCurrency: host.currency, limit: req.method === 'HEAD' ? 0 : req.query.limit ? toNumber(req.query.limit) : 1000, offset: req.query.offset ? toNumber(req.query.offset) : 0, sort: req.query.sort && JSON.parse(req.query.sort as string), From 6e30ccf0f89ab985a9ef78578029218d74dc5ecc Mon Sep 17 00:00:00 2001 From: Leo Kewitz Date: Thu, 14 Nov 2024 09:41:57 +0100 Subject: [PATCH 2/3] refact: average periods as argument and refunded total --- src/server/controllers/hosted-collectives.ts | 60 ++++++++++++++------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/server/controllers/hosted-collectives.ts b/src/server/controllers/hosted-collectives.ts index 8eea11d3..e19ca2b2 100644 --- a/src/server/controllers/hosted-collectives.ts +++ b/src/server/controllers/hosted-collectives.ts @@ -43,6 +43,7 @@ type Fields = | 'numberOfPayeesYear' | 'numberOfContributionsYear' | 'valueOfContributionsYear' + | 'valueOfRefundedContributionsYear' | 'valueOfHostFeeYear' | 'spentTotalYear' | 'receivedTotalYear' @@ -52,6 +53,7 @@ type Fields = | 'numberOfPayeesAllTime' | 'numberOfContributionsAllTime' | 'valueOfContributionsAllTime' + | 'valueOfRefundedContributionsAllTime' | 'valueOfHostFeeAllTime' | 'spentTotalAllTime' | 'receivedTotalAllTime' @@ -60,6 +62,10 @@ type Fields = | 'contributionMonthlyAverageCount' | 'contributionMonthlyAverageTotal' | 'spentTotalMonthlyAverage' + | 'receivedTotalMonthlyAverage' + | 'spentTotalYearlyAverage' + | 'receivedTotalYearlyAverage'; + const hostQuery = gqlV2` query HostedCollectives( $hostSlug: String! @@ -172,32 +178,36 @@ export const hostedCollectivesQuery = gqlV2` } } yearSummary: summary(dateFrom: $lastYear) @include(if: $includeYearSummary) { - expenseTotal { valueInCents, value, currency } + expenseTotal { value, currency } expenseCount - expenseMaxValue { valueInCents, value, currency } + expenseMaxValue { value, currency } expenseDistinctPayee contributionCount - contributionTotal { valueInCents, value, currency } - hostFeeTotal { valueInCents, value, currency } - spentTotal { valueInCents, value, currency } - receivedTotal { valueInCents, value, currency } + contributionTotal { value, currency } + contributionRefundedTotal { value, currency } + hostFeeTotal { value, currency } + spentTotal { value, currency } + receivedTotal { value, currency } } allTimeSummary: summary @include(if: $includeAllTimeSummary) { - expenseTotal { valueInCents, value, currency } + expenseTotal { value, currency } expenseCount - expenseMaxValue { valueInCents, value, currency } + expenseMaxValue { value, currency } expenseDistinctPayee contributionCount - contributionTotal { valueInCents, value, currency } - hostFeeTotal { valueInCents, value, currency } - spentTotal { valueInCents, value, currency } - receivedTotal { valueInCents, value, currency } - expenseMonthlyAverageCount - expenseMonthlyAverageTotal { valueInCents, value, currency } - contributionMonthlyAverageCount - contributionMonthlyAverageTotal { valueInCents, value, currency } - spentTotalMonthlyAverage { valueInCents, value, currency } - receivedTotalMonthlyAverage { valueInCents, value, currency } + contributionTotal { value, currency } + contributionRefundedTotal { value, currency } + hostFeeTotal { value, currency } + spentTotal { value, currency } + receivedTotal { value, currency } + expenseMonthlyAverageCount: expenseAverageCount(period: MONTH) + expenseMonthlyAverageTotal: expenseAverageTotal(period: MONTH) { value, currency } + contributionMonthlyAverageCount: contributionAverageCount(period: MONTH) + contributionMonthlyAverageTotal: contributionAverageTotal(period: MONTH) { value, currency } + spentTotalMonthlyAverage: spentTotalAverage(period: MONTH) { value, currency } + receivedTotalMonthlyAverage: receivedTotalAverage(period: MONTH) { value, currency } + spentTotalYearlyAverage: spentTotalAverage(period: YEAR) { value, currency } + receivedTotalYearlyAverage: receivedTotalAverage(period: YEAR) { value, currency } } } admins: members(role: [ADMIN]) { @@ -294,6 +304,8 @@ const csvMapping: Record = { numberOfContributionsYear: (account) => account.yearSummary?.contributionCount, valueOfContributionsYear: (account) => account.yearSummary?.contributionTotal && amountAsString(account.yearSummary.contributionTotal), + valueOfRefundedContributionsYear: (account) => + account.yearSummary?.contributionRefundedTotal && amountAsString(account.yearSummary.contributionRefundedTotal), valueOfHostFeeYear: (account) => account.yearSummary?.hostFeeTotal && amountAsString(account.yearSummary.hostFeeTotal), spentTotalYear: (account) => account.yearSummary?.spentTotal && amountAsString(account.yearSummary.spentTotal), @@ -308,6 +320,9 @@ const csvMapping: Record = { numberOfContributionsAllTime: (account) => account.allTimeSummary?.contributionCount, valueOfContributionsAllTime: (account) => account.allTimeSummary?.contributionTotal && amountAsString(account.allTimeSummary.contributionTotal), + valueOfRefundedContributionsAllTime: (account) => + account.allTimeSummary?.contributionRefundedTotal && + amountAsString(account.allTimeSummary.contributionRefundedTotal), valueOfHostFeeAllTime: (account) => account.allTimeSummary?.hostFeeTotal && amountAsString(account.allTimeSummary.hostFeeTotal), spentTotalAllTime: (account) => @@ -327,6 +342,11 @@ const csvMapping: Record = { receivedTotalMonthlyAverage: (account) => account.allTimeSummary?.receivedTotalMonthlyAverage && amountAsString(account.allTimeSummary.receivedTotalMonthlyAverage), + spentTotalYearlyAverage: (account) => + account.allTimeSummary?.spentTotalYearlyAverage && amountAsString(account.allTimeSummary.spentTotalYearlyAverage), + receivedTotalYearlyAverage: (account) => + account.allTimeSummary?.receivedTotalYearlyAverage && + amountAsString(account.allTimeSummary.receivedTotalYearlyAverage), }; const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' }> = async (req, res) => { @@ -385,6 +405,7 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } 'numberOfPayeesYear', 'numberOfContributionsYear', 'valueOfContributionsYear', + 'valueOfRefundedContributionsYear', 'valueOfHostFeeYear', 'spentTotalYear', 'receivedTotalYear', @@ -398,6 +419,7 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } 'numberOfPayeesAllTime', 'numberOfContributionsAllTime', 'valueOfContributionsAllTime', + 'valueOfRefundedContributionsAllTime', 'valueOfHostFeeAllTime', 'spentTotalAllTime', 'receivedTotalAllTime', @@ -405,6 +427,8 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } 'expenseMonthlyAverageTotal', 'contributionMonthlyAverageCount', 'contributionMonthlyAverageTotal', + 'spentTotalYearlyAverage', + 'receivedTotalYearlyAverage', ].includes(field), ), }; From e254aeff47b03f8f1fd2ccd69b52612fb155595f Mon Sep 17 00:00:00 2001 From: Leo Kewitz Date: Thu, 14 Nov 2024 09:42:04 +0100 Subject: [PATCH 3/3] chore: update schema --- src/graphql/schemaV2.graphql | 45 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/graphql/schemaV2.graphql b/src/graphql/schemaV2.graphql index 8871ac28..84233034 100644 --- a/src/graphql/schemaV2.graphql +++ b/src/graphql/schemaV2.graphql @@ -9600,36 +9600,45 @@ Return a summary of transaction info about a given account within the context of """ type HostedAccountSummary { expenseCount: Int + expenseTotal: Amount + expenseMaxValue: Amount + expenseDistinctPayee: Int + contributionCount: Int + contributionTotal: Amount + hostFeeTotal: Amount + spentTotal: Amount + receivedTotal: Amount """ - Average calculated based on the number of months since the first transaction of this kind within the requested time frame + Average calculated over the number of months the collective was approved or the number of months since dateFrom, whichever is less """ - expenseMonthlyAverageCount: Float - expenseTotal: Amount + expenseAverageTotal(period: AveragePeriod = MONTH): Amount """ - Average calculated based on the number of months since the first transaction of this kind within the requested time frame + Average calculated over the number of months the collective was approved or the number of months since dateFrom, whichever is less """ - expenseMonthlyAverageTotal: Amount - expenseMaxValue: Amount - expenseDistinctPayee: Int - contributionCount: Int + expenseAverageCount(period: AveragePeriod = MONTH): Float """ - Average calculated based on the number of months since the first transaction of this kind within the requested time frame + Average calculated over the number of months the collective was approved or the number of months since dateFrom, whichever is less """ - contributionMonthlyAverageCount: Float - contributionTotal: Amount + contributionAverageTotal(period: AveragePeriod = MONTH): Amount """ - Average calculated based on the number of months since the first transaction of this kind within the requested time frame + Average calculated over the number of months/years the collective was approved or the number of months since dateFrom, whichever is less """ - contributionMonthlyAverageTotal: Amount - hostFeeTotal: Amount - spentTotal: Amount - receivedTotal: Amount - spentTotalMonthlyAverage: Amount - receivedTotalMonthlyAverage: Amount + contributionAverageCount(period: AveragePeriod = MONTH): Float + spentTotalAverage(period: AveragePeriod = MONTH): Amount + receivedTotalAverage(period: AveragePeriod = MONTH): Amount + contributionRefundedTotal: Amount +} + +""" +The period over which the average is calculated +""" +enum AveragePeriod { + YEAR + MONTH } """