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/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/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/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/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;