Skip to content

Commit

Permalink
feature: 동아리 박람회 qr 이벤트 기능 구현 (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
5uhwann authored Feb 12, 2024
1 parent 8f1f435 commit 2da650f
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 1 deletion.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'

implementation 'io.hypersistence:hypersistence-utils-hibernate-55:3.7.2'

implementation 'com.auth0:java-jwt:4.2.1'

Expand All @@ -38,6 +41,7 @@ dependencies {

implementation 'org.apache.poi:poi:5.2.0'
implementation 'org.apache.poi:poi-ooxml:5.2.0'
implementation 'org.springframework.boot:spring-boot-configuration-processor'


compileOnly 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public SecurityFilterChain filterChain(HttpSecurity http, JwtAuthService authSer
throws Exception {
http
.authorizeHttpRequests()
.antMatchers(API_PREFIX + "/auth/**")
.antMatchers(API_PREFIX + "/auth/**",
API_PREFIX + "/qr-stamps/**")
.permitAll()
.antMatchers(GET,
API_PREFIX + "/clubs/**",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ddingdong.ddingdongBE.domain.qrstamp.controller;

import ddingdong.ddingdongBE.domain.qrstamp.controller.dto.request.CollectStampRequest;
import ddingdong.ddingdongBE.domain.qrstamp.controller.dto.response.CollectionResultResponse;
import ddingdong.ddingdongBE.domain.qrstamp.service.QrStampService;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/server/qr-stamps")
@RequiredArgsConstructor
public class QrStampController {

private final QrStampService qrStampService;

@PostMapping("/collect")
public void collectStamp(@RequestBody CollectStampRequest request) {
LocalDateTime collectedAt = LocalDateTime.now();
qrStampService.collectStamp(request, collectedAt);
}

@GetMapping()
public CollectionResultResponse getCollectionResult(@RequestParam String studentName, @RequestParam String studentNumber) {
return qrStampService.getCollectionResult(studentName, studentNumber);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ddingdong.ddingdongBE.domain.qrstamp.controller.dto.request;

import ddingdong.ddingdongBE.domain.qrstamp.entity.StampHistory;
import javax.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

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

private String studentName;

@Size(min = 8, max = 8, message = "학번은 8자리입니다.")
private String studentNumber;

private String clubCode;

public StampHistory toStampHistoryEntity() {
return StampHistory.builder()
.studentName(this.studentName)
.studentNumber(this.studentNumber).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ddingdong.ddingdongBE.domain.qrstamp.controller.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
public class CollectedStampsResponse {

private String stamp;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime collectedAt;

public static CollectedStampsResponse of(String stampName, LocalDateTime collectedAt) {
return CollectedStampsResponse.builder()
.stamp(stampName)
.collectedAt(collectedAt).build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ddingdong.ddingdongBE.domain.qrstamp.controller.dto.response;

import ddingdong.ddingdongBE.domain.qrstamp.entity.StampHistory;
import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
public class CollectionResultResponse {

private boolean isCompleted;
private List<CollectedStampsResponse> collections;

public static CollectionResultResponse of(boolean isCompleted,
List<CollectedStampsResponse> collectedStampsResponse) {
return CollectionResultResponse.builder()
.isCompleted(isCompleted)
.collections(collectedStampsResponse)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ddingdong.ddingdongBE.domain.qrstamp.entity;

import java.util.Arrays;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum ClubStamp {

COW("카우", "COW"),
TEST("테스트", "TEST");

private final String name;
private final String code;

public static ClubStamp getByClubCode(String code) {
return Arrays.stream(ClubStamp.values())
.filter(clubStamp -> clubStamp.getCode().equals(code))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("동아리 코드를 확인해주세요."));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package ddingdong.ddingdongBE.domain.qrstamp.entity;

import ddingdong.ddingdongBE.common.BaseEntity;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"studentName", "studentNumber"}))
@TypeDef(name = "json", typeClass = JsonType.class)
public class StampHistory extends BaseEntity {

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

@Column(nullable = false)
private String studentName;

@Column(nullable = false)
private String studentNumber;

@Type(type = "json")
@Column(columnDefinition = "json")
private final Map<ClubStamp, LocalDateTime> collectedStamps = new HashMap<>();

private LocalDateTime completedAt;

@Builder
private StampHistory(Long id, String studentName, String studentNumber, LocalDateTime completedAt) {
this.id = id;
this.studentName = studentName;
this.studentNumber = studentNumber;
this.completedAt = completedAt;
}

public void collectStamp(ClubStamp clubStamp, LocalDateTime collectedAt) {
this.collectedStamps.put(clubStamp, collectedAt);
if (this.collectedStamps.size() == ClubStamp.values().length) {
this.completedAt = LocalDateTime.now();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ddingdong.ddingdongBE.domain.qrstamp.repository;

import ddingdong.ddingdongBE.domain.qrstamp.entity.StampHistory;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StampHistoryRepository extends JpaRepository<StampHistory, Long> {

Optional<StampHistory> findStampHistoryByStudentNameAndStudentNumber(String studentName, String studentNumber);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package ddingdong.ddingdongBE.domain.qrstamp.service;


import ddingdong.ddingdongBE.domain.qrstamp.controller.dto.request.CollectStampRequest;
import ddingdong.ddingdongBE.domain.qrstamp.controller.dto.response.CollectedStampsResponse;
import ddingdong.ddingdongBE.domain.qrstamp.controller.dto.response.CollectionResultResponse;
import ddingdong.ddingdongBE.domain.qrstamp.entity.ClubStamp;
import ddingdong.ddingdongBE.domain.qrstamp.entity.StampHistory;
import ddingdong.ddingdongBE.domain.qrstamp.repository.StampHistoryRepository;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class QrStampService {

private final StampHistoryRepository stampHistoryRepository;

@Transactional
public void collectStamp(CollectStampRequest request, LocalDateTime collectedAt) {
StampHistory stampHistory = stampHistoryRepository.findStampHistoryByStudentNameAndStudentNumber(
request.getStudentName(),
request.getStudentNumber())
.orElse(request.toStampHistoryEntity());

ClubStamp clubStamp = ClubStamp.getByClubCode(request.getClubCode());
stampHistory.collectStamp(clubStamp, collectedAt);

stampHistoryRepository.save(stampHistory);
}

public CollectionResultResponse getCollectionResult(String studentNumber, String studentName) {
StampHistory stampHistory = stampHistoryRepository.findStampHistoryByStudentNameAndStudentNumber(
studentName, studentNumber)
.orElse(StampHistory.builder()
.studentNumber(studentNumber)
.studentName(studentName).build());

List<CollectedStampsResponse> collectedStampsResponse = stampHistory.getCollectedStamps().keySet().stream()
.map(stamp -> CollectedStampsResponse.of(stamp.getName(),
stampHistory.getCollectedStamps().get(stamp)))
.toList();
boolean isCompleted = stampHistory.getCollectedStamps().size() == ClubStamp.values().length;
return CollectionResultResponse.of(isCompleted, collectedStampsResponse);
}

}

0 comments on commit 2da650f

Please sign in to comment.