This commit is contained in:
ROSHAN GARG 2024-09-06 10:54:13 +05:30
commit 24e84e7186
11 changed files with 299 additions and 11 deletions

5
app.js
View File

@ -189,7 +189,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 SalesRoute from "./resources/Sales/SalesRoute.js";
// PD Order place // PD Order place
@ -268,7 +268,8 @@ app.use("/api",notification)
app.use("/api",PdOrderRoute) app.use("/api",PdOrderRoute)
//Inventory //Inventory
app.use("/api/inventory", InventoryRoute); app.use("/api/inventory", InventoryRoute);
// Sales
app.use("/api/sales", SalesRoute);
//Task //Task
app.use("/api/task", TaskRoute); app.use("/api/task", TaskRoute);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,193 @@
import { Sales } from "./SalesModel.js";
import User from "../user/userModel.js";
import { KYC } from "../KYC/KycModel.js";
import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js";
import TerritoryManager from "../TerritoryManagers/TerritoryManagerModel.js";
import SalesCoordinator from "../SalesCoOrdinators/SalesCoOrdinatorModel.js";
import crypto from "crypto";
// Add Sales data
const parseDate = (dateStr) => {
const [day, month, year] = dateStr.split("/").map(Number);
// Create a UTC date object to ensure the correct date is stored
return new Date(Date.UTC(year, month - 1, day));
};
export const addSales = async (req, res) => {
try {
const { products, addedFor, addedForId, tradename, date } = req.body;
const userId = req.user._id;
const userType = req.userType;
// console.log("req.user", req.user);
const currentYear = new Date().getFullYear().toString().slice(-2);
const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase();
const uniqueId = `${currentYear}-${randomChars}`;
// console.log("uniqueId", uniqueId);
// Convert the date from DD/MM/YYYY string to Date object
const parsedDate = parseDate(date);
const newSales = new Sales({
userId,
userType,
addedFor,
addedForId,
products,
uniqueId,
tradename,
date: parsedDate,
});
// console.log("newSales", newSales);
await newSales.save();
res.status(201).json({
success: true,
message: "Sales added successfully",
data: newSales,
});
} catch (error) {
res.status(500).json({ success: false, message: "Server error", error });
}
};
export const getAllSales = async (req, res) => {
try {
const { page = 1, show = 10, startDate, endDate, name } = req.query;
const query = {};
if (startDate && endDate) {
const start = new Date(startDate);
const end = new Date(endDate);
if (start.toDateString() === end.toDateString()) {
query.createdAt = {
$gte: start,
$lt: new Date(start).setDate(start.getDate() + 1),
};
} else {
query.createdAt = {
$gte: start,
$lte: new Date(end).setDate(end.getDate() + 1),
};
}
} else if (startDate && endDate === "") {
query.createdAt = {
$gte: new Date(startDate),
$lte: new Date(),
};
} else if (endDate && startDate === "") {
query.createdAt = {
$lte: new Date(endDate),
};
}
const allSales = await Sales.find(query).sort({ createdAt: -1 });
// Populate additional details
const populatedSales = await Promise.all(
allSales.map(async (Sales) => {
let user = null;
if (Sales.userType === "TerritoryManager") {
user = await TerritoryManager.findById(Sales.userId);
} else if (Sales.userType === "SalesCoordinator") {
user = await SalesCoordinator.findById(Sales.userId);
}
let addedForData = null;
let tradeName = null;
if (Sales.addedFor === "PrincipalDistributor") {
addedForData = await User.findById(Sales.addedForId);
if (addedForData) {
const shippingAddress = await ShippingAddress.findOne({
user: addedForData._id,
});
addedForData = {
...addedForData.toObject(),
shippingAddress,
};
tradeName =
addedForData.shippingAddress?.tradeName?.toLowerCase() || "";
}
} else if (Sales.addedFor === "RetailDistributor") {
addedForData = await KYC.findById(Sales.addedForId);
tradeName = addedForData?.trade_name?.toLowerCase() || "";
}
return {
...Sales.toObject(),
user,
addedForData,
tradeName,
};
})
);
// Apply name filter if the name parameter is provided
let filteredSales = populatedSales;
if (name) {
filteredSales = filteredSales.filter(
(Sales) =>
Sales.tradeName && Sales.tradeName.includes(name.toLowerCase())
);
}
// Calculate total count of filtered data
const total_data = filteredSales.length;
// Apply pagination after filtering
const paginatedSales = filteredSales.slice((page - 1) * show, page * show);
// Calculate total pages
const total_pages = Math.ceil(total_data / show);
// Send response with pagination info
res.status(200).json({
total_data,
total_pages,
current_page: Number(page),
Sales: paginatedSales,
});
} catch (error) {
console.error("Error in getAllSales:", error);
res.status(500).json({ message: error.message });
}
};
// Get single Sales
export const getSingleSales = async (req, res) => {
try {
const { id } = req.params;
const Sales = await Sales.findById(id);
if (!Sales) {
return res.status(404).json({ message: "Sales not found" });
}
// Populate user details based on userType
let user = null;
if (Sales.userType === "TerritoryManager") {
user = await TerritoryManager.findById(Sales.userId);
} else if (Sales.userType === "SalesCoOrdinator") {
user = await SalesCoordinator.findById(Sales.userId);
}
// Populate addedFor details based on addedFor
let addedForData = null;
if (Sales.addedFor === "PrincipalDistributor") {
addedForData = await User.findById(Sales.addedForId);
const shippingAddress = await ShippingAddress.findOne({
user: addedForData._id,
});
addedForData = {
...addedForData.toObject(),
shippingAddress,
};
} else if (Sales.addedFor === "RetailDistributor") {
addedForData = await KYC.findById(Sales.addedForId);
}
res.status(200).json({
...Sales.toObject(),
user,
addedForData,
});
} catch (error) {
res.status(500).json({ message: error.message });
}
};

