Files
turnosxpress/server/src/Models/PlanUsageCycle/PlanUsageCycle.Adapter.Mongoose.ts
T

153 lines
5.6 KiB
TypeScript

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,
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,
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,
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 }
);
}
}