From 1cdf22ce5c1eb61fef99fa2a802faa80abfae8d6 Mon Sep 17 00:00:00 2001 From: himaniraghav3 Date: Tue, 11 Aug 2026 14:48:09 +0530 Subject: [PATCH 1/2] PM-5460 Include Preferred Roles in Profile Completion Calculation --- .circleci/config.yml | 2 +- docs/swagger.yaml | 12 ++++++--- src/services/MemberService.js | 50 +++++++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4379e6e..40d8c2c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -67,7 +67,7 @@ workflows: branches: only: - develop - - PM-4482 + - PM-5460 # Production builds are exectuted only on tagged commits to the # master branch. diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 79bcc8f..379e0e3 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2259,11 +2259,12 @@ definitions: properties: skills: type: boolean - gigAvailability: + engagementAvailability: type: boolean - bio: + preferredRoles: type: boolean - profilePicture: + description: True when the member has selected at least one preferred role. + bio: type: boolean workHistory: type: boolean @@ -2274,7 +2275,10 @@ definitions: skillsLastUpdateDate: type: date-time description: 'ISO-8601 formatted date times (YYYY-MM-DDTHH:mm:ss.sssZ)' - gigAvailabilityLastUpdateDate: + engagementAvailabilityLastUpdateDate: + type: date-time + description: 'ISO-8601 formatted date times (YYYY-MM-DDTHH:mm:ss.sssZ)' + preferredRolesLastUpdateDate: type: date-time description: 'ISO-8601 formatted date times (YYYY-MM-DDTHH:mm:ss.sssZ)' workHistoryLastUpdateDate: diff --git a/src/services/MemberService.js b/src/services/MemberService.js index 83910b8..e4bac2d 100644 --- a/src/services/MemberService.js +++ b/src/services/MemberService.js @@ -452,6 +452,7 @@ async function getProfileCompleteness (currentUser, handle, query) { // data.verified = false data.skills = false data.engagementAvailability = false + data.preferredRoles = false data.bio = false data.workHistory = false data.education = false @@ -461,6 +462,7 @@ async function getProfileCompleteness (currentUser, handle, query) { data.skillsLastUpdateDate = undefined data.engagementAvailabilityLastUpdateDate = undefined + data.preferredRolesLastUpdateDate = undefined data.workHistoryLastUpdateDate = undefined data.educationLastUpdateDate = undefined data.locationLastUpdateDate = undefined @@ -480,17 +482,40 @@ async function getProfileCompleteness (currentUser, handle, query) { data.workHistoryLastUpdateDate = new Date(item.updatedAt).toISOString() } - if (item.traitId === 'personalization' && item.traits.data.length > 0 && !data.engagementAvailability) { - const openToWorkTrait = item.traits.data.find(r => Object.keys(r).includes('openToWork')) || {} - const openToWorkData = openToWorkTrait.openToWork - - if (openToWorkData && ( - !openToWorkData.availability || - (openToWorkData.preferredRoles && openToWorkData.preferredRoles.length) - )) { - completeItems += 1 - data.engagementAvailability = true - data.engagementAvailabilityLastUpdateDate = new Date(item.updatedAt).toISOString() + if (item.traitId === 'personalization' && item.traits.data.length > 0) { + if (!data.engagementAvailability) { + const openToWorkTrait = item.traits.data.find(r => Object.keys(r).includes('openToWork')) || {} + const openToWorkData = openToWorkTrait.openToWork + + if (openToWorkData && ( + !openToWorkData.availability || + (openToWorkData.preferredRoles && openToWorkData.preferredRoles.length) + )) { + completeItems += 1 + data.engagementAvailability = true + data.engagementAvailabilityLastUpdateDate = new Date(item.updatedAt).toISOString() + } + } + + // Prefer top-level preferredRoles (current model); fall back to legacy openToWork.preferredRoles + if (!data.preferredRoles) { + const personalizationEntry = item.traits.data.find(r => + Object.prototype.hasOwnProperty.call(r, 'preferredRoles') || + Object.prototype.hasOwnProperty.call(r, 'openToWork') + ) || item.traits.data[0] || {} + + let preferredRoles + if (Object.prototype.hasOwnProperty.call(personalizationEntry, 'preferredRoles')) { + preferredRoles = personalizationEntry.preferredRoles + } else { + preferredRoles = personalizationEntry.openToWork && personalizationEntry.openToWork.preferredRoles + } + + if (Array.isArray(preferredRoles) && preferredRoles.length > 0) { + completeItems += 1 + data.preferredRoles = true + data.preferredRolesLastUpdateDate = new Date(item.updatedAt).toISOString() + } } } }) @@ -504,6 +529,9 @@ async function getProfileCompleteness (currentUser, handle, query) { if (!data.engagementAvailability) { showToast.push('engagementAvailability') } + if (!data.preferredRoles) { + showToast.push('preferredRoles') + } // TODO: Do we use the short bio or the "description" field of the member object? if (member.description && !data.bio) { From 83e5c0ff3d62b41f68bce4b2853e7143deb7eacd Mon Sep 17 00:00:00 2001 From: himaniraghav3 Date: Wed, 12 Aug 2026 10:13:26 +0530 Subject: [PATCH 2/2] PM-5460 Fix preferred roles check --- src/services/MemberService.ts | 59 +++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/services/MemberService.ts b/src/services/MemberService.ts index f47c2a3..d3fc265 100644 --- a/src/services/MemberService.ts +++ b/src/services/MemberService.ts @@ -81,6 +81,34 @@ function isEngagementAvailabilityComplete (member, openToWorkData) { return hasAvailability || hasLegacyPreferredRoles } +/** + * Determine whether the member has selected at least one preferred role. + * Prefers the top-level personalization.preferredRoles field (current model) + * and falls back to legacy openToWork.preferredRoles when the top-level key + * is absent. + * @param {Array} personalizationData personalization trait data entries + * @returns {Boolean} true when at least one preferred role is selected + */ +function hasPreferredRolesSelected (personalizationData) { + if (!Array.isArray(personalizationData) || personalizationData.length === 0) { + return false + } + + const personalizationEntry = personalizationData.find(r => + Object.prototype.hasOwnProperty.call(r, 'preferredRoles') || + Object.prototype.hasOwnProperty.call(r, 'openToWork') + ) || personalizationData[0] || {} + + let preferredRoles + if (Object.prototype.hasOwnProperty.call(personalizationEntry, 'preferredRoles')) { + preferredRoles = personalizationEntry.preferredRoles + } else { + preferredRoles = personalizationEntry.openToWork && personalizationEntry.openToWork.preferredRoles + } + + return Array.isArray(preferredRoles) && preferredRoles.length > 0 +} + /** * Resolve compact memberStats track/type UUIDs before deriving current * maxRating labels for member profile responses. @@ -652,32 +680,17 @@ async function getProfileCompleteness (currentUser, handle, query) { const openToWorkTrait = item.traits.data.find(r => Object.keys(r).includes('openToWork')) || {} const openToWorkData = openToWorkTrait.openToWork - if (isEngagementAvailabilityComplete(member, openToWorkData)) { - completeItems += 1 - data.engagementAvailability = true - data.engagementAvailabilityLastUpdateDate = new Date(item.updatedAt).toISOString() - } - - // Prefer top-level preferredRoles (current model); fall back to legacy openToWork.preferredRoles - if (!data.preferredRoles) { - const personalizationEntry = item.traits.data.find(r => - Object.prototype.hasOwnProperty.call(r, 'preferredRoles') || - Object.prototype.hasOwnProperty.call(r, 'openToWork') - ) || item.traits.data[0] || {} - - let preferredRoles - if (Object.prototype.hasOwnProperty.call(personalizationEntry, 'preferredRoles')) { - preferredRoles = personalizationEntry.preferredRoles - } else { - preferredRoles = personalizationEntry.openToWork && personalizationEntry.openToWork.preferredRoles - } - - if (Array.isArray(preferredRoles) && preferredRoles.length > 0) { + if (isEngagementAvailabilityComplete(member, openToWorkData)) { completeItems += 1 - data.preferredRoles = true - data.preferredRolesLastUpdateDate = new Date(item.updatedAt).toISOString() + data.engagementAvailability = true + data.engagementAvailabilityLastUpdateDate = new Date(item.updatedAt).toISOString() } } + + if (!data.preferredRoles && hasPreferredRolesSelected(item.traits.data)) { + completeItems += 1 + data.preferredRoles = true + data.preferredRolesLastUpdateDate = new Date(item.updatedAt).toISOString() } } })