From 14c0303c787b66a4ed9dd5abf53e2d9ad0898765 Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 30 Jul 2024 12:01:48 -0300 Subject: [PATCH] feat: add routes for external API requests and operation logs, add sessionId property --- app.js | 10 +-- controllers/apiUsagePricing.js | 115 ++++++++++++++++++++++++--------- models/API_Call.js | 36 +++++++++++ models/API_Operation.js | 27 ++++++++ models/API_Usage.js | 50 +++++++------- routes/apiPriceRoute.js | 4 +- swagger.yaml | 50 ++++++++------ 7 files changed, 214 insertions(+), 78 deletions(-) create mode 100644 models/API_Call.js create mode 100644 models/API_Operation.js diff --git a/app.js b/app.js index 0d2de8e..6155eb1 100644 --- a/app.js +++ b/app.js @@ -28,13 +28,13 @@ const notFoundMiddlware = require('./middleware/not-found') //middleware app.set('trust proxy', 1) -app.use(rateLimiter({ - windowMs: 15 * 60 * 1000, - max: 60, -})) +// app.use(rateLimiter({ +// windowMs: 15 * 60 * 1000, +// max: 60, +// })) // Security packages -app.use(helmet()) +// app.use(helmet()) app.use(cors()) app.use(xss()) diff --git a/controllers/apiUsagePricing.js b/controllers/apiUsagePricing.js index d4d6b03..46b8b6f 100644 --- a/controllers/apiUsagePricing.js +++ b/controllers/apiUsagePricing.js @@ -7,6 +7,8 @@ const { const API_Usage = require("../models/API_Usage.js") 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 setApiPricing = async (req, res) => { @@ -18,74 +20,67 @@ const setApiPricing = async (req, res) => { 'billingBy', 'billingUnit']) - const apiPricing = await API_Pricing.create({ - provider: provider.trim().toLowerCase(), - product: product.trim().toLowerCase(), + const normalizedProvider = provider.trim().toLowerCase() + const normalizedProduct = product.trim().toLowerCase() + + const filter = { provider: normalizedProvider, product: normalizedProduct } + const update = { + provider: normalizedProvider, + product: normalizedProduct, currency, price, billingBy, billingUnit, type - }) + } + const options = { new: true, upsert: true } + + const apiPricing = await API_Pricing.findOneAndUpdate(filter, update, options) res.status(StatusCodes.OK).json({ apiPricing }) } const registerUsage = async (req, res) => { - const { + const { provider, product, usage, - callerId, + callerId, + sessionId, companyId, quantityOfOperationAttempts, - chosenOperation, - requestLogsOpenAI, - responseErrorLogsOpenAI, - quantityOfCallsToFalconFlowAPI, - requestLogsFalconFlowAPI, - responseErrorLogsFalconFlowAPI, + } = req.body mustContainProperties(req, [ 'companyId', 'callerId', + 'sessionId', 'quantityOfOperationAttempts', - 'chosenOperation', - 'requestLogsOpenAI', - // 'responseErrorLogsOpenAI', - 'quantityOfCallsToFalconFlowAPI', - 'requestLogsFalconFlowAPI', - // 'responseErrorLogsFalconFlowAPI', 'provider', 'product', 'usage', - ]) + ]) const apiPricing = await API_Pricing.findOne({ provider: provider.trim().toLowerCase(), product: product.trim().toLowerCase(), }) - - if (apiPricing) { - const { price, billingBy, billingUnit } = apiPricing + if (apiPricing) { + + const { price, billingBy, billingUnit } = apiPricing const apiUsage = await API_Usage.create({ provider: provider.trim().toLowerCase(), - product: product.trim().toLowerCase(), - callerId, + product: product.trim().toLowerCase(), + callerId, + sessionId, quantityOfOperationAttempts, - chosenOperation, - requestLogsOpenAI, - responseErrorLogsOpenAI, - quantityOfCallsToFalconFlowAPI, - requestLogsFalconFlowAPI, - responseErrorLogsFalconFlowAPI, usage, price, billingBy, - billingUnit, + billingUnit, companyId, total_cost: calculateApiUsage(price, billingUnit, usage, billingBy) }) @@ -98,6 +93,62 @@ const registerUsage = async (req, res) => { } +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, + } = req.body + + mustContainProperties(req, [ + 'companyId', + 'callerId', + 'sessionId', + 'operation' + ]) + + const apiOperation = await API_Operation.create({ + callerId, + companyId, + sessionId, + operation + }) + + res.status(StatusCodes.OK).json({ apiOperation }) +} + const getUsage = async (req, res) => { const { startDate, endDate, companyId, } = req.body @@ -124,5 +175,7 @@ const getUsage = async (req, res) => { module.exports = { setApiPricing, registerUsage, + registerAPICall, + registerOperation, getUsage } \ No newline at end of file diff --git a/models/API_Call.js b/models/API_Call.js new file mode 100644 index 0000000..9428815 --- /dev/null +++ b/models/API_Call.js @@ -0,0 +1,36 @@ +const mongoose = require('../db/connect') + +const { Schema } = mongoose + +const apiCall = new Schema({ + companyId: { + type: String, + required: true, + }, + callerId: { + type: String, + required: true, + }, + sessionId: { + type: String, + required: true, + }, + type: { + type: String, + enum: ['IAProvider', 'externalAPI',], + }, + requestLogs: { + type: String, + }, + responseError: { + type: String, + }, + quantityOfAPICall: { + type: String, + }, + +}, { timestamps: true }) + +const API_Call = mongoose.model('API_Call', apiCall) + +module.exports = API_Call diff --git a/models/API_Operation.js b/models/API_Operation.js new file mode 100644 index 0000000..68b9260 --- /dev/null +++ b/models/API_Operation.js @@ -0,0 +1,27 @@ +const mongoose = require('../db/connect') + +const { Schema } = mongoose + +const apiOperation = new Schema({ + companyId: { + type: String, + required: true, + }, + callerId: { + type: String, + required: true, + }, + sessionId: { + type: String, + required: true, + }, + operation: { + type: String, + required: true, + }, + +}, { timestamps: true }) + +const API_Operation = mongoose.model('API_Operation', apiOperation) + +module.exports = API_Operation diff --git a/models/API_Usage.js b/models/API_Usage.js index 355c74e..2976524 100644 --- a/models/API_Usage.js +++ b/models/API_Usage.js @@ -11,33 +11,37 @@ const apiUsage = new Schema({ type: String, required: true, }, + sessionId: { + type: String, + required: true, + }, quantityOfOperationAttempts: { type: String, required: true, }, - chosenOperation: { - type: String, - required: true, - }, - requestLogsOpenAI: { - type: String, - required: true, - }, - responseErrorLogsOpenAI: { - type: String, - }, - quantityOfCallsToFalconFlowAPI: { - type: String, - required: true, - }, - requestLogsFalconFlowAPI: { - type: String, - required: true, - }, - responseErrorLogsFalconFlowAPI: { - type: String, - required: true, - }, + // chosenOperation: { + // type: String, + // required: true, + // }, + // requestLogsOpenAI: { + // type: String, + // required: true, + // }, + // responseErrorLogsOpenAI: { + // type: String, + // }, + // quantityOfCallsToFalconFlowAPI: { + // type: String, + // required: true, + // }, + // requestLogsFalconFlowAPI: { + // type: String, + // required: true, + // }, + // responseErrorLogsFalconFlowAPI: { + // type: String, + // required: true, + // }, provider: { type: String, required: true, diff --git a/routes/apiPriceRoute.js b/routes/apiPriceRoute.js index 7b60b21..e06423e 100644 --- a/routes/apiPriceRoute.js +++ b/routes/apiPriceRoute.js @@ -1,11 +1,13 @@ const express = require('express') const router = express.Router() const { authorization, } = require('../middleware/authentication') -const { setApiPricing, registerUsage, getUsage} = require('../controllers/apiUsagePricing') +const { setApiPricing, registerUsage, getUsage, registerAPICall, registerOperation} = require('../controllers/apiUsagePricing') router.route('/create').post(authorization, setApiPricing) router.route('/usage').post(authorization, registerUsage) router.route('/report').post(authorization, getUsage) +router.route('/api-call').post(authorization, registerAPICall) +router.route('/api-operation').post(authorization, registerOperation) diff --git a/swagger.yaml b/swagger.yaml index 4ea56dd..0b7ddb9 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -24,68 +24,82 @@ paths: properties: companyId: type: string - description: Company identifier example: "1" callerId: type: string - description: Identifier of the person who made the call example: "17988310949" quantityOfOperationAttempts: type: string - description: Number of attempts to perform the operation made by the person who made the call example: "2" chosenOperation: type: string - description: Operation chosen by the person who made the call example: "unblokUser" requestLogsOpenAI: type: string - description: Response logs of requests made to openai example: "{}" responseErrorLogsOpenAI: type: string - description: Openai error request response logs example: "{}" quantityOfCallsToFalconFlowAPI: type: string - description: Number of requests made to third-party api example: "2" requestLogsFalconFlowAPI: type: string - description: Response logs of requests made to third-party api example: "{}" responseErrorLogsFalconFlowAPI: type: string - description: Third-party api error request response logs example: "{}" provider: type: string - description: Identifier of the organization providing the AI ​​solution example: "openai" product: type: string - description: Product provided by the organization that is providing AI solution example: "whisper" usage: - type: integer - description: "Using the API. The product Whisper should be sent in seconds" - example: 15 + type: string + description: "Time in seconds" + example: "15" required: - companyId - callerId - quantityOfOperationAttempts - chosenOperation - - requestLogsOpenAI + - requestLogsOpenAI + - responseErrorLogsOpenAI - quantityOfCallsToFalconFlowAPI - - requestLogsFalconFlowAPI + - requestLogsFalconFlowAPI + - responseErrorLogsFalconFlowAPI - provider - product - usage required: true responses: '200': - description: '' - headers: {} + description: 'Successful response' + content: + application/json: + example: + apiUsage: + companyId: "1" + callerId: "17988310949" + quantityOfOperationAttempts: "2" + chosenOperation: "unblokUser" + requestLogsOpenAI: "{}" + responseErrorLogsOpenAI: "{}" + quantityOfCallsToFalconFlowAPI: "2" + requestLogsFalconFlowAPI: "{}" + responseErrorLogsFalconFlowAPI: "{}" + provider: "openai" + product: "whisper" + usage: 15 + price: "0.006" + billingBy: "minute" + billingUnit: 1 + total_cost: "0.0015000000" + _id: "66a8df390cbb7371c4ade653" + createdAt: "2024-07-30T12:40:25.782Z" + updatedAt: "2024-07-30T12:40:25.782Z" + __v: 0 deprecated: false security: - bearer: []