Skip to content

Commit

Permalink
fix relationships for estimated matching filters
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlosQ96 committed Oct 3, 2023
1 parent 484f6ff commit 84a8bf0
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 44 deletions.
17 changes: 16 additions & 1 deletion src/entities/ProjectEstimatedMatchingView.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ObjectType } from 'type-graphql';
import { Field, ObjectType } from 'type-graphql';
import {
Entity,
Column,
Expand All @@ -8,6 +8,8 @@ import {
ViewEntity,
ManyToOne,
RelationId,
ViewColumn,
JoinColumn,
} from 'typeorm';
import { Project } from './project';

Expand All @@ -26,26 +28,39 @@ import { Project } from './project';
])
@ObjectType()
export class ProjectEstimatedMatchingView extends BaseEntity {
@Field(type => Project)
@ManyToOne(type => Project, project => project.projectEstimatedMatchingView)
@JoinColumn({ referencedColumnName: 'id' })
project: Project;

@Field()
@ViewColumn()
@PrimaryColumn()
projectId: number;

// QF Round ID associated with the donations
@ViewColumn()
@Field()
@PrimaryColumn()
qfRoundId: number;

// Sum of the square root of the value in USD of the donations
@ViewColumn()
@Column('double precision')
sqrtRootSum: number;

// Count of unique donations per user per project per QF round
@ViewColumn()
@Column('int')
uniqueDonationCount: number;

// Sum of the value in USD of the donations for active QF rounds where the donation status is verified
@ViewColumn()
@Column('double precision')
sumValueUsd: number;

// Count of unique donors who have verified donations for each project
@ViewColumn()
@Column('int')
uniqueDonorsCount: number;
}
8 changes: 8 additions & 0 deletions src/entities/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
} from '../repositories/qfRoundRepository';
import { EstimatedMatching } from '../types/qfTypes';
import { Campaign } from './campaign';
import { ProjectEstimatedMatchingView } from './ProjectEstimatedMatchingView';
// tslint:disable-next-line:no-var-requires
const moment = require('moment');

Expand Down Expand Up @@ -342,6 +343,13 @@ export class Project extends BaseEntity {
@OneToMany(type => SocialProfile, socialProfile => socialProfile.project)
socialProfiles?: SocialProfile[];

@Field(type => [ProjectEstimatedMatchingView], { nullable: true })
@OneToMany(
type => ProjectEstimatedMatchingView,
projectEstimatedMatchingView => projectEstimatedMatchingView.project,
)
projectEstimatedMatchingView?: ProjectEstimatedMatchingView[];

@Field(type => Float)
@Column({ type: 'real' })
totalDonations: number;
Expand Down
33 changes: 19 additions & 14 deletions src/repositories/projectRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,10 @@ import {
} from '../entities/project';
import { ProjectVerificationForm } from '../entities/projectVerificationForm';
import { ProjectAddress } from '../entities/projectAddress';
import {
errorMessages,
i18n,
translationErrorMessagesKeys,
} from '../utils/errorMessages';
import { i18n, translationErrorMessagesKeys } from '../utils/errorMessages';
import { User, publicSelectionFields } from '../entities/user';
import { ResourcesTotalPerMonthAndYear } from '../resolvers/donationResolver';
import { OrderDirection, ProjectResolver } from '../resolvers/projectResolver';
import { ProjectEstimatedMatchingView } from '../entities/ProjectEstimatedMatchingView';
import { findActiveQfRound } from './qfRoundRepository';

export const findProjectById = (projectId: number): Promise<Project | null> => {
// return Project.findOne({ id: projectId });

Expand Down Expand Up @@ -62,7 +55,6 @@ export type FilterProjectQueryInputParams = {
sortingBy?: SortingField;
qfRoundId?: number;
activeQfRoundId?: number;
qfRoundProjectsIds?: number[];
};
export const filterProjectsQuery = (params: FilterProjectQueryInputParams) => {
const {
Expand All @@ -76,7 +68,6 @@ export const filterProjectsQuery = (params: FilterProjectQueryInputParams) => {
slugArray,
qfRoundId,
activeQfRoundId,
qfRoundProjectsIds,
} = params;

let query = Project.createQueryBuilder('project')
Expand Down Expand Up @@ -175,10 +166,24 @@ export const filterProjectsQuery = (params: FilterProjectQueryInputParams) => {
);
break;
case SortingField.ActiveQfRoundRaisedFunds:
if (activeQfRoundId && qfRoundProjectsIds) {
query.andWhere('project.id IN (:...qfRoundProjectsIds)', {
qfRoundProjectsIds,
});
if (activeQfRoundId) {
query
.innerJoin(
'project.projectEstimatedMatchingView',
'projectEstimatedMatchingView',
)
.addSelect([
'projectEstimatedMatchingView.sumValueUsd',
'projectEstimatedMatchingView.qfRoundId',
])
.andWhere('projectEstimatedMatchingView.qfRoundId = :qfRoundId', {
qfRoundId: activeQfRoundId,
})
.orderBy(
'projectEstimatedMatchingView.sumValueUsd',
OrderDirection.DESC,
)
.addOrderBy(`project.verified`, OrderDirection.DESC);
}
break;
default:
Expand Down
29 changes: 0 additions & 29 deletions src/resolvers/projectResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -762,18 +762,9 @@ export class ProjectResolver {
let projects: Project[];
let totalCount: number;
let activeQfRoundId: number | undefined;
let qfRoundProjectsIds: number[] | undefined;

if (sortingBy === SortingField.ActiveQfRoundRaisedFunds) {
activeQfRoundId = (await findActiveQfRound())?.id;

if (activeQfRoundId) {
qfRoundProjectsIds = await projectsInQfRoundOrderedBySumValueUsd(
activeQfRoundId,
limit,
skip,
);
}
}

const filterQueryParams: FilterProjectQueryInputParams = {
Expand All @@ -786,7 +777,6 @@ export class ProjectResolver {
sortingBy,
qfRoundId,
activeQfRoundId,
qfRoundProjectsIds,
};
let campaign;
if (campaignSlug) {
Expand Down Expand Up @@ -815,25 +805,6 @@ export class ProjectResolver {
.cache(projectsQueryCacheKey, projectFiltersCacheDuration)
.getManyAndCount();

// No join or custom subquery worked, solution is to write a full raw sql which is too much work
// Sorting will be required to be done in-memory
if (
sortingBy === SortingField.ActiveQfRoundRaisedFunds &&
activeQfRoundId &&
qfRoundProjectsIds
) {
const orderMap: { [key: string]: number } = {};
qfRoundProjectsIds.forEach((id, index) => {
orderMap[id] = index;
});

const orderedProjects = projects.sort((a, b) => {
return orderMap[a.id] - orderMap[b.id];
});

projects = orderedProjects;
}

const userId = connectedWalletUserId || user?.userId;
if (projects.length > 0 && userId) {
const userReactions = await findUserReactionsByProjectIds(
Expand Down

0 comments on commit 84a8bf0

Please sign in to comment.