diff --git a/backend/controllers/transaction.js b/backend/controllers/transaction.js index ace31bb..1c0fe58 100644 --- a/backend/controllers/transaction.js +++ b/backend/controllers/transaction.js @@ -6,16 +6,16 @@ exports.getTransactionWithPagination = async (req, res) => { const offset = (page - 1) * limit; try { const [data, _] = await db.execute( - `SELECT T.TransactionID, DATE_FORMAT(T.Date, '%b-%d-%Y %h:%i %p') as Date, T.PaymentStatus, U.Name as UserName, P.Name as ProductName + `SELECT T.TransactionID, DATE_FORMAT(T.Date, '%b-%d-%Y %h:%i %p') as Date, T.PaymentStatus, U.Name as UserName, P.Name as ProductName FROM Transaction T LEFT JOIN User U ON T.UserID = U.UserID LEFT JOIN Product P ON T.ProductID = P.ProductID ORDER BY T.TransactionID ASC LIMIT ? OFFSET ?`, - [limit.toString(), offset.toString()] + [limit.toString(), offset.toString()], ); const [result] = await db.execute( - "SELECT COUNT(*) AS count FROM Transaction" + "SELECT COUNT(*) AS count FROM Transaction", ); const { count: total } = result[0]; return res.json({ data, total }); @@ -29,7 +29,7 @@ exports.removeTransation = async (req, res) => { try { const [result] = await db.execute( "DELETE FROM Transaction WHERE TransactionID = ?;", - [id.toString()] + [id.toString()], ); return res.json({ message: "Remove transaction successfully!" }); } catch (error) { @@ -38,3 +38,188 @@ exports.removeTransation = async (req, res) => { .json({ error: "Cannot remove transactions from database!" }); } }; +// Create a new transaction +exports.createTransaction = async (req, res) => { + const { userID, productID, date, paymentStatus } = req.body; + + try { + // Check if the transaction already exists for the same user and product + const [existingTransaction] = await db.execute( + `SELECT TransactionID FROM Transaction WHERE UserID = ? AND ProductID = ?`, + [userID, productID], + ); + + if (existingTransaction.length > 0) { + return res.status(400).json({ + success: false, + message: "Transaction already exists for this user and product", + }); + } + + // Format the date + const formattedDate = new Date(date) + .toISOString() + .slice(0, 19) + .replace("T", " "); + + // Insert the new transaction + const [result] = await db.execute( + `INSERT INTO Transaction (UserID, ProductID, Date, PaymentStatus) + VALUES (?, ?, ?, ?)`, + [userID, productID, formattedDate, paymentStatus], + ); + + res.json({ + success: true, + message: "Transaction created successfully", + transactionID: result.insertId, + }); + } catch (error) { + console.error("Error creating transaction:", error); + res.status(500).json({ error: "Could not create transaction" }); + } +}; + +// Get all transactions for a given product +exports.getTransactionsByProduct = async (req, res) => { + const { productID } = req.params; + + try { + const [transactions] = await db.execute( + `SELECT + T.TransactionID, + T.UserID, + T.ProductID, + T.Date, + T.PaymentStatus, + P.Name AS ProductName, + MIN(I.URL) AS Image_URL + FROM Transaction T + JOIN Product P ON T.ProductID = P.ProductID + LEFT JOIN Image_URL I ON P.ProductID = I.ProductID + GROUP BY T.TransactionID, T.UserID, T.ProductID, T.Date, T.PaymentStatus, P.Name`, + ); + + res.json({ + success: true, + transactions, + }); + } catch (error) { + console.error("Error fetching transactions by product:", error); + res.status(500).json({ error: "Could not retrieve transactions" }); + } +}; + +// Get all transactions for a given user +exports.getTransactionsByUser = async (req, res) => { + const { userID } = req.body; + + try { + const [transactions] = await db.execute( + `SELECT + T.TransactionID, + T.UserID, + T.ProductID, + T.Date, + T.PaymentStatus, + P.Name AS ProductName, + I.URL AS Image_URL + FROM Transaction T + JOIN Product P ON T.ProductID = P.ProductID + LEFT JOIN Image_URL I ON P.ProductID = I.ProductID + WHERE T.UserID = ?`, + [userID], + ); + + res.json({ + success: true, + transactions, + }); + } catch (error) { + console.error("Error fetching transactions by user:", error); + res.status(500).json({ error: "Could not retrieve transactions" }); + } +}; + +// Get all transactions in the system +exports.getAllTransactions = async (req, res) => { + try { + const [transactions] = await db.execute( + `SELECT + T.TransactionID, + T.UserID, + T.ProductID, + T.Date, + T.PaymentStatus, + P.Name AS ProductName, + MIN(I.URL) AS Image_URL + FROM Transaction T + JOIN Product P ON T.ProductID = P.ProductID + LEFT JOIN Image_URL I ON P.ProductID = I.ProductID + GROUP BY T.TransactionID, T.UserID, T.ProductID, T.Date, T.PaymentStatus, P.Name`, + ); + + res.json({ + success: true, + transactions, + }); + } catch (error) { + console.error("Error fetching all transactions:", error); + res.status(500).json({ error: "Could not retrieve transactions" }); + } +}; + +// Update the payment status of a transaction +exports.updatePaymentStatus = async (req, res) => { + const { transactionID, paymentStatus } = req.body; + + try { + const [result] = await db.execute( + `UPDATE Transaction + SET PaymentStatus = ? + WHERE TransactionID = ?`, + [paymentStatus, transactionID], + ); + + if (result.affectedRows === 0) { + return res + .status(404) + .json({ success: false, message: "Transaction not found" }); + } + + res.json({ + success: true, + message: "Payment status updated successfully", + }); + } catch (error) { + console.error("Error updating payment status:", error); + res.status(500).json({ error: "Could not update payment status" }); + } +}; + +// Delete a transaction +exports.deleteTransaction = async (req, res) => { + const { transactionID } = req.body; + + try { + const [result] = await db.execute( + `DELETE FROM Transaction + WHERE TransactionID = ?`, + [transactionID], + ); + + if (result.affectedRows === 0) { + return res + .status(404) + .json({ success: false, message: "Transaction not found" }); + } + + res.json({ + success: true, + message: "Transaction deleted successfully", + }); + } catch (error) { + console.error("Error deleting transaction:", error); + res.status(500).json({ error: "Could not delete transaction" }); + } +}; diff --git a/backend/index.js b/backend/index.js index b06f1fc..08d260d 100644 --- a/backend/index.js +++ b/backend/index.js @@ -9,7 +9,9 @@ const searchRouter = require("./routes/search"); const recommendedRouter = require("./routes/recommendation"); const history = require("./routes/history"); const review = require("./routes/review"); + const categoryRouter = require("./routes/category"); + const transactionRouter = require("./routes/transaction"); const { generateEmailTransporter } = require("./utils/mail"); @@ -44,9 +46,9 @@ app.use("/api/search", searchRouter); app.use("/api/engine", recommendedRouter); app.use("/api/history", history); app.use("/api/review", review); -app.use("/api/category", categoryRouter); app.use("/api/transaction", transactionRouter); app.use("/api/category", categoryRouter); +app.use("/api/transaction", transactionRouter); // Set up a scheduler to run cleanup every hour clean_up_time = 30 * 60 * 1000; diff --git a/backend/routes/transaction.js b/backend/routes/transaction.js index 0788b96..c29611e 100644 --- a/backend/routes/transaction.js +++ b/backend/routes/transaction.js @@ -1,11 +1,39 @@ +// routes/transaction.js const express = require("express"); const { - getTransactionWithPagination, - removeTransation, + createTransaction, + getTransactionsByProduct, + getTransactionsByUser, + getAllTransactions, + updatePaymentStatus, + deleteTransaction, } = require("../controllers/transaction"); - const router = express.Router(); +// logging middleware +router.use((req, res, next) => { + console.log(`Incoming ${req.method} ${req.originalUrl}`); + next(); +}); + +// Create a new transaction +router.post("/createTransaction", createTransaction); + +// Get all transactions for a specific product +router.get("/getTransactionsByProduct/:productID", getTransactionsByProduct); + +// Get all transactions for a specific user +router.post("/getTransactionsByUser", getTransactionsByUser); + +// Get all transactions in the system +router.post("/getAllTransactions", getAllTransactions); + +// Update payment status on a transaction +router.patch("/updatePaymentStatus", updatePaymentStatus); + +// Delete a transaction +router.delete("/deleteTransaction", deleteTransaction); + router.get("/getTransactions", getTransactionWithPagination); router.delete("/:id", removeTransation); diff --git a/backend/utils/database.js b/backend/utils/database.js index 379d5df..7e9a4c9 100644 --- a/backend/utils/database.js +++ b/backend/utils/database.js @@ -4,6 +4,7 @@ const pool = mysql.createPool({ host: "localhost", user: "root", database: "Marketplace", + password: "12345678" }); // const pool = mysql.createPool( diff --git a/backend/utils/helper.js b/backend/utils/helper.js index 406a897..1d39b48 100644 --- a/backend/utils/helper.js +++ b/backend/utils/helper.js @@ -18,7 +18,7 @@ async function sendVerificationEmail(email, verificationCode) { // Clean up expired verification codes (run this periodically) function cleanupExpiredCodes() { - db_con.query( + db.query( "DELETE FROM AuthVerification WHERE Date < DATE_SUB(NOW(), INTERVAL 15 MINUTE) AND Authenticated = 0", (err, result) => { if (err) { diff --git a/frontend/src/pages/ProductDetail.jsx b/frontend/src/pages/ProductDetail.jsx index ebec8f2..e5b1143 100644 --- a/frontend/src/pages/ProductDetail.jsx +++ b/frontend/src/pages/ProductDetail.jsx @@ -414,8 +414,45 @@ const ProductDetail = () => {
+ Once transactions are created, they’ll appear here. +
+ + Browse Listings + ++ ${tx.price.toFixed(2)} +
+ )} ++ Status: {tx.status} +
+