Переглянути джерело

feat: adiciona integração de BI do IXC

leonardo 1 місяць тому
батько
коміт
9380444f81

+ 19 - 0
src/controllers/IxcBi.Controller.js

@@ -0,0 +1,19 @@
+import { buscarBi, listarBiPaths } from "../services/ixcBiService.js";
+
+export const IxcBiController = {
+  Proxy: async function (req, res, next) {
+    try {
+      const subpath = req.params[0];
+      const dados = await buscarBi(subpath, req.query);
+      res.json(dados);
+    } catch (err) {
+      next(err);
+    }
+  },
+
+  ListarEndpoints: async function (req, res) {
+    res.json({ endpoints: listarBiPaths() });
+  }
+};
+
+export default IxcBiController;

+ 9 - 0
src/routes/IxcBi.Rotas.js

@@ -0,0 +1,9 @@
+import { Router } from "express";
+import { IxcBiController } from "../controllers/IxcBi.Controller.js";
+
+export const ixcBiRouter = Router();
+
+ixcBiRouter.get("/_endpoints", IxcBiController.ListarEndpoints);
+ixcBiRouter.get("/*", IxcBiController.Proxy);
+
+export default ixcBiRouter;

+ 3 - 0
src/routes/IxcIntegrador.Rotas.js

@@ -1,5 +1,6 @@
 import { Router } from "express";
 import { IxcIntegradorController } from "../controllers/IxcIntegrador.Controller.js";
+import { ixcBiRouter } from "./IxcBi.Rotas.js";
 import { requireUser } from "../middleware/RequireUser.js";
 import { requireAdmin } from "../middleware/RequireAdmin.js";
 import { parseId } from "../middleware/ParseId.js";
@@ -28,4 +29,6 @@ ixcIntegradorRouter.get("/os/assuntos", IxcIntegradorController.ListarAssuntosOs
 ixcIntegradorRouter.get("/os/atendimento/:id", parseId, IxcIntegradorController.ObterAtendimentoOs);
 ixcIntegradorRouter.get("/os/:id", parseId, IxcIntegradorController.ObterOs);
 
+ixcIntegradorRouter.use("/bi", ixcBiRouter);
+
 export default ixcIntegradorRouter;

+ 102 - 0
src/services/ixcBiService.js

@@ -0,0 +1,102 @@
+import { fetchJson } from "./ixcIntegradorService.js";
+
+
+const BI_ALLOWED_PATHS = new Set([
+
+  "cancelamentos/resumo",
+  "cancelamentos/tendencia",
+  "cancelamentos/por-cidade",
+  "cancelamentos/por-bairro",
+  "cancelamentos/por-permanencia",
+  "cancelamentos/motivos",
+  "cancelamentos/vendedores",
+  "cancelamentos/produtos",
+  "cancelamentos/detalhe",
+  "cancelamentos-os/resumo",
+  "cancelamentos-os/motivos-vs-assuntos",
+  "cancelamentos-os/linha-tempo",
+  "cancelamentos-os/detalhe",
+
+  
+
+  "score-risco",
+  "mudanca-pagamento",
+
+
+  "notas/resumo",
+  "notas/geradas-erradas",
+  "notas/nao-geradas-13",
+  "notas/clientes-sem-notas",
+  "notas/contratos-emitidas",
+
+  
+  "ativacoes/por-mes",
+  "ativacoes/relatorio",
+
+
+  "indicadores/backbone/rompimentos",
+  "indicadores/backbone/rompimentos-por-cidade",
+  "indicadores/backbone/implantacao",
+  "indicadores/backbone/implantacao-por-cidade",
+  "indicadores/backbone/adequacao",
+  "indicadores/backbone/adequacao-por-cidade",
+  "indicadores/backbone/rompimento-cto",
+  "indicadores/backbone/rompimento-cto-por-cidade",
+  "indicadores/backbone/ocupacao-cto",
+  "indicadores/backbone/ocupacao-cto-por-projeto",
+
+  
+  "indicadores/suporte/os-total",
+  "indicadores/suporte/os-interno",
+  "indicadores/suporte/os-externo",
+  "indicadores/suporte/os-sam-telecom",
+  "indicadores/suporte/os-alexandre",
+  "indicadores/suporte/os-servicos",
+  "indicadores/suporte/os-telefonia",
+  "indicadores/suporte/os-internet",
+  "indicadores/suporte/os-sem-contrato",
+  "indicadores/suporte/resolucao-interna",
+  "indicadores/suporte/resolucao-externa",
+  "indicadores/suporte/resolucao-sam-telecom",
+  "indicadores/suporte/resolucao-alexandre",
+  "indicadores/suporte/interacoes-interno",
+  "indicadores/suporte/interacoes-externo",
+  "indicadores/suporte/recorrencia-interna",
+  "indicadores/suporte/recorrencia-externa",
+  "indicadores/suporte/recorrencia-sam-telecom",
+  "indicadores/suporte/recorrencia-alexandre",
+  "indicadores/suporte/os-externa-sobre-clientes",
+  "indicadores/suporte/os-externa-sobre-contratos",
+  "indicadores/suporte/por-diagnostico",
+  "indicadores/suporte/retiradas-equipamentos",
+  "indicadores/suporte/tme",
+  "indicadores/suporte/sla-interno",
+  "indicadores/suporte/sla-externo",
+  "indicadores/suporte/produtos-retirados"
+]);
+
+function montarQueryString(query) {
+  const params = new URLSearchParams();
+  for (const [chave, valor] of Object.entries(query ?? {})) {
+    if (valor !== undefined && valor !== null && valor !== "") params.set(chave, valor);
+  }
+  const qs = params.toString();
+  return qs ? `?${qs}` : "";
+}
+
+export function biPathPermitido(subpath) {
+  return BI_ALLOWED_PATHS.has(subpath);
+}
+
+export function listarBiPaths() {
+  return [...BI_ALLOWED_PATHS].sort();
+}
+
+export async function buscarBi(subpath, query) {
+  if (!biPathPermitido(subpath)) {
+    const err = new Error("bi_endpoint_nao_permitido");
+    err.statusCode = 404;
+    throw err;
+  }
+  return fetchJson(`bi/${subpath}${montarQueryString(query)}`);
+}

+ 2 - 4
src/services/ixcIntegradorService.js

@@ -11,7 +11,7 @@ function baseUrlComBarra(url) {
 }
 
 
-async function fetchJson(path, { method = "GET", body } = {}) {
+export async function fetchJson(path, { method = "GET", body } = {}) {
   const integracao = await atualizaTokenIxcIntegradorERetorna();
   const { token } = parseOutros(integracao.Outros);
   const baseUrl = baseUrlComBarra(integracao.Url);
@@ -30,9 +30,7 @@ async function fetchJson(path, { method = "GET", body } = {}) {
     throw err;
   }
 
-  // axios tenta fazer JSON.parse internamente e, se falhar (ex: HTML de erro),
-  // devolve o corpo cru como string em vez de lancar - detectamos isso aqui
-  // pra manter o mesmo contrato de erro que o res.json() do fetch tinha.
+
   if (typeof res.data === "string") {
     const err = new Error("ixc_integrador_invalid_json");
     err.statusCode = 502;