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 => { const { page, limit } = determinePaginationParameters(request?.query ?? {}); const tariffsCount = await TariffModel.countDocuments(); const totalPages = Math.ceil(tariffsCount / limit); const offset = (page - 1) * limit; const tariffs = await TariffModel.find({}).sort({ createdAt: "desc" }).skip(offset).limit(limit).lean(); return { tariffs, totalPages }; }; export const getTariff = async (request: GetTariffRequest, reply: FastifyReply) => { const [requestParams, error] = validateEmptyFields(request.params ?? {}, ["id"]); if (error) { void reply.status(400); return error; } if (!Types.ObjectId.isValid(requestParams.id)) { void reply.status(400); return new Error("invalid id"); } const tariff = await TariffModel.findById(requestParams.id).lean(); if (!tariff) { void reply.status(404); return new Error("tariff not found"); } return tariff; }; export const createTariff = async (request: CreateTariffRequest, reply: FastifyReply): Promise => { 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 privilegiesMap = new Map(requestBody.privilegies.map((privilege) => [privilege.privilegeId, privilege])); const privilegeIDs = requestBody.privilegies.map(({ privilegeId }) => privilegeId); const privilegies = await PrivilegeModel.find({ privilegeId: privilegeIDs }).lean(); const cleanPrivilegies = privilegies.map>((privilege) => { const currentPrivilege = privilegiesMap.get(privilege.privilegeId); 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, }; }); const newTariff = new TariffModel({ name: requestBody.name, price: requestBody.price, isCustom: requestBody.isCustom, privilegies: cleanPrivilegies, }); await newTariff.save(); return newTariff; }; export const replaceTariff = async (request: ReplaceTariffRequest, reply: FastifyReply) => { const [requestBody, error] = validateTariff(request.body ?? {}); if (error) { void reply.status(400); return error; } if (!Types.ObjectId.isValid(request.params?.id || "")) { void reply.status(400); return new Error("invalid id"); } const tariff = await TariffModel.findById(request.params?.id); if (!tariff) { void reply.status(404); return new Error("tariff not found"); } for (const privilege of requestBody.privilegies) { if (!Types.ObjectId.isValid(privilege.privilegeId)) { void reply.status(404); return 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({ privilegeId: privilegeIDs }).lean(); const cleanPrivilegies = privilegies.map>((privilege) => { const currentPrivilege = privilegiesMap.get(privilege.privilegeId); 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) => { const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]); if (error) { void reply.status(400); return error; } if (!Types.ObjectId.isValid(id)) { void reply.status(400); return new Error("invalid id"); } const tariff = await TariffModel.findByIdAndUpdate(id, { $set: { isDeleted: true, deletedAt: new Date() }, }).lean(); if (!tariff) { void reply.status(404); return new Error("tariff not found"); } return tariff; }; export const deleteTariff = async (request: RemoveTariffRequest, reply: FastifyReply) => { const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]); if (error) { void reply.status(400); return error; } if (!Types.ObjectId.isValid(id)) { void reply.status(400); return new Error("invalid id"); } const tariff = await TariffModel.findByIdAndDelete(id).lean(); if (!tariff) { void reply.status(404); return new Error("tariff not found"); } return tariff; }; export const restoreTariff = async (request: RemoveTariffRequest, reply: FastifyReply) => { const [{ id }, error] = validateEmptyFields(request.body ?? {}, ["id"]); if (error) { void reply.status(400); return error; } if (!Types.ObjectId.isValid(id)) { void reply.status(400); return new Error("invalid id"); } const tariff = await TariffModel.findByIdAndUpdate(id, { $set: { isDeleted: false } }).lean(); if (!tariff) { void reply.status(404); return new Error("tariff not found"); } return tariff; };