Skip to content
Closed
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 @@ -6,7 +6,7 @@
import java.util.List;

public interface DocumentRepository {
void save(DocumentEntity entity);
DocumentEntity save(DocumentEntity entity);

DocumentEntity getByIdAndStaffId(Long id, Long staffId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,20 @@ public List<ContractEntity> findAllByStoreId(final Long storeId) {
return contractRepository.findAllByStoreId(storeId);
}

private byte[] generateContractPdf(final ContractData contractData, final String bossSignatureKey) {
public byte[] generateContractPdf(final ContractData contractData, final String bossSignatureKey) {
final String bossSignatureBase64 = fetchSignatureBase64(bossSignatureKey);
final String html = contractHtmlGenerator.generateHtmlWithBossSignature(contractData, bossSignatureBase64);
return pdfGenerator.generatePdfFromHtml(html);
}

private byte[] generateStaffSignedContractPdf(final ContractData data, final String bossSignatureKey, final String staffSignatureKey) {
public byte[] generateStaffSignedContractPdf(final ContractData data, final String bossSignatureKey, final String staffSignatureKey) {
final String bossSignatureBase64 = fetchSignatureBase64(bossSignatureKey);
final String staffSignatureBase64 = fetchSignatureBase64(staffSignatureKey);
final String html = contractHtmlGenerator.generateHtmlWithStaffSignature(data, bossSignatureBase64, staffSignatureBase64);
return pdfGenerator.generatePdfFromHtml(html);
}

private String fetchSignatureBase64(final String signatureKey) {
public String fetchSignatureBase64(final String signatureKey) {
return s3FileManager.fetchAsBase64(signatureKey, ContentType.PNG.getMimeType());
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public class DocumentRepositoryImpl implements DocumentRepository {
private final DocumentJpaRepository documentJpaRepository;

@Override
public void save(DocumentEntity entity) {
documentJpaRepository.save(entity);
public DocumentEntity save(DocumentEntity entity) {
return documentJpaRepository.save(entity);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.mangoboss.app.domain.service.attendance.context;

import com.mangoboss.app.common.exception.CustomErrorInfo;
import com.mangoboss.app.common.exception.CustomException;
import com.mangoboss.app.domain.service.attendance.strategy.AttendanceValidationStrategy;
import com.mangoboss.app.dto.attendance.base.AttendanceBaseRequest;
import com.mangoboss.storage.store.AttendanceMethod;
import com.mangoboss.storage.store.StoreEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.*;

class AttendanceStrategyContextTest {

private AttendanceStrategyContext context;
private AttendanceValidationStrategy<TestRequest> mockStrategy;

@BeforeEach
void setUp() {
mockStrategy = mock(AttendanceValidationStrategy.class);
context = new AttendanceStrategyContext(List.of(mockStrategy));
}

@Test
void 전략이_정상적으로_선택되면_검증이_수행된다() {
// given
StoreEntity store = mock(StoreEntity.class);
TestRequest request = new TestRequest();

when(mockStrategy.supports(store, request.attendanceMethod())).thenReturn(true);
when(mockStrategy.getRequestType()).thenReturn(TestRequest.class);

// when
context.validate(store, request);

// then
verify(mockStrategy).executionValidate(store, request);
}

@Test
void 지원하는_전략이_없으면_예외가_발생한다() {
// given
StoreEntity store = mock(StoreEntity.class);
TestRequest request = new TestRequest();

when(mockStrategy.supports(store, request.attendanceMethod())).thenReturn(false);
when(mockStrategy.getRequestType()).thenReturn(TestRequest.class);

// when & then
assertThatThrownBy(() -> context.validate(store, request))
.isInstanceOf(CustomException.class)
.satisfies(e -> assertThat(((CustomException) e).getErrorCode())
.isEqualTo(CustomErrorInfo.INVALID_ATTENDANCE_REQUEST_TYPE));

verify(mockStrategy, never()).executionValidate(any(), any());
}

@Test
void request_타입이_전략에서_요구하는_타입과_다르면_예외가_발생한다() {
// given
StoreEntity store = mock(StoreEntity.class);
WrongRequest request = new WrongRequest();

when(mockStrategy.supports(store, request.attendanceMethod())).thenReturn(true);
when(mockStrategy.getRequestType()).thenReturn(TestRequest.class); // 타입 불일치

// when & then
assertThatThrownBy(() -> context.validate(store, request))
.isInstanceOf(CustomException.class)
.satisfies(e -> assertThat(((CustomException) e).getErrorCode())
.isEqualTo(CustomErrorInfo.INVALID_ATTENDANCE_REQUEST_TYPE));

verify(mockStrategy, never()).executionValidate(any(), any());
}

// 테스트용 request 구현체들
private static class TestRequest implements AttendanceBaseRequest {
@Override
public AttendanceMethod attendanceMethod() {
return AttendanceMethod.GPS;
}

@Override
public Long scheduleId() {
return 1L;
}
}

private static class WrongRequest implements AttendanceBaseRequest {
@Override
public AttendanceMethod attendanceMethod() {
return AttendanceMethod.GPS;
}

@Override
public Long scheduleId() {
return 2L;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.mangoboss.app.domain.service.attendance.strategy;

import com.mangoboss.app.common.exception.CustomErrorInfo;
import com.mangoboss.app.common.exception.CustomException;
import com.mangoboss.app.dto.attendance.request.AttendanceBothRequest;
import com.mangoboss.storage.store.AttendanceMethod;
import com.mangoboss.storage.store.StoreEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.*;

class BothValidationStrategyTest {

private BothValidationStrategy bothValidationStrategy;
private StoreEntity store;

@BeforeEach
void setUp() {
bothValidationStrategy = new BothValidationStrategy();
store = StoreEntity.builder()
.qrCode("VALID_QR")
.gpsLatitude(37.123)
.gpsLongitude(127.123)
.gpsRangeMeters(100)
.attendanceMethod(AttendanceMethod.BOTH)
.build();
}

@Test
void 유효한_요청이면_검증을_통과한다() {
var request = new AttendanceBothRequest(AttendanceMethod.BOTH, 1L, "VALID_QR", 37.123, 127.123, LocalDateTime.now());
assertDoesNotThrow(() -> bothValidationStrategy.executionValidate(store, request));
}

@Test
void 잘못된_qr이면_검증에서_예외가_발생한다() {
var request = new AttendanceBothRequest(AttendanceMethod.BOTH, 1L, "WRONG_QR", 37.123, 127.123, LocalDateTime.now());
var ex = assertThrows(CustomException.class, () -> bothValidationStrategy.executionValidate(store, request));
assertEquals(CustomErrorInfo.INVALID_QR_CODE, ex.getErrorCode());
}

@Test
void gps_범위를_벗어나면_예외가_발생한다() {
var request = new AttendanceBothRequest(AttendanceMethod.BOTH, 1L, "VALID_QR", 36.0, 126.0, LocalDateTime.now());
var ex = assertThrows(CustomException.class, () -> bothValidationStrategy.executionValidate(store, request));
assertEquals(CustomErrorInfo.GPS_OUT_OF_RANGE, ex.getErrorCode());
}

@Test
void gps_시간차이가_10초를_초과하면_예외가_발생한다() {
var request = new AttendanceBothRequest(AttendanceMethod.BOTH, 1L, "VALID_QR", 37.123, 127.123, LocalDateTime.now().minusSeconds(20));
var ex = assertThrows(CustomException.class, () -> bothValidationStrategy.executionValidate(store, request));
assertEquals(CustomErrorInfo.INVALID_GPS_TIME, ex.getErrorCode());
}

@Test
void 지원하는_가게_설정과_출결방식이면_true를_반환한다() {
assertTrue(bothValidationStrategy.supports(store, AttendanceMethod.BOTH));
}

@Test
void 출결방식이나_가게설정이_다르면_false를_반환한다() {
assertFalse(bothValidationStrategy.supports(store, AttendanceMethod.QR));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.mangoboss.app.domain.service.attendance.strategy;

import com.mangoboss.app.common.exception.CustomErrorInfo;
import com.mangoboss.app.common.exception.CustomException;
import com.mangoboss.app.dto.attendance.base.AttendanceBaseRequest;
import com.mangoboss.app.dto.attendance.request.AttendanceGpsRequest;
import com.mangoboss.storage.store.AttendanceMethod;
import com.mangoboss.storage.store.StoreEntity;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
class GpsValidationStrategyTest {

private final GpsValidationStrategy gpsValidationStrategy = new GpsValidationStrategy();

private final StoreEntity store = StoreEntity.builder()
.attendanceMethod(AttendanceMethod.GPS)
.gpsLatitude(37.1234)
.gpsLongitude(127.1234)
.gpsRangeMeters(100)
.qrCode("QR")
.build();

@Test
void gps_범위_내_정상시간이면_예외_없음() {
AttendanceGpsRequest request = new AttendanceGpsRequest(
AttendanceMethod.GPS,
1L,
37.1234, 127.1234,
LocalDateTime.now()
);

assertDoesNotThrow(() -> gpsValidationStrategy.executionValidate(store, request));
}

@Test
void gps_범위_초과시_예외() {
AttendanceGpsRequest request = new AttendanceGpsRequest(
AttendanceMethod.GPS,
1L,
36.0, 126.0, // 거리 매우 멀 때
LocalDateTime.now()
);

CustomException ex = assertThrows(CustomException.class, () ->
gpsValidationStrategy.executionValidate(store, request));

assertEquals(CustomErrorInfo.GPS_OUT_OF_RANGE, ex.getCustomErrorInfo());
}

@Test
void gps_시간_지연되면_예외() {
AttendanceGpsRequest request = new AttendanceGpsRequest(
AttendanceMethod.GPS,
1L,
37.1234, 127.1234,
LocalDateTime.now().minusSeconds(20)
);

CustomException ex = assertThrows(CustomException.class, () ->
gpsValidationStrategy.executionValidate(store, request));

assertEquals(CustomErrorInfo.INVALID_GPS_TIME, ex.getCustomErrorInfo());
}

@Test
void 지원하지않는_request_type이면_예외발생() {
AttendanceBaseRequest wrongRequest = new AttendanceBaseRequest() {
@Override
public AttendanceMethod attendanceMethod() {
return AttendanceMethod.GPS;
}

@Override
public Long scheduleId() {
return 1L;
}
};

CustomException ex = assertThrows(CustomException.class,
() -> gpsValidationStrategy.executionValidate(store, wrongRequest));

assertEquals(CustomErrorInfo.INVALID_ATTENDANCE_REQUEST_TYPE, ex.getCustomErrorInfo());
}

@Test
void gps방식과_설정이_일치하면_supports는_true를_반환한다() {
assertTrue(gpsValidationStrategy.supports(store, AttendanceMethod.GPS));
}

@Test
void gps방식과_설정이_일치하지_않으면_supports는_false를_반환한다() {
assertFalse(gpsValidationStrategy.supports(store, AttendanceMethod.QR));
}
}
Loading