TASK
This commit is contained in:
parent
96c46a8726
commit
b8e525e774
5
app.js
5
app.js
@ -188,7 +188,7 @@ import leave from "./resources/Leaves/LeaveRoute.js";
|
|||||||
import notification from "./resources/Notification/notificationRoute.js"
|
import notification from "./resources/Notification/notificationRoute.js"
|
||||||
//Inventory
|
//Inventory
|
||||||
import InventoryRoute from "./resources/Inventory/InventoryRoute.js";
|
import InventoryRoute from "./resources/Inventory/InventoryRoute.js";
|
||||||
|
import TaskRoute from "./resources/Task/TaskRoute.js";
|
||||||
app.use("/api/v1", user);
|
app.use("/api/v1", user);
|
||||||
|
|
||||||
//Product
|
//Product
|
||||||
@ -259,6 +259,9 @@ app.use("/api",notification)
|
|||||||
//Inventory
|
//Inventory
|
||||||
app.use("/api/inventory", InventoryRoute);
|
app.use("/api/inventory", InventoryRoute);
|
||||||
|
|
||||||
|
//Task
|
||||||
|
app.use("/api/task", TaskRoute);
|
||||||
|
|
||||||
//config specialty
|
//config specialty
|
||||||
// app.use("/api/config/specialty", SpecialtiesRouter);
|
// app.use("/api/config/specialty", SpecialtiesRouter);
|
||||||
//specialties
|
//specialties
|
||||||
|
@ -7,7 +7,8 @@ import password from "secure-random-password";
|
|||||||
import catchAsyncErrors from "../../middlewares/catchAsyncErrors.js";
|
import catchAsyncErrors from "../../middlewares/catchAsyncErrors.js";
|
||||||
|
|
||||||
export const register = async (req, res) => {
|
export const register = async (req, res) => {
|
||||||
let { name, email, countryCode, mobileNumber } = req.body;
|
let { name, email, countryCode, mobileNumber,territoryManager } = req.body;
|
||||||
|
// console.log(req.body);
|
||||||
countryCode = countryCode?.trim();
|
countryCode = countryCode?.trim();
|
||||||
mobileNumber = mobileNumber?.trim();
|
mobileNumber = mobileNumber?.trim();
|
||||||
const fullMobileNumber = `${countryCode}${mobileNumber}`;
|
const fullMobileNumber = `${countryCode}${mobileNumber}`;
|
||||||
@ -30,6 +31,7 @@ export const register = async (req, res) => {
|
|||||||
if (salesCoordinator) {
|
if (salesCoordinator) {
|
||||||
salesCoordinator.otp = otp;
|
salesCoordinator.otp = otp;
|
||||||
salesCoordinator.otpExpires = otpExpires;
|
salesCoordinator.otpExpires = otpExpires;
|
||||||
|
salesCoordinator.mappedby = territoryManager;
|
||||||
} else {
|
} else {
|
||||||
salesCoordinator = new SalesCoOrdinator({
|
salesCoordinator = new SalesCoOrdinator({
|
||||||
name,
|
name,
|
||||||
@ -37,6 +39,7 @@ export const register = async (req, res) => {
|
|||||||
mobileNumber: fullMobileNumber,
|
mobileNumber: fullMobileNumber,
|
||||||
otp,
|
otp,
|
||||||
otpExpires,
|
otpExpires,
|
||||||
|
mappedby: territoryManager,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Generate uniqueId if not already present
|
// Generate uniqueId if not already present
|
||||||
|
@ -51,6 +51,11 @@ const salescoordinatorSchema = new mongoose.Schema(
|
|||||||
type: String,
|
type: String,
|
||||||
unique: true,
|
unique: true,
|
||||||
},
|
},
|
||||||
|
mappedby: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "TerritoryManager",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
logout,
|
logout,
|
||||||
} from "./SalesCoOrdinatorController.js";
|
} from "./SalesCoOrdinatorController.js";
|
||||||
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
|
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
|
||||||
|
import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js";
|
||||||
import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js";
|
import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js";
|
||||||
|
|
||||||
router.post("/register", register);
|
router.post("/register", register);
|
||||||
@ -31,6 +32,11 @@ router.get(
|
|||||||
authorizeRoles("admin"),
|
authorizeRoles("admin"),
|
||||||
getAllSalesCoOrdinator
|
getAllSalesCoOrdinator
|
||||||
);
|
);
|
||||||
|
router.get(
|
||||||
|
"/getAll-TM",
|
||||||
|
isAuthenticatedTerritoryManager,
|
||||||
|
getAllSalesCoOrdinator
|
||||||
|
);
|
||||||
router.get(
|
router.get(
|
||||||
"/getOne/:id",
|
"/getOne/:id",
|
||||||
isAuthenticatedUser,
|
isAuthenticatedUser,
|
||||||
|
92
resources/Task/TaskController.js
Normal file
92
resources/Task/TaskController.js
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import Task from "./TaskModel.js";
|
||||||
|
import SalesCoOrdinator from "../SalesCoOrdinators/SalesCoOrdinatorModel.js";
|
||||||
|
import crypto from "crypto";
|
||||||
|
|
||||||
|
export const assignTask = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
task,
|
||||||
|
note,
|
||||||
|
taskPriority,
|
||||||
|
taskDueDate,
|
||||||
|
taskAssignedTo,
|
||||||
|
addedFor,
|
||||||
|
addedForId,
|
||||||
|
} = req.body;
|
||||||
|
// console.log(req.body);
|
||||||
|
const currentYear = new Date().getFullYear().toString().slice(-2);
|
||||||
|
const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase();
|
||||||
|
const uniqueId = `${currentYear}-${randomChars}`;
|
||||||
|
// Create a new task
|
||||||
|
const newTask = await Task.create({
|
||||||
|
taskId: uniqueId,
|
||||||
|
task,
|
||||||
|
note,
|
||||||
|
taskStatus: "Pending",
|
||||||
|
taskPriority,
|
||||||
|
taskDueDate,
|
||||||
|
taskAssignedTo,
|
||||||
|
taskAssignedBy: req.user._id, // The Territory Manager's ID
|
||||||
|
addedFor,
|
||||||
|
addedForId,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
success: true,
|
||||||
|
message: "Task assigned successfully",
|
||||||
|
task: newTask,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTasksForSalesCoordinator = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const tasks = await Task.find({ taskAssignedTo: req.user._id });
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
tasks,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateTaskStatus = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { taskId } = req.params;
|
||||||
|
|
||||||
|
// Find the task to ensure it belongs to the logged-in Sales Coordinator
|
||||||
|
const task = await Task.findOne({ _id: taskId, taskAssignedTo: req.user._id });
|
||||||
|
|
||||||
|
if (!task) {
|
||||||
|
return res.status(404).json({
|
||||||
|
success: false,
|
||||||
|
message: "Task not found or you're not authorized to update this task.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the task status to "Completed"
|
||||||
|
task.taskStatus = "Completed";
|
||||||
|
await task.save();
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "Task status updated to Completed.",
|
||||||
|
task,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
68
resources/Task/TaskModel.js
Normal file
68
resources/Task/TaskModel.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import dotenv from "dotenv";
|
||||||
|
dotenv.config();
|
||||||
|
import mongoose from "mongoose";
|
||||||
|
|
||||||
|
const TaskSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
taskId: {
|
||||||
|
type: String,
|
||||||
|
unique: true,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
task: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: ["Visit Retailers", "Update Sales Data", "Update Inventory Data", "Collect KYC"], // Restrict to specific tasks
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
type: String,
|
||||||
|
required: function () {
|
||||||
|
return this.task === "Collect KYC";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
taskStatus: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: ["Pending", "In Progress", "Completed"],
|
||||||
|
},
|
||||||
|
taskPriority: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: ["Low", "Medium", "High"],
|
||||||
|
},
|
||||||
|
taskDueDate: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
match: /^\d{2}\/\d{2}\/\d{4}$/,
|
||||||
|
},
|
||||||
|
taskAssignedTo: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "SalesCoOrdinator",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
taskAssignedBy: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "TerritoryManager",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
addedFor: {
|
||||||
|
type: String,
|
||||||
|
enum: ['PrincipalDistributor', 'RetailDistributor'],
|
||||||
|
required: function () {
|
||||||
|
return this.task === "Update Inventory Data";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
addedForId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
refPath: 'addedFor',
|
||||||
|
required: function () {
|
||||||
|
return this.task === "Update Inventory Data";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Task = mongoose.model("Task", TaskSchema);
|
||||||
|
|
||||||
|
export default Task;
|
32
resources/Task/TaskRoute.js
Normal file
32
resources/Task/TaskRoute.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import express from "express";
|
||||||
|
import {
|
||||||
|
assignTask,
|
||||||
|
getTasksForSalesCoordinator,
|
||||||
|
updateTaskStatus,
|
||||||
|
} from "./TaskController.js";
|
||||||
|
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
|
||||||
|
import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Route for Territory Manager to assign a task
|
||||||
|
router.post(
|
||||||
|
"/assign-task",
|
||||||
|
isAuthenticatedTerritoryManager,
|
||||||
|
assignTask
|
||||||
|
);
|
||||||
|
|
||||||
|
// Route for Sales Coordinator to view their tasks
|
||||||
|
router.get(
|
||||||
|
"/tasks",
|
||||||
|
isAuthenticatedSalesCoOrdinator,
|
||||||
|
getTasksForSalesCoordinator
|
||||||
|
);
|
||||||
|
|
||||||
|
router.put(
|
||||||
|
"/update-task-status/:taskId",
|
||||||
|
isAuthenticatedSalesCoOrdinator,
|
||||||
|
updateTaskStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
export default router;
|
Loading…
Reference in New Issue
Block a user