Skip to content

Commit

Permalink
Merge pull request #71 from uswLectureEvaluation/feat/version_update
Browse files Browse the repository at this point in the history
feat: 버전 강제 업데이트 API
  • Loading branch information
wonslee authored Jan 24, 2024
2 parents 47d7adb + 884cf89 commit b5e66b1
Show file tree
Hide file tree
Showing 20 changed files with 524 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package usw.suwiki.domain.evaluatepost.domain;

import java.time.LocalDateTime;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
Expand All @@ -13,7 +12,6 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.LastModifiedDate;
import usw.suwiki.domain.evaluatepost.controller.dto.EvaluatePostSaveDto;
import usw.suwiki.domain.evaluatepost.controller.dto.EvaluatePostUpdateDto;
import usw.suwiki.domain.lecture.domain.Lecture;
Expand Down Expand Up @@ -50,8 +48,6 @@ public class EvaluatePost extends BaseTimeEntity {
@JoinColumn(name = "user_idx")
private User user;

@LastModifiedDate
private LocalDateTime modifiedDate;

@Column(columnDefinition = "TEXT", nullable = false)
private String content; //주관적인 강의평가 입력내용
Expand Down
17 changes: 9 additions & 8 deletions src/main/java/usw/suwiki/domain/exampost/domain/ExamPost.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package usw.suwiki.domain.exampost.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.LastModifiedDate;
import usw.suwiki.domain.exampost.controller.dto.ExamPostsSaveDto;
import usw.suwiki.domain.exampost.controller.dto.ExamPostUpdateDto;
import usw.suwiki.domain.exampost.controller.dto.ExamPostsSaveDto;
import usw.suwiki.domain.lecture.domain.Lecture;
import usw.suwiki.domain.user.user.User;
import usw.suwiki.global.BaseTimeEntity;

import javax.persistence.*;
import java.time.LocalDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
Expand All @@ -30,9 +34,6 @@ public class ExamPost extends BaseTimeEntity {
private String examInfo; //시험방식
private String examDifficulty; //난이도

@LastModifiedDate
private LocalDateTime modifiedDate;

@Column(columnDefinition = "TEXT", nullable = false)
private String content;

Expand Down
4 changes: 0 additions & 4 deletions src/main/java/usw/suwiki/domain/lecture/domain/Lecture.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package usw.suwiki.domain.lecture.domain;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
Expand All @@ -16,7 +15,6 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.LastModifiedDate;
import usw.suwiki.domain.evaluatepost.domain.EvaluatePost;
import usw.suwiki.domain.evaluatepost.service.dto.EvaluatePostsToLecture;
import usw.suwiki.global.BaseTimeEntity;
Expand Down Expand Up @@ -52,8 +50,6 @@ public class Lecture extends BaseTimeEntity {

private int postsCount = 0;

@LastModifiedDate
private LocalDateTime modifiedDate;

@OneToMany(mappedBy = "lecture", cascade = CascadeType.ALL, orphanRemoval = true)
private List<EvaluatePost> evaluatePostList = new ArrayList<>();
Expand Down
14 changes: 4 additions & 10 deletions src/main/java/usw/suwiki/domain/notice/domain/Notice.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package usw.suwiki.domain.notice.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.LastModifiedDate;
import usw.suwiki.domain.notice.controller.dto.NoticeSaveOrUpdateDto;
import usw.suwiki.global.BaseTimeEntity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.NoArgsConstructor;
import usw.suwiki.domain.notice.controller.dto.NoticeSaveOrUpdateDto;
import usw.suwiki.global.BaseTimeEntity;

@Getter
@NoArgsConstructor
Expand All @@ -20,9 +17,6 @@ public class Notice extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@LastModifiedDate
private LocalDateTime modifiedDate;

private String title;
private String content;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package usw.suwiki.domain.version.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import usw.suwiki.domain.version.dto.response.CheckUpdateMandatoryResponse;
import usw.suwiki.domain.version.service.ClientAppVersionService;

@Slf4j
@RestController
@RequestMapping("/client/version")
@RequiredArgsConstructor
public class ClientAppVersionController {
private final ClientAppVersionService clientAppVersionService;

@GetMapping("/update-mandatory")
public ResponseEntity<CheckUpdateMandatoryResponse> checkIsUpdateMandatory(
@RequestParam String os,
@RequestParam Integer versionCode
) {
return ResponseEntity.ok(clientAppVersionService.checkIsUpdateMandatory(os, versionCode));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package usw.suwiki.domain.version.dto.response;

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

@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class CheckUpdateMandatoryResponse {
private final Boolean isUpdateMandatory;

public static CheckUpdateMandatoryResponse from(boolean isUpdateMandatory) {
return CheckUpdateMandatoryResponse.builder()
.isUpdateMandatory(isUpdateMandatory)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package usw.suwiki.domain.version.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import usw.suwiki.global.BaseTimeEntity;
import usw.suwiki.global.exception.ExceptionType;
import usw.suwiki.global.exception.errortype.VersionException;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(uniqueConstraints = {
@UniqueConstraint(
name = "UNIQUE_OS_AND_VERSION_CODE",
columnNames = {"os", "version_code"}
)
})
public class ClientAppVersion extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "client_app_version_id")
private Long id;

@Enumerated(EnumType.STRING)
@NotNull
@Column(name = "os")
private ClientOS os;

@NotNull
@Min(value = 0)
@Column(name = "version_code")
private Integer versionCode;

@NotNull
private Boolean isVital;

@Size(max = 2000)
private String description;


@Builder
public ClientAppVersion(ClientOS os, Integer versionCode, Boolean isVital, String description) {
this.os = os;
this.versionCode = versionCode;
this.isVital = isVital;
this.description = description;
}

public boolean judgeIsUpdateMandatory(ClientOS os, Integer otherVersionCode) {
if (!this.os.equals(os)) {
throw new VersionException(ExceptionType.SERVER_ERROR);
}
return this.isVital && this.versionCode > otherVersionCode;
}
}
35 changes: 35 additions & 0 deletions src/main/java/usw/suwiki/domain/version/entity/ClientOS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package usw.suwiki.domain.version.entity;

import java.util.Arrays;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import usw.suwiki.global.exception.ExceptionType;
import usw.suwiki.global.exception.errortype.VersionException;
import usw.suwiki.global.util.enums.KeyValueEnumModel;

@RequiredArgsConstructor
public enum ClientOS implements KeyValueEnumModel<String> {
ANDROID("ANDROID"), IOS("IOS"), WEB("WEB");

private final String value;

public static ClientOS ofString(String param) {
if (Objects.isNull(param)) {
throw new VersionException(ExceptionType.INVALID_CLIENT_OS);
}
return Arrays.stream(ClientOS.values())
.filter(v -> v.getValue().equals(param.toUpperCase()))
.findFirst()
.orElseThrow(() -> new VersionException(ExceptionType.COMMON_CLIENT_ERROR));
}

@Override
public String getKey() {
return name();
}

@Override
public String getValue() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package usw.suwiki.domain.version.repository;

import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import usw.suwiki.domain.version.entity.ClientAppVersion;
import usw.suwiki.domain.version.entity.ClientOS;

public interface ClientAppVersionRepository extends JpaRepository<ClientAppVersion, Long> {
Optional<ClientAppVersion> findFirstByOsAndIsVitalTrueOrderByVersionCodeDesc(ClientOS os);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package usw.suwiki.domain.version.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import usw.suwiki.domain.version.dto.response.CheckUpdateMandatoryResponse;
import usw.suwiki.domain.version.entity.ClientAppVersion;
import usw.suwiki.domain.version.entity.ClientOS;
import usw.suwiki.domain.version.repository.ClientAppVersionRepository;
import usw.suwiki.global.exception.ExceptionType;
import usw.suwiki.global.exception.errortype.VersionException;


@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ClientAppVersionService {
private final ClientAppVersionRepository clientAppVersionRepository;

public CheckUpdateMandatoryResponse checkIsUpdateMandatory(String os, int versionCode) {
ClientOS clientOS = ClientOS.ofString(os);
ClientAppVersion clientAppVersion = clientAppVersionRepository
.findFirstByOsAndIsVitalTrueOrderByVersionCodeDesc(clientOS)
.orElseThrow(() -> new VersionException(ExceptionType.SERVER_ERROR));

boolean isUpdateMandatory = clientAppVersion.judgeIsUpdateMandatory(clientOS, versionCode);
return CheckUpdateMandatoryResponse.from(isUpdateMandatory);
}
}
17 changes: 10 additions & 7 deletions src/main/java/usw/suwiki/global/BaseTimeEntity.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package usw.suwiki.global;

import java.time.LocalDateTime;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;


@Getter
@MappedSuperclass //Jpa Entity 클래스들이 BastTimeEntity 를 상속할 경우, 필드들도 칼럼으로 인식된다.
@EntityListeners(AuditingEntityListener.class) //Auditing 기능을 포함시킨다.
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {

@CreatedDate // Entity가 생성되어 저장할 때 시간이 자동 저장된다.
@CreatedDate
private LocalDateTime createDate;

@LastModifiedDate
private LocalDateTime modifiedDate;
}
8 changes: 8 additions & 0 deletions src/main/java/usw/suwiki/global/exception/ExceptionType.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ public enum ExceptionType {

INVALID_TIMETABLE_CELL_SCHEDULE("TIMETABLE210", "유효하지 않은 셀 스케줄입니다.", BAD_REQUEST),
OVERLAPPED_TIMETABLE_CELL_SCHEDULE("TIMETABLE211", "시간표에 중복되는 요일-교시입니다.", CONFLICT),

/**
* Domain : Client Version
*/
CLIENT_VERSION_NOT_FOUND("VERSION001", "존재하지 않는 클라이언트 버전입니다.", NOT_FOUND),
INVALID_CLIENT_OS("VERSION110", "유효하지 않은 클라이언트 OS 입니다.", BAD_REQUEST),


/**
* 공통
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package usw.suwiki.global.exception.errortype;

import usw.suwiki.global.exception.ExceptionType;

public class VersionException extends BaseException {
public VersionException(ExceptionType exceptionType) {
super(exceptionType);
}

}
23 changes: 23 additions & 0 deletions src/test/java/usw/suwiki/global/annotation/SuwikiJpaTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package usw.suwiki.global.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import usw.suwiki.config.TestJpaConfig;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)

@DataJpaTest
@Import(TestJpaConfig.class)
@TestMethodOrder(MethodOrderer.DisplayName.class)
@AutoConfigureTestDatabase(replace = Replace.NONE)
public @interface SuwikiJpaTest {
}
Loading

0 comments on commit b5e66b1

Please sign in to comment.