Skip to content

Commit

Permalink
Prepared ground for service implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
zhamdi committed Oct 3, 2023
1 parent be2f4e6 commit c25534c
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 28 deletions.
2 changes: 2 additions & 0 deletions src/db/dao/IBaseDAO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface IBaseDAO<D extends object> {
// Find documents that match a query
find(query: object): Promise<D[]>;

findOne(query: object): Promise<D>;

findById(userId: object): Promise<D | null>;

// Update a document by ID
Expand Down
7 changes: 7 additions & 0 deletions src/db/model/BaseEntity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Entities have instance method signatures copied from mongoose
* @param K the type of the id dependency fields
*/
export interface BaseEntity<K> {
save(): Promise<unknown>;
}
4 changes: 3 additions & 1 deletion src/db/model/IOffer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { BaseEntity } from "./BaseEntity";

/**
* @param K the type of foreign keys (is used for all foreign keys type)
*/
export interface IOffer<K extends object> {
export interface IOffer<K extends object> extends BaseEntity<K> {
cycle: "once" | "weekly" | "monthly" | "yearly";
/**indicates information about exclusive offers. Designed to be a boolean*/
hasSubOffers: unknown;
Expand Down
4 changes: 3 additions & 1 deletion src/db/model/IOrder.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { BaseEntity } from "./BaseEntity";

export interface OrderStatus {
date: Date;
message: string;
Expand All @@ -7,7 +9,7 @@ export interface OrderStatus {
/**
* @param K the type of foreign keys (is used for all foreign keys type)
*/
export interface IOrder<K extends object> {
export interface IOrder<K extends object> extends BaseEntity<K> {
history: [OrderStatus] | null;
offerId: K;
status: "pending" | "paid" | "refused";
Expand Down
4 changes: 3 additions & 1 deletion src/db/model/ITokenTimetable.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { BaseEntity } from "./BaseEntity";

/**
* @param K the type of foreign keys (is used for all foreign keys type)
*/
export interface ITokenTimetable<K extends object> {
export interface ITokenTimetable<K extends object> extends BaseEntity<K> {
createdAt: Date;
tokens: number;
userId: K;
Expand Down
4 changes: 3 additions & 1 deletion src/db/model/IUserCredits.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { BaseEntity } from "./BaseEntity";

/**
* @param K the type of foreign keys (is used for all foreign keys type)
*/
export interface ISubscription<K extends object> {
export interface ISubscription<K extends object> extends BaseEntity<K> {
expires: Date;
offerId: K;
starts: Date;
Expand Down
27 changes: 11 additions & 16 deletions src/impl/mongoose/service/Payment.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
import { HydratedDocument, Model, ObjectId } from "mongoose";
import { ObjectId } from "mongoose";

import { IDaoFactory } from "../../../db/dao";
import { IOffer } from "../../../db/model/IOffer";
import { IOrder } from "../../../db/model/IOrder";
import { IUserCredits } from "../../../db/model/IUserCredits";
import { EntityNotFoundError } from "../../../errors/EntityNotFoundError";
import { BaseService } from "../../../service/BaseService";
import { IDaoFactory, IOfferDao, IOrderDao, IUserCreditsDao } from "../../../db/dao";
import UserCredits, { IMongooseUserCredits } from "../model/UserCredits";
import { IMongooseOrder } from "../model/Order";
import { IMongooseOffer } from "../model/Offer";

type OrderDocument = HydratedDocument<IOrder<ObjectId>>;
type UserCreditsDocument = HydratedDocument<IUserCredits<ObjectId>>;

export class Payment extends BaseService<ObjectId> {

constructor(daoFactory: IDaoFactory<ObjectId>) {
super(daoFactory);
}

async createOrder(
offerId: unknown,
userId: unknown,
offerId: ObjectId,
userId: ObjectId,
): Promise<IMongooseOrder> {
const order: IMongooseOrder = await this.orderDao.create({
const order: IMongooseOrder = (await this.orderDao.create({
history: [],
offerId: offerId,
status: "pending",
tokenCount: 100,
userId: userId
}) as IMongooseOrder;
userId: userId,
})) as IMongooseOrder;
return order;
}

Expand All @@ -43,18 +37,19 @@ export class Payment extends BaseService<ObjectId> {
}

async orderStatusChanged(
orderId: unknown,
orderId: ObjectId,
status: "pending" | "paid" | "refused",
): Promise<IOrder<ObjectId>> {
const order: null | OrderDocument = await this.orderDao.findById(orderId);
const order: null | IOrder<ObjectId> =
await this.orderDao.findById(orderId);
if (!order) throw new EntityNotFoundError("IOrder", orderId);
order.status = status;
await order.save();
return order as IOrder<ObjectId>;
}

async remainingTokens(userId: ObjectId): Promise<IUserCredits<ObjectId>> {
const userCredits: null | UserCreditsDocument =
const userCredits: null | IUserCredits<ObjectId> =
await this.userCreditsDao.findOne({ userId });
if (!userCredits) throw new EntityNotFoundError("IUserCredits", userId);
return userCredits;
Expand Down
16 changes: 8 additions & 8 deletions src/service/BaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import { ITokenTimetable } from "../db/model";
export class BaseService<K extends object> implements IPayment<K> {
protected daoFactory: IDaoFactory<ObjectId>;

protected readonly offerDAO: IOfferDao<K, IOffer<K>>;
protected readonly offerDao: IOfferDao<K, IOffer<K>>;
protected readonly orderDao: IOrderDao<K, IOrder<K>>;
protected readonly tokenTimetableDao: ITokenTimetableDao<K, ITokenTimetable<K>>;
protected readonly userCreditsDAO: IUserCreditsDao<K, IUserCredits<K>>;
protected readonly userCreditsDao: IUserCreditsDao<K, IUserCredits<K>>;

constructor(daoFactory) {
this.daoFactory = daoFactory;

this.offerDAO = daoFactory.getOfferDao();
this.offerDao = daoFactory.getOfferDao();
this.orderDao = daoFactory.getOrderDao();
this.tokenTimetableDao = daoFactory.getTokenTimetableDao();
this.userCreditsDAO = daoFactory.getUserCreditsDao();
this.userCreditsDao = daoFactory.getUserCreditsDao();
}

/**
Expand All @@ -30,7 +30,7 @@ export class BaseService<K extends object> implements IPayment<K> {
*/
async loadOffers(userId: K): Promise<IOffer<K>[]> {
if (!userId) {
return this.offerDAO.find({ parentOfferId: null });
return this.offerDao.find({ parentOfferId: null });
}

const activeSubscriptions = await this.getActiveSubscriptions(userId);
Expand All @@ -48,7 +48,7 @@ export class BaseService<K extends object> implements IPayment<K> {
* @returns A promise that resolves to an array of active subscriptions.
*/
async getActiveSubscriptions(userId: K): Promise<ISubscription<K>[]> {
const userCredits = await this.userCreditsDAO.findById(userId);
const userCredits = await this.userCreditsDao.findById(userId);
return (userCredits ?? null).subscriptions.filter(
(subscription) => subscription.status === "paid",
);
Expand All @@ -63,7 +63,7 @@ export class BaseService<K extends object> implements IPayment<K> {
const uniqueOfferIds = [
...new Set(subscriptions.map((sub) => sub.offerId)),
];
return this.offerDAO.find({
return this.offerDao.find({
hasSubOffers: false,
parentOfferId: { $in: uniqueOfferIds },
});
Expand All @@ -74,7 +74,7 @@ export class BaseService<K extends object> implements IPayment<K> {
* @returns A promise that resolves to an array of "regular" offers.
*/
async getRegularOffers(): Promise<IOffer<K>[]> {
return this.offerDAO.find({
return this.offerDao.find({
hasSubOffers: false,
overridingKey: { $exists: false },
});
Expand Down

0 comments on commit c25534c

Please sign in to comment.