-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* get donation to giveth with donation box analytics (#1661) * Add a method for finding relevant donations to the donationRepository.ts * Add a method for calculating donations metrics to the donationService.ts * Add a gql resolver for donations metrics to the donationResolver.ts * Add unit test for gql query resolver * Fix division by zero issue * times 100 average percentage to represent percent * add useDonationBox field to donation and draftDonation * fill useDonationBox field with correct data in migrations * Change donationMetrics endpoint based on change in data schema * remove unused import Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * remove unused import Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * add default value for useDonationBox field Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * add false removed imports * add default value for useDonationBox field Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix tests based on changes * fix tests * send useDonationBox as last arg and make it optional * add relevant donation tx hash to donation creation flow * calculate related donations based on relevant donation tx hash * add unit tests * update unit test * fix bug * fix bug in donation repository and tests are pass * Clear All donations after donation metrics test cases * Add new function for deleting project from db and use it to don't affect other test cases * comment new test cases to ensure bug is related to that or not * Clear donations after tests * Comments new test cases in donationRepository.test.ts * uncomment tests and Clean up test effects on DB * Remove project addresses too * Add a new method to testUtils.ts for removing project from db by id * change donation dates to now * Remove clear donations sections * Change update count to a bigger number to pass test --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Remove old donation and add new ones (#1674) * Remove unused variable --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Loading branch information
1 parent
de0ea53
commit 0f760e0
Showing
17 changed files
with
592 additions
and
6 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
migration/1719887968639-addUseDonationBoxToDraftDonations.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; | ||
|
||
export class AddUseDonationBoxToDraftDonations1719887968639 | ||
implements MigrationInterface | ||
{ | ||
public async up(queryRunner: QueryRunner): Promise<void> { | ||
await queryRunner.addColumn( | ||
'draft_donation', | ||
new TableColumn({ | ||
name: 'useDonationBox', | ||
type: 'boolean', | ||
isNullable: true, | ||
default: false, | ||
}), | ||
); | ||
|
||
await queryRunner.addColumn( | ||
'draft_donation', | ||
new TableColumn({ | ||
name: 'relevantDonationTxHash', | ||
type: 'varchar', | ||
isNullable: true, | ||
}), | ||
); | ||
} | ||
|
||
public async down(queryRunner: QueryRunner): Promise<void> { | ||
await queryRunner.dropColumn('draft_donation', 'useDonationBox'); | ||
await queryRunner.dropColumn('draft_donation', 'relevantDonationTxHash'); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
migration/1720634068179-addUseDonationBoxAndRelevantTxHashToDonation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; | ||
|
||
export class AddUseDonationBoxAndRelevantTxHashToDonation1720634068179 | ||
implements MigrationInterface | ||
{ | ||
public async up(queryRunner: QueryRunner): Promise<void> { | ||
const table = await queryRunner.getTable('donation'); | ||
const useDonationBoxColumn = table?.findColumnByName('useDonationBox'); | ||
const relevantDonationTxHashColumn = table?.findColumnByName( | ||
'relevantDonationTxHash', | ||
); | ||
|
||
if (!useDonationBoxColumn) { | ||
await queryRunner.addColumn( | ||
'donation', | ||
new TableColumn({ | ||
name: 'useDonationBox', | ||
type: 'boolean', | ||
isNullable: true, | ||
default: false, | ||
}), | ||
); | ||
} | ||
|
||
if (!relevantDonationTxHashColumn) { | ||
await queryRunner.addColumn( | ||
'donation', | ||
new TableColumn({ | ||
name: 'relevantDonationTxHash', | ||
type: 'varchar', | ||
isNullable: true, | ||
}), | ||
); | ||
} | ||
} | ||
|
||
public async down(queryRunner: QueryRunner): Promise<void> { | ||
await queryRunner.dropColumn('donation', 'useDonationBox'); | ||
await queryRunner.dropColumn('donation', 'relevantDonationTxHash'); | ||
} | ||
} |
136 changes: 136 additions & 0 deletions
136
migration/1720634181001-fillUseDonationBoxAndRelevantTxHashInDonation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import { MigrationInterface, QueryRunner } from 'typeorm'; | ||
|
||
interface DonationUpdate { | ||
id: number; | ||
useDonationBox: boolean; | ||
relevantDonationTxHash: string | null; | ||
} | ||
|
||
export class FillUseDonationBoxAndRelevantTxHashInDonation1720634181001 | ||
implements MigrationInterface | ||
{ | ||
public async up(queryRunner: QueryRunner): Promise<void> { | ||
const givethProjectId = 1; | ||
const timeDiff = 60 * 1000; // 1 minute in milliseconds | ||
|
||
// Load all donations into memory | ||
const donations = await queryRunner.query( | ||
`SELECT id, "userId", "projectId", "createdAt", "transactionId" FROM donation`, | ||
); | ||
|
||
// Calculate relevant donations | ||
const updates: DonationUpdate[] = []; | ||
const userDonations = donations.reduce( | ||
(acc, donation) => { | ||
const userId = donation.userId; | ||
if (!acc[userId]) { | ||
acc[userId] = []; | ||
} | ||
acc[userId].push(donation); | ||
return acc; | ||
}, | ||
{} as Record<number, any[]>, | ||
); | ||
|
||
for (const userId in userDonations) { | ||
const userDonationList = userDonations[userId]; | ||
userDonationList.sort( | ||
(a, b) => | ||
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(), | ||
); | ||
|
||
for (let i = 0; i < userDonationList.length; i++) { | ||
const donation = userDonationList[i]; | ||
if (donation.projectId === givethProjectId) { | ||
let found = false; | ||
|
||
// Check for donations after the current donation | ||
for (let j = i + 1; j < userDonationList.length; j++) { | ||
const nextDonation = userDonationList[j]; | ||
const timeDifference = | ||
new Date(nextDonation.createdAt).getTime() - | ||
new Date(donation.createdAt).getTime(); | ||
if (timeDifference <= timeDiff) { | ||
if (nextDonation.projectId !== givethProjectId) { | ||
updates.push({ | ||
id: donation.id, | ||
useDonationBox: true, | ||
relevantDonationTxHash: nextDonation.transactionId, | ||
}); | ||
updates.push({ | ||
id: nextDonation.id, | ||
useDonationBox: true, | ||
relevantDonationTxHash: null, | ||
}); | ||
found = true; | ||
break; | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
|
||
// Check for donations before the current donation if no relevant donation found | ||
if (!found) { | ||
for (let k = i - 1; k >= 0; k--) { | ||
const prevDonation = userDonationList[k]; | ||
const timeDifference = | ||
new Date(donation.createdAt).getTime() - | ||
new Date(prevDonation.createdAt).getTime(); | ||
if (timeDifference <= timeDiff) { | ||
if (prevDonation.projectId !== givethProjectId) { | ||
updates.push({ | ||
id: donation.id, | ||
useDonationBox: true, | ||
relevantDonationTxHash: prevDonation.transactionId, | ||
}); | ||
updates.push({ | ||
id: prevDonation.id, | ||
useDonationBox: true, | ||
relevantDonationTxHash: null, | ||
}); | ||
break; | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Perform batch update using a single query | ||
const updateQuery = updates | ||
.map( | ||
update => | ||
`(${update.id}, ${update.useDonationBox}, ${ | ||
update.relevantDonationTxHash | ||
? `'${update.relevantDonationTxHash}'` | ||
: 'NULL' | ||
})`, | ||
) | ||
.join(', '); | ||
|
||
await queryRunner.query( | ||
` | ||
UPDATE donation AS d | ||
SET "useDonationBox" = u."useDonationBox", | ||
"relevantDonationTxHash" = u."relevantDonationTxHash" | ||
FROM (VALUES ${updateQuery}) AS u(id, "useDonationBox", "relevantDonationTxHash") | ||
WHERE d.id = u.id; | ||
`, | ||
); | ||
} | ||
|
||
public async down(queryRunner: QueryRunner): Promise<void> { | ||
await queryRunner.query( | ||
` | ||
UPDATE donation | ||
SET "useDonationBox" = false, | ||
"relevantDonationTxHash" = NULL | ||
WHERE "useDonationBox" = true; | ||
`, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.