Skip to content

Commit a5bf2f9

Browse files
committed
Validate partnership date overrides against the project
1 parent 3aee239 commit a5bf2f9

File tree

5 files changed

+72
-0
lines changed

5 files changed

+72
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './apply-finalized-changeset-to-partnership.handler';
2+
export * from './validate-partnership-date-overrides-on-project-change.handler';
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { DateOverrideConflictException } from '~/common';
2+
import { EventsHandler, IEventHandler } from '~/core';
3+
import { ProjectUpdatedEvent } from '../../project/events';
4+
import { PartnershipService } from '../partnership.service';
5+
6+
@EventsHandler(ProjectUpdatedEvent)
7+
export class ValidatePartnershipDateOverridesOnProjectChangeHandler
8+
implements IEventHandler<ProjectUpdatedEvent>
9+
{
10+
constructor(private readonly partnerships: PartnershipService) {}
11+
12+
async handle(event: ProjectUpdatedEvent) {
13+
const { updated: project, changes, session } = event;
14+
15+
if (changes.mouStart === undefined && changes.mouEnd === undefined) {
16+
return;
17+
}
18+
19+
const canonical = { start: project.mouStart, end: project.mouEnd };
20+
const partnerships = await this.partnerships.listAllByProjectId(
21+
project.id,
22+
session,
23+
);
24+
const conflicts = DateOverrideConflictException.findConflicts(
25+
canonical,
26+
partnerships.map((partnership) => ({
27+
__typename: 'Partnership',
28+
id: partnership.id,
29+
label: partnership.id, // TODO
30+
start: partnership.mouStartOverride,
31+
end: partnership.mouEndOverride,
32+
})),
33+
);
34+
if (!conflicts) return;
35+
throw new DateOverrideConflictException(
36+
{
37+
__typename: event.resource.name,
38+
id: project.id,
39+
name: project.name,
40+
},
41+
canonical,
42+
['A partnership', 'Some partnerships'],
43+
conflicts,
44+
);
45+
}
46+
}

src/components/partnership/partnership.gel.repository.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ export class PartnershipGelRepository
4949
),
5050
);
5151

52+
async listAllByProjectId(project: ID) {
53+
return await this.db.run(this.listAllByProjectIdQuery, { project });
54+
}
55+
private readonly listAllByProjectIdQuery = e.params(
56+
{ project: e.uuid },
57+
($) => e.select(e.cast(e.Project, $.project).partnerships, this.hydrate),
58+
);
59+
5260
async isFirstPartnership(projectId: ID) {
5361
const project = e.cast(e.Project, e.uuid(projectId));
5462
const query = e.op('not', e.op('exists', project.partnerships));

src/components/partnership/partnership.repository.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,19 @@ export class PartnershipRepository extends DtoRepository<
183183
.run();
184184
}
185185

186+
async listAllByProjectId(projectId: ID, session: Session) {
187+
return await this.db
188+
.query()
189+
.match([
190+
node('project', 'Project', { id: projectId }),
191+
relation('out', '', 'partnership', ACTIVE),
192+
node('node', 'Partnership'),
193+
])
194+
.apply(this.hydrate(session))
195+
.map('dto')
196+
.run();
197+
}
198+
186199
protected override hydrate(session: Session, view?: ObjectView) {
187200
return (query: Query) =>
188201
query

src/components/partnership/partnership.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ export class PartnershipService {
144144
}));
145145
}
146146

147+
async listAllByProjectId(projectId: ID, session: Session) {
148+
return await this.repo.listAllByProjectId(projectId, session);
149+
}
150+
147151
secure(dto: UnsecuredDto<Partnership>, session: Session) {
148152
return this.privileges.for(session, Partnership).secure(dto);
149153
}

0 commit comments

Comments
 (0)