239 lines
6.7 KiB
JavaScript
239 lines
6.7 KiB
JavaScript
const { RelocationRequest, Outlet, User, Worknote } = require('../models');
|
|
const { Op } = require('sequelize');
|
|
const { v4: uuidv4 } = require('uuid');
|
|
|
|
exports.submitRequest = async (req, res) => {
|
|
try {
|
|
const {
|
|
outletId, relocationType, currentAddress, currentCity, currentState,
|
|
currentLatitude, currentLongitude, proposedAddress, proposedCity,
|
|
proposedState, proposedLatitude, proposedLongitude, reason, proposedDate
|
|
} = req.body;
|
|
|
|
const requestId = `REL-${Date.now()}-${uuidv4().substring(0, 4).toUpperCase()}`;
|
|
|
|
const request = await RelocationRequest.create({
|
|
requestId,
|
|
outletId,
|
|
dealerId: req.user.id,
|
|
relocationType,
|
|
currentAddress,
|
|
currentCity,
|
|
currentState,
|
|
currentLatitude,
|
|
currentLongitude,
|
|
proposedAddress,
|
|
proposedCity,
|
|
proposedState,
|
|
proposedLatitude,
|
|
proposedLongitude,
|
|
reason,
|
|
proposedDate,
|
|
currentStage: 'RBM Review',
|
|
status: 'Pending',
|
|
progressPercentage: 0,
|
|
timeline: [{
|
|
stage: 'Submitted',
|
|
timestamp: new Date(),
|
|
user: req.user.full_name, // Assuming req.user.full_name is available
|
|
action: 'Request submitted'
|
|
}]
|
|
});
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: 'Relocation request submitted successfully',
|
|
requestId: request.requestId
|
|
});
|
|
} catch (error) {
|
|
console.error('Submit relocation error:', error);
|
|
res.status(500).json({ success: false, message: 'Error submitting request' });
|
|
}
|
|
};
|
|
|
|
exports.getRequests = async (req, res) => {
|
|
try {
|
|
const where = {};
|
|
if (req.user.role === 'Dealer') {
|
|
where.dealerId = req.user.id;
|
|
}
|
|
|
|
const requests = await RelocationRequest.findAll({
|
|
where,
|
|
include: [
|
|
{
|
|
model: Outlet,
|
|
as: 'outlet',
|
|
attributes: ['code', 'name']
|
|
},
|
|
{
|
|
model: User,
|
|
as: 'dealer',
|
|
attributes: ['full_name'] // Changed 'name' to 'full_name' based on original query
|
|
}
|
|
],
|
|
order: [['createdAt', 'DESC']]
|
|
});
|
|
|
|
res.json({ success: true, requests });
|
|
} catch (error) {
|
|
console.error('Get relocation requests error:', error);
|
|
res.status(500).json({ success: false, message: 'Error fetching requests' });
|
|
}
|
|
};
|
|
|
|
exports.getRequestById = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
|
|
const request = await RelocationRequest.findOne({
|
|
where: {
|
|
[Op.or]: [
|
|
{ id },
|
|
{ requestId: id }
|
|
]
|
|
},
|
|
include: [
|
|
{
|
|
model: Outlet,
|
|
as: 'outlet'
|
|
},
|
|
{
|
|
model: User,
|
|
as: 'dealer',
|
|
attributes: ['full_name', 'email'] // Changed 'name' to 'full_name'
|
|
},
|
|
{
|
|
model: Worknote,
|
|
as: 'worknotes', // Assuming Worknote model is for workflow/comments
|
|
include: [{
|
|
model: User,
|
|
as: 'actionedBy', // Assuming Worknote has an association to User for actioned_by
|
|
attributes: ['full_name']
|
|
}],
|
|
order: [['createdAt', 'ASC']]
|
|
}
|
|
]
|
|
});
|
|
|
|
if (!request) {
|
|
return res.status(404).json({ success: false, message: 'Request not found' });
|
|
}
|
|
|
|
// Calculate distance between current and proposed location (retained from original)
|
|
if (request.currentLatitude && request.proposedLatitude) {
|
|
const distance = calculateDistance(
|
|
request.currentLatitude, request.currentLongitude,
|
|
request.proposedLatitude, request.proposedLongitude
|
|
);
|
|
request.dataValues.distance = `${distance.toFixed(2)} km`; // Add to dataValues for response
|
|
}
|
|
|
|
res.json({ success: true, request });
|
|
} catch (error) {
|
|
console.error('Get relocation details error:', error);
|
|
res.status(500).json({ success: false, message: 'Error fetching details' });
|
|
}
|
|
};
|
|
|
|
exports.takeAction = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { action, comments } = req.body;
|
|
|
|
const request = await RelocationRequest.findOne({
|
|
where: {
|
|
[Op.or]: [
|
|
{ id },
|
|
{ requestId: id }
|
|
]
|
|
}
|
|
});
|
|
|
|
if (!request) {
|
|
return res.status(404).json({ success: false, message: 'Request not found' });
|
|
}
|
|
|
|
// Update status and current_stage based on action
|
|
let newStatus = request.status;
|
|
let newCurrentStage = request.currentStage;
|
|
|
|
if (action === 'Approved') {
|
|
newStatus = 'Approved';
|
|
// Assuming next stage logic would be here, e.g., 'Final Approval'
|
|
} else if (action === 'Rejected') {
|
|
newStatus = 'Rejected';
|
|
} else if (action === 'Forwarded to RBM') {
|
|
newCurrentStage = 'RBM Review';
|
|
} else if (action === 'Forwarded to ZBM') {
|
|
newCurrentStage = 'ZBM Review';
|
|
} else if (action === 'Forwarded to HO') {
|
|
newCurrentStage = 'HO Review';
|
|
}
|
|
|
|
// Create a worknote entry
|
|
await Worknote.create({
|
|
requestId: request.id,
|
|
stage: newCurrentStage, // Or the specific stage where action was taken
|
|
action: action,
|
|
comments: comments,
|
|
actionedBy: req.user.id,
|
|
actionedAt: new Date()
|
|
});
|
|
|
|
// Update the request status and current stage
|
|
await request.update({
|
|
status: newStatus,
|
|
currentStage: newCurrentStage,
|
|
updatedAt: new Date()
|
|
});
|
|
|
|
res.json({ success: true, message: `Request ${action.toLowerCase()} successfully` });
|
|
} catch (error) {
|
|
console.error('Take action error:', error);
|
|
res.status(500).json({ success: false, message: 'Error processing action' });
|
|
}
|
|
};
|
|
|
|
exports.uploadDocuments = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { documents } = req.body;
|
|
|
|
const request = await RelocationRequest.findOne({
|
|
where: {
|
|
[Op.or]: [
|
|
{ id },
|
|
{ requestId: id }
|
|
]
|
|
}
|
|
});
|
|
|
|
if (!request) {
|
|
return res.status(404).json({ success: false, message: 'Request not found' });
|
|
}
|
|
|
|
await request.update({
|
|
documents: documents,
|
|
updatedAt: new Date()
|
|
});
|
|
|
|
res.json({ success: true, message: 'Documents uploaded successfully' });
|
|
} catch (error) {
|
|
console.error('Upload documents error:', error);
|
|
res.status(500).json({ success: false, message: 'Error uploading documents' });
|
|
}
|
|
};
|
|
|
|
// Helper function to calculate distance between two coordinates
|
|
function calculateDistance(lat1, lon1, lat2, lon2) {
|
|
const R = 6371; // Radius of Earth in km
|
|
const dLat = (lat2 - lat1) * Math.PI / 180;
|
|
const dLon = (lon2 - lon1) * Math.PI / 180;
|
|
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
|
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
return R * c;
|
|
}
|