Skip to content

Commit

Permalink
[MERGE] fix/#300 -> develop
Browse files Browse the repository at this point in the history
[FIX/#300] 웹 어드민 푸시 알림 기능 수정 / 예약 기능 구현 수정
  • Loading branch information
yummygyudon authored Jan 19, 2025
2 parents f5fc166 + 19b12b4 commit feb9836
Show file tree
Hide file tree
Showing 76 changed files with 1,073 additions and 693 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.List;

import lombok.Builder;
import org.sopt.makers.operation.common.domain.Part;
import org.sopt.makers.operation.member.domain.Part;
import org.sopt.makers.operation.member.domain.Member;

import static lombok.AccessLevel.PRIVATE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.sopt.makers.operation.alarm.domain.Status;
import org.sopt.makers.operation.alarm.domain.AlarmStatus;
import org.sopt.makers.operation.dto.BaseResponse;
import org.sopt.makers.operation.web.alarm.dto.request.AlarmInstantSendRequest;
import org.sopt.makers.operation.web.alarm.dto.request.AlarmScheduleSendRequest;
import org.sopt.makers.operation.web.alarm.dto.request.AlarmScheduleStatusUpdateRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
Expand Down Expand Up @@ -79,7 +80,7 @@ public interface AlarmApi {
)
ResponseEntity<BaseResponse<?>> getAlarms(
@RequestParam(required = false) Integer generation,
@RequestParam(required = false) Status status,
@RequestParam(required = false) AlarmStatus status,
Pageable pageable
);

Expand Down Expand Up @@ -120,4 +121,23 @@ ResponseEntity<BaseResponse<?>> getAlarms(
}
)
ResponseEntity<BaseResponse<?>> deleteAlarm(@PathVariable long alarmId);

