build: refresh release artifacts after product design surveys and catalog polish
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1695
-50
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
-- Product detail opens in the customer app, for the admin «آمار» screen.
|
||||
CREATE TABLE "ProductView" (
|
||||
"id" TEXT NOT NULL,
|
||||
"productId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ProductView_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX "ProductView_productId_createdAt_idx" ON "ProductView"("productId", "createdAt");
|
||||
CREATE INDEX "ProductView_createdAt_idx" ON "ProductView"("createdAt");
|
||||
|
||||
ALTER TABLE "ProductView" ADD CONSTRAINT "ProductView_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Product labels from the «برچسبها» list. IF NOT EXISTS: some databases
|
||||
-- already carry this column from an earlier, unmerged migration.
|
||||
ALTER TABLE "Product" ADD COLUMN IF NOT EXISTS "tags" TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[];
|
||||
UPDATE "Product" SET "tags" = ARRAY[]::TEXT[] WHERE "tags" IS NULL;
|
||||
ALTER TABLE "Product" ALTER COLUMN "tags" SET DEFAULT ARRAY[]::TEXT[];
|
||||
ALTER TABLE "Product" ALTER COLUMN "tags" SET NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "Product_tags_idx" ON "Product" USING GIN ("tags");
|
||||
@@ -0,0 +1,13 @@
|
||||
-- Server-side customer cart for daily expiry + reminder SMS (cart.expiry).
|
||||
CREATE TABLE "CustomerCart" (
|
||||
"customerId" TEXT NOT NULL,
|
||||
"items" JSONB NOT NULL DEFAULT '[]',
|
||||
"reminderSentForClearAt" TIMESTAMP(3),
|
||||
"clearedAt" TIMESTAMP(3),
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "CustomerCart_pkey" PRIMARY KEY ("customerId")
|
||||
);
|
||||
|
||||
ALTER TABLE "CustomerCart" ADD CONSTRAINT "CustomerCart_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "Customer"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,12 @@
|
||||
-- Deferred «خرید بعدی» list — separate from CustomerCart so daily expiry
|
||||
-- and order-clear never touch it, and stock is never reserved.
|
||||
CREATE TABLE "CustomerBuyLater" (
|
||||
"customerId" TEXT NOT NULL,
|
||||
"items" JSONB NOT NULL DEFAULT '[]',
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "CustomerBuyLater_pkey" PRIMARY KEY ("customerId")
|
||||
);
|
||||
|
||||
ALTER TABLE "CustomerBuyLater" ADD CONSTRAINT "CustomerBuyLater_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "Customer"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,49 @@
|
||||
-- Product design survey (like/dislike before manufacturing).
|
||||
CREATE TYPE "ProductSurveyStatus" AS ENUM ('PENDING_REVIEW', 'OPEN', 'CLOSED', 'APPROVED', 'REJECTED');
|
||||
CREATE TYPE "ProductSurveyVoteValue" AS ENUM ('LIKE', 'DISLIKE');
|
||||
|
||||
CREATE TABLE "ProductSurvey" (
|
||||
"id" TEXT NOT NULL,
|
||||
"title" TEXT,
|
||||
"imageUrl" TEXT NOT NULL,
|
||||
"suggestedWeightGrams" DECIMAL(14,4) NOT NULL,
|
||||
"status" "ProductSurveyStatus" NOT NULL DEFAULT 'PENDING_REVIEW',
|
||||
"createdByCustomerId" TEXT,
|
||||
"createdByAdminId" TEXT,
|
||||
"publishedAt" TIMESTAMP(3),
|
||||
"decidedAt" TIMESTAMP(3),
|
||||
"decidedByAdminId" TEXT,
|
||||
"decisionNote" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "ProductSurvey_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "ProductSurveyVote" (
|
||||
"id" TEXT NOT NULL,
|
||||
"surveyId" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"value" "ProductSurveyVoteValue" NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "ProductSurveyVote_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX "ProductSurvey_status_idx" ON "ProductSurvey"("status");
|
||||
CREATE INDEX "ProductSurvey_createdByCustomerId_idx" ON "ProductSurvey"("createdByCustomerId");
|
||||
CREATE INDEX "ProductSurvey_createdAt_idx" ON "ProductSurvey"("createdAt");
|
||||
CREATE INDEX "ProductSurveyVote_customerId_idx" ON "ProductSurveyVote"("customerId");
|
||||
CREATE UNIQUE INDEX "ProductSurveyVote_surveyId_customerId_key" ON "ProductSurveyVote"("surveyId", "customerId");
|
||||
|
||||
ALTER TABLE "ProductSurvey" ADD CONSTRAINT "ProductSurvey_createdByCustomerId_fkey" FOREIGN KEY ("createdByCustomerId") REFERENCES "Customer"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "ProductSurvey" ADD CONSTRAINT "ProductSurvey_createdByAdminId_fkey" FOREIGN KEY ("createdByAdminId") REFERENCES "Admin"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "ProductSurvey" ADD CONSTRAINT "ProductSurvey_decidedByAdminId_fkey" FOREIGN KEY ("decidedByAdminId") REFERENCES "Admin"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE "ProductSurveyVote" ADD CONSTRAINT "ProductSurveyVote_surveyId_fkey" FOREIGN KEY ("surveyId") REFERENCES "ProductSurvey"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "ProductSurveyVote" ADD CONSTRAINT "ProductSurveyVote_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "Customer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
INSERT INTO "permission" ("rid", "userTypeId")
|
||||
SELECT 'product.survey', 85
|
||||
WHERE EXISTS (SELECT 1 FROM "user_type" WHERE "id" = 85)
|
||||
ON CONFLICT DO NOTHING;
|
||||
@@ -1621,6 +1621,7 @@ var ALL_RIDS = [
|
||||
"config.statics.tags.edit",
|
||||
"config.statics.tags.remove",
|
||||
"config.wallet",
|
||||
"config.cart",
|
||||
"custom.config.statics.slider",
|
||||
"custom.config.statics.tags.banner.ids",
|
||||
"dashboard.view",
|
||||
@@ -1712,6 +1713,7 @@ var ALL_RIDS = [
|
||||
"product.list.variants.remove",
|
||||
"product.list.view",
|
||||
"product.percent",
|
||||
"product.survey",
|
||||
"report.order.item",
|
||||
"report.product",
|
||||
"sms.create",
|
||||
|
||||
+69
-3
File diff suppressed because one or more lines are too long
@@ -248,6 +248,22 @@ exports.Prisma.CustomerScalarFieldEnum = {
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.CustomerCartScalarFieldEnum = {
|
||||
customerId: 'customerId',
|
||||
items: 'items',
|
||||
reminderSentForClearAt: 'reminderSentForClearAt',
|
||||
clearedAt: 'clearedAt',
|
||||
updatedAt: 'updatedAt',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.CustomerBuyLaterScalarFieldEnum = {
|
||||
customerId: 'customerId',
|
||||
items: 'items',
|
||||
updatedAt: 'updatedAt',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.CustomerFavoriteScalarFieldEnum = {
|
||||
customerId: 'customerId',
|
||||
productId: 'productId',
|
||||
@@ -318,11 +334,18 @@ exports.Prisma.ProductScalarFieldEnum = {
|
||||
showType: 'showType',
|
||||
isActive: 'isActive',
|
||||
createdAt: 'createdAt',
|
||||
tags: 'tags',
|
||||
accountingStockWeight: 'accountingStockWeight',
|
||||
accountingStockCount: 'accountingStockCount',
|
||||
accountingStockAt: 'accountingStockAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductViewScalarFieldEnum = {
|
||||
id: 'id',
|
||||
productId: 'productId',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductImageScalarFieldEnum = {
|
||||
id: 'id',
|
||||
productId: 'productId',
|
||||
@@ -484,6 +507,31 @@ exports.Prisma.CommentScalarFieldEnum = {
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductSurveyScalarFieldEnum = {
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
imageUrl: 'imageUrl',
|
||||
suggestedWeightGrams: 'suggestedWeightGrams',
|
||||
status: 'status',
|
||||
createdByCustomerId: 'createdByCustomerId',
|
||||
createdByAdminId: 'createdByAdminId',
|
||||
publishedAt: 'publishedAt',
|
||||
decidedAt: 'decidedAt',
|
||||
decidedByAdminId: 'decidedByAdminId',
|
||||
decisionNote: 'decisionNote',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductSurveyVoteScalarFieldEnum = {
|
||||
id: 'id',
|
||||
surveyId: 'surveyId',
|
||||
customerId: 'customerId',
|
||||
value: 'value',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.SettingScalarFieldEnum = {
|
||||
key: 'key',
|
||||
value: 'value',
|
||||
@@ -753,6 +801,19 @@ exports.CommentStatus = exports.$Enums.CommentStatus = {
|
||||
REJECTED: 'REJECTED'
|
||||
};
|
||||
|
||||
exports.ProductSurveyStatus = exports.$Enums.ProductSurveyStatus = {
|
||||
PENDING_REVIEW: 'PENDING_REVIEW',
|
||||
OPEN: 'OPEN',
|
||||
CLOSED: 'CLOSED',
|
||||
APPROVED: 'APPROVED',
|
||||
REJECTED: 'REJECTED'
|
||||
};
|
||||
|
||||
exports.ProductSurveyVoteValue = exports.$Enums.ProductSurveyVoteValue = {
|
||||
LIKE: 'LIKE',
|
||||
DISLIKE: 'DISLIKE'
|
||||
};
|
||||
|
||||
exports.AccountingEntityType = exports.$Enums.AccountingEntityType = {
|
||||
CUSTOMER: 'CUSTOMER',
|
||||
PRODUCT: 'PRODUCT'
|
||||
@@ -803,6 +864,8 @@ exports.Prisma.ModelName = {
|
||||
AdminSession: 'AdminSession',
|
||||
SalesExpertProfile: 'SalesExpertProfile',
|
||||
Customer: 'Customer',
|
||||
CustomerCart: 'CustomerCart',
|
||||
CustomerBuyLater: 'CustomerBuyLater',
|
||||
CustomerFavorite: 'CustomerFavorite',
|
||||
CustomerAddress: 'CustomerAddress',
|
||||
Branch: 'Branch',
|
||||
@@ -812,6 +875,7 @@ exports.Prisma.ModelName = {
|
||||
Collection: 'Collection',
|
||||
CollectionProduct: 'CollectionProduct',
|
||||
Product: 'Product',
|
||||
ProductView: 'ProductView',
|
||||
ProductImage: 'ProductImage',
|
||||
ProductVariant: 'ProductVariant',
|
||||
Order: 'Order',
|
||||
@@ -825,6 +889,8 @@ exports.Prisma.ModelName = {
|
||||
UserType: 'UserType',
|
||||
Permission: 'Permission',
|
||||
Comment: 'Comment',
|
||||
ProductSurvey: 'ProductSurvey',
|
||||
ProductSurveyVote: 'ProductSurveyVote',
|
||||
Setting: 'Setting',
|
||||
AccountingLink: 'AccountingLink',
|
||||
AccountingOutbox: 'AccountingOutbox',
|
||||
|
||||
+9698
-77
File diff suppressed because it is too large
Load Diff
+69
-3
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "prisma-client-116b04ea3171f5cde20e1cb240deadd7003ef9332c0f79ef1b0e851c763aeb43",
|
||||
"name": "prisma-client-07ff23aaae8323751fefc58ab63b3494732076b6adca58b30cf4c84ef5f8c271",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"browser": "index-browser.js",
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+140
-19
@@ -173,14 +173,16 @@ model Admin {
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
supervisedWorkshops Workshop[] @relation("WorkshopSupervisor")
|
||||
branchAllocations BranchAllocation[] @relation("AllocationAuthor")
|
||||
postedLedgerEntries LedgerEntry[]
|
||||
orderStatusEvents OrderStatusEvent[]
|
||||
preOrderStatusEvents PreOrderStatusEvent[]
|
||||
sentSmsMessages SmsMessage[] @relation("SmsAuthor")
|
||||
sentNotifications Notification[] @relation("NotificationAuthor")
|
||||
uploadedFiles UploadedFile[] @relation("FileUploader")
|
||||
supervisedWorkshops Workshop[] @relation("WorkshopSupervisor")
|
||||
branchAllocations BranchAllocation[] @relation("AllocationAuthor")
|
||||
postedLedgerEntries LedgerEntry[]
|
||||
orderStatusEvents OrderStatusEvent[]
|
||||
preOrderStatusEvents PreOrderStatusEvent[]
|
||||
sentSmsMessages SmsMessage[] @relation("SmsAuthor")
|
||||
sentNotifications Notification[] @relation("NotificationAuthor")
|
||||
uploadedFiles UploadedFile[] @relation("FileUploader")
|
||||
createdProductSurveys ProductSurvey[] @relation("SurveyAdminCreator")
|
||||
decidedProductSurveys ProductSurvey[] @relation("SurveyDecider")
|
||||
|
||||
/// Issued admin-panel tokens, recorded only while session tracking is on
|
||||
/// (AUTH_SESSION_TRACKING, or implicitly whenever the IAM is enabled) so a
|
||||
@@ -553,23 +555,62 @@ model Customer {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
addresses CustomerAddress[]
|
||||
orders Order[]
|
||||
preOrders PreOrder[]
|
||||
ledgerEntries LedgerEntry[]
|
||||
walletBonuses WalletBonus[]
|
||||
comments Comment[]
|
||||
promotions Promotion[]
|
||||
notifications NotificationRecipient[]
|
||||
activityLogs CustomerActivityLog[]
|
||||
otpChallenges CustomerOtp[]
|
||||
favorites CustomerFavorite[]
|
||||
addresses CustomerAddress[]
|
||||
orders Order[]
|
||||
preOrders PreOrder[]
|
||||
ledgerEntries LedgerEntry[]
|
||||
walletBonuses WalletBonus[]
|
||||
comments Comment[]
|
||||
promotions Promotion[]
|
||||
notifications NotificationRecipient[]
|
||||
activityLogs CustomerActivityLog[]
|
||||
otpChallenges CustomerOtp[]
|
||||
favorites CustomerFavorite[]
|
||||
productSurveys ProductSurvey[] @relation("SurveyCustomerCreator")
|
||||
productSurveyVotes ProductSurveyVote[]
|
||||
/// App shopping cart synced from user-app-v2 so daily expiry + reminder SMS
|
||||
/// can run on the server (localStorage alone cannot).
|
||||
cart CustomerCart?
|
||||
/// Deferred «خرید بعدی» list — never reserved against stock and never
|
||||
/// cleared by the daily cart-expiry worker.
|
||||
buyLater CustomerBuyLater?
|
||||
|
||||
@@index([referredByAgentId])
|
||||
@@index([firstName])
|
||||
@@index([lastName])
|
||||
}
|
||||
|
||||
/// Server-side mirror of the customer-app cart (`appCart` in localStorage).
|
||||
/// Empty `items` means no basket; the daily expiry worker clears it and may
|
||||
/// SMS a reminder before the configured clear time (Setting `cart.expiry`).
|
||||
model CustomerCart {
|
||||
customerId String @id
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
||||
|
||||
/// Cart lines as JSON — same shape the app stores (pid, vid, qty, …).
|
||||
items Json @default("[]")
|
||||
|
||||
/// Which clear-deadline this cart already got a reminder SMS for (ISO of
|
||||
/// that deadline). Null = never reminded for the current cycle.
|
||||
reminderSentForClearAt DateTime?
|
||||
|
||||
clearedAt DateTime?
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
/// «سبد خرید بعدی» — wish/defer list. Same line shape as the cart, but:
|
||||
/// never decrements stock, never participates in checkout, never cleared by
|
||||
/// cart.expiry. Moving a line here only removes it from the active cart.
|
||||
model CustomerBuyLater {
|
||||
customerId String @id
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
||||
|
||||
items Json @default("[]")
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
/// Legacy `fav` (251 rows) — saved products. The target had no model for this,
|
||||
/// so every customer's favourites would have been lost in the migration; the
|
||||
/// owner confirmed on 2026-10-06 that they matter.
|
||||
@@ -694,6 +735,9 @@ model Product {
|
||||
showType Int @default(3)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
/// Labels picked from the «ثابتها → برچسبها» list (Setting `__list__tags`).
|
||||
/// Shown on the app's product cards; tagged products get their own home section.
|
||||
tags String[] @default([])
|
||||
|
||||
/// Stock of the linked کارساخته as last read from the accounting software
|
||||
/// (D27). Weight for gram-type items, count for count-type ones — whichever
|
||||
@@ -710,6 +754,7 @@ model Product {
|
||||
promotions Promotion[]
|
||||
allocationItems BranchAllocationItem[]
|
||||
favoritedBy CustomerFavorite[]
|
||||
views ProductView[]
|
||||
|
||||
// Storefront paging (owner: the real catalogue reaches ~16k products, so
|
||||
// GET /catalog/products must page rather than return everything). This model
|
||||
@@ -722,6 +767,19 @@ model Product {
|
||||
@@index([isActive, createdAt])
|
||||
@@index([categoryId])
|
||||
@@index([brandId])
|
||||
@@index([tags], type: Gin)
|
||||
}
|
||||
|
||||
/// One opening of a product's detail screen in the customer app. Read by the
|
||||
/// admin «آمار» screen for the most-viewed products and brands.
|
||||
model ProductView {
|
||||
id String @id @default(cuid())
|
||||
productId String
|
||||
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([productId, createdAt])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model ProductImage {
|
||||
@@ -1097,6 +1155,69 @@ model Comment {
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Product design survey — before manufacturing, a design (photo + suggested
|
||||
// weight) is shown for like/dislike. Admin or customer can create; customer
|
||||
// submissions need admin publish. Admin decides APPROVED/REJECTED by hand.
|
||||
// Not linked to Product / PreOrder.
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
enum ProductSurveyStatus {
|
||||
PENDING_REVIEW
|
||||
OPEN
|
||||
CLOSED
|
||||
APPROVED
|
||||
REJECTED
|
||||
}
|
||||
|
||||
enum ProductSurveyVoteValue {
|
||||
LIKE
|
||||
DISLIKE
|
||||
}
|
||||
|
||||
model ProductSurvey {
|
||||
id String @id @default(cuid())
|
||||
title String?
|
||||
imageUrl String
|
||||
suggestedWeightGrams Decimal @db.Decimal(14, 4)
|
||||
status ProductSurveyStatus @default(PENDING_REVIEW)
|
||||
|
||||
createdByCustomerId String?
|
||||
createdByCustomer Customer? @relation("SurveyCustomerCreator", fields: [createdByCustomerId], references: [id])
|
||||
createdByAdminId String?
|
||||
createdByAdmin Admin? @relation("SurveyAdminCreator", fields: [createdByAdminId], references: [id])
|
||||
|
||||
publishedAt DateTime?
|
||||
decidedAt DateTime?
|
||||
decidedByAdminId String?
|
||||
decidedByAdmin Admin? @relation("SurveyDecider", fields: [decidedByAdminId], references: [id])
|
||||
decisionNote String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
votes ProductSurveyVote[]
|
||||
|
||||
@@index([status])
|
||||
@@index([createdByCustomerId])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model ProductSurveyVote {
|
||||
id String @id @default(cuid())
|
||||
surveyId String
|
||||
survey ProductSurvey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
||||
customerId String
|
||||
customer Customer @relation(fields: [customerId], references: [id])
|
||||
value ProductSurveyVoteValue
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([surveyId, customerId])
|
||||
@@index([customerId])
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Settings — replaces legacy `config_static`, a key/value table the admin
|
||||
// panel read and wrote through endpoints like /wallet/config and
|
||||
|
||||
+66
@@ -248,6 +248,22 @@ exports.Prisma.CustomerScalarFieldEnum = {
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.CustomerCartScalarFieldEnum = {
|
||||
customerId: 'customerId',
|
||||
items: 'items',
|
||||
reminderSentForClearAt: 'reminderSentForClearAt',
|
||||
clearedAt: 'clearedAt',
|
||||
updatedAt: 'updatedAt',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.CustomerBuyLaterScalarFieldEnum = {
|
||||
customerId: 'customerId',
|
||||
items: 'items',
|
||||
updatedAt: 'updatedAt',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.CustomerFavoriteScalarFieldEnum = {
|
||||
customerId: 'customerId',
|
||||
productId: 'productId',
|
||||
@@ -318,11 +334,18 @@ exports.Prisma.ProductScalarFieldEnum = {
|
||||
showType: 'showType',
|
||||
isActive: 'isActive',
|
||||
createdAt: 'createdAt',
|
||||
tags: 'tags',
|
||||
accountingStockWeight: 'accountingStockWeight',
|
||||
accountingStockCount: 'accountingStockCount',
|
||||
accountingStockAt: 'accountingStockAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductViewScalarFieldEnum = {
|
||||
id: 'id',
|
||||
productId: 'productId',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductImageScalarFieldEnum = {
|
||||
id: 'id',
|
||||
productId: 'productId',
|
||||
@@ -484,6 +507,31 @@ exports.Prisma.CommentScalarFieldEnum = {
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductSurveyScalarFieldEnum = {
|
||||
id: 'id',
|
||||
title: 'title',
|
||||
imageUrl: 'imageUrl',
|
||||
suggestedWeightGrams: 'suggestedWeightGrams',
|
||||
status: 'status',
|
||||
createdByCustomerId: 'createdByCustomerId',
|
||||
createdByAdminId: 'createdByAdminId',
|
||||
publishedAt: 'publishedAt',
|
||||
decidedAt: 'decidedAt',
|
||||
decidedByAdminId: 'decidedByAdminId',
|
||||
decisionNote: 'decisionNote',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.ProductSurveyVoteScalarFieldEnum = {
|
||||
id: 'id',
|
||||
surveyId: 'surveyId',
|
||||
customerId: 'customerId',
|
||||
value: 'value',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.SettingScalarFieldEnum = {
|
||||
key: 'key',
|
||||
value: 'value',
|
||||
@@ -753,6 +801,19 @@ exports.CommentStatus = exports.$Enums.CommentStatus = {
|
||||
REJECTED: 'REJECTED'
|
||||
};
|
||||
|
||||
exports.ProductSurveyStatus = exports.$Enums.ProductSurveyStatus = {
|
||||
PENDING_REVIEW: 'PENDING_REVIEW',
|
||||
OPEN: 'OPEN',
|
||||
CLOSED: 'CLOSED',
|
||||
APPROVED: 'APPROVED',
|
||||
REJECTED: 'REJECTED'
|
||||
};
|
||||
|
||||
exports.ProductSurveyVoteValue = exports.$Enums.ProductSurveyVoteValue = {
|
||||
LIKE: 'LIKE',
|
||||
DISLIKE: 'DISLIKE'
|
||||
};
|
||||
|
||||
exports.AccountingEntityType = exports.$Enums.AccountingEntityType = {
|
||||
CUSTOMER: 'CUSTOMER',
|
||||
PRODUCT: 'PRODUCT'
|
||||
@@ -803,6 +864,8 @@ exports.Prisma.ModelName = {
|
||||
AdminSession: 'AdminSession',
|
||||
SalesExpertProfile: 'SalesExpertProfile',
|
||||
Customer: 'Customer',
|
||||
CustomerCart: 'CustomerCart',
|
||||
CustomerBuyLater: 'CustomerBuyLater',
|
||||
CustomerFavorite: 'CustomerFavorite',
|
||||
CustomerAddress: 'CustomerAddress',
|
||||
Branch: 'Branch',
|
||||
@@ -812,6 +875,7 @@ exports.Prisma.ModelName = {
|
||||
Collection: 'Collection',
|
||||
CollectionProduct: 'CollectionProduct',
|
||||
Product: 'Product',
|
||||
ProductView: 'ProductView',
|
||||
ProductImage: 'ProductImage',
|
||||
ProductVariant: 'ProductVariant',
|
||||
Order: 'Order',
|
||||
@@ -825,6 +889,8 @@ exports.Prisma.ModelName = {
|
||||
UserType: 'UserType',
|
||||
Permission: 'Permission',
|
||||
Comment: 'Comment',
|
||||
ProductSurvey: 'ProductSurvey',
|
||||
ProductSurveyVote: 'ProductSurveyVote',
|
||||
Setting: 'Setting',
|
||||
AccountingLink: 'AccountingLink',
|
||||
AccountingOutbox: 'AccountingOutbox',
|
||||
|
||||
Reference in New Issue
Block a user