252 lines
7.1 KiB
TypeScript
252 lines
7.1 KiB
TypeScript
import {
|
|
PrismaClient,
|
|
RiskStatus,
|
|
TodoStatus,
|
|
Role,
|
|
PriorityStatus,
|
|
SecurityType,
|
|
} from "@prisma/client";
|
|
import bcrypt from "bcryptjs";
|
|
|
|
import {
|
|
firstNames,
|
|
lastNames,
|
|
jobTitles,
|
|
actionVerbs,
|
|
subjects,
|
|
loremWords,
|
|
phoneNumbers,
|
|
middleNames,
|
|
departments,
|
|
} from "./mockData";
|
|
|
|
const sentenceFrom = (seed: number, min = 10, max = 22) => {
|
|
const len = min + (seed % (max - min + 1));
|
|
const words: string[] = [];
|
|
let i = seed;
|
|
for (let c = 0; c < len; c++) {
|
|
i = (i * 9301 + 49297) % 233280;
|
|
words.push(loremWords[i % loremWords.length]);
|
|
}
|
|
const s = words.join(" ");
|
|
return s.charAt(0).toUpperCase() + s.slice(1) + ".";
|
|
};
|
|
|
|
const uniqueTitle = (idx: number) => {
|
|
const verb = actionVerbs[idx % actionVerbs.length];
|
|
const subj = subjects[(idx * 7) % subjects.length];
|
|
return `${verb} ${subj} #${idx + 1}`;
|
|
};
|
|
|
|
const uniqueTask = (idx: number) => {
|
|
// Blend a seeded lorem sentence with a hint to ensure uniqueness
|
|
const hint = `${firstNames[idx % firstNames.length]} ${
|
|
lastNames[(idx * 3) % lastNames.length]
|
|
} ${jobTitles[(idx * 5) % jobTitles.length]}`;
|
|
return `${sentenceFrom(idx)}\n\nContext: ${hint} [T${idx + 1}]`;
|
|
};
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const getRandom = <T>(arr: T[]): T =>
|
|
arr[Math.floor(Math.random() * arr.length)];
|
|
|
|
// Determine security type by role for consistent seed data
|
|
const securityFor = (role: Role): SecurityType => {
|
|
switch (role) {
|
|
case Role.MANAGER:
|
|
return SecurityType.MAXIMUM;
|
|
case Role.ADMIN:
|
|
return SecurityType.ASSISTANCE;
|
|
case Role.USER:
|
|
default:
|
|
return SecurityType.BASIC;
|
|
}
|
|
};
|
|
|
|
async function main() {
|
|
console.log("🌱 Starting seed...");
|
|
await prisma.todo.deleteMany();
|
|
await prisma.user.deleteMany();
|
|
|
|
const users = [] as Array<Awaited<ReturnType<typeof prisma.user.create>>>;
|
|
|
|
const defaultPassword = await bcrypt.hash("password", 10);
|
|
|
|
const superAdmin = await prisma.user.create({
|
|
data: {
|
|
firstName: "Super",
|
|
middleName: "John Travolta",
|
|
lastName: "Admin",
|
|
email: "superadmin@example.com",
|
|
password: defaultPassword,
|
|
riskStatus: RiskStatus.NO_RISK,
|
|
phoneNumber: "1234567890",
|
|
department: "Admin",
|
|
imageUrl: null,
|
|
title: "Administrator",
|
|
isLocked: false,
|
|
isActivated: true,
|
|
role: Role.MANAGER,
|
|
securityType: securityFor(Role.MANAGER),
|
|
},
|
|
});
|
|
users.push(superAdmin);
|
|
|
|
// Second MANAGER (Manager)
|
|
const managerSuperAdmin = await prisma.user.create({
|
|
data: {
|
|
firstName: "Manager",
|
|
middleName: "John Travolta",
|
|
lastName: "SuperAdmin",
|
|
email: "manager@example.com",
|
|
password: defaultPassword,
|
|
riskStatus: RiskStatus.NO_RISK,
|
|
phoneNumber: "1234567890",
|
|
department: "Admin",
|
|
imageUrl: null,
|
|
title: "Administrator",
|
|
isLocked: false,
|
|
isActivated: true,
|
|
role: Role.MANAGER,
|
|
securityType: securityFor(Role.MANAGER),
|
|
},
|
|
});
|
|
users.push(managerSuperAdmin);
|
|
|
|
// Create 10 ADMIN users and split them between the two MANAGERs' teams
|
|
const teamAAdmins: Array<Awaited<ReturnType<typeof prisma.user.create>>> = [];
|
|
const teamBAdmins: Array<Awaited<ReturnType<typeof prisma.user.create>>> = [];
|
|
for (let i = 1; i <= 10; i++) {
|
|
const assignedManagerId = i <= 5 ? superAdmin.id : managerSuperAdmin.id;
|
|
const adminUser = await prisma.user.create({
|
|
data: {
|
|
firstName: `Admin${i}`,
|
|
middleName: "Admin",
|
|
lastName: "User",
|
|
email: `admin${i}@example.com`,
|
|
phoneNumber: `123456789${i}`,
|
|
department: "Admin",
|
|
password: defaultPassword,
|
|
riskStatus: RiskStatus.NO_RISK,
|
|
imageUrl: null,
|
|
title: "Administrator",
|
|
isLocked: false,
|
|
isActivated: true,
|
|
role: Role.ADMIN,
|
|
securityType: securityFor(Role.ADMIN),
|
|
managerId: assignedManagerId,
|
|
},
|
|
});
|
|
users.push(adminUser);
|
|
if (assignedManagerId === superAdmin.id) {
|
|
teamAAdmins.push(adminUser);
|
|
} else {
|
|
teamBAdmins.push(adminUser);
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < 100; i++) {
|
|
const firstName = getRandom(firstNames);
|
|
const lastName = getRandom(lastNames);
|
|
const middleName = getRandom(middleNames);
|
|
const phoneNumber = getRandom(phoneNumbers);
|
|
const department = getRandom(departments);
|
|
|
|
const user = await prisma.user.create({
|
|
data: {
|
|
firstName,
|
|
middleName,
|
|
lastName,
|
|
email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${i}@example.com`,
|
|
phoneNumber,
|
|
department,
|
|
password: defaultPassword,
|
|
riskStatus: getRandom(Object.values(RiskStatus)),
|
|
imageUrl:
|
|
Math.random() > 0.5
|
|
? `https://i.pravatar.cc/150?u=${firstName}${lastName}${i}`
|
|
: null,
|
|
title: getRandom(jobTitles),
|
|
isLocked: false,
|
|
isActivated: true,
|
|
role: Role.USER,
|
|
securityType: securityFor(Role.USER),
|
|
},
|
|
});
|
|
|
|
users.push(user);
|
|
}
|
|
|
|
// Build team pools (Manager + their Admins)
|
|
const teamA = [superAdmin, ...teamAAdmins];
|
|
const teamB = [managerSuperAdmin, ...teamBAdmins];
|
|
|
|
// Helper: get a random subset from an array (unique, size k)
|
|
const pickSubset = <T extends { id: string }>(arr: T[], k: number): T[] => {
|
|
const n = Math.max(1, Math.min(k, arr.length));
|
|
const pool = [...arr];
|
|
for (let i = pool.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[pool[i], pool[j]] = [pool[j], pool[i]];
|
|
}
|
|
return pool.slice(0, n);
|
|
};
|
|
|
|
// Create 50 todos split evenly between the two teams.
|
|
const totalTodos = 50;
|
|
const half = Math.floor(totalTodos / 2);
|
|
let todoIndex = 0;
|
|
|
|
const createTeamTodo = async (
|
|
team: Array<Awaited<ReturnType<typeof prisma.user.create>>>
|
|
) => {
|
|
const createdByUser = getRandom(team);
|
|
// 1-3 assignees from the same team (ensure createdBy is included)
|
|
const baseAssignees = pickSubset(
|
|
team,
|
|
1 + Math.floor(Math.random() * Math.min(3, team.length))
|
|
);
|
|
const ensureCreatedBy = baseAssignees.some((u) => u.id === createdByUser.id)
|
|
? baseAssignees
|
|
: [...baseAssignees, createdByUser];
|
|
const uniqueAssignees = Array.from(
|
|
new Map(ensureCreatedBy.map((u) => [u.id, u])).values()
|
|
);
|
|
|
|
const dueDate = new Date();
|
|
dueDate.setDate(dueDate.getDate() + Math.floor(Math.random() * 30));
|
|
|
|
await prisma.todo.create({
|
|
data: {
|
|
title: uniqueTitle(todoIndex),
|
|
task: uniqueTask(todoIndex),
|
|
status: getRandom(Object.values(TodoStatus)),
|
|
priority: getRandom(Object.values(PriorityStatus)),
|
|
dueDate,
|
|
createdBy: { connect: { id: createdByUser.id } },
|
|
assignees: { connect: uniqueAssignees.map((u) => ({ id: u.id })) },
|
|
},
|
|
});
|
|
todoIndex += 1;
|
|
};
|
|
|
|
for (let i = 0; i < half; i++) {
|
|
await createTeamTodo(teamA);
|
|
}
|
|
for (let i = 0; i < totalTodos - half; i++) {
|
|
await createTeamTodo(teamB);
|
|
}
|
|
|
|
console.log(`✅ Seeded ${users.length} users and 50 todos`);
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error("❌ Seed error:", e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|