Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
* 특정 유저의 회원 가입 시점을 저장하는 엔티티
* 이 엔티티는 유저의 회원 가입 이벤트를 기록하여, 나중에 회원 가입 이력을 추적할 수 있도록 합니다.
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/*
* 특정 회고의 답변 생성 시점을 저장하는 엔티티
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/*
* 특정 회고의 생성 시점을 저장하는 엔티티
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/*
* 특정 스페이스에 멤버가 참여한 시점을 저장하는 엔티티
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/*
* 특정 스페이스의 생성 시점을 저장하는 엔티티
* 이 엔티티는 스페이스의 생성 이벤트를 기록하여, 나중에 스페이스의 생성 이력을 추적할 수 있도록 합니다.
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.List;

import org.layer.admin.template.controller.dto.TemplateChoiceCountResponse;
import org.layer.admin.template.controller.dto.TemplateViewCountResponse;
import org.layer.admin.template.controller.dto.TemplateClickCountResponse;
import org.layer.admin.template.enums.AdminChoiceType;
import org.layer.admin.template.service.AdminTemplateService;
import org.springframework.http.ResponseEntity;
Expand All @@ -30,12 +30,12 @@ public ResponseEntity<List<TemplateChoiceCountResponse>> getTemplateChoiceTotalC
return ResponseEntity.ok().body(response);
}

@GetMapping("/admin/template/recommended-list-count")
public ResponseEntity<List<TemplateViewCountResponse>> getTemplateRecommendedListCount(
@GetMapping("/admin/template/click-count")
public ResponseEntity<List<TemplateClickCountResponse>> getTemplateClickCount(
@RequestParam(name = "startDate") LocalDateTime startDate,
@RequestParam(name = "endDate") LocalDateTime endDate
) {
List<TemplateViewCountResponse> responses = adminTemplateService.getTemplateRecommendedListCount(
List<TemplateClickCountResponse> responses = adminTemplateService.getTemplateClickCount(
startDate, endDate);

return ResponseEntity.ok().body(responses);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import org.layer.admin.template.enums.AdminChoiceType;

public record TemplateViewCountResponse(
public record TemplateClickCountResponse(
AdminChoiceType viewType,
long count
) {
public TemplateViewCountResponse(AdminChoiceType viewType, long count) {
public TemplateClickCountResponse(AdminChoiceType viewType, long count) {
this.viewType = viewType;
this.count = count;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
* 특정 유저의 템플릿 선택 이력을 저장하는 엔티티
* 이 엔티티는 유저가 템플릿을 선택한 시점과 관련된 정보를 기록하여, 나중에 템플릿 선택 이력을 추적할 수 있도록 합니다.
* 추천을 통해 선택된 템플릿은 AdminChoiceType.RECOMMENDATION으로, 목록에서 선택된 템플릿은 AdminChoiceType.LIST_VIEW로 저장됩니다.
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
* 특정 유저의 템플릿 클릭 이력을 저장하는 엔티티
* 이 엔티티는 유저가 [추천받기] 또는 [리스트 보기] 버튼을 클릭한 시점을 기록합니다.
*/
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class AdminTemplateViewHistory {
public class AdminTemplateClickHistory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Expand All @@ -38,7 +42,7 @@ public class AdminTemplateViewHistory {
private String eventId;

@Builder
private AdminTemplateViewHistory(AdminChoiceType viewType, LocalDateTime eventTime, Long memberId, String eventId) {
private AdminTemplateClickHistory(AdminChoiceType viewType, LocalDateTime eventTime, Long memberId, String eventId) {
this.viewType = viewType;
this.eventTime = eventTime;
this.memberId = memberId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import org.layer.admin.common.UserOnlyEventListener;
import org.layer.admin.template.service.AdminTemplateService;
import org.layer.event.template.TemplateListViewEvent;
import org.layer.event.template.TemplateListViewChoiceEvent;
import org.layer.event.template.TemplateListViewClickEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

Expand All @@ -15,7 +16,13 @@ public class TemplateListViewEventListener {

@UserOnlyEventListener
@EventListener
public void handleTemplateListView(TemplateListViewEvent event) {
adminTemplateService.saveTemplateListViewHistory(event);
public void handleTemplateListViewChoiceEvent(TemplateListViewChoiceEvent event) {
adminTemplateService.saveTemplateChoice(event);
}

@UserOnlyEventListener
@EventListener
public void handleTemplateListViewClickEvent(TemplateListViewClickEvent event) {
adminTemplateService.saveTemplateClickHistory(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import org.layer.admin.common.UserOnlyEventListener;
import org.layer.admin.template.service.AdminTemplateService;
import org.layer.event.template.TemplateRecommendedEvent;
import org.layer.event.template.TemplateRecommendedChoiceEvent;
import org.layer.event.template.TemplateRecommendedClickEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

Expand All @@ -15,8 +16,13 @@ public class TemplateRecommendedEventListener {

@UserOnlyEventListener
@EventListener
public void handleTemplateRecommended(TemplateRecommendedEvent event) {
adminTemplateService.saveTemplateRecommendation(event);
adminTemplateService.saveTemplateRecommendedViewHistory(event);
public void handleTemplateRecommendedChoiceEvent(TemplateRecommendedChoiceEvent event) {
adminTemplateService.saveTemplateChoice(event);
}

@UserOnlyEventListener
@EventListener
public void handleTemplateRecommendedClickEvent(TemplateRecommendedClickEvent event) {
adminTemplateService.saveTemplateClickHistory(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface AdminTemplateRecommendationRepository extends JpaRepository<AdminTemplateChoice, Long> {
public interface AdminTemplateChoiceRepository extends JpaRepository<AdminTemplateChoice, Long> {

@Query("SELECT new org.layer.admin.template.controller.dto.TemplateChoiceCountResponse(r.formTag, COUNT(r)) " +
"FROM AdminTemplateChoice r " +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.layer.admin.template.repository;

import java.time.LocalDateTime;
import java.util.List;

import org.layer.admin.template.controller.dto.TemplateClickCountResponse;
import org.layer.admin.template.entity.AdminTemplateClickHistory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface AdminTemplateClickHistoryRepository extends JpaRepository<AdminTemplateClickHistory, Long> {
@Query("SELECT new org.layer.admin.template.controller.dto.TemplateClickCountResponse(v.viewType, COUNT(v)) " +
"FROM AdminTemplateClickHistory v " +
"WHERE v.eventTime BETWEEN :startDate AND :endDate " +
"GROUP BY v.viewType ")
List<TemplateClickCountResponse> countByViewType(LocalDateTime startDate, LocalDateTime endDate);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
import java.util.List;

import org.layer.admin.template.controller.dto.TemplateChoiceCountResponse;
import org.layer.admin.template.controller.dto.TemplateViewCountResponse;
import org.layer.admin.template.controller.dto.TemplateClickCountResponse;
import org.layer.admin.template.entity.AdminTemplateChoice;
import org.layer.admin.template.entity.AdminTemplateViewHistory;
import org.layer.admin.template.entity.AdminTemplateClickHistory;
import org.layer.admin.template.enums.AdminFormTag;
import org.layer.admin.template.enums.AdminChoiceType;
import org.layer.admin.template.repository.AdminTemplateRecommendationRepository;
import org.layer.admin.template.repository.AdminTemplateViewHistoryRepository;
import org.layer.event.template.TemplateListViewEvent;
import org.layer.event.template.TemplateRecommendedEvent;
import org.layer.admin.template.repository.AdminTemplateChoiceRepository;
import org.layer.admin.template.repository.AdminTemplateClickHistoryRepository;
import org.layer.event.template.TemplateListViewChoiceEvent;
import org.layer.event.template.TemplateListViewClickEvent;
import org.layer.event.template.TemplateRecommendedChoiceEvent;
import org.layer.event.template.TemplateRecommendedClickEvent;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -26,62 +28,76 @@
@RequiredArgsConstructor
@Slf4j
public class AdminTemplateService {
private final AdminTemplateRecommendationRepository templateRecommendationRepository;
private final AdminTemplateViewHistoryRepository templateViewHistoryRepository;
private final AdminTemplateChoiceRepository templateChoiceRepository;
private final AdminTemplateClickHistoryRepository templateClickHistoryRepository;

public List<TemplateChoiceCountResponse> getTemplateChoiceCount(
LocalDateTime startDate, LocalDateTime endDate, AdminChoiceType choiceType) {

if( choiceType != null) {
return templateRecommendationRepository.countByChoiceType(startDate, endDate, choiceType);
if (choiceType != null) {
return templateChoiceRepository.countByChoiceType(startDate, endDate, choiceType);
}

return templateRecommendationRepository.countAll(startDate, endDate);
return templateChoiceRepository.countAll(startDate, endDate);
}

public List<TemplateViewCountResponse> getTemplateRecommendedListCount(
public List<TemplateClickCountResponse> getTemplateClickCount(
LocalDateTime startDate, LocalDateTime endDate) {

return templateViewHistoryRepository.countByViewType(startDate, endDate);
return templateClickHistoryRepository.countByViewType(startDate, endDate);
}

@Transactional(propagation = REQUIRES_NEW)
@Async
public void saveTemplateRecommendation(TemplateRecommendedEvent event) {
AdminTemplateChoice recommendation = AdminTemplateChoice.builder()
public void saveTemplateChoice(TemplateRecommendedChoiceEvent event) {
AdminTemplateChoice choice = AdminTemplateChoice.builder()
.formTag(AdminFormTag.from(event.formTag()))
.eventTime(event.eventTime())
.memberId(event.memberId())
.eventId(event.eventId())
.choiceType(AdminChoiceType.RECOMMENDATION)
.build();

templateRecommendationRepository.save(recommendation);
templateChoiceRepository.save(choice);
}

@Transactional(propagation = REQUIRES_NEW)
@Async
public void saveTemplateRecommendedViewHistory(TemplateRecommendedEvent event) {
AdminTemplateViewHistory viewHistory = AdminTemplateViewHistory.builder()
public void saveTemplateChoice(TemplateListViewChoiceEvent event) {
AdminTemplateChoice choice = AdminTemplateChoice.builder()
.formTag(AdminFormTag.from(event.formTag()))
.eventTime(event.eventTime())
.memberId(event.memberId())
.eventId(event.eventId())
.choiceType(AdminChoiceType.LIST_VIEW)
.build();

templateChoiceRepository.save(choice);
}

@Transactional(propagation = REQUIRES_NEW)
@Async
public void saveTemplateClickHistory(TemplateRecommendedClickEvent event) {
AdminTemplateClickHistory clickHistory = AdminTemplateClickHistory.builder()
.viewType(AdminChoiceType.RECOMMENDATION)
.eventTime(event.eventTime())
.memberId(event.memberId())
.eventId(event.eventId())
.build();

templateViewHistoryRepository.save(viewHistory);
templateClickHistoryRepository.save(clickHistory);
}

@Transactional(propagation = REQUIRES_NEW)
@Async
public void saveTemplateListViewHistory(TemplateListViewEvent event) {
AdminTemplateViewHistory viewHistory = AdminTemplateViewHistory.builder()
public void saveTemplateClickHistory(TemplateListViewClickEvent event) {
AdminTemplateClickHistory clickHistory = AdminTemplateClickHistory.builder()
.viewType(AdminChoiceType.LIST_VIEW)
.eventTime(event.eventTime())
.memberId(event.memberId())
.eventId(event.eventId())
.build();

templateViewHistoryRepository.save(viewHistory);
templateClickHistoryRepository.save(clickHistory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@
import org.layer.domain.space.repository.SpaceRepository;
import org.layer.domain.template.entity.TemplateMetadata;
import org.layer.domain.template.repository.TemplateMetadataRepository;
import org.layer.event.template.TemplateRecommendedEvent;
import org.layer.event.template.TemplateRecommendedChoiceEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;

import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -87,7 +86,7 @@ public RecommendFormResponseDto getRecommendTemplate(RecommendFormQueryDto query
Form form = formRepository.findByFormTagAndFormTypeOrThrow(recommandFormTag, FormType.TEMPLATE);
TemplateMetadata metadata = metadataRepository.findByFormIdOrThrow(form.getId());

eventPublisher.publishEvent(new TemplateRecommendedEvent(
eventPublisher.publishEvent(new TemplateRecommendedChoiceEvent(
customRandom.generateRandomValue(), memberId, recommandFormTag.getTag(), time.now()));

return RecommendFormResponseDto.of(form, metadata.getTemplateImageUrl());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.layer.domain.stats;

import org.layer.annotation.MemberId;
import org.layer.domain.form.enums.FormTag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestParam;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "[어드민] 템플릿 관련", description = "템플릿 관련한 어드민 기능 API")
public interface StatsTemplateApi {

@Operation(summary = "템플릿 리스트 보기 클릭 이벤트", description = "템플릿 리스트 보기를 클릭했을 때 해당 API를 호출합니다.")
ResponseEntity<Void> publishTemplateListViewClickEvent(@MemberId Long memberId);

@Operation(summary = "템플릿 리스트 보기 내에서 선택 이벤트", description = "템플릿 리스트에서 특정 템플릿을 선택했을 때 해당 API를 호출합니다.")
ResponseEntity<Void> publishTemplateListViewChoiceEvent(@MemberId Long memberId, @RequestParam FormTag formTag);

@Operation(summary = "템플릿 추천 클릭 이벤트", description = "템플릿 추천을 클릭했을 때 해당 API를 호출합니다.")
ResponseEntity<Void> publishTemplateRecommendedClickEvent(@MemberId Long memberId);
}
Loading
Loading