- Added Docker support (Dockerfiles, docker-compose.yml) - Fixed authentication and authorization (token storage, CORS, permissions) - Fixed API response transformations for all modules - Added production deployment scripts and guides - Fixed frontend permission checks and module access - Added database seeding script for production - Complete documentation for deployment and configuration Co-authored-by: Cursor <cursoragent@cursor.com>
304 lines
7.7 KiB
JavaScript
304 lines
7.7 KiB
JavaScript
const { PrismaClient } = require('@prisma/client');
|
|
const bcrypt = require('bcryptjs');
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function main() {
|
|
console.log('🌱 Starting database seeding...');
|
|
|
|
// Create Departments
|
|
const salesDept = await prisma.department.create({
|
|
data: {
|
|
name: 'Sales Department',
|
|
nameAr: 'قسم المبيعات',
|
|
code: 'SALES',
|
|
description: 'Sales and Business Development',
|
|
},
|
|
});
|
|
|
|
const itDept = await prisma.department.create({
|
|
data: {
|
|
name: 'IT Department',
|
|
nameAr: 'قسم تقنية المعلومات',
|
|
code: 'IT',
|
|
description: 'Information Technology',
|
|
},
|
|
});
|
|
|
|
const hrDept = await prisma.department.create({
|
|
data: {
|
|
name: 'HR Department',
|
|
nameAr: 'قسم الموارد البشرية',
|
|
code: 'HR',
|
|
description: 'Human Resources',
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created departments');
|
|
|
|
// Create Positions
|
|
const gmPosition = await prisma.position.create({
|
|
data: {
|
|
title: 'General Manager',
|
|
titleAr: 'المدير العام',
|
|
code: 'GM',
|
|
departmentId: salesDept.id,
|
|
level: 1,
|
|
description: 'Chief Executive - Full Access',
|
|
},
|
|
});
|
|
|
|
const salesManagerPosition = await prisma.position.create({
|
|
data: {
|
|
title: 'Sales Manager',
|
|
titleAr: 'مدير المبيعات',
|
|
code: 'SM',
|
|
departmentId: salesDept.id,
|
|
level: 2,
|
|
description: 'Sales Department Manager',
|
|
},
|
|
});
|
|
|
|
const salesRepPosition = await prisma.position.create({
|
|
data: {
|
|
title: 'Sales Representative',
|
|
titleAr: 'مندوب مبيعات',
|
|
code: 'SR',
|
|
departmentId: salesDept.id,
|
|
level: 3,
|
|
description: 'Sales Representative',
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created positions');
|
|
|
|
// Create Permissions for GM (Full Access)
|
|
const modules = ['contacts', 'crm', 'inventory', 'projects', 'hr', 'marketing'];
|
|
for (const module of modules) {
|
|
await prisma.positionPermission.create({
|
|
data: {
|
|
positionId: gmPosition.id,
|
|
module: module,
|
|
resource: 'all',
|
|
actions: ['create', 'read', 'update', 'delete', 'export', 'approve'],
|
|
},
|
|
});
|
|
}
|
|
|
|
// Create Permissions for Sales Manager
|
|
await prisma.positionPermission.create({
|
|
data: {
|
|
positionId: salesManagerPosition.id,
|
|
module: 'contacts',
|
|
resource: 'contacts',
|
|
actions: ['create', 'read', 'update', 'delete', 'export'],
|
|
},
|
|
});
|
|
|
|
await prisma.positionPermission.create({
|
|
data: {
|
|
positionId: salesManagerPosition.id,
|
|
module: 'crm',
|
|
resource: 'deals',
|
|
actions: ['create', 'read', 'update', 'approve', 'export'],
|
|
},
|
|
});
|
|
|
|
// Create Permissions for Sales Rep
|
|
await prisma.positionPermission.create({
|
|
data: {
|
|
positionId: salesRepPosition.id,
|
|
module: 'contacts',
|
|
resource: 'contacts',
|
|
actions: ['create', 'read', 'update'],
|
|
},
|
|
});
|
|
|
|
await prisma.positionPermission.create({
|
|
data: {
|
|
positionId: salesRepPosition.id,
|
|
module: 'crm',
|
|
resource: 'deals',
|
|
actions: ['create', 'read', 'update'],
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created permissions');
|
|
|
|
// Create Employees
|
|
const hashedPassword = await bcrypt.hash('Admin@123', 10);
|
|
|
|
const gmEmployee = await prisma.employee.create({
|
|
data: {
|
|
uniqueEmployeeId: 'EMP-001',
|
|
firstName: 'Ahmed',
|
|
lastName: 'Al-Mansour',
|
|
firstNameAr: 'أحمد',
|
|
lastNameAr: 'المنصور',
|
|
email: 'gm@atmata.com',
|
|
mobile: '+966501234567',
|
|
employmentType: 'Full-time',
|
|
hireDate: new Date('2020-01-01'),
|
|
departmentId: salesDept.id,
|
|
positionId: gmPosition.id,
|
|
basicSalary: 50000,
|
|
status: 'ACTIVE',
|
|
},
|
|
});
|
|
|
|
const salesManager = await prisma.employee.create({
|
|
data: {
|
|
uniqueEmployeeId: 'EMP-002',
|
|
firstName: 'Fahd',
|
|
lastName: 'Al-Sayed',
|
|
firstNameAr: 'فهد',
|
|
lastNameAr: 'السيد',
|
|
email: 'sales.manager@atmata.com',
|
|
mobile: '+966507654321',
|
|
employmentType: 'Full-time',
|
|
hireDate: new Date('2021-01-01'),
|
|
departmentId: salesDept.id,
|
|
positionId: salesManagerPosition.id,
|
|
reportingToId: gmEmployee.id,
|
|
basicSalary: 30000,
|
|
status: 'ACTIVE',
|
|
},
|
|
});
|
|
|
|
const salesRep = await prisma.employee.create({
|
|
data: {
|
|
uniqueEmployeeId: 'EMP-003',
|
|
firstName: 'Omar',
|
|
lastName: 'Al-Hassan',
|
|
firstNameAr: 'عمر',
|
|
lastNameAr: 'الحسن',
|
|
email: 'sales.rep@atmata.com',
|
|
mobile: '+966509876543',
|
|
employmentType: 'Full-time',
|
|
hireDate: new Date('2022-01-01'),
|
|
departmentId: salesDept.id,
|
|
positionId: salesRepPosition.id,
|
|
reportingToId: salesManager.id,
|
|
basicSalary: 15000,
|
|
status: 'ACTIVE',
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created employees');
|
|
|
|
// Create Users
|
|
await prisma.user.create({
|
|
data: {
|
|
email: 'gm@atmata.com',
|
|
username: 'general.manager',
|
|
password: hashedPassword,
|
|
isActive: true,
|
|
employeeId: gmEmployee.id,
|
|
},
|
|
});
|
|
|
|
await prisma.user.create({
|
|
data: {
|
|
email: 'sales.manager@atmata.com',
|
|
username: 'sales.manager',
|
|
password: hashedPassword,
|
|
isActive: true,
|
|
employeeId: salesManager.id,
|
|
},
|
|
});
|
|
|
|
await prisma.user.create({
|
|
data: {
|
|
email: 'sales.rep@atmata.com',
|
|
username: 'sales.rep',
|
|
password: hashedPassword,
|
|
isActive: true,
|
|
employeeId: salesRep.id,
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created users');
|
|
|
|
// Create Contact Categories
|
|
await prisma.contactCategory.create({
|
|
data: {
|
|
name: 'Client',
|
|
nameAr: 'عميل',
|
|
},
|
|
});
|
|
|
|
await prisma.contactCategory.create({
|
|
data: {
|
|
name: 'Supplier',
|
|
nameAr: 'مورّد',
|
|
},
|
|
});
|
|
|
|
await prisma.contactCategory.create({
|
|
data: {
|
|
name: 'Partner',
|
|
nameAr: 'شريك',
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created contact categories');
|
|
|
|
// Create Pipelines
|
|
await prisma.pipeline.create({
|
|
data: {
|
|
name: 'B2B Sales Pipeline',
|
|
nameAr: 'مسار مبيعات الشركات',
|
|
structure: 'B2B',
|
|
stages: [
|
|
{ name: 'OPEN', order: 1 },
|
|
{ name: 'NEGOTIATION', order: 2 },
|
|
{ name: 'PENDING_INTERNAL', order: 3 },
|
|
{ name: 'PENDING_CLIENT', order: 4 },
|
|
{ name: 'WON', order: 5 },
|
|
{ name: 'LOST', order: 6 },
|
|
],
|
|
},
|
|
});
|
|
|
|
await prisma.pipeline.create({
|
|
data: {
|
|
name: 'B2C Sales Pipeline',
|
|
nameAr: 'مسار المبيعات الفردية',
|
|
structure: 'B2C',
|
|
stages: [
|
|
{ name: 'OPEN', order: 1 },
|
|
{ name: 'NEGOTIATION', order: 2 },
|
|
{ name: 'WON', order: 3 },
|
|
{ name: 'LOST', order: 4 },
|
|
],
|
|
},
|
|
});
|
|
|
|
console.log('✅ Created pipelines');
|
|
|
|
console.log('\n🎉 Database seeding completed successfully!');
|
|
console.log('\n📝 Login Credentials:');
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
console.log('👤 General Manager:');
|
|
console.log(' Email: gm@atmata.com');
|
|
console.log(' Password: Admin@123');
|
|
console.log('');
|
|
console.log('👤 Sales Manager:');
|
|
console.log(' Email: sales.manager@atmata.com');
|
|
console.log(' Password: Admin@123');
|
|
console.log('');
|
|
console.log('👤 Sales Representative:');
|
|
console.log(' Email: sales.rep@atmata.com');
|
|
console.log(' Password: Admin@123');
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error('❌ Error seeding database:', e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|