settings/controllers/apiUsagePricing.js

473 lines
12 KiB
JavaScript
Raw Normal View History

2024-07-30 11:26:42 +00:00
const { StatusCodes } = require("http-status-codes")
const API_Pricing = require("../models/API_Pricing.js")
2025-06-10 17:15:34 +00:00
const mongoose = require('mongoose');
2024-07-30 11:26:42 +00:00
const {
mustContainProperties,
calculateApiUsage,
} = require('../utils')
const API_Usage = require("../models/API_Usage.js")
2025-06-10 17:15:34 +00:00
const API_Products = require("../models/API_Products.js")
2024-07-30 11:26:42 +00:00
const billingSumUsage = require("../utils/billingSumUsage.js")
const moment = require('moment')
const API_Call = require("../models/API_Call.js")
const API_Operation = require("../models/API_Operation.js")
const API_Usage_Whatsapp = require("../models/API_Usage_Whatsapp.js")
2024-07-30 11:26:42 +00:00
const setApiPricing = async (req, res) => {
const { provider, product, currency, price, billingBy, billingUnit, type, clientPrice } = req.body
2024-07-30 11:26:42 +00:00
mustContainProperties(req, ['provider',
'product',
'price',
'billingBy',
'billingUnit'])
const normalizedProvider = provider.trim().toLowerCase()
const normalizedProduct = product.trim().toLowerCase()
let filter = { provider: normalizedProvider, product: normalizedProduct }
if (type) {
filter = { ...filter, type }
}
const update = {
provider: normalizedProvider,
product: normalizedProduct,
2024-07-30 11:26:42 +00:00
currency,
price,
billingBy,
billingUnit,
type,
clientPrice
}
const options = { new: true, upsert: true }
const apiPricing = await API_Pricing.findOneAndUpdate(filter, update, options)
2024-07-30 11:26:42 +00:00
res.status(StatusCodes.OK).json({ apiPricing })
}
2025-06-10 17:15:34 +00:00
const updateProductPricing = async (req, res) => {
const { price, name, description } = req.body;
const { id } = req.params;
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(StatusCodes.BAD_REQUEST).json({
error: 'ID do produto inválido.'
});
}
let existingProduct = await API_Products.findById(id);
if (!existingProduct) {
return res.status(StatusCodes.NOT_FOUND).json({
error: 'Produto não encontrado.'
});
}
if (price) {
const activePriceIndex = existingProduct.priceHistory.findIndex(priceEntry => !priceEntry.endDate);
if (activePriceIndex !== -1 && existingProduct.priceHistory[activePriceIndex].price != price) {
existingProduct.priceHistory[activePriceIndex].endDate = new Date();
}
else {
return res.status(StatusCodes.BAD_REQUEST).json({
msg: `Product with the same price ${price}`
});
}
}
const newPriceEntry = {
startDate: new Date(),
endDate: null, // Novo preço ativo
price
};
if (description) existingProduct.description = description.trim();
if (name) existingProduct.name = name.trim();
if (price) existingProduct.priceHistory.push(newPriceEntry);
await existingProduct.save();
res.status(StatusCodes.OK).json({
msg: 'Preço do produto atualizado com sucesso!',
product: existingProduct
});
};
const setProductPricing = async (req, res) => {
const { name, description, price } = req.body;
console.log("price: ", price)
mustContainProperties(req, ['name']);
const normalizedName = name.trim();
let existingProduct = await API_Products.findOne({ name: normalizedName });
if (existingProduct) {
if (price) {
const activePriceIndex = existingProduct.priceHistory.findIndex(priceEntry => !priceEntry.endDate);
if (activePriceIndex !== -1 && existingProduct.priceHistory[activePriceIndex].price != price) {
existingProduct.priceHistory[activePriceIndex].endDate = new Date();
}
else {
return res.status(StatusCodes.BAD_REQUEST).json({
msg: `Product with the same price ${price}`
});
}
const newPriceEntry = {
startDate: new Date(),
endDate: null, // Novo preço ativo
price
};
existingProduct.priceHistory.push(newPriceEntry);
if (description) existingProduct.description = description.trim();
await existingProduct.save();
return res.status(StatusCodes.OK).json({
msg: 'Preço do produto atualizado com sucesso!',
product: existingProduct
});
} else {
return res.status(StatusCodes.CONFLICT).json({
error: 'Produto já existe. Para atualizar o preço, forneça o campo "price".',
product: existingProduct
});
}
}
// Se o produto não existe, criar um novo
const productData = {
name: normalizedName,
description: description?.trim() || '',
priceHistory: []
};
if (price) {
const priceEntry = {
startDate: new Date(), // Data atual automática
endDate: null, // Preço ativo (sem data de fim)
price,
};
productData.priceHistory.push(priceEntry);
}
console.log('---------> Dados do produto a ser criado:', productData);
// Criar o produto
const newProduct = new API_Products(productData);
await newProduct.save();
res.status(StatusCodes.CREATED).json({
msg: 'Produto criado com sucesso!',
product: newProduct
});
};
const listProductPricing = async (req, res) => {
const products = await API_Products.find();
res.status(StatusCodes.OK).json({
msg: 'ok',
products
})
}
2024-07-30 11:26:42 +00:00
const registerUsage = async (req, res) => {
const {
2024-07-30 11:26:42 +00:00
provider,
product,
usage,
callerId,
sessionId,
companyId,
2024-07-30 11:26:42 +00:00
} = req.body
mustContainProperties(req, [
'companyId',
'callerId',
'sessionId',
2024-07-30 11:26:42 +00:00
'provider',
'product',
'usage',
])
2024-07-30 11:26:42 +00:00
const apiPricing = await API_Pricing.findOne({
provider: provider.trim().toLowerCase(),
product: product.trim().toLowerCase(),
})
if (apiPricing) {
const { price, billingBy, billingUnit } = apiPricing
2024-07-30 11:26:42 +00:00
const apiUsage = await API_Usage.create({
provider: provider.trim().toLowerCase(),
product: product.trim().toLowerCase(),
callerId,
sessionId,
2024-07-30 11:26:42 +00:00
usage,
price,
billingBy,
billingUnit,
2024-07-30 11:26:42 +00:00
companyId,
total_cost: calculateApiUsage(price, billingUnit, usage)
2024-07-30 11:26:42 +00:00
})
return res.status(StatusCodes.OK).json({ apiUsage })
}
res.status(StatusCodes.NOT_FOUND).json({ msg: `Price not found for ${product} in the API Pricing table` })
}
const registerWhatsappUsage = async (req, res) => {
const {
companyId,
companyPhone,
clientPhone,
provider,
product,
type,
msgId,
ticketId,
ticketUrl,
billable,
pricing_model,
} = req.body
mustContainProperties(req, [
'companyId',
'provider',
'product',
'type',
'msgId',
'ticketId',
'billable',
'pricing_model',
'companyPhone',
2025-06-10 17:15:34 +00:00
'clientPhone',
])
const apiPricing = await API_Pricing.findOne({
provider: provider.trim().toLowerCase(),
product: product.trim().toLowerCase(),
type: type.trim().toLowerCase(),
})
if (apiPricing) {
const { price } = apiPricing
const apiUsageWhatsapp = await API_Usage_Whatsapp.create({
companyId,
companyPhone,
clientPhone,
provider: provider.trim().toLowerCase(),
product: product.trim().toLowerCase(),
price,
msgId,
ticketId,
ticketUrl,
billable,
pricing_model,
type
})
return res.status(StatusCodes.OK).json({ apiUsageWhatsapp })
}
res.status(StatusCodes.NOT_FOUND).json({ msg: `Price not found for ${product} in the API Pricing table` })
}
const registerAPICall = async (req, res) => {
const {
callerId,
companyId,
sessionId,
type,
requestLogs,
responseError,
quantityOfAPICall
} = req.body
mustContainProperties(req, [
'companyId',
'callerId',
'sessionId'
])
const apiCall = await API_Call.create({
callerId,
companyId,
sessionId,
type,
requestLogs,
responseError,
quantityOfAPICall
})
res.status(StatusCodes.OK).json({ apiCall })
}
const registerOperation = async (req, res) => {
const {
callerId,
companyId,
sessionId,
operation,
quantityOfOperationAttempts: quantityOfAttempts,
} = req.body
mustContainProperties(req, [
'companyId',
'callerId',
'sessionId',
'operation',
])
const apiOperation = await API_Operation.create({
callerId,
companyId,
sessionId,
operation,
quantityOfAttempts
})
res.status(StatusCodes.OK).json({ apiOperation })
}
const registerAll = async (req, res) => {
const {
callerId,
companyId,
sessionId,
lstUsage,
lstRequest,
lstOperation,
} = req.body
if (lstUsage) {
for (const used of lstUsage) {
const { product, provider, usage } = used
const apiPricing = await API_Pricing.findOne({
provider: provider.trim().toLowerCase(),
product: product.trim().toLowerCase(),
})
if (apiPricing) {
const { price, billingBy, billingUnit } = apiPricing
const apiUsage = await API_Usage.create({
provider: provider.trim().toLowerCase(),
product: product.trim().toLowerCase(),
callerId,
sessionId,
usage,
price,
billingBy,
billingUnit,
companyId,
total_cost: calculateApiUsage(price, billingUnit, usage)
})
}
}
}
if (lstRequest) {
for (const request of lstRequest) {
const { type,
requestLogs,
responseError,
quantityOfAPICall } = request
const apiCall = await API_Call.create({
callerId,
companyId,
sessionId,
type,
requestLogs,
responseError,
quantityOfAPICall
})
}
}
if (lstOperation) {
for (const op of lstOperation) {
const { operation, quantityOfOperationAttempts: quantityOfAttempts } = op
const apiOperation = await API_Operation.create({
callerId,
companyId,
sessionId,
operation,
quantityOfAttempts
})
}
}
res.send(StatusCodes.OK)
}
2024-07-30 11:26:42 +00:00
const getUsage = async (req, res) => {
const { startDate, endDate, companyId, } = req.body
mustContainProperties(req, ['startDate', 'endDate', 'companyId'])
const total = await billingSumUsage(startDate, endDate, companyId)
if (total) {
const usage = await API_Usage.find({
createdAt: {
$gte: moment(startDate, 'YYYY-MM-DD').startOf('day').toDate(),
$lte: moment(endDate, 'YYYY-MM-DD').endOf('day').toDate()
},
})
return res.status(StatusCodes.OK).json({ usage, total })
}
return res.status(StatusCodes.NOT_FOUND).json({})
}
module.exports = {
setApiPricing,
2025-06-10 17:15:34 +00:00
setProductPricing,
updateProductPricing,
listProductPricing,
2024-07-30 11:26:42 +00:00
registerUsage,
registerAPICall,
registerOperation,
getUsage,
registerAll,
registerWhatsappUsage
2024-07-30 11:26:42 +00:00
}