Skip to content

Commit

Permalink
Ref: add types instead of any
Browse files Browse the repository at this point in the history
  • Loading branch information
manelcecs authored and Pl217 committed Nov 17, 2023
1 parent 51e70cc commit 6ed5cd7
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 79 deletions.
5 changes: 2 additions & 3 deletions src/domain-services/categories/category-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Category } from './graphql/types';
import { InstanceDataOfModel } from '@unocha/hpc-api-core/src/db/util/raw-model';
import { Op } from '@unocha/hpc-api-core/src/db/util/conditions';

// TODO: add proper type for flowLinks
@Service()
export class CategoryService {
async getCategoriesForFlows(
Expand Down Expand Up @@ -50,15 +49,15 @@ export class CategoryService {
categoriesMap.set(flowId, []);
}

const categoriesForFlow = categoriesMap.get(flowId)!;
const categoriesPerFlow = categoriesMap.get(flowId)!;

const category = categories.find((cat) => cat.id === catRef.categoryID);

if (!category) {
throw new Error(`Category with ID ${catRef.categoryID} does not exist`);
}

categoriesForFlow.push(this.mapCategoryToFlowCategory(category, catRef));
categoriesPerFlow.push(this.mapCategoryToFlowCategory(category, catRef));
});

return categoriesMap;
Expand Down
11 changes: 11 additions & 0 deletions src/domain-services/flow-object/flow-object-service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Database } from '@unocha/hpc-api-core/src/db';
import { FlowId } from '@unocha/hpc-api-core/src/db/models/flow';
import { Op } from '@unocha/hpc-api-core/src/db/util/conditions';
import { Service } from 'typedi';

@Service()
Expand All @@ -14,4 +15,14 @@ export class FlowObjectService {
// Keep only not duplicated flowIDs
return [...new Set(flowObjects.map((flowObject) => flowObject.flowID))];
}

async getFlowObjectByFlowId(models: Database, flowIds: FlowId[]) {
return await models.flowObject.find({
where: {
flowID: {
[Op.IN]: flowIds,
},
},
});
}
}
4 changes: 4 additions & 0 deletions src/domain-services/flow-object/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Database } from '@unocha/hpc-api-core/src/db';
import { InstanceOfModel } from '@unocha/hpc-api-core/src/db/util/types';

export type FlowObject = InstanceOfModel<Database['flowObject']>;
183 changes: 115 additions & 68 deletions src/domain-services/flows/flow-search-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {
SearchFlowsArgs,
SearchFlowsFilters,
} from './graphql/args';
import { FlowParkedParentSource, FlowSearchResult } from './graphql/types';
import {
FlowPaged,
FlowParkedParentSource,
FlowSearchResult,
} from './graphql/types';
import { FlowSearchStrategy } from './strategy/flow-search-strategy';
import { OnlyFlowFiltersStrategy } from './strategy/impl/only-flow-conditions-strategy';
import { FlowObjectFiltersStrategy } from './strategy/impl/flow-object-conditions-strategy';
Expand All @@ -20,6 +24,14 @@ import { PlanService } from '../plans/plan-service';
import { ReportDetailService } from '../report-details/report-detail-service';
import { UsageYearService } from '../usage-years/usage-year-service';
import { FlowLinkService } from '../flow-link/flow-link-service';
import { FlowObject } from '../flow-object/model';
import { FlowObjectService } from '../flow-object/flow-object-service';
import { FlowEntity } from './model';
import { Category } from '../categories/graphql/types';
import { Organization } from '../organizations/graphql/types';
import { BaseLocation } from '../location/graphql/types';
import { BasePlan } from '../plans/graphql/types';
import { UsageYear } from '../usage-years/grpahql/types';

