Skip to content

Commit

Permalink
Merge pull request #71 from Tune-Fun/feature/vote/paper_detail
Browse files Browse the repository at this point in the history
Feature/vote/paper detail
  • Loading branch information
habinkim authored May 5, 2024
2 parents 232c934 + 48f574e commit 4152963
Show file tree
Hide file tree
Showing 21 changed files with 261 additions and 32 deletions.
12 changes: 6 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,18 @@ dependencies {
// Persistence Layer
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.4'
implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.5'
implementation "io.github.openfeign.querydsl:querydsl-jpa-spring:${queryDslVersion}"
implementation "io.github.openfeign.querydsl:querydsl-collections:${queryDslVersion}"
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.1'
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-database-postgresql:10.11.1'
implementation 'org.flywaydb:flyway-database-postgresql:10.12.0'
implementation 'org.postgresql:postgresql'

// development
implementation 'org.springframework.retry:spring-retry'
implementation 'org.springframework:spring-aspects'
implementation 'com.github.f4b6a3:ulid-creator:5.2.2'
implementation 'com.github.f4b6a3:ulid-creator:5.2.3'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
// @see https://github.com/awspring/spring-cloud-aws/issues/657
// developmentOnly 'org.springframework.boot:spring-boot-devtools'
Expand All @@ -102,7 +102,7 @@ dependencies {
implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-jdbc:2.0.2'
implementation 'software.amazon.awssdk:kms'
implementation 'com.amazonaws:aws-encryption-sdk-java:3.0.0'
implementation 'software.amazon.cryptography:aws-cryptographic-material-providers:1.2.0'
implementation 'software.amazon.cryptography:aws-cryptographic-material-providers:1.3.0'
implementation 'org.springframework.boot:spring-boot-starter-quartz'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1'
implementation 'com.slack.api:slack-app-backend:1.39.0'
Expand Down Expand Up @@ -149,15 +149,15 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'com.c4-soft.springaddons:spring-addons-oauth2-test:7.6.12'
testImplementation 'com.c4-soft.springaddons:spring-addons-oauth2-test:7.6.13'
testImplementation 'org.springframework.kafka:spring-kafka-test'
testImplementation 'org.apache.commons:commons-lang3:3.14.0'
testImplementation 'com.tngtech.archunit:archunit-junit5:1.2.2' // Architecture Rule Test
testImplementation 'com.navercorp.fixturemonkey:fixture-monkey-starter:1.0.15' // Test Double
testImplementation 'org.quickperf:quick-perf-junit5:1.1.0' // Performance Test
testImplementation 'io.karatelabs:karate-junit5:1.5.0.RC3' // Both Test Pyramid
testImplementation 'com.icegreen:greenmail-junit5:2.0.1'
testImplementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager:3.1.0'
testImplementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager'

testImplementation 'org.awaitility:awaitility:4.2.1'
testImplementation 'org.awaitility:awaitility-proxy:3.1.6'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.tune_fun.v1.account.adapter.output.persistence.device.DeviceJpaEntity;
import com.tune_fun.v1.account.adapter.output.persistence.oauth2.OAuth2AccountJpaEntity;
import com.tune_fun.v1.common.entity.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
Expand All @@ -28,9 +29,9 @@
public class AccountJpaEntity extends BaseEntity implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Tsid
@Column(name = "id", nullable = false, updatable = false)
@Comment("Sequence")
@Comment("TSID")
private Long id;

@Size(max = 255)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity;
import com.tune_fun.v1.common.entity.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
Expand All @@ -23,9 +24,9 @@
public class DeviceJpaEntity extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Tsid
@Column(name = "id", nullable = false, updatable = false)
@Comment("Sequence")
@Comment("TSID")
private Long id;

@Size(max = 255)
Expand Down Expand Up @@ -65,5 +66,5 @@ public final boolean equals(Object object) {
public final int hashCode() {
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity;
import com.tune_fun.v1.common.entity.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
Expand All @@ -24,9 +25,9 @@
public class OAuth2AccountJpaEntity extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Tsid
@Column(name = "id", nullable = false, updatable = false)
@Comment("Sequence")
@Comment("TSID")
private Long id;

@Size(max = 255)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.tune_fun.v1.common.response;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public interface BasePayload {
}
5 changes: 5 additions & 0 deletions src/main/java/com/tune_fun/v1/common/util/StringUtil.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tune_fun.v1.common.util;

import com.github.f4b6a3.ulid.UlidCreator;
import com.tune_fun.v1.common.constant.Constants;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.RandomStringUtils;
Expand Down Expand Up @@ -78,6 +79,10 @@ public static String uuid() {
return UUID.randomUUID().toString();
}

public static String ulid() {
return UlidCreator.getMonotonicUlid().toString();
}

public boolean hasText(String text) {
return StringUtils.hasText(text);
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/tune_fun/v1/external/aws/s3/S3Template.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ public ResponseBytes<GetObjectResponse> getObject(String s3BucketName, String ke
}

@NotNull
public String getKey(String rootPath, MultipartFile multipartFile) throws NoSuchAlgorithmException {
String generatedFileName = StringUtil.randomAlphanumeric(40);
public String getKey(String rootPath, MultipartFile multipartFile) {
String generatedFileName = StringUtil.ulid();
log.info("generated file name is {}", generatedFileName);

String extractedExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.tune_fun.v1.common.response.ResponseMapper;
import com.tune_fun.v1.vote.application.port.input.command.VotePaperCommands;
import com.tune_fun.v1.vote.application.port.input.usecase.*;
import com.tune_fun.v1.vote.domain.value.FullVotePaper;
import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
Expand All @@ -29,6 +30,8 @@ public class VotePaperController {

private final ScrollVotePaperUseCase scrollVotePaperUseCase;

private final GetVotePaperUseCase getVotePaperUseCase;

private final RegisterVotePaperUseCase registerVotePaperUseCase;
private final RegisterVoteChoiceUseCase registerVoteChoiceUseCase;

Expand All @@ -45,6 +48,13 @@ public ResponseEntity<Response<ScrollVotePaperResponse>> getVotePapers(@RequestP
return responseMapper.ok(MessageCode.SUCCESS, new ScrollVotePaperResponse(scrollableVotePapers));
}

@GetMapping(value = Uris.VOTE_PAPER_ROOT + "/{votePaperId}")
public ResponseEntity<Response<FullVotePaper>> getVotePaper(@PathVariable("votePaperId") @NotNull(message = "{vote.paper.id.not_null}") final Long votePaperId,
@CurrentUser final User user) {
FullVotePaper votePaper = getVotePaperUseCase.getVotePaper(votePaperId);
return responseMapper.ok(MessageCode.SUCCESS, votePaper);
}

// TODO : Follower 로직 구현 후 테스트 재진행 예정
@PreAuthorize("hasRole('ARTIST')")
@PostMapping(value = Uris.VOTE_PAPER_ROOT)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.tune_fun.v1.vote.adapter.output.persistence;

import com.tune_fun.v1.common.entity.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
Expand Down Expand Up @@ -29,9 +30,9 @@
public class VoteChoiceJpaEntity extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Tsid
@Column(name = "id", nullable = false, updatable = false)
@Comment("Sequence")
@Comment("TSID")
private Long id;

@Size(max = 255)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity;
import com.tune_fun.v1.common.entity.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
Expand All @@ -23,9 +24,9 @@
public class VoteJpaEntity extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Tsid
@Column(name = "id", nullable = false, updatable = false)
@Comment("Sequence")
@Comment("TSID")
private Long id;

@Size(max = 255)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
@Table(name = "vote_paper")
public class VotePaperJpaEntity extends BaseEntity {

// TODO : TSID Generation으로 변경 필요하나 DummyService.initVotePaperBatch()에서 사용하므로 일단 미적용
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, updatable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.tune_fun.v1.vote.domain.behavior.SaveVotePaper;
import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper;
import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper;
import com.tune_fun.v1.vote.domain.value.VotePaperOption;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public interface VotePaperRepository extends JpaRepository<VotePaperJpaEntity, L
@EntityGraph(attributePaths = {"author"})
Optional<VotePaperJpaEntity> findByVoteEndAtAfterAndAuthorUsernameAndEnabledTrue(LocalDateTime voteEndAt, String author);

@EntityGraph(attributePaths = {"author"})
Optional<VotePaperJpaEntity> findByVoteEndAtAfterAndIdAndEnabledTrue(LocalDateTime voteEndAt, Long id);

Optional<VotePaperJpaEntity> findByVoteEndAtBeforeAndIdAndEnabledTrue(LocalDateTime voteEndAt, Long id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.tune_fun.v1.vote.application.port.input.usecase;

import com.tune_fun.v1.vote.domain.value.FullVotePaper;

@FunctionalInterface
public interface GetVotePaperUseCase {

FullVotePaper getVotePaper(final Long votePaperId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.tune_fun.v1.vote.application.service;

import com.tune_fun.v1.common.exception.CommonApplicationException;
import com.tune_fun.v1.common.hexagon.UseCase;
import com.tune_fun.v1.vote.application.port.input.usecase.GetVotePaperUseCase;
import com.tune_fun.v1.vote.application.port.output.LoadVoteChoicePort;
import com.tune_fun.v1.vote.application.port.output.LoadVotePaperPort;
import com.tune_fun.v1.vote.domain.value.FullVotePaper;
import com.tune_fun.v1.vote.domain.value.RegisteredVoteChoice;
import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.tune_fun.v1.common.response.MessageCode.VOTE_PAPER_NOT_FOUND;

@Service
@UseCase
@RequiredArgsConstructor
public class GetVotePaperService implements GetVotePaperUseCase {

private final LoadVotePaperPort loadVotePaperPort;
private final LoadVoteChoicePort loadVoteChoicePort;

private final VoteValueMapper voteValueMapper;


@Override
public FullVotePaper getVotePaper(final Long votePaperId) {
RegisteredVotePaper registeredVotePaper = loadVotePaperPort.loadRegisteredVotePaper(votePaperId)
.orElseThrow(() -> new CommonApplicationException(VOTE_PAPER_NOT_FOUND));
List<RegisteredVoteChoice> registeredVoteChoices = loadVoteChoicePort.loadRegisteredVoteChoice(votePaperId);

return voteValueMapper.fullVotePaper(registeredVotePaper, registeredVoteChoices);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.tune_fun.v1.vote.application.service;

import com.tune_fun.v1.common.config.BaseMapperConfig;
import com.tune_fun.v1.vote.domain.value.FullVotePaper;
import com.tune_fun.v1.vote.domain.value.RegisteredVoteChoice;
import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import java.util.List;

@Mapper(config = BaseMapperConfig.class)
public abstract class VoteValueMapper {

@Mapping(target = "id", source = "votePaper.id")
@Mapping(target = "uuid", source = "votePaper.uuid")
@Mapping(target = "author", source = "votePaper.author")
@Mapping(target = "authorUsername", source = "votePaper.authorUsername")
@Mapping(target = "title", source = "votePaper.title")
@Mapping(target = "content", source = "votePaper.content")
@Mapping(target = "option", source = "votePaper.option")
@Mapping(target = "videoUrl", source = "votePaper.videoUrl")
@Mapping(target = "voteStartAt", source = "votePaper.voteStartAt")
@Mapping(target = "voteEndAt", source = "votePaper.voteEndAt")
@Mapping(target = "deliveryAt", source = "votePaper.deliveryAt")
@Mapping(target = "createdAt", source = "votePaper.createdAt")
@Mapping(target = "updatedAt", source = "votePaper.updatedAt")
@Mapping(target = "choices", source = "voteChoices")
public abstract FullVotePaper fullVotePaper(final RegisteredVotePaper votePaper, final List<RegisteredVoteChoice> voteChoices);

}
8 changes: 8 additions & 0 deletions src/main/java/com/tune_fun/v1/vote/domain/value/Choice.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.tune_fun.v1.vote.domain.value;

public record Choice(
Long id,
String music,
String artistName
) {
}
37 changes: 37 additions & 0 deletions src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.tune_fun.v1.vote.domain.value;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.tune_fun.v1.common.response.BasePayload;

import java.time.LocalDateTime;
import java.util.Set;

public record FullVotePaper(
Long id,
String uuid,
String author,
String authorUsername,
String title,
String content,
VotePaperOption option,
String videoUrl,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime voteStartAt,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime voteEndAt,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime deliveryAt,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createdAt,

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime updatedAt,

Set<RegisteredVoteChoice> choices
) implements BasePayload {

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.tune_fun.v1.vote.domain.value;

import com.tune_fun.v1.common.response.BasePayload;

import java.util.Set;

public record RegisteredVoteChoice(
Expand All @@ -10,5 +12,5 @@ public record RegisteredVoteChoice(
Set<String> genres,
String releaseDate,
Integer durationMs
) {
) implements BasePayload {
}
Loading

0 comments on commit 4152963

Please sign in to comment.