Добавлены новые модели и мутации для управления товарами дня, лучшими ценами и топом продаж. Обновлены типы GraphQL и резолверы для обработки запросов, что улучшает функциональность и структуру данных. В боковое меню добавлены новые элементы для навигации по товарам. Это повышает удобство работы с приложением и расширяет возможности взаимодействия с API.

This commit is contained in:
Bivekich
2025-07-10 00:11:02 +03:00
parent 2c2ccf8876
commit c7dcb96c05
9 changed files with 2982 additions and 645 deletions

View File

@ -9,21 +9,19 @@ datasource db {
}
model User {
id String @id @default(cuid())
firstName String
lastName String
email String @unique
password String
avatar String?
role UserRole @default(ADMIN)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Связь с логами аудита
auditLogs AuditLog[]
id String @id @default(cuid())
firstName String
lastName String
email String @unique
password String
avatar String?
role UserRole @default(ADMIN)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
auditLogs AuditLog[]
balanceChanges ClientBalanceHistory[]
managedClients Client[]
productHistory ProductHistory[]
managedClients Client[] // Клиенты, которыми управляет менеджер
balanceChanges ClientBalanceHistory[] // История изменений баланса
@@map("users")
}
@ -31,103 +29,103 @@ model User {
model AuditLog {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
action AuditAction
details String?
ipAddress String?
userAgent String?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("audit_logs")
}
// Модели каталога товаров
model Category {
id String @id @default(cuid())
name String
slug String @unique
description String?
seoTitle String?
seoDescription String?
image String?
isHidden Boolean @default(false)
includeSubcategoryProducts Boolean @default(false)
parentId String?
parent Category? @relation("CategoryHierarchy", fields: [parentId], references: [id], onDelete: Cascade)
children Category[] @relation("CategoryHierarchy")
products Product[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
name String
slug String @unique
description String?
seoTitle String?
seoDescription String?
image String?
isHidden Boolean @default(false)
includeSubcategoryProducts Boolean @default(false)
parentId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
parent Category? @relation("CategoryHierarchy", fields: [parentId], references: [id], onDelete: Cascade)
children Category[] @relation("CategoryHierarchy")
products Product[] @relation("CategoryToProduct")
@@map("categories")
}
model Product {
id String @id @default(cuid())
name String
slug String @unique
article String? @unique
description String?
videoUrl String?
wholesalePrice Float?
retailPrice Float?
weight Float?
dimensions String? // ДхШхВ в формате "10x20x30"
unit String @default("шт")
isVisible Boolean @default(true)
applyDiscounts Boolean @default(true)
stock Int @default(0)
// Связи
categories Category[]
images ProductImage[]
options ProductOption[]
characteristics ProductCharacteristic[]
relatedProducts Product[] @relation("RelatedProducts")
relatedTo Product[] @relation("RelatedProducts")
accessoryProducts Product[] @relation("AccessoryProducts")
accessoryTo Product[] @relation("AccessoryProducts")
history ProductHistory[]
orderItems OrderItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
name String
slug String @unique
article String? @unique
description String?
videoUrl String?
wholesalePrice Float?
retailPrice Float?
weight Float?
dimensions String?
unit String @default("шт")
isVisible Boolean @default(true)
applyDiscounts Boolean @default(true)
stock Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
brand String?
bestPriceProducts BestPriceProduct?
dailyProducts DailyProduct[]
topSalesProducts TopSalesProduct?
orderItems OrderItem[]
characteristics ProductCharacteristic[]
history ProductHistory[]
images ProductImage[]
options ProductOption[]
products_AccessoryProducts_A Product[] @relation("AccessoryProducts")
products_AccessoryProducts_B Product[] @relation("AccessoryProducts")
categories Category[] @relation("CategoryToProduct")
products_RelatedProducts_A Product[] @relation("RelatedProducts")
products_RelatedProducts_B Product[] @relation("RelatedProducts")
@@map("products")
}
model ProductImage {
id String @id @default(cuid())
id String @id @default(cuid())
url String
alt String?
order Int @default(0)
order Int @default(0)
productId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@map("product_images")
}
model Option {
id String @id @default(cuid())
name String @unique
type OptionType @default(SINGLE)
values OptionValue[]
products ProductOption[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
name String @unique
type OptionType @default(SINGLE)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
values OptionValue[]
products ProductOption[]
@@map("options")
}
model OptionValue {
id String @id @default(cuid())
id String @id @default(cuid())
value String
price Float @default(0)
price Float @default(0)
optionId String
option Option @relation(fields: [optionId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
option Option @relation(fields: [optionId], references: [id], onDelete: Cascade)
products ProductOption[]
createdAt DateTime @default(now())
@@map("option_values")
}
@ -135,22 +133,22 @@ model OptionValue {
model ProductOption {
id String @id @default(cuid())
productId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
optionId String
option Option @relation(fields: [optionId], references: [id], onDelete: Cascade)
optionValueId String
option Option @relation(fields: [optionId], references: [id], onDelete: Cascade)
optionValue OptionValue @relation(fields: [optionValueId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@unique([productId, optionId, optionValueId])
@@map("product_options")
}
model Characteristic {
id String @id @default(cuid())
name String @unique
id String @id @default(cuid())
name String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
products ProductCharacteristic[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("characteristics")
}
@ -159,9 +157,9 @@ model ProductCharacteristic {
id String @id @default(cuid())
value String
productId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
characteristicId String
characteristic Characteristic @relation(fields: [characteristicId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@unique([productId, characteristicId])
@@map("product_characteristics")
@ -170,16 +168,526 @@ model ProductCharacteristic {
model ProductHistory {
id String @id @default(cuid())
productId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
action String // CREATE, UPDATE, DELETE
changes Json? // JSON с изменениями
action String
changes Json?
userId String?
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
user User? @relation(fields: [userId], references: [id])
@@map("product_history")
}
model Client {
id String @id @default(cuid())
clientNumber String @unique
type ClientType @default(INDIVIDUAL)
name String
email String?
phone String
city String?
markup Float? @default(0)
isConfirmed Boolean @default(false)
profileId String?
managerId String?
balance Float @default(0)
comment String?
emailNotifications Boolean @default(true)
smsNotifications Boolean @default(true)
pushNotifications Boolean @default(false)
legalEntityType String?
legalEntityName String?
inn String?
kpp String?
ogrn String?
okpo String?
legalAddress String?
actualAddress String?
bankAccount String?
bankName String?
bankBik String?
correspondentAccount String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
balanceHistory ClientBalanceHistory[]
bankDetails ClientBankDetails[]
contacts ClientContact[]
contracts ClientContract[]
deliveryAddresses ClientDeliveryAddress[]
discounts ClientDiscount[]
legalEntities ClientLegalEntity[]
vehicles ClientVehicle[]
manager User? @relation(fields: [managerId], references: [id])
profile ClientProfile? @relation(fields: [profileId], references: [id])
favorites Favorite[]
orders Order[]
partsSearchHistory PartsSearchHistory[]
@@map("clients")
}
model Favorite {
id String @id @default(cuid())
clientId String
productId String?
offerKey String?
name String
brand String
article String
price Float?
currency String?
image String?
createdAt DateTime @default(now())
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@unique([clientId, productId, offerKey, article, brand])
@@map("favorites")
}
model ClientProfile {
id String @id @default(cuid())
code String @unique
name String @unique
description String?
baseMarkup Float @default(0)
autoSendInvoice Boolean @default(true)
vinRequestModule Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
clients Client[]
discountProfiles DiscountProfile[]
brandMarkups ProfileBrandMarkup[]
categoryMarkups ProfileCategoryMarkup[]
excludedBrands ProfileExcludedBrand[]
excludedCategories ProfileExcludedCategory[]
orderDiscounts ProfileOrderDiscount[]
paymentTypes ProfilePaymentType[]
priceRangeMarkups ProfilePriceRangeMarkup[]
supplierMarkups ProfileSupplierMarkup[]
@@map("client_profiles")
}
model ProfilePriceRangeMarkup {
id String @id @default(cuid())
profileId String
priceFrom Float
priceTo Float
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_price_range_markups")
}
model ProfileOrderDiscount {
id String @id @default(cuid())
profileId String
minOrderSum Float
discountType DiscountType @default(PERCENTAGE)
discountValue Float
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_order_discounts")
}
model ProfileSupplierMarkup {
id String @id @default(cuid())
profileId String
supplierName String
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_supplier_markups")
}
model ProfileBrandMarkup {
id String @id @default(cuid())
profileId String
brandName String
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_brand_markups")
}
model ProfileCategoryMarkup {
id String @id @default(cuid())
profileId String
categoryName String
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_category_markups")
}
model ProfileExcludedBrand {
id String @id @default(cuid())
profileId String
brandName String
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_excluded_brands")
}
model ProfileExcludedCategory {
id String @id @default(cuid())
profileId String
categoryName String
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_excluded_categories")
}
model ProfilePaymentType {
id String @id @default(cuid())
profileId String
paymentType PaymentType
isEnabled Boolean @default(true)
createdAt DateTime @default(now())
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@map("profile_payment_types")
}
model ClientVehicle {
id String @id @default(cuid())
clientId String
name String
vin String?
frame String?
licensePlate String?
brand String?
model String?
modification String?
year Int?
mileage Int?
comment String?
createdAt DateTime @default(now())
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("client_vehicles")
}
model PartsSearchHistory {
id String @id @default(cuid())
clientId String
searchQuery String
searchType SearchType
brand String?
articleNumber String?
vehicleBrand String?
vehicleModel String?
vehicleYear Int?
resultCount Int @default(0)
createdAt DateTime @default(now())
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("parts_search_history")
}
model ClientDeliveryAddress {
id String @id @default(cuid())
clientId String
name String
address String
deliveryType DeliveryType @default(COURIER)
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
apartment String?
contactPhone String?
deliveryTime String?
entrance String?
floor String?
intercom String?
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("client_delivery_addresses")
}
model ClientContact {
id String @id @default(cuid())
clientId String
phone String?
email String?
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("client_contacts")
}
model ClientContract {
id String @id @default(cuid())
clientId String
contractNumber String
contractDate DateTime
name String
ourLegalEntity String
clientLegalEntity String
balance Float @default(0)
currency String @default("RUB")
isActive Boolean @default(true)
isDefault Boolean @default(false)
contractType String
relationship String
paymentDelay Boolean @default(false)
creditLimit Float?
delayDays Int?
fileUrl String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
balanceInvoices BalanceInvoice[]
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("client_contracts")
}
model BalanceInvoice {
id String @id @default(cuid())
contractId String
amount Float
currency String @default("RUB")
status InvoiceStatus @default(PENDING)
invoiceNumber String @unique
qrCode String
pdfUrl String?
paymentUrl String?
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
contract ClientContract @relation(fields: [contractId], references: [id], onDelete: Cascade)
@@map("balance_invoices")
}
model ClientLegalEntity {
id String @id @default(cuid())
clientId String
shortName String
fullName String
form String
legalAddress String
actualAddress String?
taxSystem String
responsiblePhone String?
responsiblePosition String?
responsibleName String?
accountant String?
signatory String?
registrationReasonCode String?
ogrn String?
inn String
vatPercent Float @default(20)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
bankDetails ClientBankDetails[]
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("client_legal_entities")
}
model ClientBankDetails {
id String @id @default(cuid())
clientId String
legalEntityId String?
name String
accountNumber String
bankName String
bik String
correspondentAccount String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
legalEntity ClientLegalEntity? @relation(fields: [legalEntityId], references: [id])
@@map("client_bank_details")
}
model ClientBalanceHistory {
id String @id @default(cuid())
clientId String
userId String?
oldValue Float
newValue Float
comment String?
createdAt DateTime @default(now())
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
user User? @relation(fields: [userId], references: [id])
@@map("client_balance_history")
}
model ClientDiscount {
id String @id @default(cuid())
clientId String
name String
type DiscountType
value Float
isActive Boolean @default(true)
validFrom DateTime?
validTo DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
@@map("client_discounts")
}
model ClientStatus {
id String @id @default(cuid())
name String @unique
color String @default("#6B7280")
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_statuses")
}
model Discount {
id String @id @default(cuid())
name String
type DiscountCodeType @default(DISCOUNT)
code String? @unique
minOrderAmount Float? @default(0)
discountType DiscountType @default(PERCENTAGE)
discountValue Float
isActive Boolean @default(true)
validFrom DateTime?
validTo DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
profiles DiscountProfile[]
@@map("discounts")
}
model DiscountProfile {
id String @id @default(cuid())
discountId String
profileId String
createdAt DateTime @default(now())
discount Discount @relation(fields: [discountId], references: [id], onDelete: Cascade)
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
@@unique([discountId, profileId])
@@map("discount_profiles")
}
model Order {
id String @id @default(cuid())
orderNumber String @unique
clientId String?
clientEmail String?
clientPhone String?
clientName String?
status OrderStatus @default(PENDING)
totalAmount Float
discountAmount Float @default(0)
finalAmount Float
currency String @default("RUB")
deliveryAddress String?
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
items OrderItem[]
client Client? @relation(fields: [clientId], references: [id])
payments Payment[]
@@map("orders")
}
model OrderItem {
id String @id @default(cuid())
orderId String
productId String?
externalId String?
name String
article String?
brand String?
price Float
quantity Int
totalPrice Float
createdAt DateTime @default(now())
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
product Product? @relation(fields: [productId], references: [id])
@@map("order_items")
}
model Payment {
id String @id @default(cuid())
orderId String
yookassaPaymentId String @unique
status PaymentStatus @default(PENDING)
amount Float
currency String @default("RUB")
paymentMethod String?
description String?
confirmationUrl String?
metadata Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
paidAt DateTime?
canceledAt DateTime?
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
@@map("payments")
}
model DailyProduct {
id String @id @default(cuid())
productId String
displayDate DateTime
discount Float?
isActive Boolean @default(true)
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@unique([productId, displayDate])
@@map("daily_products")
}
model BestPriceProduct {
id String @id @default(cuid())
productId String @unique
discount Float?
isActive Boolean @default(true)
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@map("best_price_products")
}
model TopSalesProduct {
id String @id @default(cuid())
productId String @unique
isActive Boolean @default(true)
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@map("top_sales_products")
}
enum UserRole {
ADMIN
MODERATOR
@ -208,591 +716,72 @@ enum OptionType {
MULTIPLE
}
// Модели для клиентов
model Client {
id String @id @default(cuid())
clientNumber String @unique
type ClientType @default(INDIVIDUAL)
name String
email String?
phone String
city String?
markup Float? @default(0)
isConfirmed Boolean @default(false)
profileId String?
profile ClientProfile? @relation(fields: [profileId], references: [id])
managerId String? // Личный менеджер
manager User? @relation(fields: [managerId], references: [id])
balance Float @default(0)
comment String?
// Уведомления
emailNotifications Boolean @default(true)
smsNotifications Boolean @default(true)
pushNotifications Boolean @default(false)
// Поля для юридических лиц
legalEntityType String? // ООО, ИП, АО и т.д.
legalEntityName String? // Наименование юрлица
inn String?
kpp String?
ogrn String?
okpo String?
legalAddress String?
actualAddress String?
bankAccount String?
bankName String?
bankBik String?
correspondentAccount String?
// Связи
vehicles ClientVehicle[]
discounts ClientDiscount[]
deliveryAddresses ClientDeliveryAddress[]
contacts ClientContact[]
contracts ClientContract[]
legalEntities ClientLegalEntity[]
bankDetails ClientBankDetails[]
balanceHistory ClientBalanceHistory[]
orders Order[]
partsSearchHistory PartsSearchHistory[]
favorites Favorite[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("clients")
}
// Модель для избранных товаров
model Favorite {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
// Данные о товаре - для внешних товаров (AutoEuro, PartsAPI)
productId String? // ID товара во внешней системе или внутренний ID
offerKey String? // Ключ предложения (для AutoEuro)
name String // Название товара
brand String // Бренд
article String // Артикул
price Float? // Цена (может отсутствовать)
currency String? // Валюта
image String? // URL изображения
createdAt DateTime @default(now())
// Уникальность по клиенту и комбинации идентификаторов товара
@@unique([clientId, productId, offerKey, article, brand])
@@map("favorites")
}
model ClientProfile {
id String @id @default(cuid())
code String @unique
name String @unique
description String?
baseMarkup Float @default(0)
autoSendInvoice Boolean @default(true)
vinRequestModule Boolean @default(false)
clients Client[]
// Связи с дополнительными настройками
priceRangeMarkups ProfilePriceRangeMarkup[]
orderDiscounts ProfileOrderDiscount[]
supplierMarkups ProfileSupplierMarkup[]
brandMarkups ProfileBrandMarkup[]
categoryMarkups ProfileCategoryMarkup[]
excludedBrands ProfileExcludedBrand[]
excludedCategories ProfileExcludedCategory[]
paymentTypes ProfilePaymentType[]
discountProfiles DiscountProfile[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_profiles")
}
// Наценки от стоимости товара
model ProfilePriceRangeMarkup {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
priceFrom Float
priceTo Float
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
@@map("profile_price_range_markups")
}
// Скидки от суммы заказа
model ProfileOrderDiscount {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
minOrderSum Float
discountType DiscountType @default(PERCENTAGE)
discountValue Float
createdAt DateTime @default(now())
@@map("profile_order_discounts")
}
// Наценки на поставщиков
model ProfileSupplierMarkup {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
supplierName String
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
@@map("profile_supplier_markups")
}
// Наценки на бренды
model ProfileBrandMarkup {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
brandName String
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
@@map("profile_brand_markups")
}
// Наценки на категории товаров
model ProfileCategoryMarkup {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
categoryName String
markupType MarkupType @default(PERCENTAGE)
markupValue Float
createdAt DateTime @default(now())
@@map("profile_category_markups")
}
// Исключенные бренды
model ProfileExcludedBrand {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
brandName String
createdAt DateTime @default(now())
@@map("profile_excluded_brands")
}
// Исключенные категории
model ProfileExcludedCategory {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
categoryName String
createdAt DateTime @default(now())
@@map("profile_excluded_categories")
}
// Типы платежей для профиля
model ProfilePaymentType {
id String @id @default(cuid())
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
paymentType PaymentType
isEnabled Boolean @default(true)
createdAt DateTime @default(now())
@@map("profile_payment_types")
}
enum MarkupType {
PERCENTAGE // Процентная наценка
FIXED_AMOUNT // Фиксированная сумма
PERCENTAGE
FIXED_AMOUNT
}
enum PaymentType {
CASH // Наличные
CARD // Банковская карта
BANK_TRANSFER // Банковский перевод
ONLINE // Онлайн платежи
CREDIT // В кредит
}
model ClientVehicle {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
name String // Название авто
vin String?
frame String?
licensePlate String?
brand String?
model String?
modification String?
year Int?
mileage Int?
comment String?
createdAt DateTime @default(now())
@@map("client_vehicles")
}
// История поиска запчастей
model PartsSearchHistory {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
searchQuery String // Поисковый запрос
searchType SearchType // Тип поиска
brand String? // Бренд (если искали по бренду)
articleNumber String? // Артикул (если искали по артикулу)
// Информация об автомобиле (если поиск был для конкретного авто)
vehicleBrand String?
vehicleModel String?
vehicleYear Int?
resultCount Int @default(0) // Количество найденных результатов
createdAt DateTime @default(now())
@@map("parts_search_history")
CASH
CARD
BANK_TRANSFER
ONLINE
CREDIT
}
enum SearchType {
TEXT // Текстовый поиск
ARTICLE // Поиск по артикулу
OEM // Поиск по OEM номеру
VIN // Поиск автомобиля по VIN/Frame
PLATE // Поиск автомобиля по госномеру
WIZARD // Поиск автомобиля по параметрам
PART_VEHICLES // Поиск автомобилей по артикулу детали
}
// Адреса доставки
model ClientDeliveryAddress {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
name String // Название адреса
address String // Полный адрес
deliveryType DeliveryType @default(COURIER)
comment String?
// Дополнительные поля для курьерской доставки
entrance String? // Подъезд
floor String? // Этаж
apartment String? // Квартира/офис
intercom String? // Домофон
deliveryTime String? // Желаемое время доставки
contactPhone String? // Контактный телефон
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_delivery_addresses")
}
// Контакты
model ClientContact {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
phone String?
email String?
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_contacts")
}
// Договоры
model ClientContract {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
contractNumber String
contractDate DateTime
name String
ourLegalEntity String // Наше ЮЛ
clientLegalEntity String // ЮЛ клиента
balance Float @default(0)
currency String @default("RUB")
isActive Boolean @default(true)
isDefault Boolean @default(false)
contractType String // Тип договора
relationship String // Отношение
paymentDelay Boolean @default(false)
creditLimit Float?
delayDays Int?
fileUrl String? // Ссылка на файл договора
balanceInvoices BalanceInvoice[] // Счета на пополнение баланса
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_contracts")
}
// Счета на пополнение баланса
model BalanceInvoice {
id String @id @default(cuid())
contractId String
contract ClientContract @relation(fields: [contractId], references: [id], onDelete: Cascade)
amount Float
currency String @default("RUB")
status InvoiceStatus @default(PENDING)
invoiceNumber String @unique
qrCode String // QR код для оплаты
pdfUrl String? // Ссылка на PDF счета
paymentUrl String? // Ссылка на оплату
expiresAt DateTime // Срок действия счета
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("balance_invoices")
TEXT
ARTICLE
OEM
VIN
PLATE
WIZARD
PART_VEHICLES
}
enum InvoiceStatus {
PENDING // Ожидает оплаты
PAID // Оплачен
EXPIRED // Просрочен
CANCELLED // Отменен
}
// Юридические лица клиента
model ClientLegalEntity {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
shortName String // Короткое наименование
fullName String // Полное наименование
form String // Форма (ООО, ИП и т.д.)
legalAddress String // Юридический адрес
actualAddress String? // Фактический адрес
taxSystem String // Система налогообложения
responsiblePhone String? // Телефон ответственного
responsiblePosition String? // Должность ответственного
responsibleName String? // ФИО ответственного
accountant String? // Бухгалтер
signatory String? // Подписант
registrationReasonCode String? // Код причины постановки на учет
ogrn String? // ОГРН
inn String // ИНН
vatPercent Float @default(20) // НДС в процентах
bankDetails ClientBankDetails[] // Банковские реквизиты
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_legal_entities")
}
// Банковские реквизиты
model ClientBankDetails {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
legalEntityId String?
legalEntity ClientLegalEntity? @relation(fields: [legalEntityId], references: [id])
name String // Название реквизитов
accountNumber String // Расчетный счет
bankName String // Наименование банка
bik String // БИК
correspondentAccount String // Корреспондентский счет
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_bank_details")
}
// История изменения баланса
model ClientBalanceHistory {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
userId String?
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
oldValue Float
newValue Float
comment String?
createdAt DateTime @default(now())
@@map("client_balance_history")
}
model ClientDiscount {
id String @id @default(cuid())
clientId String
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
name String
type DiscountType
value Float // процент или фиксированная сумма
isActive Boolean @default(true)
validFrom DateTime?
validTo DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_discounts")
}
model ClientStatus {
id String @id @default(cuid())
name String @unique
color String @default("#6B7280")
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("client_statuses")
PENDING
PAID
EXPIRED
CANCELLED
}
enum ClientType {
INDIVIDUAL // Физическое лицо
LEGAL_ENTITY // Юридическое лицо
INDIVIDUAL
LEGAL_ENTITY
}
enum DiscountType {
PERCENTAGE // Процентная скидка
FIXED_AMOUNT // Фиксированная сумма
}
// Модели для скидок и промокодов
model Discount {
id String @id @default(cuid())
name String
type DiscountCodeType @default(DISCOUNT)
code String? @unique // Промокод (если есть)
minOrderAmount Float? @default(0)
discountType DiscountType @default(PERCENTAGE)
discountValue Float
isActive Boolean @default(true)
validFrom DateTime?
validTo DateTime?
// Связи с профилями
profiles DiscountProfile[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("discounts")
}
// Связь скидок с профилями клиентов
model DiscountProfile {
id String @id @default(cuid())
discountId String
discount Discount @relation(fields: [discountId], references: [id], onDelete: Cascade)
profileId String
profile ClientProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@unique([discountId, profileId])
@@map("discount_profiles")
PERCENTAGE
FIXED_AMOUNT
}
enum DiscountCodeType {
DISCOUNT // Обычная скидка
PROMOCODE // Промокод
DISCOUNT
PROMOCODE
}
enum DeliveryType {
COURIER // Курьер
PICKUP // Самовывоз
POST // Почта России
TRANSPORT // Транспортная компания
}
// Модели для заказов и платежей
model Order {
id String @id @default(cuid())
orderNumber String @unique
clientId String?
client Client? @relation(fields: [clientId], references: [id], onDelete: SetNull)
clientEmail String? // Для гостевых заказов
clientPhone String? // Для гостевых заказов
clientName String? // Для гостевых заказов
status OrderStatus @default(PENDING)
totalAmount Float
discountAmount Float @default(0)
finalAmount Float // totalAmount - discountAmount
currency String @default("RUB")
items OrderItem[]
payments Payment[]
deliveryAddress String?
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("orders")
}
model OrderItem {
id String @id @default(cuid())
orderId String
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
productId String? // Для внутренних товаров
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
// Для внешних товаров (AutoEuro)
externalId String? // ID товара во внешней системе
name String // Название товара
article String? // Артикул
brand String? // Бренд
price Float // Цена за единицу
quantity Int // Количество
totalPrice Float // price * quantity
createdAt DateTime @default(now())
@@map("order_items")
}
model Payment {
id String @id @default(cuid())
orderId String
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
yookassaPaymentId String @unique // ID платежа в YooKassa
status PaymentStatus @default(PENDING)
amount Float
currency String @default("RUB")
paymentMethod String? // Способ оплаты
description String?
confirmationUrl String? // URL для подтверждения платежа
// Метаданные от YooKassa
metadata Json?
// Даты
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
paidAt DateTime? // Дата успешной оплаты
canceledAt DateTime? // Дата отмены
@@map("payments")
COURIER
PICKUP
POST
TRANSPORT
}
enum OrderStatus {
PENDING // Ожидает оплаты
PAID // Оплачен
PROCESSING // В обработке
SHIPPED // Отправлен
DELIVERED // Доставлен
CANCELED // Отменен
REFUNDED // Возвращен
PENDING
PAID
PROCESSING
SHIPPED
DELIVERED
CANCELED
REFUNDED
}
enum PaymentStatus {
PENDING // Ожидает оплаты
WAITING_FOR_CAPTURE // Ожидает подтверждения
SUCCEEDED // Успешно оплачен
CANCELED // Отменен
REFUNDED // Возвращен
PENDING
WAITING_FOR_CAPTURE
SUCCEEDED
CANCELED
REFUNDED
}