@Service()
export class FlowSearchService {
Expand All @@ -33,7 +45,8 @@ export class FlowSearchService {
private readonly categoryService: CategoryService,
private readonly flowLinkService: FlowLinkService,
private readonly externalReferenceService: ExternalReferenceService,
private readonly reportDetailService: ReportDetailService
private readonly reportDetailService: ReportDetailService,
private readonly flowObjectService: FlowObjectService
) {}

async search(
Expand All @@ -42,41 +55,28 @@ export class FlowSearchService {
): Promise<FlowSearchResult> {
const { limit, afterCursor, beforeCursor, sortField, sortOrder } = filters;

if (beforeCursor && afterCursor) {
throw new Error('Cannot use before and after cursor at the same time');
}

let cursorCondition;
if (afterCursor) {
cursorCondition = {
id: {
[Op.GT]: createBrandedValue(afterCursor),
},
};
} else if (beforeCursor) {
cursorCondition = {
id: {
[Op.LT]: createBrandedValue(beforeCursor),
},
};
}

const orderBy = {
column: sortField ?? 'updatedAt',
order: sortOrder ?? 'desc',
};

const { flowFilters, flowObjectFilters } = filters;

const cursorCondition = this.buildCursorCondition(
beforeCursor,
afterCursor
);

// Determine strategy of how to search for flows
const { strategy, conditions } = this.determineStrategy(
flowFilters,
flowObjectFilters,
cursorCondition
flowObjectFilters
);

// Fetch one more item to check for hasNextPage
const limitComputed = limit + 1;

// Obtain flows and its count based on the strategy selected
const { flows, count } = await strategy.search(
conditions,
orderBy,
Expand All @@ -93,31 +93,36 @@ export class FlowSearchService {

const flowIds: FlowId[] = flows.map((flow) => flow.id);

const organizationsFO: any[] = [];
const locationsFO: any[] = [];
const plansFO: any[] = [];
const usageYearsFO: any[] = [];

const [externalReferencesMap] = await Promise.all([
// Obtain external references and flow objects in parallel
const [externalReferencesMap, flowObjects] = await Promise.all([
this.externalReferenceService.getExternalReferencesForFlows(
flowIds,
models
),
this.getFlowObjects(
flowIds,
models,
organizationsFO,
locationsFO,
plansFO,
usageYearsFO
),
this.flowObjectService.getFlowObjectByFlowId(models, flowIds),
]);

// Map flow objects to their respective arrays
const organizationsFO: FlowObject[] = [];
const locationsFO: FlowObject[] = [];
const plansFO: FlowObject[] = [];
const usageYearsFO: FlowObject[] = [];

this.mapFlowObjects(
flowObjects,
organizationsFO,
locationsFO,
plansFO,
usageYearsFO
);

// Obtain flow links
const flowLinksMap = await this.flowLinkService.getFlowLinksForFlows(
flowIds,
models
);

// Perform all nested queries in parallel
const [
categoriesMap,
organizationsMap,
Expand Down Expand Up @@ -171,32 +176,19 @@ export class FlowSearchService {
)
.map((flowLink) => flowLink.parentID.valueOf()) as number[];

return {
// Mandatory fields
id: flow.id.valueOf(),
versionID: flow.versionID,
amountUSD: flow.amountUSD.toString(),
createdAt: flow.createdAt.toISOString(),
updatedAt: flow.updatedAt.toISOString(),
activeStatus: flow.activeStatus,
restricted: flow.restricted,
// Optional fields
return this.buildFlowDTO(
flow,
categories,
organizations,
locations,
plans,
usageYears,
childIDs,
parentIDs,
origAmount: flow.origAmount ? flow.origAmount.toString() : '',
origCurrency: flow.origCurrency ? flow.origCurrency.toString() : '',
externalReferences,
reportDetails,
parkedParentSource:
parkedParentSource.length > 0 ? parkedParentSource : null,
// Paged item field
cursor: flow.id.valueOf(),
};
parkedParentSource
);
})
);

Expand Down Expand Up @@ -260,9 +252,9 @@ export class FlowSearchService {

determineStrategy(
flowFilters: SearchFlowsFilters,
flowObjectFilters: FlowObjectFilters[],
conditions: any
flowObjectFilters: FlowObjectFilters[]
): { strategy: FlowSearchStrategy; conditions: any } {
let conditions = {};
if (
(!flowFilters &&
(!flowObjectFilters || flowObjectFilters.length === 0)) ||
Expand Down Expand Up @@ -310,22 +302,13 @@ export class FlowSearchService {
conditionsMap.set('flow', flowConditions);
return conditionsMap;
}
private async getFlowObjects(
flowIds: FlowId[],
models: Database,
private mapFlowObjects(
flowObjects: FlowObject[],
organizationsFO: any[],
locationsFO: any[],
plansFO: any[],
usageYearsFO: any[]
): Promise<void> {
const flowObjects = await models.flowObject.find({
where: {
flowID: {
[Op.IN]: flowIds,
},
},
});

) {
flowObjects.forEach((flowObject) => {
if (flowObject.objectType === 'organization') {
organizationsFO.push(flowObject);
Expand Down Expand Up @@ -381,4 +364,68 @@ export class FlowSearchService {

return parentFlows;
}

private buildCursorCondition(beforeCursor: number, afterCursor: number) {
if (beforeCursor && afterCursor) {
throw new Error('Cannot use before and after cursor at the same time');
}

let cursorCondition;
if (afterCursor) {
cursorCondition = {
id: {
[Op.GT]: createBrandedValue(afterCursor),
},
};
} else if (beforeCursor) {
cursorCondition = {
id: {
[Op.LT]: createBrandedValue(beforeCursor),
},
};
}

return cursorCondition;
}

private buildFlowDTO(
flow: FlowEntity,
categories: Category[],
organizations: Organization[],
locations: BaseLocation[],
plans: BasePlan[],
usageYears: UsageYear[],
childIDs: number[],
parentIDs: number[],
externalReferences: any[],
reportDetails: any[],
parkedParentSource: FlowParkedParentSource[]
): FlowPaged {
return {
// Mandatory fields
id: flow.id.valueOf(),
versionID: flow.versionID,
amountUSD: flow.amountUSD.toString(),
createdAt: flow.createdAt.toISOString(),
updatedAt: flow.updatedAt.toISOString(),
activeStatus: flow.activeStatus,
restricted: flow.restricted,
// Optional fields
categories,
organizations,
locations,
plans,
usageYears,
childIDs,
parentIDs,
origAmount: flow.origAmount ? flow.origAmount.toString() : '',
origCurrency: flow.origCurrency ? flow.origCurrency.toString() : '',
externalReferences,
reportDetails,
parkedParentSource:
parkedParentSource.length > 0 ? parkedParentSource : null,
// Paged item field
cursor: flow.id.valueOf(),
};
}
}
4 changes: 4 additions & 0 deletions src/domain-services/flows/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Database } from '@unocha/hpc-api-core/src/db';
import { InstanceDataOfModel } from '@unocha/hpc-api-core/src/db/util/raw-model';

export type FlowEntity = InstanceDataOfModel<Database['flow']>;
6 changes: 2 additions & 4 deletions src/domain-services/flows/strategy/flow-search-strategy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Database } from '@unocha/hpc-api-core/src/db';
import { FlowSearchResult } from '../graphql/types';
import { InstanceOfModel } from '@unocha/hpc-api-core/src/db/util/types';
import { InstanceDataOfModel } from '@unocha/hpc-api-core/src/db/util/raw-model';
import { FlowEntity } from '../model';

export interface FlowSearchStrategyResponse {
flows: InstanceDataOfModel<Database['flow']>[];
flows: FlowEntity[];
count: number;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class FlowObjectFiltersStrategy implements FlowSearchStrategy {
// and flow conditions
const [flows, countRes] = await Promise.all([
this.flowService.getFlows(models, conditions, orderBy, limit),
this.flowService.getFlowsCount(models, conditions),
this.flowService.getFlowsCount(models, mergedFlowConditions),
]);

// Map count result query to count object
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Database } from '@unocha/hpc-api-core/src/db';
import { Service } from 'typedi';
import { FlowId } from '@unocha/hpc-api-core/src/db/models/flow';
import { FlowService } from '../../flow-service';
import {
FlowSearchStrategy,
FlowSearchStrategyResponse,
} from '../flow-search-strategy';
import { Op } from '@unocha/hpc-api-core/src/db/util/conditions';

@Service()
export class OnlyFlowFiltersStrategy implements FlowSearchStrategy {
Expand All @@ -24,7 +22,7 @@ export class OnlyFlowFiltersStrategy implements FlowSearchStrategy {

const [flows, countRes] = await Promise.all([
this.flowService.getFlows(models, conditions, orderBy, limit),
this.flowService.getFlowsCount(models, conditions),
this.flowService.getFlowsCount(models, flowConditions),
]);

// Map count result query to count object
Expand Down

0 comments on commit 6ed5cd7

Please sign in to comment.