task updated and product manual completed
This commit is contained in:
parent
768fc3c77f
commit
059e39e13c
3
app.js
3
app.js
@ -132,6 +132,7 @@ app.use(
|
||||
//auth
|
||||
import user from "./resources/user/userRoute.js";
|
||||
import ProductRouter from "./resources/Products/ProductRoute.js";
|
||||
import ProductManualRouter from "./resources/ProductMannual/ProductManualRoute.js";
|
||||
//Businesses
|
||||
// import BusinessRoute from "./resources/Businesses/BusinessRoute.js";
|
||||
|
||||
@ -199,6 +200,8 @@ app.use("/api/v1", user);
|
||||
|
||||
//Product
|
||||
app.use("/api", ProductRouter);
|
||||
//Product Manual
|
||||
app.use("/api/productmanual", ProductManualRouter);
|
||||
//businesses
|
||||
// app.use("/api/businesses", BusinessRoute);
|
||||
// Design
|
||||
|
Binary file not shown.
181
resources/ProductMannual/ProductManualController.js
Normal file
181
resources/ProductMannual/ProductManualController.js
Normal file
@ -0,0 +1,181 @@
|
||||
import ProductManual from "./ProductManualModel.js";
|
||||
import cloudinary from "../../Utils/cloudinary.js";
|
||||
|
||||
// Create a new product manual
|
||||
export const createProductManual = async (req, res) => {
|
||||
const { title } = req.body;
|
||||
|
||||
try {
|
||||
let productManualDetails;
|
||||
|
||||
// Check if a file is provided
|
||||
if (req.files && req.files.product_manual) {
|
||||
const pdfFile = req.files.product_manual;
|
||||
const result = await cloudinary.v2.uploader.upload(pdfFile.tempFilePath, {
|
||||
folder: "chemiNova/ProductManuals",
|
||||
resource_type: "raw", // For PDF or other non-image files
|
||||
});
|
||||
|
||||
productManualDetails = {
|
||||
public_id: result.public_id,
|
||||
url: result.secure_url,
|
||||
};
|
||||
}
|
||||
|
||||
// Create the product manual
|
||||
const productManual = await ProductManual.create({
|
||||
title,
|
||||
product_manual: productManualDetails,
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
productManual,
|
||||
message: "Product manual created successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating product manual:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Internal server error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Get all product manuals
|
||||
export const getAllProductManuals = async (req, res) => {
|
||||
try {
|
||||
const productManuals = await ProductManual.find();
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
productManuals,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching product manuals:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Internal server error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Get a single product manual by ID
|
||||
export const getSingleProductManual = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
try {
|
||||
const productManual = await ProductManual.findById(id);
|
||||
|
||||
if (!productManual) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "Product manual not found",
|
||||
});
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
productManual,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching product manual:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Internal server error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Update a product manual
|
||||
export const updateProductManual = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { title } = req.body;
|
||||
|
||||
try {
|
||||
const productManual = await ProductManual.findById(id);
|
||||
|
||||
if (!productManual) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "Product manual not found",
|
||||
});
|
||||
}
|
||||
|
||||
// Check if a new file is provided
|
||||
if (req.files && req.files.product_manual) {
|
||||
// Delete the old file from Cloudinary
|
||||
if (productManual.product_manual.public_id) {
|
||||
await cloudinary.v2.uploader.destroy(productManual.product_manual.public_id, {
|
||||
resource_type: "raw",
|
||||
});
|
||||
}
|
||||
|
||||
// Upload the new file to Cloudinary
|
||||
const pdfFile = req.files.product_manual;
|
||||
const result = await cloudinary.v2.uploader.upload(pdfFile.tempFilePath, {
|
||||
folder: "chemiNova/ProductManuals",
|
||||
resource_type: "raw",
|
||||
});
|
||||
|
||||
// Update the product manual details
|
||||
productManual.product_manual = {
|
||||
public_id: result.public_id,
|
||||
url: result.secure_url,
|
||||
};
|
||||
}
|
||||
|
||||
// Update the title
|
||||
productManual.title = title || productManual.title;
|
||||
|
||||
await productManual.save();
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
productManual,
|
||||
message: "Product manual updated successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error updating product manual:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Internal server error",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Delete a product manual
|
||||
export const deleteProductManual = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
try {
|
||||
const productManual = await ProductManual.findById(id);
|
||||
|
||||
if (!productManual) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "Product manual not found",
|
||||
});
|
||||
}
|
||||
|
||||
// Delete the file from Cloudinary
|
||||
if (productManual.product_manual.public_id) {
|
||||
await cloudinary.v2.uploader.destroy(productManual.product_manual.public_id, {
|
||||
resource_type: "raw",
|
||||
});
|
||||
}
|
||||
|
||||
// Delete the product manual from the database
|
||||
await ProductManual.findByIdAndDelete(id);
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: "Product manual deleted successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error deleting product manual:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Internal server error",
|
||||
});
|
||||
}
|
||||
};
|
25
resources/ProductMannual/ProductManualModel.js
Normal file
25
resources/ProductMannual/ProductManualModel.js
Normal file
@ -0,0 +1,25 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const ProductManualSchema = new mongoose.Schema(
|
||||
{
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
product_manual: {
|
||||
public_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
const ProductManual = mongoose.model("ProductManual", ProductManualSchema);
|
||||
|
||||
export default ProductManual;
|
90
resources/ProductMannual/ProductManualRoute.js
Normal file
90
resources/ProductMannual/ProductManualRoute.js
Normal file
@ -0,0 +1,90 @@
|
||||
import express from "express";
|
||||
import {
|
||||
createProductManual,
|
||||
getAllProductManuals,
|
||||
getSingleProductManual,
|
||||
updateProductManual,
|
||||
deleteProductManual,
|
||||
} from "./ProductManualController.js";
|
||||
import {
|
||||
isAuthenticatedUser,
|
||||
authorizeRoles,
|
||||
} from "../../middlewares/auth.js";
|
||||
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
|
||||
import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Route for creating a product manual (Only Admin can create)
|
||||
router
|
||||
.route("/create")
|
||||
.post(isAuthenticatedUser, authorizeRoles("admin"), createProductManual);
|
||||
|
||||
// Route for getting all product manuals (accessible to Sales Coordinator, Territory Manager, and Admin)
|
||||
router.route("/").get(
|
||||
(req, res, next) => {
|
||||
// Allow access if the user is a sales coordinator, territory manager, or admin
|
||||
isAuthenticatedSalesCoOrdinator(req, res, (err) => {
|
||||
if (err) {
|
||||
isAuthenticatedTerritoryManager(req, res, (err) => {
|
||||
if (err) {
|
||||
isAuthenticatedUser(req, res, (err) => {
|
||||
if (err || !["admin"].includes(req.user.role)) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: "Access denied. Unauthorized role.",
|
||||
});
|
||||
}
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
getAllProductManuals
|
||||
);
|
||||
|
||||
// Route for getting a single product manual by ID (accessible to Sales Coordinator, Territory Manager, and Admin)
|
||||
router.route("/:id").get(
|
||||
(req, res, next) => {
|
||||
// Allow access if the user is a sales coordinator, territory manager, or admin
|
||||
isAuthenticatedSalesCoOrdinator(req, res, (err) => {
|
||||
if (err) {
|
||||
isAuthenticatedTerritoryManager(req, res, (err) => {
|
||||
if (err) {
|
||||
isAuthenticatedUser(req, res, (err) => {
|
||||
if (err || !["admin"].includes(req.user.role)) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: "Access denied. Unauthorized role.",
|
||||
});
|
||||
}
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
getSingleProductManual
|
||||
);
|
||||
// Route to update a product manual by ID
|
||||
router
|
||||
.route("/update/:id")
|
||||
.put(isAuthenticatedUser, authorizeRoles("admin"), updateProductManual);
|
||||
|
||||
// Route to delete a product manual by ID
|
||||
router
|
||||
.route("/delete/:id")
|
||||
.delete(isAuthenticatedUser, authorizeRoles("admin"), deleteProductManual);
|
||||
export default router;
|
||||
// /api/productmanual
|
@ -12,6 +12,7 @@ export const assignTask = async (req, res) => {
|
||||
taskAssignedTo,
|
||||
addedFor,
|
||||
addedForId,
|
||||
tradename,
|
||||
} = req.body;
|
||||
|
||||
const currentYear = new Date().getFullYear().toString().slice(-2);
|
||||
@ -29,6 +30,7 @@ export const assignTask = async (req, res) => {
|
||||
taskAssignedBy: req.user._id,
|
||||
addedFor,
|
||||
addedForId,
|
||||
tradename,
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
@ -73,8 +75,33 @@ export const getTasksByStatus = async (req, res) => {
|
||||
});
|
||||
}
|
||||
};
|
||||
export const getTasksbytask = async (req, res) => {
|
||||
try {
|
||||
const { task } = req.params;
|
||||
|
||||
// Validate the provided status
|
||||
if (!["Visit RD/PD", "Update Sales Data", "Update Inventory Data", "Collect KYC"].includes(task)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "Invalid task type provided.",
|
||||
});
|
||||
}
|
||||
const tasks = await Task.find({
|
||||
taskAssignedTo: req.user._id,
|
||||
task: task,
|
||||
}).sort({ createdAt: -1 });
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
tasks,
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
export const updateTaskStatus = async (req, res) => {
|
||||
try {
|
||||
const { taskId } = req.params;
|
||||
|
@ -12,12 +12,12 @@ const TaskSchema = new mongoose.Schema(
|
||||
task: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ["Visit Retailers", "Update Sales Data", "Update Inventory Data", "Collect KYC"],
|
||||
enum: ["Visit RD/PD", "Update Sales Data", "Update Inventory Data", "Collect KYC"],
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
required: function () {
|
||||
return this.task === "Collect KYC";
|
||||
return this.task === "Collect KYC" || this.task === "Visit RD/PD";
|
||||
},
|
||||
},
|
||||
taskStatus: {
|
||||
@ -60,6 +60,12 @@ const TaskSchema = new mongoose.Schema(
|
||||
return this.task === "Update Inventory Data";
|
||||
},
|
||||
},
|
||||
tradename: {
|
||||
type: String,
|
||||
required: function () {
|
||||
return this.task === "Update Inventory Data";
|
||||
},
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
assignTask,
|
||||
getTasksByStatus,
|
||||
updateTaskStatus,
|
||||
getTasksbytask,
|
||||
} from "./TaskController.js";
|
||||
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
|
||||
import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js";
|
||||
@ -22,7 +23,11 @@ router.get(
|
||||
isAuthenticatedSalesCoOrdinator,
|
||||
getTasksByStatus
|
||||
);
|
||||
|
||||
router.get(
|
||||
"/task/type/:task",
|
||||
isAuthenticatedSalesCoOrdinator,
|
||||
getTasksbytask
|
||||
);
|
||||
// Route to update task status
|
||||
router.put(
|
||||
"/update-task-status/:taskId",
|
||||
|
@ -563,7 +563,19 @@ export const uploadPrincipaldistributors = async (req, res) => {
|
||||
uniqueId: item.uniqueId,
|
||||
});
|
||||
await distributor.save();
|
||||
|
||||
await sendEmail({
|
||||
to: distributor.email,
|
||||
from: process.env.SEND_EMAIL_FROM,
|
||||
subject: `Cheminova Account Created`,
|
||||
html: `
|
||||
Your Principal Distributor Account is created successfully.
|
||||
<br/>Name: <strong>${distributor.name}</strong><br/>
|
||||
<br/>Mobile Number: <strong>${distributor.phone}</strong><br/>
|
||||
<br/>Password: <strong>${password}</strong><br/><br/>
|
||||
<a href="${process.env.PD_APP_URL}/login">Click here to login</a><br/><br/>
|
||||
If you have not requested this email, please ignore it.
|
||||
`,
|
||||
});
|
||||
// Now create the address for the new user
|
||||
const addressData = {
|
||||
street: item.street,
|
||||
|
Loading…
Reference in New Issue
Block a user