- 약관 동의서 노출 및 동작 방식 관리 기능 추가
eapim-portal CI (from elink-portal-common) / build (push) Waiting to run
eapim-portal CI (from elink-portal-common) / build (push) Waiting to run
- '전체 동의' 및 약관 항목별 활성화 설정 반영 - 사용자 타입 및 약관 페이지 구성에 따른 렌더링 로직 개선
This commit is contained in:
+146
@@ -0,0 +1,146 @@
|
|||||||
|
package com.eactive.apim.portal.agreements.service;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.agreements.entity.AgreementType;
|
||||||
|
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 약관 종류 운영 설정 조회. PTL_PROPERTY(그룹 {@code Portal})로 관리하며 admin·portal 이 같은 값을 본다.
|
||||||
|
*
|
||||||
|
* <table>
|
||||||
|
* <caption>PTL_PROPERTY (group = Portal)</caption>
|
||||||
|
* <tr><th>{@code portal.terms.enabled-types}</th>
|
||||||
|
* <td>시스템에서 사용할 약관 종류. 쉼표 구분, 순서 무의미</td></tr>
|
||||||
|
* <tr><th>{@code portal.terms.display-types}</th>
|
||||||
|
* <td>약관 페이지에 노출할 약관 종류. 쉼표 구분, <b>기재 순서가 노출 순서</b></td></tr>
|
||||||
|
* </table>
|
||||||
|
*
|
||||||
|
* <p>값은 관리 콘솔의 '약관 목록 > 약관 종류 관리' 화면에서 설정한다. 프로퍼티가 없으면
|
||||||
|
* {@link #DEFAULT_TYPES} 를 사용하며 <b>조회만으로 행을 만들지는 않는다</b>
|
||||||
|
* (PTL_PROPERTY 는 (그룹, 이름) 유니크 제약이 없어 동시 요청이 중복 행을 만들 수 있다).
|
||||||
|
* 알 수 없는 코드는 무시하므로 enum 항목이 빠져도 화면이 깨지지 않는다.
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AgreementTypeConfigService {
|
||||||
|
|
||||||
|
public static final String PROPERTY_GROUP = "Portal";
|
||||||
|
public static final String ENABLED_TYPES_KEY = "portal.terms.enabled-types";
|
||||||
|
public static final String DISPLAY_TYPES_KEY = "portal.terms.display-types";
|
||||||
|
public static final String AGREE_ALL_ENABLED_KEY = "portal.terms.agree-all-enabled";
|
||||||
|
|
||||||
|
/** '전체 동의' 기본값 — 미설정 시 항목별로 끝까지 읽고 개별 동의하는 방식 */
|
||||||
|
public static final boolean DEFAULT_AGREE_ALL_ENABLED = false;
|
||||||
|
|
||||||
|
/** 프로퍼티 미설정 시 기본값 — 현재 운영중인 약관 종류 */
|
||||||
|
public static final List<AgreementType> DEFAULT_TYPES = Collections.unmodifiableList(Arrays.asList(
|
||||||
|
AgreementType.TERMS_OF_USE,
|
||||||
|
AgreementType.PRIVACY_COLLECT,
|
||||||
|
AgreementType.NOTIFICATION_CONSENT));
|
||||||
|
|
||||||
|
private final PortalPropertyService portalPropertyService;
|
||||||
|
|
||||||
|
/** 시스템에서 사용하는 약관 종류 */
|
||||||
|
public Set<AgreementType> getEnabledTypes() {
|
||||||
|
Set<AgreementType> enabled = EnumSet.noneOf(AgreementType.class);
|
||||||
|
enabled.addAll(readTypes(readGroupProperties(), ENABLED_TYPES_KEY));
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 약관 페이지에 노출할 약관 종류(노출 순서대로). 사용하지 않는 종류는 제외된다. */
|
||||||
|
public List<AgreementType> getDisplayTypes() {
|
||||||
|
Map<String, String> properties = readGroupProperties();
|
||||||
|
List<AgreementType> enabled = readTypes(properties, ENABLED_TYPES_KEY);
|
||||||
|
|
||||||
|
List<AgreementType> display = new ArrayList<>();
|
||||||
|
for (AgreementType type : readTypes(properties, DISPLAY_TYPES_KEY)) {
|
||||||
|
if (enabled.contains(type)) {
|
||||||
|
display.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 시스템에서 사용하는 약관 종류인지 여부 */
|
||||||
|
public boolean isEnabled(AgreementType type) {
|
||||||
|
return getEnabledTypes().contains(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 약관 페이지에 노출(배치)된 약관 종류인지 여부. 사용하지 않는 종류는 항상 {@code false}. */
|
||||||
|
public boolean isDisplayed(AgreementType type) {
|
||||||
|
return getDisplayTypes().contains(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회원가입 약관 동의 화면에서 '전체 동의'를 허용할지 여부.
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code false} — 항목을 펼쳐 끝까지 읽어야 개별 동의할 수 있고, '전체 동의' 체크박스는 노출하지 않는다</li>
|
||||||
|
* <li>{@code true} — '전체 동의' 체크박스를 노출하고, 항목별 스크롤 없이 바로 동의할 수 있다</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public boolean isAgreeAllEnabled() {
|
||||||
|
return parseBoolean(readGroupProperties().get(AGREE_ALL_ENABLED_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@code true/false} 외에 레거시 {@code Y/N}, {@code 1/0} 표기도 허용한다. */
|
||||||
|
private boolean parseBoolean(String value) {
|
||||||
|
if (value == null || value.trim().isEmpty()) {
|
||||||
|
return DEFAULT_AGREE_ALL_ENABLED;
|
||||||
|
}
|
||||||
|
String trimmed = value.trim();
|
||||||
|
if ("true".equalsIgnoreCase(trimmed) || "Y".equalsIgnoreCase(trimmed) || "1".equals(trimmed)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ("false".equalsIgnoreCase(trimmed) || "N".equalsIgnoreCase(trimmed) || "0".equals(trimmed)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log.warn("PTL_PROPERTY {}/{} 값을 해석할 수 없어 기본값({})을 사용합니다. : {}",
|
||||||
|
PROPERTY_GROUP, AGREE_ALL_ENABLED_KEY, DEFAULT_AGREE_ALL_ENABLED, trimmed);
|
||||||
|
return DEFAULT_AGREE_ALL_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code Portal} 그룹 프로퍼티 전체를 읽는다.
|
||||||
|
*
|
||||||
|
* <p>단건 조회({@code findById})는 중복 행에서 예외가 나므로 그룹 단위로 읽는다.
|
||||||
|
*/
|
||||||
|
private Map<String, String> readGroupProperties() {
|
||||||
|
return portalPropertyService.getPortalPropertiesAsMap(PROPERTY_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 프로퍼티 값을 약관 종류 목록으로 변환. 미설정이면 기본값, 알 수 없는 코드는 무시한다. */
|
||||||
|
private List<AgreementType> readTypes(Map<String, String> properties, String propertyName) {
|
||||||
|
String value = properties.get(propertyName);
|
||||||
|
if (value == null) {
|
||||||
|
return new ArrayList<>(DEFAULT_TYPES);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AgreementType> types = new ArrayList<>();
|
||||||
|
for (String code : value.split(",")) {
|
||||||
|
String trimmed = code.trim();
|
||||||
|
if (trimmed.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
types.add(AgreementType.valueOf(trimmed));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.warn("PTL_PROPERTY {}/{} 에 알 수 없는 약관 종류 코드가 있어 무시합니다. : {}",
|
||||||
|
PROPERTY_GROUP, propertyName, trimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>(new LinkedHashSet<>(types));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user