Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Hosted Collectives export fields #581

Merged
merged 1 commit into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 131 additions & 2 deletions src/graphql/schemaV2.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5159,6 +5159,31 @@ type AccountStats {
@deprecated(reason: "2022-12-14: this is not used anymore as results should be fast by default")
): Amount!

"""
Amount pledged time series
"""
amountPledgedTimeSeries(
"""
The start date of the time series
"""
dateFrom: DateTime

"""
The end date of the time series
"""
dateTo: DateTime

"""
The time unit of the time series (such as MONTH, YEAR, WEEK etc). If no value is provided this is calculated using the dateFrom and dateTo values.
"""
timeUnit: TimeUnit

"""
Include expected funds.
"""
includeExpectedFunds: Boolean = false
): TimeSeriesAmount!

"""
Total amount received time series
"""
Expand Down Expand Up @@ -5469,6 +5494,11 @@ type AccountStats {
Include transactions from children (Projects and Events)
"""
includeChildren: Boolean = false

"""
Filter by kind
"""
kind: [TransactionKind]
): [AmountStats]

"""
Expand All @@ -5494,6 +5524,11 @@ type AccountStats {
Include transactions from children (Projects and Events)
"""
includeChildren: Boolean = false

"""
Filter by kind
"""
kind: [TransactionKind]
): TimeSeriesAmount!
}

Expand Down Expand Up @@ -5553,6 +5588,7 @@ enum TimeUnit {
type TimeSeriesAmountNode {
date: DateTime!
amount: Amount!
count: Int
label: String
}

Expand Down Expand Up @@ -6910,6 +6946,16 @@ type TransactionsImport {
"""
lastSyncAt: DateTime

"""
Whether the import is currently syncing
"""
isSyncing: Boolean!

"""
Cursor that defines where the last sync left off. Useful to know if there is new data to sync
"""
lastSyncCursor: String

"""
Connected account linked to the import
"""
Expand All @@ -6918,7 +6964,27 @@ type TransactionsImport {
"""
List of rows in the import
"""
rows: TransactionsImportRowCollection!
rows(
"""
The number of results to fetch (default 10, max 1000)
"""
limit: Int! = 100

"""
The offset to use to fetch
"""
offset: Int! = 0

"""
Filter rows by status
"""
status: TransactionsImportRowStatus

"""
Search by text
"""
searchTerm: String
): TransactionsImportRowCollection!
stats: TransactionsImportStats
}

Expand Down Expand Up @@ -7001,6 +7067,26 @@ The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](
"""
scalar JSONObject

"""
The status of a row in a transactions import
"""
enum TransactionsImportRowStatus {
"""
The row has not been processed yet
"""
PENDING

"""
The row has been linked to an existing expense or order
"""
LINKED

"""
The row has been ignored
"""
IGNORED
}

type TransactionsImportStats {
"""
Total number of rows in the import
Expand Down Expand Up @@ -9514,13 +9600,36 @@ Return a summary of transaction info about a given account within the context of
"""
type HostedAccountSummary {
expenseCount: Int

"""
Average calculated based on the number of months since the first transaction of this kind within the requested time frame
"""
expenseMonthlyAverageCount: Float
expenseTotal: Amount

"""
Average calculated based on the number of months since the first transaction of this kind within the requested time frame
"""
expenseMonthlyAverageTotal: Amount
expenseMaxValue: Amount
expenseDistinctPayee: Int
contributionCount: Int

"""
Average calculated based on the number of months since the first transaction of this kind within the requested time frame
"""
contributionMonthlyAverageCount: Float
contributionTotal: Amount

"""
Average calculated based on the number of months since the first transaction of this kind within the requested time frame
"""
contributionMonthlyAverageTotal: Amount
hostFeeTotal: Amount
spentTotal: Amount
receivedTotal: Amount
spentTotalMonthlyAverage: Amount
receivedTotalMonthlyAverage: Amount
}

"""
Expand Down Expand Up @@ -19990,6 +20099,16 @@ type Mutation {
name: String
): PlaidConnectAccountResponse!

"""
Manually request a sync for Plaid account
"""
syncPlaidAccount(
"""
The connected account to refresh
"""
connectedAccount: ConnectedAccountReferenceInput!
): TransactionsImport!

"""
[Root only] Edits account flags (deleted, banned, archived, trusted host)
"""
Expand Down Expand Up @@ -20202,7 +20321,17 @@ type Mutation {
"""
Rows to update
"""
rows: [TransactionsImportRowUpdateInput!]!
rows: [TransactionsImportRowUpdateInput!]

"""
Whether to ignore all non-processed rows
"""
dismissAll: Boolean

"""
Whether to restore all dismissed rows
"""
restoreAll: Boolean
): TransactionsImport!

"""
Expand Down
57 changes: 44 additions & 13 deletions src/server/controllers/hosted-collectives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,22 @@ type Fields =
| 'valueOfContributionsYear'
| 'valueOfHostFeeYear'
| 'spentTotalYear'
| 'receivedTotalYear'
| 'numberOfExpensesAllTime'
| 'valueOfExpensesAllTime'
| 'maxExpenseValueAllTime'
| 'numberOfPayeesAllTime'
| 'numberOfContributionsAllTime'
| 'valueOfContributionsAllTime'
| 'valueOfHostFeeAllTime'
| 'spentTotalAllTime';
| 'spentTotalAllTime'
| 'receivedTotalAllTime'
| 'expenseMonthlyAverageCount'
| 'expenseMonthlyAverageTotal'
| 'contributionMonthlyAverageCount'
| 'contributionMonthlyAverageTotal'
| 'spentTotalMonthlyAverage'
| 'receivedTotalMonthlyAverage';

export const hostedCollectivesQuery = gqlV2`
query HostedCollectives(
Expand Down Expand Up @@ -118,15 +126,6 @@ export const hostedCollectivesQuery = gqlV2`
value
currency
}
totalAmountSpent {
value
currency
}
totalAmountReceived(net: true) {
value
currency
}

}
policies {
id
Expand Down Expand Up @@ -167,7 +166,8 @@ export const hostedCollectivesQuery = gqlV2`
contributionCount
contributionTotal { valueInCents, value, currency }
hostFeeTotal { valueInCents, value, currency }
spentTotal { valueInCents, value, currency}
spentTotal { valueInCents, value, currency }
receivedTotal { valueInCents, value, currency }
}
allTimeSummary: summary @include(if: $includeAllTimeSummary) {
expenseTotal { valueInCents, value, currency }
Expand All @@ -177,7 +177,14 @@ export const hostedCollectivesQuery = gqlV2`
contributionCount
contributionTotal { valueInCents, value, currency }
hostFeeTotal { valueInCents, value, currency }
spentTotal { 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 }
}
}
admins: members(role: [ADMIN]) {
Expand Down Expand Up @@ -277,6 +284,8 @@ const csvMapping: Record<Fields, string | Function> = {
valueOfHostFeeYear: (account) =>
account.yearSummary?.hostFeeTotal && amountAsString(account.yearSummary.hostFeeTotal),
spentTotalYear: (account) => account.yearSummary?.spentTotal && amountAsString(account.yearSummary.spentTotal),
receivedTotalYear: (account) =>
account.yearSummary?.receivedTotal && amountAsString(account.yearSummary.receivedTotal),
numberOfExpensesAllTime: (account) => account.allTimeSummary?.expenseCount,
valueOfExpensesAllTime: (account) =>
account.allTimeSummary?.expenseTotal && amountAsString(account.allTimeSummary.expenseTotal),
Expand All @@ -290,14 +299,28 @@ const csvMapping: Record<Fields, string | Function> = {
account.allTimeSummary?.hostFeeTotal && amountAsString(account.allTimeSummary.hostFeeTotal),
spentTotalAllTime: (account) =>
account.allTimeSummary?.spentTotal && amountAsString(account.allTimeSummary.spentTotal),
receivedTotalAllTime: (account) =>
account.allTimeSummary?.receivedTotal && amountAsString(account.allTimeSummary.receivedTotal),
expenseMonthlyAverageCount: (account) => account.allTimeSummary?.expenseMonthlyAverageCount,
expenseMonthlyAverageTotal: (account) =>
account.allTimeSummary?.expenseMonthlyAverageTotal &&
amountAsString(account.allTimeSummary.expenseMonthlyAverageTotal),
contributionMonthlyAverageCount: (account) => account.allTimeSummary?.contributionMonthlyAverageCount,
contributionMonthlyAverageTotal: (account) =>
account.allTimeSummary?.contributionMonthlyAverageTotal &&
amountAsString(account.allTimeSummary.contributionMonthlyAverageTotal),
spentTotalMonthlyAverage: (account) =>
account.allTimeSummary?.spentTotalMonthlyAverage && amountAsString(account.allTimeSummary.spentTotalMonthlyAverage),
receivedTotalMonthlyAverage: (account) =>
account.allTimeSummary?.receivedTotalMonthlyAverage &&
amountAsString(account.allTimeSummary.receivedTotalMonthlyAverage),
};

const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' }> = async (req, res) => {
if (!['HEAD', 'GET'].includes(req.method)) {
res.status(405).send({ error: { message: 'Method not allowed' } });
return;
}

try {
// Forward Api Key or Authorization header
const headers = {};
Expand Down Expand Up @@ -345,6 +368,8 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' }
'numberOfContributionsYear',
'valueOfContributionsYear',
'valueOfHostFeeYear',
'spentTotalYear',
'receivedTotalYear',
].includes(field),
),
includeAllTimeSummary: fields.some((field) =>
Expand All @@ -356,6 +381,12 @@ const hostedCollectives: RequestHandler<{ slug: string; format: 'csv' | 'json' }
'numberOfContributionsAllTime',
'valueOfContributionsAllTime',
'valueOfHostFeeAllTime',
'spentTotalAllTime',
'receivedTotalAllTime',
'expenseMonthlyAverageCount',
'expenseMonthlyAverageTotal',
'contributionMonthlyAverageCount',
'contributionMonthlyAverageTotal',
].includes(field),
),
};
Expand Down