Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
971bb9d
Fix update of mentorship types in mentee section
nycotin Jan 17, 2026
b68e92f
Change parameter validator for Country object
nycotin Jan 17, 2026
af31354
Add validation to prevent data loss
nycotin Jan 17, 2026
ad5e31a
Add unit tests for mentee section update repo
nycotin Jan 18, 2026
c0208ec
Remove unnecessary validation
nycotin Jan 18, 2026
08593fe
Change paramenter to Mentor object to avoid data loss
nycotin Jan 18, 2026
fe89ec4
Change test naming according to pmdAll
nycotin Jan 18, 2026
06a444b
Change spokenLanguages definition to avoid null instead of empty list
nycotin Jan 18, 2026
a5ed5af
Remove reference to Member merge, simplified checks
nycotin Jan 18, 2026
2615070
Add unit tests for MentorDto logic
nycotin Jan 18, 2026
751824c
Remove unnecessary Mentor casting
nycotin Jan 18, 2026
0be3a16
Remove unused variable
nycotin Jan 18, 2026
571fc8e
Change SQL statements into variables
nycotin Jan 18, 2026
bc69661
Add test for checking InvalidMentorException
nycotin Jan 18, 2026
5ba5296
Add normalizer for capitalization in Builder
nycotin Jan 18, 2026
883b18d
Add test for checking capitalization of languages, adjusted spokenLan…
nycotin Jan 18, 2026
8cc43ed
Update src/main/java/com/wcc/platform/domain/platform/mentorship/Ment…
nycotin Jan 21, 2026
3fab175
Update src/main/java/com/wcc/platform/domain/platform/mentorship/Ment…
nycotin Jan 21, 2026
09ebeb8
Add missing imports
nycotin Jan 21, 2026
02e5a5a
Merge branch 'main' of https://github.com/nycotin/wcc-backend into fi…
nycotin Jan 26, 2026
8b99f89
Add missing import
nycotin Jan 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

/** Represents the mentor members of the community. */
@Getter
Expand Down Expand Up @@ -73,13 +74,22 @@ public Mentor(

this.profileStatus = profileStatus;
this.skills = skills;
this.spokenLanguages = spokenLanguages.stream().map(StringUtils::capitalize).toList();
this.spokenLanguages = normalizeLanguages(spokenLanguages);
this.bio = bio;
this.menteeSection = menteeSection;
this.feedbackSection = feedbackSection;
this.resources = resources;
}

/** Checks for empty or null and returns capitalized list of string. */
private static List<String> normalizeLanguages(final List<String> languages) {
if (CollectionUtils.isEmpty(languages)) {
return List.of();
}

return languages.stream().filter(StringUtils::isNotBlank).map(StringUtils::capitalize).toList();
}

