Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Payment Schema, Controllers, and Admin-Restricted Management Routes for Backend #954

Merged
merged 1 commit into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions backend/controllers/shop/sub-controllers/adminController.js
Original file line number Diff line number Diff line change
@@ -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 };
161 changes: 161 additions & 0 deletions backend/controllers/shop/sub-controllers/paymentController.js
Original file line number Diff line number Diff line change
@@ -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,
};
25 changes: 25 additions & 0 deletions backend/middleware/sub-ware/validatePaymentInvoice.js
Original file line number Diff line number Diff line change
@@ -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 };
34 changes: 34 additions & 0 deletions backend/model/shop/sub-model/payment.js
Original file line number Diff line number Diff line change
@@ -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;
34 changes: 34 additions & 0 deletions backend/routes/sub-routes/paymentRoutes.js
Original file line number Diff line number Diff line change
@@ -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;
Loading