Skip to content

PM-4318 move to next phase when manually closing#80

Merged
vas3a merged 7 commits intodevelopfrom
PM-4318_move-to-next-phase-when-manually-closing
Mar 18, 2026
Merged

PM-4318 move to next phase when manually closing#80
vas3a merged 7 commits intodevelopfrom
PM-4318_move-to-next-phase-when-manually-closing

Conversation

@vas3a
Copy link
Collaborator

@vas3a vas3a commented Mar 17, 2026

https://topcoder.atlassian.net/browse/PM-4318 - When submission phase is manually closed, the AI screening phase doesn't get opened even if all AI reviews are completed

Make sure phases are recalculated and autopilot is advancing phases when user intervenes in timeline

Challenge Phase Scheduling Improvements:

  • Added a new function, shiftDependentPhaseDates, to ChallengePhaseService.js that shifts the scheduled start and end dates of all successor phases when a phase is closed with an actual end date different from its scheduled end date. This ensures phase timelines remain consistent when phases are closed early or late.
  • Updated partiallyUpdateChallengePhase to call shiftDependentPhaseDates when closing a phase, applying the time delta to all dependent phases.
  • Added a comprehensive unit test to verify that closing a phase shifts the scheduled dates of its successors to match the actual closure time.

AI Screening Phase Closure Logic Refactor:

  • Moved extractSubmissionId, ensureChallengeHasAiReviewers, and ensureAIScreeningCanBeClosed from ChallengePhaseService.js to ChallengeService.js for better separation of concerns and to avoid circular dependencies.

Open with Devin

@vas3a vas3a requested review from jmgasper and kkartunov March 17, 2026 21:35
const endChanged = !datesAreSame(successor.scheduledEndDate, desiredEndDate);

if (startChanged || endChanged) {
successorForQueue = await tx.challengePhase.update({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The update operation inside the loop could lead to performance issues if there are many successor phases. Consider batching updates or using a more efficient mechanism to reduce the number of database transactions.

await recalculateDependentPhaseDates(tx, challengeId, updatedPhase, currentUserId);
}
}
if (isClosingPhase && !_.isNil(originalScheduledEndDate) && !_.isNil(updatedPhase.actualEndDate)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
The logic for calculating scheduledEndTime and actualEndTime should handle potential NaN values more explicitly to avoid unexpected behavior if dates are malformed or missing.

data.challenge.id,
data.challengePhase2Id,
{
isOpen: false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Consider adding validation to ensure that the actualEndDate is set before closing the phase. This will prevent potential issues if the phase is closed without an end date, which could lead to incorrect scheduling of successor phases.


actualEndMs.should.be.at.least(before.getTime())
actualEndMs.should.be.at.most(after.getTime())
successorStartMs.should.equal(actualEndMs)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 design]
The test assumes that the successor phase's start date should exactly match the actualEndDate of the closed phase. Ensure that this behavior is intended and documented, as it might not be obvious to all developers.

devin-ai-integration[bot]

This comment was marked as resolved.

…-close-review-when-escalations-pending

PM-4363 - do not allow review phase to be clsoed, appeals to be open …
`Found AI review configuration ${aiReviewConfig.id} for challenge ${challengeId}`
);

const reviewPrisma = getReviewClient();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
Consider using a single instance of the review client for the entire service to avoid creating multiple connections, which can lead to resource exhaustion.


// Check if this is the Appeals phase
const normalizedPhaseName = normalizePhaseName(phaseName);
if (normalizedPhaseName === "appeals") {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The check for pending escalation requests is performed only when opening the Appeals phase. Ensure that this logic aligns with the business requirements, as it might be necessary to check for pending escalations in other phases as well.

}
if (
String(closingPhaseName || "").toLowerCase() === "appeals response" &&
normalizedClosingPhaseName === "review" &&

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The check for pending escalation requests when closing the Review phase is similar to the check when opening the Appeals phase. Ensure consistency in how these checks are applied across different phases.

vas3a added 2 commits March 18, 2026 13:33
…thub.com:topcoder-platform/challenge-api-v6 into PM-4318_move-to-next-phase-when-manually-closing
@vas3a vas3a requested a review from kkartunov March 18, 2026 11:34
devin-ai-integration[bot]

This comment was marked as resolved.

id: challengePhase.id,
},
});
let scheduleExtended = false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 readability]
The variable scheduleExtended is declared with let and then reassigned. Consider using const for the initial declaration and reassigning only if necessary to improve code clarity and prevent accidental reassignment.

await recalculateDependentPhaseDates(tx, challengeId, updatedPhase, currentUserId);
}
}
if (isClosingPhase && !_.isNil(originalScheduledEndDate) && !_.isNil(updatedPhase.actualEndDate)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 readability]
The logic for determining shiftBaselineScheduledEndDate could be simplified by directly assigning the value based on the condition, which would enhance readability.

@vas3a vas3a merged commit caef239 into develop Mar 18, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants