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

[feature/post-service] 좋아요, soft delete로 변경 및 테스트코드 작성 #32

Merged
merged 14 commits into from
Mar 12, 2023
Merged
Show file tree
Hide file tree
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
15 changes: 15 additions & 0 deletions script.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
SET GLOBAL log_bin_trust_function_creators = 1;

CREATE FUNCTION `strip_tags`($str text) RETURNS text
BEGIN
DECLARE $start, $end INT DEFAULT 1;
LOOP
SET $start = LOCATE('<', $str, $start);
IF (!$start) THEN RETURN $str; END IF;
SET $end = LOCATE('>', $str, $start);
IF (!$end) THEN SET $end = $start; END IF;
SET $str = INSERT($str, $start, $end - $start + 1, "");
END LOOP;
END;

SET GLOBAL log_bin_trust_function_creators = 0;
57 changes: 57 additions & 0 deletions src/docs/asciidoc/ads-post.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
== 홍보 게시판 API

=== 1. 홍보 게시글 작성
==== Request
include::{snippets}/ads-post-create/http-request.adoc[]
==== Response
include::{snippets}/ads-post-create/http-response.adoc[]

`응답 데이터로 반환되는 값은 게시글의 PK 값입니다.`

=== 2. 홍보 게시글 조회
==== Request
include::{snippets}/ads-post-create/http-request.adoc[]
==== Response
include::{snippets}/ads-post-create/http-response.adoc[]

=== 3. 홍보 게시글 수정
==== Request
include::{snippets}/ads-post-update/http-request.adoc[]
==== Response
include::{snippets}/ads-post-update/http-response.adoc[]

=== 4. 홍보 게시글 삭제
==== Request
include::{snippets}/ads-post-delete/http-request.adoc[]
==== Response
include::{snippets}/ads-post-delete/http-response.adoc[]

=== 5. 홍보 게시글 검색
==== Request
include::{snippets}/ads-post-search-all/http-request.adoc[]
==== Response
include::{snippets}/ads-post-search-all/http-response.adoc[]

=== 6. 홍보 게시글 상세 조회
==== Request
include::{snippets}/ads-post-get-one/http-request.adoc[]
==== Response
include::{snippets}/ads-post-get-one/http-response.adoc[]

=== 7. 홍보 게시글 말머리 조회
==== Request
include::{snippets}/ads-post-category/http-request.adoc[]
==== Response
include::{snippets}/ads-post-category/http-response.adoc[]

=== 8. 홍보 게시글 임시저장 목록 조회
==== Request
include::{snippets}/ads-post-get-temporary/http-request.adoc[]
==== Response
include::{snippets}/ads-post-get-temporary/http-response.adoc[]

==== 9. 홍보 게시글 좋아요
==== Request
include::{snippets}/ads-post-love/http-request.adoc[]
==== Response
include::{snippets}/ads-post-love/http-response.adoc[]
6 changes: 4 additions & 2 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ ifndef::snippets[]
:java: {sources-root}/main/java
:java-test: {sources-root}/test/java
endif::[]
= API Document
= 주말의집 API 명세서
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toclevels: 5
:sectlinks:

include::user.adoc[]
include::user.adoc[]

