Skip to content

Commit

Permalink
Merge pull request #90 from GeneralMagicio/feat/improve-queries
Browse files Browse the repository at this point in the history
improve record create/update queries
  • Loading branch information
aminlatifi authored Oct 9, 2024
2 parents c85bc33 + 24b26e1 commit 55abe59
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 53 deletions.
22 changes: 22 additions & 0 deletions src/repositories/projectRoundRecordRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,28 @@ describe('ProjectRoundRecord test cases', () => {
expect(roundRecord2?.totalDonationAmount).to.equal(donationAmount2);
expect(roundRecord2?.totalDonationUsdAmount).to.equal(donationUsdAmount2);
});

it('should not cause issue in case of multiple call of updateOrCreateProjectRoundRecord', async () => {
const donationAmount1 = 100;
const donationUsdAmount1 = 150;

await insertDonation({
amount: donationAmount1,
valueUsd: donationUsdAmount1,
qfRoundId: qfRound1.id,
});

const record1 = await updateOrCreateProjectRoundRecord(
projectId,
qfRound1.id,
);
const record2 = await updateOrCreateProjectRoundRecord(
projectId,
qfRound1.id,
);

expect(record1).to.deep.equal(record2);
});
});

describe('getProjectRoundRecord test cases', () => {
Expand Down
47 changes: 27 additions & 20 deletions src/repositories/projectRoundRecordRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,40 @@ export async function updateOrCreateProjectRoundRecord(
const { totalDonationAmount, totalDonationUsdAmount } =
await query.getRawOne();

let record = await ProjectRoundRecord.findOneBy({
projectId,
qfRoundId: qfRoundId ?? undefined,
earlyAccessRoundId: earlyAccessRoundId ?? undefined,
});
// If a new record was created, result will have one entry; if not, result will be empty

if (!record) {
record = ProjectRoundRecord.create({
projectId,
qfRoundId,
earlyAccessRoundId,
createdAt: new Date(),
updatedAt: new Date(),
});
}

record.totalDonationAmount = totalDonationAmount || 0;
record.totalDonationUsdAmount = totalDonationUsdAmount || 0;
record.updatedAt = new Date();
record.cumulativePastRoundsDonationAmounts =
const cumulativePastRoundsDonationAmounts =
await getCumulativePastRoundsDonationAmounts({
projectId,
qfRoundId: qfRoundId || undefined,
earlyAccessRoundId: earlyAccessRoundId || undefined,
});

const prr = await ProjectRoundRecord.save(record);
const result = await ProjectRoundRecord.createQueryBuilder(
'projectRoundRecord',
)
.insert()
.values({
projectId,
qfRoundId,
earlyAccessRoundId,
totalDonationAmount: totalDonationAmount || 0,
totalDonationUsdAmount: totalDonationUsdAmount || 0,
cumulativePastRoundsDonationAmounts,
createdAt: new Date(),
updatedAt: new Date(),
})
.orUpdate(
[
'totalDonationAmount',
'totalDonationUsdAmount',
'cumulativePastRoundsDonationAmounts',
'updatedAt',
],
['projectId', qfRoundId ? 'qfRoundId' : 'earlyAccessRoundId'],
)
.execute();
const prr = result.raw[0];

logger.info(`ProjectRoundRecord updated for project ${projectId}`);

Expand Down
44 changes: 44 additions & 0 deletions src/repositories/projectUserRecordRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,48 @@ describe('projectUserRecordRepository', () => {
ea1DonationAmount + ea2DonationAmount + qfDonationAmount,
);
});

it('should update record if it already exists', async () => {
const donationAmount1 = 100;
const donationAmount2 = 200;

await saveDonationDirectlyToDb(
{
...createDonationData(),
amount: donationAmount1,
status: DONATION_STATUS.VERIFIED,
},
user.id,
project.id,
);

let projectUserRecord = await updateOrCreateProjectUserRecord({
projectId: project.id,
userId: user.id,
});

assert.isOk(projectUserRecord);
assert.equal(projectUserRecord.totalDonationAmount, donationAmount1);

await saveDonationDirectlyToDb(
{
...createDonationData(),
amount: donationAmount2,
status: DONATION_STATUS.VERIFIED,
},
user.id,
project.id,
);

projectUserRecord = await updateOrCreateProjectUserRecord({
projectId: project.id,
userId: user.id,
});

assert.isOk(projectUserRecord);
assert.equal(
projectUserRecord.totalDonationAmount,
donationAmount1 + donationAmount2,
);
});
});
57 changes: 24 additions & 33 deletions src/repositories/projectUserRecordRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Donation, DONATION_STATUS } from '../entities/donation';
import { DONATION_STATUS } from '../entities/donation';
import { ProjectUserRecord } from '../entities/projectUserRecord';

