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

[BE/FEAT] 팀빌딩 상태를 검증한다. #269

Merged
merged 8 commits into from
Feb 20, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.blackcompany.eeos.teamBuilding.application.dto;

import com.blackcompany.eeos.common.support.dto.AbstractResponseDto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
public class ValidateTeamBuildingResponse implements AbstractResponseDto {
private String status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.blackcompany.eeos.teamBuilding.application.dto.converter;

import com.blackcompany.eeos.teamBuilding.application.dto.ValidateTeamBuildingResponse;
import org.springframework.stereotype.Component;

@Component
public class ValidateTeamBuildingResponseConverter {
public ValidateTeamBuildingResponse from(String status) {
return ValidateTeamBuildingResponse.builder().status(status).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.blackcompany.eeos.teamBuilding.application.model;

public enum Accessibility {
CREATABLE("creatable"),
NONCREATABLE("noncreatable"),
JOINABLE("joinable"),
NONJOINABLE("nonjoinable");

private final String status;

Accessibility(String status) {
this.status = status;
}

public String getStatus() {
return status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.blackcompany.eeos.teamBuilding.application.model;

import java.util.Arrays;
import java.util.List;

public enum AccessibilityStandard {
CREATABILITY("creatability", List.of(Accessibility.CREATABLE, Accessibility.NONCREATABLE)),
JOINABILITY("joinability", List.of(Accessibility.JOINABLE, Accessibility.NONJOINABLE));

private final String standard;
private final List<Accessibility> accessibilities;

AccessibilityStandard(String standard, List<Accessibility> accessibilities) {
this.standard = standard;
this.accessibilities = accessibilities;
}

public String getStandard() {
return standard;
}

public List<Accessibility> getAccessibilities() {
return accessibilities;
}

public static AccessibilityStandard find(String source) {
return Arrays.stream(AccessibilityStandard.values())
.filter(standard -> standard.getStandard().equals(source))
.findAny()
.orElse(AccessibilityStandard.CREATABILITY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,15 @@ public RestrictTeamBuildingModel subtractActiveCount() {
return this;
}

public Accessibility getCreatableAccessibility() {
if (isOver()) {
return Accessibility.NONCREATABLE;
}
return Accessibility.CREATABLE;
}

private void validateCreation() {
if (totalActiveCount > UPPER_LIMIT) {
if (isOver()) {
throw new DeniedOverUpperLimitException();
}
}
Expand All @@ -48,4 +55,8 @@ private void validateDeletion() {
throw new NotFoundTeamBuildingStatusException(TeamBuildingStatus.PROGRESS.getStatus());
}
}

private boolean isOver() {
return totalActiveCount >= UPPER_LIMIT;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.blackcompany.eeos.teamBuilding.application.service;

import com.blackcompany.eeos.teamBuilding.application.model.Accessibility;
import com.blackcompany.eeos.teamBuilding.application.model.AccessibilityStandard;
import com.blackcompany.eeos.teamBuilding.application.model.RestrictTeamBuildingModel;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CreatableValidateService implements ValidateService {
private final QueryRestrictTeamBuildingService queryRestrictTeamBuildingService;

@Override
public AccessibilityStandard support() {
return AccessibilityStandard.CREATABILITY;
}

@Override
public Accessibility getAccessibility(Long memberId) {
RestrictTeamBuildingModel model = queryRestrictTeamBuildingService.getRestrict();

return model.getCreatableAccessibility();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.blackcompany.eeos.teamBuilding.application.service;

import com.blackcompany.eeos.target.application.exception.NotFoundTargetTeamBuildingException;
import com.blackcompany.eeos.target.application.service.QueryTeamBuildingTargetService;
import com.blackcompany.eeos.teamBuilding.application.model.Accessibility;
import com.blackcompany.eeos.teamBuilding.application.model.AccessibilityStandard;
import com.blackcompany.eeos.teamBuilding.persistence.TeamBuildingEntity;
import com.blackcompany.eeos.teamBuilding.persistence.TeamBuildingStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class JoinableValidateService implements ValidateService {
private final QueryTeamBuildingService queryTeamBuildingService;
private final QueryTeamBuildingTargetService queryTeamBuildingTargetService;

@Override
public AccessibilityStandard support() {
return AccessibilityStandard.JOINABILITY;
}

@Override
public Accessibility getAccessibility(Long memberId) {
TeamBuildingEntity entity = queryTeamBuildingService.getByStatus(TeamBuildingStatus.PROGRESS);
try {
queryTeamBuildingTargetService.getTarget(memberId, entity.getId());
return Accessibility.JOINABLE;
} catch (NotFoundTargetTeamBuildingException ex) {
return Accessibility.NONCREATABLE;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.blackcompany.eeos.teamBuilding.application.service;

import com.blackcompany.eeos.teamBuilding.application.exception.NotFoundTeamBuildingStatusException;
import com.blackcompany.eeos.teamBuilding.application.model.RestrictTeamBuildingModel;
import com.blackcompany.eeos.teamBuilding.application.model.converter.RestrictTeamBuildingConverter;
import com.blackcompany.eeos.teamBuilding.persistence.RestrictTeamBuildingRepository;
import com.blackcompany.eeos.teamBuilding.persistence.TeamBuildingStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class QueryRestrictTeamBuildingService {
private final RestrictTeamBuildingRepository restrictTeamBuildingRepository;
private final RestrictTeamBuildingConverter restrictTeamBuildingConverter;

public RestrictTeamBuildingModel getRestrict() {
return restrictTeamBuildingRepository
.findTopByOrderByVersion()
.map(restrictTeamBuildingConverter::from)
.orElseThrow(
() -> new NotFoundTeamBuildingStatusException(TeamBuildingStatus.PROGRESS.getStatus()));
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.blackcompany.eeos.teamBuilding.application.service;

import com.blackcompany.eeos.teamBuilding.application.exception.DeniedOverUpperLimitException;
import com.blackcompany.eeos.teamBuilding.application.exception.NotFoundTeamBuildingStatusException;
import com.blackcompany.eeos.teamBuilding.application.model.RestrictTeamBuildingModel;
import com.blackcompany.eeos.teamBuilding.application.model.converter.RestrictTeamBuildingConverter;
import com.blackcompany.eeos.teamBuilding.persistence.RestrictTeamBuildingRepository;
import com.blackcompany.eeos.teamBuilding.persistence.TeamBuildingStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.stereotype.Service;
Expand All @@ -17,6 +15,7 @@
public class RestrictTeamBuildingService {
private final RestrictTeamBuildingRepository restrictTeamBuildingRepository;
private final RestrictTeamBuildingConverter restrictTeamBuildingConverter;
private final QueryRestrictTeamBuildingService queryRestrictTeamBuildingService;

@Transactional
public void addTeamBuilding() {
Expand All @@ -35,10 +34,6 @@ public void subtractTeamBuilding() {
}

private RestrictTeamBuildingModel getRestrict() {
return restrictTeamBuildingRepository
.findTopByOrderByVersion()
.map(restrictTeamBuildingConverter::from)
.orElseThrow(
() -> new NotFoundTeamBuildingStatusException(TeamBuildingStatus.PROGRESS.getStatus()));
return queryRestrictTeamBuildingService.getRestrict();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.blackcompany.eeos.teamBuilding.application.service;

import com.blackcompany.eeos.teamBuilding.application.model.Accessibility;
import com.blackcompany.eeos.teamBuilding.application.model.AccessibilityStandard;

public interface ValidateService {
AccessibilityStandard support();

Accessibility getAccessibility(Long memberId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.blackcompany.eeos.teamBuilding.application.service;

import com.blackcompany.eeos.teamBuilding.application.dto.ValidateTeamBuildingResponse;
import com.blackcompany.eeos.teamBuilding.application.dto.converter.ValidateTeamBuildingResponseConverter;
import com.blackcompany.eeos.teamBuilding.application.model.Accessibility;
import com.blackcompany.eeos.teamBuilding.application.model.AccessibilityStandard;
import com.blackcompany.eeos.teamBuilding.application.support.ValidateTeamBuildingServiceComposite;
import com.blackcompany.eeos.teamBuilding.application.usecase.ValidateTeamBuildingUsecase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ValidateTeamBuildingService implements ValidateTeamBuildingUsecase {
private final ValidateTeamBuildingServiceComposite validateTeamBuildingServiceComposite;
private final ValidateTeamBuildingResponseConverter responseConverter;

@Override
public ValidateTeamBuildingResponse validate(Long memberId, String status) {
Accessibility accessibility =
validateTeamBuildingServiceComposite.getAccessibility(
AccessibilityStandard.find(status), memberId);

return responseConverter.from(accessibility.getStatus());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.blackcompany.eeos.teamBuilding.application.support;

import com.blackcompany.eeos.teamBuilding.application.model.Accessibility;
import com.blackcompany.eeos.teamBuilding.application.model.AccessibilityStandard;
import com.blackcompany.eeos.teamBuilding.application.service.ValidateService;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;

@Component
public class ValidateTeamBuildingServiceComposite {
private final Map<AccessibilityStandard, ValidateService> services;

public ValidateTeamBuildingServiceComposite(Set<ValidateService> validateServices) {
this.services =
validateServices.stream()
.collect(Collectors.toMap(ValidateService::support, Function.identity()));
}

public Accessibility getAccessibility(AccessibilityStandard standard, Long memberId) {
ValidateService validateService = getValidateService(standard);

return validateService.getAccessibility(memberId);
}

private ValidateService getValidateService(AccessibilityStandard standard) {
return services.get(standard);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.blackcompany.eeos.teamBuilding.application.usecase;

import com.blackcompany.eeos.teamBuilding.application.dto.ValidateTeamBuildingResponse;

public interface ValidateTeamBuildingUsecase {
/**
* 팀빌딩이 요청한 정보가 가능한 상태인지 검증한다.
*
* @param memberId 팀빌딩 작성자
*/
ValidateTeamBuildingResponse validate(Long memberId, String status);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,26 @@
import com.blackcompany.eeos.common.presentation.respnose.ApiResponseGenerator;
import com.blackcompany.eeos.common.presentation.respnose.MessageCode;
import com.blackcompany.eeos.teamBuilding.application.dto.CreateTeamBuildingRequest;
import com.blackcompany.eeos.teamBuilding.application.dto.ValidateTeamBuildingResponse;
import com.blackcompany.eeos.teamBuilding.application.usecase.CreateTeamBuildingUsecase;
import com.blackcompany.eeos.teamBuilding.application.usecase.EndTeamBuildingUsecase;
import com.blackcompany.eeos.teamBuilding.application.usecase.ValidateTeamBuildingUsecase;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class TeamBuildingController {
private final CreateTeamBuildingUsecase createTeamBuildingUsecase;
private final EndTeamBuildingUsecase endTeamBuildingUsecase;
private final ValidateTeamBuildingUsecase validateTeamBuildingUsecase;

@PostMapping("/team-building")
public ApiResponse<SuccessBody<Void>> create(
Expand All @@ -34,4 +39,11 @@ public ApiResponse<SuccessBody<Void>> end(@Member Long memberId) {
endTeamBuildingUsecase.delete(memberId);
return ApiResponseGenerator.success(HttpStatus.OK, MessageCode.DELETE);
}

@GetMapping("/team-building/validate")
public ApiResponse<SuccessBody<ValidateTeamBuildingResponse>> validateStatus(
@Member Long memberId, @RequestParam("status") String status) {
ValidateTeamBuildingResponse response = validateTeamBuildingUsecase.validate(memberId, status);
return ApiResponseGenerator.success(response, HttpStatus.OK, MessageCode.GET);
}
}
Loading