include::ads-post.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import org.springframework.web.bind.annotation.*
class AdPostController(
val adsPostService: AdsPostService
) {

/**
* 홍보게시글 생성
*
* @author 이은비
* */
@Auth
@PostMapping
fun createPost(
Expand All @@ -29,8 +33,11 @@ class AdPostController(
) : ApplicationResponse<Long> {
return ApplicationResponse.ok(adsPostService.createPost(req, user))
}


/**
* 홍보게시글 수정 ( 임시저장 상태도 해당 API로 수정 )
*
* @author 이은비
* */
@Auth
@PutMapping("/{postId}")
fun updatePost(
Expand All @@ -40,7 +47,11 @@ class AdPostController(
) : ApplicationResponse<Long> {
return ApplicationResponse.ok(adsPostService.updatePost(postId, req, user))
}

/**
* 홍보게시글 삭제 ( soft delete 적용 )
*
* @author 이은비
* */
@Auth
@DeleteMapping("/{postId}")
fun deletePost(
Expand All @@ -50,29 +61,71 @@ class AdPostController(
adsPostService.deletePost(postId, user)
return ApplicationResponse.ok()
}

/**
* 홍보게시글 전체 조회 ( 페이징 처리 )
*
* @author 이은비
* */
@GetMapping
fun getPostAll() :ApplicationResponse<List<AdsPostResDto>> {
return ApplicationResponse.ok(adsPostService.getPostAll())
fun getPostAll(pageable: Pageable) :ApplicationResponse<Page<AdsPostResDto>> {
return ApplicationResponse.ok(adsPostService.getPostAll(pageable))
}

/**
* 홍보게시글 상세 조회
*
* @author 이은비
* */
@GetMapping("/{postId}")
fun getPostOne(
@PathVariable postId : Long
) : ApplicationResponse<AdsPostResDto> {
return ApplicationResponse.ok(adsPostService.getPostOne(postId))
}

/**
* 홍보게시글 검색 ( 페이징 처리 )
*
* @author 이은비
* */
@GetMapping("/search")
fun getPostAllCustom(
@RequestParam keyword: String,
pageable: Pageable
) : ApplicationResponse<Page<AdsPostListResDto>> {
return ApplicationResponse.ok(adsPostService.getPostAllByKeywordCustom(keyword, pageable))
}

/**
* 홍보게시글 말머리 조회 ( 영문코드, 코드명 )
*
* @author 이은비
* */
@GetMapping("/category")
fun getPostCategory() : ApplicationResponse<List<CodeResDto>> {
return ApplicationResponse.ok(adsPostService.getPostCategory())
}
/**
* 홍보게시글 좋아요 ( 작성자 포함 좋아요 클릭 가능 )
*
* @author 이은비
* */
@Auth
@PutMapping("/love/{postId}")
fun updatePostLove(
@PathVariable postId: Long,
@AuthUser user: User
) : ApplicationResponse<Long> {
return ApplicationResponse.ok(adsPostService.updatePostLove(postId, user))
}
/**
* 유저가 갖는 임시저장된 홍보게시글 목록 조회 ( 페이징 처리 )
*
* @author 이은비
* */
@Auth
@GetMapping("/temporary")
fun getTemporaryPostList(
@AuthUser user: User,
pageable: Pageable
) : ApplicationResponse<Page<AdsPostResDto>> {
return ApplicationResponse.ok(adsPostService.getTemporaryPostList(user, pageable))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ data class AdsPostCreateReqDto(
@field:NotNull(message = "게시글의 제목은 필수값입니다.")
val title : String? = null,
val imageUrls : List<String>,
@field:NotNull(message = "임시 저장 여부는 필수값입니다.")
//@field:NotNull(message = "임시 저장 여부는 필수값입니다.")
val isSaved : Boolean? = null,
@field:NotNull(message = "말머리는 필수값입니다.")
val category : AdsPostCategory? = null,
Expand All @@ -24,7 +24,7 @@ data class AdsPostUpdateReqDto(
@field:NotNull(message = "게시글의 제목은 필수값입니다.")
val title : String? = null,
val imageUrls : List<String>,
@field:NotNull(message = "임시 저장 여부는 필수값입니다.")
// @field:NotNull(message = "임시 저장 여부는 필수값입니다.")
val isSaved : Boolean? = null,
@field:NotNull(message = "말머리는 필수값입니다.")
val category : String? = null,
Expand All @@ -34,6 +34,7 @@ data class AdsPostResDto(
val postId : Long,
val code : String,
val isFixed : Boolean,
val love : Int,
)

data class AdsPostListResDto(
Expand All @@ -45,15 +46,16 @@ data class AdsPostListResDto(
val createdAt : LocalDate,
val imageUrl : String,
val isFixed : Boolean,
val love : Int
)

fun toDto(adPost: AdPost) : AdsPostResDto {
return AdsPostResDto(adPost.id, adPost.code, adPost.isFixed)
return AdsPostResDto(adPost.id, adPost.code, adPost.isFixed, adPost.love)
}

fun toListDto(post: AdPost) : AdsPostListResDto {
return AdsPostListResDto(post.id, post.title, post.code, post.comment.size, post.user.nickName,
LocalDate.of(post.createdAt.year, post.createdAt.month, post.createdAt.dayOfMonth),
post.imageUrls[0], post.isFixed
post.imageUrls[0], post.isFixed, post.love
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class AdPost(
@OneToMany(mappedBy = "post", cascade = [CascadeType.ALL], orphanRemoval = true)
var comment: MutableList<Comment> = mutableListOf(),

var useYn : Boolean = true,

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0L
): BaseEntity() {
Expand All @@ -62,4 +64,13 @@ class AdPost(
this.isFixedAt = LocalDateTime.now()
return this
}

fun updateLove() : AdPost {
this.love ++;
return this
}

fun deleteEntity() {
this.useYn = false
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.jhouse_server.domain.ads.repository

import com.example.jhouse_server.domain.ads.entity.AdPost
import com.example.jhouse_server.domain.user.entity.User
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
Expand All @@ -12,4 +13,6 @@ interface AdsPostRepository : JpaRepository<AdPost, Long> {
value = "select * from ads_post where strip_tags(ads_post.code) like concat('%', :keyword, '%')",
countQuery = "select count(*) from ads_post")
fun findAllByKeywordCustom(keyword: String, pageable: Pageable) : Page<AdPost>
fun findAllByIsSavedAndUseYn(isSaved : Boolean, useYn : Boolean, pageable: Pageable) : Page<AdPost>
fun findAllByIsSavedAndUseYnAndUser(isSaved : Boolean, useYn : Boolean, user : User, pageable: Pageable) : Page<AdPost>
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable

interface AdsPostService {
fun getPostAll() : List<AdsPostResDto>
fun getPostAll(pageable: Pageable): Page<AdsPostResDto>
fun getPostOne(postId : Long) : AdsPostResDto
fun updatePost(postId: Long, req : AdsPostUpdateReqDto, user : User) : Long
fun createPost(req: AdsPostCreateReqDto, user: User) : Long
fun deletePost(postId : Long, user: User)
fun getPostAllByKeywordCustom(keyword: String, pageable: Pageable) : Page<AdsPostListResDto>
fun fixPost(postId : Long, user: User) : Long
fun getPostCategory(): List<CodeResDto>
fun updatePostLove(postId: Long, user: User): Long
fun getTemporaryPostList(user: User, pageable: Pageable): Page<AdsPostResDto>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.example.jhouse_server.domain.user.entity.Authority
import com.example.jhouse_server.domain.user.entity.User
import com.example.jhouse_server.global.exception.ApplicationException
import com.example.jhouse_server.global.exception.ErrorCode
import com.example.jhouse_server.global.findByIdOrThrow
import com.example.jhouse_server.global.util.findByIdOrThrow
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
Expand All @@ -20,8 +20,12 @@ import org.springframework.transaction.annotation.Transactional
class AdsPostServiceImpl(
val adsPostRepository: AdsPostRepository
): AdsPostService {
override fun getPostAll(): List<AdsPostResDto> {
return adsPostRepository.findAll().map { toDto(it) }
override fun getPostAll(pageable: Pageable): Page<AdsPostResDto> {
return adsPostRepository.findAllByIsSavedAndUseYn(
isSaved = true,
useYn = true,
pageable = pageable
).map { toDto(it) }
}

override fun getPostOne(postId: Long): AdsPostResDto {
Expand All @@ -32,19 +36,19 @@ class AdsPostServiceImpl(
override fun updatePost(postId: Long, req: AdsPostUpdateReqDto, user: User): Long {
val adPost = adsPostRepository.findByIdOrThrow(postId)
if(user != adPost.user) throw ApplicationException(ErrorCode.UNAUTHORIZED_EXCEPTION)
return adPost.updateEntity(req.code!!, req.title!!, req.category!!, req.imageUrls, req.isSaved!!).id
return adPost.updateEntity(req.code!!, req.title!!, req.category!!, req.imageUrls, req.isSaved ?: false).id
}
@Transactional
override fun createPost(req: AdsPostCreateReqDto, user: User): Long {
val adPost = AdPost(
req.code!!, req.title!!, req.category!!, req.imageUrls, req.isSaved!!, user
req.code!!, req.title!!, req.category!!, req.imageUrls, req.isSaved ?: false, user
)
return adsPostRepository.save(adPost).id
}
@Transactional
override fun deletePost(postId: Long, user: User) {
val adPost = adsPostRepository.findByIdOrThrow(postId)
if(user == adPost.user) adsPostRepository.delete(adPost)
if(user == adPost.user) adPost.deleteEntity()
else throw ApplicationException(ErrorCode.UNAUTHORIZED_EXCEPTION)
}

Expand All @@ -64,4 +68,14 @@ class AdsPostServiceImpl(
override fun getPostCategory(): List<CodeResDto> {
return AdsPostCategory.values().map { CodeResDto(it.value, it.name) }
}

@Transactional
override fun updatePostLove(postId: Long, user: User): Long {
val adPost = adsPostRepository.findByIdOrThrow(postId)
return adPost.updateLove().id
}

override fun getTemporaryPostList(user: User, pageable: Pageable): Page<AdsPostResDto> {
return adsPostRepository.findAllByIsSavedAndUseYnAndUser(isSaved = false, useYn = true, user, pageable).map { toDto(it) }
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.example.jhouse_server.domain.comment.service

import com.example.jhouse_server.domain.comment.entity.Comment
import com.example.jhouse_server.domain.comment.dto.CommentCreateReqDto
import com.example.jhouse_server.domain.comment.dto.CommentResDto
import com.example.jhouse_server.domain.comment.dto.CommentUpdateReqDto
import com.example.jhouse_server.domain.comment.dto.toDto
import com.example.jhouse_server.domain.comment.entity.Comment
import com.example.jhouse_server.domain.comment.repository.CommentRepository
import com.example.jhouse_server.domain.post.repository.PostRepository
import com.example.jhouse_server.domain.user.entity.User
import com.example.jhouse_server.domain.user.repository.UserRepository
import com.example.jhouse_server.global.exception.ApplicationException
import com.example.jhouse_server.global.exception.ErrorCode
import com.example.jhouse_server.global.findByIdOrThrow
import com.example.jhouse_server.global.util.findByIdOrThrow
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

Expand Down
Loading