Реализация реферальной системы и улучшение системы авторизации
- Добавлена полная реферальная система с GraphQL резолверами и UI компонентами - Улучшена система регистрации с поддержкой ВКонтакте и реферальных ссылок - Обновлена схема Prisma для поддержки реферальной системы - Добавлены новые файлы документации правил системы - Улучшена система партнерства и контрагентов - Обновлены компоненты авторизации для поддержки новых функций - Удален устаревший server.log 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -2,7 +2,6 @@ generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
// Конфигурация для автоматического seeding
|
||||
generator seed {
|
||||
provider = "prisma-client-js"
|
||||
output = "./generated/client"
|
||||
@ -31,7 +30,7 @@ model User {
|
||||
model Admin {
|
||||
id String @id @default(cuid())
|
||||
username String @unique
|
||||
password String // Хеш пароля
|
||||
password String
|
||||
email String? @unique
|
||||
isActive Boolean @default(true)
|
||||
lastLogin DateTime?
|
||||
@ -89,6 +88,9 @@ model Organization {
|
||||
revenue BigInt?
|
||||
taxSystem String?
|
||||
dadataData Json?
|
||||
referralCode String? @unique
|
||||
referredById String?
|
||||
referralPoints Int @default(0)
|
||||
apiKeys ApiKey[]
|
||||
carts Cart?
|
||||
counterpartyOf Counterparty[] @relation("CounterpartyOf")
|
||||
@ -96,25 +98,31 @@ model Organization {
|
||||
receivedRequests CounterpartyRequest[] @relation("ReceivedRequests")
|
||||
sentRequests CounterpartyRequest[] @relation("SentRequests")
|
||||
employees Employee[]
|
||||
externalAds ExternalAd[] @relation("ExternalAds")
|
||||
favorites Favorites[]
|
||||
logistics Logistics[]
|
||||
receivedMessages Message[] @relation("ReceivedMessages")
|
||||
sentMessages Message[] @relation("SentMessages")
|
||||
referredBy Organization? @relation("ReferralRelation", fields: [referredById], references: [id])
|
||||
referrals Organization[] @relation("ReferralRelation")
|
||||
products Product[]
|
||||
referralTransactions ReferralTransaction[] @relation("ReferralTransactions")
|
||||
referrerTransactions ReferralTransaction[] @relation("ReferrerTransactions")
|
||||
sellerStatsCaches SellerStatsCache[] @relation("SellerStatsCaches")
|
||||
services Service[]
|
||||
supplies Supply[]
|
||||
users User[]
|
||||
logistics Logistics[]
|
||||
supplyOrders SupplyOrder[]
|
||||
partnerSupplyOrders SupplyOrder[] @relation("SupplyOrderPartner")
|
||||
sellerSupplies Supply[] @relation("SellerSupplies")
|
||||
fulfillmentSupplyOrders SupplyOrder[] @relation("SupplyOrderFulfillmentCenter")
|
||||
logisticsSupplyOrders SupplyOrder[] @relation("SupplyOrderLogistics")
|
||||
wildberriesSupplies WildberriesSupply[]
|
||||
supplyOrders SupplyOrder[]
|
||||
partnerSupplyOrders SupplyOrder[] @relation("SupplyOrderPartner")
|
||||
supplySuppliers SupplySupplier[] @relation("SupplySuppliers")
|
||||
externalAds ExternalAd[] @relation("ExternalAds")
|
||||
users User[]
|
||||
wbWarehouseCaches WBWarehouseCache[] @relation("WBWarehouseCaches")
|
||||
sellerStatsCaches SellerStatsCache[] @relation("SellerStatsCaches")
|
||||
sellerSupplies Supply[] @relation("SellerSupplies")
|
||||
wildberriesSupplies WildberriesSupply[]
|
||||
|
||||
@@index([referralCode])
|
||||
@@index([referredById])
|
||||
@@map("organizations")
|
||||
}
|
||||
|
||||
@ -149,14 +157,18 @@ model CounterpartyRequest {
|
||||
}
|
||||
|
||||
model Counterparty {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
organizationId String
|
||||
counterpartyId String
|
||||
counterparty Organization @relation("CounterpartyOf", fields: [counterpartyId], references: [id])
|
||||
organization Organization @relation("OrganizationCounterparties", fields: [organizationId], references: [id])
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
organizationId String
|
||||
counterpartyId String
|
||||
type CounterpartyType @default(MANUAL)
|
||||
triggeredBy String?
|
||||
triggerEntityId String?
|
||||
counterparty Organization @relation("CounterpartyOf", fields: [counterpartyId], references: [id])
|
||||
organization Organization @relation("OrganizationCounterparties", fields: [organizationId], references: [id])
|
||||
|
||||
@@unique([organizationId, counterpartyId])
|
||||
@@index([type])
|
||||
@@map("counterparties")
|
||||
}
|
||||
|
||||
@ -203,26 +215,26 @@ model Supply {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
price Decimal @db.Decimal(10, 2) // Цена закупки у поставщика (не меняется)
|
||||
pricePerUnit Decimal? @db.Decimal(10, 2) // Цена продажи селлерам (устанавливается фулфилментом)
|
||||
price Decimal @db.Decimal(10, 2)
|
||||
pricePerUnit Decimal? @db.Decimal(10, 2)
|
||||
quantity Int @default(0)
|
||||
unit String @default("шт")
|
||||
category String @default("Расходники")
|
||||
status String @default("planned") // planned, in-transit, delivered, in-stock
|
||||
status String @default("planned")
|
||||
date DateTime @default(now())
|
||||
supplier String @default("Не указан")
|
||||
minStock Int @default(0)
|
||||
currentStock Int @default(0)
|
||||
usedStock Int @default(0) // Количество использованных расходников
|
||||
usedStock Int @default(0)
|
||||
imageUrl String?
|
||||
type SupplyType @default(FULFILLMENT_CONSUMABLES) // Тип расходников
|
||||
sellerOwnerId String? // ID селлера-владельца (для расходников селлеров)
|
||||
sellerOwner Organization? @relation("SellerSupplies", fields: [sellerOwnerId], references: [id], onDelete: SetNull)
|
||||
shopLocation String? // Местоположение в магазине фулфилмента
|
||||
type SupplyType @default(FULFILLMENT_CONSUMABLES)
|
||||
sellerOwnerId String?
|
||||
shopLocation String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
sellerOwner Organization? @relation("SellerSupplies", fields: [sellerOwnerId], references: [id])
|
||||
|
||||
@@map("supplies")
|
||||
}
|
||||
@ -266,9 +278,9 @@ model Product {
|
||||
organizationId String
|
||||
cartItems CartItem[]
|
||||
favorites Favorites[]
|
||||
supplyOrderItems SupplyOrderItem[]
|
||||
category Category? @relation(fields: [categoryId], references: [id])
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
supplyOrderItems SupplyOrderItem[]
|
||||
|
||||
@@unique([organizationId, article])
|
||||
@@map("products")
|
||||
@ -401,6 +413,156 @@ model WildberriesSupplyCard {
|
||||
@@map("wildberries_supply_cards")
|
||||
}
|
||||
|
||||
model Logistics {
|
||||
id String @id @default(cuid())
|
||||
fromLocation String
|
||||
toLocation String
|
||||
priceUnder1m3 Float
|
||||
priceOver1m3 Float
|
||||
description String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
|
||||
@@map("logistics")
|
||||
}
|
||||
|
||||
model SupplyOrder {
|
||||
id String @id @default(cuid())
|
||||
partnerId String
|
||||
deliveryDate DateTime
|
||||
status SupplyOrderStatus @default(PENDING)
|
||||
totalAmount Decimal @db.Decimal(12, 2)
|
||||
totalItems Int
|
||||
fulfillmentCenterId String?
|
||||
logisticsPartnerId String?
|
||||
consumableType String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organizationId String
|
||||
items SupplyOrderItem[]
|
||||
fulfillmentCenter Organization? @relation("SupplyOrderFulfillmentCenter", fields: [fulfillmentCenterId], references: [id])
|
||||
logisticsPartner Organization? @relation("SupplyOrderLogistics", fields: [logisticsPartnerId], references: [id])
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
partner Organization @relation("SupplyOrderPartner", fields: [partnerId], references: [id])
|
||||
|
||||
@@map("supply_orders")
|
||||
}
|
||||
|
||||
model SupplyOrderItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String
|
||||
productId String
|
||||
quantity Int
|
||||
price Decimal @db.Decimal(12, 2)
|
||||
totalPrice Decimal @db.Decimal(12, 2)
|
||||
services String[] @default([])
|
||||
fulfillmentConsumables String[] @default([])
|
||||
sellerConsumables String[] @default([])
|
||||
marketplaceCardId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
supplyOrder SupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("supply_order_items")
|
||||
}
|
||||
|
||||
model SupplySupplier {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
contactName String
|
||||
phone String
|
||||
market String?
|
||||
address String?
|
||||
place String?
|
||||
telegram String?
|
||||
organizationId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("SupplySuppliers", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("supply_suppliers")
|
||||
}
|
||||
|
||||
model ExternalAd {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
url String
|
||||
cost Decimal @db.Decimal(12, 2)
|
||||
date DateTime
|
||||
nmId String
|
||||
clicks Int @default(0)
|
||||
organizationId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("ExternalAds", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([organizationId, date])
|
||||
@@map("external_ads")
|
||||
}
|
||||
|
||||
model WBWarehouseCache {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
cacheDate DateTime
|
||||
data Json
|
||||
totalProducts Int @default(0)
|
||||
totalStocks Int @default(0)
|
||||
totalReserved Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("WBWarehouseCaches", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([organizationId, cacheDate])
|
||||
@@index([organizationId, cacheDate])
|
||||
@@map("wb_warehouse_caches")
|
||||
}
|
||||
|
||||
model SellerStatsCache {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
cacheDate DateTime
|
||||
period String
|
||||
dateFrom DateTime?
|
||||
dateTo DateTime?
|
||||
productsData Json?
|
||||
productsTotalSales Decimal? @db.Decimal(15, 2)
|
||||
productsTotalOrders Int?
|
||||
productsCount Int?
|
||||
advertisingData Json?
|
||||
advertisingTotalCost Decimal? @db.Decimal(15, 2)
|
||||
advertisingTotalViews Int?
|
||||
advertisingTotalClicks Int?
|
||||
expiresAt DateTime
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("SellerStatsCaches", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([organizationId, cacheDate, period, dateFrom, dateTo])
|
||||
@@index([organizationId, cacheDate])
|
||||
@@index([expiresAt])
|
||||
@@map("seller_stats_caches")
|
||||
}
|
||||
|
||||
model ReferralTransaction {
|
||||
id String @id @default(cuid())
|
||||
referrerId String
|
||||
referralId String
|
||||
points Int
|
||||
type ReferralTransactionType
|
||||
description String?
|
||||
createdAt DateTime @default(now())
|
||||
referral Organization @relation("ReferralTransactions", fields: [referralId], references: [id])
|
||||
referrer Organization @relation("ReferrerTransactions", fields: [referrerId], references: [id])
|
||||
|
||||
@@index([referrerId, createdAt])
|
||||
@@index([referralId])
|
||||
@@map("referral_transactions")
|
||||
}
|
||||
|
||||
enum OrganizationType {
|
||||
FULFILLMENT
|
||||
SELLER
|
||||
@ -467,147 +629,20 @@ enum ProductType {
|
||||
}
|
||||
|
||||
enum SupplyType {
|
||||
FULFILLMENT_CONSUMABLES // Расходники фулфилмента (купленные фулфилментом для себя)
|
||||
SELLER_CONSUMABLES // Расходники селлеров (принятые от селлеров для хранения)
|
||||
FULFILLMENT_CONSUMABLES
|
||||
SELLER_CONSUMABLES
|
||||
}
|
||||
|
||||
model Logistics {
|
||||
id String @id @default(cuid())
|
||||
fromLocation String
|
||||
toLocation String
|
||||
priceUnder1m3 Float
|
||||
priceOver1m3 Float
|
||||
description String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
|
||||
@@map("logistics")
|
||||
enum CounterpartyType {
|
||||
MANUAL
|
||||
REFERRAL
|
||||
AUTO_BUSINESS
|
||||
AUTO
|
||||
}
|
||||
|
||||
model SupplyOrder {
|
||||
id String @id @default(cuid())
|
||||
partnerId String
|
||||
deliveryDate DateTime
|
||||
status SupplyOrderStatus @default(PENDING)
|
||||
totalAmount Decimal @db.Decimal(12, 2)
|
||||
totalItems Int
|
||||
fulfillmentCenterId String?
|
||||
logisticsPartnerId String? // Опциональная логистика - может назначить фулфилмент
|
||||
consumableType String? // Классификация расходников: FULFILLMENT_CONSUMABLES, SELLER_CONSUMABLES
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organizationId String
|
||||
items SupplyOrderItem[]
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
partner Organization @relation("SupplyOrderPartner", fields: [partnerId], references: [id])
|
||||
fulfillmentCenter Organization? @relation("SupplyOrderFulfillmentCenter", fields: [fulfillmentCenterId], references: [id])
|
||||
logisticsPartner Organization? @relation("SupplyOrderLogistics", fields: [logisticsPartnerId], references: [id])
|
||||
|
||||
@@map("supply_orders")
|
||||
}
|
||||
|
||||
model SupplyOrderItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String
|
||||
productId String
|
||||
quantity Int
|
||||
price Decimal @db.Decimal(12, 2)
|
||||
totalPrice Decimal @db.Decimal(12, 2)
|
||||
// Поля для рецептуры продукта
|
||||
services String[] @default([]) // ID услуг
|
||||
fulfillmentConsumables String[] @default([]) // ID расходников фулфилмента
|
||||
sellerConsumables String[] @default([]) // ID расходников селлера
|
||||
marketplaceCardId String? // ID карточки маркетплейса
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
supplyOrder SupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("supply_order_items")
|
||||
}
|
||||
|
||||
model SupplySupplier {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
contactName String
|
||||
phone String
|
||||
market String?
|
||||
address String?
|
||||
place String?
|
||||
telegram String?
|
||||
organizationId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("SupplySuppliers", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("supply_suppliers")
|
||||
}
|
||||
|
||||
model ExternalAd {
|
||||
id String @id @default(cuid())
|
||||
name String // Название рекламы
|
||||
url String // URL рекламы
|
||||
cost Decimal @db.Decimal(12, 2) // Стоимость
|
||||
date DateTime // Дата рекламы
|
||||
nmId String // ID товара Wildberries
|
||||
clicks Int @default(0) // Количество кликов
|
||||
organizationId String // ID организации
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("ExternalAds", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([organizationId, date])
|
||||
@@map("external_ads")
|
||||
}
|
||||
|
||||
model WBWarehouseCache {
|
||||
id String @id @default(cuid())
|
||||
organizationId String // ID организации
|
||||
cacheDate DateTime // Дата кеширования (только дата, без времени)
|
||||
data Json // Кешированные данные склада WB
|
||||
totalProducts Int @default(0) // Общее количество товаров
|
||||
totalStocks Int @default(0) // Общее количество остатков
|
||||
totalReserved Int @default(0) // Общее количество в резерве
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("WBWarehouseCaches", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([organizationId, cacheDate])
|
||||
@@index([organizationId, cacheDate])
|
||||
@@map("wb_warehouse_caches")
|
||||
}
|
||||
|
||||
model SellerStatsCache {
|
||||
id String @id @default(cuid())
|
||||
organizationId String // ID организации
|
||||
cacheDate DateTime // Дата кеширования (только дата, без времени)
|
||||
period String // Период статистики (week, month, quarter, custom)
|
||||
dateFrom DateTime? // Дата начала периода (для custom)
|
||||
dateTo DateTime? // Дата окончания периода (для custom)
|
||||
|
||||
// Данные товаров
|
||||
productsData Json? // Кешированные данные товаров
|
||||
productsTotalSales Decimal? @db.Decimal(15, 2) // Общая сумма продаж товаров
|
||||
productsTotalOrders Int? // Общее количество заказов товаров
|
||||
productsCount Int? // Количество товаров
|
||||
|
||||
// Данные рекламы
|
||||
advertisingData Json? // Кешированные данные рекламы
|
||||
advertisingTotalCost Decimal? @db.Decimal(15, 2) // Общие расходы на рекламу
|
||||
advertisingTotalViews Int? // Общие показы рекламы
|
||||
advertisingTotalClicks Int? // Общие клики рекламы
|
||||
|
||||
// Метаданные
|
||||
expiresAt DateTime // Время истечения кеша (24 часа)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation("SellerStatsCaches", fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([organizationId, cacheDate, period, dateFrom, dateTo])
|
||||
@@index([organizationId, cacheDate])
|
||||
@@index([expiresAt])
|
||||
@@map("seller_stats_caches")
|
||||
enum ReferralTransactionType {
|
||||
REGISTRATION
|
||||
AUTO_PARTNERSHIP
|
||||
FIRST_ORDER
|
||||
MONTHLY_BONUS
|
||||
}
|
||||
|
Reference in New Issue
Block a user