From 890b21f4abe5d196ad06d91ee6d95c1642eb2e1a Mon Sep 17 00:00:00 2001 From: YONGWOOK CHOI <60510921+CYY1007@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:31:32 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A8=20Hotfix/165=20refresh=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=8C=80=EC=9D=91=20?= =?UTF-8?q?(#166)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :sparkles: Feat: 캐시 무효화 정책 추가 (브리핑 등록, 수정 시) (#159) * Refactor/161 : Facade 도입 & 클래스 의존관계 개선 (#162) * :recycle: Refactor: Briefing V1 Facade 도입 * :recycle: Refactor: Briefing V2 API Facade 추가 * Update README.md * :bug: Hotfix : refresh token 관련 에러에 대비해 우선적으로 브리핑 목록 인증 대상에서 제거 --------- Co-authored-by: SeongHoon Jeong --- README.md | 1 + .../briefing/base/QBaseDateTimeEntity.java | 39 --------- .../briefing/briefing/domain/QArticle.java | 51 ------------ .../briefing/briefing/domain/QBriefing.java | 62 -------------- .../briefing/domain/QBriefingArticle.java | 62 -------------- .../briefing/member/domain/QMember.java | 60 -------------- .../briefing/scrap/domain/QScrap.java | 62 -------------- .../briefing/briefing/api/BriefingApi.java | 44 +++------- .../briefing/briefing/api/BriefingV2Api.java | 33 +------- .../application/BriefingCommandService.java | 53 ------------ .../briefing/application/BriefingFacade.java | 82 +++++++++++++++++++ .../application/BriefingV2Facade.java | 47 +++++++++++ .../service/ArticleCommandService.java | 19 +++++ .../BriefingArticleCommandService.java | 19 +++++ .../service/BriefingCommandService.java | 24 ++++++ .../{ => service}/BriefingQueryService.java | 4 +- .../security/config/SecurityConfig.java | 2 +- .../application/BriefingQueryServiceTest.java | 1 + 18 files changed, 209 insertions(+), 456 deletions(-) delete mode 100644 src/main/generated/briefing/base/QBaseDateTimeEntity.java delete mode 100644 src/main/generated/briefing/briefing/domain/QArticle.java delete mode 100644 src/main/generated/briefing/briefing/domain/QBriefing.java delete mode 100644 src/main/generated/briefing/briefing/domain/QBriefingArticle.java delete mode 100644 src/main/generated/briefing/member/domain/QMember.java delete mode 100644 src/main/generated/briefing/scrap/domain/QScrap.java delete mode 100644 src/main/java/briefing/briefing/application/BriefingCommandService.java create mode 100644 src/main/java/briefing/briefing/application/BriefingFacade.java create mode 100644 src/main/java/briefing/briefing/application/BriefingV2Facade.java create mode 100644 src/main/java/briefing/briefing/application/service/ArticleCommandService.java create mode 100644 src/main/java/briefing/briefing/application/service/BriefingArticleCommandService.java create mode 100644 src/main/java/briefing/briefing/application/service/BriefingCommandService.java rename src/main/java/briefing/briefing/application/{ => service}/BriefingQueryService.java (90%) diff --git a/README.md b/README.md index 43ddd9f..5a4efaa 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ - [[Briefing] Spotless로 코드 포맷 유지하기](https://poisson-it.tistory.com/77) - [[Briefing] Spring Security - Swagger 로그인 적용하기](https://ddol-dev-blog.tistory.com/3) - [[Briefing] API 응답 캐싱을 통한 조회 속도 개선](https://poisson-it.tistory.com/78) +- [[Briefing] Facade로 계층 구조 개선하기](https://poisson-it.tistory.com/79)
diff --git a/src/main/generated/briefing/base/QBaseDateTimeEntity.java b/src/main/generated/briefing/base/QBaseDateTimeEntity.java deleted file mode 100644 index 55211cf..0000000 --- a/src/main/generated/briefing/base/QBaseDateTimeEntity.java +++ /dev/null @@ -1,39 +0,0 @@ -package briefing.base; - -import static com.querydsl.core.types.PathMetadataFactory.*; - -import com.querydsl.core.types.dsl.*; - -import com.querydsl.core.types.PathMetadata; -import javax.annotation.processing.Generated; -import com.querydsl.core.types.Path; - - -/** - * QBaseDateTimeEntity is a Querydsl query type for BaseDateTimeEntity - */ -@Generated("com.querydsl.codegen.DefaultSupertypeSerializer") -public class QBaseDateTimeEntity extends EntityPathBase { - - private static final long serialVersionUID = 1261212710L; - - public static final QBaseDateTimeEntity baseDateTimeEntity = new QBaseDateTimeEntity("baseDateTimeEntity"); - - public final DateTimePath createdAt = createDateTime("createdAt", java.time.LocalDateTime.class); - - public final DateTimePath updatedAt = createDateTime("updatedAt", java.time.LocalDateTime.class); - - public QBaseDateTimeEntity(String variable) { - super(BaseDateTimeEntity.class, forVariable(variable)); - } - - public QBaseDateTimeEntity(Path path) { - super(path.getType(), path.getMetadata()); - } - - public QBaseDateTimeEntity(PathMetadata metadata) { - super(BaseDateTimeEntity.class, metadata); - } - -} - diff --git a/src/main/generated/briefing/briefing/domain/QArticle.java b/src/main/generated/briefing/briefing/domain/QArticle.java deleted file mode 100644 index db837a2..0000000 --- a/src/main/generated/briefing/briefing/domain/QArticle.java +++ /dev/null @@ -1,51 +0,0 @@ -package briefing.briefing.domain; - -import static com.querydsl.core.types.PathMetadataFactory.*; - -import com.querydsl.core.types.dsl.*; - -import com.querydsl.core.types.PathMetadata; -import javax.annotation.processing.Generated; -import com.querydsl.core.types.Path; - - -/** - * QArticle is a Querydsl query type for Article - */ -@Generated("com.querydsl.codegen.DefaultEntitySerializer") -public class QArticle extends EntityPathBase
{ - - private static final long serialVersionUID = -598074260L; - - public static final QArticle article = new QArticle("article"); - - public final briefing.base.QBaseDateTimeEntity _super = new briefing.base.QBaseDateTimeEntity(this); - - //inherited - public final DateTimePath createdAt = _super.createdAt; - - public final NumberPath id = createNumber("id", Long.class); - - public final StringPath press = createString("press"); - - public final StringPath title = createString("title"); - - //inherited - public final DateTimePath updatedAt = _super.updatedAt; - - public final StringPath url = createString("url"); - - public QArticle(String variable) { - super(Article.class, forVariable(variable)); - } - - public QArticle(Path path) { - super(path.getType(), path.getMetadata()); - } - - public QArticle(PathMetadata metadata) { - super(Article.class, metadata); - } - -} - diff --git a/src/main/generated/briefing/briefing/domain/QBriefing.java b/src/main/generated/briefing/briefing/domain/QBriefing.java deleted file mode 100644 index 1169e07..0000000 --- a/src/main/generated/briefing/briefing/domain/QBriefing.java +++ /dev/null @@ -1,62 +0,0 @@ -package briefing.briefing.domain; - -import static com.querydsl.core.types.PathMetadataFactory.*; - -import com.querydsl.core.types.dsl.*; - -import com.querydsl.core.types.PathMetadata; -import javax.annotation.processing.Generated; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.dsl.PathInits; - - -/** - * QBriefing is a Querydsl query type for Briefing - */ -@Generated("com.querydsl.codegen.DefaultEntitySerializer") -public class QBriefing extends EntityPathBase { - - private static final long serialVersionUID = 63849586L; - - public static final QBriefing briefing = new QBriefing("briefing"); - - public final briefing.base.QBaseDateTimeEntity _super = new briefing.base.QBaseDateTimeEntity(this); - - public final ListPath briefingArticles = this.createList("briefingArticles", BriefingArticle.class, QBriefingArticle.class, PathInits.DIRECT2); - - public final StringPath content = createString("content"); - - //inherited - public final DateTimePath createdAt = _super.createdAt; - - public final EnumPath gptModel = createEnum("gptModel", briefing.common.enums.GptModel.class); - - public final NumberPath id = createNumber("id", Long.class); - - public final NumberPath ranks = createNumber("ranks", Integer.class); - - public final StringPath subtitle = createString("subtitle"); - - public final EnumPath timeOfDay = createEnum("timeOfDay", TimeOfDay.class); - - public final StringPath title = createString("title"); - - public final EnumPath type = createEnum("type", BriefingType.class); - - //inherited - public final DateTimePath updatedAt = _super.updatedAt; - - public QBriefing(String variable) { - super(Briefing.class, forVariable(variable)); - } - - public QBriefing(Path path) { - super(path.getType(), path.getMetadata()); - } - - public QBriefing(PathMetadata metadata) { - super(Briefing.class, metadata); - } - -} - diff --git a/src/main/generated/briefing/briefing/domain/QBriefingArticle.java b/src/main/generated/briefing/briefing/domain/QBriefingArticle.java deleted file mode 100644 index fb3152a..0000000 --- a/src/main/generated/briefing/briefing/domain/QBriefingArticle.java +++ /dev/null @@ -1,62 +0,0 @@ -package briefing.briefing.domain; - -import static com.querydsl.core.types.PathMetadataFactory.*; - -import com.querydsl.core.types.dsl.*; - -import com.querydsl.core.types.PathMetadata; -import javax.annotation.processing.Generated; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.dsl.PathInits; - - -/** - * QBriefingArticle is a Querydsl query type for BriefingArticle - */ -@Generated("com.querydsl.codegen.DefaultEntitySerializer") -public class QBriefingArticle extends EntityPathBase { - - private static final long serialVersionUID = 37002276L; - - private static final PathInits INITS = PathInits.DIRECT2; - - public static final QBriefingArticle briefingArticle = new QBriefingArticle("briefingArticle"); - - public final briefing.base.QBaseDateTimeEntity _super = new briefing.base.QBaseDateTimeEntity(this); - - public final QArticle article; - - public final QBriefing briefing; - - //inherited - public final DateTimePath createdAt = _super.createdAt; - - public final NumberPath id = createNumber("id", Long.class); - - //inherited - public final DateTimePath updatedAt = _super.updatedAt; - - public QBriefingArticle(String variable) { - this(BriefingArticle.class, forVariable(variable), INITS); - } - - public QBriefingArticle(Path path) { - this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); - } - - public QBriefingArticle(PathMetadata metadata) { - this(metadata, PathInits.getFor(metadata, INITS)); - } - - public QBriefingArticle(PathMetadata metadata, PathInits inits) { - this(BriefingArticle.class, metadata, inits); - } - - public QBriefingArticle(Class type, PathMetadata metadata, PathInits inits) { - super(type, metadata, inits); - this.article = inits.isInitialized("article") ? new QArticle(forProperty("article")) : null; - this.briefing = inits.isInitialized("briefing") ? new QBriefing(forProperty("briefing")) : null; - } - -} - diff --git a/src/main/generated/briefing/member/domain/QMember.java b/src/main/generated/briefing/member/domain/QMember.java deleted file mode 100644 index 1f80880..0000000 --- a/src/main/generated/briefing/member/domain/QMember.java +++ /dev/null @@ -1,60 +0,0 @@ -package briefing.member.domain; - -import static com.querydsl.core.types.PathMetadataFactory.*; - -import com.querydsl.core.types.dsl.*; - -import com.querydsl.core.types.PathMetadata; -import javax.annotation.processing.Generated; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.dsl.PathInits; - - -/** - * QMember is a Querydsl query type for Member - */ -@Generated("com.querydsl.codegen.DefaultEntitySerializer") -public class QMember extends EntityPathBase { - - private static final long serialVersionUID = 2051544022L; - - public static final QMember member = new QMember("member1"); - - public final briefing.base.QBaseDateTimeEntity _super = new briefing.base.QBaseDateTimeEntity(this); - - //inherited - public final DateTimePath createdAt = _super.createdAt; - - public final NumberPath id = createNumber("id", Long.class); - - public final StringPath nickName = createString("nickName"); - - public final StringPath profileImgUrl = createString("profileImgUrl"); - - public final EnumPath role = createEnum("role", MemberRole.class); - - public final ListPath scrapList = this.createList("scrapList", briefing.scrap.domain.Scrap.class, briefing.scrap.domain.QScrap.class, PathInits.DIRECT2); - - public final StringPath socialId = createString("socialId"); - - public final EnumPath socialType = createEnum("socialType", SocialType.class); - - public final EnumPath status = createEnum("status", MemberStatus.class); - - //inherited - public final DateTimePath updatedAt = _super.updatedAt; - - public QMember(String variable) { - super(Member.class, forVariable(variable)); - } - - public QMember(Path path) { - super(path.getType(), path.getMetadata()); - } - - public QMember(PathMetadata metadata) { - super(Member.class, metadata); - } - -} - diff --git a/src/main/generated/briefing/scrap/domain/QScrap.java b/src/main/generated/briefing/scrap/domain/QScrap.java deleted file mode 100644 index 13e31f8..0000000 --- a/src/main/generated/briefing/scrap/domain/QScrap.java +++ /dev/null @@ -1,62 +0,0 @@ -package briefing.scrap.domain; - -import static com.querydsl.core.types.PathMetadataFactory.*; - -import com.querydsl.core.types.dsl.*; - -import com.querydsl.core.types.PathMetadata; -import javax.annotation.processing.Generated; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.dsl.PathInits; - - -/** - * QScrap is a Querydsl query type for Scrap - */ -@Generated("com.querydsl.codegen.DefaultEntitySerializer") -public class QScrap extends EntityPathBase { - - private static final long serialVersionUID = -881090678L; - - private static final PathInits INITS = PathInits.DIRECT2; - - public static final QScrap scrap = new QScrap("scrap"); - - public final briefing.base.QBaseDateTimeEntity _super = new briefing.base.QBaseDateTimeEntity(this); - - public final briefing.briefing.domain.QBriefing briefing; - - //inherited - public final DateTimePath createdAt = _super.createdAt; - - public final NumberPath id = createNumber("id", Long.class); - - public final briefing.member.domain.QMember member; - - //inherited - public final DateTimePath updatedAt = _super.updatedAt; - - public QScrap(String variable) { - this(Scrap.class, forVariable(variable), INITS); - } - - public QScrap(Path path) { - this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); - } - - public QScrap(PathMetadata metadata) { - this(metadata, PathInits.getFor(metadata, INITS)); - } - - public QScrap(PathMetadata metadata, PathInits inits) { - this(Scrap.class, metadata, inits); - } - - public QScrap(Class type, PathMetadata metadata, PathInits inits) { - super(type, metadata, inits); - this.briefing = inits.isInitialized("briefing") ? new briefing.briefing.domain.QBriefing(forProperty("briefing")) : null; - this.member = inits.isInitialized("member") ? new briefing.member.domain.QMember(forProperty("member")) : null; - } - -} - diff --git a/src/main/java/briefing/briefing/api/BriefingApi.java b/src/main/java/briefing/briefing/api/BriefingApi.java index ed6fc1f..02c01dd 100644 --- a/src/main/java/briefing/briefing/api/BriefingApi.java +++ b/src/main/java/briefing/briefing/api/BriefingApi.java @@ -1,22 +1,17 @@ package briefing.briefing.api; -import java.util.List; -import java.util.Optional; - import jakarta.validation.Valid; import org.springdoc.core.annotations.ParameterObject; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; -import briefing.briefing.application.BriefingCommandService; -import briefing.briefing.application.BriefingQueryService; +import briefing.briefing.application.BriefingFacade; import briefing.briefing.application.dto.*; -import briefing.briefing.domain.Briefing; -import briefing.common.enums.APIVersion; +import briefing.common.aop.annotation.CacheEvictByBriefingId; import briefing.common.response.CommonResponse; import briefing.member.domain.Member; -import briefing.scrap.application.ScrapQueryService; import briefing.security.handler.annotation.AuthMember; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -28,19 +23,14 @@ @RequiredArgsConstructor public class BriefingApi { - private final BriefingQueryService briefingQueryService; - private final BriefingCommandService briefingCommandService; - private final ScrapQueryService scrapQueryService; + private final BriefingFacade briefingFacade; @GetMapping("/briefings") @Parameter(name = "timeOfDay", hidden = true) @Operation(summary = "03-01Briefing \uD83D\uDCF0 브리핑 목록 조회 V1", description = "") public CommonResponse findBriefings( @ParameterObject @ModelAttribute BriefingRequestParam.BriefingPreviewListParam params) { - - List briefingList = briefingQueryService.findBriefings(params, APIVersion.V1); - return CommonResponse.onSuccess( - BriefingConverter.toBriefingPreviewListDTO(params.getDate(), briefingList)); + return CommonResponse.onSuccess(briefingFacade.findBriefings(params)); } @GetMapping("/briefings/{id}") @@ -48,28 +38,15 @@ public CommonResponse findBriefings( @Operation(summary = "03-02Briefing \uD83D\uDCF0 브리핑 단건 조회 V1", description = "") public CommonResponse findBriefing( @PathVariable final Long id, @AuthMember Member member) { - - Boolean isScrap = - Optional.ofNullable(member) - .map(m -> scrapQueryService.existsByMemberIdAndBriefingId(m.getId(), id)) - .orElseGet(() -> Boolean.FALSE); - - Boolean isBriefingOpen = false; - Boolean isWarning = false; - - return CommonResponse.onSuccess( - BriefingConverter.toBriefingDetailDTO( - briefingQueryService.findBriefing(id, APIVersion.V1), - isScrap, - isBriefingOpen, - isWarning)); + return CommonResponse.onSuccess(briefingFacade.findBriefing(id, member)); } + @CacheEvict(value = "findBriefingsV2", key = "#request.getBriefingType()") @PostMapping("/briefings") @ResponseStatus(HttpStatus.CREATED) @Operation(summary = "03-03Briefing \uD83D\uDCF0 브리핑 등록", description = "") public void createBriefing(@RequestBody final BriefingRequestDTO.BriefingCreate request) { - briefingCommandService.createBriefing(request); + briefingFacade.createBriefing(request); } /* @@ -82,14 +59,13 @@ public void createBriefing(@RequestBody final BriefingRequestDTO.BriefingCreate * @param id, BriefingResponseDTO.BriefingUpdateDTO * @return 수정된 값, 요청으로 온 값과 동일 */ + @CacheEvictByBriefingId(value = "findBriefingsV2", briefingId = "#id") @Operation(summary = "03-04Briefing \uD83D\uDCF0 브리핑 내용 수정", description = "") @Parameter(name = "id", description = "브리핑 아이디", example = "1") @PatchMapping("/briefings/{id}") public CommonResponse patchBriefingContent( @PathVariable(name = "id") Long id, @RequestBody @Valid BriefingRequestDTO.BriefingUpdateDTO request) { - - Briefing briefing = briefingCommandService.updateBriefing(id, request); - return CommonResponse.onSuccess(BriefingConverter.toBriefingUpdateDTO(briefing)); + return CommonResponse.onSuccess(briefingFacade.updateBriefing(id, request)); } } diff --git a/src/main/java/briefing/briefing/api/BriefingV2Api.java b/src/main/java/briefing/briefing/api/BriefingV2Api.java index b887e5f..bfe3d21 100644 --- a/src/main/java/briefing/briefing/api/BriefingV2Api.java +++ b/src/main/java/briefing/briefing/api/BriefingV2Api.java @@ -1,21 +1,14 @@ package briefing.briefing.api; -import java.util.List; -import java.util.Optional; - import org.springdoc.core.annotations.ParameterObject; import org.springframework.cache.annotation.Cacheable; import org.springframework.web.bind.annotation.*; -import briefing.briefing.application.BriefingCommandService; -import briefing.briefing.application.BriefingQueryService; +import briefing.briefing.application.BriefingV2Facade; import briefing.briefing.application.dto.BriefingRequestParam; import briefing.briefing.application.dto.BriefingResponseDTO; -import briefing.briefing.domain.Briefing; -import briefing.common.enums.APIVersion; import briefing.common.response.CommonResponse; import briefing.member.domain.Member; -import briefing.scrap.application.ScrapQueryService; import briefing.security.handler.annotation.AuthMember; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -27,18 +20,14 @@ @RequiredArgsConstructor @RequestMapping("/v2") public class BriefingV2Api { - private final BriefingQueryService briefingQueryService; - private final BriefingCommandService briefingCommandService; - private final ScrapQueryService scrapQueryService; + private final BriefingV2Facade briefingFacade; @GetMapping("/briefings") @Operation(summary = "03-01Briefing \uD83D\uDCF0 브리핑 목록 조회 V2", description = "") @Cacheable(value = "findBriefingsV2", key = "#params.getType()") public CommonResponse findBriefingsV2( @ParameterObject @ModelAttribute BriefingRequestParam.BriefingPreviewListParam params) { - List briefingList = briefingQueryService.findBriefings(params, APIVersion.V2); - return CommonResponse.onSuccess( - BriefingConverter.toBriefingPreviewListDTOV2(params.getDate(), briefingList)); + return CommonResponse.onSuccess(briefingFacade.findBriefings(params)); } @GetMapping("/briefings/{id}") @@ -46,20 +35,6 @@ public CommonResponse findBriefing @Parameter(name = "member", hidden = true) public CommonResponse findBriefingV2( @PathVariable final Long id, @AuthMember Member member) { - - Boolean isScrap = - Optional.ofNullable(member) - .map(m -> scrapQueryService.existsByMemberIdAndBriefingId(m.getId(), id)) - .orElseGet(() -> Boolean.FALSE); - - Boolean isBriefingOpen = false; - Boolean isWarning = false; - - return CommonResponse.onSuccess( - BriefingConverter.toBriefingDetailDTOV2( - briefingQueryService.findBriefing(id, APIVersion.V2), - isScrap, - isBriefingOpen, - isWarning)); + return CommonResponse.onSuccess(briefingFacade.findBriefing(id, member)); } } diff --git a/src/main/java/briefing/briefing/application/BriefingCommandService.java b/src/main/java/briefing/briefing/application/BriefingCommandService.java deleted file mode 100644 index a0b5cca..0000000 --- a/src/main/java/briefing/briefing/application/BriefingCommandService.java +++ /dev/null @@ -1,53 +0,0 @@ -package briefing.briefing.application; - -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import briefing.briefing.api.BriefingConverter; -import briefing.briefing.application.dto.BriefingRequestDTO; -import briefing.briefing.domain.Article; -import briefing.briefing.domain.Briefing; -import briefing.briefing.domain.BriefingArticle; -import briefing.briefing.domain.repository.ArticleRepository; -import briefing.briefing.domain.repository.BriefingArticleRepository; -import briefing.briefing.domain.repository.BriefingRepository; -import briefing.exception.ErrorCode; -import briefing.exception.handler.BriefingException; -import lombok.RequiredArgsConstructor; - -@Service -@Transactional -@RequiredArgsConstructor -public class BriefingCommandService { - - private final BriefingRepository briefingRepository; - private final ArticleRepository articleRepository; - private final BriefingArticleRepository briefingArticleRepository; - - public void createBriefing(final BriefingRequestDTO.BriefingCreate request) { - final Briefing briefing = BriefingConverter.toBriefing(request); - final List
articles = - request.getArticles().stream().map(BriefingConverter::toArticle).toList(); - - briefingRepository.save(briefing); - articleRepository.saveAll(articles); - - final List briefingArticles = - articles.stream().map(article -> new BriefingArticle(briefing, article)).toList(); - briefingArticleRepository.saveAll(briefingArticles); - } - - public Briefing updateBriefing(Long id, final BriefingRequestDTO.BriefingUpdateDTO request) { - - Briefing briefing = - briefingRepository - .findById(id) - .orElseThrow(() -> new BriefingException(ErrorCode.NOT_FOUND_BRIEFING)); - - briefing.updateBriefing(request.getTitle(), request.getSubTitle(), request.getContent()); - - return briefing; - } -} diff --git a/src/main/java/briefing/briefing/application/BriefingFacade.java b/src/main/java/briefing/briefing/application/BriefingFacade.java new file mode 100644 index 0000000..0d947ff --- /dev/null +++ b/src/main/java/briefing/briefing/application/BriefingFacade.java @@ -0,0 +1,82 @@ +package briefing.briefing.application; + +import java.util.List; +import java.util.Optional; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import briefing.briefing.api.BriefingConverter; +import briefing.briefing.application.dto.BriefingRequestDTO; +import briefing.briefing.application.dto.BriefingRequestParam; +import briefing.briefing.application.dto.BriefingResponseDTO; +import briefing.briefing.application.service.ArticleCommandService; +import briefing.briefing.application.service.BriefingArticleCommandService; +import briefing.briefing.application.service.BriefingCommandService; +import briefing.briefing.application.service.BriefingQueryService; +import briefing.briefing.domain.Article; +import briefing.briefing.domain.Briefing; +import briefing.briefing.domain.BriefingArticle; +import briefing.common.enums.APIVersion; +import briefing.member.domain.Member; +import briefing.scrap.application.ScrapQueryService; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class BriefingFacade { + private final ScrapQueryService scrapQueryService; + private final BriefingQueryService briefingQueryService; + private final BriefingCommandService briefingCommandService; + private final ArticleCommandService articleCommandService; + private final BriefingArticleCommandService briefingArticleCommandService; + private static final APIVersion version = APIVersion.V1; + + @Transactional(readOnly = true) + public BriefingResponseDTO.BriefingPreviewListDTO findBriefings( + BriefingRequestParam.BriefingPreviewListParam params) { + List briefingList = briefingQueryService.findBriefings(params, version); + return BriefingConverter.toBriefingPreviewListDTO(params.getDate(), briefingList); + } + + @Transactional(readOnly = true) + public BriefingResponseDTO.BriefingDetailDTO findBriefing(final Long id, Member member) { + Boolean isScrap = + Optional.ofNullable(member) + .map(m -> scrapQueryService.existsByMemberIdAndBriefingId(m.getId(), id)) + .orElseGet(() -> Boolean.FALSE); + + Boolean isBriefingOpen = false; + Boolean isWarning = false; + + return BriefingConverter.toBriefingDetailDTO( + briefingQueryService.findBriefing(id, version), isScrap, isBriefingOpen, isWarning); + } + + @Transactional + public void createBriefing(final BriefingRequestDTO.BriefingCreate request) { + final List
articles = + request.getArticles().stream().map(BriefingConverter::toArticle).toList(); + + Briefing createdBriefing = + briefingCommandService.create(BriefingConverter.toBriefing(request)); + List
createdArticles = articleCommandService.createAll(articles); + + final List briefingArticles = + createdArticles.stream() + .map(article -> new BriefingArticle(createdBriefing, article)) + .toList(); + + briefingArticleCommandService.createAll(briefingArticles); + } + + @Transactional + public BriefingResponseDTO.BriefingUpdateDTO updateBriefing( + Long id, final BriefingRequestDTO.BriefingUpdateDTO request) { + Briefing briefing = briefingQueryService.findBriefing(id, APIVersion.V1); + Briefing updatedBriefing = + briefingCommandService.update( + briefing, request.getTitle(), request.getSubTitle(), request.getContent()); + return BriefingConverter.toBriefingUpdateDTO(updatedBriefing); + } +} diff --git a/src/main/java/briefing/briefing/application/BriefingV2Facade.java b/src/main/java/briefing/briefing/application/BriefingV2Facade.java new file mode 100644 index 0000000..0051bce --- /dev/null +++ b/src/main/java/briefing/briefing/application/BriefingV2Facade.java @@ -0,0 +1,47 @@ +package briefing.briefing.application; + +import java.util.List; +import java.util.Optional; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import briefing.briefing.api.BriefingConverter; +import briefing.briefing.application.dto.BriefingRequestParam; +import briefing.briefing.application.dto.BriefingResponseDTO; +import briefing.briefing.application.service.BriefingQueryService; +import briefing.briefing.domain.Briefing; +import briefing.common.enums.APIVersion; +import briefing.member.domain.Member; +import briefing.scrap.application.ScrapQueryService; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class BriefingV2Facade { + + private final BriefingQueryService briefingQueryService; + private final ScrapQueryService scrapQueryService; + private static final APIVersion version = APIVersion.V2; + + @Transactional(readOnly = true) + public BriefingResponseDTO.BriefingPreviewListDTOV2 findBriefings( + BriefingRequestParam.BriefingPreviewListParam params) { + List briefingList = briefingQueryService.findBriefings(params, version); + return BriefingConverter.toBriefingPreviewListDTOV2(params.getDate(), briefingList); + } + + @Transactional(readOnly = true) + public BriefingResponseDTO.BriefingDetailDTOV2 findBriefing(final Long id, Member member) { + Boolean isScrap = + Optional.ofNullable(member) + .map(m -> scrapQueryService.existsByMemberIdAndBriefingId(m.getId(), id)) + .orElseGet(() -> Boolean.FALSE); + + Boolean isBriefingOpen = false; + Boolean isWarning = false; + + return BriefingConverter.toBriefingDetailDTOV2( + briefingQueryService.findBriefing(id, version), isScrap, isBriefingOpen, isWarning); + } +} diff --git a/src/main/java/briefing/briefing/application/service/ArticleCommandService.java b/src/main/java/briefing/briefing/application/service/ArticleCommandService.java new file mode 100644 index 0000000..d60a183 --- /dev/null +++ b/src/main/java/briefing/briefing/application/service/ArticleCommandService.java @@ -0,0 +1,19 @@ +package briefing.briefing.application.service; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import briefing.briefing.domain.Article; +import briefing.briefing.domain.repository.ArticleRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ArticleCommandService { + private final ArticleRepository articleRepository; + + public List
createAll(final List
articles) { + return articleRepository.saveAll(articles); + } +} diff --git a/src/main/java/briefing/briefing/application/service/BriefingArticleCommandService.java b/src/main/java/briefing/briefing/application/service/BriefingArticleCommandService.java new file mode 100644 index 0000000..fb44963 --- /dev/null +++ b/src/main/java/briefing/briefing/application/service/BriefingArticleCommandService.java @@ -0,0 +1,19 @@ +package briefing.briefing.application.service; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import briefing.briefing.domain.BriefingArticle; +import briefing.briefing.domain.repository.BriefingArticleRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class BriefingArticleCommandService { + private final BriefingArticleRepository briefingArticleRepository; + + public List createAll(final List briefingArticles) { + return briefingArticleRepository.saveAll(briefingArticles); + } +} diff --git a/src/main/java/briefing/briefing/application/service/BriefingCommandService.java b/src/main/java/briefing/briefing/application/service/BriefingCommandService.java new file mode 100644 index 0000000..4d9f1ab --- /dev/null +++ b/src/main/java/briefing/briefing/application/service/BriefingCommandService.java @@ -0,0 +1,24 @@ +package briefing.briefing.application.service; + +import org.springframework.stereotype.Service; + +import briefing.briefing.domain.Briefing; +import briefing.briefing.domain.repository.BriefingRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class BriefingCommandService { + + private final BriefingRepository briefingRepository; + + public Briefing create(final Briefing briefing) { + return briefingRepository.save(briefing); + } + + public Briefing update( + Briefing briefing, final String title, final String subTitle, final String content) { + briefing.updateBriefing(title, subTitle, content); + return briefing; + } +} diff --git a/src/main/java/briefing/briefing/application/BriefingQueryService.java b/src/main/java/briefing/briefing/application/service/BriefingQueryService.java similarity index 90% rename from src/main/java/briefing/briefing/application/BriefingQueryService.java rename to src/main/java/briefing/briefing/application/service/BriefingQueryService.java index 931245a..1b90db0 100644 --- a/src/main/java/briefing/briefing/application/BriefingQueryService.java +++ b/src/main/java/briefing/briefing/application/service/BriefingQueryService.java @@ -1,9 +1,8 @@ -package briefing.briefing.application; +package briefing.briefing.application.service; import java.util.List; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import briefing.briefing.application.context.BriefingQueryContext; import briefing.briefing.application.context.BriefingQueryContextFactory; @@ -15,7 +14,6 @@ import lombok.RequiredArgsConstructor; @Service -@Transactional(readOnly = true) @RequiredArgsConstructor public class BriefingQueryService { diff --git a/src/main/java/briefing/security/config/SecurityConfig.java b/src/main/java/briefing/security/config/SecurityConfig.java index cf2b06c..7982ffa 100644 --- a/src/main/java/briefing/security/config/SecurityConfig.java +++ b/src/main/java/briefing/security/config/SecurityConfig.java @@ -83,7 +83,7 @@ public WebSecurityCustomizer webSecurityCustomizer() { "/v3/api-docs", "/v3/api-docs/**", "/docs/**", - "/briefings/temp"); + "/briefings/temp","/v2/**","/briefings/**"); } @Bean diff --git a/src/test/java/briefing/briefing/application/BriefingQueryServiceTest.java b/src/test/java/briefing/briefing/application/BriefingQueryServiceTest.java index ff0dba9..72e0c91 100644 --- a/src/test/java/briefing/briefing/application/BriefingQueryServiceTest.java +++ b/src/test/java/briefing/briefing/application/BriefingQueryServiceTest.java @@ -18,6 +18,7 @@ import org.springframework.test.context.jdbc.Sql; import org.springframework.test.context.jdbc.Sql.ExecutionPhase; +import briefing.briefing.application.service.BriefingQueryService; import briefing.briefing.domain.Article; import briefing.briefing.domain.Briefing; import briefing.briefing.domain.BriefingArticle;