From 2cdbee92f01b0678d229613d205191988201c942 Mon Sep 17 00:00:00 2001 From: Leo Kewitz Date: Fri, 18 Oct 2024 14:13:53 +0200 Subject: [PATCH] wip --- src/graphql/schemaV2.graphql | 653 ++++++++++++++++++- src/server/controllers/hosted-collectives.ts | 115 +++- src/server/lib/utils.ts | 4 +- 3 files changed, 744 insertions(+), 28 deletions(-) diff --git a/src/graphql/schemaV2.graphql b/src/graphql/schemaV2.graphql index 1b1811d6..f381ede4 100644 --- a/src/graphql/schemaV2.graphql +++ b/src/graphql/schemaV2.graphql @@ -223,6 +223,16 @@ interface Account { """ updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -951,6 +961,41 @@ interface Account { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -1691,6 +1736,23 @@ enum ImageFormat { svg } +input AccountReferenceInput { + """ + The public id identifying the account (ie: dgm9bnk8-0437xqry-ejpvzeol-jdayw5re) + """ + id: String + + """ + The internal id of the account (ie: 580) + """ + legacyId: Int @deprecated(reason: "2020-01-01: should only be used during the transition to GraphQL API v2.") + + """ + The slug identifying the account (ie: babel for https://opencollective.com/babel) + """ + slug: String +} + """ A collection of "Members" (ie: Organization backing a Collective) """ @@ -2612,6 +2674,16 @@ type Host implements Account & AccountWithContributions { createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -3356,6 +3428,41 @@ type Host implements Account & AccountWithContributions { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -4052,23 +4159,6 @@ type Contributor { publicMessage: String } -input AccountReferenceInput { - """ - The public id identifying the account (ie: dgm9bnk8-0437xqry-ejpvzeol-jdayw5re) - """ - id: String - - """ - The internal id of the account (ie: 580) - """ - legacyId: Int @deprecated(reason: "2020-01-01: should only be used during the transition to GraphQL API v2.") - - """ - The slug identifying the account (ie: babel for https://opencollective.com/babel) - """ - slug: String -} - """ A legal document (e.g. W9, W8BEN, W8BEN-E) """ @@ -4937,6 +5027,7 @@ Stats for the Account """ type AccountStats { id: String + summary: TransactionSummary """ Amount of money in cents in the currency of the collective currently available to spend @@ -5407,6 +5498,19 @@ type AccountStats { ): TimeSeriesAmount! } +""" +Summary of transactions for the account +""" +type TransactionSummary { + expenseCount: Int + expenseTotal: Amount + expenseMaxValue: Amount + expenseDistinctPayee: Int + contributionCount: Int + contributionTotal: Amount + hostFeeTotal: Amount +} + """ Amount time series """ @@ -6111,6 +6215,41 @@ enum ActivityClassType { REPORTS } +""" +A collection of Transactions groups +""" +type TransactionGroupCollection implements Collection { + offset: Int + limit: Int + totalCount: Int + nodes: [TransactionGroup!]! +} + +""" +Transaction group +""" +type TransactionGroup { + id: String! + totalAmount: Amount! + host: Account + + """ + The account on the main side of the transaction (CREDIT -> recipient, DEBIT -> sender) + """ + account: Account + + """ + The primary transaction in the group + """ + primaryTransaction: Transaction + + """ + The transactions in the group + """ + transactions: [Transaction] + createdAt: DateTime +} + """ EXPERIMENTAL (this may change or be deleted): Host transaction report """ @@ -6780,6 +6919,16 @@ type TransactionsImport { """ updatedAt: DateTime! + """ + When the import was last synced + """ + lastSyncAt: DateTime + + """ + Connected account linked to the import + """ + connectedAccount: ConnectedAccount + """ List of rows in the import """ @@ -7515,6 +7664,16 @@ type Bot implements Account { createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -8259,6 +8418,41 @@ type Bot implements Account { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -8327,6 +8521,16 @@ type Collective implements Account & AccountWithHost & AccountWithContributions createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -9071,6 +9275,41 @@ type Collective implements Account & AccountWithHost & AccountWithContributions """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -9118,6 +9357,11 @@ type Collective implements Account & AccountWithHost & AccountWithContributions """ approvedAt: DateTime + """ + Date when the collective was last unfrozen by current Fiscal Host + """ + unfrozenAt: DateTime + """ Returns whether it's approved by the Fiscal Host """ @@ -9226,6 +9470,11 @@ interface AccountWithHost { """ approvedAt: DateTime + """ + Date when the collective was last unfrozen by current Fiscal Host + """ + unfrozenAt: DateTime + """ Returns whether it's approved by the Fiscal Host """ @@ -9592,6 +9841,16 @@ type Event implements Account & AccountWithHost & AccountWithContributions & Acc createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -10336,6 +10595,41 @@ type Event implements Account & AccountWithHost & AccountWithContributions & Acc """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -10383,6 +10677,11 @@ type Event implements Account & AccountWithHost & AccountWithContributions & Acc """ approvedAt: DateTime + """ + Date when the collective was last unfrozen by current Fiscal Host + """ + unfrozenAt: DateTime + """ Returns whether it's approved by the Fiscal Host """ @@ -10639,6 +10938,16 @@ type Individual implements Account { createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -11381,6 +11690,41 @@ type Individual implements Account { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -11657,6 +12001,16 @@ type Organization implements Account & AccountWithContributions { createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -12399,6 +12753,41 @@ type Organization implements Account & AccountWithContributions { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -12564,6 +12953,16 @@ type Vendor implements Account & AccountWithContributions { createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -13308,6 +13707,41 @@ type Vendor implements Account & AccountWithContributions { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -14431,6 +14865,61 @@ type Query { accountingCategory: [String] ): TransactionCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroup( + """ + The public id identifying the transaction group (ie: rvelja97-pkzqbgq7-bbzyx6wd-50o8n4rm) + """ + groupId: String! + + """ + Account associated to the transaction group + """ + account: AccountReferenceInput! + ): TransactionGroup + + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + Reference of the account(s) assigned to the main side of the transaction group (CREDIT -> recipient, DEBIT -> sender) + """ + account: AccountReferenceInput! + + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ Fetch a transactions import """ @@ -16050,6 +16539,16 @@ type Fund implements Account & AccountWithHost & AccountWithContributions { createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -16794,6 +17293,41 @@ type Fund implements Account & AccountWithHost & AccountWithContributions { """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -16841,6 +17375,11 @@ type Fund implements Account & AccountWithHost & AccountWithContributions { """ approvedAt: DateTime + """ + Date when the collective was last unfrozen by current Fiscal Host + """ + unfrozenAt: DateTime + """ Returns whether it's approved by the Fiscal Host """ @@ -16975,6 +17514,16 @@ type Project implements Account & AccountWithHost & AccountWithContributions & A createdAt: DateTime updatedAt: DateTime + """ + Date of unhosting by a given Fiscal Host. + """ + unhostedAt( + """ + The host account this collective was hosted by + """ + host: AccountReferenceInput! + ): DateTime + """ Returns whether this account is archived """ @@ -17719,6 +18268,41 @@ type Project implements Account & AccountWithHost & AccountWithContributions & A """ duplicatedAccounts(limit: Int! = 100, offset: Int! = 0): AccountCollection! + """ + [!] Warning: this query is currently in beta and the API might change + """ + transactionGroups( + """ + The number of results to fetch (default 10, max 1000) + """ + limit: Int! = 100 + + """ + The offset to use to fetch + """ + offset: Int! = 0 + + """ + Filter transaction groups by the type of the primary transaction + """ + type: TransactionType + + """ + Filter transaction groups by the kind of the primary transaction + """ + kind: TransactionKind + + """ + Only return transaction groups that were created after this date + """ + dateFrom: DateTime + + """ + Only return transaction groups that were created before this date + """ + dateTo: DateTime + ): TransactionGroupCollection! + """ EXPERIMENTAL (this may change or be removed) """ @@ -17766,6 +18350,11 @@ type Project implements Account & AccountWithHost & AccountWithContributions & A """ approvedAt: DateTime + """ + Date when the collective was last unfrozen by current Fiscal Host + """ + unfrozenAt: DateTime + """ Returns whether it's approved by the Fiscal Host """ @@ -19501,6 +20090,26 @@ type Mutation { type: TransactionsImportType! ): TransactionsImport! + """ + Edit an import + """ + editTransactionsImport( + """ + ID of the import to edit + """ + id: NonEmptyString! + + """ + Source of the import (e.g. "Bank of America", "Eventbrite", etc...) + """ + source: NonEmptyString + + """ + Name of the import (e.g. "Contributions May 2021", "Tickets for Mautic Conference 2024") + """ + name: NonEmptyString + ): TransactionsImport! + """ Import transactions, manually or from a CSV file """ @@ -19541,6 +20150,16 @@ type Mutation { rows: [TransactionsImportRowUpdateInput!]! ): TransactionsImport! + """ + Delete an import and all its associated rows + """ + deleteTransactionsImport( + """ + ID of the import to delete + """ + id: NonEmptyString! + ): Boolean! + """ Create update. Scope: "updates". """ diff --git a/src/server/controllers/hosted-collectives.ts b/src/server/controllers/hosted-collectives.ts index b6d4625e..dd8ae859 100644 --- a/src/server/controllers/hosted-collectives.ts +++ b/src/server/controllers/hosted-collectives.ts @@ -31,6 +31,10 @@ export const hostedCollectivesQuery = gqlV2` $balance: AmountRangeInput $consolidatedBalance: AmountRangeInput $currencies: [String] + $includeYearSummary: Boolean! + $lastYear: DateTime! + $includeQuarterSummary: Boolean! + $lastQuarter: DateTime! ) { host(slug: $hostSlug) { id @@ -70,6 +74,7 @@ export const hostedCollectivesQuery = gqlV2` tags settings createdAt + unhostedAt(host: { slug: $hostSlug }) stats { id balance { @@ -84,15 +89,26 @@ export const hostedCollectivesQuery = gqlV2` value currency } + } policies { id COLLECTIVE_ADMINS_CAN_SEE_PAYOUT_METHODS } ... on AccountWithHost { + host { + id + legacyId + slug + } hostFeesStructure hostFeePercent approvedAt + unfrozenAt + hostApplication { + id + createdAt + } hostAgreements { totalCount nodes { @@ -106,6 +122,24 @@ export const hostedCollectivesQuery = gqlV2` } } } + yearSummary: summary(dateFrom: $lastYear) @include(if: $includeYearSummary) { + expenseTotal { valueInCents, value, currency } + expenseCount + expenseMaxValue { valueInCents, value, currency } + expenseDistinctPayee + contributionCount + contributionTotal { valueInCents, value, currency } + hostFeeTotal { valueInCents, value, currency } + } + quarterSummary: summary(dateFrom: $lastQuarter) @include(if: $includeQuarterSummary) { + expenseTotal { valueInCents, value, currency } + expenseCount + expenseMaxValue { valueInCents, value, currency } + expenseDistinctPayee + contributionCount + contributionTotal { valueInCents, value, currency } + hostFeeTotal { valueInCents, value, currency } + } } admins: members(role: [ADMIN]) { totalCount @@ -183,6 +217,42 @@ const csvMapping = { firstExpenseDate: (account) => shortDate(account.firstExpenseReceived?.nodes[0]?.createdAt), lastExpenseDate: (account) => shortDate(account.lastExpenseReceived?.nodes[0]?.createdAt), numberOfExpenses: (account) => account.numberOfExpenses?.totalCount, + status: (account, host) => { + if (account.host?.id !== host.id) { + return 'UNHOSTED'; + } else if (account.isFrozen) { + return 'FROZEN'; + } else { + return 'ACTIVE'; + } + }, + // Added fields + totalAmountSpent: (account) => account.stats.totalAmountSpent && amountAsString(account.stats.totalAmountSpent), + dateApplied: (account) => shortDate(account.hostApplication?.createdAt), + unhostedAt: (account) => account.unhostedAt && shortDate(account.unhostedAt), + unfrozenAt: (account) => account.unfrozenAtd && shortDate(account.unfrozenAt), + numberOfExpensesYear: (account) => account.yearSummary?.expenseCount, + valueOfExpensesYear: (account) => + account.yearSummary?.expenseTotal && amountAsString(account.yearSummary.expenseTotal), + maxExpenseValueYear: (account) => + account.yearSummary?.expenseMaxValue && amountAsString(account.yearSummary.expenseMaxValue), + numberOfPayeesYear: (account) => account.yearSummary?.expenseDistinctPayee, + numberOfContributionsYear: (account) => account.yearSummary?.contributionCount, + valueOfContributionsYear: (account) => + account.yearSummary?.contributionTotal && amountAsString(account.yearSummary.contributionTotal), + valueOfHostFeeYear: (account) => + account.yearSummary?.hostFeeTotal && amountAsString(account.yearSummary.hostFeeTotal), + numberOfExpensesQuarter: (account) => account.quarterSummary?.expenseCount, + valueOfExpensesQuarter: (account) => + account.quarterSummary?.expenseTotal && amountAsString(account.quarterSummary.expenseTotal), + maxExpenseValueQuarter: (account) => + account.quarterSummary?.expenseMaxValue && amountAsString(account.quarterSummary.expenseMaxValue), + numberOfPayeesQuarter: (account) => account.quarterSummary?.expenseDistinctPayee, + numberOfContributionsQuarter: (account) => account.quarterSummary?.contributionCount, + valueOfContributionsQuarter: (account) => + account.quarterSummary?.contributionTotal && amountAsString(account.quarterSummary.contributionTotal), + valueOfHostFeeQuarter: (account) => + account.quarterSummary?.hostFeeTotal && amountAsString(account.quarterSummary.hostFeeTotal), }; const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' }> = async (req, res) => { @@ -210,11 +280,17 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } const hostSlug = req.params.slug; assert(hostSlug, 'Please provide a slug'); + const fields = (get(req.query, 'fields', '') as string) + .split(',') + .map(trim) + .filter((v) => !!v); + const variables = { hostSlug, 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, + sort: req.query.sort && JSON.parse(req.query.sort as string), + consolidatedBalance: req.query.consolidatedBalance && JSON.parse(req.query.consolidatedBalance as string), hostFeesStructure: req.query.hostFeesStructure, searchTerm: req.query.searchTerm, type: splitEnums(req.query.type as string), @@ -222,14 +298,33 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } isFrozen: req.query.isFrozen ? parseToBooleanDefaultTrue(req.query.isFrozen as string) : undefined, isUnhosted: req.query.isUnhosted ? parseToBooleanDefaultTrue(req.query.isUnhosted as string) : undefined, currencies: splitEnums(req.query.currencies as string), + lastYear: moment().subtract(1, 'year').toISOString(), + includeYearSummary: fields.some((field) => + [ + 'numberOfExpensesYear', + 'valueOfExpensesYear', + 'maxExpenseValueYear', + 'numberOfPayeesYear', + 'numberOfContributionsYear', + 'valueOfContributionsYear', + 'valueOfHostFeeYear', + ].includes(field), + ), + lastQuarter: moment().subtract(3, 'month').toISOString(), + includeQuarterSummary: fields.some((field) => + [ + 'numberOfExpensesQuarter', + 'valueOfExpensesQuarter', + 'maxExpenseValueQuarter', + 'numberOfPayeesQuarter', + 'numberOfContributionsQuarter', + 'valueOfContributionsQuarter', + 'valueOfHostFeeQuarter', + ].includes(field), + ), }; const fetchAll = variables.offset ? false : parseToBooleanDefaultFalse(req.query.fetchAll as string); - logger.debug('hostedCollectives:query', variables); - - const fields = (get(req.query, 'fields', '') as string) - .split(',') - .map(trim) - .filter((v) => !!v); + logger.debug('hostedCollectives:query', { variables, headers }); let result = await graphqlRequest(hostedCollectivesQuery, variables, { version: 'v2', headers }); @@ -259,7 +354,7 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } } const mapping = pick(csvMapping, fields); - const mappedTransactions = result.host.hostedAccounts.nodes.map((t) => applyMapping(mapping, t)); + const mappedTransactions = result.host.hostedAccounts.nodes.map((t) => applyMapping(mapping, t, result.host)); res.write(json2csv(mappedTransactions, null)); res.write(`\n`); @@ -268,7 +363,9 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' } do { variables.offset += result.host.hostedAccounts.limit; result = await graphqlRequest(hostedCollectivesQuery, variables, { version: 'v2', headers }); - const mappedTransactions = result.host.hostedAccounts.nodes.map((t) => applyMapping(mapping, t)); + const mappedTransactions = result.host.hostedAccounts.nodes.map((t) => + applyMapping(mapping, t, result.host), + ); res.write(json2csv(mappedTransactions, { header: false })); res.write(`\n`); } while ( diff --git a/src/server/lib/utils.ts b/src/server/lib/utils.ts index 68120057..18a80b2f 100644 --- a/src/server/lib/utils.ts +++ b/src/server/lib/utils.ts @@ -92,12 +92,12 @@ export const splitIds = (str?: string) => str?.split(',').map(trim) || []; export const splitEnums = (str?: string) => splitIds(str).map(toUpper); -export const applyMapping = (mapping, row) => { +export const applyMapping = (mapping, row, meta?) => { const res = {}; Object.keys(mapping).map((key) => { const val = mapping[key]; if (typeof val === 'function') { - return (res[key] = val(row)); + return (res[key] = val(row, meta)); } else { return (res[key] = get(row, val)); }