diff --git a/.circleci/config.yml b/.circleci/config.yml index 85b1277..55f7706 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,8 +59,7 @@ workflows: branches: only: - develop - - PM-4482 - - security_july_2026 + - 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 460315b..0c64c3c 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2489,11 +2489,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 @@ -2504,7 +2505,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.ts b/src/services/MemberService.ts index f0dc0d9..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. @@ -617,6 +645,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 @@ -626,6 +655,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 @@ -645,14 +675,22 @@ 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 (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 (isEngagementAvailabilityComplete(member, openToWorkData)) { + if (isEngagementAvailabilityComplete(member, openToWorkData)) { + completeItems += 1 + data.engagementAvailability = true + data.engagementAvailabilityLastUpdateDate = new Date(item.updatedAt).toISOString() + } + } + + if (!data.preferredRoles && hasPreferredRolesSelected(item.traits.data)) { completeItems += 1 - data.engagementAvailability = true - data.engagementAvailabilityLastUpdateDate = new Date(item.updatedAt).toISOString() + data.preferredRoles = true + data.preferredRolesLastUpdateDate = new Date(item.updatedAt).toISOString() } } }) @@ -666,6 +704,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) {