Skip to content
Merged
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
@@ -1,5 +1,6 @@
package leets.weeth.domain.attendance.application.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import leets.weeth.domain.attendance.domain.entity.enums.Status;
Expand All @@ -13,6 +14,8 @@ public record Main(
Integer attendanceRate,
String title,
Status status,
@Schema(description = "어드민인 경우 출석 코드 노출")
Integer code,
LocalDateTime start,
LocalDateTime end,
String location
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@ public interface AttendanceMapper {
@Mapping(target = "attendanceRate", source = "user.attendanceRate"),
@Mapping(target = "title", source = "attendance.meeting.title"),
@Mapping(target = "status", source = "attendance.status"),
@Mapping(target = "code", ignore = true),
@Mapping(target = "start", source = "attendance.meeting.start"),
@Mapping(target = "end", source = "attendance.meeting.end"),
@Mapping(target = "location", source = "attendance.meeting.location"),
})
AttendanceDTO.Main toMainDto(User user, Attendance attendance);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ignore 옵션으로 , ROLE별로 매핑되는 필드를 조절할 수 있군요! 좋은 설계같습니다

@Mappings({
@Mapping(target = "attendanceRate", source = "user.attendanceRate"),
@Mapping(target = "title", source = "attendance.meeting.title"),
@Mapping(target = "status", source = "attendance.status"),
@Mapping(target = "code", source = "attendance.meeting.code"),
@Mapping(target = "start", source = "attendance.meeting.start"),
@Mapping(target = "end", source = "attendance.meeting.end"),
@Mapping(target = "location", source = "attendance.meeting.location"),
})
AttendanceDTO.Main toAdminResponse(User user, Attendance attendance);

@Mappings({
@Mapping(target = "attendances", source = "attendances"),
@Mapping(target = "total", expression = "java( user.getAttendanceCount() + user.getAbsenceCount() )")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import leets.weeth.domain.schedule.domain.service.MeetingGetService;
import leets.weeth.domain.user.domain.entity.Cardinal;
import leets.weeth.domain.user.domain.entity.User;
import leets.weeth.domain.user.domain.entity.enums.Role;
import leets.weeth.domain.user.domain.service.UserCardinalGetService;
import leets.weeth.domain.user.domain.service.UserGetService;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -66,6 +67,10 @@ public AttendanceDTO.Main find(Long userId) {
.findAny()
.orElse(null);

if (Role.ADMIN == user.getRole()) {
return mapper.toAdminResponse(user, todayMeeting);
}

return mapper.toMainDto(user, todayMeeting);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package leets.weeth.domain.attendance.application.mapper;

import static leets.weeth.domain.attendance.test.fixture.AttendanceTestFixture.*;
import static org.assertj.core.api.Assertions.*;

import java.time.LocalDate;
import java.util.List;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import leets.weeth.domain.attendance.application.dto.AttendanceDTO;
import leets.weeth.domain.attendance.domain.entity.Attendance;
import leets.weeth.domain.schedule.domain.entity.Meeting;
import leets.weeth.domain.user.domain.entity.User;
import leets.weeth.domain.user.domain.entity.enums.Position;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mapstruct.factory.Mappers;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDate;
import java.util.List;

import static leets.weeth.domain.attendance.test.fixture.AttendanceTestFixture.*;
import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(MockitoExtension.class)
class AttendanceMapperTest {

private final AttendanceMapper attendanceMapper = new AttendanceMapperImpl();
@InjectMocks
private final AttendanceMapper attendanceMapper = Mappers.getMapper(AttendanceMapper.class);

@Test
@DisplayName("toMainDto: 사용자 + 당일 출석 객체를 Main DTO로 매핑한다")
Expand Down Expand Up @@ -121,4 +126,45 @@ void nullSafety_whenTodayAttendanceNull() {
assertThat(main.end()).isNull();
assertThat(main.location()).isNull();
}
}

@Test
@DisplayName("toMainDto: 일반 유저는 출석 코드가 null로 매핑된다")
void toMainDto_normalUser_codeIsNull() {
// given
LocalDate today = LocalDate.now();
Meeting meeting = createOneDayMeeting(today, 1, 1234, "Today");
User user = createActiveUserWithAttendances("일반유저", List.of(meeting));
Attendance attendance = user.getAttendances().get(0);

// when
AttendanceDTO.Main main = attendanceMapper.toMainDto(user, attendance);

// then
assertThat(main).isNotNull();
assertThat(main.code()).isNull();
assertThat(main.title()).isEqualTo("Today");
assertThat(main.status()).isEqualTo(attendance.getStatus());
}

@Test
@DisplayName("toAdminResponse: ADMIN 유저는 출석 코드가 포함된다")
void toAdminResponse_adminUser_includesCode() {
// given
LocalDate today = LocalDate.now();
Integer expectedCode = 1234;
Meeting meeting = createOneDayMeeting(today, 1, expectedCode, "Today");
User adminUser = createAdminUserWithAttendances("관리자", List.of(meeting));
Attendance attendance = adminUser.getAttendances().get(0);

// when
AttendanceDTO.Main main = attendanceMapper.toAdminResponse(adminUser, attendance);

// then
assertThat(main).isNotNull();
assertThat(main.code()).isEqualTo(expectedCode);
assertThat(main.title()).isEqualTo("Today");
assertThat(main.start()).isEqualTo(meeting.getStart());
assertThat(main.end()).isEqualTo(meeting.getEnd());
assertThat(main.location()).isEqualTo(meeting.getLocation());
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트도 케이스별로 보기좋게 잘 작성해주신 것 같아요 !! 굳굳

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import leets.weeth.domain.user.domain.entity.User;
import leets.weeth.domain.user.domain.entity.enums.Department;
import leets.weeth.domain.user.domain.entity.enums.Position;
import leets.weeth.domain.user.domain.entity.enums.Role;
import leets.weeth.domain.user.domain.entity.enums.Status;

public class AttendanceTestFixture {
Expand All @@ -21,6 +22,29 @@ public static User createActiveUser(String name) {
return User.builder().name(name).status(Status.ACTIVE).build();
}

public static User createAdminUser(String name) {
return User.builder().name(name).status(Status.ACTIVE).role(Role.ADMIN).build();
}

public static User createAdminUserWithAttendances(String name, List<Meeting> meetings) {
User user = createAdminUser(name);

if (user.getAttendances() == null) {
try {
java.lang.reflect.Field f = user.getClass().getDeclaredField("attendances");
f.setAccessible(true);
f.set(user, new java.util.ArrayList<>());
} catch (Exception ignore) {}
}
if (meetings != null) {
for (Meeting meeting : meetings) {
Attendance attendance = createAttendance(meeting, user);
user.add(attendance);
}
}
return user;
}

//todo : 추후 User Fixture 활용 예정
public static User createActiveUserWithAttendances(String name, List<Meeting> meetings) {
User user = createActiveUser(name);
Expand Down