Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 운영진 관리 기능 구현 완료 #648

Merged
merged 16 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
@@ -0,0 +1,37 @@
package page.clab.api.domain.memberManagement.executive.adapter.in.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import page.clab.api.domain.memberManagement.executive.application.dto.request.ExecutiveRequestDto;
import page.clab.api.domain.memberManagement.executive.application.port.in.RegisterExecutiveUseCase;
import page.clab.api.global.common.dto.ApiResponse;

@RestController
@RequestMapping("/api/v1/executive")
@RequiredArgsConstructor
@Tag(name = "Member Management - Executive", description = "운영진")
public class ExecutiveRegisterController {

private final RegisterExecutiveUseCase registerExecutiveUseCase;

@Operation(summary = "[A] 운영진 등록", description = "ROLE_ADMIN 이상의 권한이 필요함<br>" +
"position은 다음과 같이 등록 가능<br>" +
"- PRESIDENT : 회장<br>" +
"- VICE_PRESIDENT : 부회장<br>" +
"- GENERAL : 일반 운영진<br>")
limehee marked this conversation as resolved.
Show resolved Hide resolved
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("")
public ApiResponse<String> registerExecutive(
@Valid @RequestBody ExecutiveRequestDto requestDto
) {
String id = registerExecutiveUseCase.registerExecutive(requestDto);
return ApiResponse.success(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package page.clab.api.domain.memberManagement.executive.adapter.in.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import page.clab.api.domain.memberManagement.executive.application.port.in.RemoveExecutiveUseCase;
import page.clab.api.global.common.dto.ApiResponse;

@RestController
@RequestMapping("/api/v1/executive")
@RequiredArgsConstructor
@Tag(name = "Member Management - Executive", description = "운영진")
public class ExecutiveRemoveController {

private final RemoveExecutiveUseCase removeExecutiveUseCase;

@Operation(summary = "[A] 운영진 정보 삭제", description = "ROLE_ADMIN 이상의 권한이 필요함")
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/{id}")
limehee marked this conversation as resolved.
Show resolved Hide resolved
public ApiResponse<String> removeMember(
@PathVariable(name = "id") String id
) {
String executiveId = removeExecutiveUseCase.removeExecutive(id);
return ApiResponse.success(executiveId);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package page.clab.api.domain.memberManagement.executive.adapter.in.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import page.clab.api.domain.memberManagement.executive.application.dto.response.ExecutiveResponseDto;
import page.clab.api.domain.memberManagement.executive.application.port.in.RetrieveExecutiveUseCase;
import page.clab.api.global.common.dto.ApiResponse;

@RestController
@RequestMapping("/api/v1/executive")
@RequiredArgsConstructor
@Tag(name = "Member Management - Executive", description = "운영진")
public class ExecutiveRetrievalController {

private final RetrieveExecutiveUseCase retrieveExecutiveUseCase;

@Operation(summary = "[G] 운영진 정보 조회", description = "ROLE_GUEST 이상의 권한이 필요함")
@PreAuthorize("hasRole('GUEST')")
@GetMapping("")
public ApiResponse<List<ExecutiveResponseDto>> retrieveExecutives() {
List<ExecutiveResponseDto> executives = retrieveExecutiveUseCase.retrieveExecutives();
return ApiResponse.success(executives);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package page.clab.api.domain.memberManagement.executive.adapter.in.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import page.clab.api.domain.memberManagement.executive.application.dto.request.ExecutiveUpdateRequestDto;
import page.clab.api.domain.memberManagement.executive.application.port.in.UpdateExecutiveUseCase;
import page.clab.api.global.common.dto.ApiResponse;

@RestController
@RequestMapping("/api/v1/executive")
@RequiredArgsConstructor
@Tag(name = "Member Management - Executive", description = "운영진")
public class ExecutiveUpdateController {

private final UpdateExecutiveUseCase updateExecutiveUseCase;

@Operation(summary = "[A] 운영진 정보 수정", description = "ROLE_ADMIN 이상의 권한이 필요함")
@PreAuthorize("hasRole('ADMIN')")
@PatchMapping("/{id}")
public ApiResponse<String> updateExecutive(
@PathVariable(name = "id") String id,
@RequestBody ExecutiveUpdateRequestDto requestDto
) {
String executiveId = updateExecutiveUseCase.updateExecutive(id, requestDto);
return ApiResponse.success(executiveId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package page.clab.api.domain.memberManagement.executive.adapter.out.persistence;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;
import page.clab.api.domain.memberManagement.executive.domain.ExecutivePosition;
import page.clab.api.global.common.domain.BaseEntity;

@Entity
@Table(name = "executive")
@Getter
@Setter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@SQLDelete(sql = "UPDATE executive SET is_deleted = true WHERE id = ?")
@SQLRestriction("is_deleted = false")
public class ExecutiveJpaEntity extends BaseEntity {

@Id
@Column(nullable = false, updatable = false, unique = true)
@Size(min = 9, max = 9, message = "{size.executive.id}")
private String id;

@Column(nullable = false)
@Size(min = 1, max = 10, message = "{size.executive.name}")
private String name;

@Column(nullable = false)
@Email(message = "{email.executive.email}")
@Size(min = 1, message = "{size.executive.email}")
private String email;

@Column(nullable = false)
private String field;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private ExecutivePosition position;

private String imageUrl;

@Column(name = "is_deleted", nullable = false)
private Boolean isDeleted;
mingmingmon marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package page.clab.api.domain.memberManagement.executive.adapter.out.persistence;

import org.mapstruct.Mapper;
import page.clab.api.domain.memberManagement.executive.domain.Executive;

@Mapper(componentModel = "spring")
public interface ExecutiveMapper {

ExecutiveJpaEntity toEntity(Executive executive);

Executive toDomain(ExecutiveJpaEntity jpaEntity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package page.clab.api.domain.memberManagement.executive.adapter.out.persistence;

import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import page.clab.api.domain.memberManagement.executive.application.port.out.RegisterExecutivePort;
import page.clab.api.domain.memberManagement.executive.application.port.out.RetrieveExecutivePort;
import page.clab.api.domain.memberManagement.executive.application.port.out.UpdateExecutivePort;
import page.clab.api.domain.memberManagement.executive.domain.Executive;
import page.clab.api.global.exception.NotFoundException;

@Component
@RequiredArgsConstructor
public class ExecutivePersistenceAdapter implements
RegisterExecutivePort,
RetrieveExecutivePort,
UpdateExecutivePort {

private final ExecutiveMapper executiveMapper;
private final ExecutiveRepository executiveRepository;

@Override
public Executive save(Executive executive) {
ExecutiveJpaEntity jpaEntity = executiveMapper.toEntity(executive);
ExecutiveJpaEntity savedEntity = executiveRepository.save(jpaEntity);
return executiveMapper.toDomain(savedEntity);
}

@Override
public Executive update(Executive executive) {
ExecutiveJpaEntity jpaEntity = executiveMapper.toEntity(executive);
ExecutiveJpaEntity savedEntity = executiveRepository.save(jpaEntity);
return executiveMapper.toDomain(savedEntity);
}

@Override
public List<Executive> findAll() {
List<ExecutiveJpaEntity> jpaEntities = executiveRepository.findAll();
return jpaEntities.stream()
.map(executiveMapper::toDomain)
.collect(Collectors.toList());
}

@Override
public Executive getById(String id) {
ExecutiveJpaEntity jpaEntity = executiveRepository.findById(id)
.orElseThrow(() -> new NotFoundException("학번이 " + id + "인 운영진이 존재하지 않습니다."));
limehee marked this conversation as resolved.
Show resolved Hide resolved
return executiveMapper.toDomain(jpaEntity);
}

@Override
public Boolean existsById(String id) {
return executiveRepository.existsById(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package page.clab.api.domain.memberManagement.executive.adapter.out.persistence;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ExecutiveRepository extends JpaRepository<ExecutiveJpaEntity, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package page.clab.api.domain.memberManagement.executive.application.dto.mapper;

import org.springframework.stereotype.Component;
import page.clab.api.domain.memberManagement.executive.application.dto.request.ExecutiveRequestDto;
import page.clab.api.domain.memberManagement.executive.application.dto.response.ExecutiveResponseDto;
import page.clab.api.domain.memberManagement.executive.domain.Executive;

@Component
public class ExecutiveDtoMapper {

public Executive fromDto(ExecutiveRequestDto requestDto) {
return Executive.builder()
.id(requestDto.getId())
.name(requestDto.getName())
.email(requestDto.getEmail())
.field(requestDto.getField())
.position(requestDto.getPosition())
.imageUrl(requestDto.getImageUrl())
.isDeleted(false)
.build();
}

public ExecutiveResponseDto toDto(Executive executive) {
return ExecutiveResponseDto.builder()
.id(executive.getId())
.name(executive.getName())
.email(executive.getEmail())
.field(executive.getField())
.position(executive.getPosition())
.imageUrl(executive.getImageUrl())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package page.clab.api.domain.memberManagement.executive.application.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import page.clab.api.domain.memberManagement.executive.domain.ExecutivePosition;

@Getter
@Setter
public class ExecutiveRequestDto {

@NotNull(message = "{notNull.executive.id}")
@Schema(description = "학번", example = "202310000")
private String id;

@NotNull(message = "{notNull.executive.name}")
@Schema(description = "이름", example = "홍길동")
private String name;

@NotNull(message = "{notNull.executive.email}")
@Schema(description = "이메일", example = "[email protected]")
Copy link
Preview

Copilot AI Dec 28, 2024

Choose a reason for hiding this comment

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

There is a typo in the email example: "[email protected]" should be "[email protected]".

Suggested change
@Schema(description = "이메일", example = "clab.coreteam@gamil.com")
@Schema(description = "이메일", example = "clab.coreteam@gmail.com")

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Copy link
Collaborator

Choose a reason for hiding this comment

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

@SongJaeHoonn 오탈자 수정 부탁드려요

private String email;

@NotNull(message = "{notNull.executive.field}")
@Schema(description = "분야", example = "Back-End")
private String field;

@NotNull(message = "{notNull.executive.position}")
@Schema(description = "직급", example = "PRESIDENT")
private ExecutivePosition position;

@Schema(description = "프로필 이미지", example = "https://www.clab.page/assets/dongmin-860f3a1e.jpeg")
private String imageUrl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package page.clab.api.domain.memberManagement.executive.application.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import page.clab.api.domain.memberManagement.executive.domain.ExecutivePosition;

@Getter
@Setter
public class ExecutiveUpdateRequestDto {

@Schema(description = "이름", example = "홍길동")
private String name;

@Schema(description = "이메일", example = "[email protected]")
SongJaeHoonn marked this conversation as resolved.
Show resolved Hide resolved
private String email;

@Schema(description = "분야", example = "Back-End")
private String field;

@Schema(description = "직급", example = "PRESIDENT")
private ExecutivePosition position;

@Schema(description = "프로필 이미지", example = "https://www.clab.page/assets/dongmin-860f3a1e.jpeg")
private String imageUrl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package page.clab.api.domain.memberManagement.executive.application.dto.response;

import lombok.Builder;
import lombok.Getter;
import page.clab.api.domain.memberManagement.executive.domain.ExecutivePosition;

@Getter
@Builder
public class ExecutiveResponseDto {

private String id;
private String name;
private String email;
private String field;
private ExecutivePosition position;
private String imageUrl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package page.clab.api.domain.memberManagement.executive.application.exception;

public class ExecutiveRegistrationException extends RuntimeException {

public ExecutiveRegistrationException(String message) {
super(message);
}
}
Loading
Loading