@@ -142,7 +162,7 @@ export default function Finish({user, scores, modules, isLoading, onViewResults}
{!isLoading && (
- {moduleResultText(calculateBandScore(selectedScore.correct, selectedScore.total, selectedModule, user.focus))}
+ {moduleResultText(selectedModule, bandScore)}
Level
-
- {calculateBandScore(selectedScore.correct, selectedScore.total, selectedModule, user.focus)}
-
+ {showLevel(bandScore)}
diff --git a/src/interfaces/paypal.ts b/src/interfaces/paypal.ts
index 56bf2688..3c1770b9 100644
--- a/src/interfaces/paypal.ts
+++ b/src/interfaces/paypal.ts
@@ -31,7 +31,7 @@ export interface Payment {
currency: string;
value: number;
isPaid: boolean;
- date: Date;
+ date: Date | string;
corporateTransfer?: string;
commissionTransfer?: string;
}
diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts
index 5594f273..cd337ac5 100644
--- a/src/interfaces/user.ts
+++ b/src/interfaces/user.ts
@@ -57,6 +57,7 @@ export interface CorporateInformation {
payment?: {
value: number;
currency: string;
+ commission: number;
};
referralAgent?: string;
}
diff --git a/src/pages/api/users/update.ts b/src/pages/api/users/update.ts
index a4f80fc8..315f84a1 100644
--- a/src/pages/api/users/update.ts
+++ b/src/pages/api/users/update.ts
@@ -1,19 +1,72 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app, storage} from "@/firebase";
-import {getFirestore, collection, getDocs, getDoc, doc, setDoc} from "firebase/firestore";
+import {getFirestore, collection, getDocs, getDoc, doc, setDoc, query, where} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {User} from "@/interfaces/user";
import {getDownloadURL, getStorage, ref, uploadBytes} from "firebase/storage";
import {getAuth, signInWithEmailAndPassword, updateEmail, updatePassword} from "firebase/auth";
import {errorMessages} from "@/constants/errors";
+import moment from "moment";
+import ShortUniqueId from "short-unique-id";
+import {Payment} from "@/interfaces/paypal";
const db = getFirestore(app);
const auth = getAuth(app);
export default withIronSessionApiRoute(handler, sessionOptions);
+// TODO: Data is set as any as data cannot be parsed to Payment
+// because the id is not a par of the hash and payment expects date to be of type Date
+// but if it is not inserted as a string, some UI components will not work (Invalid Date)
+const addPaymentRecord = async (data: any) => {
+ await setDoc(doc(db, "payments", data.id), data);
+}
+const managePaymentRecords = async (user: User, userId: string | undefined): Promise => {
+ try {
+ if(user.type === 'corporate' && userId) {
+ const shortUID = new ShortUniqueId();
+ const data: Payment = {
+ id: shortUID.randomUUID(8),
+ corporate: userId,
+ agent: user.corporateInformation.referralAgent,
+ agentCommission: user.corporateInformation.payment!.commission,
+ agentValue: (user.corporateInformation.payment!.commission / 100) * user.corporateInformation.payment!.value,
+ currency: user.corporateInformation.payment!.currency,
+ value: user.corporateInformation.payment!.value,
+ isPaid: false,
+ date: new Date().toISOString(),
+ };
+
+ const corporatePayments = await getDocs(query(collection(db, "payments"), where("corporate", "==", userId)));
+ if(corporatePayments.docs.length === 0) {
+ await addPaymentRecord(data);
+ return true;
+ }
+
+ const hasPaymentPaidAndExpiring = corporatePayments.docs.filter((doc) => {
+ const data = doc.data();
+ return data.isPaid
+ && moment().isAfter(moment(user.subscriptionExpirationDate).subtract(30, "days"))
+ && moment().isBefore(moment(user.subscriptionExpirationDate));
+ });
+
+ if(hasPaymentPaidAndExpiring.length > 0) {
+ await addPaymentRecord(data);
+ return true;
+ }
+ }
+
+ return false;
+ } catch(e) {
+ // if this process fails it should not stop the rest of the process
+ console.log(e);
+ return false;
+ }
+
+}
+
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
res.status(401).json({ok: false});
@@ -24,7 +77,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const updatedUser = req.body as User & {password?: string; newPassword?: string};
if (!!req.query.id) {
- await setDoc(userRef, updatedUser, {merge: true});
+ const user = await setDoc(userRef, updatedUser, {merge: true});
+ await managePaymentRecords(updatedUser, updatedUser.id);
res.status(200).json({ok: true});
return;
}
@@ -73,6 +127,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
await req.session.save();
}
+ await managePaymentRecords(user, req.query.id);
+
res.status(200).json({user});
}
diff --git a/src/utils/score.ts b/src/utils/score.ts
index 18a13c63..08707312 100644
--- a/src/utils/score.ts
+++ b/src/utils/score.ts
@@ -1,4 +1,5 @@
import {Module} from "@/interfaces";
+import { LevelScore } from "@/constants/ielts";
type Type = "academic" | "general";
@@ -94,11 +95,12 @@ const academicMarking: {[key: number]: number} = {
};
const levelMarking: {[key: number]: number} = {
- 88: 9,
- 64: 8,
- 52: 6,
- 32: 4,
- 16: 2,
+ 88: 9, // Advanced
+ 64: 8 , // Upper-Intermediate
+ 52: 6, // Intermediate
+ 32: 4, // Pre-Intermediate
+ 16: 2, // Elementary
+ 0: 0, // Beginner
};
const moduleMarkings: {[key in Module]: {[key in Type]: {[key: number]: number}}} = {
@@ -142,3 +144,21 @@ export const calculateBandScore = (correct: number, total: number, module: Modul
export const calculateAverageLevel = (levels: {[key in Module]: number}) => {
return Object.keys(levels).reduce((accumulator, current) => levels[current as Module] + accumulator, 0) / 4;
};
+
+export const getLevelScore = (level: number) => {
+ switch(level) {
+ case 0:
+ return ['Beginner', 'Low A1'];
+ case 2:
+ return ['Elementary', 'High A1/Low A2'];
+ case 4:
+ return ['Pre-Intermediate', 'High A2/Low B1'];
+ case 6:
+ return ['Intermediate', 'High B1/Low B2'];
+ case 8:
+ return ['Upper-Intermediate', 'High B2/Low C1'];
+ case 9:
+ return ['Advanced', 'C1'];
+ default: return [];
+ }
+}
\ No newline at end of file