diff --git a/app.js b/app.js
index 6adea88..4781cde 100644
--- a/app.js
+++ b/app.js
@@ -171,6 +171,8 @@ import CouponRoute from "./resources/Affiliate&Coupon/Coupon/CouponRoute.js";
// import ShortUrlRouter from "./resources/Businesses/Short_Urls/ShortUrlRoute.js";
//support Ticket
import SupportRouter from "./resources/Supports/supportRoute.js";
+// Point of Sale
+import PosorderRoute from "./resources/PosOrders/PosorderRoute.js";
app.use("/api/v1/", user);
//Product
@@ -238,4 +240,6 @@ app.use("/api/panel", PanelRoute);
// app.use("/api/shorturl", ShortUrlRouter);
//Support
app.use("/api", SupportRouter);
+// Point of Sale
+app.use("/api/posOrder", PosorderRoute);
export default app;
diff --git a/resources/PosOrders/PosCheckoutController.js b/resources/PosOrders/PosCheckoutController.js
new file mode 100644
index 0000000..8acb18e
--- /dev/null
+++ b/resources/PosOrders/PosCheckoutController.js
@@ -0,0 +1,85 @@
+import { POSOrder } from "./PosorderModel.js";
+import { shippingAddress } from "../ShippingAddresses/ShippingAddressModel.js";
+
+//generate unique order id
+const generateOrderId = async () => {
+ const currentYear = new Date().getFullYear();
+ // Find the latest order to get the last serial number
+ const latestOrder = await POSOrder.findOne({}, {}, { sort: { orderID: -1 } });
+ let serialNumber = 1;
+
+ if (latestOrder) {
+ const lastYear = parseInt(latestOrder.orderID.substring(0, 4), 10);
+ if (lastYear === currentYear) {
+ // If the last order was in the current year, increment the serial number
+ serialNumber = parseInt(latestOrder.orderID.substring(4), 10) + 1;
+ }
+ }
+ // Pad the serial number with zeros and concatenate with the current year
+ const paddedSerialNumber = serialNumber.toString().padStart(7, "0");
+ const orderId = `${currentYear}${paddedSerialNumber}`;
+ return orderId;
+};
+
+export const createOrderCheckout = async (req, res) => {
+ try {
+ const { address, cart, user, SalesType, paymentMode } =
+ req.body;
+// console.log(req.body)
+ // Perform validation
+ if (!address || !cart || cart.length === 0 || !SalesType || !user || !paymentMode) {
+ return res.status(400).json({ message: "Invalid order data" });
+ }
+
+ // Retrieve shipping address from database
+ const shippingInfo = await shippingAddress.findById(address);
+ if (!shippingInfo) {
+ return res.status(404).json({ message: "Shipping address not found" });
+ }
+
+ // Ensure that addressId is included in the shippingInfo object
+ const { _id: addressId, ...restOfShippingInfo } = shippingInfo.toObject();
+
+ // Calculate total amount based on the product_Subtotal of each product
+ const totalAmount = cart.reduce(
+ (acc, item) => acc + item.product_Subtotal,
+ 0
+ );
+
+ // Construct order items array
+ const orderItems = cart.map((item) => ({
+ product: item.product,
+ name: item.name,
+ price: item.price,
+ quantity: item.quantity,
+ product_Subtotal: item.total_amount,
+ gst_amount: item.gst_amount,
+ image: item.image,
+ variant_Name: item.variant_Name,
+ }));
+
+ // Generate a unique order ID
+ const orderId = await generateOrderId();
+
+ // Create the order document
+ const order = await POSOrder.create({
+ orderID: orderId,
+ total_amount: totalAmount,
+ orderItems,
+ shippingInfo: {
+ addressId: addressId, // Include the addressId
+ ...restOfShippingInfo, // Include other shipping information
+ },
+ user, // Assuming you have authenticated users
+ SalesType,
+ paymentMode,
+ });
+
+ return res.status(201).json({ success: true, order });
+ } catch (error) {
+ console.error("Error creating order:", error);
+ return res
+ .status(500)
+ .json({ success: false, message: "Internal server error" });
+ }
+};
diff --git a/resources/PosOrders/PosRazerPayCheckoutController.js b/resources/PosOrders/PosRazerPayCheckoutController.js
new file mode 100644
index 0000000..111fbe4
--- /dev/null
+++ b/resources/PosOrders/PosRazerPayCheckoutController.js
@@ -0,0 +1,481 @@
+import bodyParser from "body-parser";
+import crypto from "crypto";
+import Razorpay from "razorpay";
+import { POSOrder } from "./PosorderModel.js";
+import { shippingAddress } from "../ShippingAddresses/ShippingAddressModel.js";
+import sendEmail from "../../Utils/sendEmail.js";
+const instance = new Razorpay({
+ key_id: process.env.RAZERPAY_KEY_ID,
+ key_secret: process.env.RAZERPAY_SECRET_KEY,
+});
+
+const generateUniqueOrderId = async () => {
+ const currentYear = new Date().getFullYear();
+ // Find the latest order to get the last serial number
+ const latestOrder = await POSOrder.findOne({}, {}, { sort: { orderID: -1 } });
+ let serialNumber = 1;
+
+ if (latestOrder) {
+ const lastYear = parseInt(latestOrder.orderID.substring(0, 4), 10);
+ if (lastYear === currentYear) {
+ // If the last order was in the current year, increment the serial number
+ serialNumber = parseInt(latestOrder.orderID.substring(4), 10) + 1;
+ }
+ }
+ // Pad the serial number with zeros and concatenate with the current year
+ const paddedSerialNumber = serialNumber.toString().padStart(7, "0");
+ const orderId = `${currentYear}${paddedSerialNumber}`;
+ return orderId;
+};
+
+export const getRzpKey = async (req, res) => {
+ try {
+ const { name, email } = req.params;
+ console.log("name", name, "email", email);
+ if (!name || !email) {
+ throw new Error("Name and email are required parameters");
+ }
+ res.status(200).json({
+ success: true,
+ key: process.env.RAZERPAY_KEY_ID,
+ name,
+ email,
+ });
+ } catch (error) {
+ console.error("Error in getRzpKey:", error);
+ res
+ .status(500)
+ .json({
+ success: false,
+ message: error.message || "Internal server error",
+ });
+ }
+};
+
+export const checkout = async (req, res) => {
+ try {
+ console.log(req.body);
+ const options = {
+ amount: Number(req.body.subtotal * 100),
+ currency: "INR",
+ };
+
+ console.log("options", options);
+
+ // Wait for the order creation to complete
+ const order = await instance.orders.create(options);
+
+ console.log("order", order);
+
+ // Check if the order was created successfully
+ if (!order || !order.id) {
+ return res.status(400).json({
+ success: false,
+ message: "Failed to create order",
+ });
+ }
+
+ // Extract required data from request parameters and body
+ const { email } = req.params;
+ const { address, cart, user, SalesType, paymentMode, subtotal } = req.body;
+
+ // Check for required parameters
+ if (!email) {
+ return res.status(400).send({ message: "Please enter the email" });
+ }
+
+ if (cart.length < 1) {
+ return res.status(400).json({ message: "Cart is empty!" });
+ }
+
+ if (!address) {
+ return res
+ .status(404)
+ .json({ message: "Please select a shipping address!" });
+ }
+
+ if (!subtotal) {
+ return res
+ .status(404)
+ .json({ message: "Please provide the product subtotal!" });
+ }
+
+ // Fetch shipping information from the database
+ const shippingInfo = await shippingAddress.findById(address);
+ if (!shippingInfo) {
+ return res.status(404).json({ message: "Shipping address not found" });
+ }
+
+ console.log("shippinginfo", shippingInfo);
+
+ // Extract addressId and other shipping information
+ const { _id: addressId, ...restOfShippingInfo } = shippingInfo.toObject();
+
+ // Prepare order items
+ const orderItems = cart.map((item) => ({
+ product: item.product,
+ name: item.name,
+ price: item.price,
+ quantity: item.quantity,
+ product_Subtotal: item.total_amount,
+ gst_amount: item.gst_amount,
+ image: item.image,
+ variant_Name: item.variant_Name,
+ }));
+
+ // Generate a unique order ID
+ const orderId = await generateUniqueOrderId();
+
+ // Create the order in the database
+ const orders = await POSOrder.create({
+ orderID: orderId,
+ total_amount: subtotal,
+ orderItems,
+ shippingInfo: {
+ addressId: addressId,
+ ...restOfShippingInfo,
+ },
+ user,
+ SalesType,
+ paymentMode,
+ razorpay_order_id: order.id,
+ });
+
+ res.status(200).json({
+ success: true,
+ order,
+ });
+ } catch (error) {
+ console.error("Error in checkout:", error);
+ res
+ .status(500)
+ .json({
+ success: false,
+ message: error.message || "Internal server error",
+ });
+ }
+};
+
+export const paymentVerification = async (req, res) => {
+ const { razorpay_order_id, razorpay_payment_id, razorpay_signature } =
+ req.body;
+ console.log(req.body);
+ const body = razorpay_order_id + "|" + razorpay_payment_id;
+
+ const expectedSignature = crypto
+ .createHmac("sha256", process.env.RAZERPAY_SECRET_KEY)
+ .update(body.toString())
+ .digest("hex");
+
+ const isAuthentic = expectedSignature === razorpay_signature;
+
+ if (isAuthentic) {
+ // Database comes here
+ let findSameOrder = await POSOrder.findOne({
+ razorpay_order_id: razorpay_order_id,
+ }).populate({
+ path: "user",
+ select: "name email -_id",
+ });
+ // console.log("findSameOrder", findSameOrder);
+ if (findSameOrder) {
+ (findSameOrder.razorpay_payment_id = razorpay_payment_id), // await Payment.create({
+ (findSameOrder.isPaid = true),
+ (findSameOrder.paidAt = Date.now()),
+ (findSameOrder.razorpay_signature = razorpay_signature);
+ // await Payment.create({
+ findSameOrder.payment_status = "success";
+
+ findSameOrder.orderStatus = "new";
+ await findSameOrder.save();
+ }
+ //send email to customer
+ // console.log("findSameOrder", findSameOrder);
+ await sendEmail({
+ to: `${findSameOrder?.user?.email}`, // Change to your recipient
+
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+
+ subject: `Your POSOrder #${findSameOrder?.orderID} Confirmation`,
+ html: `
Welcome to Smellika - Let the Shopping Begin!
+ Hi ${
+ findSameOrder?.shippingInfo?.first_Name
+ },
+
+ Great news! Your order #${
+ findSameOrder?.orderID
+ } has been confirmed. Here are the details
+ Shipping Address : ${
+ findSameOrder?.shippingInfo?.first_Name
+ } ${findSameOrder?.shippingInfo?.last_Name} , ${
+ findSameOrder?.shippingInfo?.street
+ } ${findSameOrder?.shippingInfo?.city} ${
+ findSameOrder?.shippingInfo?.state
+ } ${findSameOrder?.shippingInfo?.country}, PIN-${
+ findSameOrder?.shippingInfo?.postalCode
+ }, Phone Number: ${findSameOrder?.shippingInfo?.phone_Number}
+ POSOrder Items :
+
+
+
+ S No. |
+
+ Product Name |
+ Image |
+
+ Quantity |
+ Price |
+ GST Amount |
+
+ SubTotal |
+
+
+
+
+ ${findSameOrder?.orderItems
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+
+ ${
+ product.name
+ } |
+  |
+
+ ${
+ product.quantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${
+ product?.gst_amount
+ } |
+ ₹${
+ product.product_Subtotal
+ } |
+
+
+ `
+ )
+ .join("")}
+
+ Total Amount : |
+ ₹${
+ findSameOrder?.total_amount
+ } |
+
+
+
+
+
+ Best regards,
+
+ Team Smellika`,
+ });
+ // console.log("findSameOrder", findSameOrder);
+
+ // // findSameOrder.razorpay_payment_id=razorpay_payment_id,// await Payment.create({
+ // findOrder.paidAt = new Date(event.data.object.created * 1000);
+ // findOrder.isPaid = true;
+
+ // razorpay_signature: { type: String },
+ // razorpay_order_id,
+ // razorpay_payment_id,
+ // razorpay_signature,
+ // });
+
+ // res.redirect(`https://admin.smellika.com/#/pos`);
+ res.redirect(`http://localhost:3000/#/pos`);
+ } else {
+ res.status(400).json({
+ success: false,
+ });
+ }
+};
+export const handlePayment = async (req, res) => {
+ try {
+ const { email } = req.user;
+ if (!email)
+ return res.status(400).send({ message: "Please enter the email" });
+ const { address, cart, subtotal } = req.body;
+ if (cart.length < 1)
+ return res.status(400).json({ message: "cart is empty!" });
+ switch (true) {
+ //validation
+ case !address: {
+ return res.status(404).json({ msg: "please provide shipping address" });
+ }
+ case !subtotal: {
+ return res.status(404).json({ msg: "please provide product subtotal" });
+ }
+ }
+ let addss = await shippingAddress.findById(address);
+ // console.log(addss?.postalCode);
+ let shipping = {
+ first_Name: addss.first_Name,
+ last_Name: addss.last_Name,
+ phone_Number: addss.phone_Number,
+ street: addss.street,
+ city: addss.city,
+ state: addss.state,
+ postalCode: addss?.postalCode,
+ country: addss.country,
+ addressId: address,
+ };
+ const orderItems = await cart.map((item) => ({
+ product: item.product._id,
+ name: item.product.name,
+ price: item.product.total_amount,
+ image: item.product.image,
+ quantity: item.quantity,
+ product_Subtotal: item.subtotal,
+ }));
+
+ // console.log("line", lineItems[0]);
+ const Id = await generateUniqueOrderId();
+ const order = await POSOrder.create({
+ orderID: Id,
+ total_amount: subtotal,
+ orderItems,
+ shippingInfo: shipping,
+ user: req.user._id,
+ });
+ console.log("fffffffff", order, "llllllllll");
+ const lineItems = await cart.map((item) => ({
+ price_data: {
+ currency: "inr",
+ product_data: {
+ name: item.product.name,
+
+ images: [item.product.image[0]?.url],
+ },
+ unit_amount: Number(item.product.total_amount) * 100,
+ },
+ quantity: Number(item.quantity),
+ }));
+ if (order) {
+ const session = await stripe.checkout.sessions.create({
+ payment_method_types: ["card"],
+ line_items: lineItems,
+ mode: "payment",
+ customer_email: `${email}`,
+ metadata: {
+ orderId: order._id.toString(),
+
+ // Add any other key-value pairs as needed
+ },
+ success_url: `${process.env.FRONTEND_URL}/cart`,
+ cancel_url: `${process.env.FRONTEND_URL}/error`,
+ });
+ // res.json({ sessionId: session.id });
+
+ res.status(200).send({ message: "order created", url: session.url });
+ }
+ } catch (err) {
+ console.log(err);
+ res.status(500).send({ message: "Something went wrong", err });
+ }
+};
+
+export const webhook = async (req, res) => {
+ const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
+ const signature = req.headers["stripe-signature"];
+ let event;
+ if (webhookSecret) {
+ try {
+ event = stripe.webhooks.constructEvent(
+ req.body,
+ signature,
+ webhookSecret
+ );
+ } catch (err) {
+ console.log(`❌ Error message: ${err.message}`);
+ res.status(400).send(`Webhook Error: ${err.message}`);
+ return;
+ }
+ }
+
+ if (event.type === "checkout.session.completed") {
+ // console.log("dddddddddddd", event.data);
+ const findOrder = await POSOrder.findById(
+ event.data.object.metadata?.orderId
+ );
+ findOrder.paypal_payer_id = event.data.object.id;
+ findOrder.paidAt = new Date(event.data.object.created * 1000);
+ findOrder.isPaid = true;
+ if (event.data.object?.payment_status === "paid") {
+ findOrder.payment_status = "success";
+ } else {
+ findOrder.payment_status = "failed";
+ }
+ findOrder.orderStatus = "new";
+ await findOrder.save();
+ await sendEmail({
+ to: `${event.data.object.customer_email}`, // Change to your recipient
+
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+
+ subject: `Your POSOrder #${findOrder?.orderID} Confirmation`,
+ html: ` Welcome to Smellika - Let the Shopping Begin!
+ Hi ${findOrder?.shippingInfo?.first_Name},
+
+ Great news! Your order #${findOrder?.orderID} has been confirmed. Here are the details
+
+ Best regards,
+
+ Team Smellika`,
+ });
+
+ // Items: [List of Purchased Items]
+ // Total Amount: [Total Amount]
+ // Shipping Address: [Shipping Address]
+
+ // We'll keep you updated on the shipping progress. Thanks for choosing Smellika!
+
+ // Best regards
+ // Team Smellika
+ console.log(
+ "event.data.object",
+ event.data.object,
+ "---------------------"
+ );
+
+ console.log(`💰 Payment status: ${event.data.object?.payment_status}`);
+
+ // Saving the payment details in the database
+ // const payment = await Payment.create({
+ // customer_email: event.data.object.customer_email,
+ // amount: event.data.object.amount_total / 100,
+ // paymentId: event.data.object.id,
+ // paymentStatus: event.data.object.payment_status,
+ // createdAt: event.data.object.created,
+ // });
+ }
+ // if (event.type === "checkout.session.completed") {
+ // console.log("dddddddddddd", event.data);
+ // console.log("event.data.object", event.data.object);
+ // console.log(`💰 Payment status: ${event.data.object?.payment_status}`);
+ // payment_intent.payment_failed;
+
+ // // Saving the payment details in the database
+ // // const payment = await Payment.create({
+ // // customer_email: event.data.object.customer_email,
+ // // amount: event.data.object.amount_total / 100,
+ // // paymentId: event.data.object.id,
+ // // paymentStatus: event.data.object.payment_status,
+ // // createdAt: event.data.object.created,
+ // // });
+ // }
+
+ // Return a 200 res to acknowledge receipt of the event
+ res.status(200).end();
+ // res.send().end();
+};
diff --git a/resources/PosOrders/PosorderController.js b/resources/PosOrders/PosorderController.js
new file mode 100644
index 0000000..6a02741
--- /dev/null
+++ b/resources/PosOrders/PosorderController.js
@@ -0,0 +1,552 @@
+import sendEmail from "../../Utils/sendEmail.js";
+import { POSOrder } from "./PosorderModel.js";
+
+export const getAllOrder = async (req, res) => {
+ try {
+ const { status } = req.params;
+ const order = await POSOrder.find({
+ IsStoreDelivery: "Cash",
+ orderStatus: status,
+ })
+ .populate({
+ path: "user",
+ select: "name -_id",
+ })
+ .populate({
+ path: "shippingInfo.addressId",
+ })
+ .sort({ updatedAt: -1 });
+ if (order) {
+ res.status(201).json({
+ success: true,
+ order,
+ message: "All POSOrder Fetched",
+ });
+ }
+ } catch (error) {
+ res.status(500).json({
+ success: false,
+ message: error.message ? error.message : "Something went Wrong",
+ });
+ }
+};
+export const getOrders = async (req, res) => {
+ try {
+ const order = await POSOrder.find({
+ // payment_status: "success",
+ })
+ .populate({
+ path: "user",
+ select: "name -_id",
+ })
+ .populate({
+ path: "shippingInfo.addressId",
+ })
+ .sort({ updatedAt: -1 });
+ if (order) {
+ res.status(201).json({
+ success: true,
+ order,
+ message: "All POSOrder Fetched",
+ });
+ }
+ } catch (error) {
+ res.status(500).json({
+ success: false,
+ message: error.message ? error.message : "Something went Wrong",
+ });
+ }
+};
+export const getSingleOrder = async (req, res) => {
+ try {
+ if (!req.params.id)
+ return res.status(400).json({ message: "please Provide POSOrder Id" });
+
+ const order = await POSOrder.findById(req.params.id)
+ .populate({
+ path: "user",
+ select: "name email -_id",
+ })
+ .populate({
+ path: "shippingInfo.addressId",
+ })
+ .sort({ createdAt: -1 });
+ if (order) {
+ res.status(201).json({
+ success: true,
+ order,
+ message: " POSOrder Fetched",
+ });
+ }
+ } catch (error) {
+ res.status(500).json({
+ success: false,
+ message: error.message ? error.message : "Something went Wrong",
+ });
+ }
+};
+
+//get self User POSOrder
+export const getUserSelf = async (req, res) => {
+ if (!req?.user) return res.status(400).json({ message: "please login !" });
+ try {
+ const order = await POSOrder.find({
+ user: req.user?._id,
+ payment_status: "success",
+ }).sort({ createdAt: -1 });
+
+ if (order) {
+ return res.status(200).json({
+ success: true,
+ order,
+ message: "self POSOrder fetched",
+ });
+ }
+ } catch (error) {
+ res.status(500).json({
+ success: false,
+ message: error.message ? error.message : "Something went Wrong",
+ });
+ }
+};
+
+export const deleteOneOrder = async (req, res) => {
+ try {
+ if (!req?.user) return res.status(400).json({ message: "please login !" });
+ if (!req.params.id)
+ return res.status(400).json({ message: "please Provide POSOrder Id" });
+ const getOrder = await POSOrder.findById(req.params.id);
+ if (!getOrder) {
+ return res.status(404).json({
+ success: false,
+ message: "No POSOrder Found!",
+ });
+ }
+ const order = await POSOrder.findByIdAndDelete(req.params.id);
+
+ await order.remove();
+ res.status(200).json({
+ success: true,
+ message: "POSOrder Deleted Successfully!!",
+ });
+ } catch (error) {
+ res.status(500).json({
+ success: false,
+ message: error.message ? error.message : "Something went Wrong",
+ });
+ }
+};
+export const updateOrderStatusById = async (req, res) => {
+ try {
+ let body = { orderStatus: req.body.status };
+
+ const currentDate = new Date();
+ body["status_timeline." + req.body.status] = currentDate;
+ // if (req.body?.package_weight) body.package_weight = req.body.package_weight;
+ const order = await POSOrder.findById(req.params.id).populate({
+ path: "user",
+ select: "name email -_id",
+ });
+ // console.log("order", order);
+ // const parentData = { email: order?.parent?.email };
+ if (req.body.status === "cancelled") {
+ body["order_Cancelled_Reason"] = req.body?.ReasonforCancellation;
+ body["iscancelled"] = true;
+ await POSOrder.findByIdAndUpdate(order._id, body);
+ await sendEmail({
+ to: `${order?.user?.email}`, // Change to your recipient
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+ subject: `POSOrder #${order?.orderID} Update: Cancellation and Refund Process`,
+ html: ` Hi ${
+ order?.shippingInfo?.first_Name
+ },
+ We hope this message finds you well. We're writing to inform you that your order ${
+ order?.orderID
+ } has been canceled. We understand that circumstances may change, and we're here to assist you throughout the process.
+
+
+ Items :
+
+
+
+ S No. |
+
+ Product Name |
+ Image |
+
+ Quantity |
+ Price |
+ GST Amount |
+
+ SubTotal |
+
+
+
+
+ ${order?.orderItems
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+
+ ${
+ product.name
+ } |
+  |
+
+ ${
+ product.quantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${
+ product?.gst_amount
+ } |
+ ₹${
+ product.product_Subtotal
+ } |
+
+
+ `
+ )
+ .join("")}
+
+ Total Amount : |
+ ₹${
+ order?.total_amount
+ } |
+
+
+
+ Cancellation Reason : ${
+ req.body?.ReasonforCancellation
+ }
+ Refund Information: The amount from your canceled order will be processed for a refund. Please allow up to 7 working days for the amount to be transferred back to your original payment method.
+
+ If you have any concerns or further questions, please feel free to reply to this email. We appreciate your understanding and hope to serve you better in the future.
+
+
+ Best regards,
+
+ Team Smellika`,
+ });
+ return res
+ .status(200)
+ .json({ status: "ok", message: "POSOrder status updated successfully!" });
+ } else if (req.body.status === "processing") {
+ await POSOrder.findByIdAndUpdate(order._id, body);
+
+ await sendEmail({
+ to: `${order?.user?.email}`, // Change to your recipient
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+ subject: `Your POSOrder #${order?.orderID} is in Processing!`,
+ html: ` Exciting news! Your order #${
+ order?.orderID
+ } has entered the processing phase. Our team is diligently preparing your items for dispatch. Rest assured, we're working hard to ensure everything is perfect for you.
+ Hi ${
+ order?.shippingInfo?.first_Name
+ },
+ POSOrder Status : Processing
+ POSOrder Items :
+
+
+
+ S No. |
+
+ Product Name |
+ Image |
+
+ Quantity |
+ Price |
+ GST Amount |
+
+ SubTotal |
+
+
+
+
+ ${order?.orderItems
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+
+ ${
+ product.name
+ } |
+  |
+
+ ${
+ product.quantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${
+ product?.gst_amount
+ } |
+ ₹${
+ product.product_Subtotal
+ } |
+
+
+ `
+ )
+ .join("")}
+
+ Total Amount : |
+ ₹${
+ order?.total_amount
+ } |
+
+
+
+ We'll send you another email with the tracking details as soon as your order is dispatched. If you have any questions or need assistance, feel free to reply to this email.
+ Thank you for choosing Smellika!
+
+ Best regards,
+
+ Team Smellika`,
+ });
+ return res
+ .status(200)
+ .json({ status: "ok", message: "POSOrder status updated successfully!" });
+ }
+ // else if (body.status === "dispatched") {
+ // const noBalanceRemaining =
+ // order?.sales_items?.filter((e) => Number(e?.balance_quantity) > 0)
+ // ?.length === 0
+ // ? true
+ // : false;
+ // if (!noBalanceRemaining)
+ // return res
+ // .status(400)
+ // .json({ message: "Few items still have balance quantity!" });
+ // await OrderDispatchedEmail(parentData.email, order.order_id, body);
+ // await Invoice.updateMany(
+ // { order: order._id, status: { $in: ["processing"] } },
+ // { status: body.status, "status_timeline.dispatched": currentDate }
+ // );
+ // } else if (body.status === "delivered") {
+ // await OrderDeliveredEmail(parentData.email, order.order_id);
+ // await Invoice.updateMany(
+ // { order: order._id, status: { $in: ["processing", "dispatched"] } },
+ // { status: body.status, "status_timeline.delivered": currentDate }
+ // );
+ // }
+ else if (req.body.status === "dispatched") {
+ body["courier_name"] = req.body.courierName;
+ body["courier_tracking_id"] = req.body.TrackingID;
+ await POSOrder.findByIdAndUpdate(order._id, body);
+ await sendEmail({
+ to: `${order?.user?.email}`, // Change to your recipient
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+ subject: `Your POSOrder #${order?.orderID} is On Its Way!`,
+ html: ` Hi ${
+ order?.shippingInfo?.first_Name
+ },
+ Exciting news! Your order #${
+ order?.orderID
+ } has been dispatched and is en route to you. 🚚 Here are the details:
+
+ Courier Name : ${
+ req.body.courierName
+ }
+ Courier Tracking ID : ${
+ req.body.TrackingID
+ }
+
+
+ Items :
+
+
+
+ S No. |
+
+ Product Name |
+ Image |
+
+ Quantity |
+ Price |
+ GST Amount |
+
+ SubTotal |
+
+
+
+
+ ${order?.orderItems
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+
+ ${
+ product.name
+ } |
+  |
+
+ ${
+ product.quantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${
+ product?.gst_amount
+ } |
+ ₹${
+ product.product_Subtotal
+ } |
+
+
+ `
+ )
+ .join("")}
+
+ Total Amount : |
+ ₹${
+ order?.total_amount
+ } |
+
+
+
+ POSOrder Status : Dispatched
+ If you have any questions or need assistance, feel free to reply to this email.
+
+Thanks for choosing Smellika! We hope you enjoy your purchase.
+
+
+ Best regards,
+
+ Team Smellika`,
+ });
+ return res
+ .status(200)
+ .json({ status: "ok", message: "POSOrder status updated successfully!" });
+ } else if (req.body.status === "delivered") {
+ body["isDelivered"] = true;
+ body["DeliveredDate"] = req.body.DDate;
+ await POSOrder.findByIdAndUpdate(order._id, body);
+ await sendEmail({
+ to: `${order?.user?.email}`, // Change to your recipient
+ from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
+ subject: `Your POSOrder #${order?.orderID} Has Been Delivered!`,
+ html: ` Hi ${
+ order?.shippingInfo?.first_Name
+ },
+ Great news! Your order #${
+ order?.orderID
+ } has been successfully delivered to your doorstep. We hope everything is just as you expected!
+ Items :
+
+
+
+ S No. |
+
+ Product Name |
+ Image |
+
+ Quantity |
+ Price |
+ GST Amount |
+
+ SubTotal |
+
+
+
+
+ ${order?.orderItems
+ ?.map(
+ (product, index) => `
+
+ ${
+ index + 1
+ } |
+
+ ${
+ product.name
+ } |
+  |
+
+ ${
+ product.quantity
+ } |
+ ₹${
+ product.price
+ } |
+ ₹${
+ product?.gst_amount
+ } |
+ ₹${
+ product.product_Subtotal
+ } |
+
+
+ `
+ )
+ .join("")}
+
+ Total Amount : |
+ ₹${
+ order?.total_amount
+ } |
+
+
+
+ Delivery Date: ${
+ req.body.DDate
+ }
+ Your satisfaction is our priority, and we'd love to hear about your experience. Please take a moment to share your thoughts by leaving a review. Your feedback is invaluable to us!
+
+ If you have any questions or concerns about your order, feel free to reply to this email.
+
+ Thank you for choosing Smellika! We hope to serve you again soon.
+
+
+
+ Best regards,
+
+ Team Smellika`,
+ });
+
+ return res
+ .status(200)
+ .json({ status: "ok", message: "POSOrder status updated successfully!" });
+ } else {
+ // await POSOrder.findByIdAndUpdate(order._id, body);
+ // console.log(order);
+ res
+ .status(200)
+ .json({ status: "ok", message: "POSOrder status updated successfully!" });
+ }
+ } catch (error) {
+ console.log(error);
+ res
+ .status(500)
+ .json({ message: error?.message || "Something went wrong!" });
+ }
+};
diff --git a/resources/PosOrders/PosorderModel.js b/resources/PosOrders/PosorderModel.js
new file mode 100644
index 0000000..5134084
--- /dev/null
+++ b/resources/PosOrders/PosorderModel.js
@@ -0,0 +1,165 @@
+import mongoose from "mongoose";
+
+const POSorderSchema = new mongoose.Schema(
+ {
+ orderID: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ user: {
+ type: mongoose.Schema.ObjectId,
+ ref: "User",
+ required: true,
+ },
+ shippingInfo: {
+ first_Name: {
+ type: String,
+ required: true,
+ },
+ last_Name: {
+ type: String,
+ required: true,
+ },
+ phone_Number: {
+ type: Number,
+ required: true,
+ },
+ street: {
+ type: String,
+ required: true,
+ },
+ city: {
+ type: String,
+ required: true,
+ trim: true,
+ },
+ state: {
+ type: String,
+ required: true,
+ },
+ postalCode: {
+ type: String,
+ required: true,
+ trim: true,
+ // Add a regular expression to enforce a specific postal code format
+ // For example, assuming a 5-digit format for the United States
+ match: /^\d{6}$/,
+ },
+ country: {
+ type: String,
+ required: true,
+ },
+ addressId: {
+ type: mongoose.Schema.ObjectId,
+ ref: "ShippingAddress",
+ required: true,
+ },
+ },
+ orderItems: [
+ {
+ name: {
+ type: String,
+ default: "",
+ },
+ price: {
+ type: Number,
+ default: "",
+ },
+ variant_Name: { type: String, default: "" },
+ quantity: {
+ type: Number,
+ default: "",
+ default: 1,
+ },
+ image: [{}],
+
+ product_Subtotal: {
+ type: Number,
+ default: "",
+ },
+ gst_amount: {
+ type: Number,
+ default: "",
+ },
+ gst_rate: {
+ type: Number,
+ default: "",
+ },
+ tax_Name: {
+ type: String,
+ default: "",
+ },
+ product: {
+ type: mongoose.Schema.ObjectId,
+ ref: "Product",
+ },
+ },
+ ],
+
+ shipping_charge: { type: Number, default: 0 },
+ tax_amount: { type: Number, default: 0 },
+ total_amount: { type: Number, default: 0 },
+ weight: { type: Number, default: 0 },
+
+ SalesType: {
+ type: String,
+ enum: ["inStoreDelivery", "shipToCustomer"],
+ },
+ paymentMode: {
+ type: String,
+ enum: ["QRCode", "Cash","SendPaymentLink"],
+ },
+ payment_status: {
+ type: String,
+ enum: ["pending", "success", "failed"],
+ },
+ isPaid: {
+ type: Boolean,
+ default: false,
+ },
+ paidAt: {
+ type: Date,
+ },
+
+ orderStatus: {
+ type: String,
+ enum: [
+ "new",
+ "processing",
+ "dispatched",
+ "delivered",
+ "cancelled",
+ "returned",
+ ],
+ default: "new",
+ },
+ razorpay_payment_id: { type: String },
+ razorpay_order_id: { type: String },
+ razorpay_signature: { type: String },
+ isDelivered: { type: Boolean, required: true, default: false },
+ DeliveredDate: { type: String, default: "" },
+
+ // deliveredAt: { type: Date },
+ status_timeline: {
+ new: { 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 },
+ },
+ { timestamps: true }
+);
+
+export const POSOrder = mongoose.model("POSOrder", POSorderSchema);
diff --git a/resources/PosOrders/PosorderRoute.js b/resources/PosOrders/PosorderRoute.js
new file mode 100644
index 0000000..65dace4
--- /dev/null
+++ b/resources/PosOrders/PosorderRoute.js
@@ -0,0 +1,51 @@
+import bodyParser from "body-parser";
+import {
+ deleteOneOrder,
+ getAllOrder,
+ getOrders,
+ getSingleOrder,
+ getUserSelf,
+ updateOrderStatusById,
+} from "./PosorderController.js";
+import { isAuthenticatedUser, authorizeRoles } from "../../middlewares/auth.js";
+import express from "express";
+import {
+ createOrderCheckout,
+} from "./PosCheckoutController.js";
+import { checkout, getRzpKey, paymentVerification } from "./PosRazerPayCheckoutController.js";
+
+const app = express();
+
+// Configure bodyParser to parse the raw request body as a buffer
+app.use(bodyParser.raw({ type: "application/json" }));
+
+
+const router = express.Router();
+//checkout Routes-------------------------//
+router.route("/pos-checkout/").post(isAuthenticatedUser, createOrderCheckout);
+// ---------------------------------------------------
+
+// --------------------------------------------------
+//get user self
+router.route("/user/self").get(isAuthenticatedUser, getUserSelf);
+
+//admin route
+router
+ .route("/pos-getAll/:status")
+ .get(isAuthenticatedUser, authorizeRoles("admin"), getAllOrder);
+router
+ .route("/pos-getAll/")
+ .get(isAuthenticatedUser, authorizeRoles("admin"), getOrders);
+router.route("/pos-getOne/:id").get(isAuthenticatedUser, getSingleOrder);
+router
+ .route("/pos-change/status/:id")
+ .patch(isAuthenticatedUser, authorizeRoles("admin"), updateOrderStatusById);
+
+router
+ .route("/pos-delete/:id")
+ .delete(isAuthenticatedUser, authorizeRoles("admin"), deleteOneOrder);
+//RAZERPAY checkout
+router.route("/getRzpKey/:name/:email").get(isAuthenticatedUser, getRzpKey);
+router.route("/Rzpcheckout/").post(isAuthenticatedUser, checkout);
+router.route("/paymentverification").post(paymentVerification);
+export default router;