@credithub/harlan-components 1.125.0 → 1.127.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.
package/README.md CHANGED
@@ -30,3 +30,18 @@ Para começar a usar o **Harlan Components** em seu projeto, siga estes passos:
30
30
  ```
31
31
 
32
32
  3. **Implementação:** Integre os componentes importados em sua aplicação.
33
+
34
+ ## Consumindo sem tag API
35
+
36
+ Quando a aplicação injeta a chave em código (em vez de repassar só via URL), envolva a árvore com `WebServiceProvider` e, se o backend exigir resolução Jurischain (challenges HTTP 402), aumente o tempo de espera com `webserviceOptions`:
37
+
38
+ ```tsx
39
+ import { WebServiceProvider } from '@credithub/harlan-components';
40
+
41
+ <WebServiceProvider
42
+ credential={apiKey}
43
+ webserviceOptions={{ jurischain: { solveTimeout: 120_000 } }}
44
+ >
45
+ {children}
46
+ </WebServiceProvider>
47
+ ```
@@ -2,7 +2,7 @@ import { __assign, __awaiter, __generator, __makeTemplateObject } from "tslib";
2
2
  import ResumoDeNegativacoesIcon from '../../assets/icones/resumoNegativacoes';
3
3
  import { useGlobalData } from '../../contexts/globalDataContext';
4
4
  import { useConsultasComplementares } from '../../hooks/useConsultasComplementares';
5
- import { converterParaFormatoValido } from '../../utils/date';
5
+ import { converterParaFormatoValido, parseProtestHistoryRowToTime } from '../../utils/date';
6
6
  import { areModulesLoaded } from '../../utils/isGlobalReady';
7
7
  import { formatMoney } from '../../utils/number';
8
8
  import { isCpf } from '../../utils/string';
@@ -133,13 +133,23 @@ var ChartSystem = function (_a) {
133
133
  if (!dataUpdated && chartData && modulesReady) {
134
134
  var protestoHistory_1 = (_b = (_a = chartData.protestos) === null || _a === void 0 ? void 0 : _a.map(function (p) {
135
135
  var _a, _b;
136
- return ({
136
+ var t = parseProtestHistoryRowToTime(p);
137
+ var dataStr = t
138
+ ? new Date(t).toISOString()
139
+ : typeof p.data === 'string'
140
+ ? p.data
141
+ : p.data instanceof Date
142
+ ? p.data.toISOString()
143
+ : '';
144
+ return {
137
145
  documento: documento,
138
- data: typeof p.data === 'string' ? p.data : p.data.toISOString(),
146
+ data: dataStr,
139
147
  quantidade: (_a = p.quantidade) !== null && _a !== void 0 ? _a : 0,
140
148
  valorTotal: (_b = p.valorTotal) !== null && _b !== void 0 ? _b : 0
141
- });
142
- }).sort(function (a, b) { return new Date(a.data).getTime() - new Date(b.data).getTime(); })) !== null && _b !== void 0 ? _b : [];
149
+ };
150
+ }).sort(function (a, b) {
151
+ return parseProtestHistoryRowToTime(a) - parseProtestHistoryRowToTime(b);
152
+ })) !== null && _b !== void 0 ? _b : [];
143
153
  var protestoLiminar_1 = calcularProtestoLiminar(protestoHistory_1);
144
154
  // Cria assinatura estável para evitar setState repetido
145
155
  var signature = JSON.stringify({
@@ -1,8 +1,8 @@
1
1
  import { Queries, RequestStatus } from '../../../components/webservice';
2
2
  import { useGlobalData } from '../../../contexts/globalDataContext';
3
- import { converterParaFormatoValido, formatDatePtBrToDate } from '../../../utils/date';
3
+ import { formatDatePtBrToDate, parseProtestDateToTime } from '../../../utils/date';
4
4
  import { useContext, useEffect, useMemo, useRef, useState } from 'react';
5
- import { processData, processProtestData } from '../utils/dataProcessing';
5
+ import { normalizeRawProtestosFirstSeen, processData, processProtestData } from '../utils/dataProcessing';
6
6
  function getLastQuantidadeProcessosFromHistory(parsed) {
7
7
  var _a;
8
8
  var arr = parsed === null || parsed === void 0 ? void 0 : parsed.processosJuridicos;
@@ -66,17 +66,7 @@ var useChartData = function (consultaSerasa, consultaBoaVista) {
66
66
  return null;
67
67
  var datas = protestos
68
68
  .map(function (p) {
69
- try {
70
- var dataStr = p.dataProtesto || '';
71
- if (!dataStr)
72
- return null;
73
- var formattedDate = converterParaFormatoValido(dataStr);
74
- var date = new Date(formattedDate);
75
- return isNaN(date.getTime()) ? null : date.getTime();
76
- }
77
- catch (_a) {
78
- return null;
79
- }
69
+ return parseProtestDateToTime(p.dataProtesto || p.firstSeen);
80
70
  })
81
71
  .filter(function (d) { return d !== null; });
82
72
  return datas.length
@@ -222,6 +212,7 @@ var useChartData = function (consultaSerasa, consultaBoaVista) {
222
212
  throw new Error('Document is undefined');
223
213
  }
224
214
  var parsed = JSON.parse(documentSnapshot_1);
215
+ normalizeRawProtestosFirstSeen(parsed);
225
216
  parsed.protestosCategory = dadosProtestos;
226
217
  var quantidadeProcessos = quantidadeProcessosFromPJ !== null && quantidadeProcessosFromPJ !== void 0 ? quantidadeProcessosFromPJ : getLastQuantidadeProcessosFromHistory(parsed);
227
218
  var processed = processData(structuredClone(parsed), quantidadeProcessos, totalProtestos, valorTotalProtestos, ultimaOcorrenciaProtestos);
@@ -1,12 +1,20 @@
1
1
  import { REGEX_PROTESTOS_DE_CREDITO, REGEX_PROTESTOS_DE_IMPOSTO } from '../../../constants/regex';
2
- import { formatDatePtBrToDate } from '../../../utils/date';
2
+ import { parseProtestDateToTime } from '../../../utils/date';
3
+ import { xmlFirstSeenFromNode } from '../../../utils/parseProtesto';
3
4
  import XPathUtils from '../../../utils/xpath';
4
5
  import { useMemo } from 'react';
5
6
  // Função de ordenação por data
7
+ var protestoEffectiveDate = function (node) {
8
+ var _a;
9
+ var dp = XPathUtils.select('string(./dataProtesto)', node);
10
+ if (typeof dp === 'string' && dp.trim())
11
+ return dp.trim();
12
+ return (_a = xmlFirstSeenFromNode(node)) !== null && _a !== void 0 ? _a : '';
13
+ };
6
14
  var byDate = function (protesto, protesto2) {
7
15
  var _a, _b;
8
- var v0 = ((_a = formatDatePtBrToDate(XPathUtils.select('string(./dataProtesto)', protesto2))) === null || _a === void 0 ? void 0 : _a.getTime()) || 0;
9
- var v1 = ((_b = formatDatePtBrToDate(XPathUtils.select('string(./dataProtesto)', protesto))) === null || _b === void 0 ? void 0 : _b.getTime()) || 0;
16
+ var v0 = (_a = parseProtestDateToTime(protestoEffectiveDate(protesto2))) !== null && _a !== void 0 ? _a : 0;
17
+ var v1 = (_b = parseProtestDateToTime(protestoEffectiveDate(protesto))) !== null && _b !== void 0 ? _b : 0;
10
18
  return v0 - v1;
11
19
  };
12
20
  export function classifyProtestos(document, iaOverrides) {
@@ -6,6 +6,8 @@ export interface Consulta {
6
6
  creation?: string | Date;
7
7
  valorTotal?: number | null;
8
8
  total?: number | null;
9
+ /** Fallback de data quando `data` vem vazia (datalake `toArray()`: `firstSeen`; JSON cru pode vir como `first_seen` — normalizado em useChartData). */
10
+ firstSeen?: string;
9
11
  }
10
12
  export interface DataInput {
11
13
  ccfs: Consulta[];
@@ -1,4 +1,6 @@
1
1
  import { DataInput } from '../../../components/chart/types/iChart';
2
+ /** JSON cru pode trazer `first_seen`; unifica em `firstSeen` antes de processData. */
3
+ export declare function normalizeRawProtestosFirstSeen(data: DataInput): void;
2
4
  /**
3
5
  * Normaliza todos os datasets do DataInput.
4
6
  */
@@ -1,6 +1,6 @@
1
- import { __assign } from "tslib";
1
+ import { __assign, __rest } from "tslib";
2
2
  import { classifyProtestos } from '../../../hooks/useProtestosClassification';
3
- import { converterParaFormatoValido, formatDatePtBrToDate } from '../../../utils/date';
3
+ import { formatDatePtBrToDate, parseProtestDateToTime, parseProtestStringToDate } from '../../../utils/date';
4
4
  import { parseProtesto } from '../../../utils/parseProtesto';
5
5
  import XPathUtils from '../../../utils/xpath';
6
6
  import { groupBy, sortBy, unique } from 'underscore';
@@ -19,10 +19,29 @@ var removeSameAsNext = function (current, index, arr) {
19
19
  return true;
20
20
  return current.quantidade !== arr[index - 1].quantidade;
21
21
  };
22
- /** Converte chave de agrupamento (string) em timestamp ordenável. */
23
- var keyToTime = function (key) {
24
- return new Date(formatDatePtBrToDate(key)).getTime();
22
+ var protestoHistoricoDataEfetiva = function (e) {
23
+ if (typeof e.data === 'string' && e.data.trim())
24
+ return e.data.trim();
25
+ if (e.data instanceof Date && !Number.isNaN(e.data.getTime())) {
26
+ return e.data.toISOString().slice(0, 10);
27
+ }
28
+ var fs = e.firstSeen;
29
+ return typeof fs === 'string' && fs.trim() ? fs.trim() : '';
25
30
  };
31
+ /** JSON cru pode trazer `first_seen`; unifica em `firstSeen` antes de processData. */
32
+ export function normalizeRawProtestosFirstSeen(data) {
33
+ data.protestos = data.protestos.map(function (row) {
34
+ var extra = row;
35
+ var merged = (typeof extra.firstSeen === 'string' && extra.firstSeen.trim()) ||
36
+ (typeof extra.first_seen === 'string' && extra.first_seen.trim()) ||
37
+ undefined;
38
+ var _snake = extra.first_seen, rest = __rest(extra, ["first_seen"]);
39
+ if (!merged)
40
+ return rest;
41
+ return __assign(__assign({}, rest), { firstSeen: merged });
42
+ });
43
+ }
44
+ var protestoKeyToTime = function (key) { var _a; return (_a = parseProtestDateToTime(key)) !== null && _a !== void 0 ? _a : 0; };
26
45
  /**
27
46
  * Normaliza todos os datasets do DataInput.
28
47
  */
@@ -30,12 +49,18 @@ export var processData = function (data, quantidadeProcessosJuridicos, totalProt
30
49
  // ------------------------------------------------------------------
31
50
  // PROTESTOS
32
51
  // ------------------------------------------------------------------
52
+ data.protestos = data.protestos.map(function (e) {
53
+ var merged = protestoHistoricoDataEfetiva(e);
54
+ if (!merged)
55
+ return e;
56
+ return __assign(__assign({}, e), { data: merged });
57
+ });
33
58
  var grouped = groupBy(data.protestos, function (e) { return e.data; });
34
59
  // transforma em array ordenado por data asc
35
60
  var groupedOrdered = Object.entries(grouped).sort(function (_a, _b) {
36
61
  var kA = _a[0];
37
62
  var kB = _b[0];
38
- return keyToTime(kA) - keyToTime(kB);
63
+ return protestoKeyToTime(kA) - protestoKeyToTime(kB);
39
64
  });
40
65
  data.protestos = groupedOrdered
41
66
  .map(function (_a) {
@@ -48,8 +73,8 @@ export var processData = function (data, quantidadeProcessosJuridicos, totalProt
48
73
  data.protestos = sortBy(unique(data.protestos, function (x) { return x.data; })
49
74
  .filter(removeZeros)
50
75
  .filter(removeSameAsNext)
51
- .map(function (info) { return (__assign(__assign({}, info), { data: formatDatePtBrToDate(info.data) // normaliza p/ ISO local
52
- })); }), function (info) { return info.data; });
76
+ .map(function (info) { return (__assign(__assign({}, info), { data: parseProtestStringToDate(info.data) })); })
77
+ .filter(function (info) { return !Number.isNaN(info.data.getTime()); }), function (info) { return info.data; });
53
78
  // ------------------------------------------------------------------
54
79
  // CCFs
55
80
  // ------------------------------------------------------------------
@@ -112,14 +137,12 @@ export function processProtestData(document, iaOverrides) {
112
137
  // Converte Node[] para Protesto[]
113
138
  var protestos = XPathUtils.selectArray('//body//protesto', document).map(parseProtesto);
114
139
  var _a = classifyProtestos(protestos, iaOverrides), protestosDeCredito = _a.protestosDeCredito, protestosDeImposto = _a.protestosDeImposto, protestosGerais = _a.protestosGerais;
115
- var obterUltimaData = function (protestos) {
116
- if (!protestos.length)
140
+ var obterUltimaData = function (lista) {
141
+ if (!lista.length)
117
142
  return null;
118
- var datas = protestos
119
- .map(function (p) {
120
- return new Date(converterParaFormatoValido(p.dataProtesto)).getTime();
121
- })
122
- .filter(function (d) { return !isNaN(d); });
143
+ var datas = lista
144
+ .map(function (p) { return parseProtestDateToTime(p.dataProtesto || p.firstSeen); })
145
+ .filter(function (d) { return d !== null; });
123
146
  return datas.length
124
147
  ? new Date(Math.max.apply(Math, datas)).toLocaleDateString('pt-BR')
125
148
  : null;
@@ -1,5 +1,6 @@
1
1
  import { __assign, __rest, __spreadArray } from "tslib";
2
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { parseProtestHistoryRowToTime } from '../../../utils/date';
3
4
  import { normalizeName, similarNames } from '../../../utils/similarNames';
4
5
  import { safeStringify } from './responseUtils';
5
6
  // -----------------------------------------------------------------------------
@@ -86,7 +87,9 @@ export var selectRelevantData = function (data) {
86
87
  var ultimaOcorrenciaProtestos = ResumoSafe === null || ResumoSafe === void 0 ? void 0 : ResumoSafe.ultimaOcorrenciaProtestos;
87
88
  if (Array.isArray(ResumoSafe === null || ResumoSafe === void 0 ? void 0 : ResumoSafe.protestoHistory) &&
88
89
  ResumoSafe.protestoHistory.length) {
89
- var latest = __spreadArray([], ResumoSafe.protestoHistory, true).sort(function (a, b) { return new Date(b.data).getTime() - new Date(a.data).getTime(); })[0];
90
+ var latest = __spreadArray([], ResumoSafe.protestoHistory, true).sort(function (a, b) {
91
+ return parseProtestHistoryRowToTime(b) - parseProtestHistoryRowToTime(a);
92
+ })[0];
90
93
  var latestWithCorrectDate = ultimaOcorrenciaProtestos
91
94
  ? __assign(__assign({}, latest), { data: ultimaOcorrenciaProtestos }) : latest;
92
95
  protestosData = [latestWithCorrectDate];
@@ -9,18 +9,12 @@ type RequestDefaults = {
9
9
  urlData?: Client.Form;
10
10
  };
11
11
  export declare const RequestDefaultsContext: React.Context<RequestDefaults>;
12
- /** Alinhado ao `WebServiceOptions` do `@credithub/webservice` com Jurischain (4.º arg. do construtor). Em runtime exige pacote com fluxo HTTP 402; tipos npm antigos não declaram o 4.º parâmetro. */
13
- export type WebServiceProviderOptions = {
14
- jurischain?: {
15
- enabled?: boolean;
16
- solveTimeout?: number;
17
- };
18
- };
12
+ export type WebServiceProviderOptions = Client.WebServiceOptions;
19
13
  export declare const WebServiceProvider: FC<PropsWithChildren<{
20
14
  credential: string;
21
15
  defaultData?: Client.Form;
22
16
  defaultUrlData?: Client.Form;
23
- /** Ex.: `{ jurischain: { solveTimeout: 120_000 } }` quando usar `@credithub/webservice` com Jurischain. */
17
+ /** Jurischain (challenges HTTP 402). Ex.: `{ jurischain: { solveTimeout: 120_000 } }`. */
24
18
  webserviceOptions?: WebServiceProviderOptions;
25
19
  }>>;
26
20
  export declare function CustomProvider<T extends Client.Form = Client.Form, R = unknown>(Provider: Context<RequestContext<R>>, query: string): FC<PropsWithChildren<{
@@ -6,10 +6,9 @@ import { RequestStatus } from './requestContextTypes';
6
6
  export * from './requestContextTypes';
7
7
  export var WebService = createContext(new Client.WebService());
8
8
  export var RequestDefaultsContext = createContext({});
9
- var WebServiceClient = Client.WebService;
10
9
  export var WebServiceProvider = function (_a) {
11
10
  var credential = _a.credential, defaultData = _a.defaultData, defaultUrlData = _a.defaultUrlData, webserviceOptions = _a.webserviceOptions, children = _a.children;
12
- return (React.createElement(WebService.Provider, { value: new WebServiceClient(credential, {}, 5, webserviceOptions !== null && webserviceOptions !== void 0 ? webserviceOptions : {}) },
11
+ return (React.createElement(WebService.Provider, { value: new Client.WebService(credential, {}, 5, webserviceOptions !== null && webserviceOptions !== void 0 ? webserviceOptions : {}) },
13
12
  React.createElement(RequestDefaultsContext.Provider, { value: { data: defaultData, urlData: defaultUrlData } }, children)));
14
13
  };
15
14
  var isDocument = function (value) {
@@ -1,11 +1,11 @@
1
1
  import { REGEX_PROTESTOS_DE_CREDITO, REGEX_PROTESTOS_DE_IMPOSTO } from '../constants/regex';
2
- import { formatDatePtBrToDate } from '../utils/date';
2
+ import { parseProtestDateToTime } from '../utils/date';
3
3
  import { useMemo } from 'react';
4
4
  // Função de ordenação por data
5
5
  var byDate = function (a, b) {
6
6
  var _a, _b;
7
- var v0 = ((_a = formatDatePtBrToDate(b.dataProtesto)) === null || _a === void 0 ? void 0 : _a.getTime()) || 0;
8
- var v1 = ((_b = formatDatePtBrToDate(a.dataProtesto)) === null || _b === void 0 ? void 0 : _b.getTime()) || 0;
7
+ var v0 = (_a = parseProtestDateToTime(b.dataProtesto || b.firstSeen)) !== null && _a !== void 0 ? _a : 0;
8
+ var v1 = (_b = parseProtestDateToTime(a.dataProtesto || a.firstSeen)) !== null && _b !== void 0 ? _b : 0;
9
9
  return v0 - v1;
10
10
  };
11
11
  export function classifyProtestos(protestos, iaOverrides) {
@@ -2,3 +2,14 @@ export declare function isDate(date: string | Date): boolean;
2
2
  export declare function parseDate(dateStr: string): Date;
3
3
  export declare function converterParaFormatoValido(data: string): string;
4
4
  export declare function formatDatePtBrToDate(date: string): Date;
5
+ /**
6
+ * Parses protest-related date strings (ISO `yyyy-MM-dd` or pt-BR `dd/MM/yyyy`).
7
+ * Used for `dataProtesto` / `data` e fallback `firstSeen` (ex.: XML `first_seen` → objeto com `firstSeen`).
8
+ */
9
+ export declare function parseProtestDateToTime(value: string | undefined | null): number | null;
10
+ /** Converte string de protesto/histórico (ISO ou pt-BR) em `Date` para armazenar em `Consulta.data`. */
11
+ export declare function parseProtestStringToDate(value: string | Date | undefined | null): Date;
12
+ /** Timestamp a partir de `data` já materializada (histórico gravado / pós-processData). */
13
+ export declare function parseProtestHistoryRowToTime(row: {
14
+ data?: string | Date;
15
+ }): number;
@@ -18,3 +18,40 @@ export function formatDatePtBrToDate(date) {
18
18
  var b = (x === null || x === void 0 ? void 0 : x.join('-')) + 'T00:00';
19
19
  return new Date(b);
20
20
  }
21
+ /**
22
+ * Parses protest-related date strings (ISO `yyyy-MM-dd` or pt-BR `dd/MM/yyyy`).
23
+ * Used for `dataProtesto` / `data` e fallback `firstSeen` (ex.: XML `first_seen` → objeto com `firstSeen`).
24
+ */
25
+ export function parseProtestDateToTime(value) {
26
+ if (value == null)
27
+ return null;
28
+ var s = String(value).trim();
29
+ if (!s)
30
+ return null;
31
+ if (/^\d{4}-\d{2}-\d{2}/.test(s)) {
32
+ var t_1 = new Date(s).getTime();
33
+ return Number.isNaN(t_1) ? null : t_1;
34
+ }
35
+ if (s.includes('/')) {
36
+ var t_2 = formatDatePtBrToDate(s).getTime();
37
+ return Number.isNaN(t_2) ? null : t_2;
38
+ }
39
+ var t = new Date(s).getTime();
40
+ return Number.isNaN(t) ? null : t;
41
+ }
42
+ /** Converte string de protesto/histórico (ISO ou pt-BR) em `Date` para armazenar em `Consulta.data`. */
43
+ export function parseProtestStringToDate(value) {
44
+ if (value instanceof Date)
45
+ return value;
46
+ var t = parseProtestDateToTime(value);
47
+ return t == null ? new Date(NaN) : new Date(t);
48
+ }
49
+ /** Timestamp a partir de `data` já materializada (histórico gravado / pós-processData). */
50
+ export function parseProtestHistoryRowToTime(row) {
51
+ var _a;
52
+ if (row.data instanceof Date && !Number.isNaN(row.data.getTime())) {
53
+ return row.data.getTime();
54
+ }
55
+ var s = typeof row.data === 'string' && row.data.trim() ? row.data.trim() : '';
56
+ return (_a = parseProtestDateToTime(s)) !== null && _a !== void 0 ? _a : 0;
57
+ }
@@ -1,9 +1,13 @@
1
+ /** Data da primeira vez que o protesto apareceu na base (XML datalake: `./first_seen`). */
2
+ export declare function xmlFirstSeenFromNode(node: Node): string | undefined;
1
3
  export interface Protesto {
2
4
  nm_chave: string;
3
5
  cpfCnpj: string;
4
6
  nomeCedente: string;
5
7
  nomeApresentante: string;
6
8
  dataProtesto: string;
9
+ /** Primeira vez que o protesto apareceu na base (XML `first_seen` → mesmo nome que `toArray()` PHP: `firstSeen`). */
10
+ firstSeen?: string;
7
11
  valor: string;
8
12
  vl_custas?: string;
9
13
  temAnuencia: boolean;
@@ -1,14 +1,14 @@
1
+ import { __assign } from "tslib";
1
2
  import XPathUtils from '../utils/xpath';
3
+ /** Data da primeira vez que o protesto apareceu na base (XML datalake: `./first_seen`). */
4
+ export function xmlFirstSeenFromNode(node) {
5
+ var raw = XPathUtils.select('string(./first_seen)', node);
6
+ if (typeof raw === 'string' && raw.trim())
7
+ return raw.trim();
8
+ return undefined;
9
+ }
2
10
  export var parseProtesto = function (node) {
3
11
  var $ = function (xp) { return XPathUtils.select("string(".concat(xp, ")"), node); };
4
- return {
5
- nm_chave: $('./nm_chave'),
6
- cpfCnpj: $('./cpfCnpj'),
7
- nomeCedente: $('./nomeCedente'),
8
- nomeApresentante: $('./nomeApresentante'),
9
- dataProtesto: $('./dataProtesto'),
10
- valor: $('./valor'),
11
- vl_custas: $('./vl_custas') || undefined,
12
- temAnuencia: $('./temAnuencia') === 'true'
13
- };
12
+ var firstSeen = xmlFirstSeenFromNode(node);
13
+ return __assign(__assign({ nm_chave: $('./nm_chave'), cpfCnpj: $('./cpfCnpj'), nomeCedente: $('./nomeCedente'), nomeApresentante: $('./nomeApresentante'), dataProtesto: $('./dataProtesto') }, (firstSeen ? { firstSeen: firstSeen } : {})), { valor: $('./valor'), vl_custas: $('./vl_custas') || undefined, temAnuencia: $('./temAnuencia') === 'true' });
14
14
  };