Skip to content

Commit

Permalink
Merge pull request #26 from TeamPu/feat/#21
Browse files Browse the repository at this point in the history
야간잔류 신청 기능 구현
  • Loading branch information
ahyeonkong authored Nov 24, 2024
2 parents ffba904 + 506cd43 commit fb92b35
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.kyonggi.teampu.domain.application.controller;

import com.kyonggi.teampu.domain.application.dto.ApplicationRequest;
import com.kyonggi.teampu.domain.application.service.ApplicationService;
import com.kyonggi.teampu.domain.auth.domain.CustomMemberDetails;
import com.kyonggi.teampu.global.response.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
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;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/apply")
public class ApplicationController {
private final ApplicationService applicationService;

/**
* 신청서 작성 API
* */
@PostMapping
public ApiResponse<Void> createApplication(@RequestBody ApplicationRequest applicationRequest,
@AuthenticationPrincipal CustomMemberDetails customMemberDetails) {
// @AuthenticationPrincipal 스프링 시큐리티 활용해서 사용자 정보 받아옴

applicationService.createApplication(applicationRequest, customMemberDetails);

return ApiResponse.ok(); // POST에 대해서 리턴 값 필요없음 >> Void
}

}
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
package com.kyonggi.teampu.domain.application.domain;

import com.kyonggi.teampu.domain.member.domain.CoParticipant;
import com.kyonggi.teampu.domain.member.domain.Member;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
Expand All @@ -33,20 +25,33 @@ public class Application {
@Column(name = "application_id")
private Long id;

@Column(name = "start_time", nullable = false)
private LocalDateTime startTime;

@Column(name = "end_time", nullable = false)
private LocalDateTime endTime;

@Column(name = "applied_date", nullable = false)
private LocalDate appliedDate;

@Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false)
private ApplicationStatus status;

@Column(name = "participant_count")
private Integer participantCount;

@ElementCollection // JPA에서 값 타입 컬렉션을 매핑할 때 사용하는 어노테이션
@CollectionTable(
name = "application_co_participants",
joinColumns = @JoinColumn(name = "application_id")
)
private List<CoParticipant> coParticipants = new ArrayList<>();

@Column(name = "privacy_agreement")
private Boolean privacyAgreement;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

private String applicantName; // Member의 name
private String applicantLoginId; // Member의 loginId
private String applicantPhone; // Member의 phoneNumber
private String applicantEmail; // Member의 email

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
package com.kyonggi.teampu.domain.application.domain;

import com.fasterxml.jackson.annotation.JsonValue;

