diff --git a/prisma/migrations/20260118180043_add_chat_models/migration.sql b/prisma/migrations/20260118180043_add_chat_models/migration.sql new file mode 100644 index 0000000..9d1ccba --- /dev/null +++ b/prisma/migrations/20260118180043_add_chat_models/migration.sql @@ -0,0 +1,94 @@ +-- CreateTable +CREATE TABLE `ChatRoom` ( + `room_id` INTEGER NOT NULL AUTO_INCREMENT, + `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `last_message_id` INTEGER NULL, + `user_id1` INTEGER NOT NULL, + `user_id2` INTEGER NOT NULL, + + UNIQUE INDEX `ChatRoom_last_message_id_key`(`last_message_id`), + UNIQUE INDEX `ChatRoom_user_id1_user_id2_key`(`user_id1`, `user_id2`), + PRIMARY KEY (`room_id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `ChatMessage` ( + `message_id` INTEGER NOT NULL AUTO_INCREMENT, + `content` TEXT NULL, + `sent_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `sender_id` INTEGER NOT NULL, + `room_id` INTEGER NOT NULL, + + PRIMARY KEY (`message_id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `ChatParticipant` ( + `chat_participant_id` INTEGER NOT NULL AUTO_INCREMENT, + `is_pinned` BOOLEAN NOT NULL DEFAULT false, + `left_at` DATETIME(3) NULL, + `room_id` INTEGER NOT NULL, + `user_id` INTEGER NOT NULL, + `last_read_message_id` INTEGER NULL, + + UNIQUE INDEX `ChatParticipant_room_id_user_id_key`(`room_id`, `user_id`), + PRIMARY KEY (`chat_participant_id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `UserBlock` ( + `block_id` INTEGER NOT NULL AUTO_INCREMENT, + `blocked_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `blocker_id` INTEGER NOT NULL, + `blocked_id` INTEGER NOT NULL, + + UNIQUE INDEX `UserBlock_blocker_id_blocked_id_key`(`blocker_id`, `blocked_id`), + PRIMARY KEY (`block_id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `Attachment` ( + `attachment_id` INTEGER NOT NULL AUTO_INCREMENT, + `message_id` INTEGER NOT NULL, + `url` TEXT NOT NULL, + `type` ENUM('IMAGE', 'FILE') NOT NULL, + `name` VARCHAR(191) NOT NULL, + `size` INTEGER NOT NULL, + `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + + INDEX `Attachment_message_id_idx`(`message_id`), + PRIMARY KEY (`attachment_id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- AddForeignKey +ALTER TABLE `ChatRoom` ADD CONSTRAINT `ChatRoom_last_message_id_fkey` FOREIGN KEY (`last_message_id`) REFERENCES `ChatMessage`(`message_id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatRoom` ADD CONSTRAINT `ChatRoom_user_id1_fkey` FOREIGN KEY (`user_id1`) REFERENCES `User`(`user_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatRoom` ADD CONSTRAINT `ChatRoom_user_id2_fkey` FOREIGN KEY (`user_id2`) REFERENCES `User`(`user_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatMessage` ADD CONSTRAINT `ChatMessage_sender_id_fkey` FOREIGN KEY (`sender_id`) REFERENCES `User`(`user_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatMessage` ADD CONSTRAINT `ChatMessage_room_id_fkey` FOREIGN KEY (`room_id`) REFERENCES `ChatRoom`(`room_id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatParticipant` ADD CONSTRAINT `ChatParticipant_room_id_fkey` FOREIGN KEY (`room_id`) REFERENCES `ChatRoom`(`room_id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatParticipant` ADD CONSTRAINT `ChatParticipant_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `User`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ChatParticipant` ADD CONSTRAINT `ChatParticipant_last_read_message_id_fkey` FOREIGN KEY (`last_read_message_id`) REFERENCES `ChatMessage`(`message_id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `UserBlock` ADD CONSTRAINT `UserBlock_blocker_id_fkey` FOREIGN KEY (`blocker_id`) REFERENCES `User`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `UserBlock` ADD CONSTRAINT `UserBlock_blocked_id_fkey` FOREIGN KEY (`blocked_id`) REFERENCES `User`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `Attachment` ADD CONSTRAINT `Attachment_message_id_fkey` FOREIGN KEY (`message_id`) REFERENCES `ChatMessage`(`message_id`) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8c6fd8c..f35ebf8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -44,6 +44,14 @@ model User { UserBankAccount UserBankAccount? notificationSetting UserNotificationSetting? consents UserConsent[] + chatRoomAs1 ChatRoom[] @relation("ChatUser1") + chatRoomAs2 ChatRoom[] @relation("ChatUser2") + sentChatMessages ChatMessage[] @relation("UserSentMessages") + chatParticipants ChatParticipant[] + blocks UserBlock[] @relation("BlockerUser") + blockedBy UserBlock[] @relation("BlockedUser") + + } model UserConsent { @@ -467,6 +475,81 @@ model UserBankAccount { @@unique([preregistered_id, user_id], map: "uniq_userbank_prereg_user") } +model ChatRoom { + room_id Int @id @default(autoincrement()) + created_at DateTime @default(now()) + last_message_id Int? @unique + user_id1 Int + user_id2 Int + + lastMessage ChatMessage? @relation("lastMessage", fields: [last_message_id], references: [message_id], onDelete: SetNull) + user1 User @relation("ChatUser1", fields: [user_id1], references: [user_id]) + user2 User @relation("ChatUser2", fields: [user_id2], references: [user_id]) + + @@unique([user_id1, user_id2]) // 두 유저간 채팅방은 유일 + + messages ChatMessage[] @relation("RoomMessages") + participants ChatParticipant[] @relation("RoomParticipants") +} + +model ChatMessage { + message_id Int @id @default(autoincrement()) + content String? @db.Text + sent_at DateTime @default(now()) + sender_id Int + room_id Int + + user User @relation("UserSentMessages", fields: [sender_id], references: [user_id]) + chatRoom ChatRoom @relation("RoomMessages", fields: [room_id], references: [room_id], onDelete: Cascade) + + lastMessageOf ChatRoom? @relation("lastMessage") + readByParticipants ChatParticipant[] @relation("LastReadMessage") + + attachments Attachment[] +} + +model ChatParticipant { + chat_participant_id Int @id @default(autoincrement()) + is_pinned Boolean @default(false) + left_at DateTime? + room_id Int + user_id Int + last_read_message_id Int? + + chatRoom ChatRoom @relation("RoomParticipants", fields: [room_id], references: [room_id], onDelete: Cascade) + user User @relation(fields: [user_id], references: [user_id], onDelete: Cascade) + lastReadMessage ChatMessage? @relation("LastReadMessage", fields: [last_read_message_id], references: [message_id], onDelete: SetNull) + + @@unique([room_id, user_id]) +} + +model UserBlock { + block_id Int @id @default(autoincrement()) + blocked_at DateTime @default(now()) + blocker_id Int + blocked_id Int + + @@unique([blocker_id, blocked_id]) + + blockerUser User @relation("BlockerUser", fields: [blocker_id], references: [user_id], onDelete: Cascade) + blockedUser User @relation("BlockedUser", fields: [blocked_id], references: [user_id], onDelete: Cascade) + +} + +model Attachment { + attachment_id Int @id @default(autoincrement()) + message_id Int + url String @db.Text + type AttachmentType + name String + size Int + created_at DateTime @default(now()) + + attachmentMessage ChatMessage @relation(fields: [message_id], references: [message_id], onDelete: Cascade) + + @@index([message_id]) +} + enum Status { Pending Succeed @@ -513,4 +596,9 @@ enum userStatus { active banned deleted +} + +enum AttachmentType { + IMAGE + FILE } \ No newline at end of file