Files
inkreach-official-website/apps/api/prisma/schema.prisma
T
yeuimu 7e04877bb6 chore: migrate to pnpm workspaces monorepo with Turborepo
- Restructure directories: apps/api, apps/admin, apps/website
- Add root pnpm-workspace.yaml, turbo.json, .prettierrc, .gitignore
- Rename packages to @inkreach/api, @inkreach/admin, @inkreach/website
- Add shared packages: packages/tsconfig, packages/shared-types
- Add pnpm.onlyBuiltDependencies for native builds
- Update docs: README.md, structs.md
- All three projects build successfully
2026-07-11 16:54:05 +08:00

202 lines
7.0 KiB
Plaintext

// InkReach Product Center Prisma Schema
// Generated based on docs/dev/database-table-design.md
// All TIMESTAMPTZ columns use DateTime @db.Timestamptz(6)
// All BIGINT columns use BigInt
// snake_case table & column names via @@map / @map
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ---------- Origin Goods ----------
model OriginGood {
id BigInt @id @default(autoincrement()) @map("origin_good_id")
sdsGoodId String @unique @map("sds_good_id")
// Cached SDS product metadata (filled during sync)
sdsCategoryId String? @map("sds_category_id")
goodName String? @map("good_name")
goodImage String? @map("good_image")
goodPrice Decimal? @map("good_price") @db.Decimal(12, 2)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
goods Good[]
@@index([sdsCategoryId])
@@map("origin_goods")
}
// ---------- Countries ----------
model Country {
id BigInt @id @default(autoincrement()) @map("country_id")
countryName String @unique @map("country_name")
countryIcon String? @map("country_icon")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
goods Good[]
positions Position[]
@@map("countries")
}
// ---------- Categories (self-referential tree) ----------
model Category {
id BigInt @id @default(autoincrement()) @map("category_id")
parentCategoryId BigInt? @map("parent_category_id")
categoryName String @map("category_name")
categoryIcon String? @map("category_icon")
sdsCategoryId String? @unique @map("sds_category_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
parent Category? @relation("CategoryToCategory", fields: [parentCategoryId], references: [id], onDelete: Restrict, onUpdate: NoAction)
children Category[] @relation("CategoryToCategory")
goods Good[]
positions Position[]
@@index([parentCategoryId])
@@map("categories")
}
// ---------- Tag Groups ----------
model TagGroup {
id BigInt @id @default(autoincrement()) @map("tag_group_id")
groupName String @unique @map("group_name")
groupIcon String? @map("group_icon")
groupColor String? @map("group_color")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
tags Tag[]
@@map("tag_groups")
}
// ---------- Tags ----------
model Tag {
id BigInt @id @default(autoincrement()) @map("tag_id")
tagName String @unique @map("tag_name")
tagColor String? @map("tag_color")
tagFontColor String? @map("tag_font_color")
timing String?
tagGroupId BigInt? @map("tag_group_id")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
goods Good[]
goodTags GoodTag[]
tagGroup TagGroup? @relation(fields: [tagGroupId], references: [id], onDelete: SetNull, onUpdate: NoAction)
@@index([tagGroupId])
@@index([tagGroupId, sortOrder])
@@map("tags")
}
// ---------- Positions ----------
model Position {
id BigInt @id @default(autoincrement()) @map("position_id")
indexVal Int @map("index_val")
countryId BigInt? @map("country_id")
categoryId BigInt? @map("category_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
country Country? @relation(fields: [countryId], references: [id], onDelete: Cascade, onUpdate: NoAction)
category Category? @relation(fields: [categoryId], references: [id], onDelete: Cascade, onUpdate: NoAction)
goods Good[]
@@index([countryId])
@@index([categoryId])
@@index([countryId, categoryId])
@@map("positions")
}
// ---------- Goods ----------
model Good {
id BigInt @id @default(autoincrement()) @map("good_id")
originGoodId BigInt @map("origin_good_id")
countryId BigInt @map("country_id")
categoryId BigInt @map("category_id")
tagId BigInt? @map("tag_id")
positionId BigInt? @map("position_id")
goodName String @map("good_name")
goodImage String? @map("good_image")
goodPriority Int @default(0) @map("good_priority")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
originGood OriginGood @relation(fields: [originGoodId], references: [id], onDelete: Restrict, onUpdate: NoAction)
country Country @relation(fields: [countryId], references: [id], onDelete: Restrict, onUpdate: NoAction)
category Category @relation(fields: [categoryId], references: [id], onDelete: Restrict, onUpdate: NoAction)
tag Tag? @relation(fields: [tagId], references: [id], onDelete: SetNull, onUpdate: NoAction)
position Position? @relation(fields: [positionId], references: [id], onDelete: SetNull, onUpdate: NoAction)
goodTags GoodTag[]
@@index([originGoodId])
@@index([countryId])
@@index([categoryId])
@@index([tagId])
@@index([positionId])
@@index([goodPriority(sort: Desc)])
@@index([countryId, goodPriority(sort: Desc)])
@@index([categoryId, countryId])
@@map("goods")
}
// ---------- Good-Tag Junction (M:N) ----------
model GoodTag {
goodId BigInt @map("good_id")
tagId BigInt @map("tag_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
good Good @relation(fields: [goodId], references: [id], onDelete: Cascade, onUpdate: NoAction)
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@id([goodId, tagId])
@@index([tagId])
@@map("good_tags")
}
// ---------- Users (admin authentication) ----------
model User {
id BigInt @id @default(autoincrement())
username String @unique
passwordHash String @map("password_hash")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
@@map("users")
}
// ---------- Sync Logs ----------
enum SyncType {
CATEGORIES
PRODUCTS
}
enum SyncStatus {
RUNNING
SUCCESS
FAILED
}
model SyncLog {
id BigInt @id @default(autoincrement())
type SyncType
status SyncStatus
message String?
startedAt DateTime @default(now()) @map("started_at") @db.Timestamptz(6)
finishedAt DateTime? @map("finished_at") @db.Timestamptz(6)
@@index([type, startedAt])
@@map("sync_logs")
}