feat(ux/sms/engine): complete Persian UX writing overhaul, Wolog SMS integration and respin support
This commit is contained in:
+2259
-575
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AccessScopeType" AS ENUM ('ALL', 'CUSTOM_CAMPAIGNS');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "admins" ADD COLUMN "is_super_admin" BOOLEAN NOT NULL DEFAULT false,
|
||||
ADD COLUMN "last_login_at" TIMESTAMP(3);
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "campaigns" ADD COLUMN "workspace_id" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "workspaces" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'ACTIVE',
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "workspaces_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "roles" (
|
||||
"id" TEXT NOT NULL,
|
||||
"code" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"is_system" BOOLEAN NOT NULL DEFAULT false,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "roles_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "permissions" (
|
||||
"id" TEXT NOT NULL,
|
||||
"code" TEXT NOT NULL,
|
||||
"module" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
|
||||
CONSTRAINT "permissions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "role_permissions" (
|
||||
"role_id" TEXT NOT NULL,
|
||||
"permission_id" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "role_permissions_pkey" PRIMARY KEY ("role_id","permission_id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "admin_role_assignments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"admin_id" TEXT NOT NULL,
|
||||
"role_id" TEXT NOT NULL,
|
||||
"assigned_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "admin_role_assignments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "admin_workspace_assignments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"admin_id" TEXT NOT NULL,
|
||||
"workspace_id" TEXT NOT NULL,
|
||||
"scope_type" "AccessScopeType" NOT NULL DEFAULT 'ALL',
|
||||
"specific_campaign_ids" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "admin_workspace_assignments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "workspaces_slug_key" ON "workspaces"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "roles_code_key" ON "roles"("code");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "permissions_code_key" ON "permissions"("code");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "permissions_module_idx" ON "permissions"("module");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "admin_role_assignments_admin_id_role_id_key" ON "admin_role_assignments"("admin_id", "role_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "admin_workspace_assignments_admin_id_workspace_id_key" ON "admin_workspace_assignments"("admin_id", "workspace_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "campaigns_workspace_id_idx" ON "campaigns"("workspace_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "campaigns" ADD CONSTRAINT "campaigns_workspace_id_fkey" FOREIGN KEY ("workspace_id") REFERENCES "workspaces"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "role_permissions" ADD CONSTRAINT "role_permissions_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "roles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "role_permissions" ADD CONSTRAINT "role_permissions_permission_id_fkey" FOREIGN KEY ("permission_id") REFERENCES "permissions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "admin_role_assignments" ADD CONSTRAINT "admin_role_assignments_admin_id_fkey" FOREIGN KEY ("admin_id") REFERENCES "admins"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "admin_role_assignments" ADD CONSTRAINT "admin_role_assignments_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "roles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "admin_workspace_assignments" ADD CONSTRAINT "admin_workspace_assignments_admin_id_fkey" FOREIGN KEY ("admin_id") REFERENCES "admins"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "admin_workspace_assignments" ADD CONSTRAINT "admin_workspace_assignments_workspace_id_fkey" FOREIGN KEY ("workspace_id") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+1882
-92
File diff suppressed because it is too large
Load Diff
+71
-7
File diff suppressed because one or more lines are too long
+64
-1
@@ -130,6 +130,8 @@ exports.Prisma.AdminScalarFieldEnum = {
|
||||
passwordHash: 'passwordHash',
|
||||
role: 'role',
|
||||
status: 'status',
|
||||
isSuperAdmin: 'isSuperAdmin',
|
||||
lastLoginAt: 'lastLoginAt',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
@@ -171,6 +173,7 @@ exports.Prisma.CampaignScalarFieldEnum = {
|
||||
ctaText: 'ctaText',
|
||||
wheelDesign: 'wheelDesign',
|
||||
settings: 'settings',
|
||||
workspaceId: 'workspaceId',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
@@ -266,6 +269,55 @@ exports.Prisma.AdminLogScalarFieldEnum = {
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.WorkspaceScalarFieldEnum = {
|
||||
id: 'id',
|
||||
name: 'name',
|
||||
slug: 'slug',
|
||||
description: 'description',
|
||||
status: 'status',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.RoleScalarFieldEnum = {
|
||||
id: 'id',
|
||||
code: 'code',
|
||||
name: 'name',
|
||||
description: 'description',
|
||||
isSystem: 'isSystem',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.PermissionScalarFieldEnum = {
|
||||
id: 'id',
|
||||
code: 'code',
|
||||
module: 'module',
|
||||
name: 'name',
|
||||
description: 'description'
|
||||
};
|
||||
|
||||
exports.Prisma.RolePermissionScalarFieldEnum = {
|
||||
roleId: 'roleId',
|
||||
permissionId: 'permissionId'
|
||||
};
|
||||
|
||||
exports.Prisma.AdminRoleAssignmentScalarFieldEnum = {
|
||||
id: 'id',
|
||||
adminId: 'adminId',
|
||||
roleId: 'roleId',
|
||||
assignedAt: 'assignedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.AdminWorkspaceAssignmentScalarFieldEnum = {
|
||||
id: 'id',
|
||||
adminId: 'adminId',
|
||||
workspaceId: 'workspaceId',
|
||||
scopeType: 'scopeType',
|
||||
specificCampaignIds: 'specificCampaignIds',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
@@ -382,6 +434,11 @@ exports.SmsStatus = exports.$Enums.SmsStatus = {
|
||||
FAILED: 'FAILED'
|
||||
};
|
||||
|
||||
exports.AccessScopeType = exports.$Enums.AccessScopeType = {
|
||||
ALL: 'ALL',
|
||||
CUSTOM_CAMPAIGNS: 'CUSTOM_CAMPAIGNS'
|
||||
};
|
||||
|
||||
exports.Prisma.ModelName = {
|
||||
Admin: 'Admin',
|
||||
User: 'User',
|
||||
@@ -393,7 +450,13 @@ exports.Prisma.ModelName = {
|
||||
Spin: 'Spin',
|
||||
UserPrize: 'UserPrize',
|
||||
SmsLog: 'SmsLog',
|
||||
AdminLog: 'AdminLog'
|
||||
AdminLog: 'AdminLog',
|
||||
Workspace: 'Workspace',
|
||||
Role: 'Role',
|
||||
Permission: 'Permission',
|
||||
RolePermission: 'RolePermission',
|
||||
AdminRoleAssignment: 'AdminRoleAssignment',
|
||||
AdminWorkspaceAssignment: 'AdminWorkspaceAssignment'
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+9238
-110
File diff suppressed because it is too large
Load Diff
+71
-7
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "prisma-client-9c4b98c054c4413303a6fe7479f16a8ffbbc92ed96b3de050b8208db40acf7bd",
|
||||
"name": "prisma-client-729d66798105c30ac604d26a6c005aea0a1618ad5abaf33082e4e12fa468731d",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"browser": "index-browser.js",
|
||||
|
||||
+95
-2
@@ -22,6 +22,11 @@ enum AdminRole {
|
||||
SUPPORT
|
||||
}
|
||||
|
||||
enum AccessScopeType {
|
||||
ALL
|
||||
CUSTOM_CAMPAIGNS
|
||||
}
|
||||
|
||||
enum UserStatus {
|
||||
ACTIVE
|
||||
BLOCKED
|
||||
@@ -112,11 +117,15 @@ model Admin {
|
||||
passwordHash String @map("password_hash")
|
||||
role AdminRole @default(OPERATOR)
|
||||
status AdminStatus @default(ACTIVE)
|
||||
isSuperAdmin Boolean @default(false) @map("is_super_admin")
|
||||
lastLoginAt DateTime? @map("last_login_at")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
auditLogs AdminLog[]
|
||||
chanceTxns ChanceTransaction[] @relation("AdminCreatedTxn")
|
||||
auditLogs AdminLog[]
|
||||
chanceTxns ChanceTransaction[] @relation("AdminCreatedTxn")
|
||||
roles AdminRoleAssignment[]
|
||||
workspaceAssignments AdminWorkspaceAssignment[]
|
||||
|
||||
@@map("admins")
|
||||
}
|
||||
@@ -172,6 +181,8 @@ model Campaign {
|
||||
ctaText String? @map("cta_text")
|
||||
wheelDesign WheelDesign @default(CLASSIC_CASINO) @map("wheel_design")
|
||||
settings Json? // primaryColor, secondaryColor, headerText, buttonText, headerImage, celebrationEffect...
|
||||
workspaceId String? @map("workspace_id")
|
||||
workspace Workspace? @relation(fields: [workspaceId], references: [id])
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@ -182,6 +193,7 @@ model Campaign {
|
||||
userPrizes UserPrize[]
|
||||
|
||||
@@index([status, startAt, endAt])
|
||||
@@index([workspaceId])
|
||||
@@map("campaigns")
|
||||
}
|
||||
|
||||
@@ -318,3 +330,84 @@ model AdminLog {
|
||||
@@index([entityType, entityId])
|
||||
@@map("admin_logs")
|
||||
}
|
||||
|
||||
// ==================== WORKSPACE & RBAC MODELS ====================
|
||||
|
||||
model Workspace {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
status String @default("ACTIVE")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
campaigns Campaign[]
|
||||
adminAssignments AdminWorkspaceAssignment[]
|
||||
|
||||
@@map("workspaces")
|
||||
}
|
||||
|
||||
model Role {
|
||||
id String @id @default(uuid())
|
||||
code String @unique // e.g. "SUPER_ADMIN", "OPERATOR", "SUPPORT"
|
||||
name String // نام فارسی
|
||||
description String?
|
||||
isSystem Boolean @default(false) @map("is_system")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
permissions RolePermission[]
|
||||
admins AdminRoleAssignment[]
|
||||
|
||||
@@map("roles")
|
||||
}
|
||||
|
||||
model Permission {
|
||||
id String @id @default(uuid())
|
||||
code String @unique // e.g. "campaigns:read", "campaigns:create"
|
||||
module String // e.g. "campaigns", "users", "prizes", "reports", "admins"
|
||||
name String // نام فارسی
|
||||
description String?
|
||||
|
||||
roles RolePermission[]
|
||||
|
||||
@@index([module])
|
||||
@@map("permissions")
|
||||
}
|
||||
|
||||
model RolePermission {
|
||||
roleId String @map("role_id")
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
permissionId String @map("permission_id")
|
||||
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([roleId, permissionId])
|
||||
@@map("role_permissions")
|
||||
}
|
||||
|
||||
model AdminRoleAssignment {
|
||||
id String @id @default(uuid())
|
||||
adminId String @map("admin_id")
|
||||
admin Admin @relation(fields: [adminId], references: [id], onDelete: Cascade)
|
||||
roleId String @map("role_id")
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
assignedAt DateTime @default(now()) @map("assigned_at")
|
||||
|
||||
@@unique([adminId, roleId])
|
||||
@@map("admin_role_assignments")
|
||||
}
|
||||
|
||||
model AdminWorkspaceAssignment {
|
||||
id String @id @default(uuid())
|
||||
adminId String @map("admin_id")
|
||||
admin Admin @relation(fields: [adminId], references: [id], onDelete: Cascade)
|
||||
workspaceId String @map("workspace_id")
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
scopeType AccessScopeType @default(ALL) @map("scope_type")
|
||||
specificCampaignIds Json? @map("specific_campaign_ids")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@unique([adminId, workspaceId])
|
||||
@@map("admin_workspace_assignments")
|
||||
}
|
||||
|
||||
+64
-1
@@ -130,6 +130,8 @@ exports.Prisma.AdminScalarFieldEnum = {
|
||||
passwordHash: 'passwordHash',
|
||||
role: 'role',
|
||||
status: 'status',
|
||||
isSuperAdmin: 'isSuperAdmin',
|
||||
lastLoginAt: 'lastLoginAt',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
@@ -171,6 +173,7 @@ exports.Prisma.CampaignScalarFieldEnum = {
|
||||
ctaText: 'ctaText',
|
||||
wheelDesign: 'wheelDesign',
|
||||
settings: 'settings',
|
||||
workspaceId: 'workspaceId',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
@@ -266,6 +269,55 @@ exports.Prisma.AdminLogScalarFieldEnum = {
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.WorkspaceScalarFieldEnum = {
|
||||
id: 'id',
|
||||
name: 'name',
|
||||
slug: 'slug',
|
||||
description: 'description',
|
||||
status: 'status',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.RoleScalarFieldEnum = {
|
||||
id: 'id',
|
||||
code: 'code',
|
||||
name: 'name',
|
||||
description: 'description',
|
||||
isSystem: 'isSystem',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.PermissionScalarFieldEnum = {
|
||||
id: 'id',
|
||||
code: 'code',
|
||||
module: 'module',
|
||||
name: 'name',
|
||||
description: 'description'
|
||||
};
|
||||
|
||||
exports.Prisma.RolePermissionScalarFieldEnum = {
|
||||
roleId: 'roleId',
|
||||
permissionId: 'permissionId'
|
||||
};
|
||||
|
||||
exports.Prisma.AdminRoleAssignmentScalarFieldEnum = {
|
||||
id: 'id',
|
||||
adminId: 'adminId',
|
||||
roleId: 'roleId',
|
||||
assignedAt: 'assignedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.AdminWorkspaceAssignmentScalarFieldEnum = {
|
||||
id: 'id',
|
||||
adminId: 'adminId',
|
||||
workspaceId: 'workspaceId',
|
||||
scopeType: 'scopeType',
|
||||
specificCampaignIds: 'specificCampaignIds',
|
||||
createdAt: 'createdAt'
|
||||
};
|
||||
|
||||
exports.Prisma.SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
@@ -382,6 +434,11 @@ exports.SmsStatus = exports.$Enums.SmsStatus = {
|
||||
FAILED: 'FAILED'
|
||||
};
|
||||
|
||||
exports.AccessScopeType = exports.$Enums.AccessScopeType = {
|
||||
ALL: 'ALL',
|
||||
CUSTOM_CAMPAIGNS: 'CUSTOM_CAMPAIGNS'
|
||||
};
|
||||
|
||||
exports.Prisma.ModelName = {
|
||||
Admin: 'Admin',
|
||||
User: 'User',
|
||||
@@ -393,7 +450,13 @@ exports.Prisma.ModelName = {
|
||||
Spin: 'Spin',
|
||||
UserPrize: 'UserPrize',
|
||||
SmsLog: 'SmsLog',
|
||||
AdminLog: 'AdminLog'
|
||||
AdminLog: 'AdminLog',
|
||||
Workspace: 'Workspace',
|
||||
Role: 'Role',
|
||||
Permission: 'Permission',
|
||||
RolePermission: 'RolePermission',
|
||||
AdminRoleAssignment: 'AdminRoleAssignment',
|
||||
AdminWorkspaceAssignment: 'AdminWorkspaceAssignment'
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user