feat: add messaging system database models and core services

- Add Conversation, ConversationParticipant, Message, MessageAttachment models
- Add ConversationType enum (admin_vendor, vendor_customer, admin_customer)
- Add ParticipantType enum (admin, vendor, customer)
- Add Alembic migration for messaging tables
- Add MessagingService for conversation/message operations
- Add MessageAttachmentService for file upload handling
- Add message-related exceptions (ConversationNotFoundException, etc.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-21 14:08:31 +01:00
parent 807cee57b2
commit 8b7d2fe312
9 changed files with 1806 additions and 0 deletions

View File

@@ -101,6 +101,15 @@ from .inventory import (
NegativeInventoryException,
)
# Message exceptions
from .message import (
ConversationClosedException,
ConversationNotFoundException,
MessageAttachmentException,
MessageNotFoundException,
UnauthorizedConversationAccessException,
)
# Marketplace import job exceptions
from .marketplace_import_job import (
ImportJobAlreadyProcessingException,
@@ -374,4 +383,10 @@ __all__ = [
"ScanParseException",
"ViolationOperationException",
"InvalidViolationStatusException",
# Message exceptions
"ConversationNotFoundException",
"MessageNotFoundException",
"ConversationClosedException",
"MessageAttachmentException",
"UnauthorizedConversationAccessException",
]

63
app/exceptions/message.py Normal file
View File

@@ -0,0 +1,63 @@
# app/exceptions/message.py
"""
Messaging specific exceptions.
"""
from .base import BusinessLogicException, ResourceNotFoundException, ValidationException
class ConversationNotFoundException(ResourceNotFoundException):
"""Raised when a conversation is not found."""
def __init__(self, conversation_identifier: str):
super().__init__(
resource_type="Conversation",
identifier=conversation_identifier,
message=f"Conversation '{conversation_identifier}' not found",
error_code="CONVERSATION_NOT_FOUND",
)
class MessageNotFoundException(ResourceNotFoundException):
"""Raised when a message is not found."""
def __init__(self, message_identifier: str):
super().__init__(
resource_type="Message",
identifier=message_identifier,
message=f"Message '{message_identifier}' not found",
error_code="MESSAGE_NOT_FOUND",
)
class ConversationClosedException(BusinessLogicException):
"""Raised when trying to send message to a closed conversation."""
def __init__(self, conversation_id: int):
super().__init__(
message=f"Cannot send message to closed conversation {conversation_id}",
error_code="CONVERSATION_CLOSED",
details={"conversation_id": conversation_id},
)
class MessageAttachmentException(ValidationException):
"""Raised when attachment validation fails."""
def __init__(self, message: str, details: dict | None = None):
super().__init__(
message=message,
error_code="MESSAGE_ATTACHMENT_INVALID",
details=details,
)
class UnauthorizedConversationAccessException(BusinessLogicException):
"""Raised when user tries to access a conversation they don't have access to."""
def __init__(self, conversation_id: int):
super().__init__(
message=f"You do not have access to conversation {conversation_id}",
error_code="CONVERSATION_ACCESS_DENIED",
details={"conversation_id": conversation_id},
)