(Feat): Initial Commit
This commit is contained in:
240
backend/database/database_seed.js
Normal file
240
backend/database/database_seed.js
Normal file
@@ -0,0 +1,240 @@
|
||||
import bcrypt from 'bcryptjs';
|
||||
import mysql from 'mysql2/promise';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
async function seedDatabase() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
// Connect to database with retry logic
|
||||
console.log('🔌 Connecting to database...');
|
||||
|
||||
let retries = 5;
|
||||
while (retries > 0) {
|
||||
try {
|
||||
connection = await mysql.createConnection({
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'admin123',
|
||||
database: process.env.DB_NAME || 'work_allocation',
|
||||
port: process.env.DB_PORT || 3306,
|
||||
connectTimeout: 10000,
|
||||
enableKeepAlive: true,
|
||||
keepAliveInitialDelay: 0
|
||||
});
|
||||
break;
|
||||
} catch (err) {
|
||||
retries--;
|
||||
if (retries === 0) throw err;
|
||||
console.log(` ⏳ Retrying connection... (${5 - retries}/5)`);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
console.log('✅ Connected to database');
|
||||
console.log('');
|
||||
|
||||
// 1. Seed Departments
|
||||
console.log('📁 Seeding departments...');
|
||||
const [existingDepts] = await connection.query('SELECT COUNT(*) as count FROM departments');
|
||||
|
||||
if (existingDepts[0].count === 0) {
|
||||
await connection.query(`
|
||||
INSERT INTO departments (name) VALUES
|
||||
('Tudki'),
|
||||
('Dana'),
|
||||
('Groundnut')
|
||||
`);
|
||||
console.log(' ✅ Departments created');
|
||||
} else {
|
||||
console.log(' ℹ️ Departments already exist');
|
||||
}
|
||||
|
||||
// 2. Seed Sub-departments for Groundnut
|
||||
console.log('📂 Seeding sub-departments...');
|
||||
const [groundnutDept] = await connection.query('SELECT id FROM departments WHERE name = ?', ['Groundnut']);
|
||||
let groundnutId = null;
|
||||
|
||||
if (groundnutDept.length > 0) {
|
||||
groundnutId = groundnutDept[0].id;
|
||||
const [existingSubDepts] = await connection.query('SELECT COUNT(*) as count FROM sub_departments WHERE department_id = ?', [groundnutId]);
|
||||
|
||||
if (existingSubDepts[0].count === 0) {
|
||||
await connection.query(`
|
||||
INSERT INTO sub_departments (department_id, name, primary_activity) VALUES
|
||||
(?, 'Mufali Aavak Katai', 'Loading/Unloading'),
|
||||
(?, 'Mufali Aavak Dhang', 'Loading/Unloading'),
|
||||
(?, 'Dhang Se Katai', 'Loading/Unloading'),
|
||||
(?, 'Guthli Bori Silai Dhang', 'Loading/Unloading'),
|
||||
(?, 'Guthali dada Pala Tulai Silai Dhang', 'Loading/Unloading'),
|
||||
(?, 'Mufali Patthar Bori silai dhang', 'Loading/Unloading'),
|
||||
(?, 'Mufali Patthar Bori Utrai', 'Loading/Unloading'),
|
||||
(?, 'Bardana Bandal Loading Unloading', 'Loading/Unloading'),
|
||||
(?, 'Bardana Gatthi Loading', 'Loading/Unloading'),
|
||||
(?, 'Black Dana Loading/Unloading', 'Loading/Unloading'),
|
||||
(?, 'Pre Cleaning', 'Pre Cleaning'),
|
||||
(?, 'Destoner', 'Destoner'),
|
||||
(?, 'Water', 'Water'),
|
||||
(?, 'Decordicater', 'Decordicater & Cleaning'),
|
||||
(?, 'Round Chalna', 'Round Chalna & Cleaning'),
|
||||
(?, 'Cleaning', 'Decordicater & Cleaning'),
|
||||
(?, 'Round Chalna No.1', 'Round Chalna No.1')
|
||||
`, Array(17).fill(groundnutId));
|
||||
console.log(' ✅ Sub-departments created');
|
||||
} else {
|
||||
console.log(' ℹ️ Sub-departments already exist');
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Seed SuperAdmin
|
||||
console.log('👤 Seeding SuperAdmin user...');
|
||||
const [existingAdmin] = await connection.query('SELECT id FROM users WHERE username = ?', ['admin']);
|
||||
|
||||
const adminPassword = await bcrypt.hash('admin123', 10);
|
||||
|
||||
if (existingAdmin.length > 0) {
|
||||
await connection.query(
|
||||
'UPDATE users SET password = ?, is_active = TRUE WHERE username = ?',
|
||||
[adminPassword, 'admin']
|
||||
);
|
||||
console.log(' ✅ SuperAdmin password updated');
|
||||
} else {
|
||||
await connection.query(
|
||||
'INSERT INTO users (username, name, email, password, role, is_active) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
['admin', 'Super Admin', 'admin@workallocate.com', adminPassword, 'SuperAdmin', true]
|
||||
);
|
||||
console.log(' ✅ SuperAdmin created');
|
||||
}
|
||||
|
||||
// 4. Seed Sample Supervisors
|
||||
console.log('👥 Seeding sample supervisors...');
|
||||
const [tudkiDept] = await connection.query('SELECT id FROM departments WHERE name = ?', ['Tudki']);
|
||||
const [danaDept] = await connection.query('SELECT id FROM departments WHERE name = ?', ['Dana']);
|
||||
|
||||
const supervisorPassword = await bcrypt.hash('supervisor123', 10);
|
||||
|
||||
const supervisors = [
|
||||
{ username: 'supervisor_tudki', name: 'Tudki Supervisor', email: 'supervisor.tudki@workallocate.com', deptId: tudkiDept[0]?.id },
|
||||
{ username: 'supervisor_dana', name: 'Dana Supervisor', email: 'supervisor.dana@workallocate.com', deptId: danaDept[0]?.id },
|
||||
{ username: 'supervisor_groundnut', name: 'Groundnut Supervisor', email: 'supervisor.groundnut@workallocate.com', deptId: groundnutId }
|
||||
];
|
||||
|
||||
for (const sup of supervisors) {
|
||||
if (sup.deptId) {
|
||||
const [existing] = await connection.query('SELECT id FROM users WHERE username = ?', [sup.username]);
|
||||
if (existing.length === 0) {
|
||||
await connection.query(
|
||||
'INSERT INTO users (username, name, email, password, role, department_id, is_active) VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
[sup.username, sup.name, sup.email, supervisorPassword, 'Supervisor', sup.deptId, true]
|
||||
);
|
||||
console.log(` ✅ ${sup.name} created`);
|
||||
} else {
|
||||
console.log(` ℹ️ ${sup.name} already exists`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Seed Sample Contractors
|
||||
console.log('🏗️ Seeding sample contractors...');
|
||||
const contractorPassword = await bcrypt.hash('contractor123', 10);
|
||||
|
||||
const contractors = [
|
||||
{ username: 'contractor1', name: 'Contractor One', email: 'contractor1@workallocate.com', deptId: groundnutId },
|
||||
{ username: 'contractor2', name: 'Contractor Two', email: 'contractor2@workallocate.com', deptId: groundnutId }
|
||||
];
|
||||
|
||||
for (const con of contractors) {
|
||||
const [existing] = await connection.query('SELECT id FROM users WHERE username = ?', [con.username]);
|
||||
if (existing.length === 0) {
|
||||
await connection.query(
|
||||
'INSERT INTO users (username, name, email, password, role, department_id, is_active) VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
[con.username, con.name, con.email, contractorPassword, 'Contractor', con.deptId, true]
|
||||
);
|
||||
console.log(` ✅ ${con.name} created`);
|
||||
} else {
|
||||
console.log(` ℹ️ ${con.name} already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Seed Sample Employees
|
||||
console.log('👷 Seeding sample employees...');
|
||||
const [contractor1] = await connection.query('SELECT id FROM users WHERE username = ?', ['contractor1']);
|
||||
const employeePassword = await bcrypt.hash('employee123', 10);
|
||||
|
||||
if (contractor1.length > 0) {
|
||||
const employees = [
|
||||
{ username: 'employee1', name: 'Employee One', email: 'employee1@workallocate.com' },
|
||||
{ username: 'employee2', name: 'Employee Two', email: 'employee2@workallocate.com' },
|
||||
{ username: 'employee3', name: 'Employee Three', email: 'employee3@workallocate.com' }
|
||||
];
|
||||
|
||||
for (const emp of employees) {
|
||||
const [existing] = await connection.query('SELECT id FROM users WHERE username = ?', [emp.username]);
|
||||
if (existing.length === 0) {
|
||||
await connection.query(
|
||||
'INSERT INTO users (username, name, email, password, role, department_id, contractor_id, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
[emp.username, emp.name, emp.email, employeePassword, 'Employee', groundnutId, contractor1[0].id, true]
|
||||
);
|
||||
console.log(` ✅ ${emp.name} created`);
|
||||
} else {
|
||||
console.log(` ℹ️ ${emp.name} already exists`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Seed Contractor Rates
|
||||
console.log('💰 Seeding contractor rates...');
|
||||
if (contractor1.length > 0) {
|
||||
const [existingRate] = await connection.query(
|
||||
'SELECT id FROM contractor_rates WHERE contractor_id = ?',
|
||||
[contractor1[0].id]
|
||||
);
|
||||
|
||||
if (existingRate.length === 0) {
|
||||
await connection.query(
|
||||
'INSERT INTO contractor_rates (contractor_id, rate, effective_date) VALUES (?, ?, CURDATE())',
|
||||
[contractor1[0].id, 500.00]
|
||||
);
|
||||
console.log(' ✅ Contractor rates created');
|
||||
} else {
|
||||
console.log(' ℹ️ Contractor rates already exist');
|
||||
}
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||||
console.log('✅ Database seeding completed successfully!');
|
||||
console.log('');
|
||||
console.log('🔑 Default Login Credentials:');
|
||||
console.log('');
|
||||
console.log(' SuperAdmin:');
|
||||
console.log(' Username: admin');
|
||||
console.log(' Password: admin123');
|
||||
console.log('');
|
||||
console.log(' Supervisor (Groundnut):');
|
||||
console.log(' Username: supervisor_groundnut');
|
||||
console.log(' Password: supervisor123');
|
||||
console.log('');
|
||||
console.log(' Contractor:');
|
||||
console.log(' Username: contractor1');
|
||||
console.log(' Password: contractor123');
|
||||
console.log('');
|
||||
console.log(' Employee:');
|
||||
console.log(' Username: employee1');
|
||||
console.log(' Password: employee123');
|
||||
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||||
console.log('');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error seeding database:', error.message);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seedDatabase();
|
||||
135
backend/database/init-schema.sql
Normal file
135
backend/database/init-schema.sql
Normal file
@@ -0,0 +1,135 @@
|
||||
-- Work Allocation System Database Schema
|
||||
-- This version is for Docker init (database already created by environment variables)
|
||||
|
||||
-- Departments table
|
||||
CREATE TABLE IF NOT EXISTS departments (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(100) NOT NULL UNIQUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Sub-departments table (for Groundnut department)
|
||||
CREATE TABLE IF NOT EXISTS sub_departments (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
department_id INT NOT NULL,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
primary_activity VARCHAR(200) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Users table (for all roles: SuperAdmin, Supervisor, Contractor, Employee)
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
username VARCHAR(100) NOT NULL UNIQUE,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
email VARCHAR(200) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role ENUM('SuperAdmin', 'Supervisor', 'Contractor', 'Employee') NOT NULL,
|
||||
department_id INT,
|
||||
contractor_id INT,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (contractor_id) REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Contractor rates table (rates per contractor + sub-department combination)
|
||||
CREATE TABLE IF NOT EXISTS contractor_rates (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
contractor_id INT NOT NULL,
|
||||
sub_department_id INT,
|
||||
activity VARCHAR(200),
|
||||
rate DECIMAL(10, 2) NOT NULL,
|
||||
effective_date DATE NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (contractor_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (sub_department_id) REFERENCES sub_departments(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Work allocations table
|
||||
CREATE TABLE IF NOT EXISTS work_allocations (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
employee_id INT NOT NULL,
|
||||
supervisor_id INT NOT NULL,
|
||||
contractor_id INT NOT NULL,
|
||||
sub_department_id INT,
|
||||
activity VARCHAR(100),
|
||||
description TEXT,
|
||||
assigned_date DATE NOT NULL,
|
||||
status ENUM('Pending', 'InProgress', 'Completed', 'Cancelled') DEFAULT 'Pending',
|
||||
completion_date DATE,
|
||||
rate DECIMAL(10, 2),
|
||||
units DECIMAL(10, 2),
|
||||
total_amount DECIMAL(10, 2),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (employee_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supervisor_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (contractor_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (sub_department_id) REFERENCES sub_departments(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Attendance table
|
||||
CREATE TABLE IF NOT EXISTS attendance (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
employee_id INT NOT NULL,
|
||||
supervisor_id INT NOT NULL,
|
||||
check_in_time DATETIME NOT NULL,
|
||||
check_out_time DATETIME,
|
||||
work_date DATE NOT NULL,
|
||||
status ENUM('CheckedIn', 'CheckedOut') DEFAULT 'CheckedIn',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (employee_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supervisor_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Insert default departments
|
||||
INSERT IGNORE INTO departments (name) VALUES
|
||||
('Tudki'),
|
||||
('Dana'),
|
||||
('Groundnut');
|
||||
|
||||
-- Insert Groundnut sub-departments
|
||||
INSERT IGNORE INTO sub_departments (department_id, name, primary_activity)
|
||||
SELECT id, 'Mufali Aavak Katai', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Mufali Aavak Dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Dhang Se Katai', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Guthli Bori Silai Dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Guthali dada Pala Tulai Silai Dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Mufali Patthar Bori silai dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Mufali Patthar Bori Utrai', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Bardana Bandal Loading Unloading', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Bardana Gatthi Loading', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Black Dana Loading/Unloading', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Pre Cleaning', 'Pre Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Destoner', 'Destoner' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Water', 'Water' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Decordicater', 'Decordicater & Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Round Chalna', 'Round Chalna & Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Cleaning', 'Decordicater & Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Round Chalna No.1', 'Round Chalna No.1' FROM departments WHERE name = 'Groundnut';
|
||||
|
||||
-- Note: Admin user will be created by running: npm run seed
|
||||
-- This ensures the password is properly hashed with bcrypt
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Migration: Add activity, units, and total_amount columns to work_allocations table
|
||||
-- Run this if you have an existing database without these columns
|
||||
|
||||
ALTER TABLE work_allocations
|
||||
ADD COLUMN IF NOT EXISTS activity VARCHAR(100) AFTER sub_department_id;
|
||||
|
||||
ALTER TABLE work_allocations
|
||||
ADD COLUMN IF NOT EXISTS units DECIMAL(10, 2) AFTER rate;
|
||||
|
||||
ALTER TABLE work_allocations
|
||||
ADD COLUMN IF NOT EXISTS total_amount DECIMAL(10, 2) AFTER units;
|
||||
13
backend/database/migrations/add_contractor_rates_columns.sql
Normal file
13
backend/database/migrations/add_contractor_rates_columns.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- Migration: Add sub_department_id and activity columns to contractor_rates table
|
||||
-- Run this if you have an existing database
|
||||
|
||||
-- Add sub_department_id column if it doesn't exist
|
||||
ALTER TABLE contractor_rates
|
||||
ADD COLUMN IF NOT EXISTS sub_department_id INT NULL,
|
||||
ADD COLUMN IF NOT EXISTS activity VARCHAR(200) NULL;
|
||||
|
||||
-- Add foreign key constraint for sub_department_id
|
||||
-- Note: This may fail if the constraint already exists
|
||||
ALTER TABLE contractor_rates
|
||||
ADD CONSTRAINT fk_contractor_rates_sub_department
|
||||
FOREIGN KEY (sub_department_id) REFERENCES sub_departments(id) ON DELETE SET NULL;
|
||||
134
backend/database/schema.sql
Normal file
134
backend/database/schema.sql
Normal file
@@ -0,0 +1,134 @@
|
||||
-- Work Allocation System Database Schema
|
||||
|
||||
-- Create database
|
||||
CREATE DATABASE IF NOT EXISTS work_allocation;
|
||||
USE work_allocation;
|
||||
|
||||
-- Departments table
|
||||
CREATE TABLE departments (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(100) NOT NULL UNIQUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Sub-departments table (for Groundnut department)
|
||||
CREATE TABLE sub_departments (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
department_id INT NOT NULL,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
primary_activity VARCHAR(200) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Users table (for all roles: SuperAdmin, Supervisor, Contractor, Employee)
|
||||
CREATE TABLE users (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
username VARCHAR(100) NOT NULL UNIQUE,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
email VARCHAR(200) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role ENUM('SuperAdmin', 'Supervisor', 'Contractor', 'Employee') NOT NULL,
|
||||
department_id INT,
|
||||
contractor_id INT,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (contractor_id) REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Contractor rates table
|
||||
CREATE TABLE contractor_rates (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
contractor_id INT NOT NULL,
|
||||
rate DECIMAL(10, 2) NOT NULL,
|
||||
effective_date DATE NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (contractor_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Work allocations table
|
||||
CREATE TABLE work_allocations (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
employee_id INT NOT NULL,
|
||||
supervisor_id INT NOT NULL,
|
||||
contractor_id INT NOT NULL,
|
||||
sub_department_id INT,
|
||||
description TEXT,
|
||||
assigned_date DATE NOT NULL,
|
||||
status ENUM('Pending', 'InProgress', 'Completed', 'Cancelled') DEFAULT 'Pending',
|
||||
completion_date DATE,
|
||||
rate DECIMAL(10, 2),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (employee_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supervisor_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (contractor_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (sub_department_id) REFERENCES sub_departments(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Attendance table
|
||||
CREATE TABLE attendance (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
employee_id INT NOT NULL,
|
||||
supervisor_id INT NOT NULL,
|
||||
check_in_time DATETIME NOT NULL,
|
||||
check_out_time DATETIME,
|
||||
work_date DATE NOT NULL,
|
||||
status ENUM('CheckedIn', 'CheckedOut') DEFAULT 'CheckedIn',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (employee_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supervisor_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Insert default departments
|
||||
INSERT INTO departments (name) VALUES
|
||||
('Tudki'),
|
||||
('Dana'),
|
||||
('Groundnut');
|
||||
|
||||
-- Insert Groundnut sub-departments
|
||||
INSERT INTO sub_departments (department_id, name, primary_activity)
|
||||
SELECT id, 'Mufali Aavak Katai', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Mufali Aavak Dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Dhang Se Katai', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Guthli Bori Silai Dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Guthali dada Pala Tulai Silai Dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Mufali Patthar Bori silai dhang', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Mufali Patthar Bori Utrai', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Bardana Bandal Loading Unloading', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Bardana Gatthi Loading', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Black Dana Loading/Unloading', 'Loading/Unloading' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Pre Cleaning', 'Pre Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Destoner', 'Destoner' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Water', 'Water' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Decordicater', 'Decordicater & Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Round Chalna', 'Round Chalna & Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Cleaning', 'Decordicater & Cleaning' FROM departments WHERE name = 'Groundnut'
|
||||
UNION ALL
|
||||
SELECT id, 'Round Chalna No.1', 'Round Chalna No.1' FROM departments WHERE name = 'Groundnut';
|
||||
|
||||
-- Insert default SuperAdmin (password: admin123)
|
||||
-- Password is hashed using bcrypt: $2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi
|
||||
INSERT INTO users (username, name, email, password, role) VALUES
|
||||
('admin', 'Super Admin', 'admin@workallocate.com', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'SuperAdmin');
|
||||
72
backend/database/seed-admin.js
Normal file
72
backend/database/seed-admin.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import bcrypt from 'bcryptjs';
|
||||
import mysql from 'mysql2/promise';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
async function seedAdmin() {
|
||||
let connection;
|
||||
|
||||
try {
|
||||
// Connect to database (use root for seeding)
|
||||
connection = await mysql.createConnection({
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
user: 'root',
|
||||
password: 'rootpassword',
|
||||
database: process.env.DB_NAME || 'work_allocation',
|
||||
port: process.env.DB_PORT || 3306
|
||||
});
|
||||
|
||||
console.log('✅ Connected to database');
|
||||
|
||||
// Check if admin already exists
|
||||
const [existingUsers] = await connection.query(
|
||||
'SELECT id FROM users WHERE username = ?',
|
||||
['admin']
|
||||
);
|
||||
|
||||
if (existingUsers.length > 0) {
|
||||
console.log('ℹ️ Admin user already exists, updating password...');
|
||||
|
||||
// Generate new password hash
|
||||
const passwordHash = await bcrypt.hash('admin123', 10);
|
||||
|
||||
// Update existing admin user
|
||||
await connection.query(
|
||||
'UPDATE users SET password = ? WHERE username = ?',
|
||||
[passwordHash, 'admin']
|
||||
);
|
||||
|
||||
console.log('✅ Admin password updated successfully');
|
||||
} else {
|
||||
console.log('📝 Creating admin user...');
|
||||
|
||||
// Generate password hash
|
||||
const passwordHash = await bcrypt.hash('admin123', 10);
|
||||
|
||||
// Insert admin user
|
||||
await connection.query(
|
||||
'INSERT INTO users (username, name, email, password, role) VALUES (?, ?, ?, ?, ?)',
|
||||
['admin', 'Super Admin', 'admin@workallocate.com', passwordHash, 'SuperAdmin']
|
||||
);
|
||||
|
||||
console.log('✅ Admin user created successfully');
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('🔑 Default Login Credentials:');
|
||||
console.log(' Username: admin');
|
||||
console.log(' Password: admin123');
|
||||
console.log('');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error seeding admin user:', error.message);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (connection) {
|
||||
await connection.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seedAdmin();
|
||||
Reference in New Issue
Block a user