@@ -19,6 +19,7 @@ const paymentService = require('./paymentService')
1919const { createOrSetNumberOfReviewers } = require ( './selfServiceReviewerService' )
2020const { disableTimelineNotifications } = require ( './selfServiceNotificationService' )
2121const legacyChallengeService = require ( './legacyChallengeService' )
22+ const legacyChallengeReviewService = require ( './legacyChallengeReviewService' )
2223
2324/**
2425 * Drop and recreate phases in ifx
@@ -51,6 +52,30 @@ async function recreatePhases (legacyId, v5Phases, createdBy) {
5152 phase . duration * 1000 ,
5253 createdBy
5354 )
55+ //Handle checkpoint phases
56+ //Magic numbers: 15=checkpoint submission, 16=checkpoint screen, 17=checkpoint review, 1=registration
57+ //For dependencyStart: 1=start, 0=end
58+ if ( phaseLegacyId == 17 ) {
59+ logger . info ( `Creating phase dependencies for checkpoint phases` )
60+
61+ const registrationPhaseId = await timelineService . getProjectPhaseId ( legacyId , 1 )
62+ const checkpointSubmissionPhaseId = await timelineService . getProjectPhaseId ( legacyId , 15 )
63+ const checkpointScreeningPhaseId = await timelineService . getProjectPhaseId ( legacyId , 16 )
64+ const checkpointReviewPhaseId = await timelineService . getProjectPhaseId ( legacyId , 17 )
65+
66+ await timelineService . insertPhaseDependency ( registrationPhaseId , checkpointSubmissionPhaseId , 1 , createdBy )
67+ await timelineService . insertPhaseDependency ( checkpointSubmissionPhaseId , checkpointScreeningPhaseId , 0 , createdBy )
68+ await timelineService . insertPhaseDependency ( checkpointScreeningPhaseId , checkpointReviewPhaseId , 0 , createdBy )
69+
70+ logger . info ( `Creating default scorecard records for checkpoint phases` )
71+ //30001364 is the default checkpoint screening scorecard for studio (https://software.topcoder-dev.com/review/actions/ViewScorecard?scid=30001364)
72+ await timelineService . insertScorecardId ( checkpointScreeningPhaseId , 30001364 , createdBy )
73+
74+ //30001364 is the default checkpoint review scorecard for studio (https://software.topcoder-dev.com/review/actions/ViewScorecard?scid=30001004)
75+ await timelineService . insertScorecardId ( checkpointReviewPhaseId , 30001004 , createdBy )
76+
77+
78+ }
5479 } else if ( ! phaseLegacyId ) {
5580 logger . warn ( `Could not create phase ${ phase . name } on legacy!` )
5681 }
@@ -79,42 +104,53 @@ async function syncChallengePhases (legacyId, v5Phases, createdBy, isSelfService
79104 const phasesFromIFx = await timelineService . getChallengePhases ( legacyId )
80105 logger . debug ( `Phases from v5: ${ JSON . stringify ( v5Phases ) } ` )
81106 logger . debug ( `Phases from IFX: ${ JSON . stringify ( phasesFromIFx ) } ` )
82- for ( const phase of phasesFromIFx ) {
83- const phaseName = _ . get ( _ . find ( phaseTypes , pt => pt . phase_type_id === phase . phase_type_id ) , 'name' )
84- const v5Equivalent = _ . find ( v5Phases , p => p . name === phaseName )
85- logger . info ( `v4 Phase: ${ JSON . stringify ( phase ) } , v5 Equiv: ${ JSON . stringify ( v5Equivalent ) } ` )
86- if ( v5Equivalent ) {
87- // Compare duration and status
88- // if (v5Equivalent.duration * 1000 !== phase.duration * 1 || isSelfService) {
89- // ||
90- // (v5Equivalent.isOpen && _.toInteger(phase.phase_status_id) === constants.PhaseStatusTypes.Closed) ||
91- // (!v5Equivalent.isOpen && _.toInteger(phase.phase_status_id) === constants.PhaseStatusTypes.Open)) {
92- // const newStatus = v5Equivalent.isOpen
93- // ? constants.PhaseStatusTypes.Open
94- // : (new Date().getTime() <= new Date(v5Equivalent.scheduledEndDate).getTime() ? constants.PhaseStatusTypes.Scheduled : constants.PhaseStatusTypes.Closed)
95- // update phase
96- logger . debug ( `Will update phase ${ phaseName } /${ v5Equivalent . name } from ${ phase . duration } to duration ${ v5Equivalent . duration * 1000 } milli` )
97- const newStatus = v5Equivalent . isOpen
98- ? constants . PhaseStatusTypes . Open
99- : ( _ . toInteger ( phase . phase_status_id ) === constants . PhaseStatusTypes . Scheduled ? constants . PhaseStatusTypes . Scheduled : constants . PhaseStatusTypes . Closed )
100- await timelineService . updatePhase (
101- phase . project_phase_id ,
102- legacyId ,
103- v5Equivalent . scheduledStartDate ,
104- v5Equivalent . scheduledEndDate ,
105- v5Equivalent . duration * 1000 ,
106- newStatus // phase.phase_status_id
107- )
108- // newStatus)
109- // } else {
110- // logger.info(`Durations for ${phaseName} match: ${v5Equivalent.duration * 1000} === ${phase.duration}`)
111- // }
112- } else {
113- logger . info ( `No v5 Equivalent Found for ${ phaseName } ` )
107+ let phaseGroups = { }
108+ _ . forEach ( phasesFromIFx , p => {
109+ if ( ! phaseGroups [ p . phase_type_id ] ) {
110+ phaseGroups [ p . phase_type_id ] = [ ]
114111 }
115- if ( isSelfService && phaseName === 'Review' ) {
116- // make sure to set the required reviewers to 2
117- await createOrSetNumberOfReviewers ( _ . toString ( phase . project_phase_id ) , _ . toString ( numOfReviewers ) , _ . toString ( createdBy ) )
112+ phaseGroups [ p . phase_type_id ] . push ( p )
113+ } )
114+ _ . forEach ( _ . cloneDeep ( phaseGroups ) , ( pg , pt ) => {
115+ phaseGroups [ pt ] = _ . sortBy ( pg , 'scheduled_start_time' )
116+ } )
117+
118+ for ( const key of _ . keys ( phaseGroups ) ) {
119+ let phaseOrder = 0
120+ let v5Equivalents = undefined
121+ for ( const phase of phaseGroups [ key ] ) {
122+ const phaseName = _ . get ( _ . find ( phaseTypes , pt => pt . phase_type_id === phase . phase_type_id ) , 'name' )
123+ if ( _ . isUndefined ( v5Equivalents ) ) {
124+ v5Equivalents = _ . sortBy ( _ . filter ( v5Phases , p => p . name === phaseName ) , 'scheduledStartDate' )
125+ }
126+ if ( v5Equivalents . length > 0 ) {
127+ if ( v5Equivalents . length === phaseGroups [ key ] . length ) {
128+ const v5Equivalent = v5Equivalents [ phaseOrder ]
129+ logger . debug ( `Will update phase ${ phaseName } /${ v5Equivalent . name } from ${ phase . duration } to duration ${ v5Equivalent . duration * 1000 } milli` )
130+ let newStatus = _ . toInteger ( phase . phase_status_id )
131+ if ( v5Equivalent . isOpen && _ . toInteger ( phase . phase_status_id ) === constants . PhaseStatusTypes . Closed ) {
132+ newStatus = constants . PhaseStatusTypes . Scheduled
133+ }
134+ await timelineService . updatePhase (
135+ phase . project_phase_id ,
136+ legacyId ,
137+ phase . fixed_start_time ? v5Equivalent . scheduledStartDate : null ,
138+ v5Equivalent . scheduledStartDate ,
139+ v5Equivalent . scheduledEndDate ,
140+ v5Equivalent . duration * 1000 ,
141+ newStatus
142+ )
143+ } else {
144+ logger . info ( `number of ${ phaseName } does not match` )
145+ }
146+ } else {
147+ logger . info ( `No v5 Equivalent Found for ${ phaseName } ` )
148+ }
149+ if ( isSelfService && phaseName === 'Review' ) {
150+ // make sure to set the required reviewers to 2
151+ await createOrSetNumberOfReviewers ( _ . toString ( phase . project_phase_id ) , _ . toString ( numOfReviewers ) , _ . toString ( createdBy ) )
152+ }
153+ phaseOrder = phaseOrder + 1
118154 }
119155 }
120156 // TODO: What about iterative reviews? There can be many for the same challenge.
@@ -701,6 +737,28 @@ async function processMessage (message) {
701737 throw new Error ( `Error getting challenge by id - Error: ${ JSON . stringify ( e ) } ` )
702738 }
703739
740+ // If iterative review is open
741+ if ( _ . find ( _ . get ( message . payload , 'phases' ) , p => p . isOpen && p . name === 'Iterative Review' ) ) {
742+ // Try to read reviews and insert them into informix DB
743+ if ( message . payload . metadata && message . payload . legacy . reviewScorecardId ) {
744+ let orReviewFeedback = _ . find ( message . payload . metadata , meta => meta . name === 'or_review_feedback' )
745+ let orReviewScore = _ . find ( message . payload . metadata , meta => meta . name === 'or_review_score' )
746+ if ( ! _ . isUndefined ( orReviewFeedback ) && ! _ . isUndefined ( orReviewScore ) ) {
747+ orReviewFeedback = JSON . parse ( orReviewFeedback )
748+ const reviewResponses = [ ]
749+ _ . each ( orReviewFeedback , ( value , key ) => {
750+ const questionId = _ . get ( _ . find ( constants . scorecardQuestionMapping [ message . payload . legacy . reviewScorecardId ] , item => _ . toString ( item . questionId ) === _ . toString ( key ) || _ . toLower ( item . description ) === _ . toLower ( key ) ) , 'questionId' )
751+ reviewResponses . push ( {
752+ questionId,
753+ answer : value
754+ } )
755+ } )
756+ orReviewScore = _ . toNumber ( orReviewFeedback )
757+ await legacyChallengeReviewService . insertReview ( legacyId , message . payload . legacy . reviewScorecardId , orReviewScore , reviewResponses , createdByUserId )
758+ }
759+ }
760+ }
761+
704762 if ( message . payload . status && challenge ) {
705763 // Whether we need to sync v4 ES again
706764 let needSyncV4ES = false
@@ -788,7 +846,7 @@ processMessage.schema = {
788846 prizeSets : Joi . array ( ) . items ( Joi . object ( ) . keys ( {
789847 type : Joi . string ( ) . valid ( _ . values ( constants . prizeSetTypes ) ) . required ( ) ,
790848 prizes : Joi . array ( ) . items ( Joi . object ( ) . keys ( {
791- value : Joi . number ( ) . positive ( ) . required ( )
849+ value : Joi . number ( ) . min ( 0 ) . required ( )
792850 } ) . unknown ( true ) )
793851 } ) . unknown ( true ) ) . min ( 1 ) ,
794852 tags : Joi . array ( ) . items ( Joi . string ( ) . required ( ) ) . min ( 1 ) , // tag names
0 commit comments