-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
264 changes: 264 additions & 0 deletions
264
backend/controllers/shop/sub-controllers/loyaltyPointsController.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,264 @@ | ||
const LoyaltyPoint = require("../../../model/shop/sub-model/loyaltyPointModel"); | ||
const User = require("../../../model/user"); | ||
|
||
// Award points to a user | ||
exports.awardPoints = async (req, res) => { | ||
try { | ||
const { userId, points, earnedBy } = req.body; | ||
|
||
const user = await User.findById(userId); | ||
if (!user) return res.status(404).json({ message: "User not found" }); | ||
|
||
const newPoints = new LoyaltyPoint({ userId, points, earnedBy }); | ||
await newPoints.save(); | ||
|
||
user.loyaltyPoints += points; | ||
await user.save(); | ||
|
||
res | ||
.status(200) | ||
.json({ message: "Points awarded successfully", points: newPoints }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Get a user's loyalty points balance | ||
exports.getPoints = async (req, res) => { | ||
try { | ||
const { userId } = req.params; | ||
|
||
const points = await LoyaltyPoint.aggregate([ | ||
{ $match: { userId: mongoose.Types.ObjectId(userId) } }, | ||
{ $group: { _id: "$userId", totalPoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
if (!points.length) | ||
return res.status(404).json({ message: "No points found for this user" }); | ||
|
||
res.status(200).json({ totalPoints: points[0].totalPoints }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Get transaction history of loyalty points | ||
exports.getTransactionHistory = async (req, res) => { | ||
try { | ||
const { userId } = req.params; | ||
|
||
const transactions = await LoyaltyPoint.find({ userId }).sort({ | ||
timestamp: -1, | ||
}); | ||
|
||
if (!transactions.length) | ||
return res | ||
.status(404) | ||
.json({ message: "No transaction history found for this user" }); | ||
|
||
res.status(200).json({ transactions }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Delete a specific loyalty point entry | ||
exports.deletePoints = async (req, res) => { | ||
try { | ||
const { transactionId } = req.params; | ||
|
||
const deletedTransaction = await LoyaltyPoint.findByIdAndDelete( | ||
transactionId | ||
); | ||
if (!deletedTransaction) | ||
return res.status(404).json({ message: "Transaction not found" }); | ||
|
||
res | ||
.status(200) | ||
.json({ | ||
message: "Loyalty points transaction deleted", | ||
transaction: deletedTransaction, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Update a specific loyalty point transaction | ||
exports.updatePoints = async (req, res) => { | ||
try { | ||
const { transactionId } = req.params; | ||
const { points, earnedBy } = req.body; | ||
|
||
const updatedTransaction = await LoyaltyPoint.findByIdAndUpdate( | ||
transactionId, | ||
{ points, earnedBy }, | ||
{ new: true } | ||
); | ||
|
||
if (!updatedTransaction) | ||
return res.status(404).json({ message: "Transaction not found" }); | ||
|
||
res | ||
.status(200) | ||
.json({ | ||
message: "Loyalty points transaction updated", | ||
transaction: updatedTransaction, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Filter transactions by earning type (e.g., 'purchase', 'referral') | ||
exports.filterTransactionsByType = async (req, res) => { | ||
try { | ||
const { userId } = req.params; | ||
const { type } = req.query; | ||
|
||
const transactions = await LoyaltyPoint.find({ userId, earnedBy: type }); | ||
|
||
if (!transactions.length) | ||
return res | ||
.status(404) | ||
.json({ message: `No transactions found for ${type}` }); | ||
|
||
res.status(200).json({ transactions }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Get total points earned by referral actions | ||
exports.getPointsByReferrals = async (req, res) => { | ||
try { | ||
const { userId } = req.params; | ||
|
||
const referralPoints = await LoyaltyPoint.aggregate([ | ||
{ | ||
$match: { | ||
userId: mongoose.Types.ObjectId(userId), | ||
earnedBy: "referral", | ||
}, | ||
}, | ||
{ $group: { _id: "$userId", totalReferralPoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
if (!referralPoints.length) | ||
return res | ||
.status(404) | ||
.json({ message: "No referral points found for this user" }); | ||
|
||
res | ||
.status(200) | ||
.json({ totalReferralPoints: referralPoints[0].totalReferralPoints }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Get total points earned by purchase actions | ||
exports.getPointsByPurchases = async (req, res) => { | ||
try { | ||
const { userId } = req.params; | ||
|
||
const purchasePoints = await LoyaltyPoint.aggregate([ | ||
{ | ||
$match: { | ||
userId: mongoose.Types.ObjectId(userId), | ||
earnedBy: "purchase", | ||
}, | ||
}, | ||
{ $group: { _id: "$userId", totalPurchasePoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
if (!purchasePoints.length) | ||
return res | ||
.status(404) | ||
.json({ message: "No purchase points found for this user" }); | ||
|
||
res | ||
.status(200) | ||
.json({ totalPurchasePoints: purchasePoints[0].totalPurchasePoints }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Redeem points (reduce points based on redemption) | ||
exports.redeemPoints = async (req, res) => { | ||
try { | ||
const { userId, pointsToRedeem } = req.body; | ||
|
||
const user = await User.findById(userId); | ||
if (!user) return res.status(404).json({ message: "User not found" }); | ||
|
||
const totalPoints = await LoyaltyPoint.aggregate([ | ||
{ $match: { userId: mongoose.Types.ObjectId(userId) } }, | ||
{ $group: { _id: "$userId", totalPoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
if (totalPoints[0].totalPoints < pointsToRedeem) { | ||
return res | ||
.status(400) | ||
.json({ message: "Insufficient points for redemption" }); | ||
} | ||
|
||
const redemption = new LoyaltyPoint({ | ||
userId, | ||
points: -pointsToRedeem, | ||
earnedBy: "redemption", | ||
}); | ||
await redemption.save(); | ||
|
||
res | ||
.status(200) | ||
.json({ message: "Points redeemed successfully", redemption }); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; | ||
|
||
// Calculate loyalty point summary (overall breakdown) | ||
exports.getLoyaltySummary = async (req, res) => { | ||
try { | ||
const { userId } = req.params; | ||
|
||
const totalPoints = await LoyaltyPoint.aggregate([ | ||
{ $match: { userId: mongoose.Types.ObjectId(userId) } }, | ||
{ $group: { _id: "$userId", totalPoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
const referralPoints = await LoyaltyPoint.aggregate([ | ||
{ | ||
$match: { | ||
userId: mongoose.Types.ObjectId(userId), | ||
earnedBy: "referral", | ||
}, | ||
}, | ||
{ $group: { _id: "$userId", totalReferralPoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
const purchasePoints = await LoyaltyPoint.aggregate([ | ||
{ | ||
$match: { | ||
userId: mongoose.Types.ObjectId(userId), | ||
earnedBy: "purchase", | ||
}, | ||
}, | ||
{ $group: { _id: "$userId", totalPurchasePoints: { $sum: "$points" } } }, | ||
]); | ||
|
||
res.status(200).json({ | ||
totalPoints: totalPoints.length ? totalPoints[0].totalPoints : 0, | ||
referralPoints: referralPoints.length | ||
? referralPoints[0].totalReferralPoints | ||
: 0, | ||
purchasePoints: purchasePoints.length | ||
? purchasePoints[0].totalPurchasePoints | ||
: 0, | ||
}); | ||
} catch (error) { | ||
res.status(500).json({ message: "Server error", error }); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const mongoose = require("mongoose"); | ||
|
||
const loyaltyPointSchema = new mongoose.Schema({ | ||
userId: { | ||
type: mongoose.Schema.Types.ObjectId, | ||
required: true, | ||
ref: "User", | ||
}, | ||
points: { | ||
type: Number, | ||
required: true, | ||
default: 0, | ||
}, | ||
earnedBy: { | ||
type: String, | ||
enum: ["purchase", "referral"], | ||
required: true, | ||
}, | ||
timestamp: { | ||
type: Date, | ||
default: Date.now, | ||
}, | ||
}); | ||
|
||
module.exports = mongoose.model("LoyaltyPoint", loyaltyPointSchema); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const express = require("express"); | ||
const loyaltyPointsController = require("../../controllers/shop/sub-controllers/loyaltyPointsController"); | ||
const authMiddleware = require("../middleware/authMiddleware"); // Middleware to check valid user | ||
|
||
const router = express.Router(); | ||
|
||
// Route to award points to a user | ||
router.post( | ||
"/api/loyalty-points", | ||
authMiddleware, | ||
loyaltyPointsController.awardPoints | ||
); | ||
|
||
// Route to get a user's total loyalty points | ||
router.get( | ||
"/api/loyalty-points/:userId", | ||
authMiddleware, | ||
loyaltyPointsController.getPoints | ||
); | ||
|
||
// Route to get a user's transaction history of loyalty points | ||
router.get( | ||
"/api/loyalty-points/:userId/history", | ||
authMiddleware, | ||
loyaltyPointsController.getTransactionHistory | ||
); | ||
|
||
// Route to delete a specific loyalty points transaction | ||
router.delete( | ||
"/api/loyalty-points/:transactionId", | ||
authMiddleware, | ||
loyaltyPointsController.deletePoints | ||
); | ||
|
||
// Route to update a specific loyalty points transaction | ||
router.put( | ||
"/api/loyalty-points/:transactionId", | ||
authMiddleware, | ||
loyaltyPointsController.updatePoints | ||
); | ||
|
||
// Route to filter transactions by type (e.g., 'purchase', 'referral') | ||
router.get( | ||
"/api/loyalty-points/:userId/filter", | ||
authMiddleware, | ||
loyaltyPointsController.filterTransactionsByType | ||
); | ||
|
||
// Route to get total points earned through referrals | ||
router.get( | ||
"/api/loyalty-points/:userId/referrals", | ||
authMiddleware, | ||
loyaltyPointsController.getPointsByReferrals | ||
); | ||
|
||
// Route to get total points earned through purchases | ||
router.get( | ||
"/api/loyalty-points/:userId/purchases", | ||
authMiddleware, | ||
loyaltyPointsController.getPointsByPurchases | ||
); | ||
|
||
// Route to redeem points | ||
router.post( | ||
"/api/loyalty-points/redeem", | ||
authMiddleware, | ||
loyaltyPointsController.redeemPoints | ||
); | ||
|
||
// Route to get loyalty points summary (overall points, referral points, and purchase points) | ||
router.get( | ||
"/api/loyalty-points/:userId/summary", | ||
authMiddleware, | ||
loyaltyPointsController.getLoyaltySummary | ||
); | ||
|
||
module.exports = router; |