Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
42 changes: 42 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Build Docker Image

on:
push:
branches:
- main

permissions:
contents: read
packages: write

concurrency:
group: docker-image-main
cancel-in-progress: false

jobs:
docker:
name: Build and Push Docker Image
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and Push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
ghcr.io/slat-to/slat-to-be:${{ github.sha }}
ghcr.io/slat-to/slat-to-be:latest
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ out/
### Local Environment ###
.env
.env.*
.env.docker
!.env.example
application-local.yml
application-dev.yml
Expand Down
12 changes: 12 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
slatto:
image: ghcr.io/slat-to/slat-to-be:${IMAGE_TAG}
container_name: slatto-prod

env_file:
- /home/ubuntu/SLAT-TO-BE/.env.prod

ports:
- "8081:8080"

restart: unless-stopped
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
slatto:
build: .

env_file:
- .env.docker

ports:
- "8080:8080"
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.slatto.domain.feedback.dto.request.FeedbackDetailRequest.ReplyUpdateReqDTO;
import com.slatto.domain.feedback.dto.response.FeedbackDetailResponse.ReplyUpdateResDTO;
import com.slatto.domain.project.repository.ProjectMemberRepository;
import com.slatto.domain.notification.service.ActivityLogService;
import com.slatto.domain.feedback.dto.request.FeedbackDetailRequest.ReplyStatusReqDTO;
import com.slatto.domain.feedback.dto.response.FeedbackDetailResponse.ReplyStatusResDTO;
import org.springframework.data.domain.PageRequest;
Expand Down Expand Up @@ -38,6 +39,7 @@ public class FeedbackDetailService {
private final GuestRepository guestRepository;
private final FeedbackDetailConverter feedbackDetailConverter;
private final ProjectMemberRepository projectMemberRepository;
private final ActivityLogService activityLogService;

private static final int DEFAULT_PAGE_SIZE = 10;
private static final int MAX_PAGE_SIZE = 50; // 페이지 크기 상한
Expand Down Expand Up @@ -69,6 +71,22 @@ public ReplyCreateResDTO createReply(Long feedbackId, Long userId, ReplyCreateRe
FeedbackDetail reply = feedbackDetailConverter.toFeedbackDetail(feedback, user, guest, req);
FeedbackDetail saved = feedbackDetailRepository.save(reply);

if (user != null) {
activityLogService.createVideoFeedbackCommentedLog(
feedback.getVideo().getProject().getId(),
user.getId(),
feedback.getVideo().getId(),
feedback.getVideo().getTitle()
);
} else {
activityLogService.createGuestVideoFeedbackCommentedLog(
feedback.getVideo().getProject().getId(),
guest,
feedback.getVideo().getId(),
feedback.getVideo().getTitle()
);
}

return feedbackDetailConverter.toCreateResponse(saved);
}

Expand Down Expand Up @@ -224,4 +242,4 @@ public ReplyStatusResDTO changeReplyStatus(Long replyId, Long userId, ReplyStatu

return feedbackDetailConverter.toStatusResponse(reply);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.slatto.domain.feedback.dto.request.FeedbackRequest.FeedbackStatusReqDTO;
import com.slatto.domain.feedback.dto.response.FeedbackResponse.FeedbackStatusResDTO;
import com.slatto.domain.feedback.repository.FeedbackDetailRepository;
import com.slatto.domain.notification.service.ActivityLogService;
import com.slatto.domain.project.repository.ProjectMemberRepository;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -45,6 +46,7 @@ public class FeedbackService {
private final ObjectProvider<EntityManager> entityManagerProvider;
private final ProjectMemberRepository projectMemberRepository;
private final FeedbackDetailRepository feedbackDetailRepository;
private final ActivityLogService activityLogService;

private static final int DEFAULT_PAGE_SIZE = 10;
private static final int MAX_PAGE_SIZE = 50; // 페이지 크기 상한
Expand Down Expand Up @@ -80,6 +82,22 @@ public FeedbackCreateResDTO createFeedback(Long videoId, Long userId, FeedbackCr
Feedback feedback = feedbackConverter.toFeedback(video, user, guest, req);
Feedback saved = feedbackRepository.save(feedback);

if (user != null) {
activityLogService.createVideoFeedbackCommentedLog(
video.getProject().getId(),
user.getId(),
video.getId(),
video.getTitle()
);
} else {
activityLogService.createGuestVideoFeedbackCommentedLog(
video.getProject().getId(),
guest,
video.getId(),
video.getTitle()
);
}

return feedbackConverter.toCreateResponse(saved);
}

Expand Down Expand Up @@ -278,4 +296,4 @@ public FeedbackStatusResDTO changeFeedbackStatus(Long feedbackId, Long userId, F

return feedbackConverter.toStatusResponse(feedback);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.slatto.domain.notification.entity;

import com.slatto.domain.common.entity.BaseEntity;
import com.slatto.domain.project.entity.Project;
import com.slatto.domain.notification.enums.ActorType;
import com.slatto.domain.notification.enums.ActivityLogTargetType;
import com.slatto.domain.notification.enums.ActivityLogType;
import com.slatto.domain.notification.model.ActivityActor;
import com.slatto.domain.project.entity.Project;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
Expand Down Expand Up @@ -52,45 +54,41 @@ public class ActivityLog extends BaseEntity {

private ActivityLog(
Project project,
Long actorUserId,
Long actorGuestId,
ActorType actorType,
ActivityActor actor,
ActivityLogType type,
String content,
String targetType,
ActivityLogTargetType targetType,
Long targetId,
String groupKey
) {
this.project = project;
this.actorUserId = actorUserId;
this.actorGuestId = actorGuestId;
this.actorType = actorType;
this.actorUserId = actor.actorUserId();
this.actorGuestId = actor.actorGuestId();
this.actorType = actor.actorType();
this.type = type;
this.content = content;
this.targetType = targetType;
this.targetType = targetType != null ? targetType.name() : null;
this.targetId = targetId;
this.groupKey = groupKey;
}

public static ActivityLog create(
Project project,
Long actorUserId,
ActorType actorType,
ActivityActor actor,
ActivityLogType type,
String content,
String targetType,
ActivityLogTargetType targetType,
Long targetId
) {
return new ActivityLog(
project,
actorUserId,
null,
actorType,
actor,
type,
content,
targetType,
targetId,
null
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.slatto.domain.notification.model;

import com.slatto.domain.notification.enums.ActorType;

public record ActivityActor(
ActorType actorType,
Long actorUserId,
Long actorGuestId,
String displayName
) {

public ActivityActor {
if (actorType == null) {
throw new IllegalArgumentException("최근활동 행위자 타입은 필수입니다.");
}
if (displayName == null || displayName.isBlank()) {
throw new IllegalArgumentException("최근활동 행위자 이름은 필수입니다.");
}

validateActorIds(actorType, actorUserId, actorGuestId);
}

public static ActivityActor user(Long userId, String displayName) {
return new ActivityActor(ActorType.USER, userId, null, displayName);
}

public static ActivityActor clientReviewer(Long guestId, String displayName) {
return new ActivityActor(ActorType.CLIENT_REVIEWER, null, guestId, displayName);
}

public static ActivityActor system(String displayName) {
return new ActivityActor(ActorType.SYSTEM, null, null, displayName);
}

private static void validateActorIds(ActorType actorType, Long actorUserId, Long actorGuestId) {
switch (actorType) {
case USER -> {
requirePositiveId(actorUserId, "사용자");
requireNull(actorGuestId, "회원 행위자는 게스트 ID를 가질 수 없습니다.");
}
case CLIENT_REVIEWER -> {
requireNull(actorUserId, "게스트 행위자는 사용자 ID를 가질 수 없습니다.");
requirePositiveId(actorGuestId, "게스트");
}
case SYSTEM -> {
requireNull(actorUserId, "시스템 행위자는 사용자 ID를 가질 수 없습니다.");
requireNull(actorGuestId, "시스템 행위자는 게스트 ID를 가질 수 없습니다.");
}
}
}

private static void requirePositiveId(Long id, String actorName) {
if (id == null || id <= 0) {
throw new IllegalArgumentException(actorName + " ID는 양수여야 합니다.");
}
}

private static void requireNull(Long id, String message) {
if (id != null) {
throw new IllegalArgumentException(message);
}
}
}
Loading
Loading