(Feat): Initial Commit
This commit is contained in:
198
backend/routes/contractor-rates.js
Normal file
198
backend/routes/contractor-rates.js
Normal file
@@ -0,0 +1,198 @@
|
||||
import express from 'express';
|
||||
import db from '../config/database.js';
|
||||
import { authenticateToken, authorize } from '../middleware/auth.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Get contractor rates
|
||||
router.get('/', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const { contractorId, subDepartmentId } = req.query;
|
||||
|
||||
let query = `
|
||||
SELECT cr.*,
|
||||
u.name as contractor_name, u.username as contractor_username,
|
||||
sd.name as sub_department_name,
|
||||
d.name as department_name
|
||||
FROM contractor_rates cr
|
||||
JOIN users u ON cr.contractor_id = u.id
|
||||
LEFT JOIN sub_departments sd ON cr.sub_department_id = sd.id
|
||||
LEFT JOIN departments d ON sd.department_id = d.id
|
||||
WHERE 1=1
|
||||
`;
|
||||
const params = [];
|
||||
|
||||
if (contractorId) {
|
||||
query += ' AND cr.contractor_id = ?';
|
||||
params.push(contractorId);
|
||||
}
|
||||
|
||||
if (subDepartmentId) {
|
||||
query += ' AND cr.sub_department_id = ?';
|
||||
params.push(subDepartmentId);
|
||||
}
|
||||
|
||||
query += ' ORDER BY cr.effective_date DESC, cr.created_at DESC';
|
||||
|
||||
const [rates] = await db.query(query, params);
|
||||
res.json(rates);
|
||||
} catch (error) {
|
||||
console.error('Get contractor rates error:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// Get current rate for a contractor + sub-department combination
|
||||
router.get('/contractor/:contractorId/current', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const { subDepartmentId } = req.query;
|
||||
|
||||
let query = `
|
||||
SELECT cr.*,
|
||||
u.name as contractor_name, u.username as contractor_username,
|
||||
sd.name as sub_department_name
|
||||
FROM contractor_rates cr
|
||||
JOIN users u ON cr.contractor_id = u.id
|
||||
LEFT JOIN sub_departments sd ON cr.sub_department_id = sd.id
|
||||
WHERE cr.contractor_id = ?
|
||||
`;
|
||||
const params = [req.params.contractorId];
|
||||
|
||||
if (subDepartmentId) {
|
||||
query += ' AND cr.sub_department_id = ?';
|
||||
params.push(subDepartmentId);
|
||||
}
|
||||
|
||||
query += ' ORDER BY cr.effective_date DESC LIMIT 1';
|
||||
|
||||
const [rates] = await db.query(query, params);
|
||||
|
||||
if (rates.length === 0) {
|
||||
return res.status(404).json({ error: 'No rate found for contractor' });
|
||||
}
|
||||
|
||||
res.json(rates[0]);
|
||||
} catch (error) {
|
||||
console.error('Get current rate error:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// Set contractor rate (Supervisor or SuperAdmin)
|
||||
router.post('/', authenticateToken, authorize('Supervisor', 'SuperAdmin'), async (req, res) => {
|
||||
try {
|
||||
const { contractorId, subDepartmentId, activity, rate, effectiveDate } = req.body;
|
||||
|
||||
if (!contractorId || !rate || !effectiveDate) {
|
||||
return res.status(400).json({ error: 'Missing required fields (contractorId, rate, effectiveDate)' });
|
||||
}
|
||||
|
||||
// Verify contractor exists
|
||||
const [contractors] = await db.query(
|
||||
'SELECT * FROM users WHERE id = ? AND role = ?',
|
||||
[contractorId, 'Contractor']
|
||||
);
|
||||
|
||||
if (contractors.length === 0) {
|
||||
return res.status(404).json({ error: 'Contractor not found' });
|
||||
}
|
||||
|
||||
// Supervisors can only set rates for contractors in their department
|
||||
if (req.user.role === 'Supervisor' && contractors[0].department_id !== req.user.departmentId) {
|
||||
return res.status(403).json({ error: 'Contractor not in your department' });
|
||||
}
|
||||
|
||||
const [result] = await db.query(
|
||||
'INSERT INTO contractor_rates (contractor_id, sub_department_id, activity, rate, effective_date) VALUES (?, ?, ?, ?, ?)',
|
||||
[contractorId, subDepartmentId || null, activity || null, rate, effectiveDate]
|
||||
);
|
||||
|
||||
const [newRate] = await db.query(
|
||||
`SELECT cr.*,
|
||||
u.name as contractor_name, u.username as contractor_username,
|
||||
sd.name as sub_department_name
|
||||
FROM contractor_rates cr
|
||||
JOIN users u ON cr.contractor_id = u.id
|
||||
LEFT JOIN sub_departments sd ON cr.sub_department_id = sd.id
|
||||
WHERE cr.id = ?`,
|
||||
[result.insertId]
|
||||
);
|
||||
|
||||
res.status(201).json(newRate[0]);
|
||||
} catch (error) {
|
||||
console.error('Set contractor rate error:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// Update contractor rate
|
||||
router.put('/:id', authenticateToken, authorize('Supervisor', 'SuperAdmin'), async (req, res) => {
|
||||
try {
|
||||
const { rate, activity, effectiveDate } = req.body;
|
||||
|
||||
const [existing] = await db.query('SELECT * FROM contractor_rates WHERE id = ?', [req.params.id]);
|
||||
|
||||
if (existing.length === 0) {
|
||||
return res.status(404).json({ error: 'Rate not found' });
|
||||
}
|
||||
|
||||
const updates = [];
|
||||
const params = [];
|
||||
|
||||
if (rate !== undefined) {
|
||||
updates.push('rate = ?');
|
||||
params.push(rate);
|
||||
}
|
||||
if (activity !== undefined) {
|
||||
updates.push('activity = ?');
|
||||
params.push(activity);
|
||||
}
|
||||
if (effectiveDate !== undefined) {
|
||||
updates.push('effective_date = ?');
|
||||
params.push(effectiveDate);
|
||||
}
|
||||
|
||||
if (updates.length === 0) {
|
||||
return res.status(400).json({ error: 'No fields to update' });
|
||||
}
|
||||
|
||||
params.push(req.params.id);
|
||||
|
||||
await db.query(`UPDATE contractor_rates SET ${updates.join(', ')} WHERE id = ?`, params);
|
||||
|
||||
const [updatedRate] = await db.query(
|
||||
`SELECT cr.*,
|
||||
u.name as contractor_name, u.username as contractor_username,
|
||||
sd.name as sub_department_name
|
||||
FROM contractor_rates cr
|
||||
JOIN users u ON cr.contractor_id = u.id
|
||||
LEFT JOIN sub_departments sd ON cr.sub_department_id = sd.id
|
||||
WHERE cr.id = ?`,
|
||||
[req.params.id]
|
||||
);
|
||||
|
||||
res.json(updatedRate[0]);
|
||||
} catch (error) {
|
||||
console.error('Update contractor rate error:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// Delete contractor rate
|
||||
router.delete('/:id', authenticateToken, authorize('Supervisor', 'SuperAdmin'), async (req, res) => {
|
||||
try {
|
||||
const [existing] = await db.query('SELECT * FROM contractor_rates WHERE id = ?', [req.params.id]);
|
||||
|
||||
if (existing.length === 0) {
|
||||
return res.status(404).json({ error: 'Rate not found' });
|
||||
}
|
||||
|
||||
await db.query('DELETE FROM contractor_rates WHERE id = ?', [req.params.id]);
|
||||
res.json({ message: 'Rate deleted successfully' });
|
||||
} catch (error) {
|
||||
console.error('Delete contractor rate error:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user