Restore Main Attachments
This commit is contained in:
@@ -2,6 +2,10 @@ package com.petshop.backend.dto.chat;
|
|||||||
|
|
||||||
public class MessageRequest {
|
public class MessageRequest {
|
||||||
private String content;
|
private String content;
|
||||||
|
private String attachmentUrl;
|
||||||
|
private String attachmentName;
|
||||||
|
private String attachmentMimeType;
|
||||||
|
private Long attachmentSizeBytes;
|
||||||
|
|
||||||
public MessageRequest() {
|
public MessageRequest() {
|
||||||
}
|
}
|
||||||
@@ -13,4 +17,36 @@ public class MessageRequest {
|
|||||||
public void setContent(String content) {
|
public void setContent(String content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAttachmentUrl() {
|
||||||
|
return attachmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentUrl(String attachmentUrl) {
|
||||||
|
this.attachmentUrl = attachmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentName() {
|
||||||
|
return attachmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentName(String attachmentName) {
|
||||||
|
this.attachmentName = attachmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentMimeType() {
|
||||||
|
return attachmentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentMimeType(String attachmentMimeType) {
|
||||||
|
this.attachmentMimeType = attachmentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAttachmentSizeBytes() {
|
||||||
|
return attachmentSizeBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentSizeBytes(Long attachmentSizeBytes) {
|
||||||
|
this.attachmentSizeBytes = attachmentSizeBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ public class MessageResponse {
|
|||||||
private String content;
|
private String content;
|
||||||
private LocalDateTime timestamp;
|
private LocalDateTime timestamp;
|
||||||
private Boolean isRead;
|
private Boolean isRead;
|
||||||
|
private String attachmentUrl;
|
||||||
|
private String attachmentName;
|
||||||
|
private String attachmentMimeType;
|
||||||
|
private Long attachmentSizeBytes;
|
||||||
|
|
||||||
public MessageResponse() {
|
public MessageResponse() {
|
||||||
}
|
}
|
||||||
@@ -34,6 +38,15 @@ public class MessageResponse {
|
|||||||
response.setContent(message.getContent());
|
response.setContent(message.getContent());
|
||||||
response.setTimestamp(message.getTimestamp());
|
response.setTimestamp(message.getTimestamp());
|
||||||
response.setIsRead(message.getIsRead());
|
response.setIsRead(message.getIsRead());
|
||||||
|
|
||||||
|
|
||||||
|
if (message.getAttachmentUrl() != null) {
|
||||||
|
response.setAttachmentUrl("/api/v1/chat/messages/" + message.getId() + "/attachment");
|
||||||
|
}
|
||||||
|
|
||||||
|
response.setAttachmentName(message.getAttachmentName());
|
||||||
|
response.setAttachmentMimeType(message.getAttachmentMimeType());
|
||||||
|
response.setAttachmentSizeBytes(message.getAttachmentSizeBytes());
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,4 +105,36 @@ public class MessageResponse {
|
|||||||
public void setIsRead(Boolean isRead) {
|
public void setIsRead(Boolean isRead) {
|
||||||
this.isRead = isRead;
|
this.isRead = isRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAttachmentUrl() {
|
||||||
|
return attachmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentUrl(String attachmentUrl) {
|
||||||
|
this.attachmentUrl = attachmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentName() {
|
||||||
|
return attachmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentName(String attachmentName) {
|
||||||
|
this.attachmentName = attachmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentMimeType() {
|
||||||
|
return attachmentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentMimeType(String attachmentMimeType) {
|
||||||
|
this.attachmentMimeType = attachmentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAttachmentSizeBytes() {
|
||||||
|
return attachmentSizeBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentSizeBytes(Long attachmentSizeBytes) {
|
||||||
|
this.attachmentSizeBytes = attachmentSizeBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,17 @@ public class Message {
|
|||||||
@Column(columnDefinition = "TEXT")
|
@Column(columnDefinition = "TEXT")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
|
@Column(length = 255)
|
||||||
|
private String attachmentUrl;
|
||||||
|
|
||||||
|
@Column(length = 255)
|
||||||
|
private String attachmentName;
|
||||||
|
|
||||||
|
@Column(length = 100)
|
||||||
|
private String attachmentMimeType;
|
||||||
|
|
||||||
|
private Long attachmentSizeBytes;
|
||||||
|
|
||||||
@CreationTimestamp
|
@CreationTimestamp
|
||||||
@Column(nullable = false, updatable = false)
|
@Column(nullable = false, updatable = false)
|
||||||
private LocalDateTime timestamp;
|
private LocalDateTime timestamp;
|
||||||
@@ -88,4 +99,36 @@ public class Message {
|
|||||||
public void setIsRead(Boolean isRead) {
|
public void setIsRead(Boolean isRead) {
|
||||||
this.isRead = isRead;
|
this.isRead = isRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAttachmentUrl() {
|
||||||
|
return attachmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentUrl(String attachmentUrl) {
|
||||||
|
this.attachmentUrl = attachmentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentName() {
|
||||||
|
return attachmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentName(String attachmentName) {
|
||||||
|
this.attachmentName = attachmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentMimeType() {
|
||||||
|
return attachmentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentMimeType(String attachmentMimeType) {
|
||||||
|
this.attachmentMimeType = attachmentMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAttachmentSizeBytes() {
|
||||||
|
return attachmentSizeBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentSizeBytes(Long attachmentSizeBytes) {
|
||||||
|
this.attachmentSizeBytes = attachmentSizeBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ import com.petshop.backend.repository.UserRepository;
|
|||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -27,15 +29,18 @@ public class ChatService {
|
|||||||
private final MessageRepository messageRepository;
|
private final MessageRepository messageRepository;
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final AvatarStorageService avatarStorageService;
|
private final AvatarStorageService avatarStorageService;
|
||||||
|
private final ChatAttachmentStorageService attachmentStorageService;
|
||||||
|
|
||||||
public ChatService(ConversationRepository conversationRepository,
|
public ChatService(ConversationRepository conversationRepository,
|
||||||
MessageRepository messageRepository,
|
MessageRepository messageRepository,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
AvatarStorageService avatarStorageService) {
|
AvatarStorageService avatarStorageService,
|
||||||
|
ChatAttachmentStorageService attachmentStorageService) {
|
||||||
this.conversationRepository = conversationRepository;
|
this.conversationRepository = conversationRepository;
|
||||||
this.messageRepository = messageRepository;
|
this.messageRepository = messageRepository;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.avatarStorageService = avatarStorageService;
|
this.avatarStorageService = avatarStorageService;
|
||||||
|
this.attachmentStorageService = attachmentStorageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -104,8 +109,8 @@ public class ChatService {
|
|||||||
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
|
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
|
||||||
Message last = messages.isEmpty() ? null : messages.get(messages.size() - 1);
|
Message last = messages.isEmpty() ? null : messages.get(messages.size() - 1);
|
||||||
String lastMessage = last != null && last.getContent() != null ? last.getContent() : "";
|
String lastMessage = last != null && last.getContent() != null ? last.getContent() : "";
|
||||||
Long lastSenderId = last != null ? last.getSenderId() : null;
|
|
||||||
|
|
||||||
|
Long lastSenderId = last != null ? last.getSenderId() : null;
|
||||||
return ConversationResponse.fromEntity(conversation, lastMessage, lastSenderId);
|
return ConversationResponse.fromEntity(conversation, lastMessage, lastSenderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +136,10 @@ public class ChatService {
|
|||||||
message.setConversationId(conversationId);
|
message.setConversationId(conversationId);
|
||||||
message.setSenderId(userId);
|
message.setSenderId(userId);
|
||||||
message.setContent(request.getContent());
|
message.setContent(request.getContent());
|
||||||
|
message.setAttachmentUrl(request.getAttachmentUrl());
|
||||||
|
message.setAttachmentName(request.getAttachmentName());
|
||||||
|
message.setAttachmentMimeType(request.getAttachmentMimeType());
|
||||||
|
message.setAttachmentSizeBytes(request.getAttachmentSizeBytes());
|
||||||
message.setIsRead(false);
|
message.setIsRead(false);
|
||||||
message = messageRepository.save(message);
|
message = messageRepository.save(message);
|
||||||
|
|
||||||
@@ -146,6 +155,52 @@ public class ChatService {
|
|||||||
return toMessageResponse(message);
|
return toMessageResponse(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public MessageResponse sendMessageWithAttachment(Long conversationId, Long userId, User.Role role, MultipartFile file, String content) {
|
||||||
|
Conversation conversation = conversationRepository.findById(conversationId)
|
||||||
|
.orElseThrow(() -> new ResourceNotFoundException("Conversation not found"));
|
||||||
|
|
||||||
|
if (conversation.getStatus() == Conversation.ConversationStatus.CLOSED) {
|
||||||
|
throw new AccessDeniedException("Conversation is closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasConversationAccess(conversation, userId, role)) {
|
||||||
|
if (role == User.Role.CUSTOMER) {
|
||||||
|
throw new AccessDeniedException("You can only send messages to your own conversations");
|
||||||
|
}
|
||||||
|
if (role == User.Role.STAFF) {
|
||||||
|
throw new AccessDeniedException("You can only reply to conversations assigned to you or unassigned conversations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String attachmentUrl = attachmentStorageService.storeAttachment(file);
|
||||||
|
Message message = new Message();
|
||||||
|
message.setConversationId(conversationId);
|
||||||
|
message.setSenderId(userId);
|
||||||
|
message.setContent(content);
|
||||||
|
message.setAttachmentUrl(attachmentUrl);
|
||||||
|
message.setAttachmentName(file.getOriginalFilename());
|
||||||
|
message.setAttachmentMimeType(file.getContentType());
|
||||||
|
message.setAttachmentSizeBytes(file.getSize());
|
||||||
|
message.setIsRead(false);
|
||||||
|
message = messageRepository.save(message);
|
||||||
|
|
||||||
|
if (role == User.Role.STAFF && conversation.getStaffId() == null) {
|
||||||
|
conversation.setStaffId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == User.Role.STAFF) {
|
||||||
|
conversation.setMode(Conversation.ConversationMode.HUMAN);
|
||||||
|
conversationRepository.save(conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toMessageResponse(message);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to store attachment", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public ConversationResponse requestHumanTakeover(Long conversationId, Long userId, User.Role role) {
|
public ConversationResponse requestHumanTakeover(Long conversationId, Long userId, User.Role role) {
|
||||||
Conversation conversation = conversationRepository.findById(conversationId)
|
Conversation conversation = conversationRepository.findById(conversationId)
|
||||||
|
|||||||
Reference in New Issue
Block a user