feat(db): add Prisma schema and global PrismaModule
This commit is contained in:
4
prisma/customObjects/prisma.custom.object.ts
Normal file
4
prisma/customObjects/prisma.custom.object.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Prisma } from '../generated/client';
|
||||
|
||||
/** Product loaded with its versions (`include: { versions: true }`). */
|
||||
export type ProductWithVersions = Prisma.ProductGetPayload<{ include: { versions: true } }>;
|
||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
9
prisma/prisma.module.ts
Normal file
9
prisma/prisma.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { PrismaService } from './prisma.service';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService],
|
||||
})
|
||||
export class PrismaModule {}
|
||||
20
prisma/prisma.service.ts
Normal file
20
prisma/prisma.service.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
||||
import { PrismaClient } from './generated/client';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
/** Prisma client shared by the whole app (global PrismaModule), connected to `DATABASE_URL` through the pg driver adapter. */
|
||||
@Injectable()
|
||||
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
||||
constructor() {
|
||||
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
||||
super({ adapter });
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
}
|
||||
|
||||
async onModuleDestroy() {
|
||||
await this.$disconnect();
|
||||
}
|
||||
}
|
||||
216
prisma/schema.prisma
Normal file
216
prisma/schema.prisma
Normal file
@@ -0,0 +1,216 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
// Get a free hosted Postgres database in seconds: `npx create-db`
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "./generated/"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
/// Product category, mirrored from Hiboutik. Categories form a tree (parent / children).
|
||||
model Category {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
/// Enabled in the Hiboutik POS (category_enabled)
|
||||
enabled Boolean @default(true)
|
||||
hiboutikId Int @unique
|
||||
name String
|
||||
/// Display order among its siblings (category_position)
|
||||
position Int @default(0)
|
||||
/// Displayed on the website (category_enabled_www)
|
||||
webEnabled Boolean @default(true)
|
||||
|
||||
/// Null for a root category
|
||||
parent Category? @relation("CategoryTree", fields: [parentId], references: [id], onDelete: SetNull)
|
||||
parentId String?
|
||||
children Category[] @relation("CategoryTree")
|
||||
|
||||
products Product[]
|
||||
|
||||
@@map("categories")
|
||||
}
|
||||
|
||||
/// Product brand, mirrored from Hiboutik.
|
||||
model Brand {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
enabled Boolean @default(true)
|
||||
hiboutikId Int @unique
|
||||
name String
|
||||
|
||||
products Product[]
|
||||
|
||||
@@map("brands")
|
||||
}
|
||||
|
||||
/// Product supplier, mirrored from Hiboutik.
|
||||
model Supplier {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
enabled Boolean @default(true)
|
||||
hiboutikId Int @unique
|
||||
name String
|
||||
|
||||
products Product[]
|
||||
|
||||
@@map("suppliers")
|
||||
}
|
||||
|
||||
/// Product mirrored from Hiboutik. What is actually sold is one of its versions (sizes).
|
||||
model Product {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
/// Archived in Hiboutik (product_arch)
|
||||
archived Boolean @default(false)
|
||||
barcode String?
|
||||
description String
|
||||
/// Null when the product has no discount
|
||||
discountPrice Decimal? @db.Decimal(10, 2)
|
||||
/// Displayed on the website (product_display_www)
|
||||
enabled Boolean @default(true)
|
||||
/// Sum of the available stock of all its versions
|
||||
globalStock Int @default(0)
|
||||
hiboutikId Int @unique
|
||||
/// Last update in Hiboutik
|
||||
hiboutikUpdatedAt DateTime?
|
||||
name String
|
||||
price Decimal @db.Decimal(10, 2)
|
||||
|
||||
brand Brand? @relation(fields: [brandId], references: [id], onDelete: SetNull)
|
||||
brandId String?
|
||||
category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||||
categoryId String?
|
||||
supplier Supplier? @relation(fields: [supplierId], references: [id], onDelete: SetNull)
|
||||
supplierId String?
|
||||
|
||||
versions ProductVersion[]
|
||||
|
||||
@@map("products")
|
||||
}
|
||||
|
||||
/// Sellable version of a product: one per Hiboutik size, or a single one (hiboutikSizeId 0) for a product without sizes.
|
||||
model ProductVersion {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
/// Not unique: Hiboutik is the source of truth and may hold the same barcode on several products
|
||||
barcode String?
|
||||
/// Size-specific discount, null when none
|
||||
discountPrice Decimal? @db.Decimal(10, 2)
|
||||
/// Hiboutik size id, 0 for a product without sizes
|
||||
hiboutikSizeId Int
|
||||
/// Size-specific price, null to use the product price (copy of the product price for a product without sizes)
|
||||
price Decimal? @db.Decimal(10, 2)
|
||||
stock Int @default(0)
|
||||
/// Size name, or the product name for a product without sizes
|
||||
versionName String
|
||||
|
||||
product Product @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: Restrict)
|
||||
productId String
|
||||
|
||||
orderLines OrderLine[]
|
||||
|
||||
@@unique([productId, hiboutikSizeId])
|
||||
@@index([barcode])
|
||||
@@map("productVersions")
|
||||
}
|
||||
|
||||
/// Customer mirrored from Hiboutik.
|
||||
model Customer {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
dateOfBirth DateTime?
|
||||
/// Kept when removed in Hiboutik (an empty Hiboutik email does not erase it)
|
||||
email String?
|
||||
firstName String
|
||||
hiboutikId Int @unique
|
||||
/// Last update in Hiboutik
|
||||
hiboutikUpdatedAt DateTime?
|
||||
lastName String
|
||||
phone String?
|
||||
|
||||
addresses CustomerAddress[]
|
||||
orders Order[]
|
||||
|
||||
@@index([email])
|
||||
@@map("customers")
|
||||
}
|
||||
|
||||
/// Address of a customer, mirrored from Hiboutik (sync not implemented yet).
|
||||
model CustomerAddress {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
address String
|
||||
city String
|
||||
country String
|
||||
hiboutikId Int @unique
|
||||
isDefault Boolean @default(false)
|
||||
zipCode String
|
||||
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
||||
customerId String
|
||||
|
||||
@@map("customer_addresses")
|
||||
}
|
||||
|
||||
/// Where an order was placed.
|
||||
enum OrderSource {
|
||||
STORE // hiboutik
|
||||
WEB // site
|
||||
}
|
||||
|
||||
/// Order placed in store (Hiboutik sale) or on the website.
|
||||
model Order {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
/// Null for a website order not (yet) sent to Hiboutik
|
||||
hiboutikSaleId Int? @unique
|
||||
orderedAt DateTime
|
||||
source OrderSource
|
||||
status String
|
||||
total Decimal @db.Decimal(10, 2)
|
||||
|
||||
/// Null for an anonymous sale or a deleted customer
|
||||
customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull)
|
||||
customerId String?
|
||||
|
||||
lines OrderLine[]
|
||||
|
||||
@@map("orders")
|
||||
}
|
||||
|
||||
/// Line of an order.
|
||||
model OrderLine {
|
||||
id String @id @default(uuid())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Snapshot of the product at order time: the catalog can change or be deleted afterwards
|
||||
barcode String?
|
||||
hiboutikProductId Int
|
||||
hiboutikSizeId Int
|
||||
productName String
|
||||
quantity Int
|
||||
unitPrice Decimal @db.Decimal(10, 2)
|
||||
versionName String
|
||||
|
||||
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
||||
orderId String
|
||||
// Link to the current catalog, set to null when the version is deleted
|
||||
productVersion ProductVersion? @relation(fields: [productVersionId], references: [id], onDelete: SetNull)
|
||||
productVersionId String?
|
||||
|
||||
@@map("order_lines")
|
||||
}
|
||||
Reference in New Issue
Block a user