Skip to content

Commit 964a46f

Browse files
authored
Merge pull request #3406 from SeedCompany/missing-fields-tweaks
2 parents 26794e9 + 5f1a237 commit 964a46f

File tree

3 files changed

+70
-24
lines changed

3 files changed

+70
-24
lines changed

src/common/required-when.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,37 @@ export const RequiredWhen =
4141
...fieldOptions,
4242
});
4343

44-
RequiredWhen.verify = <TResourceStatic extends ResourceShape<any>>(
44+
RequiredWhen.calc = <TResourceStatic extends ResourceShape<any>>(
4545
resource: TResourceStatic,
4646
obj: UnsecuredDto<TResourceStatic['prototype']>,
4747
) => {
4848
const res = EnhancedResource.of(resource);
49-
const missing = [...res.props].flatMap((prop: string) => {
49+
const conditions = [...res.props].flatMap((prop: string) => {
5050
const condition = RequiredWhenMetadata.get(resource, prop);
51-
return condition?.isEnabled(obj) &&
52-
(condition.isMissing?.(obj) ?? obj[prop] == null)
51+
return condition ? { ...condition, field: prop } : [];
52+
});
53+
const missing = conditions.flatMap((condition) => {
54+
return condition.isEnabled(obj) &&
55+
(condition.isMissing?.(obj) ?? obj[condition.field] == null)
5356
? {
54-
field: condition.field ?? prop,
57+
field: condition.field,
5558
description: condition.description,
5659
}
5760
: [];
5861
});
5962
if (missing.length > 0) {
60-
throw new MissingRequiredFieldsException(res, { id: obj.id }, missing);
63+
return new MissingRequiredFieldsException(res, { id: obj.id }, missing);
64+
}
65+
return undefined;
66+
};
67+
68+
RequiredWhen.verify = <TResourceStatic extends ResourceShape<any>>(
69+
resource: TResourceStatic,
70+
obj: UnsecuredDto<TResourceStatic['prototype']>,
71+
) => {
72+
const ex = RequiredWhen.calc(resource, obj);
73+
if (ex) {
74+
throw ex;
6175
}
6276
};
6377

src/components/engagement/engagement.service.ts

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Range,
88
RangeException,
99
RequiredWhen,
10+
ResourceShape,
1011
SecuredList,
1112
Session,
1213
UnsecuredDto,
@@ -149,8 +150,12 @@ export class EngagementService {
149150
return engagements.map((dto) => this.secure(dto, session));
150151
}
151152

152-
secure(dto: UnsecuredDto<Engagement>, session: Session): Engagement {
153-
return this.privileges.for(session, resolveEngagementType(dto)).secure(dto);
153+
private secure<E extends Engagement>(
154+
dto: UnsecuredDto<E>,
155+
session: Session,
156+
): E {
157+
const res = resolveEngagementType(dto) as unknown as ResourceShape<E>;
158+
return this.privileges.for(session, res).secure(dto);
154159
}
155160

156161
async updateLanguageEngagement(
@@ -160,20 +165,23 @@ export class EngagementService {
160165
): Promise<LanguageEngagement> {
161166
const view: ObjectView = viewOfChangeset(changeset);
162167

163-
const previous = await this.repo.readOne(input.id, session, view);
164-
const object = this.secure(previous, session) as LanguageEngagement;
168+
const previous = (await this.repo.readOne(
169+
input.id,
170+
session,
171+
view,
172+
)) as UnsecuredDto<LanguageEngagement>;
173+
const object = this.secure(previous, session);
165174

166-
if (input.status && input.status !== previous.status) {
175+
const { methodology, ...maybeChanges } = input;
176+
const changes = this.repo.getActualLanguageChanges(object, maybeChanges);
177+
if (changes.status) {
167178
await this.engagementRules.verifyStatusChange(
168179
input.id,
169180
session,
170-
input.status,
181+
changes.status,
171182
changeset,
172183
);
173184
}
174-
175-
const { methodology, ...maybeChanges } = input;
176-
const changes = this.repo.getActualLanguageChanges(object, maybeChanges);
177185
this.privileges
178186
.for(session, LanguageEngagement, object)
179187
.verifyChanges(changes);
@@ -188,7 +196,14 @@ export class EngagementService {
188196
changeset,
189197
);
190198

191-
RequiredWhen.verify(LanguageEngagement, updated);
199+
const prevMissing = RequiredWhen.calc(LanguageEngagement, previous);
200+
const nowMissing = RequiredWhen.calc(LanguageEngagement, updated);
201+
if (
202+
nowMissing &&
203+
(!prevMissing || nowMissing.missing.length >= prevMissing.missing.length)
204+
) {
205+
throw nowMissing;
206+
}
192207

193208
const event = new EngagementUpdatedEvent(
194209
updated,
@@ -210,19 +225,22 @@ export class EngagementService {
210225
): Promise<InternshipEngagement> {
211226
const view: ObjectView = viewOfChangeset(changeset);
212227

213-
const previous = await this.repo.readOne(input.id, session, view);
214-
const object = this.secure(previous, session) as InternshipEngagement;
228+
const previous = (await this.repo.readOne(
229+
input.id,
230+
session,
231+
view,
232+
)) as UnsecuredDto<InternshipEngagement>;
233+
const object = this.secure(previous, session);
215234

216-
if (input.status && input.status !== previous.status) {
235+
const changes = this.repo.getActualInternshipChanges(object, input);
236+
if (changes.status) {
217237
await this.engagementRules.verifyStatusChange(
218238
input.id,
219239
session,
220-
input.status,
240+
changes.status,
221241
changeset,
222242
);
223243
}
224-
225-
const changes = this.repo.getActualInternshipChanges(object, input);
226244
this.privileges
227245
.for(session, InternshipEngagement, object)
228246
.verifyChanges(changes, { pathPrefix: 'engagement' });
@@ -234,7 +252,14 @@ export class EngagementService {
234252
changeset,
235253
);
236254

237-
RequiredWhen.verify(InternshipEngagement, updated);
255+
const prevMissing = RequiredWhen.calc(InternshipEngagement, previous);
256+
const nowMissing = RequiredWhen.calc(InternshipEngagement, updated);
257+
if (
258+
nowMissing &&
259+
(!prevMissing || nowMissing.missing.length >= prevMissing.missing.length)
260+
) {
261+
throw nowMissing;
262+
}
238263

239264
const event = new EngagementUpdatedEvent(
240265
updated,

src/components/project/project.service.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,14 @@ export class ProjectService {
343343

344344
updated = await this.repo.update(updated, changes, changeset);
345345

346-
RequiredWhen.verify(IProject, updated);
346+
const prevMissing = RequiredWhen.calc(IProject, currentProject);
347+
const nowMissing = RequiredWhen.calc(IProject, updated);
348+
if (
349+
nowMissing &&
350+
(!prevMissing || nowMissing.missing.length >= prevMissing.missing.length)
351+
) {
352+
throw nowMissing;
353+
}
347354

348355
const event = new ProjectUpdatedEvent(
349356
updated,

0 commit comments

Comments
 (0)