// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // Модель пользователя model User { id String @id @default(cuid()) phone String @unique avatar String? // URL аватара в S3 managerName String? // Имя управляющего createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Связь с организацией organization Organization? @relation(fields: [organizationId], references: [id]) organizationId String? // SMS коды для авторизации smsCodes SmsCode[] // Отправленные сообщения sentMessages Message[] @relation("SentMessages") @@map("users") } // Модель для SMS кодов model SmsCode { id String @id @default(cuid()) code String phone String expiresAt DateTime isUsed Boolean @default(false) attempts Int @default(0) maxAttempts Int @default(3) createdAt DateTime @default(now()) // Связь с пользователем user User? @relation(fields: [userId], references: [id]) userId String? @@map("sms_codes") } // Модель организации model Organization { id String @id @default(cuid()) inn String @unique kpp String? // КПП name String? // Краткое наименование fullName String? // Полное наименование ogrn String? // ОГРН организации ogrnDate DateTime? // Дата выдачи ОГРН type OrganizationType createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Адрес организации address String? // Адрес одной строкой addressFull String? // Полный адрес с индексом // Статус организации status String? // ACTIVE, LIQUIDATED и т.д. actualityDate DateTime? // Дата последних изменений registrationDate DateTime? // Дата регистрации liquidationDate DateTime? // Дата ликвидации // Руководитель managementName String? // ФИО или наименование руководителя managementPost String? // Должность руководителя // ОПФ (Организационно-правовая форма) opfCode String? // Код ОКОПФ opfFull String? // Полное название ОПФ opfShort String? // Краткое название ОПФ // Коды статистики okato String? // Код ОКАТО oktmo String? // Код ОКТМО okpo String? // Код ОКПО okved String? // Основной код ОКВЭД // Контакты phones Json? // Массив телефонов emails Json? // Массив email адресов // Финансовые данные employeeCount Int? // Численность сотрудников revenue BigInt? // Выручка taxSystem String? // Система налогообложения // Полные данные из DaData (для полноты) dadataData Json? // Связи users User[] apiKeys ApiKey[] // Связи контрагентов sentRequests CounterpartyRequest[] @relation("SentRequests") receivedRequests CounterpartyRequest[] @relation("ReceivedRequests") organizationCounterparties Counterparty[] @relation("OrganizationCounterparties") counterpartyOf Counterparty[] @relation("CounterpartyOf") // Сообщения sentMessages Message[] @relation("SentMessages") receivedMessages Message[] @relation("ReceivedMessages") // Услуги и расходники (только для фулфилмент центров) services Service[] supplies Supply[] // Товары (только для оптовиков) products Product[] // Корзины carts Cart[] // Избранные товары favorites Favorites[] @@map("organizations") } // Модель для API ключей маркетплейсов model ApiKey { id String @id @default(cuid()) marketplace MarketplaceType apiKey String isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Данные для валидации (например, информация о продавце) validationData Json? // Связь с организацией organization Organization @relation(fields: [organizationId], references: [id]) organizationId String @@unique([organizationId, marketplace]) @@map("api_keys") } // Тип организации enum OrganizationType { FULFILLMENT // Фулфилмент SELLER // Селлер LOGIST // Логистика WHOLESALE // Оптовик } // Тип маркетплейса enum MarketplaceType { WILDBERRIES OZON } // Модель для заявок на добавление в контрагенты model CounterpartyRequest { id String @id @default(cuid()) status CounterpartyRequestStatus @default(PENDING) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Кто отправил заявку sender Organization @relation("SentRequests", fields: [senderId], references: [id]) senderId String // Кому отправили заявку receiver Organization @relation("ReceivedRequests", fields: [receiverId], references: [id]) receiverId String // Комментарий к заявке message String? @@unique([senderId, receiverId]) @@map("counterparty_requests") } // Модель для связей контрагентов model Counterparty { id String @id @default(cuid()) createdAt DateTime @default(now()) // Основная организация organization Organization @relation("OrganizationCounterparties", fields: [organizationId], references: [id]) organizationId String // Контрагент counterparty Organization @relation("CounterpartyOf", fields: [counterpartyId], references: [id]) counterpartyId String @@unique([organizationId, counterpartyId]) @@map("counterparties") } // Статус заявки на добавление в контрагенты enum CounterpartyRequestStatus { PENDING // Ожидает ответа ACCEPTED // Принята REJECTED // Отклонена CANCELLED // Отменена отправителем } // Модель сообщений в мессенджере model Message { id String @id @default(cuid()) content String? // Текст сообщения (nullable для медиа) type MessageType @default(TEXT) voiceUrl String? // URL голосового файла в S3 voiceDuration Int? // Длительность голосового сообщения в секундах fileUrl String? // URL файла/изображения в S3 fileName String? // Оригинальное имя файла fileSize Int? // Размер файла в байтах fileType String? // MIME тип файла isRead Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Отправитель sender User @relation("SentMessages", fields: [senderId], references: [id]) senderId String senderOrganization Organization @relation("SentMessages", fields: [senderOrganizationId], references: [id]) senderOrganizationId String // Получатель receiverOrganization Organization @relation("ReceivedMessages", fields: [receiverOrganizationId], references: [id]) receiverOrganizationId String @@index([senderOrganizationId, receiverOrganizationId, createdAt]) @@index([receiverOrganizationId, isRead]) @@map("messages") } // Типы сообщений enum MessageType { TEXT VOICE IMAGE FILE } // Модель услуг (для фулфилмент центров) model Service { id String @id @default(cuid()) name String description String? price Decimal @db.Decimal(10,2) // Цена за единицу imageUrl String? // URL фотографии в S3 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Связь с организацией organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) organizationId String @@map("services") } // Модель расходников (для фулфилмент центров) model Supply { id String @id @default(cuid()) name String description String? price Decimal @db.Decimal(10,2) // Цена за единицу quantity Int @default(0) // Количество в наличии imageUrl String? // URL фотографии в S3 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Связь с организацией organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) organizationId String @@map("supplies") } // Модель категорий товаров model Category { id String @id @default(cuid()) name String @unique // Название категории createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Связь с товарами products Product[] @@map("categories") } // Модель товаров (для оптовиков) model Product { id String @id @default(cuid()) // Основные поля name String // Название товара article String // Артикул/номер записи description String? // Описание // Цена и количество price Decimal @db.Decimal(12,2) // Цена за единицу quantity Int @default(0) // Количество в наличии // Основные характеристики category Category? @relation(fields: [categoryId], references: [id]) categoryId String? // ID категории brand String? // Бренд // Дополнительные характеристики (необязательные) color String? // Цвет size String? // Размер weight Decimal? @db.Decimal(8,3) // Вес в кг dimensions String? // Габариты (ДxШxВ) material String? // Материал // Изображения (JSON массив URL-ов в S3) images Json @default("[]") // Массив URL изображений mainImage String? // URL главного изображения // Статус товара isActive Boolean @default(true) // Активен ли товар // Временные метки createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Связь с организацией (только оптовики) organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) organizationId String // Связь с элементами корзины cartItems CartItem[] // Избранные товары favorites Favorites[] // Уникальность артикула в рамках организации @@unique([organizationId, article]) @@map("products") } // Модель корзины model Cart { id String @id @default(cuid()) // Связь с организацией (только покупатель может иметь корзину) organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) organizationId String @unique // У каждой организации может быть только одна корзина // Элементы корзины items CartItem[] // Временные метки createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("carts") } // Модель элемента корзины model CartItem { id String @id @default(cuid()) // Связь с корзиной cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade) cartId String // Связь с товаром product Product @relation(fields: [productId], references: [id], onDelete: Cascade) productId String // Количество товара в корзине quantity Int @default(1) // Временные метки createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Уникальность: один товар может быть только один раз в корзине @@unique([cartId, productId]) @@map("cart_items") } // Модель избранных товаров model Favorites { id String @id @default(cuid()) // Связь с организацией (пользователь может добавлять товары в избранное) organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) organizationId String // Связь с товаром product Product @relation(fields: [productId], references: [id], onDelete: Cascade) productId String // Временные метки createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Уникальность: один товар может быть только один раз в избранном у организации @@unique([organizationId, productId]) @@map("favorites") }