feat: implement sysadmin subscription management and plan usage cycle recalculation tools
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
import { Document, Model, Schema, model } from "mongoose";
|
||||
import {
|
||||
CreatePlanUsageCycleParams,
|
||||
FindPlanUsageCycleParams,
|
||||
IPlanUsageCycle,
|
||||
IPlanUsageCycleAdapter,
|
||||
UpdatePlanUsageCycleParams,
|
||||
} from "./PlanUsageCycle.Interface";
|
||||
|
||||
export interface IPlanUsageCycleDocument extends Omit<IPlanUsageCycle, "id">, Document {}
|
||||
|
||||
export class PlanUsageCycleAdapterMongoose implements IPlanUsageCycleAdapter {
|
||||
schema: Schema;
|
||||
planUsageCycleList: Model<IPlanUsageCycleDocument>;
|
||||
|
||||
constructor() {
|
||||
this.schema = new Schema({
|
||||
userId: { type: Schema.Types.ObjectId, required: true, ref: "User" },
|
||||
subscriptionId: { type: Schema.Types.ObjectId, required: false, ref: "PlanSuscription" },
|
||||
planId: { type: Schema.Types.ObjectId, required: true, ref: "Plan" },
|
||||
cycleStart: { type: Date, required: true },
|
||||
cycleEnd: { type: Date, required: true },
|
||||
appointmentsCount: { type: Number, required: true, default: 0 },
|
||||
creationDate: { type: Date, required: true, default: Date.now },
|
||||
updateDate: { type: Date, required: true, default: Date.now },
|
||||
});
|
||||
|
||||
this.schema.index({ userId: 1, subscriptionId: 1, planId: 1, cycleStart: 1 }, { unique: true });
|
||||
|
||||
this.planUsageCycleList = model<IPlanUsageCycleDocument>("PlanUsageCycle", this.schema);
|
||||
}
|
||||
|
||||
public async findOne(filters: FindPlanUsageCycleParams): Promise<IPlanUsageCycleDocument | null> {
|
||||
return await this.planUsageCycleList.findOne(filters);
|
||||
}
|
||||
|
||||
public async create(data: CreatePlanUsageCycleParams): Promise<IPlanUsageCycleDocument> {
|
||||
return await this.planUsageCycleList.create({
|
||||
...data,
|
||||
appointmentsCount: data.appointmentsCount || 0,
|
||||
updateDate: new Date(),
|
||||
});
|
||||
}
|
||||
|
||||
public async getOrCreateCurrent(data: UpdatePlanUsageCycleParams): Promise<IPlanUsageCycleDocument> {
|
||||
const now = new Date();
|
||||
return await this.planUsageCycleList.findOneAndUpdate(
|
||||
{
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
},
|
||||
{
|
||||
$setOnInsert: {
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
cycleEnd: data.cycleEnd,
|
||||
appointmentsCount: 0,
|
||||
creationDate: now,
|
||||
},
|
||||
$set: { updateDate: now },
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
}
|
||||
|
||||
public async incrementAppointments(
|
||||
data: UpdatePlanUsageCycleParams & { quantity: number }
|
||||
): Promise<IPlanUsageCycleDocument | null> {
|
||||
const now = new Date();
|
||||
return await this.planUsageCycleList.findOneAndUpdate(
|
||||
{
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
},
|
||||
{
|
||||
$setOnInsert: {
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
cycleEnd: data.cycleEnd,
|
||||
appointmentsCount: 0,
|
||||
creationDate: now,
|
||||
},
|
||||
$inc: { appointmentsCount: data.quantity },
|
||||
$set: { updateDate: now },
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
}
|
||||
|
||||
public async incrementAppointmentsIfWithinLimit(
|
||||
data: UpdatePlanUsageCycleParams & { quantity: number; limit: number }
|
||||
): Promise<IPlanUsageCycleDocument | null> {
|
||||
const now = new Date();
|
||||
return await this.planUsageCycleList.findOneAndUpdate(
|
||||
{
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
appointmentsCount: { $lte: data.limit - data.quantity },
|
||||
},
|
||||
{
|
||||
$setOnInsert: {
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
cycleEnd: data.cycleEnd,
|
||||
appointmentsCount: 0,
|
||||
creationDate: now,
|
||||
},
|
||||
$inc: { appointmentsCount: data.quantity },
|
||||
$set: { updateDate: now },
|
||||
},
|
||||
{ new: true }
|
||||
);
|
||||
}
|
||||
|
||||
public async setAppointmentsCount(
|
||||
data: UpdatePlanUsageCycleParams & { appointmentsCount: number }
|
||||
): Promise<IPlanUsageCycleDocument | null> {
|
||||
const now = new Date();
|
||||
return await this.planUsageCycleList.findOneAndUpdate(
|
||||
{
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
},
|
||||
{
|
||||
$setOnInsert: {
|
||||
userId: data.userId,
|
||||
subscriptionId: data.subscriptionId,
|
||||
planId: data.planId,
|
||||
cycleStart: data.cycleStart,
|
||||
cycleEnd: data.cycleEnd,
|
||||
creationDate: now,
|
||||
},
|
||||
$set: {
|
||||
appointmentsCount: Math.max(data.appointmentsCount, 0),
|
||||
updateDate: now,
|
||||
},
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user