Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -55,6 +55,17 @@ private void processSitesData(CSVSitesData sitesItem) {
// ==================================================
private void processChannelUserData(CSVChannelData channelDataItem) {
String channelName = channelDataItem.getChannelName();
String email = channelDataItem.getChannelUserEmail();

if (email == null || email.isBlank()) {
loggingService.logWarning(
"Skipping channel user entry with missing email for channel: %s, user: %s",
channelName,
channelDataItem.getChannelUser()
);
return;
}

List<String[]> existing = cacheService.getChannelReference(channelName)
.orElse(new ArrayList<>());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ public ItemReader<PostMigratedItemGroup> createReader(boolean dryRun) {

for (String[] user : matchedUsers) {
String email = user[1];
if (email == null || email.isBlank()) {
loggingService.logWarning(
"Skipping channel user with missing email for record %s, groupKey=%s, user=%s",
orig.getArchiveId(),
orig.getRecordingGroupKey(),
user[0]
);
continue;
}
String fullName = user[0];
String[] nameParts = fullName.split("\\.");
String firstName = nameParts.length > 0 ? nameParts[0] : "Unknown";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,15 @@ public PostMigratedItemGroup createShareBookingAndInviteIfNotExists(BookingDTO b
String email,
String firstName,
String lastName) {
if (email == null || email.isBlank()) {
loggingService.logWarning(
"Cannot create share booking: email is null or blank for user %s %s",
firstName,
lastName
);
return null;
}

loggingService.logDebug("Preparing data for share booking and user: %s %s %s", email, firstName, lastName);
String lowerEmail = email.toLowerCase();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,130 @@ private MigrationRecord migrationRecord(String archiveId, String groupKey) {
return record;
}

@Test
void createReaderSkipsUserWithNullEmail() throws Exception {
MigrationRecord record = migrationRecord("archive-null-email-user", "case|segment");
record.setBookingId(UUID.randomUUID());

when(migrationRecordService.findShareableOrigs()).thenReturn(List.of(record));
Map<String, List<String[]>> channelMap = new HashMap<>();

channelMap.put("case|segment", Collections.singletonList(new String[] {"user.name", null}));
when(cacheService.getAllChannelReferences()).thenReturn(channelMap);

BookingDTO booking = mock(BookingDTO.class);
when(booking.getShares()).thenReturn(List.of());
when(bookingService.findById(record.getBookingId())).thenReturn(booking);

var readerResult = reader.createReader(false);
assertThat(assertDoesNotThrow(readerResult::read)).isNull();

verify(loggingService).logWarning(
eq("Skipping channel user with missing email for record %s, groupKey=%s, user=%s"),
eq("archive-null-email-user"),
eq("case|segment"),
eq("user.name")
);
verify(entityCreationService, never()).createShareBookingAndInviteIfNotExists(
any(), anyString(), anyString(), anyString()
);
}

@Test
void createReaderSkipsUserWithBlankEmail() throws Exception {
MigrationRecord record = migrationRecord("archive-blank-email-user", "case|segment");
record.setBookingId(UUID.randomUUID());

when(migrationRecordService.findShareableOrigs()).thenReturn(List.of(record));
Map<String, List<String[]>> channelMap = new HashMap<>();

channelMap.put("case|segment", Collections.singletonList(new String[] {"user.name", " "}));
when(cacheService.getAllChannelReferences()).thenReturn(channelMap);

BookingDTO booking = mock(BookingDTO.class);
when(booking.getShares()).thenReturn(List.of());
when(bookingService.findById(record.getBookingId())).thenReturn(booking);

var readerResult = reader.createReader(false);
assertThat(assertDoesNotThrow(readerResult::read)).isNull();

verify(loggingService).logWarning(
eq("Skipping channel user with missing email for record %s, groupKey=%s, user=%s"),
eq("archive-blank-email-user"),
eq("case|segment"),
eq("user.name")
);
verify(entityCreationService, never()).createShareBookingAndInviteIfNotExists(
any(), anyString(), anyString(), anyString()
);
}

@Test
void createReaderSkipsUserWithEmptyEmail() throws Exception {
MigrationRecord record = migrationRecord("archive-empty-email-user", "case|segment");
record.setBookingId(UUID.randomUUID());

when(migrationRecordService.findShareableOrigs()).thenReturn(List.of(record));
Map<String, List<String[]>> channelMap = new HashMap<>();

channelMap.put("case|segment", Collections.singletonList(new String[] {"user.name", ""}));
when(cacheService.getAllChannelReferences()).thenReturn(channelMap);

BookingDTO booking = mock(BookingDTO.class);
when(booking.getShares()).thenReturn(List.of());
when(bookingService.findById(record.getBookingId())).thenReturn(booking);

var readerResult = reader.createReader(false);
assertThat(assertDoesNotThrow(readerResult::read)).isNull();

verify(loggingService).logWarning(
eq("Skipping channel user with missing email for record %s, groupKey=%s, user=%s"),
eq("archive-empty-email-user"),
eq("case|segment"),
eq("user.name")
);
verify(entityCreationService, never()).createShareBookingAndInviteIfNotExists(
any(), anyString(), anyString(), anyString()
);
}

@Test
void createReaderProcessesValidUserWhenAnotherHasNullEmail() throws Exception {
MigrationRecord record = migrationRecord("archive-mixed-emails", "case|segment");
record.setBookingId(UUID.randomUUID());

when(migrationRecordService.findShareableOrigs()).thenReturn(List.of(record));
Map<String, List<String[]>> channelMap = new HashMap<>();

channelMap.put("case|segment", Arrays.asList(
new String[] {"invalid.user", null},
new String[] {"valid.user", "valid@example.com"}
));
when(cacheService.getAllChannelReferences()).thenReturn(channelMap);

BookingDTO booking = mock(BookingDTO.class);
when(booking.getShares()).thenReturn(List.of());
when(bookingService.findById(record.getBookingId())).thenReturn(booking);

PostMigratedItemGroup group = new PostMigratedItemGroup();
when(entityCreationService.createShareBookingAndInviteIfNotExists(
booking, "valid@example.com", "valid", "user"
)).thenReturn(group);

var readerResult = reader.createReader(false);
assertThat(assertDoesNotThrow(readerResult::read)).isEqualTo(group);

verify(loggingService).logWarning(
eq("Skipping channel user with missing email for record %s, groupKey=%s, user=%s"),
eq("archive-mixed-emails"),
eq("case|segment"),
eq("invalid.user")
);
verify(entityCreationService).createShareBookingAndInviteIfNotExists(
booking, "valid@example.com", "valid", "user"
);
}

private BookingDTO buildBookingWithShares(String alreadySharedEmail) {
ShareBookingDTO share = new ShareBookingDTO();
share.setId(UUID.randomUUID());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,72 @@ void createShareBookingAndInviteIfNotExistsReturnsNullWhenVodafoneMissing() {
verify(loggingService).logWarning("Vodafone user ID not found in cache for email: %s", VODAFONE_EMAIL);
}

@Test
@DisplayName("createShareBookingAndInviteIfNotExists should return null when email is null")
void createShareBookingAndInviteIfNotExistsReturnsNullWhenEmailIsNull() {
BookingDTO booking = createTestBooking();

PostMigratedItemGroup result = entityCreationService.createShareBookingAndInviteIfNotExists(
booking,
null,
"Test",
"User"
);

assertThat(result).isNull();
verify(loggingService).logWarning(
eq("Cannot create share booking: email is null or blank for user %s %s"),
eq("Test"),
eq("User")
);
verify(cacheService, never()).getHashValue(anyString(), anyString(), any());
verify(cacheService, never()).getShareBooking(anyString());
}

@Test
@DisplayName("createShareBookingAndInviteIfNotExists should return null when email is blank")
void createShareBookingAndInviteIfNotExistsReturnsNullWhenEmailIsBlank() {
BookingDTO booking = createTestBooking();

PostMigratedItemGroup result = entityCreationService.createShareBookingAndInviteIfNotExists(
booking,
" ",
"Test",
"User"
);

assertThat(result).isNull();
verify(loggingService).logWarning(
eq("Cannot create share booking: email is null or blank for user %s %s"),
eq("Test"),
eq("User")
);
verify(cacheService, never()).getHashValue(anyString(), anyString(), any());
verify(cacheService, never()).getShareBooking(anyString());
}

@Test
@DisplayName("createShareBookingAndInviteIfNotExists should return null when email is empty")
void createShareBookingAndInviteIfNotExistsReturnsNullWhenEmailIsEmpty() {
BookingDTO booking = createTestBooking();

PostMigratedItemGroup result = entityCreationService.createShareBookingAndInviteIfNotExists(
booking,
"",
"Test",
"User"
);

assertThat(result).isNull();
verify(loggingService).logWarning(
eq("Cannot create share booking: email is null or blank for user %s %s"),
eq("Test"),
eq("User")
);
verify(cacheService, never()).getHashValue(anyString(), anyString(), any());
verify(cacheService, never()).getShareBooking(anyString());
}

@Test
@DisplayName("isOrigRecordingPersisted should identify persisted originals")
void isOrigRecordingPersistedReturnsTrueWhenOrigHasRecordingId() throws Exception {
Expand Down
Loading