/**
* Converts this Mentor entity and an optional active MentorshipCycle into a MentorDto
* representation.
Expand Down Expand Up @@ -136,4 +146,12 @@ private MentorDtoBuilder buildFromMentor(final Mentor mentor) {
.feedbackSection(mentor.getFeedbackSection())
.resources(mentor.getResources());
}

/** Lombok builder hook to enforce normalization. */
public static class MentorBuilder {
public MentorBuilder spokenLanguages(final List<String> spokenLanguages) {
this.spokenLanguages = normalizeLanguages(spokenLanguages);
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.wcc.platform.domain.cms.attributes.Image;
import com.wcc.platform.domain.cms.pages.mentorship.FeedbackSection;
import com.wcc.platform.domain.cms.pages.mentorship.MenteeSection;
import com.wcc.platform.domain.exceptions.InvalidMentorException;
import com.wcc.platform.domain.platform.SocialNetwork;
import com.wcc.platform.domain.platform.member.MemberDto;
import com.wcc.platform.domain.platform.member.ProfileStatus;
Expand Down Expand Up @@ -83,46 +84,36 @@ public MentorDto(
}

/**
* Merges the current Mentor instance with the attributes of the provided Mentor instance.
* Combines properties from both instances into a new Mentor object, giving precedence to non-null
* values in the provided Mentor instance while retaining existing values where the provided
* values are null or empty.
* Merges this DTO with an existing Mentor entity. Non-null/non-blank DTO values override existing
* values; otherwise existing values are retained.
*
* @param mentor the Mentor object containing updated attributes to merge with the current
* instance
* @return a new Mentor object created by merging attributes from the current instance and the
* provided instance
* @param mentor the existing mentor to merge with
* @return merged Mentor with updated fields
*/
public Mentor merge(final Mentor mentor) {
final var member = super.merge(mentor);

final Mentor.MentorBuilder builder =
Mentor.mentorBuilder()
.id(member.getId())
.fullName(mergeString(this.getFullName(), member.getFullName()))
.position(mergeString(this.getPosition(), member.getPosition()))
.email(mergeString(this.getEmail(), member.getEmail()))
.slackDisplayName(mergeString(this.getSlackDisplayName(), member.getSlackDisplayName()))
.country(mergeNullable(this.getCountry(), member.getCountry()))
.profileStatus(mergeNullable(this.profileStatus, mentor.getProfileStatus()))
.bio(mergeString(this.bio, mentor.getBio()))
.skills(mergeNullable(this.skills, mentor.getSkills()))
.menteeSection(mergeNullable(this.menteeSection, mentor.getMenteeSection()));

mergeOptionalString(this.getCity(), member.getCity(), builder::city);

mergeOptionalString(this.getCompanyName(), member.getCompanyName(), builder::companyName);

builder.network(mergeCollection(this.getNetwork(), member.getNetwork()));
builder.spokenLanguages(
mergeCollection(this.getSpokenLanguages(), mentor.getSpokenLanguages()));
builder.images(mergeCollection(this.getImages(), member.getImages()));

mergeOptional(this.feedbackSection, mentor.getFeedbackSection(), builder::feedbackSection);

mergeOptional(this.resources, mentor.getResources(), builder::resources);
if (mentor == null) {
throw new InvalidMentorException("Cannot merge with null mentor");
}

return builder.build();
return Mentor.mentorBuilder()
.id(mentor.getId())
.fullName(mergeString(this.getFullName(), mentor.getFullName()))
.position(mergeString(this.getPosition(), mentor.getPosition()))
.email(mergeString(this.getEmail(), mentor.getEmail()))
.slackDisplayName(mergeString(this.getSlackDisplayName(), mentor.getSlackDisplayName()))
.city(mergeString(this.getCity(), mentor.getCity()))
.companyName(mergeString(this.getCompanyName(), mentor.getCompanyName()))
.country(mergeNullable(this.getCountry(), mentor.getCountry()))
.profileStatus(mergeNullable(this.getProfileStatus(), mentor.getProfileStatus()))
.bio(mergeString(this.getBio(), mentor.getBio()))
.skills(mergeNullable(this.getSkills(), mentor.getSkills()))
.menteeSection(mergeNullable(this.getMenteeSection(), mentor.getMenteeSection()))
.feedbackSection(mergeNullable(this.getFeedbackSection(), mentor.getFeedbackSection()))
.resources(mergeNullable(this.getResources(), mentor.getResources()))
.network(mergeCollection(this.getNetwork(), mentor.getNetwork()))
.spokenLanguages(mergeCollection(this.getSpokenLanguages(), mentor.getSpokenLanguages()))
.images(mergeCollection(this.getImages(), mentor.getImages()))
.build();
}

private String mergeString(final String candidate, final String existing) {
Expand All @@ -134,24 +125,9 @@ private <T> T mergeNullable(final T candidate, final T existing) {
}

private <T> List<T> mergeCollection(final List<T> candidate, final List<T> existing) {
return CollectionUtils.isEmpty(candidate) ? existing : candidate;
}

private void mergeOptionalString(
final String candidate,
final String existing,
final java.util.function.Consumer<String> setter) {

if (StringUtils.isNotBlank(candidate) || StringUtils.isNotBlank(existing)) {
setter.accept(mergeString(candidate, existing));
}
}

private <T> void mergeOptional(
final T candidate, final T existing, final java.util.function.Consumer<T> setter) {

if (candidate != null || existing != null) {
setter.accept(mergeNullable(candidate, existing));
if (!CollectionUtils.isEmpty(candidate)) {
return candidate;
}
return existing != null ? existing : List.of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ public class PostgresMenteeSectionRepository implements MenteeSectionRepository

public static final String UPDATE_MENTEE_SECTION =
"UPDATE mentor_mentee_section SET ideal_mentee = ?, additional = ? WHERE mentor_id = ?";
public static final String UPDATE_MENTOR_TYPE =
"UPDATE mentor_mentorship_types SET mentorship_type = ? WHERE mentor_id = ?";
private static final String UPDATE_AVAILABILITY =
"UPDATE mentor_availability SET month_num = ?, hours = ? WHERE mentor_id = ?";
public static final String UPDATE_AVAILABILITY =
"UPDATE mentor_availability SET " + "month_num = ?, " + "hours = ? " + "WHERE mentor_id = ?";
public static final String INSERT_MENTOR_TYPES =
"INSERT INTO mentor_mentorship_types (mentor_id, mentorship_type) VALUES (?, ?)";
public static final String DELETE_MENTOR_TYPES =
"DELETE FROM mentor_mentorship_types WHERE mentor_id = ?";
private static final String SQL_BASE =
"SELECT ideal_mentee, additional, created_at, updated_at "
+ "FROM mentor_mentee_section WHERE mentor_id = ?";
Expand All @@ -41,8 +43,6 @@ public class PostgresMenteeSectionRepository implements MenteeSectionRepository
"INSERT INTO mentor_mentee_section (mentor_id, ideal_mentee, additional) VALUES (?, ?, ?)";
private static final String INSERT_AVAILABILITY =
"INSERT INTO mentor_availability (mentor_id, month_num, hours) VALUES (?, ?, ?)";
private static final String INSERT_MENTOR_TYPES =
"INSERT INTO mentor_mentorship_types (mentor_id, mentorship_type) VALUES (?, ?)";
private final JdbcTemplate jdbc;

/** Inserts the mentee section details for the mentor. */
Expand All @@ -58,7 +58,8 @@ public void insertMenteeSection(final MenteeSection menteeSec, final Long member
*/
public void updateMenteeSection(final MenteeSection menteeSec, final Long mentorId) {
jdbc.update(UPDATE_MENTEE_SECTION, menteeSec.idealMentee(), menteeSec.additional(), mentorId);
jdbc.update(UPDATE_MENTOR_TYPE, menteeSec.mentorshipType(), mentorId);
jdbc.update(DELETE_MENTOR_TYPES, mentorId);
insertMentorshipTypes(menteeSec, mentorId);
updateAvailability(menteeSec, mentorId);
}

Expand Down Expand Up @@ -116,7 +117,7 @@ private void insertMentorshipTypes(final MenteeSection ms, final Long memberId)

private void updateAvailability(final MenteeSection ms, final Long memberId) {
for (final MentorMonthAvailability a : ms.availability()) {
jdbc.update(UPDATE_AVAILABILITY, memberId, a.month().getValue(), a.hours());
jdbc.update(UPDATE_AVAILABILITY, a.month().getValue(), a.hours(), memberId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertNotEquals;

import com.wcc.platform.domain.platform.mentorship.Mentor;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -43,11 +44,18 @@ void testToString() {
final var expected =
"Mentor(profileStatus=ACTIVE, skills=Skills[yearsExperience=2, areas=[Backend, Frontend], "
+ "languages=[Javascript], mentorshipFocus=[Grow from beginner to mid-level]], "
+ "spokenLanguages=[English], bio=Mentor bio, "
+ "spokenLanguages=[English, Spanish, German], bio=Mentor bio, "
+ "menteeSection=MenteeSection[mentorshipType=[Long-Term], "
+ "availability=[MentorMonthAvailability[month=APRIL, hours=2]], "
+ "idealMentee=ideal mentee description, "
+ "additional=additional], feedbackSection=null, resources=null)";
assertEquals(expected, mentor.toString());
}

@Test
void testSpokenLanguagesAreCapitalized() {
var mentor = createMentorTest(1L, "test name", "test@email.com");

assertEquals(List.of("English", "Spanish", "German"), mentor.getSpokenLanguages());
}
}
Loading
Loading