Skip to content

Commit 747866a

Browse files
author
Janushikha
committed
feat: Refactor employee and branch models, update relationships, and enhance employee retrieval queries
1 parent 72d9ce6 commit 747866a

File tree

6 files changed

+238
-91
lines changed

6 files changed

+238
-91
lines changed

controllers/employeeController.js

Lines changed: 113 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { Employee, Branch, User } = require('../models');
1+
const { Employee, Branch, User, sequelize } = require('../models');
22
const { Op } = require('sequelize');
33

44
// Get all employees with optional filtering
@@ -12,45 +12,54 @@ exports.getAllEmployees = async (req, res) => {
1212
offset = 0
1313
} = req.query;
1414

15-
const whereClause = {};
16-
const userWhereClause = {};
17-
18-
// Filter by branch
15+
// Build WHERE conditions
16+
let whereConditions = [];
17+
let params = {};
18+
1919
if (branch_id) {
20-
whereClause.branch_id = branch_id;
20+
whereConditions.push('e.branch_id = :branch_id');
21+
params.branch_id = branch_id;
2122
}
22-
23-
// Filter by role (role is stored in user_account table)
23+
2424
if (role) {
25-
userWhereClause.role = role;
25+
whereConditions.push('u.role = :role');
26+
params.role = role;
2627
}
27-
28-
// Search by name or email
28+
2929
if (search) {
30-
whereClause[Op.or] = [
31-
{ name: { [Op.iLike]: `%${search}%` } },
32-
{ email: { [Op.iLike]: `%${search}%` } }
33-
];
30+
whereConditions.push('(e.name ILIKE :search OR e.email ILIKE :search)');
31+
params.search = `%${search}%`;
3432
}
35-
36-
const employees = await Employee.findAll({
37-
where: whereClause,
38-
include: [
39-
{
40-
model: Branch,
41-
as: 'Branch',
42-
attributes: ['branch_id', 'branch_name', 'address', 'contact_no']
43-
},
44-
{
45-
model: User,
46-
as: 'User',
47-
attributes: ['id', 'username', 'role'],
48-
where: Object.keys(userWhereClause).length > 0 ? userWhereClause : undefined
49-
}
50-
],
51-
limit: parseInt(limit),
52-
offset: parseInt(offset),
53-
order: [['employee_id', 'ASC']]
33+
34+
const whereClause = whereConditions.length > 0
35+
? 'WHERE ' + whereConditions.join(' AND ')
36+
: '';
37+
38+
// Execute raw SQL query
39+
const [employees] = await sequelize.query(`
40+
SELECT
41+
e.employee_id,
42+
e.user_id,
43+
e.branch_id,
44+
e.name,
45+
e.email,
46+
e.contact_no,
47+
b.branch_name,
48+
b.address as branch_address,
49+
u.username,
50+
u.role
51+
FROM employee e
52+
LEFT JOIN branch b ON e.branch_id = b.branch_id
53+
LEFT JOIN user_account u ON e.user_id = u.user_id
54+
${whereClause}
55+
ORDER BY e.employee_id ASC
56+
LIMIT :limit OFFSET :offset
57+
`, {
58+
replacements: {
59+
...params,
60+
limit: parseInt(limit),
61+
offset: parseInt(offset)
62+
}
5463
});
5564

5665
// Format the response
@@ -61,12 +70,10 @@ exports.getAllEmployees = async (req, res) => {
6170
name: emp.name,
6271
email: emp.email,
6372
contact_no: emp.contact_no,
64-
branch_name: emp.Branch?.branch_name,
65-
branch_address: emp.Branch?.address,
66-
role: emp.User?.role,
67-
username: emp.User?.username,
68-
createdAt: emp.createdAt,
69-
updatedAt: emp.updatedAt
73+
branch_name: emp.branch_name,
74+
branch_address: emp.branch_address,
75+
role: emp.role,
76+
username: emp.username
7077
}));
7178

