tariffs/src/handlers/tariff/index.ts

222 lines
6.1 KiB
TypeScript

import { Types } from "mongoose";
import { TariffModel } from "@/models/tariff.model";
import { PrivilegeModel } from "@/models/privilege.model";
import { validateEmptyFields } from "@/utils/validate-empty-fields";
import { determinePaginationParameters } from "@/utils/determine-pagination-parameters";
import { validateTariff } from "./helpers";
import type { FastifyReply } from "fastify";
import type { Privilege } from "@/types/models/privilege.type";
import type { Tariff } from "@/types/models/tariff.type";
import type { Eloquent } from "@/types/models/eloquent.type";
import type {
CreateTariffRequest,
GetTariffRequest,
ReplaceTariffRequest,
RemoveTariffRequest,
GetTariffsResponse,
GetTariffsRequest,
} from "./types";
export const getTariffs = async (request: GetTariffsRequest): Promise<GetTariffsResponse> => {
const { page, limit } = determinePaginationParameters(request?.query ?? {});
const tariffsCount = await TariffModel.countDocuments({
$or: [{ isCustom: false }, { isCustom: true, userId: request.user.id }],
});
const totalPages = Math.ceil(tariffsCount / limit);
const offset = (page - 1) * limit;
const tariffs = await TariffModel.find({ $or: [{ isCustom: false }, { isCustom: true, userId: request.user.id }] })
.sort({ createdAt: "desc" })
.skip(offset)
.limit(limit)
.lean();
return { tariffs, totalPages };
};
export const getTariff = async (request: GetTariffRequest, reply: FastifyReply): Promise<Tariff> => {
const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["id"]);
if (error) {
void reply.status(400);
throw error;
}
if (!Types.ObjectId.isValid(requestParams.id)) {
void reply.status(400);
throw new Error("invalid id");
}
const tariff = await TariffModel.findOne({
$or: [
{ _id: new Types.ObjectId(requestParams.id), isCustom: false },
{ _id: new Types.ObjectId(requestParams.id), isCustom: true, userId: request.user.id },
],
}).lean();
if (!tariff) {
void reply.status(404);
throw new Error("tariff not found");
}
return tariff;
};
export const createTariff = async (request: CreateTariffRequest, reply: FastifyReply): Promise<Tariff> => {
const [requestBody, error] = validateTariff(request.body);
if (error) {
void reply.status(400);
throw error;
}
for (const privilege of requestBody.privilegies) {
if (!Types.ObjectId.isValid(privilege.privilegeId)) {
void reply.status(404);
throw new Error(`privilege id <${privilege.privilegeId}> invalid`);
}
}
const newTariff = new TariffModel({
name: requestBody.name,
price: requestBody.price,
userId: request.user.id,
isCustom: requestBody.isCustom,
privilegies: requestBody.privilegies,
});
return newTariff.save();
};
export const replaceTariff = async (request: ReplaceTariffRequest, reply: FastifyReply): Promise<Tariff> => {
const [requestBody, error] = validateTariff(request.body ?? {});
if (error) {
void reply.status(400);
throw error;
}
if (!Types.ObjectId.isValid(request.params?.id || "")) {
void reply.status(400);
throw new Error("invalid id");
}
const tariff = await TariffModel.findById(request.params?.id);
if (!tariff) {
void reply.status(404);
throw new Error("tariff not found");
}
for (const privilege of requestBody.privilegies) {
if (!Types.ObjectId.isValid(privilege.privilegeId)) {
void reply.status(404);
throw new Error(`privilege id <${privilege.privilegeId}> invalid`);
}
}
const privilegiesMap = new Map(requestBody.privilegies.map((privilege) => [privilege.privilegeId, privilege]));
const privilegeIDs = requestBody.privilegies.map(({ privilegeId }) => privilegeId);
const privilegies = await PrivilegeModel.find({ _id: privilegeIDs }).lean();
const cleanPrivilegies = privilegies.map<Omit<Privilege, keyof Eloquent>>((privilege) => {
const currentPrivilege = privilegiesMap.get(privilege._id.toString());
return {
name: privilege.name,
privilegeId: privilege.privilegeId,
serviceKey: privilege.serviceKey,
description: privilege.description,
amount: currentPrivilege?.amount ?? 0,
type: privilege.type,
value: privilege.value,
price: privilege.price,
};
});
await tariff.replaceOne({
name: requestBody.name,
price: requestBody.price,
isCustom: requestBody.isCustom,
privilegies: cleanPrivilegies,
});
return tariff;
};
export const removeTariff = async (request: RemoveTariffRequest, reply: FastifyReply): Promise<Tariff> => {
const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]);
if (error) {
void reply.status(400);
throw error;
}
if (!Types.ObjectId.isValid(id)) {
void reply.status(400);
throw new Error("invalid id");
}
const tariff = await TariffModel.findByIdAndUpdate(id, {
$set: { isDeleted: true, deletedAt: new Date() },
}).lean();
if (!tariff) {
void reply.status(404);
throw new Error("tariff not found");
}
return tariff;
};
export const deleteTariff = async (request: RemoveTariffRequest, reply: FastifyReply): Promise<Tariff> => {
const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]);
if (error) {
void reply.status(400);
throw error;
}
if (!Types.ObjectId.isValid(id)) {
void reply.status(400);
throw new Error("invalid id");
}
const tariff = await TariffModel.findByIdAndDelete(id).lean();
if (!tariff) {
void reply.status(404);
throw new Error("tariff not found");
}
return tariff;
};
export const restoreTariff = async (request: RemoveTariffRequest, reply: FastifyReply): Promise<Tariff> => {
const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]);
if (error) {
void reply.status(400);
throw error;
}
if (!Types.ObjectId.isValid(id)) {
void reply.status(400);
throw new Error("invalid id");
}
const tariff = await TariffModel.findByIdAndUpdate(id, { $set: { isDeleted: false } }).lean();
if (!tariff) {
void reply.status(404);
throw new Error("tariff not found");
}
return tariff;
};