public enum ApplicationStatus {
PENDING,
APPROVED,
REJECTED
PENDING("pending"),
APPROVED("approved"),
REJECTED("rejected");

private final String code;

ApplicationStatus(String code) {
this.code = code;
}

@JsonValue
public String getCode() {
return this.code;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.kyonggi.teampu.domain.application.dto;
import com.kyonggi.teampu.domain.application.domain.ApplicationStatus;
import com.kyonggi.teampu.domain.member.dto.CoParticipantRequest;
import lombok.AllArgsConstructor;
import lombok.Getter;

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

/**
* 예약 제출 페이지에서
* 사용자의 정보(이름, 학번, 전화번호, 이메일)를 자동으로 받아옴 >> 로그인 정보에서 가져옴
* 날짜 >> 사용자가 직접 입력
* 공동 참여자 목록(이름, 전화번호) >> 사용자가 직접 입력
* 인원 >> 공동 참여자 목록 + 1으로 신청자 포함한 사용 인원 자동 계산
* 개인정보 동의 여부 >> 사용자가 직접 체크
*/

@Getter
@AllArgsConstructor
public class ApplicationRequest {
// 로그인 정보를 통해 이름, 학번, 전화번호, 이메일 받아옴
private LocalDate appliedDate; // 날짜
private List<CoParticipantRequest> coParticipants; // 공동 참여자 목록 (이름, 전화번호)
private Boolean privacyAgreement; // 개인정보 동의 여부
private ApplicationStatus status;

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

public interface ApplicationRepository extends JpaRepository<Application, Long> {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.kyonggi.teampu.domain.application.service;

import com.kyonggi.teampu.domain.application.domain.Application;
import com.kyonggi.teampu.domain.application.dto.ApplicationRequest;
import com.kyonggi.teampu.domain.application.repository.ApplicationRepository;
import com.kyonggi.teampu.domain.auth.domain.CustomMemberDetails;
import com.kyonggi.teampu.domain.member.domain.CoParticipant;
import com.kyonggi.teampu.domain.member.domain.Member;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ApplicationService {
private final ApplicationRepository applicationRepository;

@Transactional
public void createApplication(ApplicationRequest applicationRequest, CustomMemberDetails customMemberDetails) {
// GET 메서드를 별도로 구현할 예정이라 void 처리

/**
* 1. 사용자의 정보(이름, 학번, 전화번호, 이메일) 추출
* 2. 사용자가 직접 정보 입력(날짜, 명단: 이름, 전화번호, 개인정보 동의)
* 3. 사용 인원 계산
*/

Member member = customMemberDetails.getMember();
List<CoParticipant> coParticipants = applicationRequest.getCoParticipants().stream()
.map(CoParticipant::from)
.collect(Collectors.toList());

// Application.builder()를 사용하여 로그인한 사용자 정보와 입력받은 정보를 결합
Application application = Application.builder()
.member(member) // memberId
.applicantName(customMemberDetails.getMember().getName()) // 이름
.applicantLoginId(customMemberDetails.getMember().getLoginId()) // 학번
.applicantPhone(customMemberDetails.getMember().getPhoneNumber()) // 전화번호
.applicantEmail(customMemberDetails.getMember().getEmail()) // 이메일

.appliedDate(applicationRequest.getAppliedDate()) // 날짜
.coParticipants(coParticipants) // 명단(이름, 전화번호)
.participantCount(applicationRequest.getCoParticipants().size() + 1) // 사용 인원 자동 계산
.privacyAgreement(applicationRequest.getPrivacyAgreement()) // 개인정보 동의
.status(applicationRequest.getStatus())
.build();

applicationRepository.save(application);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.kyonggi.teampu.domain.member.domain;

import com.kyonggi.teampu.domain.member.dto.CoParticipantRequest;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
* 공동 사용자 정보를 별도의 엔티티로 관리함
*/
@Embeddable
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class CoParticipant {
@Column(name = "name")
private String name;

@Column(name = "phone_number")
private String phoneNumber;

// DTO를 값 타입으로 변환하는 메서드
public static CoParticipant from(CoParticipantRequest request) {
return new CoParticipant(
request.getName(),
request.getPhoneNumber()
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kyonggi.teampu.domain.member.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

import java.util.List;

@Getter
@Builder
@AllArgsConstructor
public class CoParticipantRequest {
// CoParticipantRequest: 공동 참여자 정보를 서버로 전송할 때 사용하는 객체
private String name; // 이름
private String phoneNumber; // 전화번호

// CoParticipantRequest에서 이름과 전화번호를 리스트로 변환하려면, CoParticipantRequest 클래스에 변환 메서드를 추가
public static List<String> toNameList(List<CoParticipantRequest> coParticipantRequests) {
return coParticipantRequests.stream()
.map(CoParticipantRequest::getName)
.toList();
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.kyonggi.teampu.domain.member.dto;

import com.kyonggi.teampu.domain.member.domain.Member;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor
public class MemberInfoResponse {
private final Long userId;
private final String loginId;
Expand All @@ -26,4 +30,5 @@ public MemberInfoResponse(Member member) {
this.type = member.getType().name();
this.isAdmin = member.getIsAdmin();
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.kyonggi.teampu.domain.member.repository;

import com.kyonggi.teampu.domain.member.domain.Member;

import org.springframework.data.repository.Repository;

import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static <T> ApiResponse<T> exception(ErrorCode errorCode) {

@Getter
@AllArgsConstructor
private static class Status {
public static class Status {
private HttpStatus httpStatus;
private String message;
}
Expand Down

0 comments on commit fb92b35

Please sign in to comment.