7279
res.json({
@@ -91,28 +98,35 @@ exports.getEmployeeById = async (req, res) => {
9198
try {
9299
const { id } = req.params;
93100

94-
const employee = await Employee.findByPk(id, {
95-
include: [
96-
{
97-
model: Branch,
98-
as: 'Branch',
99-
attributes: ['branch_id', 'branch_name', 'address', 'contact_no']
100-
},
101-
{
102-
model: User,
103-
as: 'User',
104-
attributes: ['id', 'username', 'role']
105-
}
106-
]
101+
const [employees] = await sequelize.query(`
102+
SELECT
103+
e.employee_id,
104+
e.user_id,
105+
e.branch_id,
106+
e.name,
107+
e.email,
108+
e.contact_no,
109+
b.branch_name,
110+
b.address as branch_address,
111+
u.username,
112+
u.role
113+
FROM employee e
114+
LEFT JOIN branch b ON e.branch_id = b.branch_id
115+
LEFT JOIN user_account u ON e.user_id = u.user_id
116+
WHERE e.employee_id = :id
117+
`, {
118+
replacements: { id }
107119
});
108120

109-
if (!employee) {
121+
if (!employees || employees.length === 0) {
110122
return res.status(404).json({
111123
success: false,
112124
error: 'Employee not found'
113125
});
114126
}
115127

128+
const employee = employees[0];
129+
116130
res.json({
117131
success: true,
118132
data: {
@@ -123,11 +137,9 @@ exports.getEmployeeById = async (req, res) => {
123137
name: employee.name,
124138
email: employee.email,
125139
contact_no: employee.contact_no,
126-
branch_name: employee.Branch?.branch_name,
127-
role: employee.User?.role,
128-
username: employee.User?.username,
129-
createdAt: employee.createdAt,
130-
updatedAt: employee.updatedAt
140+
branch_name: employee.branch_name,
141+
role: employee.role,
142+
username: employee.username
131143
}
132144
}
133145
});
@@ -347,29 +359,56 @@ exports.getEmployeeStats = async (req, res) => {
347359
try {
348360
const { branch_id } = req.query;
349361

350-
const whereClause = branch_id ? { branch_id } : {};
362+
const whereClause = branch_id ? 'WHERE e.branch_id = :branch_id' : '';
363+
364+
const [roleStats] = await sequelize.query(`
365+
SELECT
366+
u.role,
367+
COUNT(*) as count
368+
FROM employee e
369+
LEFT JOIN user_account u ON e.user_id = u.user_id
370+
${whereClause}
371+
GROUP BY u.role
372+
`, {
373+
replacements: branch_id ? { branch_id } : {}
374+
});
351375

352-
const employees = await Employee.findAll({
353-
where: whereClause,
354-
include: [
355-
{
356-
model: User,
357-
as: 'User',
358-
attributes: ['role']
359-
}
360-
]
376+
const [branchStats] = await sequelize.query(`
377+
SELECT
378+
e.branch_id,
379+
b.branch_name,
380+
COUNT(*) as count
381+
FROM employee e
382+
LEFT JOIN branch b ON e.branch_id = b.branch_id
383+
${whereClause}
384+
GROUP BY e.branch_id, b.branch_name
385+
`, {
386+
replacements: branch_id ? { branch_id } : {}
387+
});
388+
389+
const [totalCount] = await sequelize.query(`
390+
SELECT COUNT(*) as total
391+
FROM employee e
392+
${whereClause}
393+
`, {
394+
replacements: branch_id ? { branch_id } : {}
361395
});
362396

363397
const stats = {
364-
total: employees.length,
398+
total: parseInt(totalCount[0]?.total || 0),
365399
byRole: {},
366400
byBranch: {}
367401
};
368402

369-
employees.forEach(emp => {
370-
const role = emp.User?.role || 'Unknown';
371-
stats.byRole[role] = (stats.byRole[role] || 0) + 1;
372-
stats.byBranch[emp.branch_id] = (stats.byBranch[emp.branch_id] || 0) + 1;
403+
roleStats.forEach(stat => {
404+
stats.byRole[stat.role] = parseInt(stat.count);
405+
});
406+
407+
branchStats.forEach(stat => {
408+
stats.byBranch[stat.branch_id] = {
409+
name: stat.branch_name,
410+
count: parseInt(stat.count)
411+
};
373412
});
374413

375414
res.json({

models/branch.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,24 @@ const Branch = sequelize.define('Branch', {
1313
unique: true
1414
},
1515
contact_number: {
16-
type: DataTypes.STRING(20),
17-
allowNull: false
16+
type: DataTypes.STRING(30), // Updated to match schema
17+
allowNull: true // Made nullable to match database
1818
},
1919
address: {
2020
type: DataTypes.TEXT,
21-
allowNull: false
21+
allowNull: true // Made nullable to match database
22+
},
23+
manager_name: {
24+
type: DataTypes.STRING(100),
25+
allowNull: true
26+
},
27+
branch_code: {
28+
type: DataTypes.STRING(10),
29+
allowNull: true
2230
}
2331
}, {
24-
tableName: 'branches',
25-
timestamps: true
32+
tableName: 'branch', // Fixed: Table name is singular in database
33+
timestamps: false // Disable timestamps
2634
});
2735

2836
module.exports = Branch;

models/employee.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ const Employee = sequelize.define('Employee', {
1111
type: DataTypes.INTEGER,
1212
allowNull: false,
1313
references: {
14-
model: 'branches',
14+
model: 'branch', // Fixed table name
1515
key: 'branch_id'
1616
}
1717
},
1818
user_id: {
1919
type: DataTypes.INTEGER,
2020
allowNull: false,
2121
references: {
22-
model: 'users',
23-
key: 'id'
22+
model: 'user_account', // Fixed table name
23+
key: 'user_id' // Fixed key name
2424
}
2525
},
2626
name: {
@@ -29,19 +29,19 @@ const Employee = sequelize.define('Employee', {
2929
},
3030
email: {
3131
type: DataTypes.STRING(100),
32-
allowNull: false,
32+
allowNull: true, // Made nullable to match database
3333
unique: true,
3434
validate: {
3535
isEmail: true
3636
}
3737
},
3838
contact_no: {
3939
type: DataTypes.STRING(20),
40-
allowNull: false
40+
allowNull: true // Made nullable to match database
4141
}
4242
}, {
4343
tableName: 'employee', // Fixed: Table name is singular in database
44-
timestamps: true
44+
timestamps: false // Disable timestamps since the table doesn't have createdAt/updatedAt
4545
});
4646

4747
module.exports = Employee;

models/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ Service.hasMany(ServiceUsage, { foreignKey: 'service_id' });
5353
ServiceUsage.belongsTo(Service, { foreignKey: 'service_id' });
5454

5555
// Branch - Employee Relationships
56-
Branch.hasMany(Employee, { foreignKey: 'branch_id' });
57-
Employee.belongsTo(Branch, { foreignKey: 'branch_id' });
56+
Branch.hasMany(Employee, { foreignKey: 'branch_id', as: 'Employees' });
57+
Employee.belongsTo(Branch, { foreignKey: 'branch_id', as: 'Branch' });
5858

5959
// User - Employee Relationships
60-
User.hasOne(Employee, { foreignKey: 'user_id' });
61-
Employee.belongsTo(User, { foreignKey: 'user_id' });
60+
User.hasOne(Employee, { foreignKey: 'user_id', as: 'Employee' });
61+
Employee.belongsTo(User, { foreignKey: 'user_id', as: 'User', targetKey: 'user_id' });
6262

6363
// Test database connection
6464
const testConnection = async () => {

0 commit comments

Comments
 (0)