View File

@ -0,0 +1,64 @@
import mongoose from 'mongoose';
// Define Product record schema
const ProductRecordSchema = new mongoose.Schema({
SKU: {
type: String,
required: true,
},
ProductName: {
type: String,
required: true,
},
QuantitySold: {
type: Number,
required: true,
},
SalesAmount: {
type: Number,
required: true,
},
comments:{
type: String,
},
});
// Define main Sales schema
const SalesSchema = new mongoose.Schema({
uniqueId: {
type: String,
required: true,
unique: true,
},
userId: {
type: mongoose.Schema.Types.ObjectId,
refPath: 'userType',
required: true,
},
userType: {
type: String,
required: true,
enum: ['SalesCoOrdinator', 'TerritoryManager'],
},
addedFor: {
type: String,
required: true,
enum: ['PrincipalDistributor', 'RetailDistributor'],
},
addedForId: {
type: mongoose.Schema.Types.ObjectId,
refPath: 'addedFor',
required: true,
},
tradename: {
type: String,
required: true,
},
date: {
type: Date,
required: true
},
products: [ProductRecordSchema],
}, { timestamps: true, versionKey: false });
export const Sales = mongoose.model('Sales', SalesSchema);

View File

@ -0,0 +1,25 @@
import express from "express";
import { addSales,getAllSales,getSingleSales } from "./SalesController.js";
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js";
import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js";
const router = express.Router();
// Route to add Sales data
router.post("/add-SC", isAuthenticatedSalesCoOrdinator, addSales);
router.post("/add-TM", isAuthenticatedTerritoryManager, addSales);
// Admin routes
router.get(
"/all",
isAuthenticatedUser,
authorizeRoles("admin"),
getAllSales
);
router.get(
"/:id",
isAuthenticatedUser,
authorizeRoles("admin"),
getSingleSales
);
export default router;

View File

@ -5,7 +5,7 @@ import { sendPushNotification } from "../../Utils/sendPushNotification.js";
import SalesCoOrdinator from "../SalesCoOrdinators/SalesCoOrdinatorModel.js"; import SalesCoOrdinator from "../SalesCoOrdinators/SalesCoOrdinatorModel.js";
import TerritoryManager from "../TerritoryManagers/TerritoryManagerModel.js"; import TerritoryManager from "../TerritoryManagers/TerritoryManagerModel.js";
// Function to update task statuses // Function to update task statuses
const updateOverdueTasks = async () => { export const updateOverdueTasks = async () => {
try { try {
const currentDate = new Date(); const currentDate = new Date();
const currentDateOnly = new Date(currentDate.setHours(0, 0, 0, 0)); const currentDateOnly = new Date(currentDate.setHours(0, 0, 0, 0));
@ -40,9 +40,9 @@ const updateOverdueTasks = async () => {
}; };
// Schedule the cron job to run daily at midnight // Schedule the cron job to run daily at midnight
cron.schedule("10 1 * * *", updateOverdueTasks, { // cron.schedule("5 9 * * *", updateOverdueTasks, {
timezone: "Asia/Kolkata", // timezone: "Asia/Kolkata",
}); // });
// cron.schedule("30 9 * * *", updateOverdueTasks); // cron.schedule("30 9 * * *", updateOverdueTasks);

View File

@ -49,20 +49,20 @@ const TaskSchema = new mongoose.Schema(
type: String, type: String,
enum: ['PrincipalDistributor', 'RetailDistributor'], enum: ['PrincipalDistributor', 'RetailDistributor'],
required: function () { required: function () {
return this.task === "Update Inventory Data" || this.task === "Visit RD/PD"; return this.task === "Update Inventory Data" || this.task === "Visit RD/PD" || this.task === "Update Sales Data";
}, },
}, },
addedForId: { addedForId: {
type: mongoose.Schema.Types.ObjectId, type: mongoose.Schema.Types.ObjectId,
refPath: 'addedFor', refPath: 'addedFor',
required: function () { required: function () {
return this.task === "Update Inventory Data" || this.task === "Visit RD/PD"; return this.task === "Update Inventory Data" || this.task === "Visit RD/PD" || this.task === "Update Sales Data";
}, },
}, },
tradename: { tradename: {
type: String, type: String,
required: function () { required: function () {
return this.task === "Update Inventory Data" || this.task === "Visit RD/PD"; return this.task === "Update Inventory Data" || this.task === "Visit RD/PD" || this.task === "Update Sales Data";
}, },
}, },
}, },

View File

@ -3,7 +3,8 @@ dotenv.config();
import app from "./app.js"; import app from "./app.js";
import connectDatabase from "./database/db.js"; import connectDatabase from "./database/db.js";
import cloudinary from "cloudinary"; import cloudinary from "cloudinary";
import cron from "node-cron";
import {updateOverdueTasks} from "./resources/Task/TaskController.js ";
// Connecting to database // Connecting to database
connectDatabase(); connectDatabase();
@ -28,6 +29,10 @@ app.get("/", (req, res) => {
res.send("API is running.."); res.send("API is running..");
}); });
// } // }
// Schedule the cron job
cron.schedule("10 0 * * *", updateOverdueTasks, {
timezone: "Asia/Kolkata",
});
//<---------deployement-------------> //<---------deployement------------->
const server = app.listen(process.env.PORT, () => { const server = app.listen(process.env.PORT, () => {
console.log(`Server is working on http://localhost:${process.env.PORT}`); console.log(`Server is working on http://localhost:${process.env.PORT}`);