added notification for the PD

This commit is contained in:
ROSHAN GARG 2024-09-16 12:54:57 +05:30
parent 4126f14a5b
commit ce6ae1a8f9
7 changed files with 281 additions and 5 deletions

View File

@ -1,5 +1,6 @@
import SalesCoOrdinator from "../resources/SalesCoOrdinators/SalesCoOrdinatorModel.js"; import SalesCoOrdinator from "../resources/SalesCoOrdinators/SalesCoOrdinatorModel.js";
import TerritoryManager from "../resources/TerritoryManagers/TerritoryManagerModel.js"; import TerritoryManager from "../resources/TerritoryManagers/TerritoryManagerModel.js";
import User from "../resources/user/userModel.js";
import { sendPushNotification } from "./sendPushNotification.js"; import { sendPushNotification } from "./sendPushNotification.js";
export const rejectKYC = async (userId, title, message) => { export const rejectKYC = async (userId, title, message) => {
@ -25,3 +26,24 @@ export const rejectKYC = async (userId, title, message) => {
console.error("No FCM token found for user:", userId); console.error("No FCM token found for user:", userId);
} }
}; };
export const createKYC = async (userId, title, message) => {
// Try to find the user in SalesCoordinator model
console.log(userId);
let user = await User.findById(userId);
console.log(user);
// Get the user's FCM token
const userToken = user ? user.fcm_token : null;
// const userToken =
// "dRnjl8F3S8GA6_BnBfloWZ:APA91bFvuiA4pEQr03Kymqtw2N207VDHwzLlfz_OPWzhTtdAAWmPLF8cQSx0WYmiaL9g-PIbzvGrmzDzxNiyq58w9Gws6p2tDlDeqycqU17W74gi36xkGSUqlzNiFoTiDDNp7OFDdVPK";
console.log(userToken);
if (userToken) {
// Send the push notification
// const message = `Your KYC has been rejected. Reason: ${reason}`;
await sendPushNotification(userToken, title, message);
console.log("sent to device ");
} else {
console.error("No FCM token found for user:", userId);
}
};

View File

@ -2,7 +2,7 @@ import mongoose from "mongoose";
import cloudinary from "../../Utils/cloudinary.js"; import cloudinary from "../../Utils/cloudinary.js";
import { KYC } from "./KycModel.js"; import { KYC } from "./KycModel.js";
import User from "../user/userModel.js"; import User from "../user/userModel.js";
import { rejectKYC } from "../../Utils/rejectKyc.js"; import { createKYC, rejectKYC } from "../../Utils/rejectKyc.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";
import { Notification } from "../Notification/notificationModal.js"; import { Notification } from "../Notification/notificationModal.js";
@ -105,6 +105,19 @@ export const createKyc = async (req, res) => {
notes, notes,
}); });
if (principal_distributer) {
await createKYC(
kyc.principal_distributer,
"KYC Created",
`${trade_name} sent request to approve the KYC .`
);
await Notification.create({
title: "KYC Created",
msg: `KYC created for the trade name ${name}`,
kyc_ref: kyc._id,
added_for: kyc.principal_distributer,
});
}
if (kyc) { if (kyc) {
return res return res
.status(201) .status(201)
@ -573,4 +586,3 @@ export const saveFCMTokenForTM = async (req, res) => {
res.status(500).send("Internal Server Error"); res.status(500).send("Internal Server Error");
} }
}; };

View File

@ -0,0 +1,50 @@
import { RetailDistributor } from "../models/RetailDistributor";
import { RdOrder } from "../models/RdOrder";
// Controller to create a new order by RD
export const createOrderRD = async (req, res) => {
try {
const {
rdId,
paymentMode,
shipTo,
billTo,
orderItem,
subtotal,
gstTotal,
grandTotal,
} = req.body;
// Fetch the Retail Distributor (RD) to find the associated Principal Distributor (PD)
const rd = await RetailDistributor.findById(rdId).populate(
"principal_distributer"
);
if (!rd) {
return res.status(404).json({ message: "Retail Distributor not found" });
}
const pdId = rd.principal_distributer._id; // Get the associated PD
// Create the order
const newOrder = new RdOrder({
paymentMode,
shipTo,
billTo,
orderItem,
subtotal,
gstTotal,
grandTotal,
addedBy: rdId, // The RD who placed the order (Retail Distributor)
pd: pdId, // Reference to the PD associated with the RD
});
await newOrder.save();
res
.status(201)
.json({ message: "Order placed successfully", order: newOrder });
} catch (error) {
res.status(500).json({ message: "Server error", error });
}
};

View File

