@credithub/harlan-components 1.128.0 → 1.129.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,7 +37,11 @@ var useChartData = function (consultaSerasa, consultaBoaVista) {
37
37
  var _g = useState(false), isProcessing = _g[0], setIsProcessing = _g[1];
38
38
  var _h = useState(false), dataReady = _h[0], setDataReady = _h[1];
39
39
  var lastProgress = useRef(0);
40
- /** Evita reprocessar o mesmo JSON + mesmos totais ao vivo; totais/PJ mudam → nova chave. */
40
+ /**
41
+ * Evita reprocessar em vão. Inclui totais do IEPTB (globalData) para atualizar o pie
42
+ * quando o JSON do DOCUMENTHISTORY for o mesmo; a série `protestos` do gráfico vem
43
+ * só do histórico em `processData` (sem override com IEPTB).
44
+ */
41
45
  var lastProcessSnapshotKey = useRef(null);
42
46
  var processingTimeout = useRef(null);
43
47
  var ctxHistory = useContext(Queries.GraficosAnaliticos);
@@ -75,13 +75,6 @@ export var processData = function (data, quantidadeProcessosJuridicos, totalProt
75
75
  .filter(removeSameAsNext)
76
76
  .map(function (info) { return (__assign(__assign({}, info), { data: parseProtestStringToDate(info.data) })); })
77
77
  .filter(function (info) { return !Number.isNaN(info.data.getTime()); }), function (info) { return info.data; });
78
- /** Alinha o último ponto (data da consulta mais recente no histórico) com os totais ao vivo (mesma fonte que o pie). */
79
- if (totalProtestos !== undefined && data.protestos.length > 0) {
80
- var i = data.protestos.length - 1;
81
- data.protestos[i] = __assign(__assign(__assign({}, data.protestos[i]), { quantidade: totalProtestos }), (valorTotalProtestos !== undefined
82
- ? { valorTotal: valorTotalProtestos }
83
- : {}));
84
- }
85
78
  // ------------------------------------------------------------------
86
79
  // CCFs
87
80
  // ------------------------------------------------------------------
@@ -1,5 +1,4 @@
1
1
  import ProtestosIcon from '../../assets/icones/protestos';
2
- import { useGlobalData } from '../../contexts/globalDataContext';
3
2
  import { formatMoney } from '../../utils/number';
4
3
  import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
5
4
  import AddItemField from '../common/addItem';
@@ -9,7 +8,6 @@ import Section from '../section';
9
8
  import { Queries, RequestStatus } from '../webservice';
10
9
  var ProtestosSP = function () {
11
10
  var ctxLiminar = useContext(Queries.Liminar);
12
- var setData = useGlobalData().setData;
13
11
  var _a = useState(false), dataUpdated = _a[0], setDataUpdated = _a[1];
14
12
  var _b = useState(false), hideSection = _b[0], setHideSection = _b[1];
15
13
  var prevCtxTypeRef = useRef(null);
@@ -28,7 +26,7 @@ var ProtestosSP = function () {
28
26
  setHideSection(true);
29
27
  }
30
28
  prevCtxTypeRef.current = ctxLiminar.type;
31
- }, [ctxLiminar.type, ctxLiminar.document, dataUpdated, setData]);
29
+ }, [ctxLiminar.type, ctxLiminar.document, dataUpdated]);
32
30
  var possuiProtestosSp = useMemo(function () {
33
31
  var _a;
34
32
  if ((ctxLiminar === null || ctxLiminar === void 0 ? void 0 : ctxLiminar.type) === RequestStatus.Success)
@@ -5,14 +5,12 @@ import { useSafeQuery } from '../../hooks/useSafeQuery';
5
5
  import { isDocumentoPF } from '../../utils/string';
6
6
  import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
7
7
  import AddItemField from '../common/addItem';
8
+ import { formatInadPercentDisplay, inadCountPer100, resolveSerasaInadPercent } from './scoreSerasaProbUtils';
8
9
  import { ConsultasComplementaresContext } from '../consultasComplementares';
9
10
  import { Result, ResultContent } from '../interface/result';
10
11
  import StatusMessage from '../interface/statusMessage';
11
12
  import Section from '../section';
12
13
  import { RequestStatus } from '../webservice';
13
- var parseProb = function (raw) {
14
- return typeof raw === 'number' ? raw : Number(String(raw).replace(',', '.')) || 0;
15
- };
16
14
  var ConsultaScoreSerasa = function (_a) {
17
15
  var _b, _c, _d, _e, _f, _g;
18
16
  var documento = _a.documento;
@@ -21,7 +19,14 @@ var ConsultaScoreSerasa = function (_a) {
21
19
  var _h = useState(false), dataUpdated = _h[0], setDataUpdated = _h[1];
22
20
  var _j = useSafeQuery("SELECT FROM 'ScoreSerasa'.'Consulta'", { documento: documento }, (_c = (_b = consultasComplementaresContext === null || consultasComplementaresContext === void 0 ? void 0 : consultasComplementaresContext.consultasComplementares) === null || _b === void 0 ? void 0 : _b.scoreSerasa) === null || _c === void 0 ? void 0 : _c.consultaRealizada), response = _j.response, isLoading = _j.isLoading, error = _j.error, loadingProgress = _j.loadingProgress;
23
21
  var scoreData = (_e = (_d = response === null || response === void 0 ? void 0 : response.document) === null || _d === void 0 ? void 0 : _d.dados) === null || _e === void 0 ? void 0 : _e.score;
24
- var inadProb = parseProb(scoreData === null || scoreData === void 0 ? void 0 : scoreData.probabilidade_inadimplencia);
22
+ var inadResolvido = useMemo(function () {
23
+ return (scoreData === null || scoreData === void 0 ? void 0 : scoreData.score_calculado) === 'S'
24
+ ? resolveSerasaInadPercent({
25
+ pontuacao: scoreData.pontuacao,
26
+ probabilidade_inadimplencia: scoreData.probabilidade_inadimplencia
27
+ })
28
+ : null;
29
+ }, [scoreData]);
25
30
  var scoreRef = useRef(null);
26
31
  var consultaRealizada = useMemo(function () {
27
32
  var _a, _b;
@@ -61,8 +66,12 @@ var ConsultaScoreSerasa = function (_a) {
61
66
  progress: loadingProgress
62
67
  }, title: "Score Serasa", subtitle: "Consulta de Score", icon: ScoreBoaVistaIcon, description: !error && (React.createElement(StatusMessage, { type: scoreData ? 'success' : 'default' }, description)), onSuccess: function () { return (React.createElement(Result, null, scoreData && (React.createElement(ResultContent, { desktop: "repeat(4, 1fr)", tablet: "repeat(3, 1fr)", mobile: "1fr 1fr" },
63
68
  React.createElement(AddItemField, { name: "Score", value: String(scoreData.pontuacao) }),
64
- React.createElement(AddItemField, { name: "Probabilidade de Inadimpl\u00EAncia", value: "".concat(scoreData.probabilidade_inadimplencia, "%") }),
65
- React.createElement(AddItemField, { name: "An\u00E1lise", value: "DE CADA 100 ".concat(isDocumentoPF(documento) ? 'PESSOAS' : 'EMPRESAS', " CLASSIFICADAS NESTA CLASSE DE SCORE, \u00C9 PROV\u00C1VEL QUE ").concat(Math.floor(inadProb), " APRESENTEM D\u00C9BITOS NO MERCADO NOS PR\u00D3XIMOS 6 MESES.") }))))); }, isError: function (err) { return ({
69
+ React.createElement(AddItemField, { name: "Probabilidade de Inadimpl\u00EAncia", value: inadResolvido
70
+ ? formatInadPercentDisplay(inadResolvido.percent0to100)
71
+ : '—' }),
72
+ React.createElement(AddItemField, { name: "An\u00E1lise", value: inadResolvido
73
+ ? "DE CADA 100 ".concat(isDocumentoPF(documento) ? 'PESSOAS' : 'EMPRESAS', " CLASSIFICADAS NESTA CLASSE DE SCORE, \u00C9 PROV\u00C1VEL QUE ").concat(inadCountPer100(inadResolvido.percent0to100), " APRESENTEM D\u00C9BITOS NO MERCADO NOS PR\u00D3XIMOS 6 MESES.")
74
+ : '—' }))))); }, isError: function (err) { return ({
66
75
  children: React.createElement(React.Fragment, null),
67
76
  description: (React.createElement(StatusMessage, { type: "error" },
68
77
  "Erro ao realizar a consulta: ",
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Escala 0–1000 do Score Serasa; fora de faixa é ajustada (clamp).
3
+ */
4
+ export declare function parsePonto1000(pontuacao: unknown): number;
5
+ /**
6
+ * A API preenche probabilidade (0–100) ou vem vazia.
7
+ */
8
+ export declare function isProbFromApiValid(raw: unknown): boolean;
9
+ export declare function inadFromFallbackPontuacao(p: number): number;
10
+ /**
11
+ * Número inteiro 0–100 na frase "de cada 100" (arredondamento do % resolvido).
12
+ */
13
+ export declare function inadCountPer100(percent0to100: number): number;
14
+ /**
15
+ * "99,80%" com duas decimais (formato local).
16
+ */
17
+ export declare function formatInadPercentDisplay(percent0to100: number): string;
18
+ export declare function resolveSerasaInadPercent(rules: {
19
+ pontuacao: unknown;
20
+ probabilidade_inadimplencia: unknown;
21
+ }): {
22
+ percent0to100: number;
23
+ fromApi: boolean;
24
+ };
@@ -0,0 +1,66 @@
1
+ var SCORE_MAX = 1000;
2
+ var parseNumberFlexible = function (raw) {
3
+ if (raw === null || raw === undefined)
4
+ return null;
5
+ if (typeof raw === 'number') {
6
+ return Number.isFinite(raw) ? raw : null;
7
+ }
8
+ var s = String(raw).trim();
9
+ if (s === '')
10
+ return null;
11
+ var n = Number(s.replace(',', '.'));
12
+ return Number.isFinite(n) ? n : null;
13
+ };
14
+ /**
15
+ * Escala 0–1000 do Score Serasa; fora de faixa é ajustada (clamp).
16
+ */
17
+ export function parsePonto1000(pontuacao) {
18
+ var n = parseNumberFlexible(pontuacao);
19
+ if (n === null)
20
+ return 0;
21
+ return Math.min(SCORE_MAX, Math.max(0, n));
22
+ }
23
+ /**
24
+ * A API preenche probabilidade (0–100) ou vem vazia.
25
+ */
26
+ export function isProbFromApiValid(raw) {
27
+ if (raw === null || raw === undefined)
28
+ return false;
29
+ if (typeof raw === 'string' && raw.trim() === '')
30
+ return false;
31
+ var n = parseNumberFlexible(raw);
32
+ return n !== null;
33
+ }
34
+ var parseApiProbPercent = function (raw) {
35
+ var n = parseNumberFlexible(raw);
36
+ return n === null ? 0 : n;
37
+ };
38
+ export function inadFromFallbackPontuacao(p) {
39
+ return ((SCORE_MAX - p) / SCORE_MAX) * 100;
40
+ }
41
+ /**
42
+ * Número inteiro 0–100 na frase "de cada 100" (arredondamento do % resolvido).
43
+ */
44
+ export function inadCountPer100(percent0to100) {
45
+ return Math.min(100, Math.max(0, Math.round(percent0to100)));
46
+ }
47
+ var percentFormatter = new Intl.NumberFormat('pt-BR', {
48
+ minimumFractionDigits: 2,
49
+ maximumFractionDigits: 2
50
+ });
51
+ /**
52
+ * "99,80%" com duas decimais (formato local).
53
+ */
54
+ export function formatInadPercentDisplay(percent0to100) {
55
+ return "".concat(percentFormatter.format(percent0to100), "%");
56
+ }
57
+ export function resolveSerasaInadPercent(rules) {
58
+ var p = parsePonto1000(rules.pontuacao);
59
+ if (isProbFromApiValid(rules.probabilidade_inadimplencia)) {
60
+ return {
61
+ percent0to100: parseApiProbPercent(rules.probabilidade_inadimplencia),
62
+ fromApi: true
63
+ };
64
+ }
65
+ return { percent0to100: inadFromFallbackPontuacao(p), fromApi: false };
66
+ }
@@ -1,6 +1,6 @@
1
1
  import { __assign } from "tslib";
2
2
  // src/contexts/createDataContext.tsx
3
- import React, { createContext, useContext, useState } from 'react';
3
+ import React, { createContext, useCallback, useContext, useState } from 'react';
4
4
  function createDataContext(defaultValue) {
5
5
  if (defaultValue === void 0) { defaultValue = {}; }
6
6
  var DataContext = createContext({
@@ -25,12 +25,12 @@ function createDataContext(defaultValue) {
25
25
  var DataProvider = function (_a) {
26
26
  var children = _a.children;
27
27
  var _b = useState(createProxy(defaultValue)), data = _b[0], setData = _b[1];
28
- var updateData = function (update) {
28
+ var updateData = useCallback(function (update) {
29
29
  setData(function (prevData) {
30
30
  var newState = typeof update === 'function' ? update(prevData) : update;
31
31
  return createProxy(__assign(__assign({}, prevData), newState));
32
32
  });
33
- };
33
+ }, []);
34
34
  return (React.createElement(DataContext.Provider, { value: { data: data, setData: updateData } }, children));
35
35
  };
36
36
  var useData = function () { return useContext(DataContext); };