added notification for the PD
This commit is contained in:
parent
4126f14a5b
commit
ce6ae1a8f9
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
50
resources/RD_Ordes/rdOrderController.js
Normal file
50
resources/RD_Ordes/rdOrderController.js
Normal 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 });
|
||||||
|
}
|
||||||
|
};
|
156
resources/RD_Ordes/rdOrderModal.js
Normal file
156
resources/RD_Ordes/rdOrderModal.js
Normal 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);
|
@ -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");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user