Updated the propagated changes to also affect expiry date changes for corporates

This commit is contained in:
Tiago Ribeiro
2024-05-07 23:53:15 +01:00
parent ed0b8bcb99
commit 72fb934d4f
2 changed files with 115 additions and 80 deletions

View File

@@ -12,7 +12,7 @@ import moment from "moment";
import ShortUniqueId from "short-unique-id"; import ShortUniqueId from "short-unique-id";
import {Payment} from "@/interfaces/paypal"; import {Payment} from "@/interfaces/paypal";
import {toFixedNumber} from "@/utils/number"; import {toFixedNumber} from "@/utils/number";
import {propagateStatusChange} from "@/utils/propagate.user.changes"; import {propagateExpiryDateChanges, propagateStatusChange} from "@/utils/propagate.user.changes";
const db = getFirestore(app); const db = getFirestore(app);
const auth = getAuth(app); const auth = getAuth(app);
@@ -79,15 +79,18 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const queryId = req.query.id as string; const queryId = req.query.id as string;
const userRef = doc(db, "users", queryId ? (queryId as string) : req.session.user.id); const userRef = doc(db, "users", queryId ? (queryId as string) : req.session.user.id);
const userSnapshot = await getDoc(userRef);
const updatedUser = req.body as User & {password?: string; newPassword?: string}; const updatedUser = req.body as User & {password?: string; newPassword?: string};
if (!!queryId) { if (!!queryId) {
const user = await setDoc(userRef, updatedUser, {merge: true}); await setDoc(userRef, updatedUser, {merge: true});
await managePaymentRecords(updatedUser, updatedUser.id); await managePaymentRecords(updatedUser, updatedUser.id);
const user = {...userSnapshot.data(), id: userSnapshot.id} as User;
if (updatedUser.status || updatedUser.type === "corporate") { if (updatedUser.status || updatedUser.type === "corporate") {
// there's no await as this does not affect the user // there's no await as this does not affect the user
propagateStatusChange(queryId, updatedUser.status); propagateStatusChange(queryId, updatedUser.status);
propagateExpiryDateChanges(queryId, user.subscriptionExpirationDate || null, updatedUser.subscriptionExpirationDate || null);
} }
res.status(200).json({ok: true}); res.status(200).json({ok: true});

View File

@@ -1,92 +1,124 @@
// updating specific user changes other users // updating specific user changes other users
// for example, updating the status of a corporate user should update the status of all users in the same corporate group // for example, updating the status of a corporate user should update the status of all users in the same corporate group
import { UserStatus, User } from "../interfaces/user"; import {UserStatus, User} from "../interfaces/user";
import { import {getFirestore, collection, getDocs, getDoc, doc, setDoc, query, where} from "firebase/firestore";
getFirestore, import {app} from "@/firebase";
collection,
getDocs,
getDoc,
doc,
setDoc,
query,
where,
} from "firebase/firestore";
import { app } from "@/firebase";
const db = getFirestore(app); const db = getFirestore(app);
export const propagateStatusChange = (userId: string, status: UserStatus) => export const propagateStatusChange = (userId: string, status: UserStatus) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
getDoc(doc(db, "users", userId)) getDoc(doc(db, "users", userId))
.then((docUser) => { .then((docUser) => {
const user = docUser.data() as User; const user = docUser.data() as User;
// only update the status of the user's groups if the user is a corporate user // only update the status of the user's groups if the user is a corporate user
if (user.type === "corporate") { if (user.type === "corporate") {
getDocs( getDocs(query(collection(db, "groups"), where("admin", "==", userId))).then(async (userGroupsRef) => {
query(collection(db, "groups"), where("admin", "==", userId)) const userGroups = userGroupsRef.docs.map((x) => x.data());
).then(async (userGroupsRef) => {
const userGroups = userGroupsRef.docs.map((x) => x.data());
const targetUsers = [ const targetUsers = [...new Set(userGroups.flatMap((g) => g.participants).filter((u) => u))];
...new Set(
userGroups.flatMap((g) => g.participants).filter((u) => u)
),
];
Promise.all( Promise.all(
targetUsers.map(async (targetUserId) => { targetUsers.map(async (targetUserId) => {
const ref = await getDoc(doc(db, "users", targetUserId)); const ref = await getDoc(doc(db, "users", targetUserId));
if (!ref.exists()) return null; if (!ref.exists()) return null;
const data = ref.data() as User; const data = ref.data() as User;
return { ...data, id: targetUserId }; return {...data, id: targetUserId};
}) }),
) )
.then((data) => { .then((data) => {
const filtered = data.filter((x) => { const filtered = data.filter((x) => {
if (x === null) return false; if (x === null) return false;
if (x.status === status) return false; if (x.status === status) return false;
if (x.type !== "student") return false; return true;
return true; }) as User[];
}) as User[];
if (filtered.length === 0) { if (filtered.length === 0) {
return; return;
} }
Promise.all( Promise.all(filtered.map((user: User) => setDoc(doc(db, "users", user.id), {status}, {merge: true})))
filtered.map((user: User) => .then(() => {
setDoc( resolve(true);
doc(db, "users", user.id), })
{ status }, .catch((err) => {
{ merge: true } console.error(err);
) reject(err);
) });
) })
.then(() => { .catch((err) => {
resolve(true); console.error(err);
}) reject(err);
.catch((err) => { });
console.error(err); });
reject(err); return;
}); }
})
.catch((err) => {
console.error(err);
reject(err);
});
});
return;
}
const error = new Error("User is not a corporate user"); const error = new Error("User is not a corporate user");
console.error(error); console.error(error);
reject(error); reject(error);
}) })
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
reject(err); reject(err);
}); });
}); });
export const propagateExpiryDateChanges = (userId: string, initialExpiryDate: Date | null, subscriptionExpirationDate: Date | null) =>
new Promise((resolve, reject) => {
getDoc(doc(db, "users", userId))
.then((docUser) => {
const user = docUser.data() as User;
// only update the status of the user's groups if the user is a corporate user
if (user.type === "corporate") {
getDocs(query(collection(db, "groups"), where("admin", "==", userId))).then(async (userGroupsRef) => {
const userGroups = userGroupsRef.docs.map((x) => x.data());
const targetUsers = [...new Set(userGroups.flatMap((g) => g.participants).filter((u) => u))];
Promise.all(
targetUsers.map(async (targetUserId) => {
const ref = await getDoc(doc(db, "users", targetUserId));
if (!ref.exists()) return null;
const data = ref.data() as User;
return {...data, id: ref.id};
}),
)
.then(async (data) => {
const filtered = data.filter((x) => {
if (x === null) return false;
if (x.subscriptionExpirationDate !== initialExpiryDate) return false;
return true;
}) as User[];
if (filtered.length === 0) return;
for (const user of filtered) {
await setDoc(doc(db, "users", user.id), {subscriptionExpirationDate}, {merge: true});
}
resolve(true);
})
.catch((err) => {
console.error(err);
reject(err);
});
});
return;
}
const error = new Error("User is not a corporate user");
console.error(error);
reject(error);
})
.catch((err) => {
console.error(err);
reject(err);
});
});