import { getDb } from "../index"; import { SimpleSubscriptionFilter, Subscription, SubscriptionDoc, SubscriptionFilter, SubscriptionQueryOptions, } from "./subscriptions.types"; import { Filter, ObjectId } from "mongodb"; import { buildSimpleQuery } from "./subscriptions.getters.utils"; import { applyQueryOptions } from "../utils/query.utils"; export const getSubscriptionsCollection = () => { return getDb().collection("subscriptions"); }; /** * A simple filter for Subscription: each field may be a value or a MongoDB operator expression */ export const findSubscriptions = async ( filter?: SubscriptionFilter, options?: SubscriptionQueryOptions, ): Promise => { let query: Filter = {}; if (filter) { const simpleFilter: SimpleSubscriptionFilter = { _id: filter._id, clientId: filter.clientId, planId: filter.planId, startDate: filter.startDate, endDate: filter.endDate, isActive: filter.isActive, createdAt: filter.createdAt, nextRenewalDate: filter.nextRenewalDate, }; const baseQuery = buildSimpleQuery(simpleFilter); if (Object.keys(baseQuery).length > 0) { query = baseQuery; } if (filter.or && filter.or.length > 0) { query.$or = filter.or.map(buildSimpleQuery); } if (filter.and && filter.and.length > 0) { query.$and = filter.and.map(buildSimpleQuery); } } const cursor = getSubscriptionsCollection().find(query); return await applyQueryOptions(cursor, options).toArray(); }; export const countSubscriptions = async ( query: Filter, ): Promise => { return getSubscriptionsCollection().countDocuments(query); }; export const createSubscriptionDoc = async ( subscriptionData: Omit, ): Promise => { const now = new Date(); const result = await getSubscriptionsCollection().insertOne({ ...subscriptionData, createdAt: now, updatedAt: now, }); const subscriptions = await findSubscriptions({ _id: result.insertedId }); if (!subscriptions[0]) throw new Error("Failed to retrieve created subscription"); return subscriptions[0]; }; export const updateSubscriptionDoc = async ( subscriptionId: ObjectId, updates: Partial, ): Promise => { return await getSubscriptionsCollection().findOneAndUpdate( { _id: subscriptionId }, { $set: { ...updates, updatedAt: new Date(), }, }, { returnDocument: "after", }, ); }; export const incrementSubscriptionUsage = async ( subscriptionId: ObjectId, amount: number = 1, ): Promise => { const fieldToIncrement = "cycles.$[activeCycle].usage.usedCalls"; return await getSubscriptionsCollection().findOneAndUpdate( { _id: subscriptionId, "cycles.isActive": true }, { $inc: { [fieldToIncrement]: amount }, $set: { updatedAt: new Date() }, }, { arrayFilters: [{ "activeCycle.isActive": true }], returnDocument: "after", }, ); }; export const deactivateCurrentSubscriptionCycle = async ( subscriptionId: ObjectId, nextRenewalDate: Date, ): Promise => { await getSubscriptionsCollection().updateOne( { _id: subscriptionId, "cycles.isActive": true }, { $set: { "cycles.$[activeCycle].isActive": false, nextRenewalDate: nextRenewalDate, updatedAt: new Date(), }, }, { arrayFilters: [{ "activeCycle.isActive": true }], }, ); }; export const pushNewSubscriptionCycle = async ( subscriptionId: ObjectId, newCycle: Subscription["cycles"][number], ): Promise => { return await getSubscriptionsCollection().findOneAndUpdate( { _id: subscriptionId }, { $push: { cycles: newCycle, }, }, { returnDocument: "after", }, ); };