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')
|
2024-07-30 15:01:48 +00:00
|
|
|
const API_Call = require("../models/API_Call.js")
|
|
|
|
const API_Operation = require("../models/API_Operation.js")
|
2024-08-09 13:39:04 +00:00
|
|
|
const API_Usage_Whatsapp = require("../models/API_Usage_Whatsapp.js")
|
2024-07-30 11:26:42 +00:00
|
|
|
|
|
|
|
const setApiPricing = async (req, res) => {
|
|
|
|
|
2025-06-05 19:30:11 +00:00
|
|
|
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'])
|
|
|
|
|
2024-07-30 15:01:48 +00:00
|
|
|
const normalizedProvider = provider.trim().toLowerCase()
|
|
|
|
const normalizedProduct = product.trim().toLowerCase()
|
|
|
|
|
2024-08-09 13:39:04 +00:00
|
|
|
let filter = { provider: normalizedProvider, product: normalizedProduct }
|
|
|
|
|
|
|
|
if (type) {
|
|
|
|
filter = { ...filter, type }
|
|
|
|
}
|
|
|
|
|
2024-07-30 15:01:48 +00:00
|
|
|
const update = {
|
|
|
|
provider: normalizedProvider,
|
|
|
|
product: normalizedProduct,
|
2024-07-30 11:26:42 +00:00
|
|
|
currency,
|
|
|
|
price,
|
|
|
|
billingBy,
|
|
|
|
billingUnit,
|
2025-06-05 19:30:11 +00:00
|
|
|
type,
|
|
|
|
clientPrice
|
2024-07-30 15:01:48 +00:00
|
|
|
}
|
|
|
|
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) => {
|
2024-07-30 15:01:48 +00:00
|
|
|
const {
|
2024-07-30 11:26:42 +00:00
|
|
|
provider,
|
|
|
|
product,
|
|
|
|
usage,
|
2024-07-30 15:01:48 +00:00
|
|
|
callerId,
|
|
|
|
sessionId,
|
2024-08-09 13:39:04 +00:00
|
|
|
companyId,
|
2024-07-30 15:01:48 +00:00
|
|
|
|
2024-07-30 11:26:42 +00:00
|
|
|
} = req.body
|
|
|
|
|
|
|
|
mustContainProperties(req, [
|
|
|
|
'companyId',
|
|
|
|
'callerId',
|
2024-08-09 13:39:04 +00:00
|
|
|
'sessionId',
|
2024-07-30 11:26:42 +00:00
|
|
|
'provider',
|
|
|
|
'product',
|
|
|
|
'usage',
|
2024-07-30 15:01:48 +00:00
|
|
|
])
|
2024-07-30 11:26:42 +00:00
|
|
|
|
|
|
|
const apiPricing = await API_Pricing.findOne({
|
|
|
|
provider: provider.trim().toLowerCase(),
|
|
|
|
product: product.trim().toLowerCase(),
|
|
|
|
})
|
|
|
|
|
2024-07-30 15:01:48 +00:00
|
|
|
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(),
|
2024-07-30 15:01:48 +00:00
|
|
|
product: product.trim().toLowerCase(),
|
|
|
|
callerId,
|
2024-08-09 13:39:04 +00:00
|
|
|
sessionId,
|
2024-07-30 11:26:42 +00:00
|
|
|
usage,
|
|
|
|
price,
|
|
|
|
billingBy,
|
2024-07-30 15:01:48 +00:00
|
|
|
billingUnit,
|
2024-07-30 11:26:42 +00:00
|
|
|
companyId,
|
2024-07-31 13:04:19 +00:00
|
|
|
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` })
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-08-09 13:39:04 +00:00
|
|
|
const registerWhatsappUsage = async (req, res) => {
|
|
|
|
const {
|
|
|
|
companyId,
|
2024-08-13 12:26:46 +00:00
|
|
|
companyPhone,
|
|
|
|
clientPhone,
|
2024-08-09 13:39:04 +00:00
|
|
|
provider,
|
|
|
|
product,
|
|
|
|
type,
|
|
|
|
msgId,
|
|
|
|
ticketId,
|
2024-08-13 12:26:46 +00:00
|
|
|
ticketUrl,
|
2024-08-09 13:39:04 +00:00
|
|
|
billable,
|
|
|
|
pricing_model,
|
|
|
|
} = req.body
|
|
|
|
|
|
|
|
mustContainProperties(req, [
|
|
|
|
'companyId',
|
|
|
|
'provider',
|
|
|
|
'product',
|
|
|
|
'type',
|
|
|
|
'msgId',
|
|
|
|
'ticketId',
|
|
|
|
'billable',
|
2024-08-13 12:26:46 +00:00
|
|
|
'pricing_model',
|
|
|
|
'companyPhone',
|
2025-06-10 17:15:34 +00:00
|
|
|
'clientPhone',
|
2024-08-09 13:39:04 +00:00
|
|
|
])
|
|
|
|
|
|
|
|
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,
|
2024-08-13 12:26:46 +00:00
|
|
|
companyPhone,
|
|
|
|
clientPhone,
|
2024-08-09 13:39:04 +00:00
|
|
|
provider: provider.trim().toLowerCase(),
|
|
|
|
product: product.trim().toLowerCase(),
|
|
|
|
price,
|
|
|
|
msgId,
|
|
|
|
ticketId,
|
2024-08-13 12:26:46 +00:00
|
|
|
ticketUrl,
|
2024-08-09 13:39:04 +00:00
|
|
|
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` })
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-07-30 15:01:48 +00:00
|
|
|
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,
|
2024-07-30 17:25:33 +00:00
|
|
|
quantityOfOperationAttempts: quantityOfAttempts,
|
2024-07-30 15:01:48 +00:00
|
|
|
} = req.body
|
2024-08-09 13:39:04 +00:00
|
|
|
|
2024-07-30 15:01:48 +00:00
|
|
|
mustContainProperties(req, [
|
|
|
|
'companyId',
|
|
|
|
'callerId',
|
|
|
|
'sessionId',
|
2024-08-09 13:39:04 +00:00
|
|
|
'operation',
|
2024-07-30 15:01:48 +00:00
|
|
|
])
|
|
|
|
|
|
|
|
const apiOperation = await API_Operation.create({
|
|
|
|
callerId,
|
|
|
|
companyId,
|
|
|
|
sessionId,
|
2024-07-30 17:25:33 +00:00
|
|
|
operation,
|
|
|
|
quantityOfAttempts
|
2024-07-30 15:01:48 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
res.status(StatusCodes.OK).json({ apiOperation })
|
|
|
|
}
|
|
|
|
|
2024-07-30 17:25:33 +00:00
|
|
|
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,
|
2024-08-09 13:39:04 +00:00
|
|
|
sessionId,
|
2024-07-30 17:25:33 +00:00
|
|
|
usage,
|
|
|
|
price,
|
|
|
|
billingBy,
|
|
|
|
billingUnit,
|
|
|
|
companyId,
|
2024-07-31 13:04:19 +00:00
|
|
|
total_cost: calculateApiUsage(price, billingUnit, usage)
|
2024-07-30 17:25:33 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 13:39:04 +00:00
|
|
|
res.send(StatusCodes.OK)
|
2024-07-30 17:25:33 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2024-07-30 15:01:48 +00:00
|
|
|
registerAPICall,
|
|
|
|
registerOperation,
|
2024-07-30 17:25:33 +00:00
|
|
|
getUsage,
|
2024-08-09 13:39:04 +00:00
|
|
|
registerAll,
|
|
|
|
registerWhatsappUsage
|
2024-07-30 11:26:42 +00:00
|
|
|
}
|