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: cotatomgmt #11

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
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
13 changes: 8 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -3,31 +3,34 @@ plugins {
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}

group = 'cotato'
version = '0.0.1-SNAPSHOT'

java {
sourceCompatibility = '17'
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'


}

tasks.named('test') {
useJUnitPlatform()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cotato.cotatomanage.management;

import cotato.cotatomanage.management.domain.Part;
import cotato.cotatomanage.management.dto.request.RegisterRequest;
import cotato.cotatomanage.management.dto.response.MemberResponse;
import cotato.cotatomanage.management.dto.response.PartResponse;
import cotato.cotatomanage.management.service.ManagementService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/management")
public class ManagementController {

private final ManagementService managementService;

@PostMapping("/register")
public void registerMember(RegisterRequest registerRequest) {
log.info("멤버 등록");
managementService.registerMember(registerRequest);
}

@GetMapping("/part")
public MemberResponse getPartAbility(
@RequestParam Part part,
@RequestParam int periodNow
) {
log.info("특정 파트 실력");
return managementService.getPartAbility(part, periodNow);
}

@GetMapping("/stats")
public PartResponse getPartStatAbility(@RequestParam int periodNow) {
log.info("파트별 실력 통계");
return managementService.getPartStatsAbility(periodNow);
}

@GetMapping
public MemberResponse getAllAbility(@RequestParam int periodNow) {
log.info("모든 부원 실력");
return managementService.getAllAbility(periodNow);
}
}
73 changes: 73 additions & 0 deletions src/main/java/cotato/cotatomanage/management/domain/Member.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cotato.cotatomanage.management.domain;

import cotato.cotatomanage.management.dto.request.RegisterRequest;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {

private static final int MAX_AGE = 27;
private static final int PERIOD_INCREASING_ABILITY = 2;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
@Size(max = 20)
private String name;

@NotNull
private int period;

@NotNull
private int age;

@NotNull
@Enumerated(EnumType.STRING)
private Part part;

// 생성자
@Builder
private Member(
String name,
int period,
int age,
Part part) {

this.name = name;
this.period = period;
this.age = age;
this.part = part;
}

public static Member of(RegisterRequest registerRequest) {
return Member.builder()
.name(registerRequest.getName())
.period(registerRequest.getPeriod())
.age(registerRequest.getAge())
.part(registerRequest.getPart())
.build();
}

private int ability(int periodNow) {
return PERIOD_INCREASING_ABILITY * (periodNow - this.getPeriod());
}

public int getAbility(int periodNow) {
int ability = this.getAge() + ability(periodNow);

if (this.getAge() <= MAX_AGE) {
return ability + Month.ability(this);
}
return ability;
}
}
46 changes: 46 additions & 0 deletions src/main/java/cotato/cotatomanage/management/domain/Month.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cotato.cotatomanage.management.domain;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Stream;

import static cotato.cotatomanage.management.domain.Part.*;

@Getter
@RequiredArgsConstructor
public enum Month {

PRODUCT_MONTH(PRODUCT, List.of(1, 5, 9), 10),
DESIGNER_MONTH(DESIGNER, List.of(2, 6, 10), 10),
FRONTEND_MONTH(FRONTEND, List.of(3, 7, 11), 10),
BACKEND_MONTH(BACKEND, List.of(4, 8, 12), 10);

private Part part;
private List<Integer> months;
private int number;

Month(Part part, List<Integer> months, int number) {
this.part = part;
this.months = months;
this.number = number;
}

public static Month partParsing(Part part) {
return Stream.of(Month.values())
.filter(partMonth -> partMonth.getPart().equals(part))
.findFirst()
.orElse(null);
}

public static int ability(Member member) {
Month partMonth = partParsing(member.getPart());
int monthNow = LocalDate.now().getDayOfMonth();
if (partMonth.months.contains(monthNow)) {
return partMonth.getNumber();
}
return 0;
}
}
28 changes: 28 additions & 0 deletions src/main/java/cotato/cotatomanage/management/domain/Part.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cotato.cotatomanage.management.domain;


import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.stream.Stream;

@Getter
@RequiredArgsConstructor
public enum Part {
DESIGNER("디자이너"),
PRODUCT("기획"),
BACKEND("백엔드"),
FRONTEND("프론트엔드");

@JsonValue private final String part;

@JsonCreator
public static Part parsing(String inputValue) {
return Stream.of(Part.values())
.filter(part -> part.getPart().equals(inputValue))
.findFirst()
.orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cotato.cotatomanage.management.dto.request;

import cotato.cotatomanage.management.domain.Part;
import lombok.Getter;

@Getter
public class RegisterRequest {

private String name;

private int period;

private int age;

private Part part;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cotato.cotatomanage.management.dto.response;

import cotato.cotatomanage.management.vo.MemberVo;
import lombok.Builder;

import java.util.List;

public class MemberResponse {

List<MemberVo> memberInfoVoList;

@Builder
private MemberResponse(List<MemberVo> memberInfoVoList) {
this.memberInfoVoList = memberInfoVoList;
}

public static MemberResponse from(List<MemberVo> memberInfoVoList) {
return MemberResponse.builder()
.memberInfoVoList(memberInfoVoList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cotato.cotatomanage.management.dto.response;

import cotato.cotatomanage.management.vo.PartVo;
import lombok.Builder;

import java.util.List;

public class PartResponse {

List<PartVo> partInfoVoList;

@Builder
private PartResponse(List<PartVo> partInfoVoList) {
this.partInfoVoList = partInfoVoList;
}

public static PartResponse from(List<PartVo> partInfoVoList) {
return PartResponse.builder()
.partInfoVoList(partInfoVoList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cotato.cotatomanage.management.helper;

import cotato.cotatomanage.management.domain.Part;
import cotato.cotatomanage.management.vo.MemberVo;
import cotato.cotatomanage.management.vo.PartVo;
import org.springframework.stereotype.Component;

import java.util.Comparator;
import java.util.List;

@Component
public class ManagementHelper {

public void sortPart(List<PartVo> partInfoVoList) {
partInfoVoList.sort(Comparator
.comparing(PartVo::getAbility)
.reversed()
.thenComparing(PartVo::getCount)
.thenComparing(PartVo::getPart, Comparator.comparing(Part::ordinal))
);
}

public void sortAll(List<MemberVo> memberInfoList) {
memberInfoList.sort(Comparator
.comparing(MemberVo::getAbility)
.reversed()
.thenComparing(MemberVo::getAge, Comparator.reverseOrder())
.thenComparing(MemberVo::getPeriod)
.thenComparing(MemberVo::getName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cotato.cotatomanage.management.mapper;

import cotato.cotatomanage.management.domain.Member;
import cotato.cotatomanage.management.domain.Part;
import cotato.cotatomanage.management.dto.response.PartResponse;
import cotato.cotatomanage.management.helper.ManagementHelper;
import cotato.cotatomanage.management.repository.MemberRepository;
import cotato.cotatomanage.management.vo.MemberVo;
import cotato.cotatomanage.management.dto.response.MemberResponse;
import cotato.cotatomanage.management.vo.PartVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@RequiredArgsConstructor
public class ManagementMapper {

private final MemberRepository memberRepository;
private final ManagementHelper managementHelper;

public MemberResponse toMemberInfoListResponse(List<Member> memberList, int periodNow) {
List<MemberVo> memberInfoList =
memberList.stream()
.map(member -> MemberVo.of(member, periodNow))
.toList();
managementHelper.sortAll(memberInfoList);
return MemberResponse.from(memberInfoList);
}

public PartResponse toPartInfoListResponse(List<PartVo> partInfoVoList) {
managementHelper.sortPart(partInfoVoList);
return PartResponse.from(partInfoVoList);
}

public List<PartVo> toPartInfoVoList(int periodNow) {
List<PartVo> partInfoVoList = new ArrayList<>();
Part[] parts = Part.class.getEnumConstants();
for (Part part : parts) {
List<Member> memberList = memberRepository.findAllByPart(part);
PartVo partInfoVo = PartVo.of(part, memberList, periodNow);
partInfoVoList.add(partInfoVo);
}
return partInfoVoList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cotato.cotatomanage.management.repository;


import cotato.cotatomanage.management.domain.Member;
import cotato.cotatomanage.management.domain.Part;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface MemberRepository extends JpaRepository<Member, Long> {

List<Member> findAllByPart(Part part);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cotato.cotatomanage.management.service;

import cotato.cotatomanage.management.domain.Member;
import cotato.cotatomanage.management.domain.Part;
import cotato.cotatomanage.management.dto.request.RegisterRequest;
import cotato.cotatomanage.management.dto.response.MemberResponse;
import cotato.cotatomanage.management.dto.response.PartResponse;
import cotato.cotatomanage.management.mapper.ManagementMapper;
import cotato.cotatomanage.management.repository.MemberRepository;
import cotato.cotatomanage.management.vo.PartVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class ManagementService {

private final MemberRepository memberRepository;
private final ManagementMapper managementMapper;

@Transactional
public void registerMember(RegisterRequest registerRequest) {
Member member = Member.of(registerRequest);
memberRepository.save(member);
}

@Transactional
public MemberResponse getPartAbility(Part part, int periodNow) {
List<Member> memberList = memberRepository.findAllByPart(part);
return managementMapper.toMemberInfoListResponse(memberList, periodNow);
}

@Transactional
public PartResponse getPartStatsAbility(int periodNow) {
List<PartVo> partInfoVoList = managementMapper.toPartInfoVoList(periodNow);
return managementMapper.toPartInfoListResponse(partInfoVoList);
}

@Transactional
public MemberResponse getAllAbility(int periodNow) {
List<Member> memberList = memberRepository.findAll();
return managementMapper.toMemberInfoListResponse(memberList, periodNow);
}

}
35 changes: 35 additions & 0 deletions src/main/java/cotato/cotatomanage/management/vo/MemberVo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cotato.cotatomanage.management.vo;

import cotato.cotatomanage.management.domain.Member;
import cotato.cotatomanage.management.domain.Part;
import lombok.Builder;
import lombok.Getter;

@Getter
public class MemberVo {

private String name;
private int period;
private int age;
private Part part;
private int ability;

@Builder
private MemberVo(String name, int period, int age, Part part, int ability) {
this.name = name;
this.period = period;
this.age = age;
this.part = part;
this.ability = ability;
}

public static MemberVo of(Member member, int periodNow) {
return MemberVo.builder()
.name(member.getName())
.period(member.getPeriod())
.age(member.getAge())
.part(member.getPart())
.ability(member.getAbility(periodNow))
.build();
}
}
42 changes: 42 additions & 0 deletions src/main/java/cotato/cotatomanage/management/vo/PartVo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cotato.cotatomanage.management.vo;

import cotato.cotatomanage.management.domain.Member;
import cotato.cotatomanage.management.domain.Part;
import lombok.Builder;
import lombok.Getter;

import java.util.List;

@Getter
public class PartVo {
private Part part;
private int ability;
private int count;

@Builder
private PartVo(Part part, int ability, int count) {
this.part = part;
this.ability = ability;
this.count = getCount();
}

public static PartVo of(Part part, List<Member> memberList, int periodNow) {
return PartVo.builder()
.part(part)
.ability(calcAbilityStats(memberList, periodNow))
.count(memberList.size())
.build();
}

private static int calcAbilityStats(List<Member> memberList, int periodNow) {
if (memberList == null || memberList.isEmpty()) {
return 0;
}

int sum = 0;
for (Member member : memberList) {
sum += member.getAbility(periodNow);
}
return (int) sum / memberList.size();
}
}