97 lines
3.8 KiB
Java
97 lines
3.8 KiB
Java
package com.walkguide.service;
|
|
|
|
import com.walkguide.dto.request.SendNotificationRequest;
|
|
import com.walkguide.dto.response.NotificationResponse;
|
|
import com.walkguide.entity.GuardianNotification;
|
|
import com.walkguide.enums.NotificationType;
|
|
import com.walkguide.enums.PairingStatus;
|
|
import com.walkguide.exception.PairingException;
|
|
import com.walkguide.exception.ResourceNotFoundException;
|
|
import com.walkguide.repository.GuardianNotificationRepository;
|
|
import com.walkguide.repository.PairingRelationRepository;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.data.domain.Page;
|
|
import org.springframework.data.domain.Pageable;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.util.Map;
|
|
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
public class NotificationService {
|
|
|
|
private final GuardianNotificationRepository notifRepository;
|
|
private final PairingRelationRepository pairingRelationRepository;
|
|
private final FcmService fcmService;
|
|
|
|
@Transactional
|
|
public NotificationResponse sendNotification(Long guardianId, SendNotificationRequest req) {
|
|
var pairing = pairingRelationRepository
|
|
.findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)
|
|
.orElseThrow(() -> new PairingException("Tidak ada user yang dipair"));
|
|
|
|
Long userId = pairing.getUser().getId();
|
|
NotificationType type = "VOICE_NOTE".equalsIgnoreCase(req.getNotifType())
|
|
? NotificationType.VOICE_NOTE : NotificationType.TEXT;
|
|
|
|
GuardianNotification notif = GuardianNotification.builder()
|
|
.guardianId(guardianId)
|
|
.userId(userId)
|
|
.notifType(type)
|
|
.content(req.getContent())
|
|
.voiceNoteUrl(req.getVoiceNoteUrl())
|
|
.voiceNoteDuration(req.getVoiceNoteDuration())
|
|
.build();
|
|
notif = notifRepository.save(notif);
|
|
|
|
// FCM ke user
|
|
String fcmToken = pairing.getUser().getFcmToken();
|
|
String fcmBody = type == NotificationType.TEXT
|
|
? req.getContent() : "Voice note from Guardian";
|
|
fcmService.sendToToken(fcmToken,
|
|
"Pesan dari Guardian",
|
|
fcmBody,
|
|
Map.of("type", "NOTIFICATION",
|
|
"notifId", String.valueOf(notif.getId()),
|
|
"notifType", type.name(),
|
|
"voiceNoteUrl", req.getVoiceNoteUrl() != null ? req.getVoiceNoteUrl() : ""));
|
|
|
|
return toResponse(notif);
|
|
}
|
|
|
|
public Page<NotificationResponse> getNotifications(Long userId, Pageable pageable) {
|
|
return notifRepository.findByUserIdOrderByCreatedAtDesc(userId, pageable)
|
|
.map(this::toResponse);
|
|
}
|
|
|
|
public long getUnreadCount(Long userId) {
|
|
return notifRepository.countByUserIdAndIsReadFalse(userId);
|
|
}
|
|
|
|
@Transactional
|
|
public void markAllRead(Long userId) {
|
|
var unread = notifRepository.findByUserIdAndIsReadFalseOrderByCreatedAtAsc(userId);
|
|
LocalDateTime now = LocalDateTime.now();
|
|
unread.forEach(n -> { n.setIsRead(true); n.setReadAt(now); });
|
|
notifRepository.saveAll(unread);
|
|
}
|
|
|
|
@Transactional
|
|
public void markOneRead(Long notifId) {
|
|
notifRepository.findById(notifId).ifPresent(n -> {
|
|
n.setIsRead(true);
|
|
n.setReadAt(LocalDateTime.now());
|
|
notifRepository.save(n);
|
|
});
|
|
}
|
|
|
|
private NotificationResponse toResponse(GuardianNotification n) {
|
|
return NotificationResponse.builder()
|
|
.id(n.getId()).notifType(n.getNotifType().name()).content(n.getContent())
|
|
.voiceNoteUrl(n.getVoiceNoteUrl()).voiceNoteDuration(n.getVoiceNoteDuration())
|
|
.isRead(n.getIsRead()).readAt(n.getReadAt()).createdAt(n.getCreatedAt()).build();
|
|
}
|
|
}
|