http-sankhya 1.0.1
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 +195 -0
- package/dist/Sankhya.d.ts +47 -0
- package/dist/Sankhya.js +164 -0
- package/dist/SankhyaHelper.d.ts +15 -0
- package/dist/SankhyaHelper.js +100 -0
- package/dist/SankhyaResponseHelper.d.ts +10 -0
- package/dist/SankhyaResponseHelper.js +59 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# http-sankhya
|
|
2
|
+
|
|
3
|
+
Uma biblioteca TypeScript para interagir com a API do ERP Sankhya. Esta biblioteca simplifica a autenticação, o tratamento de respostas e a formatação de payloads para operações CRUD comuns.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
Certifique-se de ter as dependências instaladas:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install axios
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Uso
|
|
14
|
+
|
|
15
|
+
### Inicialização
|
|
16
|
+
|
|
17
|
+
Importe a classe `Sankhya` e inicialize-a com sua configuração.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { Sankhya } from './src/Sankhya'; // Ajuste o caminho conforme necessário
|
|
21
|
+
|
|
22
|
+
const config = {
|
|
23
|
+
urlBase: 'https://api.sandbox.sankhya.com.br', // URL Base da API do Sankhya
|
|
24
|
+
clientId: 'seu-client-id',
|
|
25
|
+
clientSecret: 'seu-client-secret',
|
|
26
|
+
token: 'seu-token' // Opcional: Se você já tiver um token
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const sankhya = new Sankhya(config);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Autenticação
|
|
33
|
+
|
|
34
|
+
Autentique-se na API para obter um token de sessão.
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
await sankhya.login();
|
|
38
|
+
```
|
|
39
|
+
*Nota: A implementação de login utiliza um fluxo de bearer token ou credenciais enviadas via header, dependendo da configuração. Certifique-se de que seu backend suporta o endpoint de autenticação configurado.*
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Métodos e Exemplos
|
|
44
|
+
|
|
45
|
+
### 1. loadRecords (Buscar Múltiplos Registros)
|
|
46
|
+
|
|
47
|
+
Busca uma lista de registros com suporte a filtros, paginação e seleção de campos.
|
|
48
|
+
|
|
49
|
+
#### Exemplo Básico
|
|
50
|
+
```typescript
|
|
51
|
+
const produtos = await sankhya.loadRecords({
|
|
52
|
+
rootEntity: 'GrupoProduto', // Nome da Tabela/Entidade no Sankhya
|
|
53
|
+
criteria: {
|
|
54
|
+
expression: "ATIVO = 'S'" // Filtro SQL-like
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Exemplo com Paginação e Seleção de Campos
|
|
60
|
+
Para otimizar a performance, solicite apenas os campos necessários (`fieldset`) e use `offsetPage` para paginar.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
const parceiros = await sankhya.loadRecords({
|
|
64
|
+
rootEntity: 'Parceiro',
|
|
65
|
+
offsetPage: 1, // Página 1 (0-indexada ou conforme API)
|
|
66
|
+
criteria: {
|
|
67
|
+
expression: "TIPPESSOA = 'F'"
|
|
68
|
+
},
|
|
69
|
+
entity: {
|
|
70
|
+
fieldset: {
|
|
71
|
+
list: "CODPARC,NOMEPARC,CGC_CPF,EMAIL" // Campos desejados
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Exemplo com Campos de Apresentação
|
|
78
|
+
Se precisar dos valores formatados (lookup), ative `includePresentationFields`.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const vendas = await sankhya.loadRecords({
|
|
82
|
+
rootEntity: 'CabecalhoNota',
|
|
83
|
+
includePresentationFields: 'S', // Retorna descrições de chaves estrangeiras
|
|
84
|
+
criteria: {
|
|
85
|
+
expression: "DTNEG >= '01/01/2024'"
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### 2. loadRecord (Buscar Registro Único)
|
|
93
|
+
|
|
94
|
+
Busca um único registro específico, geralmente pela Chave Primária (PK).
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const produto = await sankhya.loadRecord({
|
|
98
|
+
rootEntity: 'Produto',
|
|
99
|
+
rows: {
|
|
100
|
+
row: {
|
|
101
|
+
CODPROD: { "$": "1005" } // Chave Primária
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
entity: {
|
|
105
|
+
fieldset: {
|
|
106
|
+
list: "*" // Retorna todos os campos
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
console.log(produto);
|
|
112
|
+
// Saída: { CODPROD: "1005", DESCRPROD: "PRODUTO TESTE", ... }
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### 3. saveRecord (Criar ou Atualizar Registro)
|
|
118
|
+
|
|
119
|
+
Cria ou atualiza registros. A biblioteca formata automaticamente o payload do objeto `localFields` para o padrão exigido pelo Sankhya.
|
|
120
|
+
|
|
121
|
+
#### Criar Novo Registro
|
|
122
|
+
Para criar, omita a Chave Primária (se for auto-incremental) ou passe os valores necessários.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
const novoGrupo = await sankhya.saveRecord({
|
|
126
|
+
rootEntity: 'GrupoProduto',
|
|
127
|
+
localFields: {
|
|
128
|
+
DESCRGRUPOPROD: "NOVO GRUPO 2024",
|
|
129
|
+
ATIVO: "S",
|
|
130
|
+
// Outros campos obrigatórios...
|
|
131
|
+
},
|
|
132
|
+
// Opcional: Retornar campos criados (ex: ID gerado)
|
|
133
|
+
entity: {
|
|
134
|
+
fieldset: {
|
|
135
|
+
list: "CODGRUPOPROD,DESCRGRUPOPROD"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Atualizar Registro Existente (Upsert)
|
|
142
|
+
Para atualizar, inclua a Chave Primária nos `localFields`. O comportamento exato depende da entidade Sankhya, mas geralmente atua como "Upsert" (Atualiza se existe, cria se não).
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const atualizacao = await sankhya.saveRecord({
|
|
146
|
+
rootEntity: 'GrupoProduto',
|
|
147
|
+
localFields: {
|
|
148
|
+
CODGRUPOPROD: "20310006", // PK existente
|
|
149
|
+
DESCRGRUPOPROD: "NOME ATUALIZADO", // Campo a alterar
|
|
150
|
+
ATIVO: "N"
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### 4. Execução de Serviço Genérico (execService)
|
|
158
|
+
|
|
159
|
+
Para endpoints que não sejam CRUD padrão (ex: executar Stored Procedures, ações de workflow, ou consultas de metadados), use `execService`.
|
|
160
|
+
|
|
161
|
+
#### Exemplo: Consultar Estoque (Serviço Hipotético)
|
|
162
|
+
```typescript
|
|
163
|
+
const estoque = await sankhya.execService({
|
|
164
|
+
serviceName: 'EstoqueSP.getEstoque',
|
|
165
|
+
requestBody: {
|
|
166
|
+
codProd: '1005',
|
|
167
|
+
codEmp: '1'
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### Exemplo: Deletar Registro de Forma Personalizada
|
|
173
|
+
Embora exista o método `.delete()`, algumas operações de exclusão no Sankhya são feitas via serviços específicos.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
await sankhya.execService({
|
|
177
|
+
serviceName: 'CRUDServiceProvider.removeRecord',
|
|
178
|
+
requestBody: {
|
|
179
|
+
entity: {
|
|
180
|
+
rootEntity: 'Parceiro',
|
|
181
|
+
pk: {
|
|
182
|
+
CODPARC: { "$": "999" }
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Funcionalidades
|
|
190
|
+
|
|
191
|
+
- **Tratamento de Resposta**: Simplifica a resposta aninhada do Sankhya.
|
|
192
|
+
- *LoadRecords*: Retorna `Array<Objeto>`.
|
|
193
|
+
- *LoadRecord*: Retorna `Objeto` único (lida com ausência de metadados).
|
|
194
|
+
- **Transformação de Payload**: O método `saveRecord` aceita objetos simples JS (ex: `{ CAMPO: "Valor" }`) e os converte automaticamente para `{ CAMPO: { "$": "Valor" } }`.
|
|
195
|
+
- **Tipagem TypeScript**: Suporte completo a interfaces para garantir segurança de tipo no desenvolvimento.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface SankhyaConfig {
|
|
2
|
+
urlBase: string;
|
|
3
|
+
clientId?: string;
|
|
4
|
+
clientSecret?: string;
|
|
5
|
+
token?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface LoadRecordsOptions {
|
|
8
|
+
rootEntity: string;
|
|
9
|
+
includePresentationFields?: 'S' | 'N';
|
|
10
|
+
offsetPage?: number;
|
|
11
|
+
criteria?: Record<string, any>;
|
|
12
|
+
entity?: Record<string, any>;
|
|
13
|
+
rows?: Record<string, any>;
|
|
14
|
+
}
|
|
15
|
+
export interface SaveRecordOptions {
|
|
16
|
+
rootEntity: string;
|
|
17
|
+
includePresentationFields?: 'S' | 'N';
|
|
18
|
+
localFields?: Record<string, any>;
|
|
19
|
+
entity?: Record<string, any>;
|
|
20
|
+
}
|
|
21
|
+
export interface ExecServiceOptions {
|
|
22
|
+
serviceName: string;
|
|
23
|
+
requestBody?: Record<string, any>;
|
|
24
|
+
outputType?: 'json' | 'xml';
|
|
25
|
+
}
|
|
26
|
+
export declare class Sankhya {
|
|
27
|
+
private urlBase;
|
|
28
|
+
private clientId?;
|
|
29
|
+
private clientSecret?;
|
|
30
|
+
private token?;
|
|
31
|
+
private tokenClient?;
|
|
32
|
+
private axiosInstance;
|
|
33
|
+
private jsessionid?;
|
|
34
|
+
constructor(config: SankhyaConfig);
|
|
35
|
+
login(): Promise<any>;
|
|
36
|
+
logout(): Promise<void>;
|
|
37
|
+
get(path: string, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
38
|
+
post(path: string, body?: Record<string, any>, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
39
|
+
put(path: string, body?: Record<string, any>, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
40
|
+
patch(path: string, body?: Record<string, any>, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
41
|
+
delete(path: string, queryParam?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
42
|
+
execService(options: ExecServiceOptions, outputType?: 'json' | 'xml'): Promise<any>;
|
|
43
|
+
loadRecords({ rootEntity, includePresentationFields, offsetPage, criteria, entity }: LoadRecordsOptions, outputType?: 'json' | 'xml'): Promise<any>;
|
|
44
|
+
loadRecord({ rootEntity, includePresentationFields, criteria, entity, rows }: LoadRecordsOptions, outputType?: 'json' | 'xml'): Promise<any>;
|
|
45
|
+
saveRecord({ rootEntity, includePresentationFields, localFields, entity }: SaveRecordOptions, outputType?: 'json' | 'xml'): Promise<any>;
|
|
46
|
+
private isEmptyObject;
|
|
47
|
+
}
|
package/dist/Sankhya.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Sankhya = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const SankhyaHelper_1 = require("./SankhyaHelper");
|
|
9
|
+
class Sankhya {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.urlBase = config.urlBase;
|
|
12
|
+
this.clientId = config.clientId;
|
|
13
|
+
this.clientSecret = config.clientSecret;
|
|
14
|
+
this.tokenClient = config.token;
|
|
15
|
+
this.axiosInstance = axios_1.default.create({
|
|
16
|
+
baseURL: this.urlBase,
|
|
17
|
+
timeout: 30000, // Default timeout
|
|
18
|
+
});
|
|
19
|
+
// Add interceptor to inject token/session if needed
|
|
20
|
+
this.axiosInstance.interceptors.request.use((req) => {
|
|
21
|
+
if (this.token) {
|
|
22
|
+
req.headers['Authorization'] = `Bearer ${this.token}`;
|
|
23
|
+
req.headers['Content-Type'] = `application/json`;
|
|
24
|
+
}
|
|
25
|
+
// Often Sankhya uses JSESSIONID cookie or header.
|
|
26
|
+
// If we firmly set token in constructor, mostly used as Bearer or specific header.
|
|
27
|
+
return req;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async login() {
|
|
31
|
+
// Implementation depends on specific Sankhya Auth endpoint (e.g. MobileLoginSP.login)
|
|
32
|
+
// or standard OAuth.
|
|
33
|
+
// Allowing placeholder or specific implementation if user didn't specify the Auth Payload.
|
|
34
|
+
// Assuming standard service execution for now or a place to fill in.
|
|
35
|
+
if (this.clientId && this.clientSecret && this.tokenClient) {
|
|
36
|
+
// Example Oauth or App interaction
|
|
37
|
+
const response = await this.axiosInstance.post('/authenticate', {
|
|
38
|
+
grant_type: 'client_credentials'
|
|
39
|
+
}, {
|
|
40
|
+
headers: {
|
|
41
|
+
'X-Token': this.tokenClient,
|
|
42
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
43
|
+
},
|
|
44
|
+
auth: {
|
|
45
|
+
username: this.clientId,
|
|
46
|
+
password: this.clientSecret
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
this.token = response.data.access_token;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
throw new Error('Missing authentication credentials');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async logout() {
|
|
56
|
+
throw new Error('Logout not implemented');
|
|
57
|
+
}
|
|
58
|
+
// HTTP Methods
|
|
59
|
+
async get(path, queryParam = {}, headers = {}) {
|
|
60
|
+
const response = await this.axiosInstance.get(path, {
|
|
61
|
+
params: queryParam,
|
|
62
|
+
headers: headers
|
|
63
|
+
});
|
|
64
|
+
return response.data;
|
|
65
|
+
}
|
|
66
|
+
async post(path, body = {}, queryParam = {}, headers = {}) {
|
|
67
|
+
const response = await this.axiosInstance.post(path, body, {
|
|
68
|
+
params: queryParam,
|
|
69
|
+
headers: headers
|
|
70
|
+
});
|
|
71
|
+
// Tenta identificar o serviceName no corpo da requisição para passar ao helper
|
|
72
|
+
const serviceName = body === null || body === void 0 ? void 0 : body.serviceName;
|
|
73
|
+
return SankhyaHelper_1.SankhyaHelper.processResponse(response.data, { serviceName });
|
|
74
|
+
}
|
|
75
|
+
async put(path, body = {}, queryParam = {}, headers = {}) {
|
|
76
|
+
const response = await this.axiosInstance.put(path, body, {
|
|
77
|
+
params: queryParam,
|
|
78
|
+
headers: headers
|
|
79
|
+
});
|
|
80
|
+
return response.data;
|
|
81
|
+
}
|
|
82
|
+
async patch(path, body = {}, queryParam = {}, headers = {}) {
|
|
83
|
+
const response = await this.axiosInstance.patch(path, body, {
|
|
84
|
+
params: queryParam,
|
|
85
|
+
headers: headers
|
|
86
|
+
});
|
|
87
|
+
return response.data;
|
|
88
|
+
}
|
|
89
|
+
async delete(path, queryParam = {}, headers = {}) {
|
|
90
|
+
const response = await this.axiosInstance.delete(path, {
|
|
91
|
+
params: queryParam,
|
|
92
|
+
headers: headers
|
|
93
|
+
});
|
|
94
|
+
return response.data;
|
|
95
|
+
}
|
|
96
|
+
// Sankhya Specific Methods
|
|
97
|
+
async execService(options, outputType = 'json') {
|
|
98
|
+
// Standard Sankhya Service URL pattern: /mge/service.sbr?serviceName=...&outputType=json
|
|
99
|
+
const { serviceName, requestBody } = options;
|
|
100
|
+
// Construct the wrapper expected by Sankhya JSON API
|
|
101
|
+
const payload = {
|
|
102
|
+
serviceName: serviceName,
|
|
103
|
+
requestBody: requestBody
|
|
104
|
+
};
|
|
105
|
+
// Note: This is an assumption of the 'service.sbr' endpoint based on typical Sankhya integrations.
|
|
106
|
+
// The user might want to adjust the exact endpoint path in the future.
|
|
107
|
+
return this.post('/gateway/v1/mge/service.sbr', payload, {
|
|
108
|
+
serviceName,
|
|
109
|
+
outputType: options.outputType || outputType
|
|
110
|
+
}, {});
|
|
111
|
+
}
|
|
112
|
+
async loadRecords({ rootEntity, includePresentationFields = 'N', offsetPage = 0, criteria = {}, entity = {} }, outputType = 'json') {
|
|
113
|
+
return this.execService({
|
|
114
|
+
serviceName: 'CRUDServiceProvider.loadRecords',
|
|
115
|
+
requestBody: {
|
|
116
|
+
dataSet: {
|
|
117
|
+
rootEntity,
|
|
118
|
+
includePresentationFields,
|
|
119
|
+
offsetPage,
|
|
120
|
+
criteria,
|
|
121
|
+
entity: this.isEmptyObject(entity) ? { fieldset: { list: "*" } } : entity
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
outputType
|
|
125
|
+
}, outputType);
|
|
126
|
+
}
|
|
127
|
+
async loadRecord({ rootEntity, includePresentationFields = 'N', criteria = {}, entity = {}, rows = {} }, outputType = 'json') {
|
|
128
|
+
return this.execService({
|
|
129
|
+
serviceName: 'CRUDServiceProvider.loadRecord',
|
|
130
|
+
requestBody: {
|
|
131
|
+
dataSet: {
|
|
132
|
+
rootEntity,
|
|
133
|
+
includePresentationFields,
|
|
134
|
+
criteria,
|
|
135
|
+
entity: this.isEmptyObject(entity) ? { fieldset: { list: "*" } } : entity,
|
|
136
|
+
rows
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
outputType
|
|
140
|
+
}, outputType);
|
|
141
|
+
}
|
|
142
|
+
async saveRecord({ rootEntity, includePresentationFields = 'N', localFields = {}, entity = {} }, outputType = 'json') {
|
|
143
|
+
return this.execService({
|
|
144
|
+
serviceName: 'CRUDServiceProvider.saveRecord',
|
|
145
|
+
requestBody: {
|
|
146
|
+
dataSet: {
|
|
147
|
+
rootEntity,
|
|
148
|
+
includePresentationFields,
|
|
149
|
+
dataRow: {
|
|
150
|
+
localFields: SankhyaHelper_1.SankhyaHelper.transformLocalFields(localFields)
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
entity
|
|
154
|
+
},
|
|
155
|
+
outputType
|
|
156
|
+
}, outputType);
|
|
157
|
+
}
|
|
158
|
+
isEmptyObject(obj) {
|
|
159
|
+
return obj != null &&
|
|
160
|
+
obj.constructor === Object &&
|
|
161
|
+
Object.keys(obj).length === 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.Sankhya = Sankhya;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class SankhyaHelper {
|
|
2
|
+
/**
|
|
3
|
+
* Converte retorno do Sankhya baseado no tipo de serviço.
|
|
4
|
+
* Utiliza switch case para rotear o tratamento.
|
|
5
|
+
*/
|
|
6
|
+
static processResponse(response: any, options?: {
|
|
7
|
+
serviceName?: string;
|
|
8
|
+
}): any;
|
|
9
|
+
/**
|
|
10
|
+
* Transforma um objeto simples de chave/valor para o formato do Sankhya
|
|
11
|
+
* Ex: { CAMPO: "VALOR" } -> { CAMPO: { "$": "VALOR" } }
|
|
12
|
+
*/
|
|
13
|
+
static transformLocalFields(localFields: Record<string, any>): Record<string, any>;
|
|
14
|
+
private static processLoadRecords;
|
|
15
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SankhyaHelper = void 0;
|
|
4
|
+
class SankhyaHelper {
|
|
5
|
+
/**
|
|
6
|
+
* Converte retorno do Sankhya baseado no tipo de serviço.
|
|
7
|
+
* Utiliza switch case para rotear o tratamento.
|
|
8
|
+
*/
|
|
9
|
+
static processResponse(response, options = {}) {
|
|
10
|
+
if (!response || !response.responseBody || !response.responseBody.entities) {
|
|
11
|
+
return response;
|
|
12
|
+
}
|
|
13
|
+
switch (options.serviceName) {
|
|
14
|
+
case 'CRUDServiceProvider.loadRecords':
|
|
15
|
+
case 'CRUDServiceProvider.loadRecord':
|
|
16
|
+
case 'CRUDServiceProvider.saveRecord':
|
|
17
|
+
return this.processLoadRecords(response);
|
|
18
|
+
default:
|
|
19
|
+
// Se não for um dos serviços conhecidos de CRUD/Load, retorna original
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Transforma um objeto simples de chave/valor para o formato do Sankhya
|
|
25
|
+
* Ex: { CAMPO: "VALOR" } -> { CAMPO: { "$": "VALOR" } }
|
|
26
|
+
*/
|
|
27
|
+
static transformLocalFields(localFields) {
|
|
28
|
+
const transformed = {};
|
|
29
|
+
Object.keys(localFields).forEach(key => {
|
|
30
|
+
const value = localFields[key];
|
|
31
|
+
// Se o valor já estiver no formato { $: ... }, mantém
|
|
32
|
+
if (value && typeof value === 'object' && '$' in value) {
|
|
33
|
+
transformed[key] = value;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
transformed[key] = { $: value };
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return transformed;
|
|
40
|
+
}
|
|
41
|
+
// Lógica de transformação extraída para método privado
|
|
42
|
+
static processLoadRecords(response) {
|
|
43
|
+
const { entities } = response.responseBody;
|
|
44
|
+
const metadata = entities.metadata;
|
|
45
|
+
// Se não tiver metadados, pode ser um loadRecord de um único registro sem fields info
|
|
46
|
+
if (!metadata || !metadata.fields || !metadata.fields.field) {
|
|
47
|
+
const entityNode = entities.entity;
|
|
48
|
+
if (entityNode && !Array.isArray(entityNode)) {
|
|
49
|
+
// Caso específico do loadRecord que retorna entity direto sem metadata
|
|
50
|
+
const record = {};
|
|
51
|
+
Object.keys(entityNode).forEach(key => {
|
|
52
|
+
const value = entityNode[key];
|
|
53
|
+
if (value && typeof value === "object" && "$" in value) {
|
|
54
|
+
record[key] = value.$;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Se for objeto vazio ou não tiver $, assume null ou mantém o valor original se não for objeto vazio
|
|
58
|
+
// No exemplo dado: "GRUPOICMS": {} -> null
|
|
59
|
+
if (Object.keys(value).length === 0) {
|
|
60
|
+
record[key] = null;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
record[key] = value; // Fallback, maintain original if not empty and no $
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return record;
|
|
68
|
+
}
|
|
69
|
+
return response;
|
|
70
|
+
}
|
|
71
|
+
const fields = metadata.fields.field;
|
|
72
|
+
const entityNode = entities.entity;
|
|
73
|
+
if (!entityNode) {
|
|
74
|
+
if (entities.total === "0")
|
|
75
|
+
return [];
|
|
76
|
+
return response;
|
|
77
|
+
}
|
|
78
|
+
const mapOne = (ent) => {
|
|
79
|
+
const record = {};
|
|
80
|
+
const fieldsArray = Array.isArray(fields) ? fields : [fields];
|
|
81
|
+
fieldsArray.forEach((f, idx) => {
|
|
82
|
+
var _a;
|
|
83
|
+
const key = (_a = f === null || f === void 0 ? void 0 : f.name) !== null && _a !== void 0 ? _a : `field_${idx}`;
|
|
84
|
+
const raw = ent[`f${idx}`];
|
|
85
|
+
if (raw && typeof raw === "object" && "$" in raw) {
|
|
86
|
+
record[key] = raw.$;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
record[key] = null;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return record;
|
|
93
|
+
};
|
|
94
|
+
if (Array.isArray(entityNode)) {
|
|
95
|
+
return entityNode.map(mapOne);
|
|
96
|
+
}
|
|
97
|
+
return mapOne(entityNode);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.SankhyaHelper = SankhyaHelper;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class SankhyaResponseHelper {
|
|
2
|
+
/**
|
|
3
|
+
* Converte retorno do Sankhya baseado no tipo de serviço.
|
|
4
|
+
* Utiliza switch case para rotear o tratamento.
|
|
5
|
+
*/
|
|
6
|
+
static processResponse(response: any, options?: {
|
|
7
|
+
serviceName?: string;
|
|
8
|
+
}): any;
|
|
9
|
+
private static processLoadRecords;
|
|
10
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SankhyaResponseHelper = void 0;
|
|
4
|
+
class SankhyaResponseHelper {
|
|
5
|
+
/**
|
|
6
|
+
* Converte retorno do Sankhya baseado no tipo de serviço.
|
|
7
|
+
* Utiliza switch case para rotear o tratamento.
|
|
8
|
+
*/
|
|
9
|
+
static processResponse(response, options = {}) {
|
|
10
|
+
if (!response || !response.responseBody || !response.responseBody.entities) {
|
|
11
|
+
return response;
|
|
12
|
+
}
|
|
13
|
+
switch (options.serviceName) {
|
|
14
|
+
case 'CRUDServiceProvider.loadRecords':
|
|
15
|
+
case 'CRUDServiceProvider.loadRecord':
|
|
16
|
+
case 'CRUDServiceProvider.saveRecord':
|
|
17
|
+
return this.processLoadRecords(response);
|
|
18
|
+
default:
|
|
19
|
+
// Se não for um dos serviços conhecidos de CRUD/Load, retorna original
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Lógica de transformação extraída para método privado
|
|
24
|
+
static processLoadRecords(response) {
|
|
25
|
+
const { entities } = response.responseBody;
|
|
26
|
+
const metadata = entities.metadata;
|
|
27
|
+
if (!metadata || !metadata.fields || !metadata.fields.field) {
|
|
28
|
+
return response;
|
|
29
|
+
}
|
|
30
|
+
const fields = metadata.fields.field;
|
|
31
|
+
const entityNode = entities.entity;
|
|
32
|
+
if (!entityNode) {
|
|
33
|
+
if (entities.total === "0")
|
|
34
|
+
return [];
|
|
35
|
+
return response;
|
|
36
|
+
}
|
|
37
|
+
const mapOne = (ent) => {
|
|
38
|
+
const record = {};
|
|
39
|
+
const fieldsArray = Array.isArray(fields) ? fields : [fields];
|
|
40
|
+
fieldsArray.forEach((f, idx) => {
|
|
41
|
+
var _a;
|
|
42
|
+
const key = (_a = f === null || f === void 0 ? void 0 : f.name) !== null && _a !== void 0 ? _a : `field_${idx}`;
|
|
43
|
+
const raw = ent[`f${idx}`];
|
|
44
|
+
if (raw && typeof raw === "object" && "$" in raw) {
|
|
45
|
+
record[key] = raw.$;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
record[key] = null;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return record;
|
|
52
|
+
};
|
|
53
|
+
if (Array.isArray(entityNode)) {
|
|
54
|
+
return entityNode.map(mapOne);
|
|
55
|
+
}
|
|
56
|
+
return mapOne(entityNode);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.SankhyaResponseHelper = SankhyaResponseHelper;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Sankhya';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Sankhya"), exports);
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "http-sankhya",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Biblioteca TypeScript para integração com ERP Sankhya",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build",
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"debug": "npx ts-node test-manual.ts"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"sankhya",
|
|
15
|
+
"erp",
|
|
16
|
+
"api",
|
|
17
|
+
"typescript",
|
|
18
|
+
"integration"
|
|
19
|
+
],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/marcosdslau/http-sankhya.git"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/marcosdslau/http-sankhya#readme",
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"axios": "^1.6.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.10.0",
|
|
39
|
+
"ts-node": "^10.9.1",
|
|
40
|
+
"typescript": "^5.3.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=14.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|