Skip to content

Commit

Permalink
Merge pull request #1046 from BCSDLab/develop
Browse files Browse the repository at this point in the history
develop -> main
  • Loading branch information
seongjae6751 authored Nov 18, 2024
2 parents 06ffdf1 + 4e8179d commit 6fa6a3f
Show file tree
Hide file tree
Showing 116 changed files with 4,382 additions and 1,120 deletions.
2 changes: 2 additions & 0 deletions src/main/java/in/koreatech/koin/KoinApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
@ConfigurationPropertiesScan
@EnableCaching
public class KoinApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.data.repository.Repository;

import in.koreatech.koin.domain.benefit.model.BenefitCategoryMap;
import org.springframework.data.repository.query.Param;

public interface AdminBenefitCategoryMapRepository extends Repository<BenefitCategoryMap, Integer> {

Expand All @@ -19,21 +20,23 @@ public interface AdminBenefitCategoryMapRepository extends Repository<BenefitCat
WHERE bcm.benefitCategory.id = :benefitId
ORDER BY bcm.shop.name ASC
""")
List<BenefitCategoryMap> findAllByBenefitCategoryIdOrderByShopName(Integer benefitId);
List<BenefitCategoryMap> findAllByBenefitCategoryIdOrderByShopName(@Param("benefitId") Integer benefitId);

@Modifying
@Query("""
DELETE FROM BenefitCategoryMap bcm
WHERE bcm.benefitCategory.id = :benefitId
AND bcm.shop.id IN :shopIds
""")
void deleteByBenefitCategoryIdAndShopIds(Integer benefitId, List<Integer> shopIds);
void deleteByBenefitCategoryIdAndShopIds(
@Param("benefitId") Integer benefitId,
@Param("shopIds") List<Integer> shopIds);

@Modifying
@Query("""
DELETE FROM BenefitCategoryMap bcm
WHERE bcm.benefitCategory.id = :benefitId
""")
void deleteByBenefitCategoryId(Integer benefitId);
void deleteByBenefitCategoryId(@Param("benefitId") Integer benefitId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package in.koreatech.koin.admin.keyword.controller;

import static in.koreatech.koin.domain.user.model.UserType.ADMIN;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import in.koreatech.koin.admin.keyword.dto.AdminFilteredKeywordsResponse;
import in.koreatech.koin.admin.keyword.dto.AdminKeywordFilterRequest;
import in.koreatech.koin.global.auth.Auth;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;

@Tag(name = "(Admin) Keyword: 키워드", description = "키워드 알림 정보를 관리한다")
public interface AdminKeywordApi {

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
}
)
@Operation(summary = "키워드 필터링")
@PostMapping("/admin/articles/keyword/filter")
ResponseEntity<Void> toggleKeywordFilter(
@Valid @RequestBody AdminKeywordFilterRequest request,
@Auth(permit = {ADMIN}) Integer adminId
);

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
}
)
@Operation(summary = "필터링 된 키워드 조회")
@GetMapping("/admin/articles/keyword/filtered")
ResponseEntity<AdminFilteredKeywordsResponse> getFilteredKeywords(
@Auth(permit = {ADMIN}) Integer adminId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package in.koreatech.koin.admin.keyword.controller;

import static in.koreatech.koin.domain.user.model.UserType.ADMIN;

import org.springframework.http.ResponseEntity;
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.RestController;

import in.koreatech.koin.admin.keyword.service.AdminKeywordService;
import in.koreatech.koin.admin.keyword.dto.AdminFilteredKeywordsResponse;
import in.koreatech.koin.admin.keyword.dto.AdminKeywordFilterRequest;
import in.koreatech.koin.global.auth.Auth;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/admin/articles/keyword")
public class AdminKeywordController implements AdminKeywordApi {

private final AdminKeywordService adminKeywordService;

@PostMapping("/filter")
public ResponseEntity<Void> toggleKeywordFilter(
@Valid @RequestBody AdminKeywordFilterRequest request,
@Auth(permit = {ADMIN}) Integer adminId
) {
adminKeywordService.filterKeyword(request.keyword(), request.isFiltered());
return ResponseEntity.ok().build();
}

@GetMapping("/filtered")
public ResponseEntity<AdminFilteredKeywordsResponse> getFilteredKeywords(
@Auth(permit = {ADMIN}) Integer adminId
) {
AdminFilteredKeywordsResponse response = adminKeywordService.getFilteredKeywords();
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package in.koreatech.koin.admin.keyword.dto;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import java.util.List;

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

import in.koreatech.koin.domain.community.keyword.model.ArticleKeyword;
import io.swagger.v3.oas.annotations.media.Schema;

@JsonNaming(value = SnakeCaseStrategy.class)
public record AdminFilteredKeywordsResponse(
@Schema(description = "필터링된 키워드 목록", requiredMode = REQUIRED)
List<InnerFilteredKeywordResponse> keywords
) {

@JsonNaming(value = SnakeCaseStrategy.class)
public record InnerFilteredKeywordResponse(
@Schema(description = "키워드 내용", example = "[ㅇ, ㄴ라]", requiredMode = REQUIRED)
String keyword
) {

public static InnerFilteredKeywordResponse from(ArticleKeyword articleKeyword) {
return new InnerFilteredKeywordResponse(
articleKeyword.getKeyword()
);
}
}

public static AdminFilteredKeywordsResponse from(List<ArticleKeyword> filteredKeywords) {
return new AdminFilteredKeywordsResponse(
filteredKeywords.stream()
.map(InnerFilteredKeywordResponse::from)
.toList()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package in.koreatech.koin.admin.keyword.dto;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;

public record AdminKeywordFilterRequest(
@NotBlank(message = "키워드는 공백일 수 없습니다.")
@Schema(example = "키워드", description = "필터링 할 키워드 단어", requiredMode = REQUIRED)
String keyword,

@Schema(example = "true", description = "필터링 여부", requiredMode = REQUIRED)
Boolean isFiltered
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package in.koreatech.koin.admin.keyword.repository;

import java.util.List;
import java.util.Optional;

import org.springframework.data.repository.Repository;

import in.koreatech.koin.domain.community.keyword.exception.ArticleKeywordNotFoundException;
import in.koreatech.koin.domain.community.keyword.model.ArticleKeyword;

public interface AdminArticleKeywordRepository extends Repository<ArticleKeyword, Integer> {

Optional<ArticleKeyword> findByKeyword(String keyword);

default ArticleKeyword getByKeyword(String keyword) {
return findByKeyword(keyword)
.orElseThrow(() -> ArticleKeywordNotFoundException.withDetail("keyword : " + keyword));
}

List<ArticleKeyword> findByIsFiltered(boolean isFiltered);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package in.koreatech.koin.admin.keyword.service;

import java.util.List;
import java.util.Objects;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import in.koreatech.koin.admin.keyword.repository.AdminArticleKeywordRepository;
import in.koreatech.koin.admin.keyword.dto.AdminFilteredKeywordsResponse;
import in.koreatech.koin.domain.community.keyword.model.ArticleKeyword;
import in.koreatech.koin.global.exception.KoinIllegalArgumentException;
import lombok.RequiredArgsConstructor;

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

private final AdminArticleKeywordRepository adminArticleKeywordRepository;

@Transactional
public void filterKeyword(String keyword, Boolean isFiltered) {
ArticleKeyword articleKeyword = adminArticleKeywordRepository.getByKeyword(keyword);

if (Objects.equals(articleKeyword.getIsFiltered(), isFiltered)) {
String action = isFiltered ? "필터링 된" : "필터링이 취소된";
throw new KoinIllegalArgumentException("이미 " + action + " 키워드입니다: " + keyword);
}

articleKeyword.applyFiltered(isFiltered);
}

public AdminFilteredKeywordsResponse getFilteredKeywords() {
List<ArticleKeyword> filteredKeywords = adminArticleKeywordRepository.findByIsFiltered(true);
return AdminFilteredKeywordsResponse.from(filteredKeywords);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@

import in.koreatech.koin.domain.member.exception.MemberNotFoundException;
import in.koreatech.koin.domain.member.model.Member;
import org.springframework.data.repository.query.Param;

public interface AdminMemberRepository extends Repository<Member, Integer> {

@EntityGraph(attributePaths = {"track"})
@Query("select m from Member m where m.track.name = :trackName and m.isDeleted = :isDeleted")
Page<Member> findAllByTrackAndIsDeleted(String trackName, Boolean isDeleted, Pageable pageable);
Page<Member> findAllByTrackAndIsDeleted(
@Param("trackName") String trackName,
@Param("isDeleted") Boolean isDeleted,
Pageable pageable);

@EntityGraph(attributePaths = {"track"})
@Query("select count(m) from Member m where m.track.name = :trackName and m.isDeleted = :isDeleted")
Integer countAllByTrackAndIsDeleted(String trackName, Boolean isDeleted);
Integer countAllByTrackAndIsDeleted(
@Param("trackName") String trackName,
@Param("isDeleted") Boolean isDeleted);

Member save(Member member);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
import org.springframework.data.repository.Repository;

import in.koreatech.koin.domain.community.article.model.KoinArticle;
import org.springframework.data.repository.query.Param;

public interface AdminKoinArticleRepository extends Repository<KoinArticle, Integer> {

@Query(value = "SELECT * FROM new_koin_articles WHERE article_id = :noticeId", nativeQuery = true)
Optional<KoinArticle> findByArticleId(Integer noticeId);
Optional<KoinArticle> findByArticleId(@Param("noticeId") Integer noticeId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
import org.springframework.data.repository.Repository;

import in.koreatech.koin.domain.community.article.model.KoreatechArticle;
import org.springframework.data.repository.query.Param;

public interface AdminKoreatechArticleRepository extends Repository<KoreatechArticle, Integer> {

@Query(value = "SELECT * FROM new_koreatech_articles WHERE article_id = :noticeId", nativeQuery = true)
Optional<KoreatechArticle> findByArticleId(Integer noticeId);
Optional<KoreatechArticle> findByArticleId(@Param("noticeId") Integer noticeId);
}
Loading

0 comments on commit 6fa6a3f

Please sign in to comment.