export async function updateOrCreateProjectUserRecord({
Expand All @@ -8,42 +8,33 @@ export async function updateOrCreateProjectUserRecord({
projectId: number;
userId: number;
}): Promise<ProjectUserRecord> {
const { eaTotalDonationAmount, qfTotalDonationAmount, totalDonationAmount } =
await Donation.createQueryBuilder('donation')
.select('SUM(donation.amount)', 'totalDonationAmount')
// sum eaTotalDonationAmount if earlyAccessRoundId is not null
.addSelect(
'SUM(CASE WHEN donation.earlyAccessRoundId IS NOT NULL THEN donation.amount ELSE 0 END)',
'eaTotalDonationAmount',
)
.addSelect(
'SUM(CASE WHEN donation.qfRoundId IS NOT NULL THEN donation.amount ELSE 0 END)',
'qfTotalDonationAmount',
)
.where('donation.projectId = :projectId', { projectId })
.andWhere('donation.status = :status', {
status: DONATION_STATUS.VERIFIED,
})
.andWhere('donation.userId = :userId', { userId })
.getRawOne();
const query = `
INSERT INTO project_user_record ("projectId", "userId", "eaTotalDonationAmount", "qfTotalDonationAmount", "totalDonationAmount")
SELECT
$1 AS projectId,
$2 AS userId,
COALESCE(SUM(CASE WHEN donation."earlyAccessRoundId" IS NOT NULL THEN donation.amount ELSE 0 END), 0) AS eaTotalDonationAmount,
COALESCE(SUM(CASE WHEN donation."qfRoundId" IS NOT NULL THEN donation.amount ELSE 0 END), 0) AS qfTotalDonationAmount,
COALESCE(SUM(donation.amount), 0) AS totalDonationAmount
FROM donation
WHERE donation."projectId" = $1
AND donation."userId" = $2
AND donation.status = $3
ON CONFLICT ("projectId", "userId") DO UPDATE
SET
"eaTotalDonationAmount" = EXCLUDED."eaTotalDonationAmount",
"qfTotalDonationAmount" = EXCLUDED."qfTotalDonationAmount",
"totalDonationAmount" = EXCLUDED."totalDonationAmount"
RETURNING *;
`;

let projectUserRecord = await ProjectUserRecord.findOneBy({
const result = await ProjectUserRecord.query(query, [
projectId,
userId,
});
DONATION_STATUS.VERIFIED,
]);

if (!projectUserRecord) {
projectUserRecord = ProjectUserRecord.create({
projectId,
userId,
});
}

projectUserRecord.eaTotalDonationAmount = eaTotalDonationAmount || 0;
projectUserRecord.qfTotalDonationAmount = qfTotalDonationAmount || 0;
projectUserRecord.totalDonationAmount = totalDonationAmount || 0;

return projectUserRecord.save();
return result[0];
}

export type ProjectUserRecordAmounts = Pick<
Expand Down

0 comments on commit 55abe59

Please sign in to comment.