Skip to content

Commit ce28298

Browse files
committed
refactor: create mixin to share helper functions across repos
1 parent 38f071b commit ce28298

9 files changed

Lines changed: 173 additions & 185 deletions

src/controllers/organization.controller.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ export class OrganizationController {
8383

8484
// create query to get all orgs and their planters
8585
if (filter?.where) {
86-
filter.where = await this.organizationRepository.applyOrganizationWhereClause(
87-
filter.where,
88-
organizationId.valueOf(),
89-
);
86+
filter.where =
87+
await this.organizationRepository.applyOrganizationWhereClause(
88+
filter.where,
89+
organizationId.valueOf(),
90+
'orgs',
91+
);
9092
}
9193

9294
const childOrgs = await this.organizationRepository.find(filter);

src/controllers/planter.controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export class PlanterController {
5454
where = await this.planterRepository.applyOrganizationWhereClause(
5555
whereWithoutOrganizationId,
5656
organizationId,
57+
'planter',
5758
);
5859
}
5960
// console.log('get /planter/count where -->', where);
@@ -85,6 +86,7 @@ export class PlanterController {
8586
filter.where = await this.planterRepository.applyOrganizationWhereClause(
8687
whereWithoutOrganizationId,
8788
organizationId,
89+
'planter',
8890
);
8991
}
9092

src/controllers/planterOrganization.controller.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@ export class PlanterOrganizationController {
6262
const filterOrgId = organizationId;
6363

6464
if (filterOrgId && filterOrgId !== orgId) {
65-
const entityIds = await this.planterRepository.getEntityIdsByOrganizationId(
66-
orgId,
67-
);
65+
const entityIds =
66+
await this.planterRepository.getEntityIdsByOrganizationId(orgId);
6867
orgId = entityIds.includes(filterOrgId) ? filterOrgId : orgId;
6968
}
7069

7170
// Replace organizationId with full entity tree and planter query
7271
where = await this.planterRepository.applyOrganizationWhereClause(
7372
whereWithoutOrganizationId,
7473
orgId,
74+
'planter',
7575
);
7676
}
7777

@@ -103,16 +103,16 @@ export class PlanterOrganizationController {
103103
const filterOrgId = organizationId;
104104

105105
if (filterOrgId && filterOrgId !== orgId) {
106-
const entityIds = await this.planterRepository.getEntityIdsByOrganizationId(
107-
orgId,
108-
);
106+
const entityIds =
107+
await this.planterRepository.getEntityIdsByOrganizationId(orgId);
109108
orgId = entityIds.includes(filterOrgId) ? filterOrgId : orgId;
110109
}
111110

112111
// Replace organizationId with full entity tree and planter query
113112
filter.where = await this.planterRepository.applyOrganizationWhereClause(
114113
whereWithoutOrganizationId,
115114
orgId,
115+
'planter',
116116
);
117117
}
118118

src/controllers/trees.controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export class TreesController {
5757
where = await this.treesRepository.applyOrganizationWhereClause(
5858
whereWithoutOrganizationId,
5959
organizationId,
60+
'trees',
6061
);
6162
}
6263

@@ -90,6 +91,7 @@ export class TreesController {
9091
filter.where = await this.treesRepository.applyOrganizationWhereClause(
9192
whereWithoutOrganizationId,
9293
organizationId,
94+
'trees',
9395
);
9496
}
9597

src/controllers/treesOrganization.controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export class TreesOrganizationController {
6161
where = await this.treesRepository.applyOrganizationWhereClause(
6262
whereWithoutOrganizationId,
6363
orgId,
64+
'trees',
6465
);
6566
}
6667

@@ -100,6 +101,7 @@ export class TreesOrganizationController {
100101
filter.where = await this.treesRepository.applyOrganizationWhereClause(
101102
whereWithoutOrganizationId,
102103
orgId,
104+
'trees',
103105
);
104106
}
105107

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { MixinTarget } from '@loopback/core';
2+
import { CrudRepository, Model } from '@loopback/repository';
3+
import expect from 'expect-runtime';
4+
import { buildFilterQuery } from '../js/buildFilterQuery';
5+
import { utils } from '../js/utils';
6+
7+
export function UtilsRepositoryMixin<
8+
M extends Model,
9+
R extends MixinTarget<CrudRepository<M>>,
10+
>(superClass: R) {
11+
return class extends superClass {
12+
[x: string]: any;
13+
// put the shared code here
14+
async getEntityIdsByOrganizationId(
15+
organizationId: number,
16+
): Promise<Array<number>> {
17+
expect(organizationId).number();
18+
expect(this).property('execute').defined();
19+
const result = await this.execute(
20+
`select * from getEntityRelationshipChildren(${organizationId})`,
21+
[],
22+
);
23+
return result.map((e) => e.entity_id);
24+
}
25+
26+
async applyOrganizationWhereClause(
27+
where: Object | undefined,
28+
organizationId: number | undefined,
29+
model: string,
30+
): Promise<Object | undefined> {
31+
if (!where || organizationId === undefined) {
32+
return Promise.resolve(where);
33+
}
34+
35+
// if planter or tree repository request
36+
if (model === 'trees' || model === 'planter') {
37+
const organizationWhereClause = await this.getOrganizationWhereClause(
38+
organizationId,
39+
model,
40+
);
41+
return {
42+
and: [where, organizationWhereClause],
43+
};
44+
} else {
45+
const entityIds = await this.getEntityIdsByOrganizationId(
46+
organizationId,
47+
);
48+
return {
49+
and: [where, { id: { inq: entityIds } }],
50+
};
51+
}
52+
}
53+
54+
async getPlanterIdsByOrganizationId(
55+
organizationId: number,
56+
): Promise<Array<number>> {
57+
expect(organizationId).number();
58+
const result = await this.execute(
59+
`select * from planter where organization_id in (select entity_id from getEntityRelationshipChildren(${organizationId}))`,
60+
[],
61+
);
62+
expect(result).match([{ id: expect.any(Number) }]);
63+
return result.map((e) => e.id);
64+
}
65+
66+
async getNonOrganizationPlanterIds(): Promise<Array<number>> {
67+
const result = await this.execute(
68+
`select * from planter where organization_id isnull`,
69+
[],
70+
);
71+
expect(result).match([{ id: expect.any(Number) }]);
72+
return result.map((e) => e.id);
73+
}
74+
75+
async getOrganizationWhereClause(
76+
organizationId: number,
77+
model: string,
78+
): Promise<Object> {
79+
if (organizationId === null) {
80+
const planterIds = await this.getNonOrganizationPlanterIds();
81+
// if planter repository request
82+
if (model === 'planter') {
83+
return {
84+
or: [{ organizationId: null }, { id: { inq: planterIds } }],
85+
};
86+
} else {
87+
// if trees or other repository request
88+
return {
89+
or: [
90+
{ plantingOrganizationId: null },
91+
{ planterId: { inq: planterIds } },
92+
],
93+
};
94+
}
95+
} else {
96+
const planterIds = await this.getPlanterIdsByOrganizationId(
97+
organizationId,
98+
);
99+
const entityIds = await this.getEntityIdsByOrganizationId(
100+
organizationId,
101+
);
102+
// if planter repository request
103+
if (model === 'planter') {
104+
return {
105+
or: [
106+
{ organizationId: { inq: entityIds } },
107+
{ id: { inq: planterIds } },
108+
],
109+
};
110+
} else {
111+
// if trees or other repository request
112+
return {
113+
or: [
114+
{ plantingOrganizationId: { inq: entityIds } },
115+
{ planterId: { inq: planterIds } },
116+
],
117+
};
118+
}
119+
}
120+
}
121+
};
122+
}
Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,22 @@
1+
import { Constructor, inject } from '@loopback/core';
12
import { DefaultCrudRepository } from '@loopback/repository';
2-
import { Organization, OrganizationRelations } from '../models';
33
import { TreetrackerDataSource } from '../datasources';
4-
import { inject } from '@loopback/core';
5-
import expect from 'expect-runtime';
4+
import { UtilsRepositoryMixin } from '../mixins/utils.repository-mixin';
5+
import { Organization, OrganizationRelations } from '../models';
66

7-
export class OrganizationRepository extends DefaultCrudRepository<
7+
export class OrganizationRepository extends UtilsRepositoryMixin<
88
Organization,
9-
typeof Organization.prototype.id,
10-
OrganizationRelations
11-
> {
9+
Constructor<
10+
DefaultCrudRepository<
11+
Organization,
12+
typeof Organization.prototype.id,
13+
OrganizationRelations
14+
>
15+
>
16+
>(DefaultCrudRepository) {
1217
constructor(
1318
@inject('datasources.treetracker') dataSource: TreetrackerDataSource,
1419
) {
1520
super(Organization, dataSource);
1621
}
17-
18-
async getEntityIdsByOrganizationId(
19-
organizationId: number,
20-
): Promise<Array<number>> {
21-
expect(organizationId).number();
22-
expect(this).property('execute').defined();
23-
const result = await this.execute(
24-
`select * from getEntityRelationshipChildren(${organizationId})`,
25-
[],
26-
);
27-
return result.map((e) => e.entity_id);
28-
}
29-
30-
async applyOrganizationWhereClause(
31-
where: Object | undefined,
32-
organizationId: number | undefined,
33-
): Promise<Object | undefined> {
34-
if (!where || organizationId === undefined) {
35-
return Promise.resolve(where);
36-
}
37-
const entityIds = await this.getEntityIdsByOrganizationId(organizationId);
38-
return {
39-
and: [where, { id: { inq: entityIds } }],
40-
};
41-
}
4222
}

0 commit comments

Comments
 (0)