Skip to content

Commit 89c5696

Browse files
committed
Create Gel PeriodicReport queries
1 parent e401f9f commit 89c5696

File tree

3 files changed

+187
-1
lines changed

3 files changed

+187
-1
lines changed

src/components/periodic-report/dto/periodic-report.dto.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Field, InterfaceType, ObjectType } from '@nestjs/graphql';
2+
import { type MergeExclusive } from 'type-fest';
23
import {
34
Calculated,
45
CalendarDate,
@@ -15,8 +16,14 @@ import { e } from '~/core/gel';
1516
import { RegisterResource } from '~/core/resources';
1617
import { type ScopedRole } from '../../authorization/dto';
1718
import { type DefinedFile } from '../../file/dto';
19+
import { ProgressReport } from '../../progress-report/dto';
1820
import { ReportType } from './report-type.enum';
1921

22+
export type AnyReport = MergeExclusive<
23+
FinancialReport,
24+
MergeExclusive<NarrativeReport, ProgressReport>
25+
>;
26+
2027
@RegisterResource({ db: e.PeriodicReport })
2128
@Calculated()
2229
@InterfaceType({
@@ -83,6 +90,12 @@ export class NarrativeReport extends PeriodicReport {
8390
})
8491
export class SecuredPeriodicReport extends SecuredProperty(PeriodicReport) {}
8592

93+
export const ReportConcretes = {
94+
Financial: FinancialReport,
95+
Narrative: NarrativeReport,
96+
Progress: ProgressReport,
97+
};
98+
8699
declare module '~/core/resources/map' {
87100
interface ResourceMap {
88101
PeriodicReport: typeof PeriodicReport;
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { type Without } from 'type-fest/source/merge-exclusive';
3+
import {
4+
CalendarDate,
5+
EnhancedResource,
6+
type ID,
7+
type PublicOf,
8+
type UnsecuredDto,
9+
} from '~/common';
10+
import { castToEnum, e, RepoFor } from '~/core/gel';
11+
import { type ProgressReport } from '../progress-report/dto';
12+
import {
13+
type FinancialReport,
14+
IPeriodicReport,
15+
type NarrativeReport,
16+
ReportType,
17+
resolveReportType,
18+
} from './dto';
19+
import { type PeriodicReportRepository } from './periodic-report.repository';
20+
21+
@Injectable()
22+
export class PeriodicReportGelRepository
23+
extends RepoFor(IPeriodicReport, {
24+
hydrate: (periodicReport) => ({
25+
...periodicReport['*'],
26+
type: castToEnum(periodicReport.__type__.name.slice(9, -7), ReportType),
27+
reportFile: true,
28+
sensitivity: periodicReport.container.is(e.Project.ContextAware)
29+
.sensitivity,
30+
scope: false,
31+
parent: e.select({
32+
identity: periodicReport.id,
33+
labels: e.array_agg(e.set(periodicReport.__type__.name.slice(9, null))),
34+
properties: e.select({
35+
id: periodicReport.id,
36+
createdAt: periodicReport.createdAt,
37+
}),
38+
}),
39+
}),
40+
omit: ['create'],
41+
})
42+
implements PublicOf<PeriodicReportRepository>
43+
{
44+
//TODO - this is close but the hydrate for ProgressReport needs worked on
45+
async matchCurrentDue(parentId: ID, reportType: ReportType) {
46+
const enhancedResource = EnhancedResource.of(
47+
resolveReportType({ type: reportType }),
48+
);
49+
const resource = e.cast(enhancedResource.db, e.uuid(parentId));
50+
const report = e.select(resource, (report) => ({
51+
...this.hydrate(report),
52+
filter: e.all(
53+
e.set(
54+
e.op(resource.id, '=', report.container.id),
55+
e.op(report.end, '<', CalendarDate.now()),
56+
),
57+
),
58+
order_by: [
59+
{ expression: report.end, direction: e.DESC },
60+
{ expression: report.start, direction: e.ASC },
61+
],
62+
}));
63+
return await this.db.run(report);
64+
}
65+
66+
getCurrentDue(
67+
_parentId: ID,
68+
_reportType: ReportType,
69+
): Promise<
70+
| UnsecuredDto<
71+
| (Without<
72+
| (Without<FinancialReport, NarrativeReport> & NarrativeReport)
73+
| (Without<NarrativeReport, FinancialReport> & FinancialReport),
74+
ProgressReport
75+
> &
76+
ProgressReport)
77+
| (Without<
78+
ProgressReport,
79+
| (Without<FinancialReport, NarrativeReport> & NarrativeReport)
80+
| (Without<NarrativeReport, FinancialReport> & FinancialReport)
81+
> &
82+
(
83+
| (Without<FinancialReport, NarrativeReport> & NarrativeReport)
84+
| (Without<NarrativeReport, FinancialReport> & FinancialReport)
85+
))
86+
>
87+
| undefined
88+
> {
89+
//TODO - is this needed? How does this differ from matchCurrentDue?
90+
throw new Error('Method not implemented.');
91+
}
92+
93+
//TODO - this is close but the hydrate for ProgressReport needs worked on
94+
async getByDate(parentId: ID, date: CalendarDate, reportType: ReportType) {
95+
const enhancedResource = EnhancedResource.of(
96+
resolveReportType({ type: reportType }),
97+
);
98+
const resource = e.cast(enhancedResource.db, e.uuid(parentId));
99+
const report = e.select(resource, (report) => ({
100+
...this.hydrate(report),
101+
filter: e.all(
102+
e.set(
103+
e.op(resource.id, '=', report.container.id),
104+
e.op(report.start, '<=', date),
105+
e.op(report.end, '>=', date),
106+
),
107+
),
108+
}));
109+
return await this.db.run(report);
110+
}
111+
112+
//TODO - this is close but the hydrate for ProgressReport needs worked on
113+
async getNextDue(parentId: ID, reportType: ReportType) {
114+
const enhancedResource = EnhancedResource.of(
115+
resolveReportType({ type: reportType }),
116+
);
117+
const resource = e.cast(enhancedResource.db, e.uuid(parentId));
118+
const report = e.select(resource, (report) => ({
119+
...this.hydrate(report),
120+
filter: e.all(
121+
e.set(
122+
e.op(resource.id, '=', report.container.id),
123+
e.op(report.end, '>', CalendarDate.now()),
124+
),
125+
),
126+
order_by: { expression: report.end, direction: e.ASC },
127+
}));
128+
129+
return await this.db.run(report);
130+
}
131+
132+
//TODO - this is close but the hydrate for ProgressReport needs worked on
133+
async getLatestReportSubmitted(parentId: ID, reportType: ReportType) {
134+
const enhancedResource = EnhancedResource.of(
135+
resolveReportType({ type: reportType }),
136+
);
137+
const resource = e.cast(enhancedResource.db, e.uuid(parentId));
138+
const report = e.select(resource, (report) => ({
139+
...this.hydrate(report),
140+
filter: e.all(
141+
e.set(
142+
e.op(resource.id, '=', report.container.id),
143+
e.op('exists', report.reportFile),
144+
),
145+
),
146+
order_by: { expression: report.start, direction: e.DESC },
147+
}));
148+
149+
return await this.db.run(report);
150+
}
151+
152+
//TODO - this is close but the hydrate for ProgressReport needs worked on
153+
async getFinalReport(parentId: ID, reportType: ReportType) {
154+
const enhancedResource = EnhancedResource.of(
155+
resolveReportType({ type: reportType }),
156+
);
157+
const resource = e.cast(enhancedResource.db, e.uuid(parentId));
158+
const report = e.select(resource, (report) => ({
159+
...this.hydrate(report),
160+
filter: e.all(
161+
e.set(
162+
e.op(resource.id, '=', report.container.id),
163+
e.op(report.start, '=', report.end),
164+
),
165+
),
166+
order_by: { expression: report.start, direction: e.DESC },
167+
}));
168+
169+
return await this.db.run(report);
170+
}
171+
}

src/components/periodic-report/periodic-report.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { forwardRef, Module } from '@nestjs/common';
2+
import { splitDb } from '~/core';
23
import { AuthorizationModule } from '../authorization/authorization.module';
34
import { EngagementModule } from '../engagement/engagement.module';
45
import { FileModule } from '../file/file.module';
@@ -7,6 +8,7 @@ import { ProjectModule } from '../project/project.module';
78
import * as handlers from './handlers';
89
import { PeriodicReportParentResolver } from './periodic-report-parent.resolver';
910
import { PeriodicReportProjectConnectionResolver } from './periodic-report-project-connection.resolver';
11+
import { PeriodicReportGelRepository } from './periodic-report.gel.repository';
1012
import { PeriodicReportLoader } from './periodic-report.loader';
1113
import { PeriodicReportRepository } from './periodic-report.repository';
1214
import { PeriodicReportResolver } from './periodic-report.resolver';
@@ -25,7 +27,7 @@ import { PeriodicReportService } from './periodic-report.service';
2527
PeriodicReportResolver,
2628
PeriodicReportProjectConnectionResolver,
2729
PeriodicReportParentResolver,
28-
PeriodicReportRepository,
30+
splitDb(PeriodicReportRepository, PeriodicReportGelRepository),
2931
PeriodicReportLoader,
3032
...Object.values(handlers),
3133
],

0 commit comments

Comments
 (0)