main
Some checks failed
Deploy Backend / deploy (push) Has been cancelled

This commit is contained in:
2026-02-05 01:29:22 +03:00
parent ae24c17f50
commit 80dcf4d04a
30 changed files with 14275 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
-- CreateTable
CREATE TABLE "Project" (
"id" TEXT NOT NULL PRIMARY KEY,
"niche" TEXT NOT NULL,
"productType" TEXT NOT NULL,
"creativity" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'draft',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "Asset" (
"id" TEXT NOT NULL PRIMARY KEY,
"projectId" TEXT NOT NULL,
"type" TEXT NOT NULL,
"path" TEXT NOT NULL,
"prompt" TEXT,
"meta" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Asset_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "SeoData" (
"id" TEXT NOT NULL PRIMARY KEY,
"projectId" TEXT NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT NOT NULL,
"keywords" TEXT NOT NULL,
"printingGuide" TEXT NOT NULL,
"suggestedPrice" TEXT NOT NULL,
CONSTRAINT "SeoData_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "BrandDna" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"description" TEXT NOT NULL,
"referenceIds" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateIndex
CREATE UNIQUE INDEX "SeoData_projectId_key" ON "SeoData"("projectId");
-- CreateIndex
CREATE UNIQUE INDEX "BrandDna_name_key" ON "BrandDna"("name");

View File

@@ -0,0 +1,21 @@
/*
Warnings:
- You are about to drop the `BrandDna` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "BrandDna";
PRAGMA foreign_keys=on;
-- CreateTable
CREATE TABLE "BrandProfile" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"referencePaths" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateIndex
CREATE UNIQUE INDEX "BrandProfile_name_key" ON "BrandProfile"("name");

View File

@@ -0,0 +1,42 @@
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL PRIMARY KEY,
"email" TEXT NOT NULL,
"passwordHash" TEXT NOT NULL,
"role" TEXT NOT NULL DEFAULT 'USER',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_BrandProfile" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"referencePaths" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"userId" TEXT,
CONSTRAINT "BrandProfile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_BrandProfile" ("createdAt", "id", "name", "referencePaths") SELECT "createdAt", "id", "name", "referencePaths" FROM "BrandProfile";
DROP TABLE "BrandProfile";
ALTER TABLE "new_BrandProfile" RENAME TO "BrandProfile";
CREATE UNIQUE INDEX "BrandProfile_name_key" ON "BrandProfile"("name");
CREATE TABLE "new_Project" (
"id" TEXT NOT NULL PRIMARY KEY,
"niche" TEXT NOT NULL,
"productType" TEXT NOT NULL,
"creativity" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'draft',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
"userId" TEXT,
CONSTRAINT "Project_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_Project" ("createdAt", "creativity", "id", "niche", "productType", "status", "updatedAt") SELECT "createdAt", "creativity", "id", "niche", "productType", "status", "updatedAt" FROM "Project";
DROP TABLE "Project";
ALTER TABLE "new_Project" RENAME TO "Project";
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");

View File

@@ -0,0 +1,114 @@
-- AlterTable
ALTER TABLE "SeoData" ADD COLUMN "jsonLd" TEXT;
-- CreateTable
CREATE TABLE "EtsyShop" (
"id" TEXT NOT NULL PRIMARY KEY,
"shopId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"shopName" TEXT NOT NULL,
"accessToken" TEXT NOT NULL,
"refreshToken" TEXT NOT NULL,
"expiresAt" BIGINT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "EtsyShop_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "UsageLog" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"action" TEXT NOT NULL,
"cost" REAL NOT NULL,
"credits" INTEGER NOT NULL,
"timestamp" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "UsageLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "Transaction" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"amount" REAL NOT NULL,
"credits" INTEGER NOT NULL,
"type" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Transaction_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "SystemConfig" (
"key" TEXT NOT NULL PRIMARY KEY,
"value" TEXT NOT NULL,
"description" TEXT,
"updatedAt" DATETIME NOT NULL
);
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Project" (
"id" TEXT NOT NULL PRIMARY KEY,
"niche" TEXT NOT NULL,
"productType" TEXT NOT NULL,
"creativity" TEXT NOT NULL,
"aspectRatio" TEXT NOT NULL DEFAULT '3:4',
"useExactReference" BOOLEAN NOT NULL DEFAULT false,
"status" TEXT NOT NULL DEFAULT 'draft',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
"userId" TEXT,
CONSTRAINT "Project_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_Project" ("createdAt", "creativity", "id", "niche", "productType", "status", "updatedAt", "userId") SELECT "createdAt", "creativity", "id", "niche", "productType", "status", "updatedAt", "userId" FROM "Project";
DROP TABLE "Project";
ALTER TABLE "new_Project" RENAME TO "Project";
CREATE TABLE "new_Asset" (
"id" TEXT NOT NULL PRIMARY KEY,
"projectId" TEXT NOT NULL,
"type" TEXT NOT NULL,
"path" TEXT NOT NULL,
"prompt" TEXT,
"meta" TEXT,
"quality" TEXT NOT NULL DEFAULT 'DRAFT',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Asset_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Asset" ("createdAt", "id", "meta", "path", "projectId", "prompt", "type") SELECT "createdAt", "id", "meta", "path", "projectId", "prompt", "type" FROM "Asset";
DROP TABLE "Asset";
ALTER TABLE "new_Asset" RENAME TO "Asset";
CREATE TABLE "new_User" (
"id" TEXT NOT NULL PRIMARY KEY,
"email" TEXT NOT NULL,
"passwordHash" TEXT,
"googleId" TEXT,
"avatar" TEXT,
"role" TEXT NOT NULL DEFAULT 'USER',
"credits" INTEGER NOT NULL DEFAULT 300,
"plan" TEXT NOT NULL DEFAULT 'FREE',
"betaAccess" BOOLEAN NOT NULL DEFAULT true,
"apiKey" TEXT,
"etsyShopName" TEXT,
"etsyShopLink" TEXT,
"etsyShopLogo" TEXT,
"paymentMethod" TEXT,
"subscriptionId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"termsAcceptedAt" DATETIME,
"kvkkAcceptedAt" DATETIME,
"totalRevenue" REAL NOT NULL DEFAULT 0.0,
"totalCost" REAL NOT NULL DEFAULT 0.0
);
INSERT INTO "new_User" ("createdAt", "email", "id", "passwordHash", "role") SELECT "createdAt", "email", "id", "passwordHash", "role" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
CREATE UNIQUE INDEX "User_googleId_key" ON "User"("googleId");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
-- CreateIndex
CREATE UNIQUE INDEX "EtsyShop_shopId_key" ON "EtsyShop"("shopId");
-- CreateIndex
CREATE UNIQUE INDEX "SystemConfig_key_key" ON "SystemConfig"("key");

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "sqlite"

154
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,154 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Project {
id String @id @default(uuid())
niche String
productType String
creativity String
aspectRatio String @default("3:4") // 1:1, 3:4, 4:5, 16:9, 9:16, etc.
useExactReference Boolean @default(false) // Strict Composition Mode
status String @default("draft") // draft, generated, finalized
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
sku String? // e.g. "WLR005"
config String? // JSON: { isStickerSet, setSize, basePrompt, characterCore }
assets Asset[]
seoData SeoData?
userId String?
user User? @relation(fields: [userId], references: [id])
}
model Asset {
id String @id @default(uuid())
projectId String
type String // master, mockup, reference, revision
path String // Local file path relative to /storage
prompt String? // The prompt that generated this asset
meta String? // JSON string for extra metadata (scenario name, etc.)
quality String @default("DRAFT") // DRAFT, MASTER, UPSCALED
createdAt DateTime @default(now())
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
}
model SeoData {
id String @id @default(uuid())
projectId String @unique
title String
description String
keywords String // Stored as comma separated string or JSON
printingGuide String
suggestedPrice String
jsonLd String? // Structured Data (Schema.org)
attributes String? // JSON String: { primaryColor, occasion, etc. }
categoryPath String? // Suggested Category Path
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
}
model EtsyShop {
id String @id @default(uuid())
shopId String @unique
userId String
shopName String
accessToken String
refreshToken String
expiresAt BigInt
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model BrandProfile {
id String @id @default(uuid())
name String @unique
referencePaths String // JSON array of file paths relative to /storage
createdAt DateTime @default(now())
// Relations
userId String?
user User? @relation(fields: [userId], references: [id])
}
model User {
id String @id @default(uuid())
email String @unique
passwordHash String? // Optional for Google Users
// OAuth Fields
googleId String? @unique
avatar String?
role String @default("USER") // USER, ADMIN
// SaaS / Beta Fields
credits Int @default(300) // Free credits (Generous tier)
plan String @default("FREE") // FREE, PRO
betaAccess Boolean @default(true) // Gated access
// New SaaS Fields (Phase 1)
apiKey String? // User's Personal Gemini API Key (Encrypted/Plain per policy)
etsyShopName String? // Manual Etsy Shop Name fallback
etsyShopLink String? // Manual Etsy Shop Link fallback
etsyShopLogo String? // Path to logo file
paymentMethod String? // Stripe Payment Method ID (Future)
subscriptionId String? // Stripe Subscription ID (Future)
skuSettings String? // JSON: { "Wall Art": {prefix: "WLR", next: 1} }
createdAt DateTime @default(now())
// Legal Compliance (Phase 6)
termsAcceptedAt DateTime? // User Agreement & IP Rights
kvkkAcceptedAt DateTime? // KVKK & Data Privacy
// Profit Analytics (Phase 7)
totalRevenue Float @default(0.0) // Total money paid by user (USD)
totalCost Float @default(0.0) // Total API cost incurred by user (USD, estimated)
projects Project[]
brandProfiles BrandProfile[]
etsyShops EtsyShop[]
usageLogs UsageLog[]
transactions Transaction[]
}
model UsageLog {
id String @id @default(uuid())
userId String
action String // GENERATE_MASTER, GENERATE_VARIANT, MOCKUP, PROMPT
cost Float // Estimated API cost in USD for this action
credits Int // Credits deducted
timestamp DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Transaction {
id String @id @default(uuid())
userId String
amount Float // USD Amount paid
credits Int // Credits added
type String // PURCHASE, ADMIN_GRANT, BONUS
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model SystemConfig {
key String @id @unique
value String
description String?
updatedAt DateTime @updatedAt
}