diff --git a/backend/controllers/shop/sub-controllers/adminController.js b/backend/controllers/shop/sub-controllers/adminController.js
new file mode 100644
index 00000000..61f9054d
--- /dev/null
+++ b/backend/controllers/shop/sub-controllers/adminController.js
@@ -0,0 +1,44 @@
+const Payment = require("../models/payment");
+const Invoice = require("../models/invoice");
+
+// Admin view all payments
+const adminViewPayments = async (req, res) => {
+ try {
+ const payments = await Payment.find()
+ .populate("orderId")
+ .populate("userId");
+ res.status(200).json(payments);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Admin view all invoices
+const adminViewInvoices = async (req, res) => {
+ try {
+ const invoices = await Invoice.find()
+ .populate("orderId")
+ .populate("userId");
+ res.status(200).json(invoices);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Admin filter/sort payments
+const adminFilterPayments = async (req, res) => {
+ const { status, startDate, endDate } = req.query;
+ const filters = {};
+ if (status) filters.paymentStatus = status;
+ if (startDate && endDate)
+ filters.paymentDate = { $gte: startDate, $lte: endDate };
+
+ try {
+ const payments = await Payment.find(filters);
+ res.status(200).json(payments);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+module.exports = { adminViewPayments, adminViewInvoices, adminFilterPayments };
diff --git a/backend/controllers/shop/sub-controllers/invoiceController.js b/backend/controllers/shop/sub-controllers/invoiceController.js
new file mode 100644
index 00000000..41cc8388
--- /dev/null
+++ b/backend/controllers/shop/sub-controllers/invoiceController.js
@@ -0,0 +1,217 @@
+const Invoice = require("../models/invoice");
+const Joi = require("joi");
+
+// Validation Schemas
+const invoiceSchema = Joi.object({
+ orderId: Joi.string().required(),
+ userId: Joi.string().required(),
+ amount: Joi.number().min(0).required(),
+ dueDate: Joi.date().required(),
+ paymentId: Joi.string().optional(),
+});
+
+const statusUpdateSchema = Joi.object({
+ status: Joi.string()
+ .valid("Paid", "Unpaid", "Overdue", "Cancelled")
+ .required(),
+});
+
+// Generate invoice after payment confirmation
+const generateInvoice = async (req, res) => {
+ const { error, value } = invoiceSchema.validate(req.body);
+ if (error) return res.status(400).json({ message: error.message });
+
+ const { orderId, userId, amount, dueDate, paymentId } = value;
+
+ const newInvoice = new Invoice({
+ invoiceId: `INV${Date.now()}`,
+ orderId,
+ userId,
+ amount,
+ dueDate,
+ paymentId,
+ });
+
+ try {
+ const invoice = await newInvoice.save();
+ res.status(201).json(invoice);
+ } catch (error) {
+ console.error(`Error generating invoice: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Retrieve invoices by user, order, status, or date range with pagination
+const getInvoices = async (req, res) => {
+ const {
+ userId,
+ orderId,
+ status,
+ startDate,
+ endDate,
+ page = 1,
+ limit = 10,
+ sortBy = "invoiceDate",
+ order = "desc",
+ } = req.query;
+
+ try {
+ const filters = {};
+ if (userId) filters.userId = userId;
+ if (orderId) filters.orderId = orderId;
+ if (status) filters.status = status;
+
+ if (startDate || endDate) {
+ filters.invoiceDate = {};
+ if (startDate) filters.invoiceDate.$gte = new Date(startDate);
+ if (endDate) filters.invoiceDate.$lte = new Date(endDate);
+ }
+
+ const invoices = await Invoice.find(filters)
+ .sort({ [sortBy]: order === "asc" ? 1 : -1 })
+ .skip((page - 1) * limit)
+ .limit(Number(limit));
+
+ res.status(200).json(invoices);
+ } catch (error) {
+ console.error(`Error fetching invoices: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Retrieve a single invoice by ID
+const getInvoiceById = async (req, res) => {
+ try {
+ const invoice = await Invoice.findById(req.params.id);
+ if (!invoice) return res.status(404).json({ message: "Invoice not found" });
+ res.status(200).json(invoice);
+ } catch (error) {
+ console.error(`Error fetching invoice by ID: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Update invoice status with validation
+const updateInvoiceStatus = async (req, res) => {
+ const { error, value } = statusUpdateSchema.validate(req.body);
+ if (error) return res.status(400).json({ message: error.message });
+
+ try {
+ const invoice = await Invoice.findByIdAndUpdate(
+ req.params.id,
+ { status: value.status },
+ { new: true }
+ );
+ if (!invoice) return res.status(404).json({ message: "Invoice not found" });
+ res.status(200).json(invoice);
+ } catch (error) {
+ console.error(`Error updating invoice status: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Delete an invoice by ID
+const deleteInvoice = async (req, res) => {
+ try {
+ const invoice = await Invoice.findByIdAndDelete(req.params.id);
+ if (!invoice) return res.status(404).json({ message: "Invoice not found" });
+ res.status(200).json({ message: "Invoice deleted successfully" });
+ } catch (error) {
+ console.error(`Error deleting invoice: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Mark overdue invoices
+const markOverdueInvoices = async (req, res) => {
+ try {
+ const overdueInvoices = await Invoice.updateMany(
+ { dueDate: { $lt: new Date() }, status: "Unpaid" },
+ { status: "Overdue" }
+ );
+ res
+ .status(200)
+ .json({
+ message: `${overdueInvoices.nModified} invoices marked as overdue`,
+ });
+ } catch (error) {
+ console.error(`Error marking overdue invoices: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Summary of invoices by status
+const invoiceSummary = async (req, res) => {
+ const { userId } = req.query;
+
+ try {
+ const match = userId ? { userId } : {};
+
+ const summary = await Invoice.aggregate([
+ { $match: match },
+ {
+ $group: {
+ _id: "$status",
+ totalAmount: { $sum: "$amount" },
+ count: { $sum: 1 },
+ },
+ },
+ ]);
+
+ const summaryData = summary.reduce((acc, item) => {
+ acc[item._id] = { totalAmount: item.totalAmount, count: item.count };
+ return acc;
+ }, {});
+
+ res.status(200).json(summaryData);
+ } catch (error) {
+ console.error(`Error generating invoice summary: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+// Bulk invoice generation
+const generateBulkInvoices = async (req, res) => {
+ const { invoices } = req.body;
+
+ if (!Array.isArray(invoices) || invoices.length === 0) {
+ return res.status(400).json({ message: "Invalid invoices data" });
+ }
+
+ const validationErrors = invoices
+ .map((invoiceData, index) => {
+ const { error } = invoiceSchema.validate(invoiceData);
+ return error ? { index, message: error.message } : null;
+ })
+ .filter(Boolean);
+
+ if (validationErrors.length > 0) {
+ return res
+ .status(400)
+ .json({ message: "Validation errors", errors: validationErrors });
+ }
+
+ try {
+ const invoiceDocuments = invoices.map((invoiceData) => ({
+ ...invoiceData,
+ invoiceId: `INV${Date.now() + Math.floor(Math.random() * 1000)}`,
+ }));
+
+ const createdInvoices = await Invoice.insertMany(invoiceDocuments);
+ res.status(201).json(createdInvoices);
+ } catch (error) {
+ console.error(`Error generating bulk invoices: ${error.message}`);
+ res.status(500).json({ message: "Internal server error" });
+ }
+};
+
+module.exports = {
+ generateInvoice,
+ getInvoices,
+ getInvoiceById,
+ updateInvoiceStatus,
+ deleteInvoice,
+ markOverdueInvoices,
+ invoiceSummary,
+ generateBulkInvoices,
+};
diff --git a/backend/controllers/shop/sub-controllers/paymentController.js b/backend/controllers/shop/sub-controllers/paymentController.js
new file mode 100644
index 00000000..0bc6569d
--- /dev/null
+++ b/backend/controllers/shop/sub-controllers/paymentController.js
@@ -0,0 +1,161 @@
+const Payment = require("../models/payment");
+
+// Retrieve all payments
+const getAllPayments = async (req, res) => {
+ try {
+ const payments = await Payment.find();
+ res.status(200).json(payments);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Retrieve payment by ID
+const getPaymentById = async (req, res) => {
+ try {
+ const payment = await Payment.findById(req.params.id);
+ if (!payment) return res.status(404).json({ message: "Payment not found" });
+ res.status(200).json(payment);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Create a new payment
+const createPayment = async (req, res) => {
+ const { orderId, userId, amount, paymentMethod, transactionId } = req.body;
+
+ const newPayment = new Payment({
+ paymentId: `PAY${Date.now()}`,
+ orderId,
+ userId,
+ amount,
+ paymentMethod,
+ transactionId,
+ });
+
+ try {
+ const payment = await newPayment.save();
+ res.status(201).json(payment);
+ } catch (error) {
+ res.status(400).json({ message: error.message });
+ }
+};
+
+// Update payment status
+const updatePaymentStatus = async (req, res) => {
+ const { paymentStatus } = req.body;
+ try {
+ const payment = await Payment.findByIdAndUpdate(
+ req.params.id,
+ { paymentStatus },
+ { new: true }
+ );
+ if (!payment) return res.status(404).json({ message: "Payment not found" });
+ res.status(200).json(payment);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+const Payment = require("../models/payment");
+
+// Update Payment Method
+const updatePaymentMethod = async (req, res) => {
+ const { paymentMethod } = req.body;
+ try {
+ if (!["Credit Card", "PayPal", "Bank Transfer"].includes(paymentMethod)) {
+ return res.status(400).json({ message: "Invalid payment method" });
+ }
+ const payment = await Payment.findByIdAndUpdate(
+ req.params.id,
+ { paymentMethod },
+ { new: true }
+ );
+ if (!payment) return res.status(404).json({ message: "Payment not found" });
+ res.status(200).json(payment);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Retrieve Payments by Date Range
+const getPaymentsByDateRange = async (req, res) => {
+ const { startDate, endDate } = req.query;
+ try {
+ const payments = await Payment.find({
+ paymentDate: {
+ $gte: new Date(startDate),
+ $lte: new Date(endDate),
+ },
+ });
+ if (!payments.length)
+ return res
+ .status(404)
+ .json({ message: "No payments found in this date range" });
+ res.status(200).json(payments);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Retrieve Payments by Amount Range
+const getPaymentsByAmountRange = async (req, res) => {
+ const { minAmount, maxAmount } = req.query;
+ try {
+ const payments = await Payment.find({
+ amount: { $gte: minAmount, $lte: maxAmount },
+ });
+ if (!payments.length)
+ return res
+ .status(404)
+ .json({ message: "No payments found in this amount range" });
+ res.status(200).json(payments);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Retrieve Payment by Transaction ID
+const getPaymentByTransactionId = async (req, res) => {
+ try {
+ const payment = await Payment.findOne({
+ transactionId: req.params.transactionId,
+ });
+ if (!payment)
+ return res
+ .status(404)
+ .json({ message: "Payment not found with this transaction ID" });
+ res.status(200).json(payment);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+// Count Payments by Status
+const countPaymentsByStatus = async (req, res) => {
+ try {
+ const counts = await Payment.aggregate([
+ {
+ $group: {
+ _id: "$paymentStatus",
+ count: { $sum: 1 },
+ },
+ },
+ ]);
+ res.status(200).json(counts);
+ } catch (error) {
+ res.status(500).json({ message: error.message });
+ }
+};
+
+module.exports = {
+ getAllPayments,
+ getPaymentById,
+ createPayment,
+ updatePaymentStatus,
+ updatePaymentMethod,
+ getPaymentsByDateRange,
+ getPaymentsByAmountRange,
+ getPaymentByTransactionId,
+ countPaymentsByStatus,
+};
diff --git a/backend/controllers/shop/sub-controllers/supplierController.js b/backend/controllers/shop/sub-controllers/supplierController.js
new file mode 100644
index 00000000..c088b5b5
--- /dev/null
+++ b/backend/controllers/shop/sub-controllers/supplierController.js
@@ -0,0 +1,176 @@
+const Supplier = require("../models/Supplier");
+
+exports.createSupplier = async (req, res) => {
+ try {
+ const { name, contactInfo, address, productsSupplied, status } = req.body;
+ const supplier = new Supplier({
+ name,
+ contactInfo,
+ address,
+ productsSupplied,
+ status,
+ });
+ await supplier.save();
+ res.status(201).json(supplier);
+ } catch (err) {
+ res.status(500).json({ message: "Error creating supplier", error: err });
+ }
+};
+
+// Get all Suppliers with pagination and sorting
+exports.getAllSuppliers = async (req, res) => {
+ try {
+ const { page = 1, limit = 10, sort = "createdAt" } = req.query;
+ const suppliers = await Supplier.find()
+ .sort(sort)
+ .skip((page - 1) * limit)
+ .limit(Number(limit));
+ res.json(suppliers);
+ } catch (err) {
+ res.status(500).json({ message: "Error fetching suppliers", error: err });
+ }
+};
+
+// Get a Supplier by ID
+exports.getSupplierById = async (req, res) => {
+ try {
+ const supplier = await Supplier.findById(req.params.id);
+ if (!supplier) {
+ return res.status(404).json({ message: "Supplier not found" });
+ }
+ res.json(supplier);
+ } catch (err) {
+ res.status(500).json({ message: "Error fetching supplier", error: err });
+ }
+};
+
+// Update a Supplier
+exports.updateSupplier = async (req, res) => {
+ try {
+ const { name, contactInfo, address, productsSupplied, status } = req.body;
+ const supplier = await Supplier.findByIdAndUpdate(
+ req.params.id,
+ {
+ name,
+ contactInfo,
+ address,
+ productsSupplied,
+ status,
+ updatedAt: Date.now(),
+ },
+ { new: true }
+ );
+ if (!supplier) {
+ return res.status(404).json({ message: "Supplier not found" });
+ }
+ res.json(supplier);
+ } catch (err) {
+ res.status(500).json({ message: "Error updating supplier", error: err });
+ }
+};
+
+// Soft delete a Supplier (set status to inactive)
+exports.deleteSupplier = async (req, res) => {
+ try {
+ const supplier = await Supplier.findByIdAndUpdate(
+ req.params.id,
+ { status: "inactive" },
+ { new: true }
+ );
+ if (!supplier) {
+ return res.status(404).json({ message: "Supplier not found" });
+ }
+ res.json(supplier);
+ } catch (err) {
+ res.status(500).json({ message: "Error deleting supplier", error: err });
+ }
+};
+
+const Supplier = require("../models/Supplier");
+const Product = require("../models/Product"); // Assuming there's a Product model
+
+// Add a product to a supplier
+exports.addProductToSupplier = async (req, res) => {
+ try {
+ const { productId } = req.body;
+ const supplier = await Supplier.findById(req.params.id);
+ if (!supplier) {
+ return res.status(404).json({ message: "Supplier not found" });
+ }
+
+ supplier.productsSupplied.push(productId);
+ await supplier.save();
+
+ res.status(200).json(supplier);
+ } catch (err) {
+ res
+ .status(500)
+ .json({ message: "Error adding product to supplier", error: err });
+ }
+};
+
+// Remove a product from a supplier
+exports.removeProductFromSupplier = async (req, res) => {
+ try {
+ const { productId } = req.body;
+ const supplier = await Supplier.findById(req.params.id);
+ if (!supplier) {
+ return res.status(404).json({ message: "Supplier not found" });
+ }
+
+ supplier.productsSupplied = supplier.productsSupplied.filter(
+ (product) => product.toString() !== productId
+ );
+ await supplier.save();
+
+ res.status(200).json(supplier);
+ } catch (err) {
+ res
+ .status(500)
+ .json({ message: "Error removing product from supplier", error: err });
+ }
+};
+
+// Get all products supplied by a supplier
+exports.getProductsSupplied = async (req, res) => {
+ try {
+ const supplier = await Supplier.findById(req.params.id).populate(
+ "productsSupplied"
+ );
+ if (!supplier) {
+ return res.status(404).json({ message: "Supplier not found" });
+ }
+ res.json(supplier.productsSupplied);
+ } catch (err) {
+ res.status(500).json({ message: "Error fetching products", error: err });
+ }
+};
+
+exports.searchSuppliers = async (req, res) => {
+ try {
+ const { name, status, email, phone } = req.query;
+ const query = {};
+
+ if (name) query.name = { $regex: name, $options: "i" };
+ if (status) query.status = status;
+ if (email) query["contactInfo.email"] = email;
+ if (phone) query["contactInfo.phone"] = phone;
+
+ const suppliers = await Supplier.find(query);
+ res.json(suppliers);
+ } catch (err) {
+ res.status(500).json({ message: "Error searching suppliers", error: err });
+ }
+};
+
+exports.getSuppliersByStatus = async (req, res) => {
+ try {
+ const { status } = req.params;
+ const suppliers = await Supplier.find({ status });
+ res.json(suppliers);
+ } catch (err) {
+ res
+ .status(500)
+ .json({ message: "Error fetching suppliers by status", error: err });
+ }
+};
diff --git a/backend/middleware/sub-ware/authSupplierMiddleware.js b/backend/middleware/sub-ware/authSupplierMiddleware.js
new file mode 100644
index 00000000..adce51f9
--- /dev/null
+++ b/backend/middleware/sub-ware/authSupplierMiddleware.js
@@ -0,0 +1,10 @@
+const isAdmin = (req, res, next) => {
+ // Assuming user object is attached to request after authentication
+ if (req.user && req.user.role === "admin") {
+ next();
+ } else {
+ return res.status(403).json({ message: "Access forbidden: Admins only" });
+ }
+};
+
+module.exports = isAdmin;
diff --git a/backend/middleware/sub-ware/validatePaymentInvoice.js b/backend/middleware/sub-ware/validatePaymentInvoice.js
new file mode 100644
index 00000000..e208773e
--- /dev/null
+++ b/backend/middleware/sub-ware/validatePaymentInvoice.js
@@ -0,0 +1,25 @@
+const validatePaymentData = (req, res, next) => {
+ const { orderId, userId, amount, paymentMethod, transactionId } = req.body;
+
+ if (!orderId || !userId || !amount || !paymentMethod || !transactionId) {
+ return res
+ .status(400)
+ .json({ message: "All fields are required for payment" });
+ }
+
+ next();
+};
+
+const validateInvoiceData = (req, res, next) => {
+ const { orderId, userId, amount, dueDate, paymentId } = req.body;
+
+ if (!orderId || !userId || !amount || !dueDate || !paymentId) {
+ return res
+ .status(400)
+ .json({ message: "All fields are required for invoice" });
+ }
+
+ next();
+};
+
+module.exports = { validatePaymentData, validateInvoiceData };
diff --git a/backend/middleware/sub-ware/validationMiddleware.js b/backend/middleware/sub-ware/validationMiddleware.js
new file mode 100644
index 00000000..c569037d
--- /dev/null
+++ b/backend/middleware/sub-ware/validationMiddleware.js
@@ -0,0 +1,28 @@
+const Joi = require('joi');
+
+// Validation schema for supplier data
+const supplierValidationSchema = Joi.object({
+ name: Joi.string().required(),
+ contactInfo: Joi.object({
+ email: Joi.string().email().required(),
+ phone: Joi.string().required(),
+ }).required(),
+ address: Joi.object({
+ street: Joi.string().required(),
+ city: Joi.string().required(),
+ state: Joi.string().required(),
+ postalCode: Joi.string().required(),
+ }).required(),
+ productsSupplied: Joi.array().items(Joi.string()).required(),
+ status: Joi.string().valid('active', 'inactive').default('active'),
+});
+
+const validateSupplierData = (req, res, next) => {
+ const { error } = supplierValidationSchema.validate(req.body);
+ if (error) {
+ return res.status(400).json({ message: 'Validation Error', details: error.details });
+ }
+ next();
+};
+
+module.exports = validateSupplierData;
diff --git a/backend/model/shop/sub-model/Supplier.js b/backend/model/shop/sub-model/Supplier.js
new file mode 100644
index 00000000..7d466d78
--- /dev/null
+++ b/backend/model/shop/sub-model/Supplier.js
@@ -0,0 +1,58 @@
+const mongoose = require("mongoose");
+
+const supplierSchema = new mongoose.Schema(
+ {
+ name: {
+ type: String,
+ required: true,
+ },
+ contactInfo: {
+ email: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ phone: {
+ type: String,
+ required: true,
+ },
+ },
+ address: {
+ street: {
+ type: String,
+ required: true,
+ },
+ city: {
+ type: String,
+ required: true,
+ },
+ state: {
+ type: String,
+ required: true,
+ },
+ postalCode: {
+ type: String,
+ required: true,
+ },
+ },
+ productsSupplied: [
+ { type: mongoose.Schema.Types.ObjectId, ref: "Product" },
+ ],
+ status: {
+ type: String,
+ required: true,
+ default: "active",
+ },
+ createdAt: {
+ type: Date,
+ default: Date.now,
+ },
+ updatedAt: {
+ type: Date,
+ default: Date.now,
+ },
+ },
+ { timestamps: true }
+);
+
+module.exports = mongoose.model("Supplier", supplierSchema);
diff --git a/backend/model/shop/sub-model/invoice.js b/backend/model/shop/sub-model/invoice.js
new file mode 100644
index 00000000..5ea2f010
--- /dev/null
+++ b/backend/model/shop/sub-model/invoice.js
@@ -0,0 +1,47 @@
+const mongoose = require("mongoose");
+
+
+const invoiceSchema = new mongoose.Schema(
+ {
+ invoiceId: { type: String, required: true, unique: true },
+ orderId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: "Order",
+ required: true,
+ },
+ userId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: "User",
+ required: true,
+ index: true, // Adds index for faster query on user invoices
+ },
+ amount: { type: Number, required: true, min: 0 },
+ invoiceDate: { type: Date, default: Date.now },
+ dueDate: {
+ type: Date,
+ required: true,
+ default: function () {
+ return new Date(+new Date() + 7 * 24 * 60 * 60 * 1000); // Default due date is 7 days from invoice date
+ },
+ },
+ status: {
+ type: String,
+ enum: ["Paid", "Unpaid", "Overdue", "Cancelled"],
+ default: "Unpaid",
+ },
+ paymentId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: "Payment",
+ sparse: true, // Allows null value indexing for unpaid invoices
+ },
+ },
+ { timestamps: true }
+);
+
+// Virtual field to check if invoice is overdue
+invoiceSchema.virtual("isOverdue").get(function () {
+ return this.status === "Unpaid" && this.dueDate < new Date();
+});
+
+const Invoice = mongoose.model("Invoice", invoiceSchema);
+module.exports = Invoice;
diff --git a/backend/model/shop/sub-model/payment.js b/backend/model/shop/sub-model/payment.js
new file mode 100644
index 00000000..44182dd7
--- /dev/null
+++ b/backend/model/shop/sub-model/payment.js
@@ -0,0 +1,34 @@
+const mongoose = require("mongoose");
+
+const paymentSchema = new mongoose.Schema(
+ {
+ paymentId: { type: String, required: true, unique: true },
+ orderId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: "Order",
+ required: true,
+ },
+ userId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: "User",
+ required: true,
+ },
+ amount: { type: Number, required: true },
+ paymentMethod: {
+ type: String,
+ enum: ["Credit Card", "PayPal", "Bank Transfer"],
+ required: true,
+ },
+ paymentStatus: {
+ type: String,
+ default: "Pending",
+ enum: ["Pending", "Completed", "Failed"],
+ },
+ paymentDate: { type: Date, default: Date.now },
+ transactionId: { type: String, required: true },
+ },
+ { timestamps: true }
+);
+
+const Payment = mongoose.model("Payment", paymentSchema);
+module.exports = Payment;
diff --git a/backend/routes/sub-routes/invoiceRoutes.js b/backend/routes/sub-routes/invoiceRoutes.js
new file mode 100644
index 00000000..a6f30c3d
--- /dev/null
+++ b/backend/routes/sub-routes/invoiceRoutes.js
@@ -0,0 +1,39 @@
+const express = require("express");
+const router = express.Router();
+
+const {
+ generateInvoice,
+ getInvoices,
+ getInvoiceById,
+ updateInvoiceStatus,
+ deleteInvoice,
+ markOverdueInvoices,
+ invoiceSummary,
+ generateBulkInvoices,
+} = require("../controllers/invoiceController");
+
+// Route to generate a new invoice after payment confirmation
+router.post("/generate", generateInvoice);
+
+// Route to retrieve invoices by user, order, status, or date range with pagination and sorting
+router.get("/", getInvoices);
+
+// Route to retrieve a specific invoice by its ID
+router.get("/:id", getInvoiceById);
+
+// Route to update an invoice's status
+router.patch("/:id/status", updateInvoiceStatus);
+
+// Route to delete an invoice by its ID
+router.delete("/:id", deleteInvoice);
+
+// Route to mark overdue invoices (based on the current date)
+router.patch("/mark-overdue", markOverdueInvoices);
+
+// Route to get an invoice summary (by status, optionally by user)
+router.get("/summary", invoiceSummary);
+
+// Route to generate bulk invoices at once
+router.post("/generate-bulk", generateBulkInvoices);
+
+module.exports = router;
diff --git a/backend/routes/sub-routes/paymentRoutes.js b/backend/routes/sub-routes/paymentRoutes.js
new file mode 100644
index 00000000..47c456df
--- /dev/null
+++ b/backend/routes/sub-routes/paymentRoutes.js
@@ -0,0 +1,34 @@
+const express = require("express");
+const router = express.Router();
+const {
+ getAllPayments,
+ getPaymentById,
+ getPaymentsByUserId,
+ getPaymentsByStatus,
+ createPayment,
+ updatePaymentStatus,
+ deletePayment,
+ updatePaymentMethod,
+ getPaymentsByDateRange,
+ getPaymentsByAmountRange,
+ getPaymentByTransactionId,
+ countPaymentsByStatus,
+} = require("../controllers/paymentController");
+
+// Payment routes
+router.get("/", getAllPayments); // Retrieve all payments
+router.get("/:id", getPaymentById); // Retrieve payment by ID
+router.get("/user/:userId", getPaymentsByUserId); // Retrieve payments by User ID
+router.get("/status/:status", getPaymentsByStatus); // Retrieve payments by Status
+router.post("/", createPayment); // Create a new payment
+router.patch("/:id/status", updatePaymentStatus); // Update payment status
+router.patch("/:id/method", updatePaymentMethod); // Update payment method
+router.delete("/:id", deletePayment); // Delete payment
+
+// Additional routes for edge cases
+router.get("/date-range", getPaymentsByDateRange); // Retrieve payments by date range
+router.get("/amount-range", getPaymentsByAmountRange); // Retrieve payments by amount range
+router.get("/transaction/:transactionId", getPaymentByTransactionId); // Retrieve payment by transaction ID
+router.get("/count/status", countPaymentsByStatus); // Count payments by status
+
+module.exports = router;
diff --git a/backend/routes/sub-routes/supplierRoutes.js b/backend/routes/sub-routes/supplierRoutes.js
new file mode 100644
index 00000000..b0fd6295
--- /dev/null
+++ b/backend/routes/sub-routes/supplierRoutes.js
@@ -0,0 +1,50 @@
+const express = require("express");
+const router = express.Router();
+const supplierController = require("../controllers/supplierController");
+const productController = require("../controllers/productController");
+const supplierSearchController = require("../controllers/supplierSearchController");
+const supplierFilterController = require("../controllers/supplierFilterController");
+const validateSupplierData = require("../middlewares/validationMiddleware");
+const isAdmin = require("../middlewares/authMiddleware");
+
+// Routes for suppliers
+router.post(
+ "/api/suppliers",
+ isAdmin,
+ validateSupplierData,
+ supplierController.createSupplier
+); // Admin only
+router.get("/api/suppliers", supplierController.getAllSuppliers);
+router.get("/api/suppliers/:id", supplierController.getSupplierById);
+router.put(
+ "/api/suppliers/:id",
+ isAdmin,
+ validateSupplierData,
+ supplierController.updateSupplier
+); // Admin only
+router.delete("/api/suppliers/:id", isAdmin, supplierController.deleteSupplier); // Admin only
+
+// Routes for managing products supplied by a supplier
+router.post(
+ "/api/suppliers/:id/products",
+ isAdmin,
+ productController.addProductToSupplier
+); // Admin only
+router.delete(
+ "/api/suppliers/:id/products",
+ isAdmin,
+ productController.removeProductFromSupplier
+); // Admin only
+router.get(
+ "/api/suppliers/:id/products",
+ productController.getProductsSupplied
+);
+
+// Routes for searching and filtering suppliers
+router.get("/api/suppliers/search", supplierSearchController.searchSuppliers);
+router.get(
+ "/api/suppliers/status/:status",
+ supplierFilterController.getSuppliersByStatus
+);
+
+module.exports = router;
diff --git a/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx b/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx
index c35d0fc1..61dbc155 100644
--- a/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx
+++ b/frontend/src/AgroShopAI/components/Pages/Admin-Dashboard.jsx
@@ -5,6 +5,7 @@ import { DashboardStats } from "./components/DashboardStats";
import { useState } from "react";
import StatisticComponent from "./components/StatisticComponent";
import ReturnPanel from "./components/ReturnPage";
+import AdminProductManagement from "./ProductManagement";
export default function AdminDashboard() {
const [activeView, setActiveView] = useState("dashboard"); // Track active view
@@ -23,6 +24,7 @@ export default function AdminDashboard() {
{activeView === "grievances" &&
${product.price.toFixed(2)} - Stock: {product.stockQuantity}
+Product Management Dashboard
+Manage your products efficiently with AgroShop's powerful admin tools.
+{dummyData.clicks}
+{dummyData.signUps}
+{dummyData.conversions}
+${dummyData.commissions.toFixed(2)}
++ Partner with us to grow together in sustainable agriculture +
+Earn commissions, access exclusive materials, and help promote sustainable farming practices!
++ Become a partner with AgroShop and earn commissions by promoting our high-quality agricultural products. + Our program offers competitive rates and simple tools to help you maximize your earnings while supporting + sustainable agriculture. +
++ Have questions? Contact us for more information + about how the AgroShop Affiliate Program can work for you. +
++ Access a range of professional marketing tools designed to help you promote AgroShop and increase your earnings. + Use these assets to engage your audience and drive conversions. +
+Choose from a variety of banners tailored to promote AgroShop products effectively.
+ + +Use your unique referral link below to start earning commissions:
+Ready-to-post content for Facebook, Instagram, and Twitter.
+ +Engage your subscribers with pre-written, customizable email templates.
+ +Need custom materials? Contact our support team for assistance.
++ By joining the AgroShop Affiliate Program, you agree to the following terms and conditions: +
++ For any questions, please contact our affiliate support team. +
++ Discover the latest and most popular agricultural innovations! Stay + ahead with new technologies. +
+ + {/* Call to Action */} ++ ${product.price.toFixed(2)} +
+ + {/* Add to Cart Button */} + +