diff --git a/scripts/update-points.mjs b/scripts/update-points.mjs new file mode 100644 index 0000000..251a421 --- /dev/null +++ b/scripts/update-points.mjs @@ -0,0 +1,46 @@ +import { MongoClient, ServerApiVersion } from 'mongodb' +import { env } from 'process' + +const clientPromise = new MongoClient(env.MONGODB_URI, { + serverApi: ServerApiVersion.v1, +}).connect() +const client = await clientPromise +const users = client.db().collection('users') + +export function sumPointAdjustments(adjustments) { + return adjustments?.reduce((p, c) => p + c.delta, 0) ?? 0 +} + +export async function computePoints(user) { + const events = user?.attendedEvents?.length + ? await client.db().collection('events').find({ + title: { $in: user.attendedEvents }, + }).toArray() + : [] + const eventPoints = events.reduce((p, c) => p + c.pointValue, 0) + const checkedInBonus = user?.checkedIn ? 50 : 0 + return eventPoints + checkedInBonus + + sumPointAdjustments(user?.pointAdjustments) +} + +let counter = 0 + +export async function updateUser(user) { + const newPoints = await computePoints(user) + await users.updateOne({ _id: user._id }, { $set: { points: newPoints } }) + if (user.points !== newPoints) { + console.log(`updated ${user.email} from ${user.points} to ${newPoints}`) + } + if (++counter % 20 === 0) { + console.log(counter) + } + return { ...user, points: newPoints } +} + +export async function updateAll() { + const all = await users.find({}, { projection: { 'application.resume': 0 } }) + .toArray() + return await Promise.all(all.map(updateUser)) +} + +await updateAll() diff --git a/src/lib/utils/server.ts b/src/lib/utils/server.ts index 2573cf3..d9f5f2d 100644 --- a/src/lib/utils/server.ts +++ b/src/lib/utils/server.ts @@ -2,8 +2,8 @@ import '@/node-only' import { Condition, - Document as MongoDocument, MongoClient, + Document as MongoDocument, ObjectId, WithId, } from 'mongodb' @@ -19,7 +19,7 @@ import logger from '@/lib/logger' import { BuiltInRoles, EnhancedSession, hasPermission } from '../auth/shared' import clientPromise from '../db' import Event from '../db/models/Event' -import { getGroupName, RenderContext, sumPointAdjustments } from './shared' +import { RenderContext, getGroupName, sumPointAdjustments } from './shared' export * from './shared' @@ -180,8 +180,31 @@ export async function createTemplateRenderContext(): Promise { return { user, - group: user?.hexId && getGroupName(user.hexId), applicationWaived: hasPermission(perms, { applicationWaived: true }), + group: user?.hexId && getGroupName(user.hexId), + pointHistory: createPointHistory(), + } + + function createPointHistory(): string { + let ans = '' + const events = user?.attendedEvents + if (user?.checkedIn || events?.length) { + ans += '**Attended Events**\n\n' + if (user?.checkedIn) { + ans += `* Checked In\n` + } + for (const event of events ?? []) { + ans += `* ${event}\n` + } + } + const adjustments = user?.pointAdjustments + if (adjustments?.length) { + ans += '\n**Adjustments**\n\n' + for (const { reason, delta } of adjustments) { + ans += `* ${reason}: **${delta >= 0 ? `+${delta}` : delta}**\n` + } + } + return ans } } diff --git a/src/lib/utils/shared.ts b/src/lib/utils/shared.ts index 7a98145..e350516 100644 --- a/src/lib/utils/shared.ts +++ b/src/lib/utils/shared.ts @@ -71,6 +71,7 @@ export type ToJsonValue = T extends Date | ObjectId ? string export interface RenderContext { user: JsonUser | null applicationWaived: boolean + pointHistory: string group?: string | undefined }