Skip to content
Open
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
41 changes: 41 additions & 0 deletions api/main_endpoints/models/MembershipPayment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const mongoose = require('mongoose');
const Schema = mongoose.Schema;


const MembershipPaymentSchema = new Schema(
{
createdAt: {
type: Date,
default: Date.now
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
default: null,
},
status: {
type: String,
enum: ['pending', 'completed', 'rejected'],
default: 'pending',
required: true,
},
confirmationCode: {
type: String,
unique: true,
required: true,
},
amount: {
type: Number,
required: true,
},
venmoDetails:{
transactionId: { type: String },
payerName: { type: String },
note: { type: String },
}
},
{ collection: 'MembershipPayments' }
);


module.exports = mongoose.model('MembershipPayment', MembershipPaymentSchema);
71 changes: 71 additions & 0 deletions api/main_endpoints/routes/MembershipPayment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser');
router.use(bodyParser.json());
const {
BAD_REQUEST,
SERVER_ERROR,
NOT_FOUND,
OK,
} = require('../../util/constants').STATUS_CODES;
const membershipState = require('../../util/constants').MEMBERSHIP_STATE;
const User = require('../models/User');
const { getMemberExpirationDate, updateMembershipExpiration } = require('../util/userHelpers');
const { findVerifyPayment, rejectPayment } = require('../util/membershipPaymentQueries');
const { decodeToken } = require('../util/token-functions.js');

router.post('/verifyMembership', async (req, res) => {
const decoded = await decodeToken(req, membershipState.PENDING);
if (decoded.status !== OK) {
return res.sendStatus(decoded.status);
}

const { confirmationCode } = req.body;
const userId = decoded.token._id;

if (!confirmationCode) {
return res.sendStatus(BAD_REQUEST);
}

const paymentDocument = await findVerifyPayment(confirmationCode, userId);
if (paymentDocument === null){
return res.sendStatus(SERVER_ERROR);
}
if (paymentDocument === false){
return res.sendStatus(NOT_FOUND);
}

const paymentId = paymentDocument._id;
const { amount } = paymentDocument;

if (amount < 20){
const rejected = await rejectPayment(paymentId);
if (rejected === null){
return res.sendStatus(SERVER_ERROR);
}
if (rejected === false){
return res.sendStatus(NOT_FOUND);
}
return res.sendStatus(BAD_REQUEST);
}

let semestersToAdd = 0;
if (amount >= 30) {
semestersToAdd = 2;
} else {
semestersToAdd = 1;
}

const membershipUpdateResult = await updateMembershipExpiration(
decoded.token._id,
semestersToAdd
);

if (membershipUpdateResult === null) {
return res.sendStatus(SERVER_ERROR);
}
if (membershipUpdateResult === false) {
return res.status(NOT_FOUND).send('User not found.');
}
return res.sendStatus(OK);
});
62 changes: 62 additions & 0 deletions api/main_endpoints/util/membershipPaymentQueries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import MembershipPayment from '../main_endpoints/models/MembershipPayment.js';

const status = {
PENDING: 'pending',
COMPLETED: 'completed',
REJECTED: 'rejected',
};

function findVerifyPayment(confirmationCode, userId) {
return new Promise((resolve) => {
try {
MembershipPayment.findOneAndUpdate(
{
confirmationCode,
status: status.PENDING,
},
{
$set: { userId, status: status.COMPLETED },
},
{
new: true,
runValidators: true,
},
(error, result) => {
if (error) {
return resolve(null);
}
if (!result) {
return resolve(false);
}
return resolve(result);
}
);
} catch (error) {
return resolve(null);
}
});
}

function rejectPayment(paymentId) {
return new Promise((resolve) => {
try {
MembershipPayment.findByIdAndUpdate(
paymentId,
{ $set: { status: status.REJECTED } },
(error, result) => {
if (error) {
return resolve(null);
}
if (!result) {
return resolve(false);
}
return resolve(true);
}
);
} catch (error) {
return resolve(null);
}
});
}

module.exports = { findVerifyPayment, rejectPayment };
25 changes: 25 additions & 0 deletions api/main_endpoints/util/userHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,30 @@ function checkIfPageCountResets(lastLogin) {
return lastLoginWasOverOneWeekAgo || aSundayHasPassedSinceLastLogin;
}

/**
* Update a user's membershipValidUntil date
* @param {String} userId - The user's ID
* @param {Number} numberOfSemestersToSignUpFor - Number of semesters to extend
* @returns {Object} result - Contains success status and message
*/
async function updateMembershipExpiration(userId, numberOfSemestersToSignUpFor) {
try {
const newExpiration = getMemberExpirationDate(numberOfSemestersToSignUpFor);
const user = await User.findByIdAndUpdate(
userId,
{ membershipValidUntil: newExpiration },
{ new: true },
);
if (!user) {
return false;
}
return true;
} catch (error) {
logger.error('Error updating membership:', error);
return null;
}
}

module.exports = {
registerUser,
getMemberExpirationDate,
Expand All @@ -211,4 +235,5 @@ module.exports = {
userWithEmailExists,
checkIfPageCountResets,
findPasswordReset,
updateMembershipExpiration
};