Restore Main Attachments

This commit is contained in:
2026-04-09 23:25:05 -06:00
parent 738ad0003b
commit da95606f64
4 changed files with 181 additions and 2 deletions

View File

@@ -2,6 +2,10 @@ package com.petshop.backend.dto.chat;
public class MessageRequest {
private String content;
private String attachmentUrl;
private String attachmentName;
private String attachmentMimeType;
private Long attachmentSizeBytes;
public MessageRequest() {
}
@@ -13,4 +17,36 @@ public class MessageRequest {
public void setContent(String 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;
}
}

View File

@@ -12,6 +12,10 @@ public class MessageResponse {
private String content;
private LocalDateTime timestamp;
private Boolean isRead;
private String attachmentUrl;
private String attachmentName;
private String attachmentMimeType;
private Long attachmentSizeBytes;
public MessageResponse() {
}
@@ -34,6 +38,15 @@ public class MessageResponse {
response.setContent(message.getContent());
response.setTimestamp(message.getTimestamp());
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;
}
@@ -92,4 +105,36 @@ public class MessageResponse {
public void setIsRead(Boolean 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;
}
}

View File

@@ -22,6 +22,17 @@ public class Message {
@Column(columnDefinition = "TEXT")
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
@Column(nullable = false, updatable = false)
private LocalDateTime timestamp;
@@ -88,4 +99,36 @@ public class Message {
public void setIsRead(Boolean 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;
}
}

View File

@@ -15,7 +15,9 @@ import com.petshop.backend.repository.UserRepository;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@@ -27,15 +29,18 @@ public class ChatService {
private final MessageRepository messageRepository;
private final UserRepository userRepository;
private final AvatarStorageService avatarStorageService;
private final ChatAttachmentStorageService attachmentStorageService;
public ChatService(ConversationRepository conversationRepository,
MessageRepository messageRepository,
UserRepository userRepository,
AvatarStorageService avatarStorageService) {
AvatarStorageService avatarStorageService,
ChatAttachmentStorageService attachmentStorageService) {
this.conversationRepository = conversationRepository;
this.messageRepository = messageRepository;
this.userRepository = userRepository;
this.avatarStorageService = avatarStorageService;
this.attachmentStorageService = attachmentStorageService;
}
@Transactional
@@ -104,8 +109,8 @@ public class ChatService {
List<Message> messages = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
Message last = messages.isEmpty() ? null : messages.get(messages.size() - 1);
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);
}
@@ -131,6 +136,10 @@ public class ChatService {
message.setConversationId(conversationId);
message.setSenderId(userId);
message.setContent(request.getContent());
message.setAttachmentUrl(request.getAttachmentUrl());
message.setAttachmentName(request.getAttachmentName());
message.setAttachmentMimeType(request.getAttachmentMimeType());
message.setAttachmentSizeBytes(request.getAttachmentSizeBytes());
message.setIsRead(false);
message = messageRepository.save(message);
@@ -146,6 +155,52 @@ public class ChatService {
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
public ConversationResponse requestHumanTakeover(Long conversationId, Long userId, User.Role role) {
Conversation conversation = conversationRepository.findById(conversationId)