diff --git a/backend/app/services/test_workflow_service.py b/backend/app/services/test_workflow_service.py index f26357e..352102e 100644 --- a/backend/app/services/test_workflow_service.py +++ b/backend/app/services/test_workflow_service.py @@ -655,27 +655,33 @@ def get_retest_chain(db: Session, test_id) -> list[Test]: def reopen_test(db: Session, test: Test, user: User) -> Test: - """Move a ``rejected`` test back to ``draft``, clearing validation fields. + """Move a ``rejected`` test back to ``draft`` for continued work. - This allows the teams to redo the test cycle. + Preserves all content (procedure, summaries, evidences) and — crucially — + the rejection NOTES so teams know what to fix without losing context. + + Clears validation decisions (status, who validated, when) so leads must + re-validate the updated submission. Phase timing is reset so the timer + starts fresh for the new execution attempt. """ test = transition_state( db, test, TestState.draft, user, action_name="reopen_test", ) - # Clear dual-validation fields + # Clear validation DECISIONS — leads must re-validate the new attempt. + # Rejection NOTES are intentionally kept so teams see what needs fixing. test.red_validation_status = None test.red_validated_by = None test.red_validated_at = None - test.red_validation_notes = None + # test.red_validation_notes → KEEP (rejection reason / clarification needed) test.blue_validation_status = None test.blue_validated_by = None test.blue_validated_at = None - test.blue_validation_notes = None + # test.blue_validation_notes → KEEP (rejection reason / clarification needed) - # Clear phase timing fields + # Reset phase timing so the new execution starts fresh test.red_started_at = None test.blue_started_at = None test.blue_work_started_at = None diff --git a/frontend/src/components/test-detail/TestDetailHeader.tsx b/frontend/src/components/test-detail/TestDetailHeader.tsx index a6151f7..537a0fa 100644 --- a/frontend/src/components/test-detail/TestDetailHeader.tsx +++ b/frontend/src/components/test-detail/TestDetailHeader.tsx @@ -225,7 +225,7 @@ export default function TestDetailHeader({ className="flex items-center gap-1.5 rounded-lg border border-cyan-500/30 bg-cyan-900/20 px-4 py-2 text-sm font-medium text-cyan-400 hover:bg-cyan-900/40 transition-colors disabled:opacity-50" > {isTransitioning ? : } - Reopen Test + Continue Test , ); } diff --git a/frontend/src/pages/TestDetailPage.tsx b/frontend/src/pages/TestDetailPage.tsx index 2d76590..de23ca5 100644 --- a/frontend/src/pages/TestDetailPage.tsx +++ b/frontend/src/pages/TestDetailPage.tsx @@ -230,7 +230,7 @@ export default function TestDetailPage() { onSuccess: () => { invalidateAll(); setConfirmReopen(false); - showToast("Test reopened", "success"); + showToast("Test returned to Draft — address the feedback and resubmit", "success"); }, onError: (err: unknown) => { setConfirmReopen(false); @@ -587,9 +587,9 @@ export default function TestDetailPage() { {/* Confirm Reopen Dialog */} reopenMutation.mutate()}