Skip to content

Commit 930763c

Browse files
committed
Allow reopening of registration phase
1 parent be54289 commit 930763c

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

src/services/ChallengePhaseService.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ const PHASE_RESOURCE_ROLE_REQUIREMENTS = Object.freeze({
3131
review: "Reviewer",
3232
"checkpoint review": "Checkpoint Reviewer",
3333
});
34+
const SUBMISSION_PHASE_NAME_SET = new Set(["submission", "topgear submission"]);
35+
const REGISTRATION_PHASE_NAME = "registration";
36+
37+
const normalizePhaseName = (name) => String(name || "").trim().toLowerCase();
3438

3539
async function hasPendingScorecardsForPhase(challengePhaseId) {
3640
if (!config.REVIEW_DB_URL) {
@@ -561,7 +565,14 @@ async function partiallyUpdateChallengePhase(currentUser, challengeId, id, data)
561565
return reopenedPhaseIdentifiers.has(String(phase.predecessor));
562566
});
563567

564-
if (dependentOpenPhases.length === 0) {
568+
const normalizedPhaseName = normalizePhaseName(phaseName);
569+
const hasSubmissionVariantOpen = openPhases.some((phase) =>
570+
SUBMISSION_PHASE_NAME_SET.has(normalizePhaseName(phase?.name))
571+
);
572+
const allowRegistrationReopenWithoutExplicitDependency =
573+
normalizedPhaseName === REGISTRATION_PHASE_NAME && hasSubmissionVariantOpen;
574+
575+
if (dependentOpenPhases.length === 0 && !allowRegistrationReopenWithoutExplicitDependency) {
565576
throw new errors.ForbiddenError(
566577
`Cannot reopen ${phaseName} because no currently open phase depends on it`
567578
);

test/unit/ChallengePhaseService.test.js

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ describe('challenge phase service unit tests', () => {
330330
}
331331
})
332332

333-
it('partially update challenge phase - cannot reopen when open phase is not a successor', async () => {
333+
it('partially update challenge phase - can reopen registration when submission is open', async () => {
334334
const startDate = new Date('2025-06-01T00:00:00.000Z')
335335
const endDate = new Date('2025-06-02T00:00:00.000Z')
336336

@@ -350,6 +350,60 @@ describe('challenge phase service unit tests', () => {
350350
}
351351
})
352352

353+
try {
354+
const challengePhase = await service.partiallyUpdateChallengePhase(
355+
authUser,
356+
data.challenge.id,
357+
data.challengePhase1Id,
358+
{
359+
isOpen: true
360+
}
361+
)
362+
should.equal(challengePhase.id, data.challengePhase1Id)
363+
should.equal(challengePhase.isOpen, true)
364+
should.equal(challengePhase.actualEndDate, null)
365+
} finally {
366+
await prisma.challengePhase.update({
367+
where: { id: data.challengePhase1Id },
368+
data: {
369+
isOpen: false,
370+
actualStartDate: startDate,
371+
actualEndDate: endDate
372+
}
373+
})
374+
await prisma.challengePhase.update({
375+
where: { id: data.challengePhase2Id },
376+
data: {
377+
isOpen: false,
378+
predecessor: data.challengePhase1Id,
379+
name: 'Submission'
380+
}
381+
})
382+
}
383+
384+
})
385+
386+
it('partially update challenge phase - cannot reopen when open phase is not a successor or submission variant', async () => {
387+
const startDate = new Date('2025-06-01T00:00:00.000Z')
388+
const endDate = new Date('2025-06-02T00:00:00.000Z')
389+
390+
await prisma.challengePhase.update({
391+
where: { id: data.challengePhase1Id },
392+
data: {
393+
isOpen: false,
394+
actualStartDate: startDate,
395+
actualEndDate: endDate
396+
}
397+
})
398+
await prisma.challengePhase.update({
399+
where: { id: data.challengePhase2Id },
400+
data: {
401+
isOpen: true,
402+
predecessor: null,
403+
name: 'Review'
404+
}
405+
})
406+
353407
try {
354408
await service.partiallyUpdateChallengePhase(authUser, data.challenge.id, data.challengePhase1Id, {
355409
isOpen: true
@@ -366,7 +420,16 @@ describe('challenge phase service unit tests', () => {
366420
where: { id: data.challengePhase2Id },
367421
data: {
368422
isOpen: false,
369-
predecessor: data.challengePhase1Id
423+
predecessor: data.challengePhase1Id,
424+
name: 'Submission'
425+
}
426+
})
427+
await prisma.challengePhase.update({
428+
where: { id: data.challengePhase1Id },
429+
data: {
430+
isOpen: false,
431+
actualStartDate: startDate,
432+
actualEndDate: endDate
370433
}
371434
})
372435
}

0 commit comments

Comments
 (0)