import { getClientConfig } from "../clientsConfig/clientsConfig.getters"; import { getClientsCollection } from "./clients.getters"; import type { ClientQuotaState, QuotaAlertInput, } from "./clients.quota.types"; export async function getClientQuotaState( clientId: string, ): Promise { const [config, client] = await Promise.all([ getClientConfig(clientId), getClientsCollection().findOne({ clientId }), ]); const usage = config?.quota; if (usage?.totalQuota === undefined || usage?.totalQuota === null) return null; const settings = client?.quota; return { totalQuota: usage.totalQuota, usedQuota: usage.usedQuota ?? 0, expiresAt: usage.expiresAt, alerts: settings?.alerts, expiredSent: settings?.expiredSent, }; } const ensureClientDoc = async (clientId: string): Promise => { const now = new Date(); await getClientsCollection().updateOne( { clientId }, { $setOnInsert: { clientId, createdAt: now, updatedAt: now, credits: 0 } }, { upsert: true }, ); await getClientsCollection().updateOne({ clientId }, { $set: { updatedAt: now } }); }; export async function updateQuotaAlertsConfig( clientId: string, alerts: QuotaAlertInput[], ): Promise { const config = await getClientConfig(clientId); if (!config) { throw new Error(`No client config found for clientId: ${clientId}`); } await ensureClientDoc(clientId); const state = await getClientQuotaState(clientId); const existing = state?.alerts ?? []; const sentByThreshold = new Map( existing.filter((a) => a.thresholdSent).map((a) => [a.thresholdPct, true]), ); const merged = alerts.map((alert) => ({ thresholdPct: alert.thresholdPct, recipientEmails: alert.recipientEmails, ...(sentByThreshold.get(alert.thresholdPct) ? { thresholdSent: true as const } : {}), })); const result = await getClientsCollection().updateOne( { clientId }, { $set: { "quota.alerts": merged, updatedAt: new Date() } }, ); if (result.matchedCount === 0) { throw new Error(`No client found for clientId: ${clientId}`); } } export async function markQuotaAlertSent( clientId: string, alertIndex: number, ): Promise { await ensureClientDoc(clientId); const result = await getClientsCollection().findOneAndUpdate( { clientId, [`quota.alerts.${alertIndex}.thresholdSent`]: { $ne: true }, }, { $set: { [`quota.alerts.${alertIndex}.thresholdSent`]: true, updatedAt: new Date() } }, { returnDocument: "after" }, ); return result !== null; } export async function markQuotaExpiredSent(clientId: string): Promise { await ensureClientDoc(clientId); const result = await getClientsCollection().findOneAndUpdate( { clientId, "quota.expiredSent": { $ne: true }, }, { $set: { "quota.expiredSent": true, updatedAt: new Date() } }, { returnDocument: "after" }, ); return result !== null; } export async function resetClientQuotaSettings(clientId: string): Promise { const client = await getClientsCollection().findOne({ clientId }); const alerts = client?.quota?.alerts?.map(({ thresholdSent: _s, ...alert }) => alert) ?? []; if (client) { await getClientsCollection().updateOne( { clientId }, { $set: { ...(alerts.length ? { "quota.alerts": alerts } : {}), updatedAt: new Date(), }, $unset: { "quota.expiredSent": "" }, }, ); } }