@@ -48,11 +48,11 @@ const DISTRIBUTION_FIELDS = ['track', 'subTrack', 'distribution', 'createdAt', '
4848 'createdBy' , 'updatedBy' ]
4949const DISTRIBUTION_FIELDS_NO_DATE = [ 'track' , 'subTrack' , 'distribution' ]
5050
51- const HISTORY_STATS_FIELDS = [ 'userId' , 'groupId' , 'handle' , 'handleLower' , 'DEVELOP' , 'DESIGN' , 'DATA_SCIENCE' ,
51+ const HISTORY_STATS_FIELDS = [ 'userId' , 'groupId' , 'handle' , 'handleLower' , 'DEVELOP' , 'DESIGN' , 'DATA_SCIENCE' , 'QA' ,
5252 'createdAt' , 'updatedAt' , 'createdBy' , 'updatedBy' ]
5353
5454const MEMBER_STATS_FIELDS = [ 'userId' , 'groupId' , 'handle' , 'handleLower' , 'maxRating' ,
55- 'challenges' , 'wins' , 'DEVELOP' , 'DESIGN' , 'DATA_SCIENCE' , 'COPILOT' , 'createdAt' ,
55+ 'challenges' , 'wins' , 'DEVELOP' , 'DESIGN' , 'DATA_SCIENCE' , 'QA' , ' COPILOT', 'createdAt' ,
5656 'updatedAt' , 'createdBy' , 'updatedBy' ]
5757
5858const LEGACY_STATS_READ_SOURCE = 'legacy'
@@ -380,7 +380,6 @@ function normalizeChallengeSourceTrack (value) {
380380
381381/**
382382 * Check whether a challenge source track is Quality Assurance.
383- * QA Challenge results are surfaced in the legacy Testing bucket.
384383 * @param {* } value raw challenge track label, enum value, or abbreviation
385384 * @returns {boolean } true when the source track is QA
386385 */
@@ -527,8 +526,8 @@ function buildBaseRatingJob (challenge, source) {
527526 if ( source === RATING_SOURCE_QUALITY_ASSURANCE_CHALLENGE ) {
528527 return {
529528 source,
530- trackId : TRACK_NAMES . DEVELOP ,
531- typeId : TYPE_NAMES . BUG_HUNT
529+ trackId : TRACK_NAMES . QA ,
530+ typeId : TYPE_NAMES . CHALLENGE
532531 }
533532 }
534533
@@ -609,7 +608,7 @@ async function fetchChallengeResultParticipantIds (reviewDbClient, challengeId)
609608
610609/**
611610 * Fetch placement winner participants from challenge-api for completed
612- * Development/Data Science rating rerates. This covers challenges where winners
611+ * Development/Data Science/QA rating rerates. This covers challenges where winners
613612 * can be assigned without a review-api challengeResult row for the same member.
614613 * @param {Object } challengeClient challenge Prisma client
615614 * @param {string|number } challengeId challenge identifier
@@ -759,8 +758,8 @@ async function rerateChallengeRatingJobForMember (challengeClient, reviewDbClien
759758 }
760759 } else if ( job . source === RATING_SOURCE_QUALITY_ASSURANCE_CHALLENGE ) {
761760 rerateOptions = {
762- targetTrackName : TRACK_NAMES . DEVELOP ,
763- targetTypeName : TYPE_NAMES . BUG_HUNT ,
761+ targetTrackName : TRACK_NAMES . QA ,
762+ targetTypeName : TYPE_NAMES . CHALLENGE ,
764763 challengeTrackNames : getQualityAssuranceChallengeSourceTrackNames ( ) ,
765764 challengeTypeNames : [ TYPE_NAMES . CHALLENGE ]
766765 }
@@ -994,8 +993,8 @@ function isMarathonMatchType (typeName) {
994993/**
995994 * Resolve the public stats dimensions for a challenge-backed row.
996995 * Marathon Match rows are part of the public DATA_SCIENCE bucket even when
997- * source challenge metadata uses a different track. QA Challenge rows retain
998- * the legacy Testing surface under DEVELOP / BUG_HUNT .
996+ * source challenge metadata uses a different track. QA Challenge rows remain
997+ * under the first-class QA / Challenge dimension .
999998 * @param {Object } row row containing trackId and typeId
1000999 * @param {Object } dimensionLookup shared challenge dimension lookup
10011000 * @returns {Object } normalized track/type ids and names
@@ -1014,15 +1013,15 @@ function resolveStatsDimensionForChallengeRow (row, dimensionLookup) {
10141013
10151014 const trackName = resolveTrackNameFromLookup ( dimensionLookup , row . trackId )
10161015 if ( typeName === TYPE_NAMES . CHALLENGE && isQualityAssuranceChallengeSourceTrack ( trackName ) ) {
1017- const developTrackId = resolveTrackIdFromLookup ( dimensionLookup , TRACK_NAMES . DEVELOP )
1018- const bugHuntTypeId = resolveTypeIdFromLookup ( dimensionLookup , TYPE_NAMES . BUG_HUNT )
1016+ const qaTrackId = resolveTrackIdFromLookup ( dimensionLookup , TRACK_NAMES . QA )
1017+ const challengeTypeId = resolveTypeIdFromLookup ( dimensionLookup , TYPE_NAMES . CHALLENGE )
10191018
1020- if ( developTrackId && bugHuntTypeId ) {
1019+ if ( qaTrackId && challengeTypeId ) {
10211020 return {
1022- trackId : developTrackId ,
1023- typeId : bugHuntTypeId ,
1024- trackName : TRACK_NAMES . DEVELOP ,
1025- typeName : TYPE_NAMES . BUG_HUNT
1021+ trackId : qaTrackId ,
1022+ typeId : challengeTypeId ,
1023+ trackName : TRACK_NAMES . QA ,
1024+ typeName : TYPE_NAMES . CHALLENGE
10261025 }
10271026 }
10281027 }
@@ -1618,12 +1617,12 @@ function buildAggregatedStatsFromReviewResults (reviewRows, challengeMetadataByI
16181617
16191618/**
16201619 * Check whether the unified history response should surface the supplied track.
1621- * The public history contract currently exposes DEVELOPMENT, DESIGN, and DATA_SCIENCE groups.
1620+ * The public history contract currently exposes DEVELOPMENT, DESIGN, DATA_SCIENCE, and QA groups.
16221621 * @param {string|undefined } trackName canonical track label
16231622 * @returns {boolean } true when the track should be included in history responses
16241623 */
16251624function isSupportedUnifiedHistoryTrack ( trackName ) {
1626- return _ . includes ( [ TRACK_NAMES . DEVELOP , TRACK_NAMES . DESIGN , TRACK_NAMES . DATA_SCIENCE ] , trackName )
1625+ return _ . includes ( [ TRACK_NAMES . DEVELOP , TRACK_NAMES . DESIGN , TRACK_NAMES . DATA_SCIENCE , TRACK_NAMES . QA ] , trackName )
16271626}
16281627
16291628/**
@@ -4353,7 +4352,7 @@ refreshMemberStats.schema = {
43534352 * rating dimensions. This includes the native challenge track/type rating when
43544353 * supported and any configured named rating paths whose tags/skills match the
43554354 * challenge, such as the default AI path. Quality Assurance Challenge rows are
4356- * replayed into the legacy Testing bucket under DEVELOP / BUG_HUNT .
4355+ * replayed into the first-class QA / Challenge stats dimension .
43574356 * @param {Object } currentUser the user who performs operation
43584357 * @param {Object } data rerate payload containing the completed challenge id
43594358 * @returns {Object } summary of participants, rating jobs, updates, and per-member failures
@@ -4514,7 +4513,7 @@ rerateChallengeSubmitterRatings.schema = {
45144513
45154514/**
45164515 * Trigger a DEVELOPMENT / Challenge, DATA_SCIENCE / Challenge,
4517- * DATA_SCIENCE / MARATHON_MATCH, or configured tag- or skill-based rating path
4516+ * QA / Challenge, DATA_SCIENCE / MARATHON_MATCH, or configured tag- or skill-based rating path
45184517 * re-rating pass beginning with the supplied challenge.
45194518 * The relevant review-api results are reprocessed in chronological order and
45204519 * persisted into the existing unified rating tables for the member.
@@ -4572,6 +4571,20 @@ async function rerateMemberStats (currentUser, handle, data) {
45724571 challengeTypeNames : [ TYPE_NAMES . CHALLENGE ]
45734572 }
45744573 )
4574+ } else if ( trackId === TRACK_NAMES . QA && typeId === TYPE_NAMES . CHALLENGE ) {
4575+ result = await rerateDevTrack (
4576+ prisma ,
4577+ challengeClient ,
4578+ reviewDbClient ,
4579+ member . userId ,
4580+ payload . challengeId ,
4581+ {
4582+ targetTrackName : TRACK_NAMES . QA ,
4583+ targetTypeName : TYPE_NAMES . CHALLENGE ,
4584+ challengeTrackNames : getQualityAssuranceChallengeSourceTrackNames ( ) ,
4585+ challengeTypeNames : [ TYPE_NAMES . CHALLENGE ]
4586+ }
4587+ )
45754588 } else if ( trackId === TRACK_NAMES . DATA_SCIENCE && typeId === TYPE_NAMES . MARATHON_MATCH ) {
45764589 result = await rerateMmTrack (
45774590 prisma ,
@@ -4582,7 +4595,7 @@ async function rerateMemberStats (currentUser, handle, data) {
45824595 payload . challengeId
45834596 )
45844597 } else {
4585- throw new errors . BadRequestError ( 'Only DEVELOP / Challenge, DATA_SCIENCE / Challenge, and DATA_SCIENCE / MARATHON_MATCH rerates are currently supported.' )
4598+ throw new errors . BadRequestError ( 'Only DEVELOP / Challenge, DATA_SCIENCE / Challenge, QA / Challenge, and DATA_SCIENCE / MARATHON_MATCH rerates are currently supported.' )
45864599 }
45874600
45884601 return {
@@ -4607,7 +4620,7 @@ rerateMemberStats.schema = {
46074620 data : Joi . object ( ) . keys ( {
46084621 challengeId : Joi . alternatives ( ) . try ( Joi . string ( ) . uuid ( ) , Joi . number ( ) . integer ( ) . strict ( ) ) . required ( ) ,
46094622 ratingName : Joi . string ( ) ,
4610- trackId : Joi . string ( ) . valid ( TRACK_NAMES . DEVELOP , TRACK_NAMES . DATA_SCIENCE ) . insensitive ( ) ,
4623+ trackId : Joi . string ( ) . valid ( TRACK_NAMES . DEVELOP , TRACK_NAMES . DATA_SCIENCE , TRACK_NAMES . QA ) . insensitive ( ) ,
46114624 typeId : Joi . string ( ) . valid ( TYPE_NAMES . CHALLENGE , TYPE_NAMES . MARATHON_MATCH ) . insensitive ( )
46124625 } ) . required ( )
46134626}
0 commit comments