Skip to content

Commit 21c0284

Browse files
authored
Emily/20250104 handle membership payment confirmation (#1993)
* initial commit * fixed spacing * fixed spacing 2 * fixed spacing 2 * updated logic and merged find and Verify functions * fix spacing * refactor: improve payment verification and rejection logic * fix * refactor: improve error handling in membership payment verification and rejection * fix * final fixes * final fixes * refactored updateMembershipExpiration * fix spacing
1 parent 56ca2bb commit 21c0284

3 files changed

Lines changed: 158 additions & 0 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const express = require('express');
2+
const router = express.Router();
3+
const bodyParser = require('body-parser');
4+
router.use(bodyParser.json());
5+
const {
6+
BAD_REQUEST,
7+
SERVER_ERROR,
8+
NOT_FOUND,
9+
OK,
10+
} = require('../../util/constants').STATUS_CODES;
11+
const membershipState = require('../../util/constants').MEMBERSHIP_STATE;
12+
const User = require('../models/User');
13+
const { getMemberExpirationDate, updateMembershipExpiration } = require('../util/userHelpers');
14+
const { findVerifyPayment, rejectPayment } = require('../util/membershipPaymentQueries');
15+
const { decodeToken } = require('../util/token-functions.js');
16+
17+
router.post('/verifyMembership', async (req, res) => {
18+
const decoded = await decodeToken(req, membershipState.PENDING);
19+
if (decoded.status !== OK) {
20+
return res.sendStatus(decoded.status);
21+
}
22+
23+
const { confirmationCode } = req.body;
24+
const userId = decoded.token._id;
25+
26+
if (!confirmationCode) {
27+
return res.sendStatus(BAD_REQUEST);
28+
}
29+
30+
const paymentDocument = await findVerifyPayment(confirmationCode, userId);
31+
if (paymentDocument === null){
32+
return res.sendStatus(SERVER_ERROR);
33+
}
34+
if (paymentDocument === false){
35+
return res.sendStatus(NOT_FOUND);
36+
}
37+
38+
const paymentId = paymentDocument._id;
39+
const { amount } = paymentDocument;
40+
41+
if (amount < 20){
42+
const rejected = await rejectPayment(paymentId);
43+
if (rejected === null){
44+
return res.sendStatus(SERVER_ERROR);
45+
}
46+
if (rejected === false){
47+
return res.sendStatus(NOT_FOUND);
48+
}
49+
return res.sendStatus(BAD_REQUEST);
50+
}
51+
52+
let semestersToAdd = 0;
53+
if (amount >= 30) {
54+
semestersToAdd = 2;
55+
} else {
56+
semestersToAdd = 1;
57+
}
58+
59+
const membershipUpdateResult = await updateMembershipExpiration(
60+
decoded.token._id,
61+
semestersToAdd
62+
);
63+
64+
if (membershipUpdateResult === null) {
65+
return res.sendStatus(SERVER_ERROR);
66+
}
67+
if (membershipUpdateResult === false) {
68+
return res.status(NOT_FOUND).send('User not found.');
69+
}
70+
return res.sendStatus(OK);
71+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import MembershipPayment from '../main_endpoints/models/MembershipPayment.js';
2+
3+
const status = {
4+
PENDING: 'pending',
5+
COMPLETED: 'completed',
6+
REJECTED: 'rejected',
7+
};
8+
9+
function findVerifyPayment(confirmationCode, userId) {
10+
return new Promise((resolve) => {
11+
try {
12+
MembershipPayment.findOneAndUpdate(
13+
{
14+
confirmationCode,
15+
status: status.PENDING,
16+
},
17+
{
18+
$set: { userId, status: status.COMPLETED },
19+
},
20+
{
21+
new: true,
22+
runValidators: true,
23+
},
24+
(error, result) => {
25+
if (error) {
26+
return resolve(null);
27+
}
28+
if (!result) {
29+
return resolve(false);
30+
}
31+
return resolve(result);
32+
}
33+
);
34+
} catch (error) {
35+
return resolve(null);
36+
}
37+
});
38+
}
39+
40+
function rejectPayment(paymentId) {
41+
return new Promise((resolve) => {
42+
try {
43+
MembershipPayment.findByIdAndUpdate(
44+
paymentId,
45+
{ $set: { status: status.REJECTED } },
46+
(error, result) => {
47+
if (error) {
48+
return resolve(null);
49+
}
50+
if (!result) {
51+
return resolve(false);
52+
}
53+
return resolve(true);
54+
}
55+
);
56+
} catch (error) {
57+
return resolve(null);
58+
}
59+
});
60+
}
61+
62+
module.exports = { findVerifyPayment, rejectPayment };

api/main_endpoints/util/userHelpers.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,30 @@ function checkIfPageCountResets(lastLogin) {
203203
return lastLoginWasOverOneWeekAgo || aSundayHasPassedSinceLastLogin;
204204
}
205205

206+
/**
207+
* Update a user's membershipValidUntil date
208+
* @param {String} userId - The user's ID
209+
* @param {Number} numberOfSemestersToSignUpFor - Number of semesters to extend
210+
* @returns {Object} result - Contains success status and message
211+
*/
212+
async function updateMembershipExpiration(userId, numberOfSemestersToSignUpFor) {
213+
try {
214+
const newExpiration = getMemberExpirationDate(numberOfSemestersToSignUpFor);
215+
const user = await User.findByIdAndUpdate(
216+
userId,
217+
{ membershipValidUntil: newExpiration },
218+
{ new: true },
219+
);
220+
if (!user) {
221+
return false;
222+
}
223+
return true;
224+
} catch (error) {
225+
logger.error('Error updating membership:', error);
226+
return null;
227+
}
228+
}
229+
206230
module.exports = {
207231
registerUser,
208232
getMemberExpirationDate,
@@ -211,4 +235,5 @@ module.exports = {
211235
userWithEmailExists,
212236
checkIfPageCountResets,
213237
findPasswordReset,
238+
updateMembershipExpiration
214239
};

0 commit comments

Comments
 (0)