diff --git a/src/entities/donation.ts b/src/entities/donation.ts index c66bf4456..1d413a63a 100644 --- a/src/entities/donation.ts +++ b/src/entities/donation.ts @@ -149,7 +149,7 @@ export class Donation extends BaseEntity { projectId: number; @Index() - @Field(type => QfRound) + @Field(type => QfRound, { nullable: true }) @ManyToOne(type => QfRound, { eager: true }) qfRound: QfRound; diff --git a/src/resolvers/donationResolver.test.ts b/src/resolvers/donationResolver.test.ts index 253d40907..564a37563 100644 --- a/src/resolvers/donationResolver.test.ts +++ b/src/resolvers/donationResolver.test.ts @@ -1910,6 +1910,134 @@ function donationsFromWalletsTestCases() { } function donationsByProjectIdTestCases() { + it('should return filtered by qfRound donations when specified', async () => { + const project = await saveProjectDirectlyToDb(createProjectData()); + const qfRound = await QfRound.create({ + isActive: true, + name: new Date().toString(), + minimumPassportScore: 8, + allocatedFund: 100, + beginDate: new Date(), + endDate: moment().add(2, 'day'), + }).save(); + project.qfRounds = [qfRound]; + await project.save(); + const referrerId = generateRandomString(); + const referrerWalletAddress = + await getChainvineAdapter().getWalletAddressFromReferrer(referrerId); + + const user = await User.create({ + walletAddress: generateRandomEtheriumAddress(), + loginType: 'wallet', + firstName: 'first name', + }).save(); + + const user2 = await User.create({ + walletAddress: referrerWalletAddress, + loginType: 'wallet', + firstName: 'first name', + }).save(); + + const donation1 = await saveDonationDirectlyToDb( + createDonationData({ + status: DONATION_STATUS.VERIFIED, + qfRoundId: qfRound.id, + }), + user.id, + project.id, + ); + + const donation2 = await saveDonationDirectlyToDb( + createDonationData({ + status: DONATION_STATUS.VERIFIED, + qfRoundId: qfRound.id, + }), + user.id, + project.id, + ); + qfRound.isActive = false; + await qfRound.save(); + + // second QF round + const qfRound2 = await QfRound.create({ + isActive: true, + name: new Date().toString(), + minimumPassportScore: 8, + allocatedFund: 100, + beginDate: new Date(), + endDate: moment().add(2, 'day'), + }).save(); + project.qfRounds = [qfRound2]; + await project.save(); + + const donation3 = await saveDonationDirectlyToDb( + createDonationData({ + status: DONATION_STATUS.VERIFIED, + qfRoundId: qfRound2.id, + }), + user.id, + project.id, + ); + + const donation4 = await saveDonationDirectlyToDb( + createDonationData({ + status: DONATION_STATUS.VERIFIED, + qfRoundId: qfRound2.id, + }), + user.id, + project.id, + ); + + const resultForRound1 = await axios.post( + graphqlUrl, + { + query: fetchDonationsByProjectIdQuery, + variables: { + projectId: project.id, + qfRoundId: qfRound.id, + orderBy: { + field: 'CreationDate', + direction: 'DESC', + }, + }, + }, + {}, + ); + + const qfRound1donations = + resultForRound1.data.data.donationsByProjectId.donations; + assert.equal(qfRound1donations.length, 2); + qfRound1donations.forEach(donation => { + assert.equal(Number(donation.qfRound.id), qfRound.id); + }); + + const resultForRound2 = await axios.post( + graphqlUrl, + { + query: fetchDonationsByProjectIdQuery, + variables: { + projectId: project.id, + qfRoundId: qfRound2.id, + orderBy: { + field: 'CreationDate', + direction: 'DESC', + }, + }, + }, + {}, + ); + + const qfRound2donations = + resultForRound2.data.data.donationsByProjectId.donations; + assert.equal(qfRound2donations.length, 2); + qfRound2donations.forEach(donation => { + assert.equal(Number(donation.qfRound.id), qfRound2.id); + }); + + qfRound2.isActive = false; + await qfRound2.save(); + }); + it('should sort by the createdAt DESC', async () => { const result = await axios.post( graphqlUrl, diff --git a/src/resolvers/donationResolver.ts b/src/resolvers/donationResolver.ts index ecb0d2603..de6d4c931 100644 --- a/src/resolvers/donationResolver.ts +++ b/src/resolvers/donationResolver.ts @@ -395,6 +395,8 @@ export class DonationResolver { @Arg('skip', type => Int, { defaultValue: 0 }) skip: number, @Arg('traceable', type => Boolean, { defaultValue: false }) traceable: boolean, + @Arg('qfRoundId', type => Int, { defaultValue: null, nullable: true }) + qfRoundId: number, @Arg('projectId', type => Int, { nullable: false }) projectId: number, @Arg('status', type => String, { nullable: true }) status: string, @Arg('searchTerm', type => String, { nullable: true }) searchTerm: string, @@ -418,6 +420,7 @@ export class DonationResolver { const query = this.donationRepository .createQueryBuilder('donation') .leftJoin('donation.user', 'user') + .leftJoinAndSelect('donation.qfRound', 'qfRound') .addSelect(publicSelectionFields) .where(`donation.projectId = ${projectId}`) .orderBy( @@ -432,6 +435,12 @@ export class DonationResolver { }); } + if (qfRoundId) { + query.andWhere('qfRound.id = :qfRoundId', { + qfRoundId, + }); + } + if (searchTerm) { query.andWhere( new Brackets(qb => { diff --git a/test/graphqlQueries.ts b/test/graphqlQueries.ts index 6e6f4a455..aee164966 100644 --- a/test/graphqlQueries.ts +++ b/test/graphqlQueries.ts @@ -246,6 +246,7 @@ export const fetchDonationsByProjectIdQuery = ` $take: Int $skip: Int $traceable: Boolean + $qfRoundId: Int $projectId: Int! $searchTerm: String $status: String @@ -255,6 +256,7 @@ export const fetchDonationsByProjectIdQuery = ` take: $take skip: $skip traceable: $traceable + qfRoundId: $qfRoundId projectId: $projectId searchTerm: $searchTerm status: $status @@ -270,6 +272,9 @@ export const fetchDonationsByProjectIdQuery = ` anonymous valueUsd amount + qfRound { + id + } status user { id diff --git a/test/testUtils.ts b/test/testUtils.ts index 7c26e4817..198dba439 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -281,6 +281,7 @@ export const createDonationData = (params?: { createdAt?: Date; valueUsd?: number; anonymous?: boolean; + qfRoundId?: number; }): CreateDonationData => { return { transactionId: generateRandomTxHash(), @@ -294,6 +295,7 @@ export const createDonationData = (params?: { valueUsd: params?.valueUsd || 15, createdAt: params?.createdAt || moment().toDate(), segmentNotified: true, + qfRoundId: params?.qfRoundId || undefined, }; };