@ -0,0 +1,156 @@
import mongoose, { Schema } from "mongoose";
import { nanoid } from "nanoid"; // To generate unique 6-char IDs
const orderItemSchema = new Schema({
productId: {
type: Schema.Types.ObjectId,
ref: "Product",
required: true,
},
SKU: {
type: String,
required: true,
},
name: {
type: String,
required: true,
},
categoryName: {
type: String, // Directly store category name
required: true,
},
brandName: {
type: String, // Directly store brand name
required: true,
},
price: {
type: Number,
required: true,
},
GST: {
type: Number,
required: true,
},
HSN_Code: {
type: Number,
required: true,
},
description: {
type: String,
},
image: [
{
public_id: String,
url: String,
},
],
quantity: {
type: Number,
required: true,
default: 1,
},
});
const StatusHistorySchema = new mongoose.Schema({
status: {
type: String,
enum: ["new", "dispatched", "cancelled", "processing", "delivered"], // Ensure this matches your status enum
required: true,
},
timestamp: {
type: Date,
default: Date.now,
},
});
const rdOrderSchema = new Schema(
{
paymentMode: {
type: String,
enum: ["cheque", "online-transfer", "credit"],
required: true,
},
shipTo: {
type: String,
required: true,
},
billTo: {
type: String,
required: true,
},
orderItem: [orderItemSchema],
subtotal: {
type: Number,
required: true,
},
gstTotal: {
type: Number,
required: true,
},
grandTotal: {
type: Number,
required: true,
},
status: {
type: String,
enum: ["new", "dispatched", "cancelled", "processing", "delivered"],
default: "new",
},
statusUpdatedAt: {
type: Date,
default: Date.now,
},
uniqueId: {
type: String,
unique: true,
default: () => nanoid(6), // Generates a 6-character unique ID
},
addedBy: {
type: Schema.Types.ObjectId,
ref: "RetailDistributor", // Reference to the RD placing the order
required: true,
},
pd: {
type: mongoose.Schema.Types.ObjectId,
ref: "User", // Reference to the PD associated with the RD
required: true,
},
status_timeline: {
new: { type: Date },
paid: { type: Date },
processing: { type: Date },
dispatched: { type: Date },
delivered: { type: Date },
cancelled: { type: Date },
returned: { type: Date },
},
iscancelled: {
type: Boolean,
default: false,
},
order_Cancelled_Reason: {
type: String,
},
courier_name: { type: String },
courier_tracking_id: { type: String },
isDelivered: { type: Boolean, required: true, default: false },
DeliveredDate: { type: String, default: "" },
statusHistory: [StatusHistorySchema], // Add this field to store the status history
},
{ timestamps: true }
);
// Middleware to update the statusUpdatedAt field whenever status changes
rdOrderSchema.pre("save", function (next) {
if (this.isModified("status")) {
this.statusUpdatedAt = Date.now();
// Add the new status and timestamp to statusHistory
this.statusHistory.push({
status: this.status,
timestamp: this.statusUpdatedAt,
});
}
next();
});
export const RdOrder = mongoose.model("RdOrder", rdOrderSchema);

View File

@ -1320,3 +1320,30 @@ export const updateEmployeeById = catchAsyncErrors(async (req, res, next) => {
}); });
} }
}); });
export const saveFCMTokenForUser = async (req, res) => {
const { fcmToken } = req.body;
const userId = req.user._id;
try {
// Fetch the current FCM token for the user
const user = await User.findById(userId);
if (!user) {
return res.status(404).send("User not found");
}
// Check if the new FCM token is different from the current one
if (user.fcm_token && user.fcm_token === fcmToken) {
return res.status(200).send("FCM Token is already up to date");
}
// Update the FCM token
user.fcm_token = fcmToken;
await user.save();
res.status(200).send("FCM Token saved successfully");
} catch (error) {
console.error("Error saving FCM Token:", error);
res.status(500).send("Internal Server Error");
}
};

View File

@ -69,6 +69,10 @@ const userSchema = new mongoose.Schema(
accessTo: {}, accessTo: {},
resetPasswordToken: String, resetPasswordToken: String,
resetPasswordExpire: Date, resetPasswordExpire: Date,
fcm_token: {
type: String,
default: null,
},
}, },
{ timestamps: true } { timestamps: true }
); );
@ -105,7 +109,10 @@ userSchema.methods.comparePassword = async function (password) {
// Generating Reset Token // Generating Reset Token
userSchema.methods.getResetPasswordToken = function () { userSchema.methods.getResetPasswordToken = function () {
const resetToken = crypto.randomBytes(20).toString("hex"); const resetToken = crypto.randomBytes(20).toString("hex");
this.resetPasswordToken = crypto.createHash("sha256").update(resetToken).digest("hex"); this.resetPasswordToken = crypto
.createHash("sha256")
.update(resetToken)
.digest("hex");
this.resetPasswordExpire = Date.now() + 15 * 60 * 1000; // 15 minutes this.resetPasswordExpire = Date.now() + 15 * 60 * 1000; // 15 minutes
return resetToken; return resetToken;
}; };

View File

@ -21,6 +21,7 @@ import {
unmappedSCinPrincipalDistributor, unmappedSCinPrincipalDistributor,
mappedbySC, mappedbySC,
getAllPrincipalDistributorbyscId, getAllPrincipalDistributorbyscId,
saveFCMTokenForUser,
} from "./userController.js"; } from "./userController.js";
import { isAuthenticatedUser, authorizeRoles } from "../../middlewares/auth.js"; import { isAuthenticatedUser, authorizeRoles } from "../../middlewares/auth.js";
@ -123,5 +124,6 @@ router
router.route("/user/password/update").put(isAuthenticatedUser, updatePassword); router.route("/user/password/update").put(isAuthenticatedUser, updatePassword);
router.route("/user/update/profile").put(isAuthenticatedUser, updateProfile); router.route("/user/update/profile").put(isAuthenticatedUser, updateProfile);
router.route("/user/fcm-token", isAuthenticatedUser, saveFCMTokenForUser);
export default router; export default router;