Skip to content

Commit

Permalink
๐Ÿ”€ refactor: ์•Œ๋ฆผ ๊ด€๋ จ api ๊ตฌํ˜„ (#375)
Browse files Browse the repository at this point in the history
* refactor: ์•Œ๋ฆผ ๊ด€๋ จ api ๊ตฌํ˜„

* refactor: ์ œ์•ˆ ์•Œ๋ฆผ ๋‚ด์šฉ ์ˆ˜์ •

* refactor: ci ํŒŒ์ผ ์ˆ˜์ •

* refactor: ์•Œ๋ฆผ ์ƒํƒœ ์ถ”๊ฐ€ ๋ฐ ์กฐํšŒ api ๋ถ„๋ฆฌ
  • Loading branch information
seheonnn authored Aug 30, 2024
1 parent 8f61643 commit c22b5d1
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 16 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/ci_gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ jobs:
shell: bash

- name: Start Docker Compose
run: docker compose up -d
run: docker compose -f docker-compose-test.yml up -d

- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Test with Gradle
run: ./gradlew test

- name: Stop Docker Compose
run: docker-compose -f docker-compose-test.yml down
run: docker compose -f docker-compose-test.yml down

Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sponus.coredomain.domain.notification.NotificationStatus;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coreinfrafirebase.FirebaseService;
import com.sponus.coreinfrafirebase.FirebaseUtil;
import com.sponus.coreinfrasecurity.annotation.AuthOrganization;
import com.sponus.sponusbe.domain.notification.dto.request.NotificationTestRequest;

Expand All @@ -23,12 +24,12 @@
@RestController
public class FirebaseTestController {

private final FirebaseService firebaseService;
private final FirebaseUtil firebaseUtil;

@PostMapping("/fcm")
public String testNotification(@RequestBody NotificationTestRequest request,
@AuthOrganization Organization organization) throws IOException {
// firebaseService.sendMessageTo(organization, request.title(), request.body(), null, null, null);
firebaseUtil.sendMessageTo(organization, request.title(), request.body(), null, NotificationStatus.SEND);
return "Notification test is successful !";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.time.LocalDateTime;

import com.sponus.coredomain.domain.notification.Notification;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.propose.Propose;

import lombok.Builder;
Expand All @@ -12,22 +13,24 @@ public record NotificationSummaryResponse(
Long id,
String title,
String body,
Long organizationId,
Long announcementId,
String organizationProfile,
String organizationName,
Long proposeId,
Long reportId,
boolean isRead,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
public static NotificationSummaryResponse from(Notification notification) {
Propose propose = notification.getPropose();
Organization organization = notification.getOrganization();
String organizationProfile = organization.getImageUrl() != null ? organization.getImageUrl() : null;

return NotificationSummaryResponse.builder()
.id(notification.getId())
.title(notification.getTitle())
.body(notification.getBody())
.organizationId(notification.getOrganization().getId())
.organizationName(notification.getOrganization().getName())
.organizationProfile(organizationProfile)
.proposeId(propose != null ? propose.getId() : null)
.isRead(notification.isRead())
.createdAt(notification.getCreatedAt())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
@Getter
@AllArgsConstructor
public enum NotificationErrorCode implements BaseErrorCode {

NOTIFICATION_ERROR(HttpStatus.BAD_REQUEST, "NOTI4000", "์•Œ๋ฆผ ๊ด€๋ จ ์—๋Ÿฌ"),
NOTIFICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTI4001", "์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•Œ๋ฆผ์ž…๋‹ˆ๋‹ค."),
INVALID_ORGANIZATION(HttpStatus.BAD_REQUEST, "NOTI4002", "ํ•ด๋‹น ๋‹จ์ฒด์˜ ์•Œ๋ฆผ์ด ์•„๋‹™๋‹ˆ๋‹ค.");
NOTIFICATION_INVALID(HttpStatus.FORBIDDEN, "NOTI4030", "ํ•ด๋‹น ๋‹จ์ฒด์˜ ์•Œ๋ฆผ์ด ์•„๋‹™๋‹ˆ๋‹ค."),
NOTIFICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTI4040", "์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•Œ๋ฆผ์ž…๋‹ˆ๋‹ค."),
NOTIFICATION_IO_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "NOTI5000", "์•Œ๋ฆผ ์ „์†ก ์ค‘ I/O ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."),
;

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -20,6 +21,7 @@
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.enums.OrganizationType;
import com.sponus.coreinfrasecurity.annotation.AuthOrganization;
import com.sponus.sponusbe.domain.notification.dto.response.NotificationSummaryResponse;
import com.sponus.sponusbe.domain.organization.club.service.ClubService;
import com.sponus.sponusbe.domain.organization.company.service.CompanyService;
import com.sponus.sponusbe.domain.organization.dto.request.OrganizationCreateRequest;
Expand Down Expand Up @@ -122,4 +124,32 @@ public ApiResponse<Void> deleteSearchKeyword(
organizationService.deleteSearchKeyword(organization.getId(), request.keyword());
return ApiResponse.onSuccess(null);
}

@GetMapping("/notifications/send")
public ApiResponse<List<NotificationSummaryResponse>> getSendNotifications(
@AuthOrganization Organization organization) {
return ApiResponse.onSuccess(organizationQueryService.getSendNotifications(organization));
}

@GetMapping("/notifications/receive")
public ApiResponse<List<NotificationSummaryResponse>> getReceivedNotifications(
@AuthOrganization Organization organization) {
return ApiResponse.onSuccess(organizationQueryService.getReceiveNotifications(organization));
}

@DeleteMapping("/notifications/{notificationId}")
public ApiResponse<Void> deleteNotification(
@AuthOrganization Organization organization,
@PathVariable("notificationId") Long notificationId) {
organizationService.deleteNotification(organization, notificationId);
return ApiResponse.onSuccess(null);
}

@PatchMapping("/notifications/{notificationId}")
public ApiResponse<Void> readNotification(
@AuthOrganization Organization organization,
@PathVariable("notificationId") Long notificationId) {
organizationService.readNotification(organization, notificationId);
return ApiResponse.onSuccess(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
import org.springframework.transaction.annotation.Transactional;

import com.sponus.coredomain.domain.bookmark.repository.BookmarkRepository;
import com.sponus.coredomain.domain.notification.NotificationStatus;
import com.sponus.coredomain.domain.notification.repository.NotificationRepository;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.enums.OrganizationType;
import com.sponus.coredomain.domain.organization.enums.ProfileStatus;
import com.sponus.coredomain.domain.organization.repository.OrganizationRepository;
import com.sponus.coredomain.domain.organization.repository.querydsl.conditions.OrganizationSearchCondition;
import com.sponus.coreinfraredis.entity.SearchHistory;
import com.sponus.coreinfraredis.repository.SearchHistoryRepository;
import com.sponus.sponusbe.domain.notification.dto.response.NotificationSummaryResponse;
import com.sponus.sponusbe.domain.organization.dto.request.PageCondition;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationGetResponse;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationSearchResponse;
Expand All @@ -38,6 +41,7 @@ public class OrganizationQueryService {
private final OrganizationRepository organizationRepository;
private final SearchHistoryRepository searchHistoryRepository;
private final BookmarkRepository bookmarkRepository;
private final NotificationRepository notificationRepository;

public Boolean verifyName(String name) {
return organizationRepository.existsByName(name);
Expand Down Expand Up @@ -127,4 +131,19 @@ private SearchHistory findSearchHistory(Long organizationId) {
});
}

public List<NotificationSummaryResponse> getSendNotifications(Organization organization) {
return notificationRepository.findByOrganizationAndAndStatusOrderByCreatedAtDesc(organization,
NotificationStatus.SEND)
.stream()
.map(NotificationSummaryResponse::from)
.toList();
}

public List<NotificationSummaryResponse> getReceiveNotifications(Organization organization) {
return notificationRepository.findByOrganizationAndAndStatusOrderByCreatedAtDesc(organization,
NotificationStatus.RECEIVE)
.stream()
.map(NotificationSummaryResponse::from)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.sponus.coredomain.domain.notification.Notification;
import com.sponus.coredomain.domain.notification.repository.NotificationRepository;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.club.Club;
import com.sponus.coredomain.domain.organization.company.Company;
Expand All @@ -13,6 +15,8 @@
import com.sponus.coreinfraredis.entity.SearchHistory;
import com.sponus.coreinfraredis.repository.SearchHistoryRepository;
import com.sponus.coreinfras3.S3Service;
import com.sponus.sponusbe.domain.notification.exception.NotificationErrorCode;
import com.sponus.sponusbe.domain.notification.exception.NotificationException;
import com.sponus.sponusbe.domain.organization.dto.request.OrganizationCreateRequest;
import com.sponus.sponusbe.domain.organization.dto.response.OrganizationImageUploadResponse;
import com.sponus.sponusbe.domain.organization.exception.OrganizationErrorCode;
Expand All @@ -31,6 +35,7 @@ public class OrganizationService {
private final S3Service s3Service;
private final PasswordEncoder passwordEncoder;
private final SearchHistoryRepository searchHistoryRepository;
private final NotificationRepository notificationRepository;

public Long createOrganization(OrganizationCreateRequest request) {
Organization organization;
Expand Down Expand Up @@ -92,4 +97,22 @@ private SearchHistory findSearchHistory(Long organizationId) {
return searchHistoryRepository.save(newSearchHistory);
});
}

public void deleteNotification(Organization organization, Long notificationId) {
Notification notification = notificationRepository.findById(notificationId)
.orElseThrow(() -> new NotificationException(NotificationErrorCode.NOTIFICATION_NOT_FOUND));
if (!notification.getOrganization().getId().equals(organization.getId())) {
throw new NotificationException(NotificationErrorCode.NOTIFICATION_INVALID);
}
notificationRepository.delete(notification);
}

public void readNotification(Organization organization, Long notificationId) {
Notification notification = notificationRepository.findById(notificationId)
.orElseThrow(() -> new NotificationException(NotificationErrorCode.NOTIFICATION_NOT_FOUND));
if (!notification.getOrganization().getId().equals(organization.getId())) {
throw new NotificationException(NotificationErrorCode.NOTIFICATION_INVALID);
}
notification.read();
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.sponus.sponusbe.domain.propose.service;

import java.io.IOException;
import java.time.LocalDateTime;

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

import com.sponus.coredomain.domain.notification.NotificationStatus;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.repository.OrganizationRepository;
import com.sponus.coredomain.domain.propose.Propose;
import com.sponus.coredomain.domain.propose.repository.ProposeRepository;
import com.sponus.coreinfrafirebase.FirebaseUtil;
import com.sponus.sponusbe.domain.organization.exception.OrganizationErrorCode;
import com.sponus.sponusbe.domain.organization.exception.OrganizationException;
import com.sponus.sponusbe.domain.propose.dto.request.ProposeCreateRequest;
Expand All @@ -27,6 +30,7 @@ public class ProposeService {

private final ProposeRepository proposeRepository;
private final OrganizationRepository organizationRepository;
private final FirebaseUtil firebaseUtil;

public ProposeCreateResponse createPropose(Organization organization, ProposeCreateRequest request) {

Expand All @@ -52,6 +56,17 @@ public ProposeCreateResponse createPropose(Organization organization, ProposeCre
// .count();

final Propose propose = proposeRepository.save(request.toEntity(organization, target));
try {
firebaseUtil.sendMessageTo(
target,
organization.getName() + "(์œผ)๋กœ๋ถ€ํ„ฐ ์ œ์•ˆ์ด ์™”์–ด์š”!",
"์ด๋ฉ”์ผ์„ ํ™•์ธํ•˜๊ณ  ๊ธฐ์—…๊ณผ ์ปจํƒํ•ด ๋ณด์„ธ์š”.",
propose,
NotificationStatus.RECEIVE
);
} catch (IOException ex) {
log.error("[*] Failed to send notification to organization: " + target.getName(), ex);
}
return ProposeCreateResponse.from(propose);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class Notification extends BaseEntity {
@ColumnDefault("false")
private boolean isRead;

@Column(name = "notification_status", nullable = false)
private NotificationStatus status;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organization_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Organization organization;
Expand All @@ -66,7 +69,7 @@ public void setPropose(Propose propose) {
this.propose = propose;
}

public void setRead(boolean read) {
isRead = read;
public void read() {
isRead = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.sponus.coredomain.domain.notification;

public enum NotificationStatus {
RECEIVE, SEND
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import org.springframework.data.jpa.repository.JpaRepository;

import com.sponus.coredomain.domain.notification.Notification;
import com.sponus.coredomain.domain.notification.NotificationStatus;
import com.sponus.coredomain.domain.organization.Organization;

public interface NotificationRepository extends JpaRepository<Notification, Long> {
List<Notification> findByOrganizationOrderByCreatedAtDesc(Organization organization);
List<Notification> findByOrganizationAndAndStatusOrderByCreatedAtDesc(Organization organization,
NotificationStatus status);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.auth.oauth2.GoogleCredentials;
import com.sponus.coredomain.domain.notification.Notification;
import com.sponus.coredomain.domain.notification.NotificationStatus;
import com.sponus.coredomain.domain.notification.repository.NotificationRepository;
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.propose.Propose;
Expand All @@ -28,7 +29,7 @@
@Slf4j
@Component
@RequiredArgsConstructor
public class FirebaseService {
public class FirebaseUtil {

@Value("${firebase.fcmUrl}")
private String fcmUrl;
Expand All @@ -45,14 +46,16 @@ public class FirebaseService {

private final RedisUtil redisUtil;

public void sendMessageTo(Organization targetOrganization, String title, String body, Propose propose) throws
public void sendMessageTo(Organization targetOrganization, String title, String body, Propose propose,
NotificationStatus status) throws
IOException {

String token = getFcmToken(targetOrganization.getEmail());

Notification notification = Notification.builder()
.title(title)
.body(body)
.status(status)
.build();

notification.setOrganization(targetOrganization);
Expand Down

0 comments on commit c22b5d1

Please sign in to comment.