// Prisma schema for Estimate Assistant generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // Справочники базовых цен (СБЦ) model PriceBook { id String @id @default(uuid()) code String @unique // SBC-GEODESY-2004, SBC-GEOLOGY-1999 name String // Полное название справочника baseDate DateTime // Дата базовых цен (01.01.2001, 01.01.1991) approvedBy String? // Кем утвержден effectiveDate DateTime? // Дата введения в действие isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tables PriceTable[] items PriceItem[] } // Таблицы справочников model PriceTable { id String @id @default(uuid()) priceBookId String tableNumber Int // Номер таблицы (8, 9, 13, и т.д.) name String // Название таблицы unit String // Единица измерения (1 пункт, 1 га, 1 км и т.д.) notes Json? // Примечания к таблице createdAt DateTime @default(now()) updatedAt DateTime @updatedAt priceBook PriceBook @relation(fields: [priceBookId], references: [id], onDelete: Cascade) items PriceItem[] @@unique([priceBookId, tableNumber]) } // Позиции справочников (расценки) model PriceItem { id String @id @default(uuid()) priceBookId String priceTableId String paragraph String // Номер параграфа (8-1, 9-4-1 и т.д.) workType String // Тип работы / наименование description String? // Дополнительное описание // Цены (полевые/камеральные для разных категорий) priceField1 Decimal? @db.Decimal(12, 2) // Полевые работы, категория 1 priceOffice1 Decimal? @db.Decimal(12, 2) // Камеральные работы, категория 1 priceField2 Decimal? @db.Decimal(12, 2) // Полевые работы, категория 2 priceOffice2 Decimal? @db.Decimal(12, 2) // Камеральные работы, категория 2 priceField3 Decimal? @db.Decimal(12, 2) // Полевые работы, категория 3 priceOffice3 Decimal? @db.Decimal(12, 2) // Камеральные работы, категория 3 priceSimple Decimal? @db.Decimal(12, 2) // Простая цена (без категорий) // Дополнительные параметры attributes Json? // Доп. атрибуты (масштаб, глубина, диаметр и т.д.) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt priceBook PriceBook @relation(fields: [priceBookId], references: [id], onDelete: Cascade) priceTable PriceTable @relation(fields: [priceTableId], references: [id], onDelete: Cascade) estimateItems EstimateItem[] @@index([paragraph]) @@index([workType]) } // Коэффициенты model Coefficient { id String @id @default(uuid()) type String // regional, transport_internal, transport_external, seasonal, special code String // Уникальный код коэффициента name String // Название value Decimal @db.Decimal(6, 4) // Значение коэффициента description String? // Описание conditions Json? // Условия применения isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([type, code]) } // Индексы инфляции (перевод в текущие цены) model InflationIndex { id String @id @default(uuid()) baseDate DateTime // Базовая дата цен effectiveFrom DateTime // Дата начала действия индекса effectiveTo DateTime? // Дата окончания (null = текущий) indexValue Decimal @db.Decimal(10, 4) // Значение индекса documentRef String? // Ссылка на документ (Письмо Минстроя и т.д.) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } // Пользователи model User { id String @id @default(uuid()) email String @unique passwordHash String name String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt estimates Estimate[] chatSessions ChatSession[] ownedShares EstimateShare[] @relation("ShareOwner") receivedShares EstimateShare[] @relation("ShareReceiver") shareNotes EstimateShareNote[] } // Направления изысканий model SurveyDirection { id String @id @default(uuid()) code String @unique // geodesy, geology, ecology, hydrology name String // Инженерно-геодезические изыскания shortName String // Геодезия isActive Boolean @default(true) estimates Estimate[] } // Сметы model Estimate { id String @id @default(uuid()) number String // Номер сметы directionId String ownerId String // Владелец сметы objectName String // Название объекта customer String // Заказчик executor String // Исполнитель // Итоговые значения totalFieldWorks Decimal? @db.Decimal(14, 2) // Итого полевые работы totalOfficeWorks Decimal? @db.Decimal(14, 2) // Итого камеральные работы totalLaboratory Decimal? @db.Decimal(14, 2) // Итого лабораторные subtotal Decimal? @db.Decimal(14, 2) // Итого по изысканиям // Коэффициенты и пересчет regionalCoef Decimal? @db.Decimal(6, 4) // Районный коэффициент regionalCoefDocRef String? // Описание (С районным коэффициентом и т.д.) inflationIndex Decimal? @db.Decimal(10, 4) // Индекс перевода в текущие цены inflationDocRef String? // Ссылка на документ (Письмо Минстроя и т.д.) companyCoef Decimal? @db.Decimal(6, 4) // Коэффициент компании (Газпром и т.д.) companyCoefDocRef String? // Описание (Коэффициент ОАО «Газпром» №544 и т.д.) executorCoef Decimal? @db.Decimal(6, 4) // Коэффициент исполнителя executorCoefDocRef String? // Описание (Коэффициент ООО «ГеоВектор» и т.д.) // Итоги withVat Boolean @default(true) // Смета с НДС (true) или без НДС (false) totalWithoutVat Decimal? @db.Decimal(14, 2) // Итого без НДС vatRate Decimal? @db.Decimal(4, 2) // Ставка НДС (18, 20, 7) vatAmount Decimal? @db.Decimal(14, 2) // Сумма НДС totalWithVat Decimal? @db.Decimal(14, 2) // Всего с НДС status String @default("draft") // draft, completed, approved createdAt DateTime @default(now()) updatedAt DateTime @updatedAt owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) direction SurveyDirection @relation(fields: [directionId], references: [id]) items EstimateItem[] totals EstimateTotal[] shares EstimateShare[] versions EstimateVersion[] } // История версий сметы (снимок при сохранении/пересчёте) model EstimateVersion { id String @id @default(uuid()) estimateId String versionNumber Int // Порядковый номер версии по смете snapshot Json // Полный снимок: estimate + items + totals createdAt DateTime @default(now()) estimate Estimate @relation(fields: [estimateId], references: [id], onDelete: Cascade) @@index([estimateId]) @@index([estimateId, createdAt]) } // Шаринг сметы с другим пользователем model EstimateShare { id String @id @default(uuid()) estimateId String ownerId String // Кто поделился sharedWithId String // С кем поделились createdAt DateTime @default(now()) estimate Estimate @relation(fields: [estimateId], references: [id], onDelete: Cascade) sharedWith User @relation("ShareReceiver", fields: [sharedWithId], references: [id], onDelete: Cascade) owner User @relation("ShareOwner", fields: [ownerId], references: [id], onDelete: Cascade) notes EstimateShareNote[] @@unique([estimateId, sharedWithId]) @@index([sharedWithId]) } // Заметки к шарингу сметы (кто что написал) model EstimateShareNote { id String @id @default(uuid()) shareId String authorId String content String @db.Text createdAt DateTime @default(now()) share EstimateShare @relation(fields: [shareId], references: [id], onDelete: Cascade) author User @relation(fields: [authorId], references: [id], onDelete: Cascade) @@index([shareId]) } // Позиции сметы model EstimateItem { id String @id @default(uuid()) estimateId String orderNumber Int // Порядковый номер sectionType String // field, office, laboratory, transport, other priceItemId String? // Ссылка на позицию справочника workName String // Наименование работы justification String? // Обоснование (ссылка на СБЦ) basePrice Decimal @db.Decimal(12, 2) // Базовая цена quantity Decimal @db.Decimal(12, 4) // Объем unit String? // Единица измерения // Коэффициенты coef1 Decimal? @db.Decimal(6, 4) // Коэффициент 1 coef1Desc String? // Описание коэффициента 1 coef2 Decimal? @db.Decimal(6, 4) // Коэффициент 2 coef2Desc String? // Описание коэффициента 2 coef3 Decimal? @db.Decimal(6, 4) // Коэффициент 3 coef3Desc String? // Описание коэффициента 3 totalPrice Decimal @db.Decimal(14, 2) // Итоговая стоимость createdAt DateTime @default(now()) updatedAt DateTime @updatedAt estimate Estimate @relation(fields: [estimateId], references: [id], onDelete: Cascade) priceItem PriceItem? @relation(fields: [priceItemId], references: [id]) @@index([estimateId, orderNumber]) } // Итоговая часть сметы (нижняя часть) model EstimateTotal { id String @id @default(uuid()) estimateId String orderNumber Int // Порядок строки label String // Название строки (Перевод в текущие цены, НДС и т.д.) description String? // Дополнительное описание baseValue Decimal? @db.Decimal(14, 2) // Базовое значение coefficient Decimal? @db.Decimal(10, 4) // Коэффициент/процент resultValue Decimal @db.Decimal(14, 2) // Результат createdAt DateTime @default(now()) updatedAt DateTime @updatedAt estimate Estimate @relation(fields: [estimateId], references: [id], onDelete: Cascade) @@index([estimateId, orderNumber]) } // Настройки приложения model Setting { id String @id @default(uuid()) key String @unique value String type String @default("string") // string, number, boolean, json category String // general, company, ai, display label String? // Человекочитаемое название createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } // Сессии чата (у каждого пользователя свои контексты ИИ) model ChatSession { id String @id @default(uuid()) userId String // Владелец сессии estimateId String? // Связанная смета (опционально) status String @default("active") // active, completed createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) messages ChatMessage[] @@index([userId]) @@index([userId, estimateId]) } // Сообщения чата model ChatMessage { id String @id @default(uuid()) sessionId String role String // user, assistant, system content String metadata Json? // Доп. данные (извлеченные сущности и т.д.) createdAt DateTime @default(now()) session ChatSession @relation(fields: [sessionId], references: [id], onDelete: Cascade) @@index([sessionId, createdAt]) }