@Operation(
summary = "알림 상태 업데이트 API (Web Hook)",
responses = {
@ApiResponse(
responseCode = "204",
description = "알림 상태 업데이트 성공"
),
@ApiResponse(
responseCode = "404",
description = "알림이 존재하지 않습니다."
),
@ApiResponse(
responseCode = "500",
description = "서버 내부 오류"
)
}
)
ResponseEntity<BaseResponse<?>> updateAlarmStatus(@PathVariable long alarmId, @RequestBody AlarmScheduleStatusUpdateRequest updateRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,21 @@
import static org.sopt.makers.operation.code.success.web.AlarmSuccessCode.SUCCESS_GET_ALARMS;
import static org.sopt.makers.operation.code.success.web.AlarmSuccessCode.SUCCESS_SCHEDULE_ALARM;
import static org.sopt.makers.operation.code.success.web.AlarmSuccessCode.SUCCESS_SEND_ALARM;
import static org.sopt.makers.operation.code.success.web.AlarmSuccessCode.SUCCESS_UPDATE_ALARM_STATUS;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.sopt.makers.operation.alarm.domain.Status;
import org.sopt.makers.operation.alarm.domain.AlarmStatus;
import org.sopt.makers.operation.dto.BaseResponse;
import org.sopt.makers.operation.util.ApiResponseUtil;
import org.sopt.makers.operation.web.alarm.dto.request.AlarmInstantSendRequest;
import org.sopt.makers.operation.web.alarm.dto.request.AlarmScheduleSendRequest;
import org.sopt.makers.operation.web.alarm.dto.request.AlarmScheduleStatusUpdateRequest;
import org.sopt.makers.operation.web.alarm.service.AlarmService;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
Expand All @@ -34,23 +30,27 @@ public class AlarmApiController implements AlarmApi {

@Override
@PostMapping("/send")
public ResponseEntity<BaseResponse<?>> sendInstantAlarm(@Valid AlarmInstantSendRequest request) {
alarmService.sendInstantAlarm(request);
return ApiResponseUtil.success(SUCCESS_SEND_ALARM);
public ResponseEntity<BaseResponse<?>> sendInstantAlarm(
@Valid @RequestBody AlarmInstantSendRequest request
) {
val result = alarmService.sendInstantAlarm(request);
return ApiResponseUtil.success(SUCCESS_SEND_ALARM, result);
}

@Override
@PostMapping("/schedule")
public ResponseEntity<BaseResponse<?>> sendScheduleAlarm(@Valid AlarmScheduleSendRequest request) {
alarmService.sendScheduleAlarm(request);
return ApiResponseUtil.success(SUCCESS_SCHEDULE_ALARM);
public ResponseEntity<BaseResponse<?>> sendScheduleAlarm(
@Valid @RequestBody AlarmScheduleSendRequest request
) {
val result = alarmService.sendScheduleAlarm(request);
return ApiResponseUtil.success(SUCCESS_SCHEDULE_ALARM, result);
}

@Override
@GetMapping
public ResponseEntity<BaseResponse<?>> getAlarms(
@RequestParam(required = false) Integer generation,
@RequestParam(required = false) Status status,
@RequestParam(required = false) AlarmStatus status,
Pageable pageable
) {
val response = alarmService.getAlarms(generation, status, pageable);
Expand All @@ -70,4 +70,16 @@ public ResponseEntity<BaseResponse<?>> deleteAlarm(@PathVariable long alarmId) {
alarmService.deleteAlarm(alarmId);
return ApiResponseUtil.success(SUCCESS_DELETE_ALARM);
}

@Override
@PatchMapping("/{alarmId}")
public ResponseEntity<BaseResponse<?>> updateAlarmStatus(
@PathVariable long alarmId,
@RequestBody AlarmScheduleStatusUpdateRequest updateRequest
) {
alarmService.updateScheduleAlarm(alarmId, updateRequest);
return ApiResponseUtil.success(SUCCESS_UPDATE_ALARM_STATUS);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,48 @@

import jakarta.validation.constraints.NotNull;
import java.util.List;

import org.sopt.makers.operation.alarm.domain.Alarm;
import org.sopt.makers.operation.alarm.domain.AlarmType;
import org.sopt.makers.operation.alarm.domain.Category;
import org.sopt.makers.operation.alarm.domain.LinkType;
import org.sopt.makers.operation.alarm.domain.Status;
import org.sopt.makers.operation.alarm.domain.TargetType;
import org.sopt.makers.operation.common.domain.Part;
import org.sopt.makers.operation.alarm.domain.AlarmTarget;
import org.sopt.makers.operation.alarm.domain.AlarmContent;
import org.sopt.makers.operation.alarm.domain.AlarmCategory;
import org.sopt.makers.operation.alarm.domain.AlarmTargetType;
import org.sopt.makers.operation.alarm.domain.AlarmTargetPart;
import org.sopt.makers.operation.alarm.domain.AlarmLinkType;

public record AlarmInstantSendRequest(
@NotNull Integer createdGeneration,
@NotNull String title,
@NotNull String content,
@NotNull Category category,
@NotNull TargetType targetType,
@NotNull AlarmCategory category,
@NotNull AlarmTargetType targetType,
AlarmTargetPart part,
Integer createdGeneration,
List<String> targetList,
Part part,
LinkType linkType,
AlarmLinkType linkType,
String link
) {

private AlarmTarget toTargetEntity() {
return switch (this.targetType) {
case ALL -> this.part.equals(AlarmTargetPart.ALL)
? AlarmTarget.all()
: AlarmTarget.partialForAll(this.part, this.targetList);
case ACTIVE -> AlarmTarget.partialForActive(this.createdGeneration, this.part, this.targetList);
case CSV -> AlarmTarget.partialForCsv(this.targetList);
};
}

private AlarmContent toContentEntity() {
return switch (this.linkType) {
case WEB -> AlarmContent.withWebLink(this.title, this.content, this.category, this.link);
case APP -> AlarmContent.withAppLink(this.title, this.content, this.category, this.link);
case NONE -> AlarmContent.withoutLink(this.title, this.content, this.category);
};
}

public Alarm toEntity() {
return Alarm.builder()
.createdGeneration(this.createdGeneration)
.category(this.category)
.title(this.title)
.content(this.content)
.targetType(this.targetType)
.alarmType(AlarmType.INSTANT)
.link(this.link)
.linkType(linkType)
.part(this.part)
.status(Status.COMPLETED)
.targetList(this.targetList)
.build();
AlarmTarget targetEntity = this.toTargetEntity();
AlarmContent contentEntity = this.toContentEntity();
return Alarm.instant(targetEntity, contentEntity);
}
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
package org.sopt.makers.operation.web.alarm.dto.request;

import jakarta.validation.constraints.NotNull;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import lombok.val;

import org.sopt.makers.operation.alarm.domain.Alarm;
import org.sopt.makers.operation.alarm.domain.AlarmType;
import org.sopt.makers.operation.alarm.domain.Category;
import org.sopt.makers.operation.alarm.domain.LinkType;
import org.sopt.makers.operation.alarm.domain.Status;
import org.sopt.makers.operation.alarm.domain.TargetType;
import org.sopt.makers.operation.common.domain.Part;
import org.sopt.makers.operation.alarm.domain.AlarmTarget;
import org.sopt.makers.operation.alarm.domain.AlarmContent;
import org.sopt.makers.operation.alarm.domain.AlarmCategory;
import org.sopt.makers.operation.alarm.domain.AlarmTargetType;
import org.sopt.makers.operation.alarm.domain.AlarmTargetPart;
import org.sopt.makers.operation.alarm.domain.AlarmLinkType;

import static org.sopt.makers.operation.constant.AlarmConstant.ALARM_REQUEST_DATE_FORMAT;
import static org.sopt.makers.operation.constant.AlarmConstant.ALARM_REQUEST_TIME_FORMAT;

public record AlarmScheduleSendRequest(
@NotNull Integer createdGeneration,
@NotNull String title,
@NotNull String content,
@NotNull Category category,
@NotNull TargetType targetType,
@NotNull AlarmCategory category,
@NotNull AlarmTargetType targetType,
List<String> targetList,
Part part,
LinkType linkType,
AlarmTargetPart part,
Integer createdGeneration,
AlarmLinkType linkType,
String link,
@NotNull String postDate,
@NotNull String postTime
) {
private AlarmTarget toTargetEntity() {
return switch (this.targetType) {
case ALL -> this.part.equals(AlarmTargetPart.ALL)
? AlarmTarget.all()
: AlarmTarget.partialForAll(this.part, this.targetList);
case ACTIVE -> AlarmTarget.partialForActive(this.createdGeneration, this.part, this.targetList);
case CSV -> AlarmTarget.partialForCsv(this.targetList);
};
}

private AlarmContent toContentEntity() {
return switch (this.linkType) {
case WEB -> AlarmContent.withWebLink(this.title, this.content, this.category, this.link);
case APP -> AlarmContent.withAppLink(this.title, this.content, this.category, this.link);
case NONE -> AlarmContent.withoutLink(this.title, this.content, this.category);
};
}

public Alarm toEntity() {
return Alarm.builder()
.createdGeneration(this.createdGeneration)
.category(this.category)
.title(this.title)
.content(this.content)
.targetType(this.targetType)
.alarmType(AlarmType.RESERVED)
.link(this.link)
.linkType(linkType)
.part(this.part)
.status(Status.SCHEDULED)
.targetList(this.targetList)
.build();
AlarmTarget targetEntity = this.toTargetEntity();
AlarmContent contentEntity = this.toContentEntity();
val date = LocalDate.parse(postDate, DateTimeFormatter.ofPattern(ALARM_REQUEST_DATE_FORMAT));
val time = LocalTime.parse(postTime, DateTimeFormatter.ofPattern(ALARM_REQUEST_TIME_FORMAT));
return Alarm.scheduled(targetEntity, contentEntity, LocalDateTime.of(date, time));
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.makers.operation.web.alarm.dto.request;

import jakarta.validation.constraints.NotNull;

import java.time.LocalDateTime;

public record AlarmScheduleStatusUpdateRequest(
@NotNull LocalDateTime sendAt
) {
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package org.sopt.makers.operation.web.alarm.dto.response;

import static lombok.AccessLevel.*;
import static lombok.AccessLevel.PRIVATE;

import org.sopt.makers.operation.alarm.domain.Alarm;

import lombok.Builder;

@Builder(access = PRIVATE)
public record AlarmCreateResponse(
long alarmId
long id
) {

public static AlarmCreateResponse of(Alarm alarm) {
return AlarmCreateResponse.builder()
.alarmId(alarm.getId())
.id(alarm.getId())
.build();
}
}
Loading

0 comments on commit feb9836

Please sign in to comment.