diff --git a/src/main/java/com/runtimematrix/service/RoleService.java b/src/main/java/com/runtimematrix/service/RoleService.java new file mode 100644 index 0000000..28f61af --- /dev/null +++ b/src/main/java/com/runtimematrix/service/RoleService.java @@ -0,0 +1,85 @@ +package com.runtimematrix.service; + +import com.runtimematrix.domain.exception.BusinessException; +import com.runtimematrix.domain.model.Role; +import com.runtimematrix.repository.RoleRepository; +import com.runtimematrix.service.command.CreateRoleCommand; +import com.runtimematrix.service.command.UpdateRoleCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 역할 관리 서비스. + * ADR-001 트랜잭션 경계: Service Layer public 메서드에서 시작 + */ +@Service +public class RoleService { + + private static final Logger log = LoggerFactory.getLogger(RoleService.class); + private final RoleRepository roleRepository; + + public RoleService(RoleRepository roleRepository) { + this.roleRepository = roleRepository; + } + + /** 쓰기 트랜잭션 */ + @Transactional + public Role createRole(CreateRoleCommand command) { + log.debug("Creating role: {}", command.name()); + if (roleRepository.existsByName(command.name())) { + throw new BusinessException.RoleAlreadyExistsException(command.name()); + } + Role role = Role.create(command.name(), command.description()); + log.info("Role created: id={}, name={}", role.getId(), role.getName()); + return roleRepository.save(role); + } + + /** 읽기 전용 트랜잭션 */ + @Transactional(readOnly = true) + public Role getRole(String roleId) { + log.debug("Fetching role: {}", roleId); + return roleRepository.findById(roleId) + .orElseThrow(() -> new BusinessException.RoleNotFoundException(roleId)); + } + + /** 읽기 전용 트랜잭션 */ + @Transactional(readOnly = true) + public List getAllRoles() { + return roleRepository.findAll(); + } + + /** 쓰기 트랜잭션 */ + @Transactional + public Role updateRole(String roleId, UpdateRoleCommand command) { + log.debug("Updating role: {}", roleId); + Role role = roleRepository.findById(roleId) + .orElseThrow(() -> new BusinessException.RoleNotFoundException(roleId)); + + if (command.name() != null && !command.name().equals(role.getName())) { + if (roleRepository.existsByName(command.name())) { + throw new BusinessException.RoleAlreadyExistsException(command.name()); + } + role.updateName(command.name()); + } + if (command.description() != null) { + role.updateDescription(command.description()); + } + log.info("Role updated: id={}", roleId); + return role; + } + + /** 쓰기 트랜잭션 */ + @Transactional + public void deleteRole(String roleId) { + log.debug("Deleting role: {}", roleId); + if (!roleRepository.existsById(roleId)) { + throw new BusinessException.RoleNotFoundException(roleId); + } + roleRepository.deleteById(roleId); + log.info("Role deleted: id={}", roleId); + } +}