package com.ga.common.system; import com.ga.common.exception.BizException; import com.ga.common.exception.ErrorCode; import com.ga.common.util.SecurityUtil; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; /** * 시스템 설정값 조회/수정 서비스. *

* 신입 메모: 코드 배포 없이 운영 중 바꿀 수 있는 설정값(키-값)을 DB에서 읽어 온다. * 값은 DB에 전부 문자열로 저장되므로, 쓰는 쪽 편의를 위해 getInt/getDecimal/getBoolean 등으로 * 타입 변환해 꺼내며, 값이 없으면 호출자가 준 기본값을 돌려준다. * 자주 조회되는 값은 {@code @Cacheable}로 캐싱하고 수정 시 해당 키 캐시를 비운다. * isEditable='N'인 설정은 보호 항목이라 수정이 막혀 있다. */ @Service @RequiredArgsConstructor public class SystemConfigService { private final SystemConfigMapper mapper; /** 전체 설정 목록 (관리 화면용). */ public List listAll() { return mapper.selectAll(); } /** 특정 그룹의 설정 목록. */ public List listByGroup(String group) { return mapper.selectByGroup(group); } /** 키로 설정값(문자열)을 조회. 없으면 빈 Optional. 결과는 캐시된다. */ @Cacheable(value = "systemConfig", key = "#key") public Optional getValue(String key) { SystemConfigVO vo = mapper.selectByKey(key); return Optional.ofNullable(vo).map(SystemConfigVO::getConfigValue); } /** 문자열 설정값 (없으면 기본값). */ public String getString(String key, String defaultValue) { return getValue(key).orElse(defaultValue); } /** 정수 설정값 (없으면 기본값). */ public int getInt(String key, int defaultValue) { return getValue(key).map(Integer::parseInt).orElse(defaultValue); } /** 금액/비율용 BigDecimal 설정값 (없으면 기본값). */ public BigDecimal getDecimal(String key, BigDecimal defaultValue) { return getValue(key).map(BigDecimal::new).orElse(defaultValue); } /** 불리언 설정값 ("true"/"Y"를 참으로 인정, 없으면 기본값). */ public boolean getBoolean(String key, boolean defaultValue) { return getValue(key).map(s -> "true".equalsIgnoreCase(s) || "Y".equalsIgnoreCase(s)).orElse(defaultValue); } /** 설정값 수정. 미존재 시 NOT_FOUND, isEditable='N'이면 수정 거부. 후 해당 키 캐시 무효화. */ @Transactional @CacheEvict(value = "systemConfig", key = "#vo.configKey") public void update(SystemConfigVO vo) { SystemConfigVO existing = mapper.selectByKey(vo.getConfigKey()); if (existing == null) throw new BizException(ErrorCode.NOT_FOUND); if (!"Y".equals(existing.getIsEditable())) { throw new BizException(ErrorCode.NOT_PERMITTED, "수정할 수 없는 설정입니다"); } vo.setUpdatedAt(LocalDateTime.now()); vo.setUpdatedBy(SecurityUtil.getCurrentUserId()); mapper.update(vo); } }